CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/add_window.c
Go to the documentation of this file.
1/*
2 * Copyright 1988 by Evans & Sutherland Computer Corporation,
3 * Salt Lake City, Utah
4 * Portions Copyright 1989 by the Massachusetts Institute of Technology
5 * Cambridge, Massachusetts
6 *
7 * Copyright 1992 Claude Lecommandeur.
8 */
9
10/**********************************************************************
11 *
12 * $XConsortium: add_window.c,v 1.153 91/07/10 13:17:26 dave Exp $
13 *
14 * Add a new window, put the titlbar and other stuff around
15 * the window
16 *
17 * 31-Mar-88 Tom LaStrange Initial Version.
18 *
19 * Do the necessary modification to be integrated in ctwm.
20 * Can no longer be used for the standard twm.
21 *
22 * 22-April-92 Claude Lecommandeur.
23 *
24 **********************************************************************/
25
26#include "ctwm.h"
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <sys/time.h>
32
33#include <X11/Xatom.h>
34#include <X11/extensions/shape.h>
35
36#include "add_window.h"
37#ifdef CAPTIVE
38#include "captive.h"
39#endif
40#include "colormaps.h"
41#include "ctwm_atoms.h"
42#include "functions.h"
43#include "events.h"
44#ifdef EWMH
45# include "ewmh_atoms.h"
46#endif
47#include "gram.tab.h"
48#include "icons.h"
49#include "iconmgr.h"
50#include "image.h"
51#include "list.h"
52#include "mwmhints.h"
53#include "occupation.h"
54#include "otp.h"
55#include "parse.h"
56#include "r_area.h"
57#include "r_layout.h"
58#include "screen.h"
59#ifdef SESSION
60#include "session.h"
61#endif
62#include "util.h"
63#include "vscreen.h"
64#ifdef WINBOX
65#include "windowbox.h"
66#endif
67#include "win_decorations.h"
68#include "win_ops.h"
69#include "win_regions.h"
70#include "win_resize.h"
71#include "win_ring.h"
72#include "win_utils.h"
73#include "workspace_manager.h"
74#include "xparsegeometry.h"
75
76
79unsigned int AddingW;
80unsigned int AddingH;
81
82static int PlaceX = -1;
83static int PlaceY = -1;
84#ifdef VSCREEN
85static void DealWithNonSensicalGeometries(Display *dpy, Window vroot,
86 TwmWindow *tmp_win);
87#endif
88
89char NoName[] = "Untitled"; /* name if no name is specified */
91
92
93
94/***********************************************************************
95 *
96 * Procedure:
97 * AddWindow - add a new window to the twm list
98 *
99 * Returned Value:
100 * (TwmWindow *) - pointer to the TwmWindow structure
101 *
102 * Inputs:
103 * w - the window id of the window to add
104 * wtype - flag to tell if this is a normal window or some ctwm
105 * internal one.
106 *
107 * iconp - pointer to icon manager struct
108 *
109 ***********************************************************************
110 */
111
112TwmWindow *
113AddWindow(Window w, AWType wtype, IconMgr *iconp, VirtualScreen *vs)
114{
115 TwmWindow *tmp_win; /* new twm window structure */
116 bool ask_user; /* don't know where to put the window */
117 int gravx, gravy; /* gravity signs for positioning */
118 int namelen;
119 int bw2;
120#ifdef SESSION
121 short restore_icon_x, restore_icon_y;
122 bool restore_iconified = false;
123 bool restore_icon_info_present = false;
124#endif
125 bool restoredFromPrevSession = false;
126 int saved_occupation = 0; /* <== [ Matthew McNeill Feb 1997 ] == */
127 bool random_placed = false;
128#ifdef WINBOX
129 WindowBox *winbox;
130#endif
131 Window vroot;
132
133#ifdef DEBUG
134 fprintf(stderr, "AddWindow: w = 0x%x\n", w);
135#endif
136
137#ifdef CAPTIVE
138 /*
139 * Possibly this window should be in a captive sub-ctwm? If so, we
140 * shouldn't mess with it at all.
141 */
142 if(!CLarg.is_captive && RedirectToCaptive(w)) {
143 /* XXX x-ref comment by SetNoRedirect() */
144 return (NULL);
145 }
146#endif
147
148
149 /*
150 * Allocate and initialize our tracking struct
151 */
152 tmp_win = calloc(1, sizeof(TwmWindow));
153 if(tmp_win == NULL) {
154 fprintf(stderr, "%s: Unable to allocate memory to manage window ID %lx.\n",
155 ProgramName, w);
156 return NULL;
157 }
158
159 /*
160 * Some of these initializations are strictly unnecessary, since they
161 * evaluate out to 0, and calloc() gives us an already zero'd buffer.
162 * I'm leaving them anyway because a couple unnecessary stores are
163 * near enough to free considering everything we're doing, that the
164 * value as documentation stupendously outweighs the cost.
165 */
166 tmp_win->w = w;
167 tmp_win->zoomed = ZOOM_NONE;
168 tmp_win->isiconmgr = (wtype == AWT_ICON_MANAGER);
169 tmp_win->iconmgrp = iconp;
170 tmp_win->iswspmgr = (wtype == AWT_WORKSPACE_MANAGER);
171 tmp_win->isoccupy = (wtype == AWT_OCCUPY);
172#ifdef WINBOX
173 tmp_win->iswinbox = (wtype == AWT_WINDOWBOX);
174#endif
175 tmp_win->vs = vs;
176 tmp_win->parent_vs = vs;
177 tmp_win->savevs = NULL;
178 tmp_win->cmaps.number_cwins = 0;
179 tmp_win->savegeometry.width = -1;
180 tmp_win->widthEverChangedByUser = false;
181 tmp_win->heightEverChangedByUser = false;
182 tmp_win->nameChanged = false;
183 tmp_win->squeezed = false;
184 tmp_win->iconified = false;
185 tmp_win->isicon = false;
186 tmp_win->icon_on = false;
187 tmp_win->ring.cursor_valid = false;
188 tmp_win->squeeze_info = NULL;
189 tmp_win->squeeze_info_copied = false;
190
191
192
193 /*
194 * Fetch a few bits of info about the window from the server, and
195 * tell the server to tell us about property changes; we'll need to
196 * know what happens.
197 *
198 * It's important that these remain relatively disconnected "early"
199 * bits; generally, they shouldn't rely on anything but the X Window
200 * in tmp_win->w to do their stuff. e.g., anything that relies on
201 * other values in our ctwm TwmWindow tmp_win (window name, various
202 * flags, etc) has to come later.
203 */
204 XSelectInput(dpy, tmp_win->w, PropertyChangeMask);
205 XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr);
206 FetchWmProtocols(tmp_win);
207 FetchWmColormapWindows(tmp_win);
208#ifdef EWMH
209 EwmhGetProperties(tmp_win);
210#endif /* EWMH */
211
212
213 /*
214 * Some other simple early initialization that has to follow those
215 * bits.
216 */
217 tmp_win->old_bw = tmp_win->attr.border_width;
218
219
220 /*
221 * Setup window name and class bits. A lot of following code starts
222 * to care about this; in particular, anything looking in our
223 * name_lists generally goes by the name/class, so we need to get
224 * these set pretty early in the process.
225 */
226 tmp_win->names.ctwm_wm_name = GetWMPropertyString(tmp_win->w,
227 XA_CTWM_WM_NAME);
228#ifdef EWMH
229 tmp_win->names.net_wm_name = GetWMPropertyString(tmp_win->w,
230 XA__NET_WM_NAME);
231#endif
232 tmp_win->names.wm_name = GetWMPropertyString(tmp_win->w, XA_WM_NAME);
233 set_window_name(tmp_win);
234 namelen = strlen(tmp_win->name);
235
236 /* Setup class. x-ref XXX in ctwm_main() about NoClass */
237 tmp_win->class = NoClass;
238 XGetClassHint(dpy, tmp_win->w, &tmp_win->class);
239 if(tmp_win->class.res_name == NULL) {
240 tmp_win->class.res_name = NoName;
241 }
242 if(tmp_win->class.res_class == NULL) {
243 tmp_win->class.res_class = NoName;
244 }
245
246 /* Grab the icon name too */
247 tmp_win->names.ctwm_wm_icon_name = GetWMPropertyString(tmp_win->w,
248 XA_CTWM_WM_ICON_NAME);
249#ifdef EWMH
250 tmp_win->names.net_wm_icon_name = GetWMPropertyString(tmp_win->w,
251 XA__NET_WM_ICON_NAME);
252#endif
253 tmp_win->names.wm_icon_name = GetWMPropertyString(tmp_win->w,
254 XA_WM_ICON_NAME);
255 set_window_icon_name(tmp_win);
256
257
258 /* Convenience macro */
259#define CHKL(lst) IsInList(Scr->lst, tmp_win)
260
261
262 /* Is it a transient? Or should we ignore that it is? */
263 tmp_win->istransient = XGetTransientForHint(dpy, tmp_win->w,
264 &tmp_win->transientfor);
265 if(tmp_win->istransient) {
266 /*
267 * XXX Should this be looking up transientfor instead of tmp_win?
268 * It seems like IgnoreTransient {} would list the windows that
269 * have transients we should ignore, while this condition makes
270 * it list the transient window names we should ignore. Probably
271 * not trivial to fix if that's right, since it might b0rk
272 * existing configs...
273 */
274 if(CHKL(IgnoreTransientL)) {
275 tmp_win->istransient = false;
276 }
277 }
278
279
280#ifdef SESSION
281 /*
282 * Look up saved X Session info for the window if we have it.
283 */
284 {
285 short saved_x, saved_y;
286 unsigned short saved_width, saved_height;
287 bool width_ever_changed_by_user;
288 bool height_ever_changed_by_user;
289
290 if(GetWindowConfig(tmp_win,
291 &saved_x, &saved_y, &saved_width, &saved_height,
292 &restore_iconified, &restore_icon_info_present,
293 &restore_icon_x, &restore_icon_y,
294 &width_ever_changed_by_user,
295 &height_ever_changed_by_user,
296 &saved_occupation)) {
297 /* Got saved info, use it */
298 restoredFromPrevSession = true;
299
300 tmp_win->attr.x = saved_x;
301 tmp_win->attr.y = saved_y;
302
303 tmp_win->widthEverChangedByUser = width_ever_changed_by_user;
304 tmp_win->heightEverChangedByUser = height_ever_changed_by_user;
305
306 if(width_ever_changed_by_user) {
307 tmp_win->attr.width = saved_width;
308 }
309
310 if(height_ever_changed_by_user) {
311 tmp_win->attr.height = saved_height;
312 }
313 }
314 }
315#endif
316
317
318 /*
319 * Clip window to maximum size (either built-in ceiling, or
320 * config MaxWindowSize).
321 *
322 * Should look at window gravity?
323 */
324 if(tmp_win->attr.width > Scr->MaxWindowWidth) {
325 tmp_win->attr.width = Scr->MaxWindowWidth;
326 }
327 if(tmp_win->attr.height > Scr->MaxWindowHeight) {
328 tmp_win->attr.height = Scr->MaxWindowHeight;
329 }
330
331
332 /*
333 * Setup WM_HINTS bits. If we get nothing, we hardcode an
334 * assumption.
335 */
336 tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w);
337 if(!tmp_win->wmhints) {
338 tmp_win->wmhints = gen_synthetic_wmhints(tmp_win);
339 if(!tmp_win->wmhints) {
340 fprintf(stderr, "Failed allocating memory for hints!\n");
341 free(tmp_win); // XXX leaky
342 return NULL;
343 }
344 }
345
346#ifdef SESSION
347 /*
348 * Override a few bits with saved stuff from previous session, if we
349 * have it.
350 */
351 if(restore_iconified) {
352 tmp_win->wmhints->initial_state = IconicState;
353 tmp_win->wmhints->flags |= StateHint;
354 }
355
356 if(restore_icon_info_present) {
357 tmp_win->wmhints->icon_x = restore_icon_x;
358 tmp_win->wmhints->icon_y = restore_icon_y;
359 tmp_win->wmhints->flags |= IconPositionHint;
360 }
361#endif
362
363 /* Munge as necessary for other stuff */
364 munge_wmhints(tmp_win, tmp_win->wmhints);
365
366
367 /*
368 * Various flags that may be screen-wide or window specific.
369 */
370 tmp_win->highlight = Scr->Highlight && !CHKL(NoHighlight);
371 tmp_win->stackmode = Scr->StackMode && !CHKL(NoStackModeL);
372 tmp_win->titlehighlight = Scr->TitleHighlight && !CHKL(NoTitleHighlight);
373 tmp_win->AlwaysSqueezeToGravity = Scr->AlwaysSqueezeToGravity
374 || CHKL(AlwaysSqueezeToGravityL);
375 tmp_win->DontSetInactive = CHKL(DontSetInactive);
376 tmp_win->AutoSqueeze = CHKL(AutoSqueeze);
377 tmp_win->StartSqueezed =
378#ifdef EWMH
379 (tmp_win->ewmhFlags & EWMH_STATE_SHADED) ||
380#endif /* EWMH */
381 CHKL(StartSqueezed);
382
383 tmp_win->auto_raise = Scr->AutoRaiseDefault || CHKL(AutoRaise);
384 if(tmp_win->auto_raise) {
385 Scr->NumAutoRaises++;
386 }
387
388 tmp_win->auto_lower = Scr->AutoLowerDefault || CHKL(AutoLower);
389 if(tmp_win->auto_lower) {
390 Scr->NumAutoLowers++;
391 }
392
393 tmp_win->OpaqueMove = Scr->DoOpaqueMove;
394 if(CHKL(OpaqueMoveList)) {
395 tmp_win->OpaqueMove = true;
396 }
397 else if(CHKL(NoOpaqueMoveList)) {
398 tmp_win->OpaqueMove = false;
399 }
400
401 tmp_win->OpaqueResize = Scr->DoOpaqueResize;
402 if(CHKL(OpaqueResizeList)) {
403 tmp_win->OpaqueResize = true;
404 }
405 else if(CHKL(NoOpaqueResizeList)) {
406 tmp_win->OpaqueResize = false;
407 }
408
409
410 /*
411 * If a window is listed in IconifyByUnmapping {}, we always iconify
412 * by unmapping. Else, if it's DontIconifyByUnmapping {} or is an
413 * icon manager, we don't i_b_u. Else, we go with the Scr-wide
414 * default.
415 */
416 {
417 bool ibum = CHKL(IconifyByUn);
418 if(!ibum) {
419 if(tmp_win->isiconmgr || CHKL(DontIconify)) {
420 ibum = false; // redundant
421 }
422 else {
423 ibum = Scr->IconifyByUnmapping;
424 }
425 }
426 tmp_win->iconify_by_unmapping = ibum;
427 }
428
429
430 /*
431 * For transient windows or group members, we copy in UBMFA from its
432 * parent/leader/etc if we can find it. Otherwise, it's just whether
433 * it's in the config list.
434 */
435 tmp_win->UnmapByMovingFarAway = CHKL(UnmapByMovingFarAway);
436 if(tmp_win->istransient || tmp_win->group) {
437 TwmWindow *t = NULL;
438 if(tmp_win->istransient) {
439 t = GetTwmWindow(tmp_win->transientfor);
440 }
441 if(!t && tmp_win->group) {
442 t = GetTwmWindow(tmp_win->group);
443 }
444 if(t) {
446 }
447 }
448
449
450 /*
451 * Link it up into the window ring if we should. If it's in
452 * WindowRing {}, we should. Otherwise, we shouldn't unless
453 * WindowRingAll is set. If it is, we still exclude several special
454 * ctwm windows, stuff in WindowRingExclude {}, and some special EWMH
455 * settings.
456 */
457 if(CHKL(WindowRingL) ||
458 (Scr->WindowRingAll && !tmp_win->iswspmgr
459 && !tmp_win->isiconmgr
460#ifdef EWMH
461 && EwmhOnWindowRing(tmp_win)
462#endif /* EWMH */
463 && !CHKL(WindowRingExcludeL))) {
464 AddWindowToRing(tmp_win);
465 }
466 else {
467 InitWindowNotOnRing(tmp_win);
468 }
469
470
471 /*
472 * Setup squeezing info. We don't bother unless the server has Shape
473 * available, and the window isn't in our DontSqueezeTitle list.
474 * Else, we do/not based on the SqueezeTitle setting. Note that
475 * "SqueezeTitle" being specified at all squeezes everything; its
476 * argument list lets you set specific squeeze params for specific
477 * windows, but other windows still get the default.
478 *
479 * Note that this does not have to be freed yet since it is coming
480 * from the screen list or from default_squeeze. Places that change
481 * it [re]set squeeze_info_copied, and then the destroy handler looks
482 * at that to determine whether to free squeeze_info.
483 *
484 * XXX Technically, the HasShape test is redundant, since the config
485 * file parsing would never set Scr->SqueezeTitle unless HasShape
486 * were true anyway...
487 */
488 if(HasShape && Scr->SqueezeTitle && !CHKL(DontSqueezeTitleL)) {
489 tmp_win->squeeze_info = LookInListWin(Scr->SqueezeTitleL, tmp_win);
490 if(!tmp_win->squeeze_info) {
491 static SqueezeInfo default_squeeze = { SIJ_LEFT, 0, 0 };
492 tmp_win->squeeze_info = &default_squeeze;
493 }
494 }
495
496
497 /*
498 * Motif WM hints are used in setting up border and titlebar bits, so
499 * put them in a block here to scope the MWM var.
500 */
501 {
502 MotifWmHints mwmHints;
503 bool have_title;
504
505 GetMWMHints(tmp_win->w, &mwmHints);
506
507 /*
508 * Figure border bits. These are all exclusive cases, so it
509 * winds up being first-match.
510 *
511 * - EWMH, MWM hints, and NoBorder{} can tell us to use none.
512 * - ThreeDBorderWidth means use it and no regular 2d frame_bw.
513 * - ClientBorderWidth tells us to use the XWindowAttributes
514 * border size rather than ours.
515 * - Else, our BorderWidth is the [2d] border size.
516 *
517 * X-ref comments in win_decorations.c:SetBorderCursor() about
518 * the somewhat differing treatment of 3d vs non-3d border widths
519 * and their effects on the window coordinates.
520 */
521 tmp_win->frame_bw3D = Scr->ThreeDBorderWidth;
522 if(
523#ifdef EWMH
524 !EwmhHasBorder(tmp_win) ||
525#endif /* EWMH */
526 (mwm_has_border(&mwmHints) == 0) ||
527 CHKL(NoBorder)) {
528 tmp_win->frame_bw = 0;
529 tmp_win->frame_bw3D = 0;
530 }
531 else if(tmp_win->frame_bw3D != 0) {
532 tmp_win->frame_bw = 0;
533 }
534 else if(Scr->ClientBorderWidth) {
535 tmp_win->frame_bw = tmp_win->old_bw;
536 }
537 else {
538 tmp_win->frame_bw = Scr->BorderWidth;
539 }
540 bw2 = tmp_win->frame_bw * 2; // Used repeatedly later
541
542
543 /*
544 * Now, what about the titlebar?
545 *
546 * - Default to showing,
547 * - Then EWMH gets to say no in some special cases,
548 * - Then MWM can say yes/no (or refuse to say anything),
549 * - NoTitle (general setting) gets to override all of that,
550 * - Specific MakeTitle beats general NoTitle,
551 * - And specific NoTitle overrides MakeTitle.
552 */
553 have_title = true;
554 ALLOW_DEAD_STORE(have_title);
555#ifdef EWMH
556 have_title = EwmhHasTitle(tmp_win);
557#endif /* EWMH */
558 if(mwm_sets_title(&mwmHints)) {
559 have_title = mwm_has_title(&mwmHints);
560 }
561 if(Scr->NoTitlebar) {
562 have_title = false;
563 }
564 if(CHKL(MakeTitle)) {
565 have_title = true;
566 }
567 if(CHKL(NoTitle)) {
568 have_title = false;
569 }
570
571 /*
572 * Now mark up how big to make it. title_height sets how tall
573 * the titlebar is, with magic treating 0 as "don't make a
574 * titlebar". We only care about adding frame_bw and never
575 * frame_bw3D, since the 3d case interprets all the inner
576 * coordinates differently (x-ref above x-ref).
577 *
578 * Transients may not be decorated regardless of the above
579 * figuring, so handle that here too.
580 */
581 if(tmp_win->istransient && !Scr->DecorateTransients) {
582 tmp_win->title_height = 0;
583 }
584 else if(have_title) {
585 tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
586 }
587 else {
588 tmp_win->title_height = 0;
589 }
590 }
591
592
593#ifdef EWMH
594 /*
595 * Now that we know the title_height and the frame border width, we
596 * can set an EWMH property to tell the client how much we're adding
597 * around them.
598 */
600#endif
601
602
603 /*
604 * Need the GetWindowAttributes() call and setting ->old_bw and
605 * ->frame_bw3D for some of the math in looking up the
606 * WM_NORMAL_HINTS bits, so now we can do that.
607 */
608 GetWindowSizeHints(tmp_win);
609
610
611 /* Maybe we're ordering it to start off iconified? */
612 if(CHKL(StartIconified)) {
613 tmp_win->wmhints->initial_state = IconicState;
614 tmp_win->wmhints->flags |= StateHint;
615 }
616
617
618 /*
619 * Figure gravity bits. When restoring from a previous session, we
620 * always use NorthWest gravity.
621 */
622 if(restoredFromPrevSession) {
623 gravx = gravy = -1;
624 }
625 else {
626 GetGravityOffsets(tmp_win, &gravx, &gravy);
627 }
628
629
630 /* So far that's the end of where we're using this */
631#undef CHKL
632
633
634 /*
635 * Now we start getting more into the active bits of things. Start
636 * figuring out how we'll decide where to position it. ask_user is
637 * slightly misnamed, as it doesn't actually mean ask the user, but
638 * rather whether the user/WM gets to choose or whether the
639 * application does. That is, we only case about whether or not
640 * RandomPlacement if(ask_user==true) anyway. ask_user=false means
641 * we just go with what's in the window's XWindowAttributes bits.
642 *
643 * We don't even consider overriding the window if:
644 *
645 * - It's a transient, or
646 * - the WM_NORMAL_HINTS property gave us a user-specified position
647 * (USPosition), or
648 * - the hints gave us a a program-specific position (PPosition), and
649 * the UsePPosition config param specifies we should use it.
650 *
651 * x-ref ICCCM discussion of WM_NORMAL_HINTS for some details on the
652 * flags
653 * (https://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html#Client_Properties)
654 */
655 ask_user = true;
656 if(tmp_win->istransient) {
657 ask_user = false;
658 }
659 else if(tmp_win->hints.flags & USPosition) {
660 ask_user = false;
661 }
662 else if(tmp_win->hints.flags & PPosition) {
663 if(Scr->UsePPosition == PPOS_ON) {
664 ask_user = false;
665 }
666 else if(Scr->UsePPosition == PPOS_NON_ZERO
667 && (tmp_win->attr.x != 0 || tmp_win->attr.y != 0)) {
668 ask_user = false;
669 }
670 }
671
672
673 /*
674 * Set the window occupation. If we pulled previous Session info,
675 * saved_occupation may have data from it that will be used;
676 * otherwise it's already zeroed and has no effect. X-ref XXX
677 * comment on SetupOccupation() for notes on order of application of
678 * various sources for occupation.
679 *
680 * Note that SetupOccupation() may update tmp_win->{parent_,}vs if
681 * needed to make the window visible in another vscreen. It may also
682 * set tmp_win->vs to NULL if it has no occupation in the current
683 * workspace.
684 */
685 SetupOccupation(tmp_win, saved_occupation);
686
687
688#ifdef WINBOX
689 /* Does it go in a window box? */
690 winbox = findWindowBox(tmp_win);
691#endif
692
693
694 /*
695 * Set some values for the frame size.
696 *
697 * These get redone down below when we create the frame, when they're
698 * actually useful. So why bother here? There is some code down in
699 * the block where we prompt for a window position that calls some
700 * functions that need plausible values in them. However, those code
701 * blocks calculate and set values themselves, so there shouldn't be
702 * any actual need for them here. Left #if'd out for the present in
703 * case something turns up; this should be GC'd at some point if
704 * nothing does.
705 */
706#if 0
707 tmp_win->frame_width = tmp_win->attr.width + 2 * tmp_win->frame_bw3D;
708 tmp_win->frame_height = tmp_win->attr.height + 2 * tmp_win->frame_bw3D +
709 tmp_win->title_height;
710 ConstrainSize(tmp_win, &tmp_win->frame_width, &tmp_win->frame_height);
711#endif
712
713
714 /*
715 * See if there's a WindowRegion we should honor. If so, it'll set
716 * the X/Y coords, and we'll want to accept them instead of doing our
717 * own (or the user's) positioning.
718 *
719 * This needs the frame_{width,height}.
720 */
721 if(PlaceWindowInRegion(tmp_win, &(tmp_win->attr.x), &(tmp_win->attr.y))) {
722 ask_user = false;
723 }
724
725
726 /*
727 * Maybe we have WindowGeometries {} set for it? If so, we'll take
728 * that as our specifics too.
729 */
730 {
731 char *geom = LookInListWin(Scr->WindowGeometries, tmp_win);
732 if(geom) {
733 int mask = RLayoutXParseGeometry(Scr->Layout, geom,
734 &tmp_win->attr.x, &tmp_win->attr.y,
735 (unsigned int *) &tmp_win->attr.width,
736 (unsigned int *) &tmp_win->attr.height);
737
738 if(mask & XNegative) {
739 tmp_win->attr.x += Scr->rootw - tmp_win->attr.width;
740 }
741 if(mask & YNegative) {
742 tmp_win->attr.y += Scr->rooth - tmp_win->attr.height;
743 }
744 ask_user = false;
745 }
746 }
747
748
749 /* Figure up what root window we should be working in */
750 if(tmp_win->parent_vs) {
751 vroot = tmp_win->parent_vs->window;
752 }
753 else {
754 vroot = Scr->Root; /* never */
755 tmp_win->parent_vs = Scr->currentvs;
756 }
757#ifdef WINBOX
758 if(winbox) {
759 vroot = winbox->window;
760 }
761#endif
762
763
764 /*
765 * Handle positioning of the window. If we're very early in startup
766 * (setting up ctwm's own windows, taking over windows already on the
767 * screen), or restoring defined session stuff, or otherwise
768 * ask_user=false'd above, we just take the already set position
769 * info. Otherwise, we handle it via RandomPlacement or user outline
770 * setting.
771 *
772 * XXX Somebody should go through these blocks in more detail,
773 * they're sure to need further cleaning and commenting. IWBNI they
774 * could be encapsulated well enough to move out into separate
775 * functions, for extra readability...
776 */
777 if(HandlingEvents && ask_user && !restoredFromPrevSession) {
778 if((Scr->RandomPlacement == RP_ALL) ||
779 ((Scr->RandomPlacement == RP_UNMAPPED) &&
780 ((tmp_win->wmhints->initial_state == IconicState) ||
781 (! visible(tmp_win))))) {
782 /* just stick it somewhere */
783
784#ifdef DEBUG
785 fprintf(stderr,
786 "DEBUG[RandomPlacement]: win: %dx%d+%d+%d, screen: %dx%d, title height: %d, random: +%d+%d\n",
787 tmp_win->attr.width, tmp_win->attr.height,
788 tmp_win->attr.x, tmp_win->attr.y,
789 Scr->rootw, Scr->rooth,
790 tmp_win->title_height,
791 PlaceX, PlaceY);
792#endif
793
794 /* Initiallise PlaceX and PlaceY */
795 if(PlaceX < 0 && PlaceY < 0) {
796 if(Scr->RandomDisplacementX >= 0) {
797 PlaceX = Scr->BorderLeft + 5;
798 }
799 else {
800 PlaceX = Scr->rootw - tmp_win->attr.width - Scr->BorderRight - 5;
801 }
802 if(Scr->RandomDisplacementY >= 0) {
803 PlaceY = Scr->BorderTop + 5;
804 }
805 else
806 PlaceY = Scr->rooth - tmp_win->attr.height - tmp_win->title_height
807 - Scr->BorderBottom - 5;
808 }
809
810 /* For a positive horizontal displacement, if the right edge
811 of the window would fall outside of the screen, start over
812 by placing the left edge of the window 5 pixels inside
813 the left edge of the screen.*/
814 if(Scr->RandomDisplacementX >= 0
815 && (PlaceX + tmp_win->attr.width
816 > Scr->rootw - Scr->BorderRight - 5)) {
817 PlaceX = Scr->BorderLeft + 5;
818 }
819
820 /* For a negative horizontal displacement, if the left edge
821 of the window would fall outside of the screen, start over
822 by placing the right edge of the window 5 pixels inside
823 the right edge of the screen.*/
824 if(Scr->RandomDisplacementX < 0 && PlaceX < Scr->BorderLeft + 5) {
825 PlaceX = Scr->rootw - tmp_win->attr.width - Scr->BorderRight - 5;
826 }
827
828 /* For a positive vertical displacement, if the bottom edge
829 of the window would fall outside of the screen, start over
830 by placing the top edge of the window 5 pixels inside the
831 top edge of the screen. Because we add the title height
832 further down, we need to count with it here as well. */
833 if(Scr->RandomDisplacementY >= 0
834 && (PlaceY + tmp_win->attr.height + tmp_win->title_height
835 > Scr->rooth - Scr->BorderBottom - 5)) {
836 PlaceY = Scr->BorderTop + 5;
837 }
838
839 /* For a negative vertical displacement, if the top edge of
840 the window would fall outside of the screen, start over by
841 placing the bottom edge of the window 5 pixels inside the
842 bottom edge of the screen. Because we add the title height
843 further down, we need to count with it here as well. */
844 if(Scr->RandomDisplacementY < 0 && PlaceY < Scr->BorderTop + 5)
845 PlaceY = Scr->rooth - tmp_win->attr.height - tmp_win->title_height
846 - Scr->BorderBottom - 5;
847
848 /* Assign the current random placement to the new window, as
849 a preliminary measure. Add the title height so things will
850 look right. */
851 tmp_win->attr.x = PlaceX;
852 tmp_win->attr.y = PlaceY + tmp_win->title_height;
853
854 /* If the window is not supposed to move off the screen, check
855 that it's still within the screen, and if not, attempt to
856 correct the situation. */
857 if(Scr->DontMoveOff) {
858 int available;
859
860#ifdef DEBUG
862 "DEBUG[DontMoveOff]: win: %dx%d+%d+%d, screen: %dx%d, bw2: %d, bw3D: %d\n",
863 tmp_win->attr.width, tmp_win->attr.height,
864 tmp_win->attr.x, tmp_win->attr.y,
865 Scr->rootw, Scr->rooth,
866 bw2, tmp_win->frame_bw3D);
867#endif
868
869 /* If the right edge of the window is outside the right edge
870 of the screen, we need to move the window left. Note that
871 this can only happen with windows that are less than 50
872 pixels less wide than the screen. */
873 if((tmp_win->attr.x + tmp_win->attr.width) > Scr->rootw) {
874 available = Scr->rootw - tmp_win->attr.width
875 - 2 * tmp_win->frame_bw3D - bw2;
876
877#ifdef DEBUG
878 fprintf(stderr, "DEBUG[DontMoveOff]: availableX: %d\n",
879 available);
880#endif
881
882 /* If the window is wider than the screen or exactly the width
883 of the screen, the availability is exactly 0. The result
884 will be to have the window placed as much to the left as
885 possible. */
886 if(available <= 0) {
887 available = 0;
888 }
889
890 /* Place the window exactly between the left and right edge of
891 the screen when possible. If available was originally less
892 than zero, it means the window's left edge will be against
893 the screen's left edge, and the window's right edge will be
894 outside the screen. */
895 tmp_win->attr.x = available / 2;
896 }
897
898 /* If the bottom edge of the window is outside the bottom edge
899 of the screen, we need to move the window up. Note that
900 this can only happen with windows that are less than 50
901 pixels less tall than the screen. Don't forget to count
902 with the title height and the frame widths. */
903 if((tmp_win->attr.y + tmp_win->attr.height) > Scr->rooth) {
904 available = Scr->rooth - tmp_win->attr.height
905 - tmp_win->title_height
906 - 2 * tmp_win->frame_bw3D - bw2;
907
908#ifdef DEBUG
909 fprintf(stderr, "DEBUG[DontMoveOff]: availableY: %d\n",
910 available);
911#endif
912
913 /* If the window is taller than the screen or exactly the
914 height of the screen, the availability is exactly 0.
915 The result will be to have the window placed as much to
916 the top as possible. */
917 if(available <= 0) {
918 available = 0;
919 }
920
921 /* Place the window exactly between the top and bottom edge of
922 the screen when possible. If available was originally less
923 than zero, it means the window's top edge will be against
924 the screen's top edge, and the window's bottom edge will be
925 outside the screen. Again, don't forget to add the title
926 height. */
927 tmp_win->attr.y = available / 2 + tmp_win->title_height;
928 }
929
930#ifdef DEBUG
932 "DEBUG[DontMoveOff]: win: %dx%d+%d+%d, screen: %dx%d\n",
933 tmp_win->attr.width, tmp_win->attr.height,
934 tmp_win->attr.x, tmp_win->attr.y,
935 Scr->rootw, Scr->rooth);
936#endif
937 }
938
939 /* We know that if the window's left edge has moved compared to
940 PlaceX, it will have moved to the left. If it was moved less
941 than 15 pixel either way, change the next "random position"
942 30 pixels down and right. */
943 if(PlaceX - tmp_win->attr.x < 15
944 || PlaceY - (tmp_win->attr.y - tmp_win->title_height) < 15) {
945 PlaceX += Scr->RandomDisplacementX;
946 PlaceY += Scr->RandomDisplacementY;
947 }
948
949 random_placed = true;
950 }
951 else if(!(tmp_win->wmhints->flags & StateHint &&
952 tmp_win->wmhints->initial_state == IconicState)) {
953 /* else prompt */
954 bool firsttime = true;
955 int found = 0;
956 int width, height;
958
959 /* better wait until all the mouse buttons have been
960 * released.
961 */
962 while(1) {
963 unsigned int qpmask;
965 int stat;
966
968 XSync(dpy, 0);
970
971 qpmask = 0;
972 if(!XQueryPointer(dpy, Scr->Root, &qproot,
973 &JunkChild, &JunkX, &JunkY,
974 &AddingX, &AddingY, &qpmask)) {
975 qpmask = 0;
976 }
977
978 /* Clear out any but the Button bits */
981
982 /*
983 * watch out for changing screens
984 */
985 if(firsttime) {
986 if(qproot != Scr->Root) {
987 int scrnum;
988 for(scrnum = 0; scrnum < NumScreens; scrnum++) {
989 if(qproot == RootWindow(dpy, scrnum)) {
990 break;
991 }
992 }
993 if(scrnum != NumScreens) {
995 }
996 }
997 if(Scr->currentvs) {
998 vroot = Scr->currentvs->window;
999 }
1000 firsttime = false;
1001 }
1002#ifdef WINBOX
1003 if(winbox) {
1004 vroot = winbox->window;
1005 }
1006#endif
1007
1008 /*
1009 * wait for buttons to come up; yuck
1010 */
1011 if(qpmask != 0) {
1012 continue;
1013 }
1014
1015 /*
1016 * this will cause a warp to the indicated root
1017 */
1023 if(stat == GrabSuccess) {
1024 break;
1025 }
1026 }
1027
1028 {
1031
1032 XmbTextExtents(Scr->SizeFont.font_set,
1033 tmp_win->name, namelen,
1035 width = SIZE_HINDENT + ink_rect.width;
1036 height = Scr->SizeFont.height + SIZE_VINDENT * 2;
1037
1038 XmbTextExtents(Scr->SizeFont.font_set,
1039 ": ", 2, NULL, &logical_rect);
1040 Scr->SizeStringOffset = width + logical_rect.width;
1041 }
1042
1044 Scr->SizeStringOffset + Scr->SizeStringWidth + SIZE_HINDENT,
1045 height);
1046 XMapRaised(dpy, Scr->SizeWindow);
1048 FB(Scr->DefaultC.fore, Scr->DefaultC.back);
1049 XmbDrawImageString(dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
1050 Scr->NormalGC, SIZE_HINDENT,
1051 SIZE_VINDENT + Scr->SizeFont.ascent,
1052 tmp_win->name, namelen);
1053
1054#ifdef WINBOX
1055 if(winbox) {
1057 }
1058#endif
1059
1060 AddingW = tmp_win->attr.width + bw2 + 2 * tmp_win->frame_bw3D;
1061 AddingH = tmp_win->attr.height + tmp_win->title_height +
1062 bw2 + 2 * tmp_win->frame_bw3D;
1064 tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
1065
1066 XmbDrawImageString(dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
1067 Scr->NormalGC, width,
1068 SIZE_VINDENT + Scr->SizeFont.ascent, ": ", 2);
1070
1071 /*
1072 * The TryTo*() and DoResize() calls below rely on having
1073 * frame_{width,height} set, so set them.
1074 */
1075 tmp_win->frame_width = AddingW - bw2;
1076 tmp_win->frame_height = AddingH - bw2;
1077 /*SetFocus (NULL, CurrentTime);*/
1078 while(1) {
1079 if(Scr->OpenWindowTimeout) {
1080 const int fd = ConnectionNumber(dpy);
1082 fd_set mask;
1083 struct timeval timeout = {
1084 .tv_sec = Scr->OpenWindowTimeout,
1085 .tv_usec = 0,
1086 };
1087
1088 FD_ZERO(&mask);
1089 FD_SET(fd, &mask);
1090 found = select(fd + 1, &mask, NULL, NULL, &timeout);
1091 if(found == 0) {
1092 break;
1093 }
1094 }
1095 if(found == 0) {
1096 break;
1097 }
1098 }
1099 else {
1100 found = 1;
1102 }
1103 if(event.type == MotionNotify) {
1104 /* discard any extra motion events before a release */
1105 while(XCheckMaskEvent(dpy,
1107 if(event.type == ButtonPress) {
1108 break;
1109 }
1110 }
1112 if(event.type == ButtonPress) {
1113 AddingX = event.xbutton.x_root;
1114 AddingY = event.xbutton.y_root;
1115
1116 /* TryTo*() need tmp_win->frame_{width,height} */
1118 if(Scr->PackNewWindows) {
1120 }
1121
1122 /* DontMoveOff prohibits user from off-screen placement */
1123 if(Scr->DontMoveOff) {
1125 }
1126 break;
1127 }
1128
1129 if(event.type != MotionNotify) {
1130 continue;
1131 }
1132
1135
1137 if(Scr->PackNewWindows) {
1139 }
1140 if(Scr->DontMoveOff) {
1142 }
1144 tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
1145
1147 }
1148
1149 if(found) {
1150 if(event.xbutton.button == Button2) {
1151 int lastx, lasty;
1153
1154 XmbTextExtents(Scr->SizeFont.font_set,
1155 ": ", 2, NULL, &logical_rect);
1156 Scr->SizeStringOffset = width + logical_rect.width;
1157
1158 MoveResizeSizeWindow(event.xbutton.x_root, event.xbutton.y_root,
1159 Scr->SizeStringOffset + Scr->SizeStringWidth + SIZE_HINDENT,
1160 height);
1161
1162 XmbDrawImageString(dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
1163 Scr->NormalGC, width,
1164 SIZE_VINDENT + Scr->SizeFont.ascent, ": ", 2);
1165
1166 if(0/*Scr->AutoRelativeResize*/) {
1167 int dx = (tmp_win->attr.width / 4);
1168 int dy = (tmp_win->attr.height / 4);
1169
1170#define HALF_AVE_CURSOR_SIZE 8 /* so that it is visible */
1171 if(dx < HALF_AVE_CURSOR_SIZE + Scr->BorderLeft) {
1172 dx = HALF_AVE_CURSOR_SIZE + Scr->BorderLeft;
1173 }
1175 dy = HALF_AVE_CURSOR_SIZE + Scr->BorderTop;
1176 }
1177#undef HALF_AVE_CURSOR_SIZE
1178 dx += (tmp_win->frame_bw + 1);
1179 dy += (bw2 + tmp_win->title_height + 1);
1180 if(AddingX + dx >= Scr->rootw - Scr->BorderRight) {
1181 dx = Scr->rootw - Scr->BorderRight - AddingX - 1;
1182 }
1183 if(AddingY + dy >= Scr->rooth - Scr->BorderBottom) {
1184 dy = Scr->rooth - Scr->BorderBottom - AddingY - 1;
1185 }
1186 if(dx > 0 && dy > 0) {
1187 XWarpPointer(dpy, None, None, 0, 0, 0, 0, dx, dy);
1188 }
1189 }
1190 else {
1191 XWarpPointer(dpy, None, vroot, 0, 0, 0, 0,
1192 AddingX + AddingW / 2, AddingY + AddingH / 2);
1193 }
1195
1196 lastx = -10000;
1197 lasty = -10000;
1198 while(1) {
1201
1202 if(event.type == MotionNotify) {
1203 /* discard any extra motion events before a release */
1204 while(XCheckMaskEvent(dpy,
1206 if(event.type == ButtonRelease) {
1207 break;
1208 }
1209 }
1211
1212 if(event.type == ButtonRelease) {
1214 break;
1215 }
1216
1217 if(event.type != MotionNotify) {
1218 continue;
1219 }
1220
1221 /*
1222 * XXX - if we are going to do a loop, we ought to consider
1223 * using multiple GXxor lines so that we don't need to
1224 * grab the server.
1225 */
1227 &JunkX, &JunkY, &AddingX, &AddingY,
1228 &JunkMask);
1229
1230 if(lastx != AddingX || lasty != AddingY) {
1231 resizeWhenAdd = true;
1232 /*
1233 * DR() calls SetupWindow(), which uses
1234 * frame_{width,height}.
1235 */
1237 resizeWhenAdd = false;
1238
1239 lastx = AddingX;
1240 lasty = AddingY;
1241 }
1242
1243 }
1244 }
1245 else if(event.xbutton.button == Button3) {
1246 RArea area;
1247 int max_bottom, max_right;
1248
1250
1251 max_bottom = RLayoutFindMonitorBottomEdge(Scr->BorderedLayout, &area) - bw2;
1252 max_right = RLayoutFindMonitorRightEdge(Scr->BorderedLayout, &area) - bw2;
1253
1254 /*
1255 * Make window go to bottom of screen, and clip to right edge.
1256 * This is useful when popping up large windows and fixed
1257 * column text windows.
1258 */
1259 if(AddingX + AddingW - 1 > max_right) {
1260 AddingW = max_right - AddingX + 1;
1261 }
1262 AddingH = max_bottom - AddingY + 1;
1263
1264 ConstrainSize(tmp_win, &AddingW, &AddingH); /* w/o borders */
1265 AddingW += bw2;
1266 AddingH += bw2;
1268 }
1269 else {
1271 }
1272 }
1273 MoveOutline(vroot, 0, 0, 0, 0, 0, 0);
1274 XUnmapWindow(dpy, Scr->SizeWindow);
1277
1278 tmp_win->attr.x = AddingX;
1279 tmp_win->attr.y = AddingY + tmp_win->title_height;
1280 tmp_win->attr.width = AddingW - bw2 - 2 * tmp_win->frame_bw3D;
1281 tmp_win->attr.height = AddingH - tmp_win->title_height -
1282 bw2 - 2 * tmp_win->frame_bw3D;
1283
1285 }
1286 }
1287 else {
1288 /*
1289 * Put it where asked, mod title bar. If the gravity is towards
1290 * the top, move it by the title height.
1291 */
1292 if(gravy < 0) {
1293 tmp_win->attr.y -= gravy * tmp_win->title_height;
1294 }
1295 }
1296
1297
1298#ifdef DEBUG
1299 fprintf(stderr, " position window %d, %d %dx%d\n",
1300 tmp_win->attr.x,
1301 tmp_win->attr.y,
1302 tmp_win->attr.width,
1303 tmp_win->attr.height);
1304#endif
1305
1306
1307 /*
1308 * Possibly need to tweak what it thinks of as its position to
1309 * account for borders. XXX Verify conditionalization and math.
1310 */
1311 if(!Scr->ClientBorderWidth) {
1312 int delta = tmp_win->attr.border_width - tmp_win->frame_bw -
1313 tmp_win->frame_bw3D;
1314 tmp_win->attr.x += gravx * delta;
1315 tmp_win->attr.y += gravy * delta;
1316 }
1317
1318
1319 /*
1320 * Init the title width to the window's width. This will be right as
1321 * long as you're not SqueezeTitle'ing; if you are, we rejigger it in
1322 * SetupFrame().
1323 */
1324 tmp_win->title_width = tmp_win->attr.width;
1325
1326
1327 /*
1328 * Figure initial screen size of writing out the window name. This
1329 * is needed when laying out titlebar bits (down in the call chain
1330 * inside SetupFrame()). The event handler updates this when it
1331 * changes.
1332 */
1333 {
1335 XmbTextExtents(Scr->TitleBarFont.font_set, tmp_win->name, namelen,
1336 NULL, &logical_rect);
1337 tmp_win->name_width = logical_rect.width;
1338 }
1339
1340
1341 /* Remove original border if there is one; we make our own now */
1342 if(tmp_win->old_bw) {
1344 }
1345
1346
1347 /*
1348 * Setup various color bits
1349 */
1350#define SETC(lst, save) GetColorFromList(Scr->lst, tmp_win->name, \
1351 &tmp_win->class, &tmp_win->save)
1352
1353 /* No distinction fore/back for borders in the lists */
1354 tmp_win->borderC.fore = Scr->BorderColorC.fore;
1355 tmp_win->borderC.back = Scr->BorderColorC.back;
1356 SETC(BorderColorL, borderC.fore);
1357 SETC(BorderColorL, borderC.back);
1358
1359 tmp_win->border_tile.fore = Scr->BorderTileC.fore;
1360 tmp_win->border_tile.back = Scr->BorderTileC.back;
1361 SETC(BorderTileForegroundL, border_tile.fore);
1362 SETC(BorderTileBackgroundL, border_tile.back);
1363
1364 tmp_win->title.fore = Scr->TitleC.fore;
1365 tmp_win->title.back = Scr->TitleC.back;
1366 SETC(TitleForegroundL, title.fore);
1367 SETC(TitleBackgroundL, title.back);
1368
1369#undef SETC
1370
1371 /* Shading on 3d bits */
1372 if(Scr->use3Dtitles && !Scr->BeNiceToColormap) {
1373 GetShadeColors(&tmp_win->title);
1374 }
1375 if(Scr->use3Dborders && !Scr->BeNiceToColormap) {
1376 GetShadeColors(&tmp_win->borderC);
1377 GetShadeColors(&tmp_win->border_tile);
1378 }
1379
1380
1381 /*
1382 * Following bits are more active, and we want to make sure nothing
1383 * else gets to do anything with the server while we're doing it.
1384 *
1385 * Minor investigations seems to suggest we could pull a number of
1386 * these things out (mostly to later, but probably some to earlier)
1387 * so we keep the server grabbed for a shorter period of time. I'm
1388 * not putting significant effort into finding out what we could pull
1389 * out because it's already plenty fast, but there is probably fruit
1390 * that could be plucked if somebody finds it not so.
1391 */
1393
1394
1395 /*
1396 * Make sure the client window still exists. We don't want to leave an
1397 * orphan frame window if it doesn't. Since we now have the server
1398 * grabbed, the window can't disappear later without having been
1399 * reparented, so we'll get a DestroyNotify for it. We won't have
1400 * gotten one for anything up to here, however.
1401 */
1403 &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0) {
1405
1406 /* XXX Leaky as all hell */
1407 free(tmp_win);
1409 return(NULL);
1410 }
1411
1412
1413 /* Link the window into our list of all the TwmWindow's */
1414 tmp_win->next = Scr->FirstWindow;
1415 if(Scr->FirstWindow != NULL) {
1416 Scr->FirstWindow->prev = tmp_win;
1417 }
1418 tmp_win->prev = NULL;
1419 Scr->FirstWindow = tmp_win;
1420
1421
1422
1423 /*
1424 * Start creating the other X windows we wrap around it for
1425 * decorations. X-ref discussion in win_decorations.c for the
1426 * details of what they all are and why they're there.
1427 *
1428 * XXX Good candidate for moving out into a helper function...
1429 */
1430
1431
1432 /*
1433 * First, the frame
1434 */
1435 {
1436 unsigned long valuemask;
1438
1439 /*
1440 * Figure size/position.
1441 */
1442 tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw
1443 - tmp_win->frame_bw - tmp_win->frame_bw3D;
1444 tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height
1445 + tmp_win->old_bw
1446 - tmp_win->frame_bw - tmp_win->frame_bw3D;
1447 tmp_win->frame_width = tmp_win->attr.width + 2 * tmp_win->frame_bw3D;
1448 tmp_win->frame_height = tmp_win->attr.height + 2 * tmp_win->frame_bw3D
1449 + tmp_win->title_height;
1450
1451 /* Adjust based on hints */
1452 ConstrainSize(tmp_win, &tmp_win->frame_width, &tmp_win->frame_height);
1453
1454 /*
1455 * Adjust as necessary to keep things on-screen. If we [ctwm]
1456 * chose the position, CBB() involves checking things like
1457 * MoveOffResistance etc to keep it on.
1458 */
1459 if(random_placed) {
1460 ConstrainByBorders(tmp_win, &tmp_win->frame_x, tmp_win->frame_width,
1461 &tmp_win->frame_y, tmp_win->frame_height);
1462 }
1463
1464 /* No matter what, make sure SOME part of the window is on-screen */
1465 {
1466 RArea area;
1468 const RLayout *layout = Scr->BorderedLayout;
1469
1470 area = RAreaNew(tmp_win->frame_x, tmp_win->frame_y,
1471 (int)tmp_win->frame_width,
1472 (int)tmp_win->frame_height);
1473
1474#ifdef EWMH
1475 // Hack: windows with EWMH struts defined are trying to
1476 // reserve a bit of the screen for themselves. We currently
1477 // do that by hacking strut'ed space into the BorderedLayout,
1478 // which is a bogus way of doing things. But it also means
1479 // that here we're forcing the windows to be outside their
1480 // own struts, which is nonsensical.
1481 //
1482 // Hack around that by making strut'd windows just use
1483 // Layout, rather than BorderedLayout. This is Wrong(tm)
1484 // because the whole point of BorderedLayout is space
1485 // reservation by the user, which we'd now be ignoring. Also
1486 // just because a window has its own struts doesn't mean it
1487 // should get to ignore everyone else's struts too. However,
1488 // this is at least consistent with pre-4.1.0 behavior, so
1489 // it's not a _new_ bug. And forcing windows outside their
1490 // own reservation is way stupider...
1491 if(tmp_win->ewmhFlags & EWMH_HAS_STRUT) {
1492 layout = Scr->Layout;
1493 }
1494#endif
1495
1497 &min_y, &max_bottom);
1499 &min_x, &max_right);
1500
1501 // These conditions would only be true if the window was
1502 // completely off-screen; in that case, the RLayout* calls
1503 // above would have found the closest edges to move it to.
1504 // We wind up sticking it in the top-left of the
1505 // bottom-right-most monitor it would touch.
1506 if(area.x > max_right || area.y > max_bottom ||
1507 area.x + area.width <= min_x ||
1508 area.y + area.height <= min_y) {
1509 tmp_win->frame_x = min_x;
1510 tmp_win->frame_y = min_y;
1511 }
1512 }
1513
1514#ifdef VSCREEN
1515 /* May need adjusting for vscreens too */
1517#endif
1518
1519
1520 /*
1521 * Setup the X attributes for the frame.
1522 */
1525 attributes.background_pixmap = None;
1526 attributes.border_pixel = tmp_win->border_tile.back;
1527 attributes.background_pixel = tmp_win->border_tile.back;
1528 attributes.cursor = Scr->FrameCursor;
1532 | ExposureMask);
1533
1534 /*
1535 * If we have BorderResizeCursors, we need to know about motions
1536 * in the window to know when to change (e.g., for corners).
1537 */
1538 if(Scr->BorderCursors) {
1539 attributes.event_mask |= PointerMotionMask;
1540 }
1541
1542 /*
1543 * If the real window specified save_under or a specific gravity,
1544 * set them on the frame too.
1545 */
1546 if(tmp_win->attr.save_under) {
1547 attributes.save_under = True;
1549 }
1550 if(tmp_win->hints.flags & PWinGravity) {
1551 attributes.win_gravity = tmp_win->hints.win_gravity;
1553 }
1554
1555
1556 /* And create */
1557 tmp_win->frame = XCreateWindow(dpy, vroot,
1558 tmp_win->frame_x, tmp_win->frame_y,
1559 tmp_win->frame_width,
1560 tmp_win->frame_height,
1561 tmp_win->frame_bw,
1562 Scr->d_depth, CopyFromParent,
1563 Scr->d_visual, valuemask, &attributes);
1564 if(Scr->NameDecorations) {
1565 XStoreName(dpy, tmp_win->frame, "CTWM frame");
1566 }
1567 }
1568
1569
1570 /*
1571 * Next, the titlebar, if we have one
1572 */
1573 if(tmp_win->title_height) {
1574 unsigned long valuemask;
1576 int x, y;
1577
1578 /*
1579 * We need to know about keys/buttons and exposure of the
1580 * titlebar, for bindings and repaining. And leave to X server
1581 * bits about border/background.
1582 */
1587 attributes.do_not_propagate_mask = PointerMotionMask;
1588 attributes.border_pixel = tmp_win->borderC.back;
1589 attributes.background_pixel = tmp_win->title.back;
1590
1591
1592 /* Create */
1593 x = y = tmp_win->frame_bw3D - tmp_win->frame_bw;
1594 tmp_win->title_w = XCreateWindow(dpy, tmp_win->frame, x, y,
1595 tmp_win->attr.width,
1596 Scr->TitleHeight, tmp_win->frame_bw,
1597 Scr->d_depth, CopyFromParent,
1598 Scr->d_visual, valuemask, &attributes);
1599 if(Scr->NameDecorations) {
1600 XStoreName(dpy, tmp_win->title_w, "CTWM titlebar");
1601 }
1602 }
1603 else {
1604 tmp_win->title_w = None;
1605 tmp_win->squeeze_info = NULL;
1606 }
1607
1608
1609 /*
1610 * If we're highlighting borders on focus, we need the pixmap to do
1611 * it.
1612 *
1613 * XXX I'm not at all sure this can't just be global and shared, so
1614 * we don't have to create one per window...
1615 */
1616 if(tmp_win->highlight) {
1617 char *which;
1618
1619 if(Scr->use3Dtitles && (Scr->Monochrome != COLOR)) {
1620 which = "black";
1621 }
1622 else {
1623 which = "gray";
1624 }
1626 tmp_win->border_tile.fore,
1627 tmp_win->border_tile.back);
1628
1629 tmp_win->hasfocusvisible = true;
1631 }
1632 else {
1633 tmp_win->gray = None;
1634 }
1635
1636
1637 /*
1638 * Setup OTP bits for stacking
1639 */
1641
1642
1643 /*
1644 * Setup the stuff inside the titlebar window, if we have it. If we
1645 * don't, fake up the coordinates where the titlebar would be for
1646 * <reasons>.
1647 */
1648 if(tmp_win->title_w) {
1651 XMoveWindow(dpy, tmp_win->title_w,
1652 tmp_win->title_x, tmp_win->title_y);
1653 XDefineCursor(dpy, tmp_win->title_w, Scr->TitleCursor);
1654 }
1655 else {
1656 tmp_win->title_x = tmp_win->frame_bw3D - tmp_win->frame_bw;
1657 tmp_win->title_y = tmp_win->frame_bw3D - tmp_win->frame_bw;
1658 }
1659
1660
1661 /*
1662 * Setup various events we want to hear about related to this window.
1663 */
1664 {
1665 unsigned long valuemask;
1667
1673 attributes.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask
1676 }
1677
1678
1679 /*
1680 * Map up the title window if we have one. As a sub-window of the
1681 * frame, it'll only actually show up in the screen if the frame
1682 * does, of course.
1683 */
1684 if(tmp_win->title_w) {
1685 XMapWindow(dpy, tmp_win->title_w);
1686 }
1687
1688
1689 /*
1690 * If the server's got Shape, look up info about the window's
1691 * Shape'ing, and subscribe to notifications about changes in it.
1692 * Actually, it's only the bounding we care about; the rest is
1693 * thrown away.
1694 */
1695 if(HasShape) {
1696 int xws, yws, xbs, ybs;
1697 unsigned wws, hws, wbs, hbs;
1699
1702 &boundingShaped, &xws, &yws, &wws, &hws,
1703 &clipShaped, &xbs, &ybs, &wbs, &hbs);
1704 tmp_win->wShaped = boundingShaped;
1705 }
1706
1707
1708 /*
1709 * If it's a normal window (i.e., not one of ctwm's internal ones),
1710 * add it to the "save set", which means that even if ctwm disappears
1711 * without doing any cleanup, it'll still show back up on the screen
1712 * like normal. Otherwise, if you kill or segfault ctwm, all the
1713 * other things you're running get their windows lost.
1714 *
1715 * XXX Conditional may be a little on the short side; I'm not sure it
1716 * catches all of our internals...
1717 */
1718 if(!(tmp_win->isiconmgr || tmp_win->iswspmgr || tmp_win->isoccupy)) {
1720 }
1721
1722
1723 /*
1724 * Now reparent the real window into our frame.
1725 */
1726 XReparentWindow(dpy, tmp_win->w, tmp_win->frame, tmp_win->frame_bw3D,
1727 tmp_win->title_height + tmp_win->frame_bw3D);
1728
1729 /*
1730 * Reparenting generates an UnmapNotify event, followed by a
1731 * MapNotify. Set the map state to false to prevent a transition
1732 * back to WithdrawnState in HandleUnmapNotify. ->mapped gets set
1733 * correctly again in HandleMapNotify.
1734 */
1735 tmp_win->mapped = false;
1736
1737
1738 /*
1739 * Call SetupFrame() which does all sorta of magic figuring to set
1740 * the various coordinates and offsets and whatnot for all the pieces
1741 * inside our frame.
1742 */
1743 SetupFrame(tmp_win, tmp_win->frame_x, tmp_win->frame_y,
1744 tmp_win->frame_width, tmp_win->frame_height, -1, true);
1745
1746
1747 /*
1748 * Don't setup the icon window and its bits; when the window is
1749 * iconified the first time, that handler will do what needs to be
1750 * done for it, so we don't have to.
1751 */
1752
1753
1754 /*
1755 * If it's anything other than our own icon manager, setup button/key
1756 * bindings for it. For icon managers, this is done for them at the
1757 * end of CreateIconManagers(), not here. X-ref comments there and
1758 * on the function defs below for some discussion about whether it
1759 * _should_ work this way.
1760 */
1761 if(!tmp_win->isiconmgr) {
1764 }
1765
1766
1767 /* Add this window to the appropriate icon manager[s] */
1769
1770
1771 /*
1772 * Stash up info about this TwmWindow and its screen in contexts on
1773 * the real window and our various decorations around it. This is
1774 * how we find out what TwmWindow things like events are happening
1775 * in.
1776 */
1777#define SETCTXS(win) do { \
1778 XSaveContext(dpy, win, TwmContext, (XPointer) tmp_win); \
1779 XSaveContext(dpy, win, ScreenContext, (XPointer) Scr); \
1780 } while(0)
1781
1782 /* The real window and our frame */
1783 SETCTXS(tmp_win->w);
1784 SETCTXS(tmp_win->frame);
1785
1786 /* Cram that all into any titlebar [sub]windows too */
1787 if(tmp_win->title_height) {
1788 int i;
1789 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
1790
1791 SETCTXS(tmp_win->title_w);
1792
1793 for(i = 0; i < nb; i++) {
1794 SETCTXS(tmp_win->titlebuttons[i].window);
1795 }
1796 if(tmp_win->hilite_wl) {
1797 SETCTXS(tmp_win->hilite_wl);
1798 }
1799 if(tmp_win->hilite_wr) {
1800 SETCTXS(tmp_win->hilite_wr);
1801 }
1802 if(tmp_win->lolite_wl) {
1803 SETCTXS(tmp_win->lolite_wl);
1804 }
1805 if(tmp_win->lolite_wr) {
1806 SETCTXS(tmp_win->lolite_wr);
1807 }
1808 }
1809
1810#undef SETCTXS
1811
1812 /*
1813 * OK, that's all we need to do while the server's grabbed. After
1814 * this point, other clients might sneak in stuff between our
1815 * actions, so they can't be considered atomic anymore.
1816 */
1818
1819
1820 /*
1821 * If we were in the middle of a menu activated function that was
1822 * deferred (x-ref comments on DeferExecution()), re-grab to re-set
1823 * the special cursor, since we may have reset it above.
1824 *
1825 * Why could that possibly happen? It would require a window coming
1826 * up and needing to be Add'd in the middle of selecting a window to
1827 * apply a function to, which is a pretty rare case, but I s'pose not
1828 * impossible...
1829 */
1830 if(RootFunction) {
1831 ReGrab();
1832 }
1833
1834
1835 /*
1836 * Add to the workspace manager. Unless this IS the workspace
1837 * manager, in which case that would just be silly.
1838 */
1839 if(!tmp_win->iswspmgr) {
1841 }
1842
1843
1844#ifdef CAPTIVE
1845 /*
1846 * If ths window being created is a new captive [sub-]ctwm, we setup
1847 * a property on it for unclear reasons. x-ref comments on the
1848 * function.
1849 */
1851#endif
1852
1853
1854 /*
1855 * Init saved geometry with the current, as if f.savegeometry was
1856 * called on the window right away. That way f.restoregeometry can't
1857 * get confuzzled.
1858 */
1860
1861
1862 /*
1863 * And that's it; we created all the bits!
1864 */
1865 return tmp_win;
1866}
1867
1868
1869
1870
1871/*
1872 * XXX GrabButtons() and GrabKeys() are in a slightly odd state. They're
1873 * almost strictly a piece of the window-adding process, which is why
1874 * they're here. They're not static because the icon manager setup in
1875 * CreateIconManagers() calls them explicitly, because they're also
1876 * explicitly skipped in AddWindow() for icon manager windows. I'm not
1877 * sure that's necessary; x-ref comment in CIM() about some ideas on the
1878 * matter.
1879 *
1880 * This should be resolved. Until it is, they're left exported so the
1881 * iconmgr code can all them, and they're left here (rather than moved to
1882 * win_utils) on the guess that it may well be resolvable and so they'd
1883 * stay here and be staticized in the end.
1884 */
1885
1886/***********************************************************************
1887 *
1888 * Procedure:
1889 * GrabButtons - grab needed buttons for the window
1890 *
1891 * Inputs:
1892 * tmp_win - the twm window structure to use
1893 *
1894 ***********************************************************************
1895 */
1896
1897#define grabbutton(button, modifier, window, pointer_mode) \
1898 XGrabButton (dpy, button, modifier, window, \
1899 True, ButtonPressMask | ButtonReleaseMask, \
1900 pointer_mode, GrabModeAsync, None, \
1901 Scr->FrameCursor);
1902
1904{
1905 FuncButton *tmp;
1906 int i;
1907 unsigned int ModifierMask[8] = { ShiftMask, ControlMask, LockMask,
1909 Mod5Mask
1910 };
1911
1912 for(tmp = Scr->FuncButtonRoot.next; tmp != NULL; tmp = tmp->next) {
1913 if((tmp->cont != C_WINDOW) || (tmp->func == 0)) {
1914 continue;
1915 }
1916 grabbutton(tmp->num, tmp->mods, tmp_win->frame, GrabModeAsync);
1917
1918 for(i = 0 ; i < 8 ; i++) {
1919 if((Scr->IgnoreModifier & ModifierMask [i]) && !(tmp->mods & ModifierMask [i]))
1920 grabbutton(tmp->num, tmp->mods | ModifierMask [i],
1921 tmp_win->frame, GrabModeAsync);
1922 }
1923 }
1924 if(Scr->ClickToFocus) {
1926 for(i = 0 ; i < 8 ; i++) {
1928 }
1929 }
1930 else if(Scr->RaiseOnClick) {
1931 grabbutton(Scr->RaiseOnClickButton, None, tmp_win->w, GrabModeSync);
1932 for(i = 0 ; i < 8 ; i++) {
1933 grabbutton(Scr->RaiseOnClickButton,
1935 }
1936 }
1937}
1938#undef grabbutton
1939
1940/***********************************************************************
1941 *
1942 * Procedure:
1943 * GrabKeys - grab needed keys for the window
1944 *
1945 * Inputs:
1946 * tmp_win - the twm window structure to use
1947 *
1948 ***********************************************************************
1949 */
1950
1951#define grabkey(funckey, modifier, window) \
1952 XGrabKey(dpy, funckey->keycode, funckey->mods | modifier, window, True, \
1953 GrabModeAsync, GrabModeAsync);
1954#define ungrabkey(funckey, modifier, window) \
1955 XUngrabKey (dpy, funckey->keycode, funckey->mods | modifier, window);
1956
1958{
1959 FuncKey *tmp;
1960 IconMgr *p;
1961 int i;
1962 unsigned int ModifierMask[8] = { ShiftMask, ControlMask, LockMask,
1964 Mod5Mask
1965 };
1966
1967 for(tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) {
1968 switch(tmp->cont) {
1969 case C_WINDOW:
1970 /* case C_WORKSPACE: */
1971#define AltMask (Alt1Mask | Alt2Mask | Alt3Mask | Alt4Mask | Alt5Mask)
1972 if(tmp->mods & AltMask) {
1973 break;
1974 }
1975#undef AltMask
1976
1977 grabkey(tmp, 0, tmp_win->w);
1978
1979 for(i = 0 ; i < 8 ; i++) {
1980 if((Scr->IgnoreModifier & ModifierMask [i]) &&
1981 !(tmp->mods & ModifierMask [i])) {
1982 grabkey(tmp, ModifierMask [i], tmp_win->w);
1983 }
1984 }
1985 break;
1986
1987 case C_ICON:
1988 if(!tmp_win->icon || tmp_win->icon->w) {
1989 break;
1990 }
1991
1992 grabkey(tmp, 0, tmp_win->icon->w);
1993
1994 for(i = 0 ; i < 8 ; i++) {
1995 if((Scr->IgnoreModifier & ModifierMask [i]) &&
1996 !(tmp->mods & ModifierMask [i])) {
1997 grabkey(tmp, ModifierMask [i], tmp_win->icon->w);
1998 }
1999 }
2000 break;
2001
2002 case C_TITLE:
2003 if(!tmp_win->title_w) {
2004 break;
2005 }
2006
2007 grabkey(tmp, 0, tmp_win->title_w);
2008
2009 for(i = 0 ; i < 8 ; i++) {
2010 if((Scr->IgnoreModifier & ModifierMask [i]) &&
2011 !(tmp->mods & ModifierMask [i])) {
2012 grabkey(tmp, ModifierMask [i], tmp_win->title_w);
2013 }
2014 }
2015 break;
2016
2017 case C_NAME:
2018 grabkey(tmp, 0, tmp_win->w);
2019 for(i = 0 ; i < 8 ; i++) {
2020 if((Scr->IgnoreModifier & ModifierMask [i]) &&
2021 !(tmp->mods & ModifierMask [i])) {
2022 grabkey(tmp, ModifierMask [i], tmp_win->w);
2023 }
2024 }
2025 if(tmp_win->icon && tmp_win->icon->w) {
2026 grabkey(tmp, 0, tmp_win->icon->w);
2027
2028 for(i = 0 ; i < 8 ; i++) {
2029 if((Scr->IgnoreModifier & ModifierMask [i]) &&
2030 !(tmp->mods & ModifierMask [i])) {
2031 grabkey(tmp, ModifierMask [i], tmp_win->icon->w);
2032 }
2033 }
2034 }
2035 if(tmp_win->title_w) {
2036 grabkey(tmp, 0, tmp_win->title_w);
2037
2038 for(i = 0 ; i < 8 ; i++) {
2039 if((Scr->IgnoreModifier & ModifierMask [i]) &&
2040 !(tmp->mods & ModifierMask [i])) {
2041 grabkey(tmp, ModifierMask [i], tmp_win->title_w);
2042 }
2043 }
2044 }
2045 break;
2046
2047#ifdef EWMH_DESKTOP_ROOT
2048 case C_ROOT:
2049 if(tmp_win->ewmhWindowType != wt_Desktop) {
2050 break;
2051 }
2052
2053 grabkey(tmp, 0, tmp_win->w);
2054
2055 for(i = 0 ; i < 8 ; i++) {
2056 if((Scr->IgnoreModifier & ModifierMask [i]) &&
2057 !(tmp->mods & ModifierMask [i])) {
2058 grabkey(tmp, ModifierMask [i], tmp_win->w);
2059 }
2060 }
2061 break;
2062#endif /* EWMH */
2063
2064 /*
2065 case C_ROOT:
2066 XGrabKey(dpy, tmp->keycode, tmp->mods, Scr->Root, True,
2067 GrabModeAsync, GrabModeAsync);
2068 break;
2069 */
2070 }
2071 }
2072 for(tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) {
2073 if(tmp->cont == C_ICONMGR && !Scr->NoIconManagers) {
2074 for(p = Scr->iconmgr; p != NULL; p = p->next) {
2075 ungrabkey(tmp, 0, p->twm_win->w);
2076
2077 for(i = 0 ; i < 8 ; i++) {
2078 if((Scr->IgnoreModifier & ModifierMask [i]) &&
2079 !(tmp->mods & ModifierMask [i])) {
2080 ungrabkey(tmp, ModifierMask [i], p->twm_win->w);
2081 }
2082 }
2083 }
2084 }
2085 }
2086}
2087#undef grabkey
2088#undef ungrabkey
2089
2090
2091#ifdef VSCREEN
2092/*
2093 * This is largely for Xinerama support with VirtualScreens.
2094 * In this case, windows may be on something other then the main screen
2095 * on startup, or the mapping may be relative to the right side of the
2096 * screen, which is on a different monitor, which will cause issues with
2097 * the virtual screens.
2098 *
2099 * It probably needs to be congnizant of windows that are actually owned by
2100 * other workspaces, and ignore them (this needs to be revisited), or perhaps
2101 * that functionality is appropriate in AddWindow(). This needs to be dug into
2102 * more deply.
2103 *
2104 * this approach assumes screens that are next to each other horizontally,
2105 * Other possibilities need to be investigated and accounted for.
2106 */
2107static void
2110{
2111 Window vvroot;
2112 int x, y;
2113 unsigned int w, h;
2114 unsigned int j;
2115 VirtualScreen *myvs, *vs;
2116 int dropx = 0;
2117
2118 if(! vroot) {
2119 return;
2120 }
2121
2122 if(!(XGetGeometry(mydpy, vroot, &vvroot, &x, &y, &w, &h, &j, &j))) {
2123 return;
2124 }
2125
2126 myvs = findIfVScreenOf(x, y);
2127
2128 /*
2129 * probably need to rethink this for unmapped vs's. ugh.
2130 */
2131 if(!myvs) {
2132 return;
2133 }
2134
2135 for(vs = myvs->next; vs; vs = vs->next) {
2136 dropx += vs->w;
2137 }
2138
2139 for(vs = Scr->vScreenList; vs && vs != myvs; vs = vs->next) {
2140 dropx -= vs->w;
2141 }
2142
2143 if(tmp_win->frame_x > 0 && tmp_win->frame_x >= w) {
2144 tmp_win->frame_x -= abs(dropx);
2145 }
2146 else {
2147 }
2148
2149}
2150#endif // VSCREEN
bool resizeWhenAdd
Definition add_window.c:90
void GrabButtons(TwmWindow *tmp_win)
#define SETC(lst, save)
static int PlaceX
Definition add_window.c:82
unsigned int AddingH
Definition add_window.c:80
#define grabbutton(button, modifier, window, pointer_mode)
void GrabKeys(TwmWindow *tmp_win)
#define ungrabkey(funckey, modifier, window)
#define AltMask
#define SETCTXS(win)
int AddingY
Definition add_window.c:78
#define HALF_AVE_CURSOR_SIZE
unsigned int AddingW
Definition add_window.c:79
#define grabkey(funckey, modifier, window)
#define CHKL(lst)
char NoName[]
Definition add_window.c:89
int AddingX
Definition add_window.c:77
static int PlaceY
Definition add_window.c:83
TwmWindow * AddWindow(Window w, AWType wtype, IconMgr *iconp, VirtualScreen *vs)
Definition add_window.c:113
AWType
Definition add_window.h:23
@ AWT_ICON_MANAGER
Definition add_window.h:25
@ AWT_OCCUPY
Definition add_window.h:28
@ AWT_WINDOWBOX
Definition add_window.h:26
@ AWT_WORKSPACE_MANAGER
Definition add_window.h:27
void SetPropsIfCaptiveCtwm(TwmWindow *win)
Definition captive.c:502
bool RedirectToCaptive(Window window)
Definition captive.c:60
ctwm_cl_args CLarg
Definition clargs.c:27
void FetchWmColormapWindows(TwmWindow *tmp)
Definition colormaps.c:354
void UninstallRootColormap(void)
Definition colormaps.c:213
void InstallRootColormap(void)
Definition colormaps.c:173
int PreviousScreen
Definition ctwm_main.c:94
XClassHint NoClass
Definition ctwm_main.c:124
int JunkY
Definition ctwm.h:358
@ SIJ_LEFT
Definition ctwm.h:172
char * ProgramName
Definition ctwm_main.c:146
bool HandlingEvents
Definition ctwm_main.c:131
unsigned int JunkBW
Definition ctwm.h:359
@ PPOS_NON_ZERO
Definition ctwm.h:246
@ PPOS_ON
Definition ctwm.h:245
unsigned int JunkWidth
Definition ctwm_main.c:144
Window JunkRoot
Definition ctwm_main.c:142
@ RP_UNMAPPED
Definition ctwm.h:239
@ RP_ALL
Definition ctwm.h:238
int JunkX
Definition ctwm_main.c:143
#define C_NAME
Definition ctwm.h:81
Cursor UpperLeftCursor
Definition ctwm_main.c:105
Display * dpy
Definition ctwm_main.c:84
#define C_ROOT
Definition ctwm.h:78
unsigned int JunkMask
Definition ctwm.h:359
#define C_TITLE
Definition ctwm.h:76
#define C_WINDOW
Definition ctwm.h:75
#define FB(fix_fore, fix_back)
Definition ctwm.h:119
#define C_ICONMGR
Definition ctwm.h:80
Window JunkChild
Definition ctwm.h:357
bool HasShape
Definition ctwm_main.c:90
unsigned int JunkHeight
Definition ctwm.h:359
#define ZOOM_NONE
Definition ctwm.h:111
#define C_ICON
Definition ctwm.h:77
unsigned int JunkDepth
Definition ctwm.h:359
#define ALLOW_DEAD_STORE(x)
Definition ctwm.h:379
int NumScreens
How many Screens are on our display.
Definition ctwm_main.c:89
#define Scr
void FixRootEvent(XEvent *e)
void EwmhSet_NET_FRAME_EXTENTS(TwmWindow *twm_win)
Set _NET_FRAME_EXTENTS property.
Definition ewmh.c:2099
bool EwmhHasBorder(TwmWindow *twm_win)
Definition ewmh.c:1876
bool EwmhOnWindowRing(TwmWindow *twm_win)
Definition ewmh.c:1898
void EwmhGetProperties(TwmWindow *twm_win)
Definition ewmh.c:1842
bool EwmhHasTitle(TwmWindow *twm_win)
Definition ewmh.c:1887
@ wt_Desktop
Definition ewmh.h:18
#define EWMH_STATE_SHADED
Definition ewmh.h:40
#define EWMH_HAS_STRUT
Definition ewmh.h:35
int RootFunction
Definition functions.c:45
void ReGrab(void)
Definition functions.c:345
int frame_bw
2d border width.
unsigned int title_height
Height of the full title bar.
unsigned int frame_width
Width of frame.
unsigned int frame_height
Height of frame.
int frame_bw3D
3d border width.
WList * AddIconManager(TwmWindow *tmp_win)
Definition iconmgr.c:697
Pixmap mk_blackgray_pixmap(const char *which, Drawable dw, unsigned long fg, unsigned long bg)
void * LookInListWin(name_list *list_head, TwmWindow *twin)
Definition list.c:135
int y
Definition menus.c:70
int x
Definition menus.c:69
int mwm_has_border(MotifWmHints *hints)
Definition mwmhints.c:104
bool mwm_sets_title(MotifWmHints *hints)
Definition mwmhints.c:127
bool GetMWMHints(Window w, MotifWmHints *mwmHints)
Definition mwmhints.c:25
bool mwm_has_title(MotifWmHints *hints)
Definition mwmhints.c:145
void SetupOccupation(TwmWindow *twm_win, int occupation_hint)
Definition occupation.c:80
void OtpAdd(TwmWindow *twm_win, WinType wintype)
Definition otp.c:1222
@ WinWin
Definition otp.h:14
RArea RAreaNew(int x, int y, int width, int height)
Construct an RArea from given components.
Definition r_area.c:19
void RLayoutFindTopBottomEdges(const RLayout *self, const RArea *area, int *top, int *bottom)
Figure the position (or nearest practical position) of an area in our screen layout,...
Definition r_layout.c:401
int RLayoutFindMonitorRightEdge(const RLayout *self, const RArea *area)
Find the right edge of the left-most monitor that contains the most of a given RArea.
Definition r_layout.c:764
int RLayoutFindMonitorBottomEdge(const RLayout *self, const RArea *area)
Find the bottom edge of the top-most monitor that contains the most of a given RArea.
Definition r_layout.c:645
void RLayoutFindLeftRightEdges(const RLayout *self, const RArea *area, int *left, int *right)
Figure the position (or nearest practical position) of an area in our screen layout,...
Definition r_layout.c:466
#define SIZE_VINDENT
Internal padding in the size window.
Definition screen.h:59
#define SIZE_HINDENT
Internal padding in the size window.
Definition screen.h:58
int GetWindowConfig(TwmWindow *theWindow, short *x, short *y, unsigned short *width, unsigned short *height, bool *iconified, bool *icon_info_present, short *icon_x, short *icon_y, bool *width_ever_changed_by_user, bool *height_ever_changed_by_user, int *occupation)
Definition session.c:704
int number_cwins
Definition ctwm.h:280
A particular extent of space.
Definition r_structs.h:16
int y
Y position.
Definition r_structs.h:18
int width
X dimension.
Definition r_structs.h:19
int height
Y dimension.
Definition r_structs.h:20
int x
X position.
Definition r_structs.h:17
The layout of our display.
Definition r_structs.h:45
char * ctwm_wm_icon_name
Icon name from override CTWM_WM_ICON_NAME property.
char * wm_name
Name from ICCCM WM_NAME property.
char * wm_icon_name
Icon name from WM_ICON_NAME property.
char * ctwm_wm_name
Name from override CTWM_WM_NAME property.
bool cursor_valid
Whether curs_x and curs_y are usable.
unsigned int width
Saved width.
Info and control for every X Window we take over.
bool iswspmgr
This is a workspace manager window.
bool OpaqueMove
Move opaquely.
bool titlehighlight
Should I highlight the title bar?
bool isiconmgr
This is an icon manager window.
XWMHints * wmhints
Window manager hints.
bool heightEverChangedByUser
Has TwmWindow::attr height ever changed? Used only in sessions.
bool iconified
Has the window ever been iconified?
bool OpaqueResize
Resize opaquely.
Window w
The actual X Window handle.
bool auto_raise
Should we auto-raise this window ?
bool nameChanged
Has TwmWindow::name ever changed? Used only in session saving.
bool stackmode
Honor stackmode requests.
bool istransient
This is a transient window.
int zoomed
ZOOM_NONE || function causing zoom.
int old_bw
Original window border width before we took it over and made our own bordering.
struct TwmWindow::_ring ring
Window ring connectivity. "
char * name
Current window name. Points into TwmWindow::names.
bool auto_lower
Should we auto-lower this window ?
bool squeeze_info_copied
Should ->squeeze_info be free()'d?
bool widthEverChangedByUser
Has TwmWindow::attr width ever changed? Used only in sessions.
bool AlwaysSqueezeToGravity
SqueezeInfo * squeeze_info
Control info for title squeezing.
struct VirtualScreen * vs
Where the window is currently mapped (may be NULL)
bool icon_on
Is the icon visible.
XClassHint class
Window class info. From XGetClassHint().
XSizeHints hints
Window size hints.
Colormaps cmaps
colormaps for this application
struct IconMgr * iconmgrp
Pointer to the icon manager structure, for windows that are icon managers.
struct VirtualScreen * savevs
Where the window would be.
struct VirtualScreen * parent_vs
Where the window is parented. Always set.
struct TwmWindow::_savegeometry savegeometry
Saved window geometry. "
struct TwmWindow::_names names
Various sources of window/icon names. "
XWindowAttributes attr
Window attributes from XGetWindowAttributes()
Window transientfor
What window it's transient for.
bool UnmapByMovingFarAway
Window group
Window group, from WM hints.
bool iconify_by_unmapping
Unmap window to iconify it.
bool isoccupy
This is an Occupy window.
bool highlight
Should highlight this window.
bool isicon
Is the window an icon now ?
bool squeezed
Is the window squeezed ?
struct VirtualScreen * next
Definition vscreen.h:12
Window window
Definition vscreen.h:9
struct WindowBox WindowBox
Definition types.h:44
void GetShadeColors(ColorPair *cp)
Try and create a 'shaded' version of a color for prettier UI.
Definition util.c:245
void CreateWindowTitlebarButtons(TwmWindow *tmp_win)
void ComputeTitleLocation(TwmWindow *tmp)
void SetupFrame(TwmWindow *tmp_win, int x, int y, int w, int h, int bw, bool sendEvent)
void SetFocusVisualAttributes(TwmWindow *tmp_win, bool focus)
Definition win_ops.c:30
void MoveOutline(Window root, int x, int y, int width, int height, int bw, int th)
Definition win_ops.c:317
void AutoSqueeze(TwmWindow *tmp_win)
Definition win_ops.c:205
bool PlaceWindowInRegion(TwmWindow *tmp_win, int *final_x, int *final_y)
void ConstrainSize(TwmWindow *tmp_win, unsigned int *widthp, unsigned int *heightp)
Definition win_resize.c:727
void AddEndResize(TwmWindow *tmp_win)
Definition win_resize.c:702
void AddStartResize(TwmWindow *tmp_win, int x, int y, int w, int h)
Definition win_resize.c:284
void DoResize(int x_root, int y_root, TwmWindow *tmp_win)
Definition win_resize.c:439
void savegeometry(TwmWindow *tmp_win)
void UnlinkWindowFromRing(TwmWindow *win)
Definition win_ring.c:26
void AddWindowToRing(TwmWindow *win)
Definition win_ring.c:77
#define InitWindowNotOnRing(win)
Definition win_ring.h:11
void GetWindowSizeHints(TwmWindow *tmp)
Definition win_utils.c:41
bool set_window_name(TwmWindow *win)
[Re]set a window's name.
Definition win_utils.c:1126
XWMHints * munge_wmhints(TwmWindow *win, XWMHints *hints)
Perform whatever adaptations of WM_HINTS info we do.
Definition win_utils.c:1059
void DisplayPosition(const TwmWindow *_unused_tmp_win, int x, int y)
Definition win_utils.c:466
bool visible(const TwmWindow *tmp_win)
Definition win_utils.c:341
void MoveResizeSizeWindow(int x, int y, unsigned int width, unsigned int height)
Definition win_utils.c:495
TwmWindow * GetTwmWindow(Window w)
Definition win_utils.c:190
void ConstrainByBorders(TwmWindow *twmwin, int *left, int width, int *top, int height)
Definition win_utils.c:825
XWMHints * gen_synthetic_wmhints(TwmWindow *win)
Definition win_utils.c:1030
void FetchWmProtocols(TwmWindow *tmp)
Definition win_utils.c:108
void TryToGrid(TwmWindow *tmp_win, int *x, int *y)
Definition win_utils.c:705
void TryToPack(TwmWindow *tmp_win, int *x, int *y)
Definition win_utils.c:560
char * GetWMPropertyString(Window w, Atom prop)
Definition win_utils.c:222
void GetGravityOffsets(TwmWindow *tmp, int *xp, int *yp)
Definition win_utils.c:149
bool set_window_icon_name(TwmWindow *win)
[Re]set a window's icon name.
Definition win_utils.c:1288
WindowBox * findWindowBox(TwmWindow *twmwin)
Definition windowbox.c:98
void ConstrainedToWinBox(TwmWindow *twmwin, int x, int y, int *nx, int *ny)
Definition windowbox.c:118
void WMapAddWindow(TwmWindow *win)
int RLayoutXParseGeometry(RLayout *layout, const char *geometry, int *x, int *y, unsigned int *width, unsigned int *height)
Parse an X Geometry out to get the positions and sizes.