10bbfda8aSnia/* 20bbfda8aSnia * Various workspace handling and utilities. 30bbfda8aSnia */ 40bbfda8aSnia 50bbfda8aSnia#include "ctwm.h" 60bbfda8aSnia 70bbfda8aSnia#include <stdio.h> 80bbfda8aSnia#include <string.h> 90bbfda8aSnia#include <stdlib.h> 100bbfda8aSnia 110bbfda8aSnia#include <X11/Xatom.h> 120bbfda8aSnia 130bbfda8aSnia#include "animate.h" 140bbfda8aSnia#include "clicktofocus.h" 150bbfda8aSnia#include "ctwm_atoms.h" 160bbfda8aSnia#include "drawing.h" 170bbfda8aSnia#include "functions.h" 180bbfda8aSnia#include "iconmgr.h" 190bbfda8aSnia#include "image.h" 200bbfda8aSnia#include "otp.h" 210bbfda8aSnia#include "screen.h" 220bbfda8aSnia#include "vscreen.h" 230bbfda8aSnia#include "win_ops.h" 240bbfda8aSnia#include "win_utils.h" 250bbfda8aSnia#include "workspace_manager.h" 260bbfda8aSnia#include "workspace_utils.h" 270bbfda8aSnia 280bbfda8aSnia#ifdef EWMH 290bbfda8aSnia# include "ewmh_atoms.h" 300bbfda8aSnia#endif 310bbfda8aSnia 320bbfda8aSnia 330bbfda8aSnia/* 340bbfda8aSnia * XXX I'm not sure this should be here; maybe it's more of a per-screen 350bbfda8aSnia * thing, and so should be in the Screen struct? 360bbfda8aSnia */ 370bbfda8aSniabool useBackgroundInfo = false; 380bbfda8aSnia 390bbfda8aSnia 400bbfda8aSnia/* 410bbfda8aSnia * Move the display (of a given vs) over to a new workspace. 420bbfda8aSnia */ 430bbfda8aSniavoid 440bbfda8aSniaGotoWorkSpace(VirtualScreen *vs, WorkSpace *ws) 450bbfda8aSnia{ 460bbfda8aSnia TwmWindow *twmWin; 470bbfda8aSnia WorkSpace *oldws, *newws; 480bbfda8aSnia WList *wl, *wl1; 490bbfda8aSnia WinList *winl; 500bbfda8aSnia XSetWindowAttributes attr; 510bbfda8aSnia long eventMask; 520bbfda8aSnia IconMgr *iconmgr; 530bbfda8aSnia Window oldw; 540bbfda8aSnia Window neww; 550bbfda8aSnia TwmWindow *focuswindow; 560bbfda8aSnia VirtualScreen *tmpvs; 570bbfda8aSnia 580bbfda8aSnia if(! Scr->workSpaceManagerActive) { 590bbfda8aSnia return; 600bbfda8aSnia } 610bbfda8aSnia for(tmpvs = Scr->vScreenList; tmpvs != NULL; tmpvs = tmpvs->next) { 620bbfda8aSnia if(ws == tmpvs->wsw->currentwspc) { 630bbfda8aSnia XBell(dpy, 0); 640bbfda8aSnia return; 650bbfda8aSnia } 660bbfda8aSnia } 670bbfda8aSnia oldws = vs->wsw->currentwspc; 680bbfda8aSnia newws = ws; 690bbfda8aSnia if(oldws == newws) { 700bbfda8aSnia return; 710bbfda8aSnia } 720bbfda8aSnia 730bbfda8aSnia /* XXX X-ref CTAG_BGDRAW in CreateWorkSpaceManager() and below */ 740bbfda8aSnia if(useBackgroundInfo && ! Scr->DontPaintRootWindow) { 750bbfda8aSnia if(newws->image == NULL) { 760bbfda8aSnia XSetWindowBackground(dpy, vs->window, newws->backcp.back); 770bbfda8aSnia } 780bbfda8aSnia else { 790bbfda8aSnia XSetWindowBackgroundPixmap(dpy, vs->window, newws->image->pixmap); 800bbfda8aSnia } 810bbfda8aSnia XClearWindow(dpy, vs->window); 820bbfda8aSnia } 830bbfda8aSnia 840bbfda8aSnia /* If SaveWorkspaceFocus is on, save the focus of the last window. */ 850bbfda8aSnia if(Scr->SaveWorkspaceFocus) { 860bbfda8aSnia oldws->save_focus = Scr->Focus; 870bbfda8aSnia } 880bbfda8aSnia 890bbfda8aSnia focuswindow = NULL; 900bbfda8aSnia /* For better visual effect, the order or map/unmap is important: 910bbfda8aSnia - map from top to bottom. 920bbfda8aSnia - unmap from bottom to top. 930bbfda8aSnia - unmap after mapping. 940bbfda8aSnia The guiding factor: at any point during the transition, something 950bbfda8aSnia should be visible only if it was visible before the transition or if 960bbfda8aSnia it will be visible at the end. */ 970bbfda8aSnia OtpCheckConsistency(); 980bbfda8aSnia 990bbfda8aSnia for(twmWin = OtpTopWin(); twmWin != NULL; 1000bbfda8aSnia twmWin = OtpNextWinDown(twmWin)) { 1010bbfda8aSnia 1020bbfda8aSnia if(OCCUPY(twmWin, newws)) { 1030bbfda8aSnia if(!twmWin->vs) { 1040bbfda8aSnia DisplayWin(vs, twmWin); 1050bbfda8aSnia } 1060bbfda8aSnia#ifdef EWMH 1070bbfda8aSnia if(OCCUPY(twmWin, oldws)) { 1080bbfda8aSnia /* 1090bbfda8aSnia * If the window remains visible, re-order the workspace 1100bbfda8aSnia * numbers in NET_WM_DESKTOP. 1110bbfda8aSnia */ 1120bbfda8aSnia EwmhSet_NET_WM_DESKTOP_ws(twmWin, newws); 1130bbfda8aSnia } 1140bbfda8aSnia#endif 1150bbfda8aSnia } 1160bbfda8aSnia } 1170bbfda8aSnia 1180bbfda8aSnia for(twmWin = OtpBottomWin(); twmWin != NULL; 1190bbfda8aSnia twmWin = OtpNextWinUp(twmWin)) { 1200bbfda8aSnia if(twmWin->vs == vs) { 1210bbfda8aSnia if(!OCCUPY(twmWin, newws)) { 1220bbfda8aSnia 1230bbfda8aSnia Vanish(vs, twmWin); 124b18c2d1eSnia#ifdef VSCREEN 1250bbfda8aSnia /* 1260bbfda8aSnia * Now that the window has Vanished from one virtual screen, 1270bbfda8aSnia * check to see if it is wanted on another one. 1280bbfda8aSnia * This is relatively rare, so don't bother with the 1290bbfda8aSnia * top-to-bottom order here. 1300bbfda8aSnia */ 1310bbfda8aSnia if(Scr->numVscreens > 1) { 132b18c2d1eSnia VirtualScreen *tvs; 1330bbfda8aSnia for(tvs = Scr->vScreenList; tvs != NULL; tvs = tvs->next) { 1340bbfda8aSnia if(tvs == vs) { /* no, not back on the old one */ 1350bbfda8aSnia continue; 1360bbfda8aSnia } 1370bbfda8aSnia if(OCCUPY(twmWin, tvs->wsw->currentwspc)) { 1380bbfda8aSnia DisplayWin(tvs, twmWin); 1390bbfda8aSnia break; 1400bbfda8aSnia } 1410bbfda8aSnia } 1420bbfda8aSnia } 143b18c2d1eSnia#endif 1440bbfda8aSnia } 1450bbfda8aSnia else if(twmWin->hasfocusvisible) { 1460bbfda8aSnia focuswindow = twmWin; 1470bbfda8aSnia SetFocusVisualAttributes(focuswindow, false); 1480bbfda8aSnia } 1490bbfda8aSnia } 1500bbfda8aSnia } 1510bbfda8aSnia OtpCheckConsistency(); 1520bbfda8aSnia 1530bbfda8aSnia /* 1540bbfda8aSnia Reorganize icon manager window lists 1550bbfda8aSnia */ 1560bbfda8aSnia for(twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) { 1570bbfda8aSnia wl = twmWin->iconmanagerlist; 1580bbfda8aSnia if(wl == NULL) { 1590bbfda8aSnia continue; 1600bbfda8aSnia } 1610bbfda8aSnia if(OCCUPY(wl->iconmgr->twm_win, newws)) { 1620bbfda8aSnia continue; 1630bbfda8aSnia } 1640bbfda8aSnia wl1 = wl; 1650bbfda8aSnia wl = wl->nextv; 1660bbfda8aSnia while(wl != NULL) { 1670bbfda8aSnia if(OCCUPY(wl->iconmgr->twm_win, newws)) { 1680bbfda8aSnia break; 1690bbfda8aSnia } 1700bbfda8aSnia wl1 = wl; 1710bbfda8aSnia wl = wl->nextv; 1720bbfda8aSnia } 1730bbfda8aSnia if(wl != NULL) { 1740bbfda8aSnia wl1->nextv = wl->nextv; 1750bbfda8aSnia wl->nextv = twmWin->iconmanagerlist; 1760bbfda8aSnia twmWin->iconmanagerlist = wl; 1770bbfda8aSnia } 1780bbfda8aSnia } 1790bbfda8aSnia wl = NULL; 1800bbfda8aSnia for(iconmgr = newws->iconmgr; iconmgr; iconmgr = iconmgr->next) { 1810bbfda8aSnia if(iconmgr->first) { 1820bbfda8aSnia wl = iconmgr->first; 1830bbfda8aSnia break; 1840bbfda8aSnia } 1850bbfda8aSnia } 1860bbfda8aSnia CurrentIconManagerEntry(wl); 1870bbfda8aSnia if(focuswindow) { 1880bbfda8aSnia SetFocusVisualAttributes(focuswindow, true); 1890bbfda8aSnia } 1900bbfda8aSnia vs->wsw->currentwspc = newws; 1910bbfda8aSnia if(Scr->ReverseCurrentWorkspace && vs->wsw->state == WMS_map) { 1920bbfda8aSnia MapSubwindow *msw = vs->wsw->mswl [oldws->number]; 1930bbfda8aSnia for(winl = msw->wl; winl != NULL; winl = winl->next) { 1940bbfda8aSnia WMapRedrawName(vs, winl); 1950bbfda8aSnia } 1960bbfda8aSnia msw = vs->wsw->mswl [newws->number]; 1970bbfda8aSnia for(winl = msw->wl; winl != NULL; winl = winl->next) { 1980bbfda8aSnia WMapRedrawName(vs, winl); 1990bbfda8aSnia } 2000bbfda8aSnia } 2010bbfda8aSnia else if(vs->wsw->state == WMS_buttons) { 2020bbfda8aSnia ButtonSubwindow *bsw = vs->wsw->bswl [oldws->number]; 2030bbfda8aSnia PaintWsButton(WSPCWINDOW, vs, bsw->w, oldws->label, oldws->cp, off); 2040bbfda8aSnia bsw = vs->wsw->bswl [newws->number]; 2050bbfda8aSnia PaintWsButton(WSPCWINDOW, vs, bsw->w, newws->label, newws->cp, on); 2060bbfda8aSnia } 2070bbfda8aSnia oldws->iconmgr = Scr->iconmgr; 2080bbfda8aSnia Scr->iconmgr = newws->iconmgr; 2090bbfda8aSnia 2100bbfda8aSnia /* XXX X-ref CTAG_BGDRAW in CreateWorkSpaceManager() and above */ 2110bbfda8aSnia oldw = vs->wsw->mswl [oldws->number]->w; 2120bbfda8aSnia neww = vs->wsw->mswl [newws->number]->w; 2130bbfda8aSnia if(useBackgroundInfo) { 2140bbfda8aSnia if(oldws->image == NULL || Scr->NoImagesInWorkSpaceManager) { 2150bbfda8aSnia XSetWindowBackground(dpy, oldw, oldws->backcp.back); 2160bbfda8aSnia } 2170bbfda8aSnia else { 2180bbfda8aSnia XSetWindowBackgroundPixmap(dpy, oldw, oldws->image->pixmap); 2190bbfda8aSnia } 2200bbfda8aSnia } 2210bbfda8aSnia else { 2220bbfda8aSnia if(Scr->workSpaceMgr.defImage == NULL || Scr->NoImagesInWorkSpaceManager) { 2230bbfda8aSnia XSetWindowBackground(dpy, oldw, Scr->workSpaceMgr.defColors.back); 2240bbfda8aSnia } 2250bbfda8aSnia else { 2260bbfda8aSnia XSetWindowBackgroundPixmap(dpy, oldw, Scr->workSpaceMgr.defImage->pixmap); 2270bbfda8aSnia } 2280bbfda8aSnia } 2290bbfda8aSnia attr.border_pixel = Scr->workSpaceMgr.defBorderColor; 2300bbfda8aSnia XChangeWindowAttributes(dpy, oldw, CWBorderPixel, &attr); 2310bbfda8aSnia 2320bbfda8aSnia if(Scr->workSpaceMgr.curImage == NULL) { 2330bbfda8aSnia if(Scr->workSpaceMgr.curPaint) { 2340bbfda8aSnia XSetWindowBackground(dpy, neww, Scr->workSpaceMgr.curColors.back); 2350bbfda8aSnia } 2360bbfda8aSnia } 2370bbfda8aSnia else { 2380bbfda8aSnia XSetWindowBackgroundPixmap(dpy, neww, Scr->workSpaceMgr.curImage->pixmap); 2390bbfda8aSnia } 2400bbfda8aSnia attr.border_pixel = Scr->workSpaceMgr.curBorderColor; 2410bbfda8aSnia XChangeWindowAttributes(dpy, neww, CWBorderPixel, &attr); 2420bbfda8aSnia 2430bbfda8aSnia XClearWindow(dpy, oldw); 2440bbfda8aSnia XClearWindow(dpy, neww); 2450bbfda8aSnia 2460bbfda8aSnia eventMask = mask_out_event(Scr->Root, PropertyChangeMask); 2470bbfda8aSnia 2480bbfda8aSnia XChangeProperty(dpy, Scr->Root, XA_WM_CURRENTWORKSPACE, XA_STRING, 8, 2490bbfda8aSnia PropModeReplace, (unsigned char *) newws->name, strlen(newws->name)); 2500bbfda8aSnia#ifdef EWMH 2510bbfda8aSnia { 2520bbfda8aSnia long number = newws->number; 2530bbfda8aSnia /* 2540bbfda8aSnia * TODO: this should probably not use Scr->Root but ->XineramaRoot. 2550bbfda8aSnia * That is the real root window if we're using virtual screens. 2560bbfda8aSnia * Also, on the real root it would need values for each of the 2570bbfda8aSnia * virtual roots, but that doesn't fit in the EWMH ideas. 2580bbfda8aSnia */ 2590bbfda8aSnia XChangeProperty(dpy, Scr->Root, XA__NET_CURRENT_DESKTOP, 2600bbfda8aSnia XA_CARDINAL, 32, 2610bbfda8aSnia PropModeReplace, (unsigned char *) &number, 1); 2620bbfda8aSnia } 2630bbfda8aSnia#endif /* EWMH */ 2640bbfda8aSnia 2650bbfda8aSnia restore_mask(Scr->Root, eventMask); 2660bbfda8aSnia 2670bbfda8aSnia /* XDestroyWindow (dpy, cachew);*/ 2680bbfda8aSnia if(Scr->ChangeWorkspaceFunction.func != 0) { 2690bbfda8aSnia char *action; 2700bbfda8aSnia XEvent event; 2710bbfda8aSnia 2720bbfda8aSnia action = Scr->ChangeWorkspaceFunction.item ? 2730bbfda8aSnia Scr->ChangeWorkspaceFunction.item->action : NULL; 2740bbfda8aSnia ExecuteFunction(Scr->ChangeWorkspaceFunction.func, action, 2750bbfda8aSnia (Window) 0, NULL, &event, C_ROOT, false); 2760bbfda8aSnia } 2770bbfda8aSnia 2780bbfda8aSnia /* If SaveWorkspaceFocus is on, try to restore the focus to the last 2790bbfda8aSnia window which was focused when we left this workspace. */ 2800bbfda8aSnia if(Scr->SaveWorkspaceFocus && newws->save_focus) { 2810bbfda8aSnia twmWin = newws->save_focus; 2820bbfda8aSnia if(OCCUPY(twmWin, newws)) { /* check should not even be needed anymore */ 2830bbfda8aSnia WarpToWindow(twmWin, false); 2840bbfda8aSnia } 2850bbfda8aSnia else { 2860bbfda8aSnia newws->save_focus = NULL; 2870bbfda8aSnia } 2880bbfda8aSnia } 2890bbfda8aSnia 2900bbfda8aSnia /* keep track of the order of the workspaces across restarts */ 2910bbfda8aSnia CtwmSetVScreenMap(dpy, Scr->Root, Scr->vScreenList); 2920bbfda8aSnia 2930bbfda8aSnia XSync(dpy, 0); 2940bbfda8aSnia if(Scr->ClickToFocus || Scr->SloppyFocus) { 2950bbfda8aSnia set_last_window(newws); 2960bbfda8aSnia } 2970bbfda8aSnia MaybeAnimate = true; 2980bbfda8aSnia} 2990bbfda8aSnia 3000bbfda8aSnia 3010bbfda8aSnia 3020bbfda8aSnia/* 3030bbfda8aSnia * Various frontends to GotoWorkSpace() 3040bbfda8aSnia */ 3050bbfda8aSnia 3060bbfda8aSnia/* 3070bbfda8aSnia * Simplify redundant checks. If no multiple workspaces, or no vs given 3080bbfda8aSnia * to the func, there's nothing to do. 3090bbfda8aSnia */ 3100bbfda8aSnia#define GWS_CHECK do { \ 3110bbfda8aSnia if(! Scr->workSpaceManagerActive) { \ 3120bbfda8aSnia return; \ 3130bbfda8aSnia } \ 3140bbfda8aSnia if(!vs) { \ 3150bbfda8aSnia return; \ 3160bbfda8aSnia } \ 3170bbfda8aSnia } while(0) 3180bbfda8aSnia 3190bbfda8aSniavoid 3200bbfda8aSniaGotoWorkSpaceByName(VirtualScreen *vs, const char *wname) 3210bbfda8aSnia{ 3220bbfda8aSnia WorkSpace *ws; 3230bbfda8aSnia 3240bbfda8aSnia GWS_CHECK; 3250bbfda8aSnia 3260bbfda8aSnia ws = GetWorkspace(wname); 3270bbfda8aSnia if(ws == NULL) { 3280bbfda8aSnia return; 3290bbfda8aSnia } 3300bbfda8aSnia GotoWorkSpace(vs, ws); 3310bbfda8aSnia} 3320bbfda8aSnia 3330bbfda8aSnia 3340bbfda8aSniavoid 3350bbfda8aSniaGotoWorkSpaceByNumber(VirtualScreen *vs, int workspacenum) 3360bbfda8aSnia{ 3370bbfda8aSnia WorkSpace *ws; 3380bbfda8aSnia 3390bbfda8aSnia GWS_CHECK; 3400bbfda8aSnia 3410bbfda8aSnia for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { 3420bbfda8aSnia if(ws->number == workspacenum) { 3430bbfda8aSnia break; 3440bbfda8aSnia } 3450bbfda8aSnia } 3460bbfda8aSnia if(ws == NULL) { 3470bbfda8aSnia return; 3480bbfda8aSnia } 3490bbfda8aSnia GotoWorkSpace(vs, ws); 3500bbfda8aSnia} 3510bbfda8aSnia 3520bbfda8aSnia 3530bbfda8aSniavoid 3540bbfda8aSniaGotoPrevWorkSpace(VirtualScreen *vs) 3550bbfda8aSnia{ 3560bbfda8aSnia WorkSpace *ws1, *ws2; 3570bbfda8aSnia 3580bbfda8aSnia GWS_CHECK; 3590bbfda8aSnia 3600bbfda8aSnia ws1 = Scr->workSpaceMgr.workSpaceList; 3610bbfda8aSnia if(ws1 == NULL) { 3620bbfda8aSnia return; 3630bbfda8aSnia } 3640bbfda8aSnia ws2 = ws1->next; 3650bbfda8aSnia 3660bbfda8aSnia while((ws2 != vs->wsw->currentwspc) && (ws2 != NULL)) { 3670bbfda8aSnia ws1 = ws2; 3680bbfda8aSnia ws2 = ws2->next; 3690bbfda8aSnia } 3700bbfda8aSnia GotoWorkSpace(vs, ws1); 3710bbfda8aSnia} 3720bbfda8aSnia 3730bbfda8aSnia 3740bbfda8aSniavoid 3750bbfda8aSniaGotoNextWorkSpace(VirtualScreen *vs) 3760bbfda8aSnia{ 3770bbfda8aSnia WorkSpace *ws; 3780bbfda8aSnia 3790bbfda8aSnia GWS_CHECK; 3800bbfda8aSnia 3810bbfda8aSnia ws = vs->wsw->currentwspc; 3820bbfda8aSnia ws = (ws->next != NULL) ? ws->next : Scr->workSpaceMgr.workSpaceList; 3830bbfda8aSnia GotoWorkSpace(vs, ws); 3840bbfda8aSnia} 3850bbfda8aSnia 3860bbfda8aSnia 3870bbfda8aSniavoid 3880bbfda8aSniaGotoRightWorkSpace(VirtualScreen *vs) 3890bbfda8aSnia{ 3900bbfda8aSnia WorkSpace *ws; 3910bbfda8aSnia int number, columns, count; 3920bbfda8aSnia 3930bbfda8aSnia GWS_CHECK; 3940bbfda8aSnia 3950bbfda8aSnia ws = vs->wsw->currentwspc; 3960bbfda8aSnia number = ws->number; 3970bbfda8aSnia columns = Scr->workSpaceMgr.columns; 3980bbfda8aSnia count = Scr->workSpaceMgr.count; 3990bbfda8aSnia number++; 4000bbfda8aSnia if((number % columns) == 0) { 4010bbfda8aSnia number -= columns; 4020bbfda8aSnia } 4030bbfda8aSnia else if(number >= count) { 4040bbfda8aSnia number = (number / columns) * columns; 4050bbfda8aSnia } 4060bbfda8aSnia 4070bbfda8aSnia GotoWorkSpaceByNumber(vs, number); 4080bbfda8aSnia} 4090bbfda8aSnia 4100bbfda8aSnia 4110bbfda8aSniavoid 4120bbfda8aSniaGotoLeftWorkSpace(VirtualScreen *vs) 4130bbfda8aSnia{ 4140bbfda8aSnia WorkSpace *ws; 4150bbfda8aSnia int number, columns, count; 4160bbfda8aSnia 4170bbfda8aSnia GWS_CHECK; 4180bbfda8aSnia 4190bbfda8aSnia ws = vs->wsw->currentwspc; 4200bbfda8aSnia number = ws->number; 4210bbfda8aSnia columns = Scr->workSpaceMgr.columns; 4220bbfda8aSnia count = Scr->workSpaceMgr.count; 4230bbfda8aSnia number += (number % columns) ? -1 : (columns - 1); 4240bbfda8aSnia if(number >= count) { 4250bbfda8aSnia number = count - 1; 4260bbfda8aSnia } 4270bbfda8aSnia GotoWorkSpaceByNumber(vs, number); 4280bbfda8aSnia} 4290bbfda8aSnia 4300bbfda8aSnia 4310bbfda8aSniavoid 4320bbfda8aSniaGotoUpWorkSpace(VirtualScreen *vs) 4330bbfda8aSnia{ 4340bbfda8aSnia WorkSpace *ws; 4350bbfda8aSnia int number, lines, columns, count; 4360bbfda8aSnia 4370bbfda8aSnia GWS_CHECK; 4380bbfda8aSnia 4390bbfda8aSnia ws = vs->wsw->currentwspc; 4400bbfda8aSnia number = ws->number; 4410bbfda8aSnia lines = Scr->workSpaceMgr.lines; 4420bbfda8aSnia columns = Scr->workSpaceMgr.columns; 4430bbfda8aSnia count = Scr->workSpaceMgr.count; 4440bbfda8aSnia number -= columns; 4450bbfda8aSnia if(number < 0) { 4460bbfda8aSnia number += lines * columns; 4470bbfda8aSnia /* If the number of workspaces is not a multiple of nr of columns */ 4480bbfda8aSnia if(number >= count) { 4490bbfda8aSnia number -= columns; 4500bbfda8aSnia } 4510bbfda8aSnia } 4520bbfda8aSnia GotoWorkSpaceByNumber(vs, number); 4530bbfda8aSnia} 4540bbfda8aSnia 4550bbfda8aSnia 4560bbfda8aSniavoid 4570bbfda8aSniaGotoDownWorkSpace(VirtualScreen *vs) 4580bbfda8aSnia{ 4590bbfda8aSnia WorkSpace *ws; 4600bbfda8aSnia int number, columns, count; 4610bbfda8aSnia 4620bbfda8aSnia GWS_CHECK; 4630bbfda8aSnia 4640bbfda8aSnia ws = vs->wsw->currentwspc; 4650bbfda8aSnia number = ws->number; 4660bbfda8aSnia columns = Scr->workSpaceMgr.columns; 4670bbfda8aSnia count = Scr->workSpaceMgr.count; 4680bbfda8aSnia number += columns; 4690bbfda8aSnia if(number >= count) { 4700bbfda8aSnia number %= columns; 4710bbfda8aSnia } 4720bbfda8aSnia GotoWorkSpaceByNumber(vs, number); 4730bbfda8aSnia} 4740bbfda8aSnia 4750bbfda8aSnia#undef GWS_CHECK 4760bbfda8aSnia 4770bbfda8aSnia 4780bbfda8aSnia 4790bbfda8aSnia/* 4800bbfda8aSnia * Show the background (by hiding all windows) or undo it. 4810bbfda8aSnia * f.showbackground, also can be called via EWMH bits. 4820bbfda8aSnia * 4830bbfda8aSnia * newstate is the desired showing state. 4840bbfda8aSnia * Pass -1 to toggle, 1 to show the background, 4850bbfda8aSnia * or 0 to re-show the windows. 4860bbfda8aSnia * 4870bbfda8aSnia * XXX Doesn't really belong here; more of a functions.c-ish thing 4880bbfda8aSnia * probably. But left here for the moment. 4890bbfda8aSnia */ 4900bbfda8aSniavoid 4910bbfda8aSniaShowBackground(VirtualScreen *vs, int newstate) 4920bbfda8aSnia{ 4930bbfda8aSnia static int state = 0; 4940bbfda8aSnia TwmWindow *twmWin; 4950bbfda8aSnia 4960bbfda8aSnia if(newstate == state) { 4970bbfda8aSnia return; 4980bbfda8aSnia } 4990bbfda8aSnia 5000bbfda8aSnia if(state) { 5010bbfda8aSnia for(twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) { 5020bbfda8aSnia if(twmWin->savevs == vs) { 5030bbfda8aSnia DisplayWin(vs, twmWin); 5040bbfda8aSnia } 5050bbfda8aSnia twmWin->savevs = NULL; 5060bbfda8aSnia } 5070bbfda8aSnia state = 0; 5080bbfda8aSnia } 5090bbfda8aSnia else { 5100bbfda8aSnia for(twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) { 5110bbfda8aSnia if(twmWin->vs == vs 5120bbfda8aSnia#ifdef EWMH 5130bbfda8aSnia /* leave wt_Desktop and wt_Dock visible */ 5140bbfda8aSnia && twmWin->ewmhWindowType == wt_Normal 5150bbfda8aSnia#endif /* EWMH */ 5160bbfda8aSnia ) { 5170bbfda8aSnia twmWin->savevs = twmWin->vs; 5180bbfda8aSnia Vanish(vs, twmWin); 5190bbfda8aSnia } 5200bbfda8aSnia } 5210bbfda8aSnia state = 1; 5220bbfda8aSnia } 5230bbfda8aSnia#ifdef EWMH 5240bbfda8aSnia EwmhSet_NET_SHOWING_DESKTOP(state); 5250bbfda8aSnia#endif /* EWMH */ 5260bbfda8aSnia} 5270bbfda8aSnia 5280bbfda8aSnia 5290bbfda8aSnia/* 5300bbfda8aSnia * Get the name of the currently active WS. Used in Execute() for 5310bbfda8aSnia * sub'ing in $currentworkspace in executing commands. 5320bbfda8aSnia */ 5330bbfda8aSniachar * 5340bbfda8aSniaGetCurrentWorkSpaceName(VirtualScreen *vs) 5350bbfda8aSnia{ 5360bbfda8aSnia if(! Scr->workSpaceManagerActive) { 5370bbfda8aSnia return (NULL); 5380bbfda8aSnia } 5390bbfda8aSnia if(!vs) { 5400bbfda8aSnia vs = Scr->vScreenList; 5410bbfda8aSnia } 5420bbfda8aSnia return vs->wsw->currentwspc->name; 5430bbfda8aSnia} 5440bbfda8aSnia 5450bbfda8aSnia 5460bbfda8aSnia/* 5470bbfda8aSnia * Find workspace by name 5480bbfda8aSnia */ 5490bbfda8aSniaWorkSpace * 5500bbfda8aSniaGetWorkspace(const char *wname) 5510bbfda8aSnia{ 5520bbfda8aSnia WorkSpace *ws; 5530bbfda8aSnia 5540bbfda8aSnia /* Guard */ 5550bbfda8aSnia if(!wname) { 5560bbfda8aSnia return (NULL); 5570bbfda8aSnia } 5580bbfda8aSnia 5590bbfda8aSnia /* Check by label */ 5600bbfda8aSnia for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { 5610bbfda8aSnia if(strcmp(ws->label, wname) == 0) { 5620bbfda8aSnia return ws; 5630bbfda8aSnia } 5640bbfda8aSnia } 5650bbfda8aSnia 5660bbfda8aSnia /* Check by name */ 5670bbfda8aSnia for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { 5680bbfda8aSnia if(strcmp(ws->name, wname) == 0) { 5690bbfda8aSnia return ws; 5700bbfda8aSnia } 5710bbfda8aSnia } 5720bbfda8aSnia 5730bbfda8aSnia /* Nope */ 5740bbfda8aSnia return NULL; 5750bbfda8aSnia} 576