~ctwm/ctwm/trunk

304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
1
/*
554.1.6 by Matthew Fuller
Collapse away redundant license texts in most .h files. These are all
2
 * Copyright 1992 Claude Lecommandeur.
21 by Richard Levitte
This constitutes all the changes Claude had done since version 3.6.
3
 */
4
395.1.1 by Matthew Fuller
Move ctwm.h to always be included first.
5
#include "ctwm.h"
6
685.1.29 by Matthew Fuller
Add assert for an invariant; these vs's are always set to something.
7
#include <assert.h>
21 by Richard Levitte
This constitutes all the changes Claude had done since version 3.6.
8
#include <stdio.h>
491.1.14 by Matthew Fuller
Remove incorrect pre-ANSI potential override prototypes for malloc()
9
#include <stdlib.h>
340.1.1 by Matthew Fuller
Rearrange includes to be in what we'll call the Proper Order.
10
492.2.17 by Matthew Fuller
Cleanup some unneeded X headers and canoncalize ordering. In
11
#include <X11/Xatom.h>
12
335.1.1 by Olaf 'Rhialto' Seibert
Automated Atoms, now for the ctwm core. Step 1: replacement of the many
13
#include "ctwm_atoms.h"
93 by Richard Levitte
- Convert all functions to use proper prototypes.
14
#include "cursor.h"
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
15
#include "icons.h"
524.1.5 by Matthew Fuller
Pull list.h out of screen.h and #include it in the places that need
16
#include "list.h"
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
17
#include "otp.h"
21 by Richard Levitte
This constitutes all the changes Claude had done since version 3.6.
18
#include "screen.h"
524.1.3 by Matthew Fuller
Pull vscreen.h out of screen.h and #include it directly in the files
19
#include "vscreen.h"
523.1.18 by Matthew Fuller
Move the masking funcs into win_util and GC util.h from the files only
20
#include "win_utils.h"
21 by Richard Levitte
This constitutes all the changes Claude had done since version 3.6.
21
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
22
23
static void DisplayWinUnchecked(VirtualScreen *vs, TwmWindow *tmp_win);
24
25
696.1.5 by Matthew Fuller
Extract this init off into a helper function.
26
static void init_def_vscreen(ScreenInfo *scr)
27
{
28
	VirtualScreen *vs = malloc(sizeof(VirtualScreen));
29
30
	vs->x      = 0;
31
	vs->y      = 0;
32
	vs->w      = scr->rootw;
33
	vs->h      = scr->rooth;
34
	vs->window = scr->Root;
35
	vs->next   = NULL;
36
	vs->wsw    = 0;
37
	scr->vScreenList = vs;
38
	scr->currentvs   = vs;
696.1.16 by Matthew Fuller
Conditionalize initing numVscreens, which means all uses of it are now
39
#ifdef VSCREEN
696.1.5 by Matthew Fuller
Extract this init off into a helper function.
40
	scr->numVscreens = 1;
696.1.16 by Matthew Fuller
Conditionalize initing numVscreens, which means all uses of it are now
41
#endif
696.1.5 by Matthew Fuller
Extract this init off into a helper function.
42
	return;
43
}
44
45
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
46
void InitVirtualScreens(ScreenInfo *scr)
47
{
696.1.6 by Matthew Fuller
Stub InitVirtualScreens down to its bare minimum form in the ifndef
48
#ifndef VSCREEN
49
	// Just do the faking if vscreens are all off anyway.
50
	init_def_vscreen(scr);
51
	return;
52
#else
53
54
	// Real implementation
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
55
	Cursor cursor;
56
	unsigned long valuemask, attrmask;
57
	XSetWindowAttributes attributes;
58
	name_list *nptr;
59
	VirtualScreen *vs00 = NULL;
60
61
	NewFontCursor(&cursor, "X_cursor");
62
63
	if(scr->VirtualScreens == NULL) {
696.1.5 by Matthew Fuller
Extract this init off into a helper function.
64
		init_def_vscreen(scr);
696.1.4 by Matthew Fuller
Reindent.
65
		return;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
66
	}
67
	scr->numVscreens = 0;
68
69
	attrmask  = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
70
	            SubstructureRedirectMask | KeyPressMask | ButtonPressMask |
71
	            ButtonReleaseMask;
72
570.1.3 by Matthew Fuller
Setting SaveUnder=False on new windows is pointless, because that's
73
	valuemask = CWBackPixel | CWOverrideRedirect | CWEventMask | CWCursor;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
74
	attributes.override_redirect = True;
75
	attributes.event_mask        = attrmask;
76
	attributes.cursor            = cursor;
77
	attributes.background_pixel  = Scr->Black;
78
79
	scr->vScreenList = NULL;
80
	for(nptr = Scr->VirtualScreens; nptr != NULL; nptr = nptr->next) {
81
		VirtualScreen *vs;
82
		char *geometry = (char *) nptr->name;
83
		int x = 0, y = 0;
84
		unsigned int w = 0, h = 0;
85
86
		XParseGeometry(geometry, &x, &y, &w, &h);
87
88
		if((x < 0) || (y < 0) || (w > scr->rootw) || (h > scr->rooth)) {
89
			fprintf(stderr, "InitVirtualScreens : invalid geometry : %s\n", geometry);
90
			continue;
91
		}
491.1.8 by Matthew Fuller
Stop casting return values of [mc]alloc(). void * has existed for 27
92
		vs = malloc(sizeof(VirtualScreen));
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
93
		vs->x = x;
94
		vs->y = y;
95
		vs->w = w;
96
		vs->h = h;
97
		vs->window = XCreateWindow(dpy, Scr->Root, x, y, w, h,
505.1.19 by Matthew Fuller
Remove casts from XCreateWindow() calls. Some of these were probably
98
		                           0, CopyFromParent, CopyFromParent,
99
		                           CopyFromParent, valuemask, &attributes);
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
100
		vs->wsw = 0;
101
102
		XSync(dpy, 0);
103
		XMapWindow(dpy, vs->window);
335.1.4 by Olaf 'Rhialto' Seibert
Add WM_VIRTUALROOT to the Automated Atoms.
104
		XChangeProperty(dpy, vs->window, XA_WM_VIRTUALROOT, XA_STRING, 8,
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
105
		                PropModeReplace, (unsigned char *) "Yes", 4);
106
107
		vs->next = scr->vScreenList;
108
		scr->vScreenList = vs;
109
		Scr->numVscreens++;
110
111
		/*
112
		 * Remember which virtual screen is at (0,0).
113
		 */
114
		if(x == 0 && y == 0) {
115
			vs00 = vs;
116
		}
117
	}
118
119
	if(scr->vScreenList == NULL) {
120
		fprintf(stderr, "no valid VirtualScreens found, exiting...\n");
121
		exit(1);
122
	}
123
	/* Setup scr->{currentvs,Root{,x,y,w,h}} as if the
124
	 * _correct_ virtual screen is entered with the mouse.
125
	 * See HandleEnterNotify().
126
	 */
127
	if(vs00 == NULL) {
128
		vs00 = scr->vScreenList;
129
	}
130
131
	Scr->Root  = vs00->window;
692.1.5 by Matthew Fuller
Add ifdef's around references to Screen and CLargs members that are
132
#ifdef CAPTIVE
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
133
	Scr->rootx = Scr->crootx + vs00->x;
134
	Scr->rooty = Scr->crooty + vs00->y;
692.1.5 by Matthew Fuller
Add ifdef's around references to Screen and CLargs members that are
135
#else
136
	Scr->rootx = vs00->x;
137
	Scr->rooty = vs00->y;
138
#endif
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
139
	Scr->rootw = vs00->w;
140
	Scr->rooth = vs00->h;
141
	Scr->currentvs = vs00;
696.1.6 by Matthew Fuller
Stub InitVirtualScreens down to its bare minimum form in the ifndef
142
#endif  // VSCREEN
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
143
}
144
696.1.11 by Matthew Fuller
Can carve this func out cleanly now in !VSCREEN case.
145
#ifdef VSCREEN
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
146
VirtualScreen *findIfVScreenOf(int x, int y)
147
{
148
	VirtualScreen *vs;
149
	for(vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
150
151
		if((x >= vs->x) && ((x - vs->x) < vs->w) &&
152
		                (y >= vs->y) && ((y - vs->y) < vs->h)) {
153
			return vs;
154
		}
155
	}
156
	return NULL;
157
}
696.1.11 by Matthew Fuller
Can carve this func out cleanly now in !VSCREEN case.
158
#endif
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
159
190 by Richard Levitte
Unused variables, undeclared functions and a few other things corrected
160
/*
186 by Todd Kover
161
 * Returns the order that virtual screens are displayed for the vscreen
162
 * list.  This is stored this way so everything ends up in the right place
190 by Richard Levitte
Unused variables, undeclared functions and a few other things corrected
163
 * on a ctwm restart.
164
 */
510.1.37 by Matthew Fuller
Just let CtwmGetVScreenMap() allocate and return the string, rather
165
char *
166
CtwmGetVScreenMap(Display *display, Window rootw)
190 by Richard Levitte
Unused variables, undeclared functions and a few other things corrected
167
{
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
168
	unsigned char       *prop;
169
	unsigned long       bytesafter;
170
	unsigned long       len;
171
	Atom                actual_type;
172
	int                 actual_format;
510.1.37 by Matthew Fuller
Just let CtwmGetVScreenMap() allocate and return the string, rather
173
	char                *ret;
190 by Richard Levitte
Unused variables, undeclared functions and a few other things corrected
174
335.1.1 by Olaf 'Rhialto' Seibert
Automated Atoms, now for the ctwm core. Step 1: replacement of the many
175
	if(XA_WM_CTWM_VSCREENMAP == None) {
492.2.36 by Matthew Fuller
bool-ify these vscreen functions.
176
		return false;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
177
	}
335.1.1 by Olaf 'Rhialto' Seibert
Automated Atoms, now for the ctwm core. Step 1: replacement of the many
178
	if(XGetWindowProperty(display, rootw, XA_WM_CTWM_VSCREENMAP, 0L, 512,
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
179
	                      False, XA_STRING, &actual_type, &actual_format, &len,
180
	                      &bytesafter, &prop) != Success) {
510.1.37 by Matthew Fuller
Just let CtwmGetVScreenMap() allocate and return the string, rather
181
		return NULL;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
182
	}
183
	if(len == 0) {
510.1.37 by Matthew Fuller
Just let CtwmGetVScreenMap() allocate and return the string, rather
184
		return NULL;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
185
	}
510.1.37 by Matthew Fuller
Just let CtwmGetVScreenMap() allocate and return the string, rather
186
187
	ret = malloc(len + 1);
188
	memcpy(ret, prop, len);
189
	ret[len] = '\0';
503.1.18 by Matthew Fuller
Stop casting XFree() arg; it's now spec'd to take a void * anyway.
190
	XFree(prop);
510.1.37 by Matthew Fuller
Just let CtwmGetVScreenMap() allocate and return the string, rather
191
192
	return ret;
186 by Todd Kover
193
}
194
492.2.124 by Matthew Fuller
Go ahead and break some function definitions that I've changed anyway.
195
bool
196
CtwmSetVScreenMap(Display *display, Window rootw,
197
                  struct VirtualScreen *firstvs)
186 by Todd Kover
198
{
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
199
	char                        buf[1024];
200
	int                         tally = 0;
201
	struct VirtualScreen        *vs;
202
335.1.1 by Olaf 'Rhialto' Seibert
Automated Atoms, now for the ctwm core. Step 1: replacement of the many
203
	if(XA_WM_CTWM_VSCREENMAP == None) {
492.2.36 by Matthew Fuller
bool-ify these vscreen functions.
204
		return false;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
205
	}
206
207
	memset(buf, 0, sizeof(buf));
208
	for(vs = firstvs; vs; vs = vs->next) {
209
		if(tally) {
210
			strcat(buf, ",");
211
		}
212
		if(vs->wsw && vs->wsw->currentwspc && vs->wsw->currentwspc->name) {
213
			strcat(buf, vs->wsw->currentwspc->name);
214
			tally++;
215
		}
216
	}
217
218
	if(! tally) {
492.2.36 by Matthew Fuller
bool-ify these vscreen functions.
219
		return false;
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
220
	}
221
335.1.1 by Olaf 'Rhialto' Seibert
Automated Atoms, now for the ctwm core. Step 1: replacement of the many
222
	XChangeProperty(display, rootw, XA_WM_CTWM_VSCREENMAP, XA_STRING, 8,
304.1.2 by Matthew Fuller
Run 'make indent' to reindent the world.
223
	                PropModeReplace, (unsigned char *)buf, strlen(buf));
492.2.36 by Matthew Fuller
bool-ify these vscreen functions.
224
	return true;
186 by Todd Kover
225
}
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
226
227
228
/*
229
 * Display a window in a given virtual screen.
230
 */
231
void
232
DisplayWin(VirtualScreen *vs, TwmWindow *tmp_win)
233
{
234
	OtpCheckConsistency();
235
	DisplayWinUnchecked(vs, tmp_win);
236
	OtpCheckConsistency();
237
}
238
239
static void
240
DisplayWinUnchecked(VirtualScreen *vs, TwmWindow *tmp_win)
241
{
242
	/*
243
	 * A window cannot be shown in multiple virtual screens, even if
244
	 * it occupies both corresponding workspaces.
245
	 */
246
	if(vs && tmp_win->vs) {
247
		return;
248
	}
249
250
	/* This is where we're moving it */
251
	tmp_win->vs = vs;
252
253
254
	/* If it's unmapped, RFAI() moves the necessary bits here */
255
	if(!tmp_win->mapped) {
256
		ReparentFrameAndIcon(tmp_win);
257
258
		/* If it's got an icon that should be up, make it up here */
259
		if(tmp_win->isicon) {
260
			if(tmp_win->icon_on) {
261
				if(tmp_win->icon && tmp_win->icon->w) {
262
263
					IconUp(tmp_win);
264
					XMapWindow(dpy, tmp_win->icon->w);
265
				}
266
			}
267
		}
268
269
		/* All there is to do with unmapped wins */
270
		return;
271
	}
272
273
274
	/* If we make it this far, the window is mapped */
275
276
	if(tmp_win->UnmapByMovingFarAway) {
277
		/*
278
		 * XXX I don't believe the handling of UnmapByMovingFarAway is
279
		 * quite correct.
280
		 */
281
		if(vs) {
282
			XReparentWindow(dpy, tmp_win->frame, vs->window,
283
			                tmp_win->frame_x, tmp_win->frame_y);
284
		}
285
		else {
286
			XMoveWindow(dpy, tmp_win->frame, tmp_win->frame_x, tmp_win->frame_y);
287
		}
288
	}
289
	else {
290
		/* Map and move it here */
291
		if(!tmp_win->squeezed) {
511.1.9 by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually
292
			long eventMask;
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
293
511.1.9 by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually
294
			eventMask = mask_out_event(tmp_win->w, StructureNotifyMask);
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
295
			XMapWindow(dpy, tmp_win->w);
511.1.9 by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually
296
			restore_mask(tmp_win->w, eventMask);
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
297
		}
298
299
		ReparentFrameAndIcon(tmp_win);
300
301
		XMapWindow(dpy, tmp_win->frame);
302
		SetMapStateProp(tmp_win, NormalState);
303
	}
304
}
305
306
307
/*
308
 * Move a window's frame and icon to a new VS.  This mostly happens as a
309
 * backend bit of the DisplayWin() process, but it does get called
310
 * directly for the Occupy window.  XXX Should it?
311
 */
312
void
313
ReparentFrameAndIcon(TwmWindow *tmp_win)
314
{
315
	VirtualScreen *vs = tmp_win->vs; /* which virtual screen we want it in */
316
317
	/* parent_vs is the current real parent of the window */
318
	if(vs != tmp_win->parent_vs) {
319
		struct Icon *icon = tmp_win->icon;
320
685.1.29 by Matthew Fuller
Add assert for an invariant; these vs's are always set to something.
321
		// This must always be something...
322
		assert(vs != NULL);
323
509.1.3 by Matthew Fuller
DisplayWin*() and ReparentFrameAndIcon() are all about changing
324
		tmp_win->parent_vs = vs;
325
326
		if(icon && icon->w) {
327
			ReparentWindowAndIcon(dpy, tmp_win, vs->window,
328
			                      tmp_win->frame_x, tmp_win->frame_y,
329
			                      icon->w_x, icon->w_y);
330
		}
331
		else {
332
			ReparentWindow(dpy, tmp_win,  WinWin, vs->window,
333
			               tmp_win->frame_x, tmp_win->frame_y);
334
		}
335
	}
336
}
509.1.4 by Matthew Fuller
Vanish() is also a vscreen thing, not a workspace thing.
337
338
339
/*
340
 * Get this window outta here.  Note that despite naming, this is
341
 * unrelated to f.vanish.
342
 */
343
void
344
Vanish(VirtualScreen *vs, TwmWindow *tmp_win)
345
{
346
	/* It's not here?  Nothing to do. */
347
	if(vs && tmp_win->vs && tmp_win->vs != vs) {
348
		return;
349
	}
350
351
	/* Unmap (or near-equivalent) all its bits */
352
	if(tmp_win->UnmapByMovingFarAway) {
353
		/* UnmapByMovingFarAway?  Move it off-screen */
354
		XMoveWindow(dpy, tmp_win->frame, Scr->rootw + 1, Scr->rooth + 1);
355
	}
356
	else if(tmp_win->mapped) {
357
		/* It's mapped; unmap it */
511.1.9 by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually
358
		long eventMask;
509.1.4 by Matthew Fuller
Vanish() is also a vscreen thing, not a workspace thing.
359
511.1.9 by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually
360
		eventMask = mask_out_event(tmp_win->w, StructureNotifyMask);
509.1.4 by Matthew Fuller
Vanish() is also a vscreen thing, not a workspace thing.
361
		XUnmapWindow(dpy, tmp_win->w);
362
		XUnmapWindow(dpy, tmp_win->frame);
511.1.9 by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually
363
		restore_mask(tmp_win->w, eventMask);
509.1.4 by Matthew Fuller
Vanish() is also a vscreen thing, not a workspace thing.
364
365
		if(!tmp_win->DontSetInactive) {
366
			SetMapStateProp(tmp_win, InactiveState);
367
		}
368
	}
369
	else if(tmp_win->icon_on && tmp_win->icon && tmp_win->icon->w) {
370
		/* It's not mapped, but the icon's up; hide it away */
371
		XUnmapWindow(dpy, tmp_win->icon->w);
372
		IconDown(tmp_win);
373
	}
374
375
#if 0
376
	/*
377
	 * The purpose of this is in the event of a ctwm death/restart,
378
	 * geometries of windows that were on unmapped workspaces will show
379
	 * up where they belong.
380
	 * XXX - I doubt its usefulness, since still-mapped windows won't
381
	 * enjoy this "protection", making it suboptimal at best.
382
	 * XXX - XReparentWindow() messes up the stacking order of windows.
383
	 * It should be avoided as much as possible. This already affects
384
	 * switching away from and back to a workspace. Therefore do this only
385
	 * if there are at least 2 virtual screens AND the new one (firstvs)
386
	 * differs from where the window currently is. (Olaf Seibert).
387
	 */
388
389
	if(Scr->numVscreens > 1) {
390
		int x, y;
391
		unsigned int junk;
392
		Window junkW, w = tmp_win->frame;
393
		VirtualScreen *firstvs = NULL;
394
395
		for(firstvs = Scr->vScreenList; firstvs; firstvs = firstvs->next)
396
			if(firstvs->x == 0 && firstvs->y == 0) {
397
				break;
398
			}
399
		if(firstvs && firstvs != vs) {
400
			tmp_win->vs = firstvs;
401
			ReparentFrameAndIcon(tmp_win);
402
		}
403
	}
404
#endif
405
406
	/* Currently displayed nowhere */
407
	tmp_win->vs = NULL;
408
}