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 |
}
|