add_window.c revision 645f5050
1645f5050Syouri/*****************************************************************************/
2645f5050Syouri/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3645f5050Syouri/**                          Salt Lake City, Utah                           **/
4645f5050Syouri/**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5645f5050Syouri/**                        Cambridge, Massachusetts                         **/
6645f5050Syouri/**                                                                         **/
7645f5050Syouri/**                           All Rights Reserved                           **/
8645f5050Syouri/**                                                                         **/
9645f5050Syouri/**    Permission to use, copy, modify, and distribute this software and    **/
10645f5050Syouri/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11645f5050Syouri/**    granted, provided that the above copyright notice appear  in  all    **/
12645f5050Syouri/**    copies and that both  that  copyright  notice  and  this  permis-    **/
13645f5050Syouri/**    sion  notice appear in supporting  documentation,  and  that  the    **/
14645f5050Syouri/**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15645f5050Syouri/**    in publicity pertaining to distribution of the  software  without    **/
16645f5050Syouri/**    specific, written prior permission.                                  **/
17645f5050Syouri/**                                                                         **/
18645f5050Syouri/**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19645f5050Syouri/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20645f5050Syouri/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21645f5050Syouri/**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22645f5050Syouri/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23645f5050Syouri/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24645f5050Syouri/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25645f5050Syouri/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26645f5050Syouri/*****************************************************************************/
27645f5050Syouri
28645f5050Syouri/*
29645f5050Syouri *  [ ctwm ]
30645f5050Syouri *
31645f5050Syouri *  Copyright 1992 Claude Lecommandeur.
32645f5050Syouri *
33645f5050Syouri * Permission to use, copy, modify  and distribute this software  [ctwm] and
34645f5050Syouri * its documentation for any purpose is hereby granted without fee, provided
35645f5050Syouri * that the above  copyright notice appear  in all copies and that both that
36645f5050Syouri * copyright notice and this permission notice appear in supporting documen-
37645f5050Syouri * tation, and that the name of  Claude Lecommandeur not be used in adverti-
38645f5050Syouri * sing or  publicity  pertaining to  distribution of  the software  without
39645f5050Syouri * specific, written prior permission. Claude Lecommandeur make no represen-
40645f5050Syouri * tations  about the suitability  of this software  for any purpose.  It is
41645f5050Syouri * provided "as is" without express or implied warranty.
42645f5050Syouri *
43645f5050Syouri * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
44645f5050Syouri * INCLUDING ALL  IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS.  IN NO
45645f5050Syouri * EVENT SHALL  Claude Lecommandeur  BE LIABLE FOR ANY SPECIAL,  INDIRECT OR
46645f5050Syouri * CONSEQUENTIAL  DAMAGES OR ANY  DAMAGES WHATSOEVER  RESULTING FROM LOSS OF
47645f5050Syouri * USE, DATA  OR PROFITS,  WHETHER IN AN ACTION  OF CONTRACT,  NEGLIGENCE OR
48645f5050Syouri * OTHER  TORTIOUS ACTION,  ARISING OUT OF OR IN  CONNECTION WITH THE USE OR
49645f5050Syouri * PERFORMANCE OF THIS SOFTWARE.
50645f5050Syouri *
51645f5050Syouri * Author:  Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
52645f5050Syouri */
53645f5050Syouri
54645f5050Syouri/**********************************************************************
55645f5050Syouri *
56645f5050Syouri * $XConsortium: add_window.c,v 1.153 91/07/10 13:17:26 dave Exp $
57645f5050Syouri *
58645f5050Syouri * Add a new window, put the titlbar and other stuff around
59645f5050Syouri * the window
60645f5050Syouri *
61645f5050Syouri * 31-Mar-88 Tom LaStrange        Initial Version.
62645f5050Syouri *
63645f5050Syouri * Do the necessary modification to be integrated in ctwm.
64645f5050Syouri * Can no longer be used for the standard twm.
65645f5050Syouri *
66645f5050Syouri * 22-April-92 Claude Lecommandeur.
67645f5050Syouri *
68645f5050Syouri **********************************************************************/
69645f5050Syouri
70645f5050Syouri#include <stdio.h>
71645f5050Syouri#include <string.h>
72645f5050Syouri#ifndef VMS
73645f5050Syouri#include <sys/time.h>
74645f5050Syouri#else
75645f5050Syouri#include <time.h>
76645f5050Syouri#endif
77645f5050Syouri#if defined(AIXV3) || defined(_SYSTYPE_SVR4) || defined(ibm) || defined __QNX__
78645f5050Syouri#include <sys/select.h>
79645f5050Syouri#endif
80645f5050Syouri#include "twm.h"
81645f5050Syouri#ifdef VMS
82645f5050Syouri#include <decw$include/Xatom.h>
83645f5050Syouri#else
84645f5050Syouri#include <X11/Xatom.h>
85645f5050Syouri#endif
86645f5050Syouri#include "add_window.h"
87645f5050Syouri#include "windowbox.h"
88645f5050Syouri#include "util.h"
89645f5050Syouri#include "resize.h"
90645f5050Syouri#include "parse.h"
91645f5050Syouri#include "list.h"
92645f5050Syouri#include "events.h"
93645f5050Syouri#include "menus.h"
94645f5050Syouri#include "screen.h"
95645f5050Syouri#include "icons.h"
96645f5050Syouri#include "iconmgr.h"
97645f5050Syouri#include "session.h"
98645f5050Syouri#include "mwmhints.h"
99645f5050Syouri
100645f5050Syouri#define gray_width 2
101645f5050Syouri#define gray_height 2
102645f5050Syouristatic unsigned char gray_bits[] = {
103645f5050Syouri   0x02, 0x01};
104645f5050Syouristatic unsigned char black_bits[] = {
105645f5050Syouri   0xFF, 0xFF};
106645f5050Syouri
107645f5050Syouriint AddingX;
108645f5050Syouriint AddingY;
109645f5050Syouriunsigned int AddingW;
110645f5050Syouriunsigned int AddingH;
111645f5050Syouri
112645f5050Syouristatic int PlaceX = -1;
113645f5050Syouristatic int PlaceY = -1;
114645f5050Syouristatic void CreateWindowTitlebarButtons(TwmWindow *tmp_win);
115645f5050Syourivoid DealWithNonSensicalGeometries(Display *dpy, Window vroot, TwmWindow *tmp_win);
116645f5050Syouri
117645f5050Syouristatic void		splitWindowRegionEntry (WindowEntry	*we,
118645f5050Syouri						int grav1, int grav2,
119645f5050Syouri						int w, int h);
120645f5050Syouristatic WindowEntry	*findWindowEntry (WorkSpace    *wl,
121645f5050Syouri					  TwmWindow    *tmp_win,
122645f5050Syouri					  WindowRegion **wrp);
123645f5050Syouristatic WindowEntry	*prevWindowEntry (WindowEntry	*we,
124645f5050Syouri					  WindowRegion	*wr);
125645f5050Syouristatic void		mergeWindowEntries (WindowEntry	*old, WindowEntry *we);
126645f5050Syouri
127645f5050Syourichar NoName[] = "Untitled"; /* name if no name is specified */
128645f5050Syouriint  resizeWhenAdd;
129645f5050Syouri
130645f5050Syouriextern Atom _OL_WIN_ATTR;
131645f5050Syouri
132645f5050Syouri#if defined(__hpux) && !defined(_XPG4_EXTENDED)
133645f5050Syouri#   define FDSET int*
134645f5050Syouri#else
135645f5050Syouri#   define FDSET fd_set*
136645f5050Syouri#endif
137645f5050Syouri/************************************************************************
138645f5050Syouri *
139645f5050Syouri *  Procedure:
140645f5050Syouri *	GetGravityOffsets - map gravity to (x,y) offset signs for adding
141645f5050Syouri *		to x and y when window is mapped to get proper placement.
142645f5050Syouri *
143645f5050Syouri ************************************************************************
144645f5050Syouri */
145645f5050Syouri
146645f5050Syourivoid GetGravityOffsets (TwmWindow *tmp,	/* window from which to get gravity */
147645f5050Syouri			int *xp, int *yp)	/* return values */
148645f5050Syouri{
149645f5050Syouri    static struct _gravity_offset {
150645f5050Syouri	int x, y;
151645f5050Syouri    } gravity_offsets[11] = {
152645f5050Syouri	{  0,  0 },			/* ForgetGravity */
153645f5050Syouri	{ -1, -1 },			/* NorthWestGravity */
154645f5050Syouri	{  0, -1 },			/* NorthGravity */
155645f5050Syouri	{  1, -1 },			/* NorthEastGravity */
156645f5050Syouri	{ -1,  0 },			/* WestGravity */
157645f5050Syouri	{  0,  0 },			/* CenterGravity */
158645f5050Syouri	{  1,  0 },			/* EastGravity */
159645f5050Syouri	{ -1,  1 },			/* SouthWestGravity */
160645f5050Syouri	{  0,  1 },			/* SouthGravity */
161645f5050Syouri	{  1,  1 },			/* SouthEastGravity */
162645f5050Syouri	{  0,  0 },			/* StaticGravity */
163645f5050Syouri    };
164645f5050Syouri    register int g = ((tmp->hints.flags & PWinGravity)
165645f5050Syouri		      ? tmp->hints.win_gravity : NorthWestGravity);
166645f5050Syouri
167645f5050Syouri    if (g < ForgetGravity || g > StaticGravity) {
168645f5050Syouri	*xp = *yp = 0;
169645f5050Syouri    } else {
170645f5050Syouri	*xp = gravity_offsets[g].x;
171645f5050Syouri	*yp = gravity_offsets[g].y;
172645f5050Syouri    }
173645f5050Syouri}
174645f5050Syouri
175645f5050Syouri
176645f5050Syouri
177645f5050Syouri
178645f5050Syouri/***********************************************************************
179645f5050Syouri *
180645f5050Syouri *  Procedure:
181645f5050Syouri *	AddWindow - add a new window to the twm list
182645f5050Syouri *
183645f5050Syouri *  Returned Value:
184645f5050Syouri *	(TwmWindow *) - pointer to the TwmWindow structure
185645f5050Syouri *
186645f5050Syouri *  Inputs:
187645f5050Syouri *	w	- the window id of the window to add
188645f5050Syouri *	iconm	- flag to tell if this is an icon manager window
189645f5050Syouri *		0 --> normal window.
190645f5050Syouri *		1 --> icon manager.
191645f5050Syouri *		2 --> window box;
192645f5050Syouri *		else --> iconmgr;
193645f5050Syouri *
194645f5050Syouri *	iconp	- pointer to icon manager struct
195645f5050Syouri *
196645f5050Syouri ***********************************************************************
197645f5050Syouri */
198645f5050Syouri
199645f5050SyouriTwmWindow *AddWindow(Window w, int iconm, IconMgr *iconp)
200645f5050Syouri{
201645f5050Syouri    virtualScreen *vs;
202645f5050Syouri    TwmWindow *tmp_win;			/* new twm window structure */
203645f5050Syouri    int stat;
204645f5050Syouri    XEvent event;
205645f5050Syouri    unsigned long valuemask;		/* mask for create windows */
206645f5050Syouri    XSetWindowAttributes attributes;	/* attributes for create windows */
207645f5050Syouri    int width, height;			/* tmp variable */
208645f5050Syouri    int ask_user;		/* don't know where to put the window */
209645f5050Syouri    int gravx, gravy;			/* gravity signs for positioning */
210645f5050Syouri    int namelen;
211645f5050Syouri    int bw2;
212645f5050Syouri    short saved_x, saved_y, restore_icon_x, restore_icon_y;
213645f5050Syouri    unsigned short saved_width, saved_height;
214645f5050Syouri    Bool restore_iconified = 0;
215645f5050Syouri    Bool restore_icon_info_present = 0;
216645f5050Syouri    int restoredFromPrevSession;
217645f5050Syouri    Bool width_ever_changed_by_user;
218645f5050Syouri    Bool height_ever_changed_by_user;
219645f5050Syouri    int saved_occupation; /* <== [ Matthew McNeill Feb 1997 ] == */
220645f5050Syouri    Bool        random_placed = False;
221645f5050Syouri    int		found = 0;
222645f5050Syouri#ifndef VMS
223645f5050Syouri    fd_set	mask;
224645f5050Syouri    int		fd;
225645f5050Syouri    struct timeval timeout;
226645f5050Syouri#endif
227645f5050Syouri    XRectangle ink_rect;
228645f5050Syouri    XRectangle logical_rect;
229645f5050Syouri    WindowBox *winbox;
230645f5050Syouri    int iswinbox = 0;
231645f5050Syouri    int iswman = 0;
232645f5050Syouri    Window vroot;
233645f5050Syouri
234645f5050Syouri#ifdef DEBUG
235645f5050Syouri    fprintf(stderr, "AddWindow: w = 0x%x\n", w);
236645f5050Syouri#endif
237645f5050Syouri
238645f5050Syouri    if (!captive && RedirectToCaptive (w)) return (NULL);
239645f5050Syouri
240645f5050Syouri    /* allocate space for the twm window */
241645f5050Syouri    tmp_win = (TwmWindow *)calloc(1, sizeof(TwmWindow));
242645f5050Syouri    if (tmp_win == 0)
243645f5050Syouri    {
244645f5050Syouri	fprintf (stderr, "%s: Unable to allocate memory to manage window ID %lx.\n",
245645f5050Syouri		 ProgramName, w);
246645f5050Syouri	return NULL;
247645f5050Syouri    }
248645f5050Syouri    switch (iconm) {
249645f5050Syouri	case  0 : iswinbox = 0; break;
250645f5050Syouri	case  1 : iswinbox = 0; break;
251645f5050Syouri	case  2 : iswinbox = 1; iconm  = 0; break;
252645f5050Syouri	case  3 : iswman   = 1; iconm  = 0; break;
253645f5050Syouri	default : iswinbox = 0; iswman = 0; iconm = 1; break;
254645f5050Syouri    }
255645f5050Syouri    tmp_win->w = w;
256645f5050Syouri    tmp_win->zoomed = ZOOM_NONE;
257645f5050Syouri    tmp_win->iconmgr = iconm;
258645f5050Syouri    tmp_win->iconmgrp = iconp;
259645f5050Syouri    tmp_win->wspmgr = iswman;
260645f5050Syouri    tmp_win->iswinbox = iswinbox;
261645f5050Syouri    tmp_win->vs = NULL;
262645f5050Syouri    tmp_win->old_parent_vs = NULL;
263645f5050Syouri    tmp_win->savevs = NULL;
264645f5050Syouri    tmp_win->cmaps.number_cwins = 0;
265645f5050Syouri    tmp_win->savegeometry.width = -1;
266645f5050Syouri
267645f5050Syouri    XSelectInput(dpy, tmp_win->w, PropertyChangeMask);
268645f5050Syouri    XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr);
269645f5050Syouri    tmp_win->name = (char*) GetWMPropertyString(tmp_win->w, XA_WM_NAME);
270645f5050Syouri    tmp_win->class = NoClass;
271645f5050Syouri    XGetClassHint(dpy, tmp_win->w, &tmp_win->class);
272645f5050Syouri    FetchWmProtocols (tmp_win);
273645f5050Syouri    FetchWmColormapWindows (tmp_win);
274645f5050Syouri
275645f5050Syouri    if (GetWindowConfig (tmp_win,
276645f5050Syouri	&saved_x, &saved_y, &saved_width, &saved_height,
277645f5050Syouri	&restore_iconified, &restore_icon_info_present,
278645f5050Syouri	&restore_icon_x, &restore_icon_y,
279645f5050Syouri	&width_ever_changed_by_user, &height_ever_changed_by_user,
280645f5050Syouri	&saved_occupation)) /* <== [ Matthew McNeill Feb 1997 ] == */
281645f5050Syouri    {
282645f5050Syouri	tmp_win->attr.x = saved_x;
283645f5050Syouri	tmp_win->attr.y = saved_y;
284645f5050Syouri
285645f5050Syouri	tmp_win->widthEverChangedByUser = width_ever_changed_by_user;
286645f5050Syouri	tmp_win->heightEverChangedByUser = height_ever_changed_by_user;
287645f5050Syouri
288645f5050Syouri	if (width_ever_changed_by_user)
289645f5050Syouri	    tmp_win->attr.width = saved_width;
290645f5050Syouri
291645f5050Syouri	if (height_ever_changed_by_user)
292645f5050Syouri	    tmp_win->attr.height = saved_height;
293645f5050Syouri
294645f5050Syouri	restoredFromPrevSession = 1;
295645f5050Syouri    }
296645f5050Syouri    else
297645f5050Syouri    {
298645f5050Syouri	tmp_win->widthEverChangedByUser = False;
299645f5050Syouri	tmp_win->heightEverChangedByUser = False;
300645f5050Syouri
301645f5050Syouri	restoredFromPrevSession = 0;
302645f5050Syouri    }
303645f5050Syouri
304645f5050Syouri    /*
305645f5050Syouri     * do initial clip; should look at window gravity
306645f5050Syouri     */
307645f5050Syouri    if (tmp_win->attr.width > Scr->MaxWindowWidth)
308645f5050Syouri      tmp_win->attr.width = Scr->MaxWindowWidth;
309645f5050Syouri    if (tmp_win->attr.height > Scr->MaxWindowHeight)
310645f5050Syouri      tmp_win->attr.height = Scr->MaxWindowHeight;
311645f5050Syouri
312645f5050Syouri    tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w);
313645f5050Syouri
314645f5050Syouri    if (tmp_win->wmhints)
315645f5050Syouri    {
316645f5050Syouri	if (restore_iconified)
317645f5050Syouri	{
318645f5050Syouri	    tmp_win->wmhints->initial_state = IconicState;
319645f5050Syouri	    tmp_win->wmhints->flags |= StateHint;
320645f5050Syouri	}
321645f5050Syouri
322645f5050Syouri	if (restore_icon_info_present)
323645f5050Syouri	{
324645f5050Syouri	    tmp_win->wmhints->icon_x = restore_icon_x;
325645f5050Syouri	    tmp_win->wmhints->icon_y = restore_icon_y;
326645f5050Syouri	    tmp_win->wmhints->flags |= IconPositionHint;
327645f5050Syouri	}
328645f5050Syouri    }
329645f5050Syouri
330645f5050Syouri    if (tmp_win->wmhints) tmp_win->wmhints->input = True;
331645f5050Syouri				/* CL: Having with not willing focus
332645f5050Syouri				cause problems with AutoSqueeze and a few others
333645f5050Syouri				things. So I suppress it. And the whole focus thing
334645f5050Syouri				is buggy anyway */
335645f5050Syouri    if (tmp_win->wmhints && !(tmp_win->wmhints->flags & InputHint))
336645f5050Syouri	tmp_win->wmhints->input = True;
337645f5050Syouri    if (tmp_win->wmhints && (tmp_win->wmhints->flags & WindowGroupHint)) {
338645f5050Syouri	tmp_win->group = tmp_win->wmhints->window_group;
339645f5050Syouri	if (tmp_win->group) {
340645f5050Syouri	    /*
341645f5050Syouri	     * GTK windows often have a spurious "group leader" window which is
342645f5050Syouri	     * never reported to us and therefore does not really exist.  This
343645f5050Syouri	     * is annoying because we treat group members a lot like transient
344645f5050Syouri	     * windows.  Look for that here. It is in fact a duplicate of the
345645f5050Syouri	     * WM_CLIENT_LEADER property.
346645f5050Syouri	     */
347645f5050Syouri	    if (tmp_win->group != w && !GetTwmWindow(tmp_win->group)) {
348645f5050Syouri		tmp_win->group = 0;
349645f5050Syouri	    }
350645f5050Syouri	}
351645f5050Syouri    } else
352645f5050Syouri	tmp_win->group = 0;
353645f5050Syouri
354645f5050Syouri    /*
355645f5050Syouri     * The July 27, 1988 draft of the ICCCM ignores the size and position
356645f5050Syouri     * fields in the WM_NORMAL_HINTS property.
357645f5050Syouri     */
358645f5050Syouri
359645f5050Syouri    tmp_win->transient = Transient(tmp_win->w, &tmp_win->transientfor);
360645f5050Syouri
361645f5050Syouri    tmp_win->nameChanged = 0;
362645f5050Syouri    if (tmp_win->name == NULL)
363645f5050Syouri	tmp_win->name = NoName;
364645f5050Syouri    if (tmp_win->class.res_name == NULL)
365645f5050Syouri    	tmp_win->class.res_name = NoName;
366645f5050Syouri    if (tmp_win->class.res_class == NULL)
367645f5050Syouri    	tmp_win->class.res_class = NoName;
368645f5050Syouri
369645f5050Syouri    /*
370645f5050Syouri     * full_name seems to exist only because in the conditional code below,
371645f5050Syouri     * name is sometimes changed. In all other cases, name and full_name
372645f5050Syouri     * seem to be identical. Is that worth it?
373645f5050Syouri     */
374645f5050Syouri    tmp_win->full_name = tmp_win->name;
375645f5050Syouri#ifdef CLAUDE
376645f5050Syouri    if (strstr (tmp_win->name, " - Mozilla")) {
377645f5050Syouri      char *moz = strstr (tmp_win->name, " - Mozilla");
378645f5050Syouri      *moz = '\0';
379645f5050Syouri    }
380645f5050Syouri#endif
381645f5050Syouri    namelen = strlen (tmp_win->name);
382645f5050Syouri
383645f5050Syouri    if (LookInList(Scr->IgnoreTransientL, tmp_win->full_name, &tmp_win->class))
384645f5050Syouri      tmp_win->transient = 0;
385645f5050Syouri
386645f5050Syouri    tmp_win->highlight = Scr->Highlight &&
387645f5050Syouri	(!LookInList(Scr->NoHighlight, tmp_win->full_name,
388645f5050Syouri	    &tmp_win->class));
389645f5050Syouri
390645f5050Syouri    tmp_win->stackmode = Scr->StackMode &&
391645f5050Syouri	(!LookInList(Scr->NoStackModeL, tmp_win->full_name,
392645f5050Syouri	    &tmp_win->class));
393645f5050Syouri
394645f5050Syouri    tmp_win->ontoppriority = (LookInList(Scr->AlwaysOnTopL,
395645f5050Syouri	tmp_win->full_name, &tmp_win->class)) ? ONTOP_MAX : ONTOP_DEFAULT;
396645f5050Syouri
397645f5050Syouri    tmp_win->titlehighlight = Scr->TitleHighlight &&
398645f5050Syouri	(!LookInList(Scr->NoTitleHighlight, tmp_win->full_name,
399645f5050Syouri	    &tmp_win->class));
400645f5050Syouri
401645f5050Syouri    tmp_win->auto_raise = Scr->AutoRaiseDefault ||
402645f5050Syouri	LookInList(Scr->AutoRaise, tmp_win->full_name,
403645f5050Syouri			      &tmp_win->class);
404645f5050Syouri    if (tmp_win->auto_raise) Scr->NumAutoRaises++;
405645f5050Syouri
406645f5050Syouri    tmp_win->auto_lower = Scr->AutoLowerDefault ||
407645f5050Syouri	LookInList(Scr->AutoLower, tmp_win->full_name,
408645f5050Syouri			      &tmp_win->class);
409645f5050Syouri    if (tmp_win->auto_lower) Scr->NumAutoLowers++;
410645f5050Syouri
411645f5050Syouri    tmp_win->iconify_by_unmapping = Scr->IconifyByUnmapping;
412645f5050Syouri    if (Scr->IconifyByUnmapping)
413645f5050Syouri    {
414645f5050Syouri	tmp_win->iconify_by_unmapping = iconm ? FALSE :
415645f5050Syouri	    !LookInList(Scr->DontIconify, tmp_win->full_name,
416645f5050Syouri		&tmp_win->class);
417645f5050Syouri    }
418645f5050Syouri    tmp_win->iconify_by_unmapping = tmp_win->iconify_by_unmapping ||
419645f5050Syouri	LookInList(Scr->IconifyByUn, tmp_win->full_name, &tmp_win->class);
420645f5050Syouri
421645f5050Syouri    if (LookInList (Scr->UnmapByMovingFarAway, tmp_win->full_name, &tmp_win->class))
422645f5050Syouri	tmp_win->UnmapByMovingFarAway = True;
423645f5050Syouri    else
424645f5050Syouri	tmp_win->UnmapByMovingFarAway = False;
425645f5050Syouri
426645f5050Syouri    if (LookInList (Scr->DontSetInactive, tmp_win->full_name, &tmp_win->class))
427645f5050Syouri	tmp_win->DontSetInactive = True;
428645f5050Syouri    else
429645f5050Syouri	tmp_win->DontSetInactive = False;
430645f5050Syouri
431645f5050Syouri    if (LookInList (Scr->AutoSqueeze, tmp_win->full_name, &tmp_win->class))
432645f5050Syouri	tmp_win->AutoSqueeze = True;
433645f5050Syouri    else
434645f5050Syouri	tmp_win->AutoSqueeze = False;
435645f5050Syouri
436645f5050Syouri    if (LookInList (Scr->StartSqueezed, tmp_win->full_name, &tmp_win->class))
437645f5050Syouri	tmp_win->StartSqueezed = True;
438645f5050Syouri    else
439645f5050Syouri	tmp_win->StartSqueezed = False;
440645f5050Syouri
441645f5050Syouri    if (Scr->AlwaysSqueezeToGravity
442645f5050Syouri	|| LookInList (Scr->AlwaysSqueezeToGravityL, tmp_win->full_name, &tmp_win->class))
443645f5050Syouri	tmp_win->AlwaysSqueezeToGravity = True;
444645f5050Syouri    else
445645f5050Syouri	tmp_win->AlwaysSqueezeToGravity = False;
446645f5050Syouri
447645f5050Syouri    if (tmp_win->transient || tmp_win->group) {
448645f5050Syouri	TwmWindow *t = NULL;
449645f5050Syouri	if (tmp_win->transient) t = GetTwmWindow(tmp_win->transientfor);
450645f5050Syouri	if (!t && tmp_win->group) t = GetTwmWindow(tmp_win->group);
451645f5050Syouri	if (t) tmp_win->UnmapByMovingFarAway = t->UnmapByMovingFarAway;
452645f5050Syouri    }
453645f5050Syouri    if ((Scr->WindowRingAll && !iswman &&
454645f5050Syouri	!LookInList(Scr->WindowRingExcludeL, tmp_win->full_name, &tmp_win->class)) ||
455645f5050Syouri	LookInList(Scr->WindowRingL, tmp_win->full_name, &tmp_win->class)) {
456645f5050Syouri	if (Scr->Ring) {
457645f5050Syouri	    tmp_win->ring.next = Scr->Ring->ring.next;
458645f5050Syouri	    if (Scr->Ring->ring.next->ring.prev)
459645f5050Syouri	      Scr->Ring->ring.next->ring.prev = tmp_win;
460645f5050Syouri	    Scr->Ring->ring.next = tmp_win;
461645f5050Syouri	    tmp_win->ring.prev = Scr->Ring;
462645f5050Syouri	} else {
463645f5050Syouri	    tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win;
464645f5050Syouri	}
465645f5050Syouri    } else
466645f5050Syouri      tmp_win->ring.next = tmp_win->ring.prev = NULL;
467645f5050Syouri    tmp_win->ring.cursor_valid = False;
468645f5050Syouri
469645f5050Syouri    tmp_win->squeeze_info = NULL;
470645f5050Syouri    tmp_win->squeeze_info_copied = 0;
471645f5050Syouri    /*
472645f5050Syouri     * get the squeeze information; note that this does not have to be freed
473645f5050Syouri     * since it is coming from the screen list
474645f5050Syouri     */
475645f5050Syouri    if (HasShape) {
476645f5050Syouri	if (!LookInList (Scr->DontSqueezeTitleL, tmp_win->full_name,
477645f5050Syouri			 &tmp_win->class)) {
478645f5050Syouri	    tmp_win->squeeze_info = (SqueezeInfo *)
479645f5050Syouri	      LookInList (Scr->SqueezeTitleL, tmp_win->full_name,
480645f5050Syouri			  &tmp_win->class);
481645f5050Syouri	    if (!tmp_win->squeeze_info) {
482645f5050Syouri		static SqueezeInfo default_squeeze = { J_LEFT, 0, 0 };
483645f5050Syouri		if (Scr->SqueezeTitle)
484645f5050Syouri		  tmp_win->squeeze_info = &default_squeeze;
485645f5050Syouri	    }
486645f5050Syouri	}
487645f5050Syouri      }
488645f5050Syouri
489645f5050Syouri    tmp_win->old_bw = tmp_win->attr.border_width;
490645f5050Syouri
491645f5050Syouri    {
492645f5050Syouri	MotifWmHints mwmHints;
493645f5050Syouri	Boolean have_title;
494645f5050Syouri
495645f5050Syouri	GetMWMHints(tmp_win->w, &mwmHints);
496645f5050Syouri
497645f5050Syouri	tmp_win->frame_bw3D = Scr->ThreeDBorderWidth;
498645f5050Syouri	if (((mwmHints.flags & MWM_HINTS_DECORATIONS) &&
499645f5050Syouri		 (mwmHints.decorations & MWM_DECOR_BORDER) == 0)
500645f5050Syouri	    || LookInList(Scr->NoBorder, tmp_win->full_name, &tmp_win->class)) {
501645f5050Syouri	    tmp_win->frame_bw = 0;
502645f5050Syouri	    tmp_win->frame_bw3D = 0;
503645f5050Syouri	} else if (tmp_win->frame_bw3D != 0) {
504645f5050Syouri	    tmp_win->frame_bw = 0;
505645f5050Syouri	    Scr->ClientBorderWidth = FALSE;
506645f5050Syouri	} else if (Scr->ClientBorderWidth) {
507645f5050Syouri	    tmp_win->frame_bw = tmp_win->old_bw;
508645f5050Syouri	} else {
509645f5050Syouri	    tmp_win->frame_bw = Scr->BorderWidth;
510645f5050Syouri	}
511645f5050Syouri	bw2 = tmp_win->frame_bw * 2;
512645f5050Syouri
513645f5050Syouri
514645f5050Syouri	have_title = True;
515645f5050Syouri	if (mwmHints.flags & MWM_HINTS_DECORATIONS)
516645f5050Syouri	    have_title = (mwmHints.decorations & MWM_DECOR_TITLE) != 0;
517645f5050Syouri	if (Scr->NoTitlebar)
518645f5050Syouri	    have_title = False;
519645f5050Syouri	if (LookInList(Scr->MakeTitle, tmp_win->full_name, &tmp_win->class))
520645f5050Syouri	    have_title = True;
521645f5050Syouri	if (LookInList(Scr->NoTitle, tmp_win->full_name, &tmp_win->class))
522645f5050Syouri	    have_title = False;
523645f5050Syouri
524645f5050Syouri	if (have_title) {
525645f5050Syouri	    tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
526645f5050Syouri	} else {
527645f5050Syouri	    tmp_win->title_height = 0;
528645f5050Syouri	}
529645f5050Syouri    }
530645f5050Syouri
531645f5050Syouri    tmp_win->OpaqueMove = Scr->DoOpaqueMove;
532645f5050Syouri    if (LookInList(Scr->OpaqueMoveList, tmp_win->full_name, &tmp_win->class))
533645f5050Syouri	tmp_win->OpaqueMove = TRUE;
534645f5050Syouri    else
535645f5050Syouri    if (LookInList(Scr->NoOpaqueMoveList, tmp_win->full_name, &tmp_win->class))
536645f5050Syouri	tmp_win->OpaqueMove = FALSE;
537645f5050Syouri
538645f5050Syouri    tmp_win->OpaqueResize = Scr->DoOpaqueResize;
539645f5050Syouri    if (LookInList(Scr->OpaqueResizeList, tmp_win->full_name, &tmp_win->class))
540645f5050Syouri	tmp_win->OpaqueResize = TRUE;
541645f5050Syouri    else
542645f5050Syouri    if (LookInList(Scr->NoOpaqueResizeList, tmp_win->full_name, &tmp_win->class))
543645f5050Syouri	tmp_win->OpaqueResize = FALSE;
544645f5050Syouri
545645f5050Syouri    /* if it is a transient window, don't put a title on it */
546645f5050Syouri    if (tmp_win->transient && !Scr->DecorateTransients)
547645f5050Syouri	tmp_win->title_height = 0;
548645f5050Syouri
549645f5050Syouri    if (LookInList(Scr->StartIconified, tmp_win->full_name, &tmp_win->class))
550645f5050Syouri    {
551645f5050Syouri	if (!tmp_win->wmhints)
552645f5050Syouri	{
553645f5050Syouri	    tmp_win->wmhints = (XWMHints *)malloc(sizeof(XWMHints));
554645f5050Syouri	    tmp_win->wmhints->flags = 0;
555645f5050Syouri	}
556645f5050Syouri	tmp_win->wmhints->initial_state = IconicState;
557645f5050Syouri	tmp_win->wmhints->flags |= StateHint;
558645f5050Syouri    }
559645f5050Syouri
560645f5050Syouri    GetWindowSizeHints (tmp_win);
561645f5050Syouri
562645f5050Syouri    if (restoredFromPrevSession)
563645f5050Syouri    {
564645f5050Syouri	/*
565645f5050Syouri	 * When restoring window positions from the previous session,
566645f5050Syouri	 * we always use NorthWest gravity.
567645f5050Syouri	 */
568645f5050Syouri
569645f5050Syouri	gravx = gravy = -1;
570645f5050Syouri    }
571645f5050Syouri    else
572645f5050Syouri    {
573645f5050Syouri	GetGravityOffsets (tmp_win, &gravx, &gravy);
574645f5050Syouri    }
575645f5050Syouri
576645f5050Syouri    /*
577645f5050Syouri     * Don't bother user if:
578645f5050Syouri     *
579645f5050Syouri     *     o  the window is a transient, or
580645f5050Syouri     *
581645f5050Syouri     *     o  a USPosition was requested, or
582645f5050Syouri     *
583645f5050Syouri     *     o  a PPosition was requested and UsePPosition is ON or
584645f5050Syouri     *        NON_ZERO if the window is at other than (0,0)
585645f5050Syouri     */
586645f5050Syouri    ask_user = TRUE;
587645f5050Syouri    if (tmp_win->transient ||
588645f5050Syouri	(tmp_win->hints.flags & USPosition) ||
589645f5050Syouri        ((tmp_win->hints.flags & PPosition) && Scr->UsePPosition &&
590645f5050Syouri	 (Scr->UsePPosition == PPOS_ON ||
591645f5050Syouri	  tmp_win->attr.x != 0 || tmp_win->attr.y != 0)))
592645f5050Syouri      ask_user = FALSE;
593645f5050Syouri
594645f5050Syouri    /*===============[ Matthew McNeill 1997 ]==========================*
595645f5050Syouri     * added the occupation parameter to this function call so that the
596645f5050Syouri     * occupation can be set up in a specific state if desired
597645f5050Syouri     * (restore session for example)
598645f5050Syouri     */
599645f5050Syouri
600645f5050Syouri    /* note, this is where tmp_win->vs get setup, among other things */
601645f5050Syouri
602645f5050Syouri    if (restoredFromPrevSession) {
603645f5050Syouri      SetupOccupation (tmp_win, saved_occupation);
604645f5050Syouri    } else
605645f5050Syouri      SetupOccupation (tmp_win, 0);
606645f5050Syouri    /*=================================================================*/
607645f5050Syouri
608645f5050Syouri    tmp_win->frame_width  = tmp_win->attr.width  + 2 * tmp_win->frame_bw3D;
609645f5050Syouri    tmp_win->frame_height = tmp_win->attr.height + 2 * tmp_win->frame_bw3D +
610645f5050Syouri			    tmp_win->title_height;
611645f5050Syouri    ConstrainSize (tmp_win, &tmp_win->frame_width, &tmp_win->frame_height);
612645f5050Syouri    winbox = findWindowBox (tmp_win);
613645f5050Syouri    if (PlaceWindowInRegion (tmp_win, &(tmp_win->attr.x), &(tmp_win->attr.y))) {
614645f5050Syouri	ask_user = False;
615645f5050Syouri    }
616645f5050Syouri    if (LookInList (Scr->WindowGeometries, tmp_win->full_name, &tmp_win->class)) {
617645f5050Syouri        char *geom;
618645f5050Syouri	int mask_;
619645f5050Syouri	geom = LookInList (Scr->WindowGeometries, tmp_win->full_name, &tmp_win->class);
620645f5050Syouri	mask_ = XParseGeometry (geom, &tmp_win->attr.x, &tmp_win->attr.y,
621645f5050Syouri				(unsigned int*) &tmp_win->attr.width,
622645f5050Syouri				(unsigned int*) &tmp_win->attr.height);
623645f5050Syouri
624645f5050Syouri	if (mask_ & XNegative) tmp_win->attr.x += Scr->rootw - tmp_win->attr.width;
625645f5050Syouri	if (mask_ & YNegative) tmp_win->attr.y += Scr->rooth - tmp_win->attr.height;
626645f5050Syouri	ask_user = False;
627645f5050Syouri    }
628645f5050Syouri
629645f5050Syouri    if (XFindContext (dpy, w, VirtScreenContext, (XPointer *)&vs) == XCSUCCESS)
630645f5050Syouri      vroot = vs->window;
631645f5050Syouri    else
632645f5050Syouri    if (tmp_win->vs)
633645f5050Syouri      vroot = tmp_win->vs->window;
634645f5050Syouri    else
635645f5050Syouri      vroot = Scr->Root;
636645f5050Syouri    if (winbox) vroot = winbox->window;
637645f5050Syouri
638645f5050Syouri    /*
639645f5050Syouri     * do any prompting for position
640645f5050Syouri     */
641645f5050Syouri
642645f5050Syouri    if (HandlingEvents && ask_user && !restoredFromPrevSession) {
643645f5050Syouri      if ((Scr->RandomPlacement == RP_ALL) ||
644645f5050Syouri          ((Scr->RandomPlacement == RP_UNMAPPED) &&
645645f5050Syouri	   ((tmp_win->wmhints && (tmp_win->wmhints->initial_state == IconicState)) ||
646645f5050Syouri	    (! visible (tmp_win))))) { /* just stick it somewhere */
647645f5050Syouri
648645f5050Syouri#ifdef DEBUG
649645f5050Syouri	fprintf(stderr,
650645f5050Syouri		"DEBUG[RandomPlacement]: win: %dx%d+%d+%d, screen: %dx%d, title height: %d, random: +%d+%d\n",
651645f5050Syouri		tmp_win->attr.width, tmp_win->attr.height,
652645f5050Syouri		tmp_win->attr.x, tmp_win->attr.y,
653645f5050Syouri		Scr->rootw, Scr->rooth,
654645f5050Syouri		tmp_win->title_height,
655645f5050Syouri		PlaceX, PlaceY);
656645f5050Syouri#endif
657645f5050Syouri
658645f5050Syouri	/* Initiallise PlaceX and PlaceY */
659645f5050Syouri	if (PlaceX < 0 && PlaceY < 0) {
660645f5050Syouri	  if (Scr->RandomDisplacementX >= 0)
661645f5050Syouri	    PlaceX = Scr->BorderLeft + 5;
662645f5050Syouri	  else
663645f5050Syouri	    PlaceX = Scr->rootw - tmp_win->attr.width - Scr->BorderRight - 5;
664645f5050Syouri	  if (Scr->RandomDisplacementY >= 0)
665645f5050Syouri	    PlaceY = Scr->BorderTop + 5;
666645f5050Syouri	  else
667645f5050Syouri	    PlaceY = Scr->rooth - tmp_win->attr.height - tmp_win->title_height
668645f5050Syouri	      - Scr->BorderBottom - 5;
669645f5050Syouri	}
670645f5050Syouri
671645f5050Syouri	/* For a positive horizontal displacement, if the right edge
672645f5050Syouri	   of the window would fall outside of the screen, start over
673645f5050Syouri	   by placing the left edge of the window 5 pixels inside
674645f5050Syouri	   the left edge of the screen.*/
675645f5050Syouri	if (Scr->RandomDisplacementX >= 0
676645f5050Syouri	    && (PlaceX + tmp_win->attr.width
677645f5050Syouri		> Scr->rootw - Scr->BorderRight - 5))
678645f5050Syouri	  PlaceX = Scr->BorderLeft + 5;
679645f5050Syouri
680645f5050Syouri	/* For a negative horizontal displacement, if the left edge
681645f5050Syouri	   of the window would fall outside of the screen, start over
682645f5050Syouri	   by placing the right edge of the window 5 pixels inside
683645f5050Syouri	   the right edge of the screen.*/
684645f5050Syouri	if (Scr->RandomDisplacementX < 0 && PlaceX < Scr->BorderLeft + 5)
685645f5050Syouri	  PlaceX = Scr->rootw - tmp_win->attr.width - Scr->BorderRight - 5;
686645f5050Syouri
687645f5050Syouri	/* For a positive vertical displacement, if the bottom edge
688645f5050Syouri	   of the window would fall outside of the screen, start over
689645f5050Syouri	   by placing the top edge of the window 5 pixels inside the
690645f5050Syouri	   top edge of the screen.  Because we add the title height
691645f5050Syouri	   further down, we need to count with it here as well.  */
692645f5050Syouri	if (Scr->RandomDisplacementY >= 0
693645f5050Syouri	    && (PlaceY + tmp_win->attr.height + tmp_win->title_height
694645f5050Syouri		> Scr->rooth - Scr->BorderBottom - 5))
695645f5050Syouri	  PlaceY = Scr->BorderTop + 5;
696645f5050Syouri
697645f5050Syouri	/* For a negative vertical displacement, if the top edge of
698645f5050Syouri	   the window would fall outside of the screen, start over by
699645f5050Syouri	   placing the bottom edge of the window 5 pixels inside the
700645f5050Syouri	   bottom edge of the screen.  Because we add the title height
701645f5050Syouri	   further down, we need to count with it here as well.  */
702645f5050Syouri	if (Scr->RandomDisplacementY < 0 && PlaceY < Scr->BorderTop + 5)
703645f5050Syouri	  PlaceY = Scr->rooth - tmp_win->attr.height - tmp_win->title_height
704645f5050Syouri	    - Scr->BorderBottom - 5;
705645f5050Syouri
706645f5050Syouri	/* Assign the current random placement to the new window, as
707645f5050Syouri	   a preliminary measure.  Add the title height so things will
708645f5050Syouri	   look right.  */
709645f5050Syouri	tmp_win->attr.x = PlaceX;
710645f5050Syouri	tmp_win->attr.y = PlaceY + tmp_win->title_height;
711645f5050Syouri
712645f5050Syouri	/* If the window is not supposed to move off the screen, check
713645f5050Syouri	   that it's still within the screen, and if not, attempt to
714645f5050Syouri	   correct the situation. */
715645f5050Syouri	if (Scr->DontMoveOff) {
716645f5050Syouri	    int available;
717645f5050Syouri
718645f5050Syouri#ifdef DEBUG
719645f5050Syouri	    fprintf(stderr,
720645f5050Syouri		    "DEBUG[DontMoveOff]: win: %dx%d+%d+%d, screen: %dx%d, bw2: %d, bw3D: %d\n",
721645f5050Syouri		    tmp_win->attr.width, tmp_win->attr.height,
722645f5050Syouri		    tmp_win->attr.x, tmp_win->attr.y,
723645f5050Syouri		    Scr->rootw, Scr->rooth,
724645f5050Syouri		    bw2, tmp_win->frame_bw3D);
725645f5050Syouri#endif
726645f5050Syouri
727645f5050Syouri	    /* If the right edge of the window is outside the right edge
728645f5050Syouri	       of the screen, we need to move the window left.  Note that
729645f5050Syouri	       this can only happen with windows that are less than 50
730645f5050Syouri	       pixels less wide than the screen. */
731645f5050Syouri	    if ((tmp_win->attr.x + tmp_win->attr.width)  > Scr->rootw) {
732645f5050Syouri	      available = Scr->rootw - tmp_win->attr.width
733645f5050Syouri		- 2 * (bw2 + tmp_win->frame_bw3D);
734645f5050Syouri
735645f5050Syouri#ifdef DEBUG
736645f5050Syouri	      fprintf(stderr, "DEBUG[DontMoveOff]: availableX: %d\n",
737645f5050Syouri		      available);
738645f5050Syouri#endif
739645f5050Syouri
740645f5050Syouri	      /* If the window is wider than the screen or exactly the width
741645f5050Syouri		 of the screen, the availability is exactly 0.  The result
742645f5050Syouri		 will be to have the window placed as much to the left as
743645f5050Syouri		 possible. */
744645f5050Syouri	      if (available <= 0) available = 0;
745645f5050Syouri
746645f5050Syouri	      /* Place the window exactly between the left and right edge of
747645f5050Syouri		 the screen when possible.  If available was originally less
748645f5050Syouri		 than zero, it means the window's left edge will be against
749645f5050Syouri		 the screen's left edge, and the window's right edge will be
750645f5050Syouri		 outside the screen.  */
751645f5050Syouri	      tmp_win->attr.x = available / 2;
752645f5050Syouri	    }
753645f5050Syouri
754645f5050Syouri	    /* If the bottom edge of the window is outside the bottom edge
755645f5050Syouri	       of the screen, we need to move the window up.  Note that
756645f5050Syouri	       this can only happen with windows that are less than 50
757645f5050Syouri	       pixels less tall than the screen.  Don't forget to count
758645f5050Syouri	       with the title height and the frame widths.  */
759645f5050Syouri	    if ((tmp_win->attr.y + tmp_win->attr.height)  > Scr->rooth) {
760645f5050Syouri	      available = Scr->rooth - tmp_win->attr.height
761645f5050Syouri		- tmp_win->title_height - 2 * (bw2 + tmp_win->frame_bw3D);
762645f5050Syouri
763645f5050Syouri#ifdef DEBUG
764645f5050Syouri	      fprintf(stderr, "DEBUG[DontMoveOff]: availableY: %d\n",
765645f5050Syouri		      available);
766645f5050Syouri#endif
767645f5050Syouri
768645f5050Syouri	      /* If the window is taller than the screen or exactly the
769645f5050Syouri		 height of the screen, the availability is exactly 0.
770645f5050Syouri		 The result will be to have the window placed as much to
771645f5050Syouri		 the top as possible. */
772645f5050Syouri	      if (available <= 0) available = 0;
773645f5050Syouri
774645f5050Syouri	      /* Place the window exactly between the top and bottom edge of
775645f5050Syouri		 the screen when possible.  If available was originally less
776645f5050Syouri		 than zero, it means the window's top edge will be against
777645f5050Syouri		 the screen's top edge, and the window's bottom edge will be
778645f5050Syouri		 outside the screen.  Again, don't forget to add the title
779645f5050Syouri		 height.  */
780645f5050Syouri	      tmp_win->attr.y = available / 2 + tmp_win->title_height;
781645f5050Syouri	    }
782645f5050Syouri
783645f5050Syouri#ifdef DEBUG
784645f5050Syouri	    fprintf(stderr,
785645f5050Syouri		    "DEBUG[DontMoveOff]: win: %dx%d+%d+%d, screen: %dx%d\n",
786645f5050Syouri		    tmp_win->attr.width, tmp_win->attr.height,
787645f5050Syouri		    tmp_win->attr.x, tmp_win->attr.y,
788645f5050Syouri		    Scr->rootw, Scr->rooth);
789645f5050Syouri#endif
790645f5050Syouri	}
791645f5050Syouri
792645f5050Syouri	/* We know that if the window's left edge has moved compared to
793645f5050Syouri	   PlaceX, it will have moved to the left.  If it was moved less
794645f5050Syouri	   than 15 pixel either way, change the next "random position"
795645f5050Syouri	   30 pixels down and right. */
796645f5050Syouri	if (PlaceX - tmp_win->attr.x < 15
797645f5050Syouri	    || PlaceY - (tmp_win->attr.y - tmp_win->title_height) < 15) {
798645f5050Syouri	  PlaceX += Scr->RandomDisplacementX;
799645f5050Syouri	  PlaceY += Scr->RandomDisplacementY;
800645f5050Syouri	}
801645f5050Syouri
802645f5050Syouri	random_placed = True;
803645f5050Syouri      } else {				/* else prompt */
804645f5050Syouri	if (!(tmp_win->wmhints && tmp_win->wmhints->flags & StateHint &&
805645f5050Syouri	      tmp_win->wmhints->initial_state == IconicState))
806645f5050Syouri	{
807645f5050Syouri	    Bool firsttime = True;
808645f5050Syouri
809645f5050Syouri	    /* better wait until all the mouse buttons have been
810645f5050Syouri	     * released.
811645f5050Syouri	     */
812645f5050Syouri	    while (TRUE)
813645f5050Syouri	    {
814645f5050Syouri		XUngrabServer(dpy);
815645f5050Syouri		XSync(dpy, 0);
816645f5050Syouri		XGrabServer(dpy);
817645f5050Syouri
818645f5050Syouri		JunkMask = 0;
819645f5050Syouri		if (!XQueryPointer (dpy, Scr->Root, &JunkRoot,
820645f5050Syouri				    &JunkChild, &JunkX, &JunkY,
821645f5050Syouri				    &AddingX, &AddingY, &JunkMask))
822645f5050Syouri		  JunkMask = 0;
823645f5050Syouri
824645f5050Syouri		JunkMask &= (Button1Mask | Button2Mask | Button3Mask |
825645f5050Syouri			     Button4Mask | Button5Mask);
826645f5050Syouri
827645f5050Syouri		/*
828645f5050Syouri		 * watch out for changing screens
829645f5050Syouri		 */
830645f5050Syouri		if (firsttime) {
831645f5050Syouri		    if (JunkRoot != Scr->Root) {
832645f5050Syouri			register int scrnum;
833645f5050Syouri			for (scrnum = 0; scrnum < NumScreens; scrnum++) {
834645f5050Syouri			    if (JunkRoot == RootWindow (dpy, scrnum)) break;
835645f5050Syouri			}
836645f5050Syouri			if (scrnum != NumScreens) PreviousScreen = scrnum;
837645f5050Syouri		    }
838645f5050Syouri		    if (Scr->currentvs) {
839645f5050Syouri			vroot = Scr->currentvs->window;
840645f5050Syouri		    }
841645f5050Syouri		    firsttime = False;
842645f5050Syouri		}
843645f5050Syouri		if (winbox) vroot = winbox->window;
844645f5050Syouri
845645f5050Syouri		/*
846645f5050Syouri		 * wait for buttons to come up; yuck
847645f5050Syouri		 */
848645f5050Syouri		if (JunkMask != 0) continue;
849645f5050Syouri
850645f5050Syouri		/*
851645f5050Syouri		 * this will cause a warp to the indicated root
852645f5050Syouri		 */
853645f5050Syouri		stat = XGrabPointer(dpy, vroot, False,
854645f5050Syouri		    ButtonPressMask | ButtonReleaseMask |
855645f5050Syouri		    PointerMotionMask | PointerMotionHintMask,
856645f5050Syouri		    GrabModeAsync, GrabModeAsync,
857645f5050Syouri		    vroot, UpperLeftCursor, CurrentTime);
858645f5050Syouri		if (stat == GrabSuccess) break;
859645f5050Syouri	    }
860645f5050Syouri
861645f5050Syouri	    XmbTextExtents(Scr->SizeFont.font_set,
862645f5050Syouri			   tmp_win->name, namelen,
863645f5050Syouri			   &ink_rect, &logical_rect);
864645f5050Syouri	    width = SIZE_HINDENT + ink_rect.width;
865645f5050Syouri	    height = logical_rect.height + SIZE_VINDENT * 2;
866645f5050Syouri	    XmbTextExtents(Scr->SizeFont.font_set,
867645f5050Syouri			   ": ", 2,  &logical_rect, &logical_rect);
868645f5050Syouri	    Scr->SizeStringOffset = width + logical_rect.width;
869645f5050Syouri
870645f5050Syouri	    XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset +
871645f5050Syouri				Scr->SizeStringWidth + SIZE_HINDENT, height);
872645f5050Syouri	    XMapRaised(dpy, Scr->SizeWindow);
873645f5050Syouri	    InstallRootColormap();
874645f5050Syouri	    FB(Scr->DefaultC.fore, Scr->DefaultC.back);
875645f5050Syouri	    XmbDrawImageString (dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
876645f5050Syouri				Scr->NormalGC, SIZE_HINDENT,
877645f5050Syouri				SIZE_VINDENT + Scr->SizeFont.ascent,
878645f5050Syouri				tmp_win->name, namelen);
879645f5050Syouri
880645f5050Syouri	    if (winbox) ConstrainedToWinBox (tmp_win, AddingX, AddingY, &AddingX, &AddingY);
881645f5050Syouri
882645f5050Syouri	    AddingW = tmp_win->attr.width + bw2 + 2 * tmp_win->frame_bw3D;
883645f5050Syouri	    AddingH = tmp_win->attr.height + tmp_win->title_height +
884645f5050Syouri				bw2 + 2 * tmp_win->frame_bw3D;
885645f5050Syouri	    MoveOutline(vroot,AddingX, AddingY, AddingW, AddingH,
886645f5050Syouri			tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
887645f5050Syouri
888645f5050Syouri	    XmbDrawImageString (dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
889645f5050Syouri				Scr->NormalGC, width,
890645f5050Syouri				SIZE_VINDENT + Scr->SizeFont.ascent, ": ", 2);
891645f5050Syouri	    DisplayPosition (tmp_win, AddingX, AddingY);
892645f5050Syouri
893645f5050Syouri	    tmp_win->frame_width  = AddingW;
894645f5050Syouri	    tmp_win->frame_height = AddingH;
895645f5050Syouri	    /*SetFocus ((TwmWindow *) NULL, CurrentTime);*/
896645f5050Syouri	    while (TRUE)
897645f5050Syouri		{
898645f5050Syouri#ifndef VMS			/* I'll try to implement this later.  RL */
899645f5050Syouri		if (Scr->OpenWindowTimeout) {
900645f5050Syouri		    fd = ConnectionNumber (dpy);
901645f5050Syouri		    while (!XCheckMaskEvent (dpy, ButtonMotionMask | ButtonPressMask, &event)) {
902645f5050Syouri			FD_ZERO (&mask);
903645f5050Syouri			FD_SET  (fd, &mask);
904645f5050Syouri			timeout.tv_sec  = Scr->OpenWindowTimeout;
905645f5050Syouri			timeout.tv_usec = 0;
906645f5050Syouri			found = select (fd + 1, (FDSET)&mask, (FDSET)0, (FDSET)0, &timeout);
907645f5050Syouri			if (found == 0) break;
908645f5050Syouri		    }
909645f5050Syouri		    if (found == 0) break;
910645f5050Syouri		} else {
911645f5050Syouri#else
912645f5050Syouri		{
913645f5050Syouri#endif
914645f5050Syouri		    found = 1;
915645f5050Syouri		    XMaskEvent(dpy, ButtonPressMask | PointerMotionMask, &event);
916645f5050Syouri		}
917645f5050Syouri		if (event.type == MotionNotify) {
918645f5050Syouri		    /* discard any extra motion events before a release */
919645f5050Syouri		    while(XCheckMaskEvent(dpy,
920645f5050Syouri			ButtonMotionMask | ButtonPressMask, &event))
921645f5050Syouri			if (event.type == ButtonPress)
922645f5050Syouri			    break;
923645f5050Syouri		}
924645f5050Syouri		FixRootEvent (&event);
925645f5050Syouri		if (event.type == ButtonPress) {
926645f5050Syouri		  AddingX = event.xbutton.x_root;
927645f5050Syouri		  AddingY = event.xbutton.y_root;
928645f5050Syouri
929645f5050Syouri		  TryToGrid (tmp_win, &AddingX, &AddingY);
930645f5050Syouri		  if (Scr->PackNewWindows) TryToPack (tmp_win, &AddingX, &AddingY);
931645f5050Syouri
932645f5050Syouri		  /* DontMoveOff prohibits user form off-screen placement */
933645f5050Syouri		  if (Scr->DontMoveOff)
934645f5050Syouri                  {
935645f5050Syouri                      ConstrainByBorders (tmp_win, &AddingX, AddingW, &AddingY, AddingH);
936645f5050Syouri                  }
937645f5050Syouri		  break;
938645f5050Syouri		}
939645f5050Syouri
940645f5050Syouri		if (event.type != MotionNotify) {
941645f5050Syouri		    continue;
942645f5050Syouri		}
943645f5050Syouri
944645f5050Syouri		XQueryPointer(dpy, vroot, &JunkRoot, &JunkChild,
945645f5050Syouri		    &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
946645f5050Syouri
947645f5050Syouri		TryToGrid (tmp_win, &AddingX, &AddingY);
948645f5050Syouri		if (Scr->PackNewWindows) TryToPack (tmp_win, &AddingX, &AddingY);
949645f5050Syouri		if (Scr->DontMoveOff)
950645f5050Syouri		{
951645f5050Syouri		    ConstrainByBorders (tmp_win, &AddingX, AddingW, &AddingY, AddingH);
952645f5050Syouri		}
953645f5050Syouri		MoveOutline(vroot, AddingX, AddingY, AddingW, AddingH,
954645f5050Syouri			    tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
955645f5050Syouri
956645f5050Syouri		DisplayPosition (tmp_win, AddingX, AddingY);
957645f5050Syouri	    }
958645f5050Syouri
959645f5050Syouri	  if (found) {
960645f5050Syouri	    if (event.xbutton.button == Button2) {
961645f5050Syouri		int lastx, lasty;
962645f5050Syouri
963645f5050Syouri		XmbTextExtents(Scr->SizeFont.font_set,
964645f5050Syouri			       ": ", 2,  &logical_rect, &logical_rect);
965645f5050Syouri		Scr->SizeStringOffset = width + logical_rect.width;
966645f5050Syouri
967645f5050Syouri		XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset +
968645f5050Syouri			       Scr->SizeStringWidth + SIZE_HINDENT, height);
969645f5050Syouri
970645f5050Syouri		XmbDrawImageString(dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
971645f5050Syouri				   Scr->NormalGC, width,
972645f5050Syouri				   SIZE_VINDENT + Scr->SizeFont.ascent, ": ", 2);
973645f5050Syouri
974645f5050Syouri		if (0/*Scr->AutoRelativeResize*/) {
975645f5050Syouri		    int dx = (tmp_win->attr.width / 4);
976645f5050Syouri		    int dy = (tmp_win->attr.height / 4);
977645f5050Syouri
978645f5050Syouri#define HALF_AVE_CURSOR_SIZE 8		/* so that it is visible */
979645f5050Syouri		    if (dx < HALF_AVE_CURSOR_SIZE + Scr->BorderLeft)
980645f5050Syouri                        dx = HALF_AVE_CURSOR_SIZE + Scr->BorderLeft;
981645f5050Syouri		    if (dy < HALF_AVE_CURSOR_SIZE + Scr->BorderTop)
982645f5050Syouri                        dy = HALF_AVE_CURSOR_SIZE + Scr->BorderTop;
983645f5050Syouri#undef HALF_AVE_CURSOR_SIZE
984645f5050Syouri		    dx += (tmp_win->frame_bw + 1);
985645f5050Syouri		    dy += (bw2 + tmp_win->title_height + 1);
986645f5050Syouri		    if (AddingX + dx >= Scr->rootw - Scr->BorderRight)
987645f5050Syouri		      dx = Scr->rootw - Scr->BorderRight - AddingX - 1;
988645f5050Syouri		    if (AddingY + dy >= Scr->rooth - Scr->BorderBottom)
989645f5050Syouri		      dy = Scr->rooth - Scr->BorderBottom - AddingY - 1;
990645f5050Syouri		    if (dx > 0 && dy > 0)
991645f5050Syouri		      XWarpPointer (dpy, None, None, 0, 0, 0, 0, dx, dy);
992645f5050Syouri		} else {
993645f5050Syouri		    XWarpPointer (dpy, None, vroot, 0, 0, 0, 0,
994645f5050Syouri				  AddingX + AddingW/2, AddingY + AddingH/2);
995645f5050Syouri		}
996645f5050Syouri		AddStartResize(tmp_win, AddingX, AddingY, AddingW, AddingH);
997645f5050Syouri
998645f5050Syouri		lastx = -10000;
999645f5050Syouri		lasty = -10000;
1000645f5050Syouri		while (TRUE)
1001645f5050Syouri		{
1002645f5050Syouri		    XMaskEvent(dpy,
1003645f5050Syouri			       ButtonReleaseMask | ButtonMotionMask, &event);
1004645f5050Syouri
1005645f5050Syouri		    if (event.type == MotionNotify) {
1006645f5050Syouri			/* discard any extra motion events before a release */
1007645f5050Syouri			while(XCheckMaskEvent(dpy,
1008645f5050Syouri			    ButtonMotionMask | ButtonReleaseMask, &event))
1009645f5050Syouri			    if (event.type == ButtonRelease)
1010645f5050Syouri				break;
1011645f5050Syouri		    }
1012645f5050Syouri		    FixRootEvent (&event);
1013645f5050Syouri
1014645f5050Syouri		    if (event.type == ButtonRelease)
1015645f5050Syouri		    {
1016645f5050Syouri			AddEndResize(tmp_win);
1017645f5050Syouri			break;
1018645f5050Syouri		    }
1019645f5050Syouri
1020645f5050Syouri		    if (event.type != MotionNotify) {
1021645f5050Syouri			continue;
1022645f5050Syouri		    }
1023645f5050Syouri
1024645f5050Syouri		    /*
1025645f5050Syouri		     * XXX - if we are going to do a loop, we ought to consider
1026645f5050Syouri		     * using multiple GXxor lines so that we don't need to
1027645f5050Syouri		     * grab the server.
1028645f5050Syouri		     */
1029645f5050Syouri		    XQueryPointer(dpy, vroot, &JunkRoot, &JunkChild,
1030645f5050Syouri				  &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
1031645f5050Syouri
1032645f5050Syouri		    if (lastx != AddingX || lasty != AddingY)
1033645f5050Syouri		    {
1034645f5050Syouri			resizeWhenAdd = TRUE;
1035645f5050Syouri			DoResize(AddingX, AddingY, tmp_win);
1036645f5050Syouri			resizeWhenAdd = FALSE;
1037645f5050Syouri
1038645f5050Syouri			lastx = AddingX;
1039645f5050Syouri			lasty = AddingY;
1040645f5050Syouri		    }
1041645f5050Syouri
1042645f5050Syouri		}
1043645f5050Syouri	    }
1044645f5050Syouri	    else if (event.xbutton.button == Button3)
1045645f5050Syouri	    {
1046645f5050Syouri		int maxw = Scr->rootw - Scr->BorderRight  - AddingX - bw2;
1047645f5050Syouri		int maxh = Scr->rooth - Scr->BorderBottom - AddingY - bw2;
1048645f5050Syouri
1049645f5050Syouri		/*
1050645f5050Syouri		 * Make window go to bottom of screen, and clip to right edge.
1051645f5050Syouri		 * This is useful when popping up large windows and fixed
1052645f5050Syouri		 * column text windows.
1053645f5050Syouri		 */
1054645f5050Syouri		if (AddingW > maxw) AddingW = maxw;
1055645f5050Syouri		AddingH = maxh;
1056645f5050Syouri
1057645f5050Syouri		ConstrainSize (tmp_win, &AddingW, &AddingH);  /* w/o borders */
1058645f5050Syouri		AddingW += bw2;
1059645f5050Syouri		AddingH += bw2;
1060645f5050Syouri		XMaskEvent(dpy, ButtonReleaseMask, &event);
1061645f5050Syouri	    }
1062645f5050Syouri	    else
1063645f5050Syouri	    {
1064645f5050Syouri		XMaskEvent(dpy, ButtonReleaseMask, &event);
1065645f5050Syouri	    }
1066645f5050Syouri	  }
1067645f5050Syouri	    MoveOutline(vroot, 0, 0, 0, 0, 0, 0);
1068645f5050Syouri	    XUnmapWindow(dpy, Scr->SizeWindow);
1069645f5050Syouri	    UninstallRootColormap();
1070645f5050Syouri	    XUngrabPointer(dpy, CurrentTime);
1071645f5050Syouri
1072645f5050Syouri	    tmp_win->attr.x = AddingX;
1073645f5050Syouri	    tmp_win->attr.y = AddingY + tmp_win->title_height;
1074645f5050Syouri	    tmp_win->attr.width = AddingW - bw2 - 2 * tmp_win->frame_bw3D;
1075645f5050Syouri	    tmp_win->attr.height = AddingH - tmp_win->title_height -
1076645f5050Syouri				bw2 - 2 * tmp_win->frame_bw3D;
1077645f5050Syouri
1078645f5050Syouri	    XUngrabServer(dpy);
1079645f5050Syouri	}
1080645f5050Syouri      }
1081645f5050Syouri    } else {				/* put it where asked, mod title bar */
1082645f5050Syouri	/* if the gravity is towards the top, move it by the title height */
1083645f5050Syouri	if (gravy < 0) tmp_win->attr.y -= gravy * tmp_win->title_height;
1084645f5050Syouri    }
1085645f5050Syouri
1086645f5050Syouri#ifdef DEBUG
1087645f5050Syouri	fprintf(stderr, "  position window  %d, %d  %dx%d\n",
1088645f5050Syouri	    tmp_win->attr.x,
1089645f5050Syouri	    tmp_win->attr.y,
1090645f5050Syouri	    tmp_win->attr.width,
1091645f5050Syouri	    tmp_win->attr.height);
1092645f5050Syouri#endif
1093645f5050Syouri
1094645f5050Syouri    if (!Scr->ClientBorderWidth) {	/* need to adjust for twm borders */
1095645f5050Syouri	int delta = tmp_win->attr.border_width - tmp_win->frame_bw - tmp_win->frame_bw3D;
1096645f5050Syouri	tmp_win->attr.x += gravx * delta;
1097645f5050Syouri	tmp_win->attr.y += gravy * delta;
1098645f5050Syouri    }
1099645f5050Syouri
1100645f5050Syouri    tmp_win->title_width = tmp_win->attr.width;
1101645f5050Syouri
1102645f5050Syouri    tmp_win->icon_name = (char*) GetWMPropertyString(tmp_win->w, XA_WM_ICON_NAME);
1103645f5050Syouri    if (!tmp_win->icon_name)
1104645f5050Syouri	tmp_win->icon_name = tmp_win->name;
1105645f5050Syouri
1106645f5050Syouri#ifdef CLAUDE
1107645f5050Syouri    if (strstr (tmp_win->icon_name, " - Mozilla")) {
1108645f5050Syouri      char *moz = strstr (tmp_win->icon_name, " - Mozilla");
1109645f5050Syouri      *moz = '\0';
1110645f5050Syouri    }
1111645f5050Syouri#endif
1112645f5050Syouri
1113645f5050Syouri    XmbTextExtents (Scr->TitleBarFont.font_set, tmp_win->name, namelen, &ink_rect, &logical_rect);
1114645f5050Syouri    tmp_win->name_width = logical_rect.width;
1115645f5050Syouri
1116645f5050Syouri    if (tmp_win->old_bw) XSetWindowBorderWidth (dpy, tmp_win->w, 0);
1117645f5050Syouri
1118645f5050Syouri    tmp_win->squeezed = FALSE;
1119645f5050Syouri    tmp_win->iconified = FALSE;
1120645f5050Syouri    tmp_win->isicon = FALSE;
1121645f5050Syouri    tmp_win->icon_on = FALSE;
1122645f5050Syouri
1123645f5050Syouri    XGrabServer(dpy);
1124645f5050Syouri
1125645f5050Syouri    /*
1126645f5050Syouri     * Make sure the client window still exists.  We don't want to leave an
1127645f5050Syouri     * orphan frame window if it doesn't.  Since we now have the server
1128645f5050Syouri     * grabbed, the window can't disappear later without having been
1129645f5050Syouri     * reparented, so we'll get a DestroyNotify for it.  We won't have
1130645f5050Syouri     * gotten one for anything up to here, however.
1131645f5050Syouri     */
1132645f5050Syouri    if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY,
1133645f5050Syouri		     &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0)
1134645f5050Syouri    {
1135645f5050Syouri	TwmWindow *prev = tmp_win->ring.prev, *next = tmp_win->ring.next;
1136645f5050Syouri
1137645f5050Syouri	if (prev) prev->ring.next = next;
1138645f5050Syouri	if (next) next->ring.prev = prev;
1139645f5050Syouri	if (Scr->Ring == tmp_win) Scr->Ring = (next != tmp_win ? next : (TwmWindow *) NULL);
1140645f5050Syouri	if (!Scr->Ring || Scr->RingLeader == tmp_win) Scr->RingLeader = Scr->Ring;
1141645f5050Syouri
1142645f5050Syouri	free((char *)tmp_win);
1143645f5050Syouri	XUngrabServer(dpy);
1144645f5050Syouri	return(NULL);
1145645f5050Syouri    }
1146645f5050Syouri
1147645f5050Syouri    /* add the window into the twm list */
1148645f5050Syouri    tmp_win->next = Scr->FirstWindow;
1149645f5050Syouri    if (Scr->FirstWindow != NULL)
1150645f5050Syouri	Scr->FirstWindow->prev = tmp_win;
1151645f5050Syouri    tmp_win->prev = NULL;
1152645f5050Syouri    Scr->FirstWindow = tmp_win;
1153645f5050Syouri
1154645f5050Syouri    /* get all the colors for the window */
1155645f5050Syouri
1156645f5050Syouri    tmp_win->borderC.fore     = Scr->BorderColorC.fore;
1157645f5050Syouri    tmp_win->borderC.back     = Scr->BorderColorC.back;
1158645f5050Syouri    tmp_win->border_tile.fore = Scr->BorderTileC.fore;
1159645f5050Syouri    tmp_win->border_tile.back = Scr->BorderTileC.back;
1160645f5050Syouri    tmp_win->title.fore       = Scr->TitleC.fore;
1161645f5050Syouri    tmp_win->title.back       = Scr->TitleC.back;
1162645f5050Syouri
1163645f5050Syouri    GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class,
1164645f5050Syouri	&tmp_win->borderC.fore);
1165645f5050Syouri    GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class,
1166645f5050Syouri	&tmp_win->borderC.back);
1167645f5050Syouri    GetColorFromList(Scr->BorderTileForegroundL, tmp_win->full_name,
1168645f5050Syouri	&tmp_win->class, &tmp_win->border_tile.fore);
1169645f5050Syouri    GetColorFromList(Scr->BorderTileBackgroundL, tmp_win->full_name,
1170645f5050Syouri	&tmp_win->class, &tmp_win->border_tile.back);
1171645f5050Syouri    GetColorFromList(Scr->TitleForegroundL, tmp_win->full_name, &tmp_win->class,
1172645f5050Syouri	&tmp_win->title.fore);
1173645f5050Syouri    GetColorFromList(Scr->TitleBackgroundL, tmp_win->full_name, &tmp_win->class,
1174645f5050Syouri	&tmp_win->title.back);
1175645f5050Syouri
1176645f5050Syouri    if (Scr->use3Dtitles  && !Scr->BeNiceToColormap) GetShadeColors (&tmp_win->title);
1177645f5050Syouri    if (Scr->use3Dborders && !Scr->BeNiceToColormap) {
1178645f5050Syouri	GetShadeColors (&tmp_win->borderC);
1179645f5050Syouri	GetShadeColors (&tmp_win->border_tile);
1180645f5050Syouri    }
1181645f5050Syouri    /* create windows */
1182645f5050Syouri
1183645f5050Syouri    tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->frame_bw
1184645f5050Syouri			- tmp_win->frame_bw3D;
1185645f5050Syouri    tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height +
1186645f5050Syouri	tmp_win->old_bw - tmp_win->frame_bw - tmp_win->frame_bw3D;
1187645f5050Syouri    tmp_win->frame_width = tmp_win->attr.width + 2 * tmp_win->frame_bw3D;
1188645f5050Syouri    tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height +
1189645f5050Syouri				2 * tmp_win->frame_bw3D;
1190645f5050Syouri
1191645f5050Syouri    ConstrainSize (tmp_win, &tmp_win->frame_width, &tmp_win->frame_height);
1192645f5050Syouri    if (random_placed)
1193645f5050Syouri        ConstrainByBorders (tmp_win, &tmp_win->frame_x, tmp_win->frame_width,
1194645f5050Syouri                            &tmp_win->frame_y, tmp_win->frame_height);
1195645f5050Syouri
1196645f5050Syouri    valuemask = CWBackPixmap | CWBorderPixel | CWCursor | CWEventMask | CWBackPixel;
1197645f5050Syouri    attributes.background_pixmap = None;
1198645f5050Syouri    attributes.border_pixel = tmp_win->border_tile.back;
1199645f5050Syouri    attributes.background_pixel = tmp_win->border_tile.back;
1200645f5050Syouri    attributes.cursor = Scr->FrameCursor;
1201645f5050Syouri    attributes.event_mask = (SubstructureRedirectMask |
1202645f5050Syouri			     ButtonPressMask | ButtonReleaseMask |
1203645f5050Syouri			     EnterWindowMask | LeaveWindowMask | ExposureMask);
1204645f5050Syouri    if (Scr->BorderCursors) attributes.event_mask |= PointerMotionMask;
1205645f5050Syouri    if (tmp_win->attr.save_under) {
1206645f5050Syouri	attributes.save_under = True;
1207645f5050Syouri	valuemask |= CWSaveUnder;
1208645f5050Syouri    }
1209645f5050Syouri    if (tmp_win->hints.flags & PWinGravity) {
1210645f5050Syouri	attributes.win_gravity = tmp_win->hints.win_gravity;
1211645f5050Syouri	valuemask |= CWWinGravity;
1212645f5050Syouri    }
1213645f5050Syouri
1214645f5050Syouri    if ((tmp_win->frame_x > Scr->rootw) ||
1215645f5050Syouri	(tmp_win->frame_y > Scr->rooth) ||
1216645f5050Syouri	((int)(tmp_win->frame_x + tmp_win->frame_width)  < 0) ||
1217645f5050Syouri	((int)(tmp_win->frame_y + tmp_win->frame_height) < 0)) {
1218645f5050Syouri      tmp_win->frame_x = 0;
1219645f5050Syouri      tmp_win->frame_y = 0;
1220645f5050Syouri    }
1221645f5050Syouri
1222645f5050Syouri    DealWithNonSensicalGeometries(dpy, vroot, tmp_win);
1223645f5050Syouri
1224645f5050Syouri    tmp_win->frame = XCreateWindow (dpy, vroot, tmp_win->frame_x, tmp_win->frame_y,
1225645f5050Syouri				    (unsigned int) tmp_win->frame_width,
1226645f5050Syouri				    (unsigned int) tmp_win->frame_height,
1227645f5050Syouri				    (unsigned int) tmp_win->frame_bw,
1228645f5050Syouri				    Scr->d_depth,
1229645f5050Syouri				    (unsigned int) CopyFromParent,
1230645f5050Syouri				    Scr->d_visual, valuemask, &attributes);
1231645f5050Syouri
1232645f5050Syouri    if (tmp_win->title_height)
1233645f5050Syouri    {
1234645f5050Syouri	valuemask = (CWEventMask | CWDontPropagate | CWBorderPixel | CWBackPixel);
1235645f5050Syouri	attributes.event_mask = (KeyPressMask | ButtonPressMask |
1236645f5050Syouri				 ButtonReleaseMask | ExposureMask);
1237645f5050Syouri	attributes.do_not_propagate_mask = PointerMotionMask;
1238645f5050Syouri	attributes.border_pixel = tmp_win->borderC.back;
1239645f5050Syouri	attributes.background_pixel = tmp_win->title.back;
1240645f5050Syouri	tmp_win->title_w = XCreateWindow (dpy, tmp_win->frame,
1241645f5050Syouri					  tmp_win->frame_bw3D - tmp_win->frame_bw,
1242645f5050Syouri					  tmp_win->frame_bw3D - tmp_win->frame_bw,
1243645f5050Syouri					  (unsigned int) tmp_win->attr.width,
1244645f5050Syouri					  (unsigned int) Scr->TitleHeight,
1245645f5050Syouri					  (unsigned int) tmp_win->frame_bw,
1246645f5050Syouri					  Scr->d_depth,
1247645f5050Syouri					  (unsigned int) CopyFromParent,
1248645f5050Syouri					  Scr->d_visual, valuemask,
1249645f5050Syouri					  &attributes);
1250645f5050Syouri    }
1251645f5050Syouri    else {
1252645f5050Syouri	tmp_win->title_w = 0;
1253645f5050Syouri	tmp_win->squeeze_info = NULL;
1254645f5050Syouri    }
1255645f5050Syouri
1256645f5050Syouri    if (tmp_win->highlight)
1257645f5050Syouri    {
1258645f5050Syouri	if (Scr->use3Dtitles && (Scr->Monochrome != COLOR))
1259645f5050Syouri	    tmp_win->gray = XCreatePixmapFromBitmapData(dpy, vroot,
1260645f5050Syouri		(char*)black_bits, gray_width, gray_height,
1261645f5050Syouri		tmp_win->border_tile.fore, tmp_win->border_tile.back,
1262645f5050Syouri		Scr->d_depth);
1263645f5050Syouri	else
1264645f5050Syouri	    tmp_win->gray = XCreatePixmapFromBitmapData(dpy, vroot,
1265645f5050Syouri		(char*)gray_bits, gray_width, gray_height,
1266645f5050Syouri		tmp_win->border_tile.fore, tmp_win->border_tile.back,
1267645f5050Syouri		Scr->d_depth);
1268645f5050Syouri
1269645f5050Syouri	tmp_win->hasfocusvisible = True;
1270645f5050Syouri	SetFocusVisualAttributes (tmp_win, False);
1271645f5050Syouri    }
1272645f5050Syouri    else
1273645f5050Syouri	tmp_win->gray = None;
1274645f5050Syouri
1275645f5050Syouri    RaiseWindow(tmp_win);
1276645f5050Syouri
1277645f5050Syouri    if (tmp_win->title_w) {
1278645f5050Syouri	ComputeTitleLocation (tmp_win);
1279645f5050Syouri	CreateWindowTitlebarButtons (tmp_win);
1280645f5050Syouri	XMoveWindow (dpy, tmp_win->title_w,
1281645f5050Syouri		     tmp_win->title_x, tmp_win->title_y);
1282645f5050Syouri	XDefineCursor(dpy, tmp_win->title_w, Scr->TitleCursor);
1283645f5050Syouri    }
1284645f5050Syouri    else {
1285645f5050Syouri	tmp_win->title_x = tmp_win->frame_bw3D - tmp_win->frame_bw;
1286645f5050Syouri	tmp_win->title_y = tmp_win->frame_bw3D - tmp_win->frame_bw;
1287645f5050Syouri    }
1288645f5050Syouri
1289645f5050Syouri    valuemask = (CWEventMask | CWDontPropagate);
1290645f5050Syouri    attributes.event_mask = (StructureNotifyMask | PropertyChangeMask |
1291645f5050Syouri			     ColormapChangeMask | VisibilityChangeMask |
1292645f5050Syouri			     FocusChangeMask |
1293645f5050Syouri			     EnterWindowMask | LeaveWindowMask);
1294645f5050Syouri    attributes.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
1295645f5050Syouri    XChangeWindowAttributes (dpy, tmp_win->w, valuemask, &attributes);
1296645f5050Syouri
1297645f5050Syouri    if (HasShape)
1298645f5050Syouri	XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask);
1299645f5050Syouri
1300645f5050Syouri    if (tmp_win->title_w) {
1301645f5050Syouri	XMapWindow (dpy, tmp_win->title_w);
1302645f5050Syouri    }
1303645f5050Syouri
1304645f5050Syouri    if (HasShape) {
1305645f5050Syouri	int xws, yws, xbs, ybs;
1306645f5050Syouri	unsigned wws, hws, wbs, hbs;
1307645f5050Syouri	int boundingShaped, clipShaped;
1308645f5050Syouri
1309645f5050Syouri	XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask);
1310645f5050Syouri	XShapeQueryExtents (dpy, tmp_win->w,
1311645f5050Syouri			    &boundingShaped, &xws, &yws, &wws, &hws,
1312645f5050Syouri			    &clipShaped, &xbs, &ybs, &wbs, &hbs);
1313645f5050Syouri	tmp_win->wShaped = boundingShaped;
1314645f5050Syouri    }
1315645f5050Syouri
1316645f5050Syouri    if (!tmp_win->iconmgr &&! iswman &&
1317645f5050Syouri	(tmp_win->w != Scr->workSpaceMgr.occupyWindow->w))
1318645f5050Syouri	XAddToSaveSet(dpy, tmp_win->w);
1319645f5050Syouri
1320645f5050Syouri    XReparentWindow(dpy, tmp_win->w, tmp_win->frame, tmp_win->frame_bw3D,
1321645f5050Syouri		tmp_win->title_height + tmp_win->frame_bw3D);
1322645f5050Syouri    /*
1323645f5050Syouri     * Reparenting generates an UnmapNotify event, followed by a MapNotify.
1324645f5050Syouri     * Set the map state to FALSE to prevent a transition back to
1325645f5050Syouri     * WithdrawnState in HandleUnmapNotify.  Map state gets set correctly
1326645f5050Syouri     * again in HandleMapNotify.
1327645f5050Syouri     */
1328645f5050Syouri    tmp_win->mapped = FALSE;
1329645f5050Syouri
1330645f5050Syouri    SetupFrame (tmp_win, tmp_win->frame_x, tmp_win->frame_y,
1331645f5050Syouri		tmp_win->frame_width, tmp_win->frame_height, -1, True);
1332645f5050Syouri
1333645f5050Syouri    /* wait until the window is iconified and the icon window is mapped
1334645f5050Syouri     * before creating the icon window
1335645f5050Syouri     */
1336645f5050Syouri    tmp_win->icon = (Icon*) 0;
1337645f5050Syouri    tmp_win->iconslist = (name_list*) 0;
1338645f5050Syouri
1339645f5050Syouri    if (!tmp_win->iconmgr)
1340645f5050Syouri    {
1341645f5050Syouri	GrabButtons(tmp_win);
1342645f5050Syouri	GrabKeys(tmp_win);
1343645f5050Syouri    }
1344645f5050Syouri
1345645f5050Syouri    (void) AddIconManager(tmp_win);
1346645f5050Syouri
1347645f5050Syouri    XSaveContext(dpy, tmp_win->w, TwmContext, (XPointer) tmp_win);
1348645f5050Syouri    XSaveContext(dpy, tmp_win->w, ScreenContext, (XPointer) Scr);
1349645f5050Syouri    XSaveContext(dpy, tmp_win->frame, TwmContext, (XPointer) tmp_win);
1350645f5050Syouri    XSaveContext(dpy, tmp_win->frame, ScreenContext, (XPointer) Scr);
1351645f5050Syouri
1352645f5050Syouri    if (tmp_win->title_height)
1353645f5050Syouri    {
1354645f5050Syouri	int i;
1355645f5050Syouri	int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
1356645f5050Syouri
1357645f5050Syouri	XSaveContext(dpy, tmp_win->title_w, TwmContext, (XPointer) tmp_win);
1358645f5050Syouri	XSaveContext(dpy, tmp_win->title_w, ScreenContext, (XPointer) Scr);
1359645f5050Syouri	for (i = 0; i < nb; i++) {
1360645f5050Syouri	    XSaveContext(dpy, tmp_win->titlebuttons[i].window, TwmContext,
1361645f5050Syouri			 (XPointer) tmp_win);
1362645f5050Syouri	    XSaveContext(dpy, tmp_win->titlebuttons[i].window, ScreenContext,
1363645f5050Syouri			 (XPointer) Scr);
1364645f5050Syouri	}
1365645f5050Syouri	if (tmp_win->hilite_wl)
1366645f5050Syouri	{
1367645f5050Syouri	    XSaveContext(dpy, tmp_win->hilite_wl, TwmContext, (XPointer)tmp_win);
1368645f5050Syouri	    XSaveContext(dpy, tmp_win->hilite_wl, ScreenContext, (XPointer)Scr);
1369645f5050Syouri	}
1370645f5050Syouri	if (tmp_win->hilite_wr)
1371645f5050Syouri	{
1372645f5050Syouri	    XSaveContext(dpy, tmp_win->hilite_wr, TwmContext, (XPointer)tmp_win);
1373645f5050Syouri	    XSaveContext(dpy, tmp_win->hilite_wr, ScreenContext, (XPointer)Scr);
1374645f5050Syouri	}
1375645f5050Syouri	if (tmp_win->lolite_wl)
1376645f5050Syouri	{
1377645f5050Syouri	    XSaveContext(dpy, tmp_win->lolite_wl, TwmContext, (XPointer)tmp_win);
1378645f5050Syouri	    XSaveContext(dpy, tmp_win->lolite_wl, ScreenContext, (XPointer)Scr);
1379645f5050Syouri	}
1380645f5050Syouri	if (tmp_win->lolite_wr)
1381645f5050Syouri	{
1382645f5050Syouri	    XSaveContext(dpy, tmp_win->lolite_wr, TwmContext, (XPointer)tmp_win);
1383645f5050Syouri	    XSaveContext(dpy, tmp_win->lolite_wr, ScreenContext, (XPointer)Scr);
1384645f5050Syouri	}
1385645f5050Syouri    }
1386645f5050Syouri
1387645f5050Syouri    XUngrabServer(dpy);
1388645f5050Syouri
1389645f5050Syouri    /* if we were in the middle of a menu activated function, regrab
1390645f5050Syouri     * the pointer
1391645f5050Syouri     */
1392645f5050Syouri    if (RootFunction) ReGrab();
1393645f5050Syouri    if (!iswman) WMapAddWindow (tmp_win);
1394645f5050Syouri    SetPropsIfCaptiveCtwm (tmp_win);
1395645f5050Syouri    savegeometry (tmp_win);
1396645f5050Syouri    return (tmp_win);
1397645f5050Syouri}
1398645f5050Syouri
1399645f5050Syouri/***********************************************************************
1400645f5050Syouri *
1401645f5050Syouri *  Procedure:
1402645f5050Syouri *	GetTwmWindow - finds the TwmWindow structure associated with
1403645f5050Syouri *		a Window (if any), or NULL.
1404645f5050Syouri *
1405645f5050Syouri *  Returned Value:
1406645f5050Syouri *	NULL	- it is not a Window we know about
1407645f5050Syouri *	otherwise- the TwmWindow *
1408645f5050Syouri *
1409645f5050Syouri *  Inputs:
1410645f5050Syouri *	w	- the window to check
1411645f5050Syouri *
1412645f5050Syouri *  Note:
1413645f5050Syouri *  	This is a relatively cheap function since it does not involve
1414645f5050Syouri *  	communication with the server. Probably faster than walking
1415645f5050Syouri *  	the list of TwmWindows, since the lookup is by a hash table.
1416645f5050Syouri *
1417645f5050Syouri ***********************************************************************
1418645f5050Syouri */
1419645f5050SyouriTwmWindow *GetTwmWindow(Window w)
1420645f5050Syouri{
1421645f5050Syouri    TwmWindow *twmwin;
1422645f5050Syouri    int stat;
1423645f5050Syouri
1424645f5050Syouri    stat = XFindContext(dpy, w, TwmContext, (XPointer *)&twmwin);
1425645f5050Syouri    if (stat == XCNOENT)
1426645f5050Syouri	twmwin = NULL;
1427645f5050Syouri
1428645f5050Syouri    return twmwin;
1429645f5050Syouri}
1430645f5050Syouri
1431645f5050Syouri/***********************************************************************
1432645f5050Syouri *
1433645f5050Syouri *  Procedure:
1434645f5050Syouri *	MappedNotOverride - checks to see if we should really
1435645f5050Syouri *		put a twm frame on the window
1436645f5050Syouri *
1437645f5050Syouri *  Returned Value:
1438645f5050Syouri *	TRUE	- go ahead and frame the window
1439645f5050Syouri *	FALSE	- don't frame the window
1440645f5050Syouri *
1441645f5050Syouri *  Inputs:
1442645f5050Syouri *	w	- the window to check
1443645f5050Syouri *
1444645f5050Syouri ***********************************************************************
1445645f5050Syouri */
1446645f5050Syouri
1447645f5050Syouriint MappedNotOverride(Window w)
1448645f5050Syouri{
1449645f5050Syouri    XWindowAttributes wa;
1450645f5050Syouri
1451645f5050Syouri    XGetWindowAttributes(dpy, w, &wa);
1452645f5050Syouri    return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
1453645f5050Syouri}
1454645f5050Syouri
1455645f5050Syouri
1456645f5050Syouri/***********************************************************************
1457645f5050Syouri *
1458645f5050Syouri *  Procedure:
1459645f5050Syouri *      AddDefaultBindings - attach default bindings so that naive users
1460645f5050Syouri *      don't get messed up if they provide a minimal twmrc.
1461645f5050Syouri */
1462645f5050Syouristatic void do_add_binding (int button, int context, int modifier, int func)
1463645f5050Syouri{
1464645f5050Syouri    AddFuncButton (button, context, modifier, func, NULL, NULL);
1465645f5050Syouri}
1466645f5050Syouri
1467645f5050Syourivoid AddDefaultBindings (void)
1468645f5050Syouri{
1469645f5050Syouri#define NoModifierMask 0
1470645f5050Syouri
1471645f5050Syouri    do_add_binding (Button1, C_TITLE, NoModifierMask, F_MOVE);
1472645f5050Syouri    do_add_binding (Button1, C_ICON, NoModifierMask, F_ICONIFY);
1473645f5050Syouri    do_add_binding (Button1, C_ICONMGR, NoModifierMask, F_ICONIFY);
1474645f5050Syouri
1475645f5050Syouri    do_add_binding (Button2, C_TITLE, NoModifierMask, F_RAISELOWER);
1476645f5050Syouri    do_add_binding (Button2, C_ICON, NoModifierMask, F_ICONIFY);
1477645f5050Syouri    do_add_binding (Button2, C_ICONMGR, NoModifierMask, F_ICONIFY);
1478645f5050Syouri
1479645f5050Syouri#undef NoModifierMask
1480645f5050Syouri}
1481645f5050Syouri
1482645f5050Syouri
1483645f5050Syouri
1484645f5050Syouri
1485645f5050Syouri/***********************************************************************
1486645f5050Syouri *
1487645f5050Syouri *  Procedure:
1488645f5050Syouri *	GrabButtons - grab needed buttons for the window
1489645f5050Syouri *
1490645f5050Syouri *  Inputs:
1491645f5050Syouri *	tmp_win - the twm window structure to use
1492645f5050Syouri *
1493645f5050Syouri ***********************************************************************
1494645f5050Syouri */
1495645f5050Syouri
1496645f5050Syouri#define AltMask (Alt1Mask | Alt2Mask | Alt3Mask | Alt4Mask | Alt5Mask)
1497645f5050Syouri#define grabbutton(button, modifier, window, pointer_mode) \
1498645f5050Syouri	XGrabButton (dpy, button, modifier, window,  \
1499645f5050Syouri		True, ButtonPressMask | ButtonReleaseMask, \
1500645f5050Syouri		pointer_mode, GrabModeAsync, None,  \
1501645f5050Syouri		Scr->FrameCursor);
1502645f5050Syouri
1503645f5050Syourivoid GrabButtons(TwmWindow *tmp_win)
1504645f5050Syouri{
1505645f5050Syouri    FuncButton *tmp;
1506645f5050Syouri    int i;
1507645f5050Syouri    unsigned int ModifierMask[8] = { ShiftMask, ControlMask, LockMask,
1508645f5050Syouri				     Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask,
1509645f5050Syouri				     Mod5Mask };
1510645f5050Syouri
1511645f5050Syouri    for (tmp = Scr->FuncButtonRoot.next; tmp != NULL; tmp = tmp->next) {
1512645f5050Syouri	if ((tmp->cont != C_WINDOW) || (tmp->func == 0)) continue;
1513645f5050Syouri	grabbutton (tmp->num, tmp->mods, tmp_win->frame, GrabModeAsync);
1514645f5050Syouri
1515645f5050Syouri	if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) {
1516645f5050Syouri	    grabbutton (tmp->num, tmp->mods | LockMask, tmp_win->frame, GrabModeAsync);
1517645f5050Syouri	}
1518645f5050Syouri	for (i = 0 ; i < 8 ; i++) {
1519645f5050Syouri	    if ((Scr->IgnoreModifier & ModifierMask [i]) && !(tmp->mods & ModifierMask [i]))
1520645f5050Syouri		grabbutton (tmp->num, tmp->mods | ModifierMask [i],
1521645f5050Syouri			  tmp_win->frame, GrabModeAsync);
1522645f5050Syouri	}
1523645f5050Syouri    }
1524645f5050Syouri    if (Scr->ClickToFocus) {
1525645f5050Syouri	grabbutton (AnyButton, None, tmp_win->w, GrabModeSync);
1526645f5050Syouri	for (i = 0 ; i < 8 ; i++) {
1527645f5050Syouri	    grabbutton (AnyButton, ModifierMask [i], tmp_win->w, GrabModeSync);
1528645f5050Syouri	}
1529645f5050Syouri    } else
1530645f5050Syouri    if (Scr->RaiseOnClick) {
1531645f5050Syouri	grabbutton (Scr->RaiseOnClickButton, None, tmp_win->w, GrabModeSync);
1532645f5050Syouri	for (i = 0 ; i < 8 ; i++) {
1533645f5050Syouri	    grabbutton (Scr->RaiseOnClickButton,
1534645f5050Syouri			ModifierMask [i], tmp_win->w, GrabModeSync);
1535645f5050Syouri	}
1536645f5050Syouri    }
1537645f5050Syouri}
1538645f5050Syouri
1539645f5050Syouri/***********************************************************************
1540645f5050Syouri *
1541645f5050Syouri *  Procedure:
1542645f5050Syouri *	GrabKeys - grab needed keys for the window
1543645f5050Syouri *
1544645f5050Syouri *  Inputs:
1545645f5050Syouri *	tmp_win - the twm window structure to use
1546645f5050Syouri *
1547645f5050Syouri ***********************************************************************
1548645f5050Syouri */
1549645f5050Syouri
1550645f5050Syouri#define MAX_KEYCODE 256
1551645f5050Syouri#define grabkey(funckey, modifier, window) \
1552645f5050Syouri	XGrabKey(dpy, funckey->keycode, funckey->mods | modifier, window, True, \
1553645f5050Syouri		GrabModeAsync, GrabModeAsync);
1554645f5050Syouri#define ungrabkey(funckey, modifier, window) \
1555645f5050Syouri	XUngrabKey (dpy, funckey->keycode, funckey->mods | modifier, window);
1556645f5050Syouri
1557645f5050Syourivoid GrabKeys(TwmWindow *tmp_win)
1558645f5050Syouri{
1559645f5050Syouri    FuncKey *tmp;
1560645f5050Syouri    IconMgr *p;
1561645f5050Syouri    int i;
1562645f5050Syouri    unsigned int ModifierMask[8] = { ShiftMask, ControlMask, LockMask,
1563645f5050Syouri				     Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask,
1564645f5050Syouri				     Mod5Mask };
1565645f5050Syouri
1566645f5050Syouri    for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
1567645f5050Syouri    {
1568645f5050Syouri	switch (tmp->cont)
1569645f5050Syouri	{
1570645f5050Syouri	case C_WINDOW:
1571645f5050Syouri	/* case C_WORKSPACE: */
1572645f5050Syouri	    if (tmp->mods & AltMask) break;
1573645f5050Syouri	    grabkey (tmp, 0, tmp_win->w);
1574645f5050Syouri	    if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask))
1575645f5050Syouri		grabkey (tmp, LockMask, tmp_win->w);
1576645f5050Syouri	    for (i = 0 ; i < 8 ; i++) {
1577645f5050Syouri		if ((Scr->IgnoreModifier & ModifierMask [i]) &&
1578645f5050Syouri		    !(tmp->mods & ModifierMask [i]))
1579645f5050Syouri		  grabkey (tmp, ModifierMask [i], tmp_win->w);
1580645f5050Syouri	    }
1581645f5050Syouri	    break;
1582645f5050Syouri
1583645f5050Syouri	case C_ICON:
1584645f5050Syouri	    if (!tmp_win->icon || tmp_win->icon->w) break;
1585645f5050Syouri	    grabkey (tmp, 0, tmp_win->icon->w);
1586645f5050Syouri	    if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask))
1587645f5050Syouri		grabkey (tmp, LockMask, tmp_win->icon->w);
1588645f5050Syouri	    for (i = 0 ; i < 8 ; i++) {
1589645f5050Syouri		if ((Scr->IgnoreModifier & ModifierMask [i]) &&
1590645f5050Syouri		    !(tmp->mods & ModifierMask [i]))
1591645f5050Syouri		    grabkey (tmp, ModifierMask [i], tmp_win->icon->w);
1592645f5050Syouri	    }
1593645f5050Syouri	    break;
1594645f5050Syouri
1595645f5050Syouri	case C_TITLE:
1596645f5050Syouri	    if (!tmp_win->title_w) break;
1597645f5050Syouri	    grabkey (tmp, 0, tmp_win->title_w);
1598645f5050Syouri	    if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask))
1599645f5050Syouri		grabkey (tmp, LockMask, tmp_win->title_w);
1600645f5050Syouri	    for (i = 0 ; i < 8 ; i++) {
1601645f5050Syouri		if ((Scr->IgnoreModifier & ModifierMask [i]) &&
1602645f5050Syouri		    !(tmp->mods & ModifierMask [i]))
1603645f5050Syouri		    grabkey (tmp, ModifierMask [i], tmp_win->title_w);
1604645f5050Syouri	    }
1605645f5050Syouri	    break;
1606645f5050Syouri
1607645f5050Syouri	case C_NAME:
1608645f5050Syouri	    grabkey (tmp, 0, tmp_win->w);
1609645f5050Syouri	    if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) {
1610645f5050Syouri		grabkey (tmp, LockMask, tmp_win->w);
1611645f5050Syouri	    }
1612645f5050Syouri	    for (i = 0 ; i < 8 ; i++) {
1613645f5050Syouri		if ((Scr->IgnoreModifier & ModifierMask [i]) &&
1614645f5050Syouri		    !(tmp->mods & ModifierMask [i]))
1615645f5050Syouri		    grabkey (tmp, ModifierMask [i], tmp_win->w);
1616645f5050Syouri	    }
1617645f5050Syouri	    if (tmp_win->icon && tmp_win->icon->w) {
1618645f5050Syouri		grabkey (tmp, 0, tmp_win->icon->w);
1619645f5050Syouri		if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask))
1620645f5050Syouri		    grabkey (tmp, LockMask, tmp_win->icon->w);
1621645f5050Syouri		for (i = 0 ; i < 8 ; i++) {
1622645f5050Syouri		    if ((Scr->IgnoreModifier & ModifierMask [i]) &&
1623645f5050Syouri			!(tmp->mods & ModifierMask [i]))
1624645f5050Syouri			grabkey (tmp, ModifierMask [i], tmp_win->icon->w);
1625645f5050Syouri		}
1626645f5050Syouri	    }
1627645f5050Syouri	    if (tmp_win->title_w) {
1628645f5050Syouri		grabkey (tmp, 0, tmp_win->title_w);
1629645f5050Syouri		if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask))
1630645f5050Syouri		    grabkey (tmp, LockMask, tmp_win->title_w);
1631645f5050Syouri		for (i = 0 ; i < 8 ; i++) {
1632645f5050Syouri		    if ((Scr->IgnoreModifier & ModifierMask [i]) &&
1633645f5050Syouri			!(tmp->mods & ModifierMask [i]))
1634645f5050Syouri			grabkey (tmp, ModifierMask [i], tmp_win->title_w);
1635645f5050Syouri		}
1636645f5050Syouri	    }
1637645f5050Syouri	    break;
1638645f5050Syouri	/*
1639645f5050Syouri	case C_ROOT:
1640645f5050Syouri	    XGrabKey(dpy, tmp->keycode, tmp->mods, Scr->Root, True,
1641645f5050Syouri		GrabModeAsync, GrabModeAsync);
1642645f5050Syouri	    break;
1643645f5050Syouri	*/
1644645f5050Syouri	}
1645645f5050Syouri    }
1646645f5050Syouri    for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
1647645f5050Syouri    {
1648645f5050Syouri	if (tmp->cont == C_ICONMGR && !Scr->NoIconManagers)
1649645f5050Syouri	{
1650645f5050Syouri	    for (p = Scr->iconmgr; p != NULL; p = p->next) {
1651645f5050Syouri		ungrabkey (tmp, 0, p->twm_win->w);
1652645f5050Syouri		if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask))
1653645f5050Syouri		    ungrabkey (tmp, LockMask, p->twm_win->w);
1654645f5050Syouri		for (i = 0 ; i < 8 ; i++) {
1655645f5050Syouri		    if ((Scr->IgnoreModifier & ModifierMask [i]) &&
1656645f5050Syouri			!(tmp->mods & ModifierMask [i]))
1657645f5050Syouri			ungrabkey (tmp, ModifierMask [i], p->twm_win->w);
1658645f5050Syouri		}
1659645f5050Syouri	    }
1660645f5050Syouri	}
1661645f5050Syouri    }
1662645f5050Syouri}
1663645f5050Syouri
1664645f5050Syourivoid ComputeCommonTitleOffsets (void)
1665645f5050Syouri{
1666645f5050Syouri    int buttonwidth = (Scr->TBInfo.width + Scr->TBInfo.pad);
1667645f5050Syouri
1668645f5050Syouri    Scr->TBInfo.leftx = Scr->TBInfo.rightoff = Scr->FramePadding;
1669645f5050Syouri    if (Scr->TBInfo.nleft  > 0) Scr->TBInfo.leftx    += Scr->ButtonIndent;
1670645f5050Syouri    if (Scr->TBInfo.nright > 0) Scr->TBInfo.rightoff += (Scr->ButtonIndent +
1671645f5050Syouri			       (Scr->TBInfo.nright * buttonwidth) -
1672645f5050Syouri				Scr->TBInfo.pad);
1673645f5050Syouri
1674645f5050Syouri    Scr->TBInfo.titlex = (Scr->TBInfo.leftx +
1675645f5050Syouri				(Scr->TBInfo.nleft * buttonwidth) -
1676645f5050Syouri				Scr->TBInfo.pad +
1677645f5050Syouri				Scr->TitlePadding);
1678645f5050Syouri}
1679645f5050Syouri
1680645f5050Syouristatic void CreateHighlightWindows (TwmWindow *tmp_win)
1681645f5050Syouri{
1682645f5050Syouri    XSetWindowAttributes attributes;	/* attributes for create windows */
1683645f5050Syouri    GC gc;
1684645f5050Syouri    XGCValues gcv;
1685645f5050Syouri    unsigned long valuemask;
1686645f5050Syouri    int h = (Scr->TitleHeight - 2 * Scr->FramePadding);
1687645f5050Syouri    int y = Scr->FramePadding;
1688645f5050Syouri
1689645f5050Syouri    if (! tmp_win->titlehighlight) {
1690645f5050Syouri	tmp_win->hilite_wl = (Window) 0;
1691645f5050Syouri	tmp_win->hilite_wr = (Window) 0;
1692645f5050Syouri	return;
1693645f5050Syouri    }
1694645f5050Syouri    /*
1695645f5050Syouri     * If a special highlight pixmap was given, use that.  Otherwise,
1696645f5050Syouri     * use a nice, even gray pattern.  The old horizontal lines look really
1697645f5050Syouri     * awful on interlaced monitors (as well as resembling other looks a
1698645f5050Syouri     * little bit too closely), but can be used by putting
1699645f5050Syouri     *
1700645f5050Syouri     *                 Pixmaps { TitleHighlight "hline2" }
1701645f5050Syouri     *
1702645f5050Syouri     * (or whatever the horizontal line bitmap is named) in the startup
1703645f5050Syouri     * file.  If all else fails, use the foreground color to look like a
1704645f5050Syouri     * solid line.
1705645f5050Syouri     */
1706645f5050Syouri
1707645f5050Syouri    if (! tmp_win->HiliteImage) {
1708645f5050Syouri	if (Scr->HighlightPixmapName) {
1709645f5050Syouri	    tmp_win->HiliteImage = GetImage (Scr->HighlightPixmapName, tmp_win->title);
1710645f5050Syouri	}
1711645f5050Syouri    }
1712645f5050Syouri    if (! tmp_win->HiliteImage) {
1713645f5050Syouri	Pixmap pm = None;
1714645f5050Syouri	Pixmap bm = None;
1715645f5050Syouri
1716645f5050Syouri	if (Scr->use3Dtitles && (Scr->Monochrome != COLOR))
1717645f5050Syouri	    bm = XCreateBitmapFromData (dpy, tmp_win->title_w,
1718645f5050Syouri					(char*)black_bits, gray_width, gray_height);
1719645f5050Syouri	else
1720645f5050Syouri	    bm = XCreateBitmapFromData (dpy, tmp_win->title_w,
1721645f5050Syouri					(char*)gray_bits, gray_width, gray_height);
1722645f5050Syouri
1723645f5050Syouri	pm = XCreatePixmap (dpy, tmp_win->title_w, gray_width, gray_height, Scr->d_depth);
1724645f5050Syouri	gcv.foreground = tmp_win->title.fore;
1725645f5050Syouri	gcv.background = tmp_win->title.back;
1726645f5050Syouri	gcv.graphics_exposures = False;
1727645f5050Syouri	gc = XCreateGC (dpy, pm, (GCForeground|GCBackground|GCGraphicsExposures), &gcv);
1728645f5050Syouri	if (gc) {
1729645f5050Syouri	    XCopyPlane (dpy, bm, pm, gc, 0, 0, gray_width, gray_height, 0, 0, 1);
1730645f5050Syouri	    tmp_win->HiliteImage = (Image*) malloc (sizeof (struct _Image));
1731645f5050Syouri	    tmp_win->HiliteImage->pixmap = pm;
1732645f5050Syouri	    tmp_win->HiliteImage->width  = gray_width;
1733645f5050Syouri	    tmp_win->HiliteImage->height = gray_height;
1734645f5050Syouri	    tmp_win->HiliteImage->mask   = None;
1735645f5050Syouri	    tmp_win->HiliteImage->next   = None;
1736645f5050Syouri	    XFreeGC (dpy, gc);
1737645f5050Syouri	} else {
1738645f5050Syouri	    XFreePixmap (dpy, pm);
1739645f5050Syouri	    pm = None;
1740645f5050Syouri	}
1741645f5050Syouri	XFreePixmap (dpy, bm);
1742645f5050Syouri    }
1743645f5050Syouri    if (tmp_win->HiliteImage) {
1744645f5050Syouri	valuemask = CWBackPixmap;
1745645f5050Syouri	attributes.background_pixmap = tmp_win->HiliteImage->pixmap;
1746645f5050Syouri    } else {
1747645f5050Syouri	valuemask = CWBackPixel;
1748645f5050Syouri	attributes.background_pixel = tmp_win->title.fore;
1749645f5050Syouri    }
1750645f5050Syouri
1751645f5050Syouri    if (Scr->use3Dtitles) {
1752645f5050Syouri	y += Scr->TitleShadowDepth;
1753645f5050Syouri	h -= 2 * Scr->TitleShadowDepth;
1754645f5050Syouri    }
1755645f5050Syouri    if (Scr->TitleJustification == J_LEFT)
1756645f5050Syouri	tmp_win->hilite_wl = (Window) 0;
1757645f5050Syouri    else
1758645f5050Syouri	tmp_win->hilite_wl = XCreateWindow (dpy, tmp_win->title_w, 0, y,
1759645f5050Syouri		       (unsigned int) Scr->TBInfo.width, (unsigned int) h,
1760645f5050Syouri		       (unsigned int) 0, Scr->d_depth, (unsigned int) CopyFromParent,
1761645f5050Syouri		       Scr->d_visual, valuemask, &attributes);
1762645f5050Syouri
1763645f5050Syouri    if (Scr->TitleJustification == J_RIGHT)
1764645f5050Syouri	tmp_win->hilite_wr = (Window) 0;
1765645f5050Syouri    else
1766645f5050Syouri	tmp_win->hilite_wr = XCreateWindow (dpy, tmp_win->title_w, 0, y,
1767645f5050Syouri		       (unsigned int) Scr->TBInfo.width, (unsigned int) h,
1768645f5050Syouri		       (unsigned int) 0,  Scr->d_depth, (unsigned int) CopyFromParent,
1769645f5050Syouri		       Scr->d_visual, valuemask, &attributes);
1770645f5050Syouri}
1771645f5050Syouri
1772645f5050Syourivoid DeleteHighlightWindows(TwmWindow *tmp_win)
1773645f5050Syouri{
1774645f5050Syouri    if (tmp_win->HiliteImage) {
1775645f5050Syouri	if (Scr->HighlightPixmapName) {
1776645f5050Syouri	    /*
1777645f5050Syouri	     * Image obtained from GetImage(): it is in a cache
1778645f5050Syouri	     * so we don't need to free it. There will not be multiple
1779645f5050Syouri	     * copies if the same xpm:foo image is requested again.
1780645f5050Syouri	     */
1781645f5050Syouri	} else {
1782645f5050Syouri	    XFreePixmap (dpy, tmp_win->HiliteImage->pixmap);
1783645f5050Syouri	    free(tmp_win->HiliteImage);
1784645f5050Syouri	}
1785645f5050Syouri	tmp_win->HiliteImage = NULL;
1786645f5050Syouri    }
1787645f5050Syouri}
1788645f5050Syouri
1789645f5050Syouristatic void CreateLowlightWindows (TwmWindow *tmp_win)
1790645f5050Syouri{
1791645f5050Syouri    XSetWindowAttributes attributes;    /* attributes for create windows */
1792645f5050Syouri    unsigned long valuemask;
1793645f5050Syouri    int h = (Scr->TitleHeight - 2 * Scr->FramePadding);
1794645f5050Syouri    int y = Scr->FramePadding;
1795645f5050Syouri    ColorPair cp;
1796645f5050Syouri
1797645f5050Syouri    if (!Scr->UseSunkTitlePixmap || ! tmp_win->titlehighlight) {
1798645f5050Syouri	tmp_win->lolite_wl = (Window) 0;
1799645f5050Syouri	tmp_win->lolite_wr = (Window) 0;
1800645f5050Syouri	return;
1801645f5050Syouri    }
1802645f5050Syouri    /*
1803645f5050Syouri     * If a special highlight pixmap was given, use that.  Otherwise,
1804645f5050Syouri     * use a nice, even gray pattern.  The old horizontal lines look really
1805645f5050Syouri     * awful on interlaced monitors (as well as resembling other looks a
1806645f5050Syouri     * little bit too closely), but can be used by putting
1807645f5050Syouri     *
1808645f5050Syouri     *                 Pixmaps { TitleHighlight "hline2" }
1809645f5050Syouri     *
1810645f5050Syouri     * (or whatever the horizontal line bitmap is named) in the startup
1811645f5050Syouri     * file.  If all else fails, use the foreground color to look like a
1812645f5050Syouri     * solid line.
1813645f5050Syouri     */
1814645f5050Syouri
1815645f5050Syouri    if (! tmp_win->LoliteImage) {
1816645f5050Syouri        if (Scr->HighlightPixmapName) {
1817645f5050Syouri            cp = tmp_win->title;
1818645f5050Syouri            cp.shadc = tmp_win->title.shadd;
1819645f5050Syouri            cp.shadd = tmp_win->title.shadc;
1820645f5050Syouri            tmp_win->LoliteImage = GetImage (Scr->HighlightPixmapName, cp);
1821645f5050Syouri        }
1822645f5050Syouri    }
1823645f5050Syouri    if (tmp_win->LoliteImage) {
1824645f5050Syouri        valuemask = CWBackPixmap;
1825645f5050Syouri        attributes.background_pixmap = tmp_win->LoliteImage->pixmap;
1826645f5050Syouri    } else {
1827645f5050Syouri        valuemask = CWBackPixel;
1828645f5050Syouri        attributes.background_pixel = tmp_win->title.fore;
1829645f5050Syouri    }
1830645f5050Syouri
1831645f5050Syouri    if (Scr->use3Dtitles) {
1832645f5050Syouri        y += 2;
1833645f5050Syouri        h -= 4;
1834645f5050Syouri    }
1835645f5050Syouri    if (Scr->TitleJustification == J_LEFT)
1836645f5050Syouri        tmp_win->lolite_wl = (Window) 0;
1837645f5050Syouri    else
1838645f5050Syouri        tmp_win->lolite_wl = XCreateWindow (dpy, tmp_win->title_w, 0, y,
1839645f5050Syouri                       (unsigned int) Scr->TBInfo.width, (unsigned int) h,
1840645f5050Syouri                       (unsigned int) 0, Scr->d_depth, (unsigned int) CopyFromParent,
1841645f5050Syouri                       Scr->d_visual, valuemask, &attributes);
1842645f5050Syouri
1843645f5050Syouri    if (Scr->TitleJustification == J_RIGHT)
1844645f5050Syouri        tmp_win->lolite_wr = (Window) 0;
1845645f5050Syouri    else
1846645f5050Syouri        tmp_win->lolite_wr = XCreateWindow (dpy, tmp_win->title_w, 0, y,
1847645f5050Syouri                       (unsigned int) Scr->TBInfo.width, (unsigned int) h,
1848645f5050Syouri                       (unsigned int) 0,  Scr->d_depth, (unsigned int) CopyFromParent,
1849645f5050Syouri                       Scr->d_visual, valuemask, &attributes);
1850645f5050Syouri}
1851645f5050Syouri
1852645f5050Syouri
1853645f5050Syourivoid ComputeWindowTitleOffsets (TwmWindow *tmp_win, unsigned int width,
1854645f5050Syouri				Bool squeeze)
1855645f5050Syouri{
1856645f5050Syouri    int titlew = width - Scr->TBInfo.titlex - Scr->TBInfo.rightoff;
1857645f5050Syouri
1858645f5050Syouri    switch (Scr->TitleJustification) {
1859645f5050Syouri	case J_LEFT :
1860645f5050Syouri	    tmp_win->name_x = Scr->TBInfo.titlex;
1861645f5050Syouri	    if (Scr->use3Dtitles) tmp_win->name_x += Scr->TitleShadowDepth + 2;
1862645f5050Syouri	    break;
1863645f5050Syouri	case J_CENTER :
1864645f5050Syouri	    tmp_win->name_x = Scr->TBInfo.titlex + (titlew - tmp_win->name_width) / 2;
1865645f5050Syouri	    break;
1866645f5050Syouri	case J_RIGHT :
1867645f5050Syouri	    tmp_win->name_x = Scr->TBInfo.titlex + titlew - tmp_win->name_width;
1868645f5050Syouri	    if (Scr->use3Dtitles) tmp_win->name_x -= Scr->TitleShadowDepth - 2;
1869645f5050Syouri	    break;
1870645f5050Syouri    }
1871645f5050Syouri    if (Scr->use3Dtitles) {
1872645f5050Syouri	if (tmp_win->name_x < (Scr->TBInfo.titlex + 2 * Scr->TitleShadowDepth))
1873645f5050Syouri		tmp_win->name_x = Scr->TBInfo.titlex + 2 * Scr->TitleShadowDepth;
1874645f5050Syouri    }
1875645f5050Syouri    else
1876645f5050Syouri    if (tmp_win->name_x < Scr->TBInfo.titlex) {
1877645f5050Syouri	tmp_win->name_x = Scr->TBInfo.titlex;
1878645f5050Syouri    }
1879645f5050Syouri    tmp_win->highlightxl = Scr->TBInfo.titlex;
1880645f5050Syouri    tmp_win->highlightxr = tmp_win->name_x + tmp_win->name_width + 2;
1881645f5050Syouri
1882645f5050Syouri    if (Scr->use3Dtitles) {
1883645f5050Syouri	tmp_win->highlightxl += Scr->TitleShadowDepth;
1884645f5050Syouri    }
1885645f5050Syouri    if (tmp_win->hilite_wr || Scr->TBInfo.nright > 0)
1886645f5050Syouri      tmp_win->highlightxr += Scr->TitlePadding;
1887645f5050Syouri    tmp_win->rightx = width - Scr->TBInfo.rightoff;
1888645f5050Syouri    if (squeeze && tmp_win->squeeze_info && !tmp_win->squeezed) {
1889645f5050Syouri	int rx = (tmp_win->highlightxr +
1890645f5050Syouri		  (tmp_win->hilite_wr
1891645f5050Syouri		    ? Scr->TBInfo.width * 2 : 0) +
1892645f5050Syouri		  (Scr->TBInfo.nright > 0 ? Scr->TitlePadding : 0) +
1893645f5050Syouri		  Scr->FramePadding);
1894645f5050Syouri	if (rx < tmp_win->rightx) tmp_win->rightx = rx;
1895645f5050Syouri    }
1896645f5050Syouri    return;
1897645f5050Syouri}
1898645f5050Syouri
1899645f5050Syouri
1900645f5050Syouri/*
1901645f5050Syouri * ComputeTitleLocation - calculate the position of the title window; we need
1902645f5050Syouri * to take the frame_bw into account since we want (0,0) of the title window
1903645f5050Syouri * to line up with (0,0) of the frame window.
1904645f5050Syouri */
1905645f5050Syourivoid ComputeTitleLocation (register TwmWindow *tmp)
1906645f5050Syouri{
1907645f5050Syouri    tmp->title_x = tmp->frame_bw3D - tmp->frame_bw;
1908645f5050Syouri    tmp->title_y = tmp->frame_bw3D - tmp->frame_bw;
1909645f5050Syouri
1910645f5050Syouri    if (tmp->squeeze_info && !tmp->squeezed) {
1911645f5050Syouri	register SqueezeInfo *si = tmp->squeeze_info;
1912645f5050Syouri	int basex;
1913645f5050Syouri	int maxwidth = tmp->frame_width;
1914645f5050Syouri	int tw = tmp->title_width + 2 * tmp->frame_bw3D;
1915645f5050Syouri
1916645f5050Syouri	/*
1917645f5050Syouri	 * figure label base from squeeze info (justification fraction)
1918645f5050Syouri	 */
1919645f5050Syouri	if (si->denom == 0) {		/* num is pixel based */
1920645f5050Syouri	    basex = si->num;
1921645f5050Syouri	} else {			/* num/denom is fraction */
1922645f5050Syouri	    basex = ((si->num * maxwidth) / si->denom);
1923645f5050Syouri	}
1924645f5050Syouri	if (si->num < 0)
1925645f5050Syouri	    basex += maxwidth;
1926645f5050Syouri
1927645f5050Syouri	/*
1928645f5050Syouri	 * adjust for left (nop), center, right justify and clip
1929645f5050Syouri	 */
1930645f5050Syouri	switch (si->justify) {
1931645f5050Syouri	  case J_CENTER:
1932645f5050Syouri	    basex -= tw / 2;
1933645f5050Syouri	    break;
1934645f5050Syouri	  case J_RIGHT:
1935645f5050Syouri	    basex -= tw - 1;
1936645f5050Syouri	    break;
1937645f5050Syouri	}
1938645f5050Syouri	if (basex > maxwidth - tw)
1939645f5050Syouri	  basex = maxwidth - tw;
1940645f5050Syouri	if (basex < 0) basex = 0;
1941645f5050Syouri
1942645f5050Syouri	tmp->title_x = basex - tmp->frame_bw + tmp->frame_bw3D;
1943645f5050Syouri    }
1944645f5050Syouri}
1945645f5050Syouri
1946645f5050Syouri
1947645f5050Syouristatic void CreateWindowTitlebarButtons (TwmWindow *tmp_win)
1948645f5050Syouri{
1949645f5050Syouri    unsigned long valuemask;		/* mask for create windows */
1950645f5050Syouri    XSetWindowAttributes attributes;	/* attributes for create windows */
1951645f5050Syouri    int leftx, rightx, y;
1952645f5050Syouri    TitleButton *tb;
1953645f5050Syouri    int nb;
1954645f5050Syouri
1955645f5050Syouri    if (tmp_win->title_height == 0)
1956645f5050Syouri    {
1957645f5050Syouri	tmp_win->hilite_wl = (Window) 0;
1958645f5050Syouri	tmp_win->hilite_wr = (Window) 0;
1959645f5050Syouri	tmp_win->lolite_wl = (Window) 0;
1960645f5050Syouri	tmp_win->lolite_wr = (Window) 0;
1961645f5050Syouri	return;
1962645f5050Syouri    }
1963645f5050Syouri
1964645f5050Syouri
1965645f5050Syouri    /*
1966645f5050Syouri     * create the title bar windows; let the event handler deal with painting
1967645f5050Syouri     * so that we don't have to spend two pixmaps (or deal with hashing)
1968645f5050Syouri     */
1969645f5050Syouri    ComputeWindowTitleOffsets (tmp_win, tmp_win->attr.width, False);
1970645f5050Syouri
1971645f5050Syouri    leftx = y = Scr->TBInfo.leftx;
1972645f5050Syouri    rightx = tmp_win->rightx;
1973645f5050Syouri
1974645f5050Syouri    attributes.win_gravity = NorthWestGravity;
1975645f5050Syouri    attributes.background_pixel = tmp_win->title.back;
1976645f5050Syouri    attributes.border_pixel = tmp_win->title.fore;
1977645f5050Syouri    attributes.event_mask = (ButtonPressMask | ButtonReleaseMask |
1978645f5050Syouri			     ExposureMask);
1979645f5050Syouri    attributes.cursor = Scr->ButtonCursor;
1980645f5050Syouri    valuemask = (CWWinGravity | CWBackPixel | CWBorderPixel | CWEventMask |
1981645f5050Syouri		 CWCursor);
1982645f5050Syouri
1983645f5050Syouri    tmp_win->titlebuttons = NULL;
1984645f5050Syouri    nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
1985645f5050Syouri    if (nb > 0) {
1986645f5050Syouri	tmp_win->titlebuttons = (TBWindow *) malloc (nb * sizeof(TBWindow));
1987645f5050Syouri	if (!tmp_win->titlebuttons) {
1988645f5050Syouri	    fprintf (stderr, "%s:  unable to allocate %d titlebuttons\n",
1989645f5050Syouri		     ProgramName, nb);
1990645f5050Syouri	} else {
1991645f5050Syouri	    TBWindow *tbw;
1992645f5050Syouri	    int boxwidth = (Scr->TBInfo.width + Scr->TBInfo.pad);
1993645f5050Syouri	    unsigned int h = (Scr->TBInfo.width - Scr->TBInfo.border * 2);
1994645f5050Syouri
1995645f5050Syouri	    for (tb = Scr->TBInfo.head, tbw = tmp_win->titlebuttons; tb;
1996645f5050Syouri		 tb = tb->next, tbw++) {
1997645f5050Syouri		int x;
1998645f5050Syouri		if (tb->rightside) {
1999645f5050Syouri		    x = rightx;
2000645f5050Syouri		    rightx += boxwidth;
2001645f5050Syouri		    attributes.win_gravity = NorthEastGravity;
2002645f5050Syouri		} else {
2003645f5050Syouri		    x = leftx;
2004645f5050Syouri		    leftx += boxwidth;
2005645f5050Syouri		    attributes.win_gravity = NorthWestGravity;
2006645f5050Syouri		}
2007645f5050Syouri		tbw->window = XCreateWindow (dpy, tmp_win->title_w, x, y, h, h,
2008645f5050Syouri					     (unsigned int) Scr->TBInfo.border,
2009645f5050Syouri					     0, (unsigned int) CopyFromParent,
2010645f5050Syouri					     (Visual *) CopyFromParent,
2011645f5050Syouri					     valuemask, &attributes);
2012645f5050Syouri		tbw->image = GetImage (tb->name, tmp_win->title);
2013645f5050Syouri		if (! tbw->image) {
2014645f5050Syouri		    tbw->image = GetImage (TBPM_QUESTION, tmp_win->title);
2015645f5050Syouri		    if (! tbw->image) {		/* cannot happen (see util.c) */
2016645f5050Syouri			fprintf (stderr, "%s:  unable to add titlebar button \"%s\"\n",
2017645f5050Syouri				 ProgramName, tb->name);
2018645f5050Syouri		    }
2019645f5050Syouri		}
2020645f5050Syouri		tbw->info = tb;
2021645f5050Syouri	    }
2022645f5050Syouri	}
2023645f5050Syouri    }
2024645f5050Syouri
2025645f5050Syouri    CreateHighlightWindows (tmp_win);
2026645f5050Syouri    CreateLowlightWindows  (tmp_win);
2027645f5050Syouri    XMapSubwindows(dpy, tmp_win->title_w);
2028645f5050Syouri    if (tmp_win->hilite_wl) XUnmapWindow(dpy, tmp_win->hilite_wl);
2029645f5050Syouri    if (tmp_win->hilite_wr) XUnmapWindow(dpy, tmp_win->hilite_wr);
2030645f5050Syouri    if (tmp_win->lolite_wl) XMapWindow(dpy, tmp_win->lolite_wl);
2031645f5050Syouri    if (tmp_win->lolite_wr) XMapWindow(dpy, tmp_win->lolite_wr);
2032645f5050Syouri    return;
2033645f5050Syouri}
2034645f5050Syouri
2035645f5050Syourivoid SetHighlightPixmap (char *filename)
2036645f5050Syouri{
2037645f5050Syouri#ifdef VMS
2038645f5050Syouri    char *ftemp;
2039645f5050Syouri    ftemp = (char *) malloc((strlen(filename)+1)*sizeof(char));
2040645f5050Syouri    Scr->HighlightPixmapName = strcpy (ftemp,filename);
2041645f5050Syouri#else
2042645f5050Syouri    Scr->HighlightPixmapName = (char*) strdup (filename);
2043645f5050Syouri#endif
2044645f5050Syouri}
2045645f5050Syouri
2046645f5050Syouri
2047645f5050Syourivoid FetchWmProtocols (TwmWindow *tmp)
2048645f5050Syouri{
2049645f5050Syouri    unsigned long flags = 0L;
2050645f5050Syouri    Atom *protocols = NULL;
2051645f5050Syouri    int n;
2052645f5050Syouri
2053645f5050Syouri    if (XGetWMProtocols (dpy, tmp->w, &protocols, &n)) {
2054645f5050Syouri	register int i;
2055645f5050Syouri	register Atom *ap;
2056645f5050Syouri
2057645f5050Syouri	for (i = 0, ap = protocols; i < n; i++, ap++) {
2058645f5050Syouri	    if (*ap == _XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus;
2059645f5050Syouri	    if (*ap == _XA_WM_SAVE_YOURSELF) flags |= DoesWmSaveYourself;
2060645f5050Syouri	    if (*ap == _XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow;
2061645f5050Syouri	}
2062645f5050Syouri	if (protocols) XFree ((char *) protocols);
2063645f5050Syouri    }
2064645f5050Syouri    tmp->protocols = flags;
2065645f5050Syouri}
2066645f5050Syouri
2067645f5050SyouriTwmColormap *CreateTwmColormap(Colormap c)
2068645f5050Syouri{
2069645f5050Syouri    TwmColormap *cmap;
2070645f5050Syouri    cmap = (TwmColormap *) malloc(sizeof(TwmColormap));
2071645f5050Syouri    if (!cmap ||
2072645f5050Syouri	XSaveContext(dpy, c, ColormapContext, (XPointer) cmap)) {
2073645f5050Syouri	if (cmap) free((char *) cmap);
2074645f5050Syouri	return (NULL);
2075645f5050Syouri    }
2076645f5050Syouri    cmap->c = c;
2077645f5050Syouri    cmap->state = 0;
2078645f5050Syouri    cmap->install_req = 0;
2079645f5050Syouri    cmap->w = None;
2080645f5050Syouri    cmap->refcnt = 1;
2081645f5050Syouri    return (cmap);
2082645f5050Syouri}
2083645f5050Syouri
2084645f5050SyouriColormapWindow *CreateColormapWindow(Window w,
2085645f5050Syouri				     Bool creating_parent,
2086645f5050Syouri				     Bool property_window)
2087645f5050Syouri{
2088645f5050Syouri    ColormapWindow *cwin;
2089645f5050Syouri    TwmColormap *cmap;
2090645f5050Syouri    XWindowAttributes attributes;
2091645f5050Syouri
2092645f5050Syouri    cwin = (ColormapWindow *) malloc(sizeof(ColormapWindow));
2093645f5050Syouri    if (cwin) {
2094645f5050Syouri	if (!XGetWindowAttributes(dpy, w, &attributes) ||
2095645f5050Syouri	    XSaveContext(dpy, w, ColormapContext, (XPointer) cwin)) {
2096645f5050Syouri	    free((char *) cwin);
2097645f5050Syouri	    return (NULL);
2098645f5050Syouri	}
2099645f5050Syouri
2100645f5050Syouri	if (XFindContext(dpy, attributes.colormap,  ColormapContext,
2101645f5050Syouri		(XPointer *)&cwin->colormap) == XCNOENT) {
2102645f5050Syouri	    cwin->colormap = cmap = CreateTwmColormap(attributes.colormap);
2103645f5050Syouri	    if (!cmap) {
2104645f5050Syouri		XDeleteContext(dpy, w, ColormapContext);
2105645f5050Syouri		free((char *) cwin);
2106645f5050Syouri		return (NULL);
2107645f5050Syouri	    }
2108645f5050Syouri	} else {
2109645f5050Syouri	    cwin->colormap->refcnt++;
2110645f5050Syouri	}
2111645f5050Syouri
2112645f5050Syouri	cwin->w = w;
2113645f5050Syouri	/*
2114645f5050Syouri	 * Assume that windows in colormap list are
2115645f5050Syouri	 * obscured if we are creating the parent window.
2116645f5050Syouri	 * Otherwise, we assume they are unobscured.
2117645f5050Syouri	 */
2118645f5050Syouri	cwin->visibility = creating_parent ?
2119645f5050Syouri	    VisibilityPartiallyObscured : VisibilityUnobscured;
2120645f5050Syouri	cwin->refcnt = 1;
2121645f5050Syouri
2122645f5050Syouri	/*
2123645f5050Syouri	 * If this is a ColormapWindow property window and we
2124645f5050Syouri	 * are not monitoring ColormapNotify or VisibilityNotify
2125645f5050Syouri	 * events, we need to.
2126645f5050Syouri	 */
2127645f5050Syouri	if (property_window &&
2128645f5050Syouri	    (attributes.your_event_mask &
2129645f5050Syouri		(ColormapChangeMask|VisibilityChangeMask)) !=
2130645f5050Syouri		    (ColormapChangeMask|VisibilityChangeMask)) {
2131645f5050Syouri	    XSelectInput(dpy, w, attributes.your_event_mask |
2132645f5050Syouri		(ColormapChangeMask|VisibilityChangeMask));
2133645f5050Syouri	}
2134645f5050Syouri    }
2135645f5050Syouri
2136645f5050Syouri    return (cwin);
2137645f5050Syouri}
2138645f5050Syouri
2139645f5050Syouriint FetchWmColormapWindows (TwmWindow *tmp)
2140645f5050Syouri{
2141645f5050Syouri    register int i, j;
2142645f5050Syouri    Window *cmap_windows = NULL;
2143645f5050Syouri    Bool can_free_cmap_windows = False;
2144645f5050Syouri    int number_cmap_windows = 0;
2145645f5050Syouri    ColormapWindow **cwins = NULL;
2146645f5050Syouri    int previously_installed;
2147645f5050Syouri
2148645f5050Syouri    number_cmap_windows = 0;
2149645f5050Syouri
2150645f5050Syouri    if (/* SUPPRESS 560 */
2151645f5050Syouri	(previously_installed =
2152645f5050Syouri	 (Scr->cmapInfo.cmaps == &tmp->cmaps && tmp->cmaps.number_cwins))) {
2153645f5050Syouri	cwins = tmp->cmaps.cwins;
2154645f5050Syouri	for (i = 0; i < tmp->cmaps.number_cwins; i++)
2155645f5050Syouri	    cwins[i]->colormap->state = 0;
2156645f5050Syouri    }
2157645f5050Syouri
2158645f5050Syouri    if (XGetWMColormapWindows (dpy, tmp->w, &cmap_windows,
2159645f5050Syouri			       &number_cmap_windows) &&
2160645f5050Syouri	number_cmap_windows > 0) {
2161645f5050Syouri
2162645f5050Syouri	can_free_cmap_windows = False;
2163645f5050Syouri	/*
2164645f5050Syouri	 * check if the top level is in the list, add to front if not
2165645f5050Syouri	 */
2166645f5050Syouri	for (i = 0; i < number_cmap_windows; i++) {
2167645f5050Syouri	    if (cmap_windows[i] == tmp->w) break;
2168645f5050Syouri	}
2169645f5050Syouri	if (i == number_cmap_windows) {	 /* not in list */
2170645f5050Syouri	    Window *new_cmap_windows =
2171645f5050Syouri	      (Window *) malloc (sizeof(Window) * (number_cmap_windows + 1));
2172645f5050Syouri
2173645f5050Syouri	    if (!new_cmap_windows) {
2174645f5050Syouri		fprintf (stderr,
2175645f5050Syouri			 "%s:  unable to allocate %d element colormap window array\n",
2176645f5050Syouri			ProgramName, number_cmap_windows+1);
2177645f5050Syouri		goto done;
2178645f5050Syouri	    }
2179645f5050Syouri	    new_cmap_windows[0] = tmp->w;  /* add to front */
2180645f5050Syouri	    for (i = 0; i < number_cmap_windows; i++) {	 /* append rest */
2181645f5050Syouri		new_cmap_windows[i+1] = cmap_windows[i];
2182645f5050Syouri	    }
2183645f5050Syouri	    XFree ((char *) cmap_windows);
2184645f5050Syouri	    can_free_cmap_windows = True;  /* do not use XFree any more */
2185645f5050Syouri	    cmap_windows = new_cmap_windows;
2186645f5050Syouri	    number_cmap_windows++;
2187645f5050Syouri	}
2188645f5050Syouri
2189645f5050Syouri	cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *) *
2190645f5050Syouri		number_cmap_windows);
2191645f5050Syouri	if (cwins) {
2192645f5050Syouri	    for (i = 0; i < number_cmap_windows; i++) {
2193645f5050Syouri
2194645f5050Syouri		/*
2195645f5050Syouri		 * Copy any existing entries into new list.
2196645f5050Syouri		 */
2197645f5050Syouri		for (j = 0; j < tmp->cmaps.number_cwins; j++) {
2198645f5050Syouri		    if (tmp->cmaps.cwins[j]->w == cmap_windows[i]) {
2199645f5050Syouri			cwins[i] = tmp->cmaps.cwins[j];
2200645f5050Syouri			cwins[i]->refcnt++;
2201645f5050Syouri			break;
2202645f5050Syouri		    }
2203645f5050Syouri		}
2204645f5050Syouri
2205645f5050Syouri		/*
2206645f5050Syouri		 * If the colormap window is not being pointed by
2207645f5050Syouri		 * some other applications colormap window list,
2208645f5050Syouri		 * create a new entry.
2209645f5050Syouri		 */
2210645f5050Syouri		if (j == tmp->cmaps.number_cwins) {
2211645f5050Syouri		    if (XFindContext(dpy, cmap_windows[i], ColormapContext,
2212645f5050Syouri				     (XPointer *)&cwins[i]) == XCNOENT) {
2213645f5050Syouri			if ((cwins[i] = CreateColormapWindow(cmap_windows[i],
2214645f5050Syouri				    (Bool) tmp->cmaps.number_cwins == 0,
2215645f5050Syouri				    True)) == NULL) {
2216645f5050Syouri			    int k;
2217645f5050Syouri			    for (k = i + 1; k < number_cmap_windows; k++)
2218645f5050Syouri				cmap_windows[k-1] = cmap_windows[k];
2219645f5050Syouri			    i--;
2220645f5050Syouri			    number_cmap_windows--;
2221645f5050Syouri			}
2222645f5050Syouri		    } else
2223645f5050Syouri			cwins[i]->refcnt++;
2224645f5050Syouri		}
2225645f5050Syouri	    }
2226645f5050Syouri	}
2227645f5050Syouri    }
2228645f5050Syouri
2229645f5050Syouri    /* No else here, in case we bailed out of clause above.
2230645f5050Syouri     */
2231645f5050Syouri    if (number_cmap_windows == 0) {
2232645f5050Syouri
2233645f5050Syouri	number_cmap_windows = 1;
2234645f5050Syouri
2235645f5050Syouri	cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *));
2236645f5050Syouri	if (XFindContext(dpy, tmp->w, ColormapContext, (XPointer *)&cwins[0]) ==
2237645f5050Syouri		XCNOENT)
2238645f5050Syouri	    cwins[0] = CreateColormapWindow(tmp->w,
2239645f5050Syouri			    (Bool) tmp->cmaps.number_cwins == 0, False);
2240645f5050Syouri	else
2241645f5050Syouri	    cwins[0]->refcnt++;
2242645f5050Syouri    }
2243645f5050Syouri
2244645f5050Syouri    if (tmp->cmaps.number_cwins)
2245645f5050Syouri	free_cwins(tmp);
2246645f5050Syouri
2247645f5050Syouri    tmp->cmaps.cwins = cwins;
2248645f5050Syouri    tmp->cmaps.number_cwins = number_cmap_windows;
2249645f5050Syouri    if (number_cmap_windows > 1)
2250645f5050Syouri	tmp->cmaps.scoreboard =
2251645f5050Syouri	  (char *) calloc(1, ColormapsScoreboardLength(&tmp->cmaps));
2252645f5050Syouri
2253645f5050Syouri    if (previously_installed) {
2254645f5050Syouri	InstallColormaps(PropertyNotify, NULL);
2255645f5050Syouri    }
2256645f5050Syouri
2257645f5050Syouri  done:
2258645f5050Syouri    if (cmap_windows) {
2259645f5050Syouri	if (can_free_cmap_windows)
2260645f5050Syouri	  free ((char *) cmap_windows);
2261645f5050Syouri	else
2262645f5050Syouri	  XFree ((char *) cmap_windows);
2263645f5050Syouri    }
2264645f5050Syouri
2265645f5050Syouri    return (0);
2266645f5050Syouri}
2267645f5050Syouri
2268645f5050Syouri
2269645f5050Syourivoid GetWindowSizeHints (TwmWindow *tmp)
2270645f5050Syouri{
2271645f5050Syouri    long supplied = 0;
2272645f5050Syouri    XSizeHints *hints = &tmp->hints;
2273645f5050Syouri
2274645f5050Syouri    if (!XGetWMNormalHints (dpy, tmp->w, hints, &supplied))
2275645f5050Syouri      hints->flags = 0;
2276645f5050Syouri
2277645f5050Syouri    if (hints->flags & PResizeInc) {
2278645f5050Syouri	if (hints->width_inc == 0) hints->width_inc = 1;
2279645f5050Syouri	if (hints->height_inc == 0) hints->height_inc = 1;
2280645f5050Syouri    }
2281645f5050Syouri
2282645f5050Syouri    if (!(supplied & PWinGravity) && (hints->flags & USPosition)) {
2283645f5050Syouri	static int gravs[] = { SouthEastGravity, SouthWestGravity,
2284645f5050Syouri			       NorthEastGravity, NorthWestGravity };
2285645f5050Syouri	int right =  tmp->attr.x + tmp->attr.width + 2 * tmp->old_bw;
2286645f5050Syouri	int bottom = tmp->attr.y + tmp->attr.height + 2 * tmp->old_bw;
2287645f5050Syouri	hints->win_gravity =
2288645f5050Syouri	  gravs[((Scr->rooth - bottom <
2289645f5050Syouri		tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 2) |
2290645f5050Syouri		((Scr->rootw - right   <
2291645f5050Syouri		tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 1)];
2292645f5050Syouri	hints->flags |= PWinGravity;
2293645f5050Syouri    }
2294645f5050Syouri
2295645f5050Syouri    /* Check for min size < max size */
2296645f5050Syouri    if ((hints->flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize)) {
2297645f5050Syouri	if (hints->max_width < hints->min_width) {
2298645f5050Syouri	    if (hints->max_width > 0) {
2299645f5050Syouri		hints->min_width = hints->max_width;
2300645f5050Syouri	    } else if (hints->min_width > 0) {
2301645f5050Syouri		hints->max_width = hints->min_width;
2302645f5050Syouri	    } else {
2303645f5050Syouri		hints->max_width = hints->min_width = 1;
2304645f5050Syouri	    }
2305645f5050Syouri	}
2306645f5050Syouri
2307645f5050Syouri	if (hints->max_height < hints->min_height) {
2308645f5050Syouri	    if (hints->max_height > 0) {
2309645f5050Syouri		hints->min_height = hints->max_height;
2310645f5050Syouri	    } else if (hints->min_height > 0) {
2311645f5050Syouri		hints->max_height = hints->min_height;
2312645f5050Syouri	    } else {
2313645f5050Syouri		hints->max_height = hints->min_height = 1;
2314645f5050Syouri	    }
2315645f5050Syouri	}
2316645f5050Syouri    }
2317645f5050Syouri}
2318645f5050Syouri
2319645f5050Syourivoid AnimateButton (TBWindow *tbw)
2320645f5050Syouri{
2321645f5050Syouri    Image	*image;
2322645f5050Syouri    XSetWindowAttributes attr;
2323645f5050Syouri
2324645f5050Syouri    image = tbw->image;
2325645f5050Syouri    attr.background_pixmap = image->pixmap;
2326645f5050Syouri    XChangeWindowAttributes (dpy, tbw->window, CWBackPixmap, &attr);
2327645f5050Syouri    XClearWindow (dpy, tbw->window);
2328645f5050Syouri    tbw->image = image->next;
2329645f5050Syouri}
2330645f5050Syouri
2331645f5050Syourivoid AnimateHighlight (TwmWindow *t)
2332645f5050Syouri{
2333645f5050Syouri    Image	*image;
2334645f5050Syouri    XSetWindowAttributes attr;
2335645f5050Syouri
2336645f5050Syouri    image = t->HiliteImage;
2337645f5050Syouri    attr.background_pixmap = image->pixmap;
2338645f5050Syouri    if (t->hilite_wl) {
2339645f5050Syouri	XChangeWindowAttributes (dpy, t->hilite_wl, CWBackPixmap, &attr);
2340645f5050Syouri	XClearWindow (dpy, t->hilite_wl);
2341645f5050Syouri    }
2342645f5050Syouri    if (t->hilite_wr) {
2343645f5050Syouri	XChangeWindowAttributes (dpy, t->hilite_wr, CWBackPixmap, &attr);
2344645f5050Syouri	XClearWindow (dpy, t->hilite_wr);
2345645f5050Syouri    }
2346645f5050Syouri    t->HiliteImage = image->next;
2347645f5050Syouri}
2348645f5050Syouri
2349645f5050Syouriname_list **AddWindowRegion (char *geom, int grav1, int grav2)
2350645f5050Syouri{
2351645f5050Syouri    WindowRegion *wr;
2352645f5050Syouri    int mask;
2353645f5050Syouri
2354645f5050Syouri    wr = (WindowRegion*) malloc (sizeof (WindowRegion));
2355645f5050Syouri    wr->next = NULL;
2356645f5050Syouri
2357645f5050Syouri    if (!Scr->FirstWindowRegion) Scr->FirstWindowRegion = wr;
2358645f5050Syouri
2359645f5050Syouri    wr->entries    = NULL;
2360645f5050Syouri    wr->clientlist = NULL;
2361645f5050Syouri    wr->grav1      = grav1;
2362645f5050Syouri    wr->grav2      = grav2;
2363645f5050Syouri    wr->x = wr->y = wr->w = wr->h = 0;
2364645f5050Syouri
2365645f5050Syouri    mask = XParseGeometry (geom, &wr->x, &wr->y, (unsigned int*) &wr->w,
2366645f5050Syouri						 (unsigned int*) &wr->h);
2367645f5050Syouri
2368645f5050Syouri    if (mask & XNegative) wr->x += Scr->rootw - wr->w;
2369645f5050Syouri    if (mask & YNegative) wr->y += Scr->rooth - wr->h;
2370645f5050Syouri
2371645f5050Syouri    return (&(wr->clientlist));
2372645f5050Syouri}
2373645f5050Syouri
2374645f5050Syourivoid CreateWindowRegions (void) {
2375645f5050Syouri    WindowRegion  *wr, *wr1 = NULL, *wr2 = NULL;
2376645f5050Syouri    WorkSpace *wl;
2377645f5050Syouri
2378645f5050Syouri    for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) {
2379645f5050Syouri	wl->FirstWindowRegion = NULL;
2380645f5050Syouri	wr2 = NULL;
2381645f5050Syouri	for (wr = Scr->FirstWindowRegion; wr != NULL; wr = wr->next) {
2382645f5050Syouri	    wr1  = (WindowRegion*) malloc (sizeof (WindowRegion));
2383645f5050Syouri	    *wr1 = *wr;
2384645f5050Syouri	    wr1->entries = (WindowEntry*) malloc (sizeof (WindowEntry));
2385645f5050Syouri	    wr1->entries->next = 0;
2386645f5050Syouri	    wr1->entries->x = wr1->x;
2387645f5050Syouri	    wr1->entries->y = wr1->y;
2388645f5050Syouri	    wr1->entries->w = wr1->w;
2389645f5050Syouri	    wr1->entries->h = wr1->h;
2390645f5050Syouri	    wr1->entries->twm_win = (TwmWindow*) 0;
2391645f5050Syouri	    wr1->entries->used = 0;
2392645f5050Syouri	    if (wr2) wr2->next = wr1; else wl->FirstWindowRegion = wr1;
2393645f5050Syouri	    wr2 = wr1;
2394645f5050Syouri	}
2395645f5050Syouri	if (wr1) wr1->next = NULL;
2396645f5050Syouri    }
2397645f5050Syouri}
2398645f5050Syouri
2399645f5050Syouri
2400645f5050SyouriBool PlaceWindowInRegion (TwmWindow *tmp_win, int *final_x, int *final_y)
2401645f5050Syouri{
2402645f5050Syouri    WindowRegion  *wr;
2403645f5050Syouri    WindowEntry	  *we;
2404645f5050Syouri    int		  w, h;
2405645f5050Syouri    WorkSpace     *wl;
2406645f5050Syouri
2407645f5050Syouri    if (!Scr->FirstWindowRegion) return (False);
2408645f5050Syouri    for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) {
2409645f5050Syouri	if (OCCUPY (tmp_win, wl)) break;
2410645f5050Syouri    }
2411645f5050Syouri    if (!wl) return (False);
2412645f5050Syouri    w = tmp_win->frame_width;
2413645f5050Syouri    h = tmp_win->frame_height;
2414645f5050Syouri    we = (WindowEntry*) 0;
2415645f5050Syouri    for (wr = wl->FirstWindowRegion; wr; wr = wr->next) {
2416645f5050Syouri	if (LookInList (wr->clientlist, tmp_win->full_name, &tmp_win->class)) {
2417645f5050Syouri	    for (we = wr->entries; we; we=we->next) {
2418645f5050Syouri	        if (we->used) continue;
2419645f5050Syouri	        if (we->w >= w && we->h >= h) break;
2420645f5050Syouri	    }
2421645f5050Syouri	    if (we) break;
2422645f5050Syouri	}
2423645f5050Syouri    }
2424645f5050Syouri    tmp_win->wr = (WindowRegion*) 0;
2425645f5050Syouri    if (!we) return (False);
2426645f5050Syouri
2427645f5050Syouri    splitWindowRegionEntry (we, wr->grav1, wr->grav2, w, h);
2428645f5050Syouri    we->used = 1;
2429645f5050Syouri    we->twm_win = tmp_win;
2430645f5050Syouri    *final_x = we->x;
2431645f5050Syouri    *final_y = we->y;
2432645f5050Syouri    tmp_win->wr = wr;
2433645f5050Syouri    return (True);
2434645f5050Syouri}
2435645f5050Syouri
2436645f5050Syouristatic void splitWindowRegionEntry (WindowEntry *we, int grav1, int grav2,
2437645f5050Syouri				    int w, int h)
2438645f5050Syouri{
2439645f5050Syouri    WindowEntry	*new;
2440645f5050Syouri
2441645f5050Syouri    switch (grav1) {
2442645f5050Syouri	case D_NORTH:
2443645f5050Syouri	case D_SOUTH:
2444645f5050Syouri	    if (w != we->w) splitWindowRegionEntry (we, grav2, grav1, w, we->h);
2445645f5050Syouri	    if (h != we->h) {
2446645f5050Syouri		new = (WindowEntry *) malloc (sizeof (WindowEntry));
2447645f5050Syouri		new->twm_win = 0;
2448645f5050Syouri		new->used = 0;
2449645f5050Syouri		new->next = we->next;
2450645f5050Syouri		we->next  = new;
2451645f5050Syouri		new->x    = we->x;
2452645f5050Syouri		new->h    = (we->h - h);
2453645f5050Syouri		new->w    = we->w;
2454645f5050Syouri		we->h     = h;
2455645f5050Syouri		if (grav1 == D_SOUTH) {
2456645f5050Syouri		    new->y = we->y;
2457645f5050Syouri		    we->y  = new->y + new->h;
2458645f5050Syouri		} else
2459645f5050Syouri		    new->y = we->y + we->h;
2460645f5050Syouri		}
2461645f5050Syouri	    break;
2462645f5050Syouri	case D_EAST:
2463645f5050Syouri	case D_WEST:
2464645f5050Syouri	    if (h != we->h) splitWindowRegionEntry (we, grav2, grav1, we->w, h);
2465645f5050Syouri	    if (w != we->w) {
2466645f5050Syouri		new = (WindowEntry *) malloc (sizeof (WindowEntry));
2467645f5050Syouri		new->twm_win = 0;
2468645f5050Syouri		new->used = 0;
2469645f5050Syouri		new->next = we->next;
2470645f5050Syouri		we->next  = new;
2471645f5050Syouri		new->y    = we->y;
2472645f5050Syouri		new->w    = (we->w - w);
2473645f5050Syouri		new->h    = we->h;
2474645f5050Syouri		we->w = w;
2475645f5050Syouri		if (grav1 == D_EAST) {
2476645f5050Syouri		    new->x = we->x;
2477645f5050Syouri		    we->x  = new->x + new->w;
2478645f5050Syouri		} else
2479645f5050Syouri		    new->x = we->x + we->w;
2480645f5050Syouri		}
2481645f5050Syouri	    break;
2482645f5050Syouri    }
2483645f5050Syouri}
2484645f5050Syouri
2485645f5050Syouristatic WindowEntry *findWindowEntry (WorkSpace *wl, TwmWindow *tmp_win,
2486645f5050Syouri				     WindowRegion **wrp)
2487645f5050Syouri{
2488645f5050Syouri    WindowRegion *wr;
2489645f5050Syouri    WindowEntry	 *we;
2490645f5050Syouri
2491645f5050Syouri    for (wr = wl->FirstWindowRegion; wr; wr = wr->next) {
2492645f5050Syouri	for (we = wr->entries; we; we=we->next) {
2493645f5050Syouri	    if (we->twm_win == tmp_win) {
2494645f5050Syouri		if (wrp) *wrp = wr;
2495645f5050Syouri		return we;
2496645f5050Syouri	    }
2497645f5050Syouri	}
2498645f5050Syouri    }
2499645f5050Syouri    return (WindowEntry*) 0;
2500645f5050Syouri}
2501645f5050Syouri
2502645f5050Syouristatic WindowEntry *prevWindowEntry (WindowEntry *we, WindowRegion *wr)
2503645f5050Syouri{
2504645f5050Syouri    WindowEntry	*wp;
2505645f5050Syouri
2506645f5050Syouri    if (we == wr->entries) return 0;
2507645f5050Syouri    for (wp = wr->entries; wp->next != we; wp=wp->next);
2508645f5050Syouri    return wp;
2509645f5050Syouri}
2510645f5050Syouri
2511645f5050Syouristatic void mergeWindowEntries (WindowEntry *old, WindowEntry *we)
2512645f5050Syouri{
2513645f5050Syouri    if (old->y == we->y) {
2514645f5050Syouri	we->w = old->w + we->w;
2515645f5050Syouri	if (old->x < we->x) we->x = old->x;
2516645f5050Syouri    } else {
2517645f5050Syouri	we->h = old->h + we->h;
2518645f5050Syouri	if (old->y < we->y) we->y = old->y;
2519645f5050Syouri    }
2520645f5050Syouri}
2521645f5050Syouri
2522645f5050Syourivoid RemoveWindowFromRegion (TwmWindow *tmp_win)
2523645f5050Syouri{
2524645f5050Syouri    WindowEntry  *we, *wp, *wn;
2525645f5050Syouri    WindowRegion *wr;
2526645f5050Syouri    WorkSpace    *wl;
2527645f5050Syouri
2528645f5050Syouri    if (!Scr->FirstWindowRegion) return;
2529645f5050Syouri    we = (WindowEntry*) 0;
2530645f5050Syouri    for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) {
2531645f5050Syouri	we = findWindowEntry (wl, tmp_win, &wr);
2532645f5050Syouri	if (we) break;
2533645f5050Syouri    }
2534645f5050Syouri    if (!we) return;
2535645f5050Syouri
2536645f5050Syouri    we->twm_win = 0;
2537645f5050Syouri    we->used = 0;
2538645f5050Syouri    wp = prevWindowEntry (we, wr);
2539645f5050Syouri    wn = we->next;
2540645f5050Syouri    for (;;) {
2541645f5050Syouri	if (wp && wp->used == 0 &&
2542645f5050Syouri	       ((wp->x == we->x && wp->w == we->w) ||
2543645f5050Syouri	        (wp->y == we->y && wp->h == we->h))) {
2544645f5050Syouri	    wp->next = we->next;
2545645f5050Syouri	    mergeWindowEntries (we, wp);
2546645f5050Syouri	    free ((char *) we);
2547645f5050Syouri	    we = wp;
2548645f5050Syouri	    wp = prevWindowEntry (wp, wr);
2549645f5050Syouri	} else
2550645f5050Syouri	if (wn && wn->used == 0 &&
2551645f5050Syouri	       ((wn->x == we->x && wn->w == we->w) ||
2552645f5050Syouri	        (wn->y == we->y && wn->h == we->h))) {
2553645f5050Syouri	    we->next = wn->next;
2554645f5050Syouri	    mergeWindowEntries (wn, we);
2555645f5050Syouri	    free ((char *) wn);
2556645f5050Syouri	    wn = we->next;
2557645f5050Syouri	} else break;
2558645f5050Syouri    }
2559645f5050Syouri}
2560645f5050Syouri
2561645f5050Syouri/*
2562645f5050Syouri * This is largely for Xinerama support with VirtualScreens.
2563645f5050Syouri * In this case, windows may be on something other then the main screen
2564645f5050Syouri * on startup, or the mapping may be relative to the right side of the
2565645f5050Syouri * screen, which is on a different monitor, which will cause issues with
2566645f5050Syouri * the virtual screens.
2567645f5050Syouri *
2568645f5050Syouri * It probably needs to be congnizant of windows that are actually owned by
2569645f5050Syouri * other workspaces, and ignore them (this needs to be revisited), or perhaps
2570645f5050Syouri * that functionality is appropriate in AddWindow().  This needs to be dug into
2571645f5050Syouri * more deply.
2572645f5050Syouri *
2573645f5050Syouri * this approach assumes screens that are next to each other horizontally,
2574645f5050Syouri * Other possibilities need to be investigated and accounted for.
2575645f5050Syouri */
2576645f5050Syourivoid DealWithNonSensicalGeometries(Display *mydpy, Window vroot, TwmWindow *tmp_win)
2577645f5050Syouri{
2578645f5050Syouri    Window		vvroot;
2579645f5050Syouri    int			x,y;
2580645f5050Syouri    unsigned int	w,h;
2581645f5050Syouri    unsigned int	j;
2582645f5050Syouri    virtualScreen	*myvs, *vs;
2583645f5050Syouri    int			dropx = 0;
2584645f5050Syouri
2585645f5050Syouri    if(! vroot)
2586645f5050Syouri	return;
2587645f5050Syouri
2588645f5050Syouri    if(!(XGetGeometry(mydpy, vroot, &vvroot, &x, &y, &w, &h, &j, &j)))
2589645f5050Syouri	return;
2590645f5050Syouri
2591645f5050Syouri    myvs = findIfVScreenOf(x, y);
2592645f5050Syouri
2593645f5050Syouri    /*
2594645f5050Syouri     * probably need to rethink this  for unmapped vs's.  ugh.
2595645f5050Syouri     */
2596645f5050Syouri    if(!myvs)
2597645f5050Syouri	return;
2598645f5050Syouri
2599645f5050Syouri    for(vs = myvs->next; vs; vs = vs->next) {
2600645f5050Syouri	dropx += vs->w;
2601645f5050Syouri    }
2602645f5050Syouri
2603645f5050Syouri    for(vs = Scr->vScreenList; vs && vs != myvs; vs = vs->next) {
2604645f5050Syouri	dropx -= vs->w;
2605645f5050Syouri    }
2606645f5050Syouri
2607645f5050Syouri    if(tmp_win->frame_x > 0 && tmp_win->frame_x >= w) {
2608645f5050Syouri	tmp_win->frame_x -= abs(dropx);
2609645f5050Syouri    } else {
2610645f5050Syouri}
2611645f5050Syouri
2612645f5050Syouri}
2613