~ctwm/ctwm/trunk

523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
1
/*
2
 * Various operations done on windows.
3
 */
4
5
#include "ctwm.h"
6
7
#include <stdio.h>
8
9
#include "animate.h"
523.1.22 by Matthew Fuller
FocusOnRoot() is a little off what I'd really consider a "window op",
10
#include "colormaps.h"
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
11
#include "drawing.h"
523.1.22 by Matthew Fuller
FocusOnRoot() is a little off what I'd really consider a "window op",
12
#include "events.h"
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
13
#include "iconmgr.h"
14
#include "image.h"
523.1.15 by Matthew Fuller
Move squeezing bits into win_ops from menus.c. This lets us reap
15
#include "otp.h"
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
16
#include "screen.h"
538.1.3 by Matthew Fuller
Rename the decorations*.h to win_decorations*.h.
17
#include "win_decorations.h"
523.1.15 by Matthew Fuller
Move squeezing bits into win_ops from menus.c. This lets us reap
18
#include "win_iconify.h"
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
19
#include "win_ops.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"
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
21
22
523.1.12 by Matthew Fuller
Add header comments and document provenance.
23
/*
24
 * Update the visuals of a window (e.g., its own decorations and its
25
 * representation in the icon manager) for having/losing focus.
26
 *
27
 * Formerly in util.c
28
 */
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
29
void
30
SetFocusVisualAttributes(TwmWindow *tmp_win, bool focus)
31
{
32
	if(! tmp_win) {
33
		return;
34
	}
35
36
	if(focus == tmp_win->hasfocusvisible) {
37
		return;
38
	}
39
	if(tmp_win->highlight) {
40
		if(Scr->use3Dborders) {
41
			PaintBorders(tmp_win, focus);
42
		}
43
		else {
44
			if(focus) {
45
				XSetWindowBorder(dpy, tmp_win->frame, tmp_win->borderC.back);
46
				if(tmp_win->title_w) {
47
					XSetWindowBorder(dpy, tmp_win->title_w, tmp_win->borderC.back);
48
				}
49
			}
50
			else {
51
				/*
52
				 * XXX It seems possible this could be replaced by a
53
				 * single global 'gray' pixmap; I don't think it actually
54
				 * varies per window, and I don't see any obvious reason
55
				 * it can't be reused, so we may be able to save an
56
				 * allocation for each window by doing so...
57
				 */
58
				XSetWindowBorderPixmap(dpy, tmp_win->frame, tmp_win->gray);
59
				if(tmp_win->title_w) {
60
					XSetWindowBorderPixmap(dpy, tmp_win->title_w, tmp_win->gray);
61
				}
62
			}
63
		}
64
	}
65
66
	if(focus) {
67
		bool hil = false;
68
69
		if(tmp_win->lolite_wl) {
70
			XUnmapWindow(dpy, tmp_win->lolite_wl);
71
		}
72
		if(tmp_win->lolite_wr) {
73
			XUnmapWindow(dpy, tmp_win->lolite_wr);
74
		}
75
		if(tmp_win->hilite_wl) {
76
			XMapWindow(dpy, tmp_win->hilite_wl);
77
			hil = true;
78
		}
79
		if(tmp_win->hilite_wr) {
80
			XMapWindow(dpy, tmp_win->hilite_wr);
81
			hil = true;
82
		}
83
		if(hil && tmp_win->HiliteImage && tmp_win->HiliteImage->next) {
84
			MaybeAnimate = true;
85
		}
86
		if(tmp_win->iconmanagerlist) {
87
			ActiveIconManager(tmp_win->iconmanagerlist);
88
		}
89
	}
90
	else {
91
		if(tmp_win->hilite_wl) {
92
			XUnmapWindow(dpy, tmp_win->hilite_wl);
93
		}
94
		if(tmp_win->hilite_wr) {
95
			XUnmapWindow(dpy, tmp_win->hilite_wr);
96
		}
97
		if(tmp_win->lolite_wl) {
98
			XMapWindow(dpy, tmp_win->lolite_wl);
99
		}
100
		if(tmp_win->lolite_wr) {
101
			XMapWindow(dpy, tmp_win->lolite_wr);
102
		}
103
		if(tmp_win->iconmanagerlist) {
104
			NotActiveIconManager(tmp_win->iconmanagerlist);
105
		}
106
	}
107
	if(Scr->use3Dtitles && Scr->SunkFocusWindowTitle && tmp_win->title_height) {
108
		ButtonState bs;
109
110
		bs = focus ? on : off;
111
		Draw3DBorder(tmp_win->title_w, Scr->TBInfo.titlex, 0,
112
		             tmp_win->title_width - Scr->TBInfo.titlex -
113
		             Scr->TBInfo.rightoff - Scr->TitlePadding,
114
		             Scr->TitleHeight, Scr->TitleShadowDepth,
115
		             tmp_win->title, bs, false, false);
116
	}
117
	tmp_win->hasfocusvisible = focus;
118
}
119
120
121
/*
523.1.12 by Matthew Fuller
Add header comments and document provenance.
122
 * Shift the focus to a given window, and do whatever subsidiary ops that
123
 * entails.
124
 *
125
 * Formerly in util.c
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
126
 */
127
void
128
SetFocus(TwmWindow *tmp_win, Time tim)
129
{
130
	Window w = (tmp_win ? tmp_win->w : PointerRoot);
131
	bool f_iconmgr = false;
132
133
	if(Scr->Focus && (Scr->Focus->isiconmgr)) {
134
		f_iconmgr = true;
135
	}
136
	if(Scr->SloppyFocus && (w == PointerRoot) && (!f_iconmgr)) {
137
		return;
138
	}
139
140
	XSetInputFocus(dpy, w, RevertToPointerRoot, tim);
141
#ifdef EWMH
142
	EwmhSet_NET_ACTIVE_WINDOW(w);
143
#endif
144
	if(Scr->Focus == tmp_win) {
145
		return;
146
	}
147
148
	if(Scr->Focus) {
149
		if(Scr->Focus->AutoSqueeze && !Scr->Focus->squeezed) {
150
			AutoSqueeze(Scr->Focus);
151
		}
152
		SetFocusVisualAttributes(Scr->Focus, false);
659.2.1 by Matthew Fuller
Commit original run at avoiding crashes with transient windows of
153
#ifdef EWMH
154
		// Priority may change when focus does
155
		if(OtpIsFocusDependent(Scr->Focus)) {
156
			OtpUnfocusWindow(Scr->Focus);
157
			// That Scr->Focus = NULL's internally for us, but we don't
158
			// care, since we're about to reset it if we need to.
159
		}
160
#endif
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
161
	}
659.2.1 by Matthew Fuller
Commit original run at avoiding crashes with transient windows of
162
163
	if(tmp_win) {
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
164
		if(tmp_win->AutoSqueeze && tmp_win->squeezed) {
165
			AutoSqueeze(tmp_win);
166
		}
167
		SetFocusVisualAttributes(tmp_win, true);
659.2.1 by Matthew Fuller
Commit original run at avoiding crashes with transient windows of
168
#ifdef EWMH
169
		// Priority may change when focus does
170
		if(OtpIsFocusDependent(tmp_win)) {
171
			OtpFocusWindow(tmp_win);
172
			// Pre-sets Scr->Focus
173
		}
174
#endif
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
175
	}
659.2.1 by Matthew Fuller
Commit original run at avoiding crashes with transient windows of
176
177
	// in the EWMH cases, this was already done.
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
178
	Scr->Focus = tmp_win;
579.1.3 by Matthew Fuller
Use focus dependency to maybe restack when we SetFocus().
179
659.2.1 by Matthew Fuller
Commit original run at avoiding crashes with transient windows of
180
	return;
523.1.11 by Matthew Fuller
Inagurate win_ops.c by moving the focus functions from util.c into it.
181
}
523.1.15 by Matthew Fuller
Move squeezing bits into win_ops from menus.c. This lets us reap
182
183
184
/*
523.1.22 by Matthew Fuller
FocusOnRoot() is a little off what I'd really consider a "window op",
185
 * Move the focus straight to the root, with associated cleanup.
186
 *
187
 * Formerly in menus.c
188
 */
189
void FocusOnRoot(void)
190
{
191
	SetFocus(NULL, EventTime);
192
	InstallColormaps(0, &Scr->RootColormaps);
193
	if(! Scr->ClickToFocus) {
194
		Scr->FocusRoot = true;
195
	}
196
}
197
198
199
/*
523.1.15 by Matthew Fuller
Move squeezing bits into win_ops from menus.c. This lets us reap
200
 * Handle doing squeezing bits for AutoSqueeze{} windows.
201
 *
202
 * Formerly in menus.c
203
 */
204
void
205
AutoSqueeze(TwmWindow *tmp_win)
206
{
207
	if(tmp_win->isiconmgr) {
208
		return;
209
	}
210
	if(Scr->RaiseWhenAutoUnSqueeze && tmp_win->squeezed) {
211
		OtpRaise(tmp_win, WinWin);
212
	}
213
	Squeeze(tmp_win);
214
}
215
216
217
/*
218
 * Toggle a window's squeezed state.
219
 *
220
 * Formerly in menus.c
221
 */
222
void
223
Squeeze(TwmWindow *tmp_win)
224
{
225
	long fx, fy, savex, savey;
226
	int  neww, newh;
227
	bool south;
228
	int  grav = ((tmp_win->hints.flags & PWinGravity)
229
	             ? tmp_win->hints.win_gravity : NorthWestGravity);
230
	long eventMask;
231
	if(tmp_win->squeezed) {
648.1.14 by Matthew Fuller
Style: use the C99 bool value instead of the Xlib Bool value, since
232
		tmp_win->squeezed = false;
523.1.15 by Matthew Fuller
Move squeezing bits into win_ops from menus.c. This lets us reap
233
#ifdef EWMH
234
		EwmhSet_NET_WM_STATE(tmp_win, EWMH_STATE_SHADED);
235
#endif /* EWMH */
236
		if(!tmp_win->isicon) {
237
			XMapWindow(dpy, tmp_win->w);
238
		}
239
		SetupWindow(tmp_win, tmp_win->actual_frame_x, tmp_win->actual_frame_y,
240
		            tmp_win->actual_frame_width, tmp_win->actual_frame_height, -1);
241
		ReMapTransients(tmp_win);
242
		return;
243
	}
244
245
	newh = tmp_win->title_height + 2 * tmp_win->frame_bw3D;
246
	if(newh < 3) {
247
		XBell(dpy, 0);
248
		return;
249
	}
250
	switch(grav) {
251
		case SouthWestGravity :
252
		case SouthGravity :
253
		case SouthEastGravity :
254
			south = true;
255
			break;
256
		default :
257
			south = false;
258
			break;
259
	}
260
	if(tmp_win->title_height && !tmp_win->AlwaysSqueezeToGravity) {
261
		south = false;
262
	}
263
264
	tmp_win->squeezed = true;
265
	tmp_win->actual_frame_width  = tmp_win->frame_width;
266
	tmp_win->actual_frame_height = tmp_win->frame_height;
267
	savex = fx = tmp_win->frame_x;
268
	savey = fy = tmp_win->frame_y;
269
	neww  = tmp_win->actual_frame_width;
270
	if(south) {
271
		fy += tmp_win->frame_height - newh;
272
	}
273
	if(tmp_win->squeeze_info) {
673 by Maxime Soulé
Adjust the repositioning when squeezeing away a window and the
274
		fx  += tmp_win->title_x + tmp_win->frame_bw - tmp_win->frame_bw3D;
275
		neww = tmp_win->title_width + 2 * tmp_win->frame_bw3D;
523.1.15 by Matthew Fuller
Move squeezing bits into win_ops from menus.c. This lets us reap
276
	}
277
278
	eventMask = mask_out_event(tmp_win->w, StructureNotifyMask);
279
#ifdef EWMH
280
	EwmhSet_NET_WM_STATE(tmp_win, EWMH_STATE_SHADED);
281
#endif /* EWMH */
282
	XUnmapWindow(dpy, tmp_win->w);
283
	restore_mask(tmp_win->w, eventMask);
284
285
	if(fx + neww >= Scr->rootw - Scr->BorderRight) {
286
		fx = Scr->rootw - Scr->BorderRight - neww;
287
	}
288
	if(fy + newh >= Scr->rooth - Scr->BorderBottom) {
289
		fy = Scr->rooth - Scr->BorderBottom - newh;
290
	}
291
	SetupWindow(tmp_win, fx, fy, neww, newh, -1);
292
	tmp_win->actual_frame_x = savex;
293
	tmp_win->actual_frame_y = savey;
294
295
	/* Now make the group members disappear */
296
	UnmapTransients(tmp_win, false, eventMask);
297
}
523.1.25 by Matthew Fuller
Move MoveOutline() over to win_ops.
298
299
300
/***********************************************************************
301
 *
302
 *  Procedure:
303
 *      MoveOutline - move a window outline
304
 *
305
 *  Inputs:
306
 *      root        - the window we are outlining
307
 *      x           - upper left x coordinate
308
 *      y           - upper left y coordinate
309
 *      width       - the width of the rectangle
310
 *      height      - the height of the rectangle
311
 *      bw          - the border width of the frame
312
 *      th          - title height
313
 *
314
 ***********************************************************************
315
 */
316
void
317
MoveOutline(Window root, int x, int y, int width, int height, int bw, int th)
318
{
319
	static int  lastx = 0;
320
	static int  lasty = 0;
321
	static int  lastWidth = 0;
322
	static int  lastHeight = 0;
323
	static int  lastBW = 0;
324
	static int  lastTH = 0;
325
	int         xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb;
326
	int         xthird, ythird;
327
	XSegment    outline[18];
328
	XSegment   *r;
329
330
	if(x == lastx && y == lasty && width == lastWidth && height == lastHeight
331
	                && lastBW == bw && th == lastTH) {
332
		return;
333
	}
334
335
	r = outline;
336
337
#define DRAWIT() \
338
    if (lastWidth || lastHeight)                        \
339
    {                                                   \
340
        xl = lastx;                                     \
341
        xr = lastx + lastWidth - 1;                     \
342
        yt = lasty;                                     \
343
        yb = lasty + lastHeight - 1;                    \
344
        xinnerl = xl + lastBW;                          \
345
        xinnerr = xr - lastBW;                          \
346
        yinnert = yt + lastTH + lastBW;                 \
347
        yinnerb = yb - lastBW;                          \
348
        xthird = (xinnerr - xinnerl) / 3;               \
349
        ythird = (yinnerb - yinnert) / 3;               \
350
                                                        \
351
        r->x1 = xl;                                     \
352
        r->y1 = yt;                                     \
353
        r->x2 = xr;                                     \
354
        r->y2 = yt;                                     \
355
        r++;                                            \
356
                                                        \
357
        r->x1 = xl;                                     \
358
        r->y1 = yb;                                     \
359
        r->x2 = xr;                                     \
360
        r->y2 = yb;                                     \
361
        r++;                                            \
362
                                                        \
363
        r->x1 = xl;                                     \
364
        r->y1 = yt;                                     \
365
        r->x2 = xl;                                     \
366
        r->y2 = yb;                                     \
367
        r++;                                            \
368
                                                        \
369
        r->x1 = xr;                                     \
370
        r->y1 = yt;                                     \
371
        r->x2 = xr;                                     \
372
        r->y2 = yb;                                     \
373
        r++;                                            \
374
                                                        \
375
        r->x1 = xinnerl + xthird;                       \
376
        r->y1 = yinnert;                                \
377
        r->x2 = r->x1;                                  \
378
        r->y2 = yinnerb;                                \
379
        r++;                                            \
380
                                                        \
381
        r->x1 = xinnerl + (2 * xthird);                 \
382
        r->y1 = yinnert;                                \
383
        r->x2 = r->x1;                                  \
384
        r->y2 = yinnerb;                                \
385
        r++;                                            \
386
                                                        \
387
        r->x1 = xinnerl;                                \
388
        r->y1 = yinnert + ythird;                       \
389
        r->x2 = xinnerr;                                \
390
        r->y2 = r->y1;                                  \
391
        r++;                                            \
392
                                                        \
393
        r->x1 = xinnerl;                                \
394
        r->y1 = yinnert + (2 * ythird);                 \
395
        r->x2 = xinnerr;                                \
396
        r->y2 = r->y1;                                  \
397
        r++;                                            \
398
                                                        \
399
        if (lastTH != 0) {                              \
400
            r->x1 = xl;                                 \
401
            r->y1 = yt + lastTH;                        \
402
            r->x2 = xr;                                 \
403
            r->y2 = r->y1;                              \
404
            r++;                                        \
405
        }                                               \
406
    }
407
408
	/* undraw the old one, if any */
409
	DRAWIT();
410
411
	lastx = x;
412
	lasty = y;
413
	lastWidth = width;
414
	lastHeight = height;
415
	lastBW = bw;
416
	lastTH = th;
417
418
	/* draw the new one, if any */
419
	DRAWIT();
420
421
#undef DRAWIT
422
423
424
	if(r != outline) {
425
		XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline);
426
	}
427
}