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