CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/workspace_utils.c
Go to the documentation of this file.
1/*
2 * Various workspace handling and utilities.
3 */
4
5#include "ctwm.h"
6
7#include <stdio.h>
8#include <string.h>
9#include <stdlib.h>
10
11#include <X11/Xatom.h>
12
13#include "animate.h"
14#include "clicktofocus.h"
15#include "ctwm_atoms.h"
16#include "drawing.h"
17#include "functions.h"
18#include "iconmgr.h"
19#include "image.h"
20#include "otp.h"
21#include "screen.h"
22#include "vscreen.h"
23#include "win_ops.h"
24#include "win_utils.h"
25#include "workspace_manager.h"
26#include "workspace_utils.h"
27
28#ifdef EWMH
29# include "ewmh_atoms.h"
30#endif
31
32
33/*
34 * XXX I'm not sure this should be here; maybe it's more of a per-screen
35 * thing, and so should be in the Screen struct?
36 */
37bool useBackgroundInfo = false;
38
39
40/*
41 * Move the display (of a given vs) over to a new workspace.
42 */
43void
45{
48 WList *wl, *wl1;
51 long eventMask;
52 IconMgr *iconmgr;
57
58 if(! Scr->workSpaceManagerActive) {
59 return;
60 }
61 for(tmpvs = Scr->vScreenList; tmpvs != NULL; tmpvs = tmpvs->next) {
62 if(ws == tmpvs->wsw->currentwspc) {
63 XBell(dpy, 0);
64 return;
65 }
66 }
67 oldws = vs->wsw->currentwspc;
68 newws = ws;
69 if(oldws == newws) {
70 return;
71 }
72
73 /* XXX X-ref CTAG_BGDRAW in CreateWorkSpaceManager() and below */
74 if(useBackgroundInfo && ! Scr->DontPaintRootWindow) {
75 if(newws->image == NULL) {
76 XSetWindowBackground(dpy, vs->window, newws->backcp.back);
77 }
78 else {
79 XSetWindowBackgroundPixmap(dpy, vs->window, newws->image->pixmap);
80 }
82 }
83
84 /* If SaveWorkspaceFocus is on, save the focus of the last window. */
85 if(Scr->SaveWorkspaceFocus) {
86 oldws->save_focus = Scr->Focus;
87 }
88
90 /* For better visual effect, the order or map/unmap is important:
91 - map from top to bottom.
92 - unmap from bottom to top.
93 - unmap after mapping.
94 The guiding factor: at any point during the transition, something
95 should be visible only if it was visible before the transition or if
96 it will be visible at the end. */
98
99 for(twmWin = OtpTopWin(); twmWin != NULL;
101
102 if(OCCUPY(twmWin, newws)) {
103 if(!twmWin->vs) {
104 DisplayWin(vs, twmWin);
105 }
106#ifdef EWMH
107 if(OCCUPY(twmWin, oldws)) {
108 /*
109 * If the window remains visible, re-order the workspace
110 * numbers in NET_WM_DESKTOP.
111 */
113 }
114#endif
115 }
116 }
117
118 for(twmWin = OtpBottomWin(); twmWin != NULL;
120 if(twmWin->vs == vs) {
121 if(!OCCUPY(twmWin, newws)) {
122
123 Vanish(vs, twmWin);
124#ifdef VSCREEN
125 /*
126 * Now that the window has Vanished from one virtual screen,
127 * check to see if it is wanted on another one.
128 * This is relatively rare, so don't bother with the
129 * top-to-bottom order here.
130 */
131 if(Scr->numVscreens > 1) {
133 for(tvs = Scr->vScreenList; tvs != NULL; tvs = tvs->next) {
134 if(tvs == vs) { /* no, not back on the old one */
135 continue;
136 }
137 if(OCCUPY(twmWin, tvs->wsw->currentwspc)) {
139 break;
140 }
141 }
142 }
143#endif
144 }
145 else if(twmWin->hasfocusvisible) {
148 }
149 }
150 }
152
153 /*
154 Reorganize icon manager window lists
155 */
156 for(twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
157 wl = twmWin->iconmanagerlist;
158 if(wl == NULL) {
159 continue;
160 }
161 if(OCCUPY(wl->iconmgr->twm_win, newws)) {
162 continue;
163 }
164 wl1 = wl;
165 wl = wl->nextv;
166 while(wl != NULL) {
167 if(OCCUPY(wl->iconmgr->twm_win, newws)) {
168 break;
169 }
170 wl1 = wl;
171 wl = wl->nextv;
172 }
173 if(wl != NULL) {
174 wl1->nextv = wl->nextv;
175 wl->nextv = twmWin->iconmanagerlist;
176 twmWin->iconmanagerlist = wl;
177 }
178 }
179 wl = NULL;
180 for(iconmgr = newws->iconmgr; iconmgr; iconmgr = iconmgr->next) {
181 if(iconmgr->first) {
182 wl = iconmgr->first;
183 break;
184 }
185 }
187 if(focuswindow) {
189 }
190 vs->wsw->currentwspc = newws;
191 if(Scr->ReverseCurrentWorkspace && vs->wsw->state == WMS_map) {
192 MapSubwindow *msw = vs->wsw->mswl [oldws->number];
193 for(winl = msw->wl; winl != NULL; winl = winl->next) {
194 WMapRedrawName(vs, winl);
195 }
196 msw = vs->wsw->mswl [newws->number];
197 for(winl = msw->wl; winl != NULL; winl = winl->next) {
198 WMapRedrawName(vs, winl);
199 }
200 }
201 else if(vs->wsw->state == WMS_buttons) {
202 ButtonSubwindow *bsw = vs->wsw->bswl [oldws->number];
203 PaintWsButton(WSPCWINDOW, vs, bsw->w, oldws->label, oldws->cp, off);
204 bsw = vs->wsw->bswl [newws->number];
205 PaintWsButton(WSPCWINDOW, vs, bsw->w, newws->label, newws->cp, on);
206 }
207 oldws->iconmgr = Scr->iconmgr;
208 Scr->iconmgr = newws->iconmgr;
209
210 /* XXX X-ref CTAG_BGDRAW in CreateWorkSpaceManager() and above */
211 oldw = vs->wsw->mswl [oldws->number]->w;
212 neww = vs->wsw->mswl [newws->number]->w;
214 if(oldws->image == NULL || Scr->NoImagesInWorkSpaceManager) {
215 XSetWindowBackground(dpy, oldw, oldws->backcp.back);
216 }
217 else {
218 XSetWindowBackgroundPixmap(dpy, oldw, oldws->image->pixmap);
219 }
220 }
221 else {
222 if(Scr->workSpaceMgr.defImage == NULL || Scr->NoImagesInWorkSpaceManager) {
223 XSetWindowBackground(dpy, oldw, Scr->workSpaceMgr.defColors.back);
224 }
225 else {
226 XSetWindowBackgroundPixmap(dpy, oldw, Scr->workSpaceMgr.defImage->pixmap);
227 }
228 }
229 attr.border_pixel = Scr->workSpaceMgr.defBorderColor;
231
232 if(Scr->workSpaceMgr.curImage == NULL) {
233 if(Scr->workSpaceMgr.curPaint) {
234 XSetWindowBackground(dpy, neww, Scr->workSpaceMgr.curColors.back);
235 }
236 }
237 else {
238 XSetWindowBackgroundPixmap(dpy, neww, Scr->workSpaceMgr.curImage->pixmap);
239 }
240 attr.border_pixel = Scr->workSpaceMgr.curBorderColor;
242
245
247
249 PropModeReplace, (unsigned char *) newws->name, strlen(newws->name));
250#ifdef EWMH
251 {
252 long number = newws->number;
253 /*
254 * TODO: this should probably not use Scr->Root but ->XineramaRoot.
255 * That is the real root window if we're using virtual screens.
256 * Also, on the real root it would need values for each of the
257 * virtual roots, but that doesn't fit in the EWMH ideas.
258 */
260 XA_CARDINAL, 32,
261 PropModeReplace, (unsigned char *) &number, 1);
262 }
263#endif /* EWMH */
264
265 restore_mask(Scr->Root, eventMask);
266
267 /* XDestroyWindow (dpy, cachew);*/
268 if(Scr->ChangeWorkspaceFunction.func != 0) {
269 char *action;
271
272 action = Scr->ChangeWorkspaceFunction.item ?
273 Scr->ChangeWorkspaceFunction.item->action : NULL;
274 ExecuteFunction(Scr->ChangeWorkspaceFunction.func, action,
275 (Window) 0, NULL, &event, C_ROOT, false);
276 }
277
278 /* If SaveWorkspaceFocus is on, try to restore the focus to the last
279 window which was focused when we left this workspace. */
280 if(Scr->SaveWorkspaceFocus && newws->save_focus) {
281 twmWin = newws->save_focus;
282 if(OCCUPY(twmWin, newws)) { /* check should not even be needed anymore */
283 WarpToWindow(twmWin, false);
284 }
285 else {
286 newws->save_focus = NULL;
287 }
288 }
289
290 /* keep track of the order of the workspaces across restarts */
291 CtwmSetVScreenMap(dpy, Scr->Root, Scr->vScreenList);
292
293 XSync(dpy, 0);
294 if(Scr->ClickToFocus || Scr->SloppyFocus) {
296 }
297 MaybeAnimate = true;
298}
299
300
301
302/*
303 * Various frontends to GotoWorkSpace()
304 */
305
306/*
307 * Simplify redundant checks. If no multiple workspaces, or no vs given
308 * to the func, there's nothing to do.
309 */
310#define GWS_CHECK do { \
311 if(! Scr->workSpaceManagerActive) { \
312 return; \
313 } \
314 if(!vs) { \
315 return; \
316 } \
317 } while(0)
318
319void
321{
322 WorkSpace *ws;
323
324 GWS_CHECK;
325
327 if(ws == NULL) {
328 return;
329 }
330 GotoWorkSpace(vs, ws);
331}
332
333
334void
336{
337 WorkSpace *ws;
338
339 GWS_CHECK;
340
341 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
342 if(ws->number == workspacenum) {
343 break;
344 }
345 }
346 if(ws == NULL) {
347 return;
348 }
349 GotoWorkSpace(vs, ws);
350}
351
352
353void
355{
356 WorkSpace *ws1, *ws2;
357
358 GWS_CHECK;
359
360 ws1 = Scr->workSpaceMgr.workSpaceList;
361 if(ws1 == NULL) {
362 return;
363 }
364 ws2 = ws1->next;
365
366 while((ws2 != vs->wsw->currentwspc) && (ws2 != NULL)) {
367 ws1 = ws2;
368 ws2 = ws2->next;
369 }
370 GotoWorkSpace(vs, ws1);
371}
372
373
374void
376{
377 WorkSpace *ws;
378
379 GWS_CHECK;
380
381 ws = vs->wsw->currentwspc;
382 ws = (ws->next != NULL) ? ws->next : Scr->workSpaceMgr.workSpaceList;
383 GotoWorkSpace(vs, ws);
384}
385
386
387void
389{
390 WorkSpace *ws;
391 int number, columns, count;
392
393 GWS_CHECK;
394
395 ws = vs->wsw->currentwspc;
396 number = ws->number;
397 columns = Scr->workSpaceMgr.columns;
398 count = Scr->workSpaceMgr.count;
399 number++;
400 if((number % columns) == 0) {
401 number -= columns;
402 }
403 else if(number >= count) {
404 number = (number / columns) * columns;
405 }
406
407 GotoWorkSpaceByNumber(vs, number);
408}
409
410
411void
413{
414 WorkSpace *ws;
415 int number, columns, count;
416
417 GWS_CHECK;
418
419 ws = vs->wsw->currentwspc;
420 number = ws->number;
421 columns = Scr->workSpaceMgr.columns;
422 count = Scr->workSpaceMgr.count;
423 number += (number % columns) ? -1 : (columns - 1);
424 if(number >= count) {
425 number = count - 1;
426 }
427 GotoWorkSpaceByNumber(vs, number);
428}
429
430
431void
433{
434 WorkSpace *ws;
435 int number, lines, columns, count;
436
437 GWS_CHECK;
438
439 ws = vs->wsw->currentwspc;
440 number = ws->number;
441 lines = Scr->workSpaceMgr.lines;
442 columns = Scr->workSpaceMgr.columns;
443 count = Scr->workSpaceMgr.count;
444 number -= columns;
445 if(number < 0) {
446 number += lines * columns;
447 /* If the number of workspaces is not a multiple of nr of columns */
448 if(number >= count) {
449 number -= columns;
450 }
451 }
452 GotoWorkSpaceByNumber(vs, number);
453}
454
455
456void
458{
459 WorkSpace *ws;
460 int number, columns, count;
461
462 GWS_CHECK;
463
464 ws = vs->wsw->currentwspc;
465 number = ws->number;
466 columns = Scr->workSpaceMgr.columns;
467 count = Scr->workSpaceMgr.count;
468 number += columns;
469 if(number >= count) {
470 number %= columns;
471 }
472 GotoWorkSpaceByNumber(vs, number);
473}
474
475#undef GWS_CHECK
476
477
478
479/*
480 * Show the background (by hiding all windows) or undo it.
481 * f.showbackground, also can be called via EWMH bits.
482 *
483 * newstate is the desired showing state.
484 * Pass -1 to toggle, 1 to show the background,
485 * or 0 to re-show the windows.
486 *
487 * XXX Doesn't really belong here; more of a functions.c-ish thing
488 * probably. But left here for the moment.
489 */
490void
492{
493 static int state = 0;
495
496 if(newstate == state) {
497 return;
498 }
499
500 if(state) {
501 for(twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
502 if(twmWin->savevs == vs) {
503 DisplayWin(vs, twmWin);
504 }
505 twmWin->savevs = NULL;
506 }
507 state = 0;
508 }
509 else {
510 for(twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
511 if(twmWin->vs == vs
512#ifdef EWMH
513 /* leave wt_Desktop and wt_Dock visible */
514 && twmWin->ewmhWindowType == wt_Normal
515#endif /* EWMH */
516 ) {
517 twmWin->savevs = twmWin->vs;
518 Vanish(vs, twmWin);
519 }
520 }
521 state = 1;
522 }
523#ifdef EWMH
525#endif /* EWMH */
526}
527
528
529/*
530 * Get the name of the currently active WS. Used in Execute() for
531 * sub'ing in $currentworkspace in executing commands.
532 */
533char *
535{
536 if(! Scr->workSpaceManagerActive) {
537 return (NULL);
538 }
539 if(!vs) {
540 vs = Scr->vScreenList;
541 }
542 return vs->wsw->currentwspc->name;
543}
544
545
546/*
547 * Find workspace by name
548 */
549WorkSpace *
550GetWorkspace(const char *wname)
551{
552 WorkSpace *ws;
553
554 /* Guard */
555 if(!wname) {
556 return (NULL);
557 }
558
559 /* Check by label */
560 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
561 if(strcmp(ws->label, wname) == 0) {
562 return ws;
563 }
564 }
565
566 /* Check by name */
567 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
568 if(strcmp(ws->name, wname) == 0) {
569 return ws;
570 }
571 }
572
573 /* Nope */
574 return NULL;
575}
static int PlaceX
Definition add_window.c:82
bool MaybeAnimate
Definition animate.c:33
void set_last_window(WorkSpace *current)
#define OCCUPY(w, b)
Definition ctwm.h:369
Display * dpy
Definition ctwm_main.c:84
#define C_ROOT
Definition ctwm.h:78
#define Scr
void PaintWsButton(PWBType which, VirtualScreen *vs, Window w, char *label, ColorPair cp, ButtonState state)
Definition drawing.c:153
@ off
Definition drawing.h:8
@ on
Definition drawing.h:8
@ WSPCWINDOW
Definition drawing.h:16
void EwmhSet_NET_WM_DESKTOP_ws(TwmWindow *twm_win, WorkSpace *ws)
Definition ewmh.c:1487
void EwmhSet_NET_SHOWING_DESKTOP(int state)
Definition ewmh.c:2116
@ wt_Normal
Definition ewmh.h:17
void ExecuteFunction(int func, void *action, Window w, TwmWindow *tmp_win, XEvent *eventp, int context, bool pulldown)
Definition functions.c:99
void CurrentIconManagerEntry(WList *current)
Definition iconmgr.c:1030
TwmWindow * OtpNextWinDown(TwmWindow *twm_win)
Definition otp.c:1467
TwmWindow * OtpNextWinUp(TwmWindow *twm_win)
Definition otp.c:1458
bool OtpCheckConsistency(void)
Definition otp.c:188
TwmWindow * OtpBottomWin(void)
Definition otp.c:1437
TwmWindow * OtpTopWin(void)
Definition otp.c:1446
TwmWindow * twm_win
Definition iconmgr.h:45
struct WList * first
Definition iconmgr.h:42
struct IconMgr * next
Next iconmgr in this workspace.
Definition iconmgr.h:37
Info and control for every X Window we take over.
struct WorkSpaceWindow * wsw
Definition vscreen.h:11
Window window
Definition vscreen.h:9
struct WList * nextv
Definition iconmgr.h:20
struct IconMgr * iconmgr
Definition iconmgr.h:22
WorkSpace * currentwspc
ButtonSubwindow ** bswl
MapSubwindow ** mswl
struct WorkSpace * next
void Vanish(VirtualScreen *vs, TwmWindow *tmp_win)
Definition vscreen.c:344
bool CtwmSetVScreenMap(Display *display, Window rootw, struct VirtualScreen *firstvs)
Definition vscreen.c:196
void DisplayWin(VirtualScreen *vs, TwmWindow *tmp_win)
Definition vscreen.c:232
void SetFocusVisualAttributes(TwmWindow *tmp_win, bool focus)
Definition win_ops.c:30
int restore_mask(Window w, long restore)
Definition win_utils.c:399
long mask_out_event(Window w, long ignore_event)
Definition win_utils.c:366
void WarpToWindow(TwmWindow *t, bool must_raise)
Definition win_utils.c:883
void WMapRedrawName(VirtualScreen *vs, WinList *wl)
@ WMS_buttons
@ WMS_map
void GotoPrevWorkSpace(VirtualScreen *vs)
void GotoRightWorkSpace(VirtualScreen *vs)
#define GWS_CHECK
bool useBackgroundInfo
void GotoWorkSpace(VirtualScreen *vs, WorkSpace *ws)
void GotoWorkSpaceByNumber(VirtualScreen *vs, int workspacenum)
void GotoWorkSpaceByName(VirtualScreen *vs, const char *wname)
void ShowBackground(VirtualScreen *vs, int newstate)
void GotoLeftWorkSpace(VirtualScreen *vs)
WorkSpace * GetWorkspace(const char *wname)
void GotoDownWorkSpace(VirtualScreen *vs)
void GotoNextWorkSpace(VirtualScreen *vs)
char * GetCurrentWorkSpaceName(VirtualScreen *vs)
void GotoUpWorkSpace(VirtualScreen *vs)