Bug Summary

File:add_window.c
Location:line 1536, column 6
Description:Potential leak of memory pointed to by 'cwins'

Annotated Source Code

1/*****************************************************************************/
2/*
3
4Copyright 1989,1998 The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25
26*/
27/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
28/** Salt Lake City, Utah **/
29/** Cambridge, Massachusetts **/
30/** **/
31/** All Rights Reserved **/
32/** **/
33/** Permission to use, copy, modify, and distribute this software and **/
34/** its documentation for any purpose and without fee is hereby **/
35/** granted, provided that the above copyright notice appear in all **/
36/** copies and that both that copyright notice and this permis- **/
37/** sion notice appear in supporting documentation, and that the **/
38/** name of Evans & Sutherland not be used in advertising **/
39/** in publicity pertaining to distribution of the software without **/
40/** specific, written prior permission. **/
41/** **/
42/** EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD **/
43/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
44/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND **/
45/** BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
46/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
47/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
48/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
49/** OR PERFORMANCE OF THIS SOFTWARE. **/
50/*****************************************************************************/
51
52
53/**********************************************************************
54 *
55 * Add a new window, put the titlbar and other stuff around
56 * the window
57 *
58 * 31-Mar-88 Tom LaStrange Initial Version.
59 *
60 **********************************************************************/
61
62#include <stdio.h>
63#include "twm.h"
64#include <X11/Xatom.h>
65#include "util.h"
66#include "resize.h"
67#include "parse.h"
68#include "list.h"
69#include "events.h"
70#include "menus.h"
71#include "screen.h"
72#include "iconmgr.h"
73#include "session.h"
74#include "add_window.h"
75
76#define gray_width2 2
77#define gray_height2 2
78static char gray_bits[] = {
79 0x02, 0x01};
80
81int AddingX;
82int AddingY;
83int AddingW;
84int AddingH;
85
86static int PlaceX = 50;
87static int PlaceY = 50;
88
89static void do_add_binding ( int button, int context, int modifier, int func );
90static Window CreateHighlightWindow ( TwmWindow *tmp_win );
91static void CreateWindowTitlebarButtons ( TwmWindow *tmp_win );
92
93
94char NoName[] = "Untitled"; /* name if no name is specified */
95
96
97/**
98 * map gravity to (x,y) offset signs for adding to x and y when window is
99 * mapped to get proper placement.
100 *
101 * \param tmp window from which to get gravity
102 * \param xp,yp return values
103 *
104 */
105void
106GetGravityOffsets (TwmWindow *tmp, int *xp, int *yp)
107{
108 static struct _gravity_offset {
109 int x, y;
110 } gravity_offsets[11] = {
111 { 0, 0 }, /* ForgetGravity */
112 { -1, -1 }, /* NorthWestGravity */
113 { 0, -1 }, /* NorthGravity */
114 { 1, -1 }, /* NorthEastGravity */
115 { -1, 0 }, /* WestGravity */
116 { 0, 0 }, /* CenterGravity */
117 { 1, 0 }, /* EastGravity */
118 { -1, 1 }, /* SouthWestGravity */
119 { 0, 1 }, /* SouthGravity */
120 { 1, 1 }, /* SouthEastGravity */
121 { 0, 0 }, /* StaticGravity */
122 };
123 register int g = ((tmp->hints.flags & PWinGravity(1L << 9))
124 ? tmp->hints.win_gravity : NorthWestGravity1);
125
126 if (g < ForgetGravity0 || g > StaticGravity10) {
127 *xp = *yp = 0;
128 } else {
129 *xp = gravity_offsets[g].x;
130 *yp = gravity_offsets[g].y;
131 }
132}
133
134
135
136
137/**
138 * add a new window to the twm list.
139 *
140 * \return pointer to the TwmWindow structure
141 *
142 * \param w the window id of the window to add
143 * \param iconm flag to tell if this is an icon manager window
144 * \param iconp pointer to icon manager struct
145 */
146TwmWindow *
147AddWindow(Window w, int iconm, IconMgr *iconp)
148{
149 TwmWindow *tmp_win; /* new twm window structure */
150 int stat;
151 XEvent event;
152 unsigned long valuemask; /* mask for create windows */
153 XSetWindowAttributes attributes; /* attributes for create windows */
154 int width, height; /* tmp variable */
155 int ask_user; /* don't know where to put the window */
156 int gravx, gravy; /* gravity signs for positioning */
157 int namelen;
158 int bw2;
159 short saved_x, saved_y, restore_icon_x, restore_icon_y;
160 unsigned short saved_width, saved_height;
161 Boolint restore_iconified = 0;
162 Boolint restore_icon_info_present = 0;
163 int restoredFromPrevSession;
164 Boolint width_ever_changed_by_user;
165 Boolint height_ever_changed_by_user;
166 char *name;
167
168#ifdef DEBUG
169 fprintf(stderr__stderrp, "AddWindow: w = 0x%lx\n", (unsigned long)w);
170#endif
171
172 /* allocate space for the twm window */
173 tmp_win = calloc(1, sizeof(TwmWindow));
174 if (tmp_win == NULL((void*)0))
175 {
176 fprintf (stderr__stderrp, "%s: Unable to allocate memory to manage window ID %lx.\n",
177 ProgramName, w);
178 return NULL((void*)0);
179 }
180 tmp_win->w = w;
181 tmp_win->zoomed = ZOOM_NONE0;
182 tmp_win->iconmgr = iconm;
183 tmp_win->iconmgrp = iconp;
184 tmp_win->cmaps.number_cwins = 0;
185
186 XSelectInput(dpy, tmp_win->w, PropertyChangeMask(1L<<22));
187
188 XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr);
189
190 if (!I18N_FetchName(dpy, tmp_win->w, &name))
191 name = NULL((void*)0);
192 tmp_win->class = NoClass;
193 XGetClassHint(dpy, tmp_win->w, &tmp_win->class);
194 FetchWmProtocols (tmp_win);
195 FetchWmColormapWindows (tmp_win);
196
197 if (name == NULL((void*)0))
198 tmp_win->name = strdup(NoName);
199 else {
200 tmp_win->name = strdup(name);
201 free(name);
202 }
203
204 if (GetWindowConfig (tmp_win,
205 &saved_x, &saved_y, &saved_width, &saved_height,
206 &restore_iconified, &restore_icon_info_present,
207 &restore_icon_x, &restore_icon_y,
208 &width_ever_changed_by_user, &height_ever_changed_by_user))
209 {
210 tmp_win->attr.x = saved_x;
211 tmp_win->attr.y = saved_y;
212
213 tmp_win->widthEverChangedByUser = width_ever_changed_by_user;
214 tmp_win->heightEverChangedByUser = height_ever_changed_by_user;
215
216 if (width_ever_changed_by_user)
217 tmp_win->attr.width = saved_width;
218
219 if (height_ever_changed_by_user)
220 tmp_win->attr.height = saved_height;
221
222 restoredFromPrevSession = 1;
223 }
224 else
225 {
226 tmp_win->widthEverChangedByUser = False0;
227 tmp_win->heightEverChangedByUser = False0;
228
229 restoredFromPrevSession = 0;
230 }
231
232
233 /*
234 * do initial clip; should look at window gravity
235 */
236 if (tmp_win->attr.width > Scr->MaxWindowWidth)
237 tmp_win->attr.width = Scr->MaxWindowWidth;
238 if (tmp_win->attr.height > Scr->MaxWindowHeight)
239 tmp_win->attr.height = Scr->MaxWindowHeight;
240
241 tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w);
242
243 if (tmp_win->wmhints)
244 {
245 if (restore_iconified)
246 {
247 tmp_win->wmhints->initial_state = IconicState3;
248 tmp_win->wmhints->flags |= StateHint(1L << 1);
249 }
250
251 if (restore_icon_info_present)
252 {
253 tmp_win->wmhints->icon_x = restore_icon_x;
254 tmp_win->wmhints->icon_y = restore_icon_y;
255 tmp_win->wmhints->flags |= IconPositionHint(1L << 4);
256 }
257 }
258
259 if (tmp_win->wmhints && (tmp_win->wmhints->flags & WindowGroupHint(1L << 6)))
260 tmp_win->group = tmp_win->wmhints->window_group;
261 else
262 tmp_win->group = tmp_win->w/* NULL */;
263
264 /*
265 * The July 27, 1988 draft of the ICCCM ignores the size and position
266 * fields in the WM_NORMAL_HINTS property.
267 */
268
269 tmp_win->transient = Transient(tmp_win->w, &tmp_win->transientfor);
270
271 tmp_win->nameChanged = 0;
272 if (tmp_win->class.res_name == NULL((void*)0))
273 tmp_win->class.res_name = NoName;
274 if (tmp_win->class.res_class == NULL((void*)0))
275 tmp_win->class.res_class = NoName;
276
277 tmp_win->full_name = strdup(tmp_win->name);
278 namelen = strlen (tmp_win->name);
279
280 tmp_win->highlight = Scr->Highlight &&
281 (!(short)(long) LookInList(Scr->NoHighlight, tmp_win->full_name,
282 &tmp_win->class));
283
284 tmp_win->stackmode = Scr->StackMode &&
285 (!(short)(long) LookInList(Scr->NoStackModeL, tmp_win->full_name,
286 &tmp_win->class));
287
288 tmp_win->titlehighlight = Scr->TitleHighlight &&
289 (!(short)(long) LookInList(Scr->NoTitleHighlight, tmp_win->full_name,
290 &tmp_win->class));
291
292 tmp_win->auto_raise = (short)(long) LookInList(Scr->AutoRaise,
293 tmp_win->full_name,
294 &tmp_win->class);
295 if (tmp_win->auto_raise) Scr->NumAutoRaises++;
296 tmp_win->iconify_by_unmapping = Scr->IconifyByUnmapping;
297 if (Scr->IconifyByUnmapping)
298 {
299 tmp_win->iconify_by_unmapping = iconm ? FALSE0 :
300 !(short)(long) LookInList(Scr->DontIconify, tmp_win->full_name,
301 &tmp_win->class);
302 }
303 tmp_win->iconify_by_unmapping |=
304 (short)(long) LookInList(Scr->IconifyByUn, tmp_win->full_name,
305 &tmp_win->class);
306
307 if (LookInList(Scr->WindowRingL, tmp_win->full_name, &tmp_win->class)) {
308 if (Scr->Ring) {
309 tmp_win->ring.next = Scr->Ring->ring.next;
310 if (Scr->Ring->ring.next->ring.prev)
311 Scr->Ring->ring.next->ring.prev = tmp_win;
312 Scr->Ring->ring.next = tmp_win;
313 tmp_win->ring.prev = Scr->Ring;
314 } else {
315 tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win;
316 }
317 } else
318 tmp_win->ring.next = tmp_win->ring.prev = NULL((void*)0);
319 tmp_win->ring.cursor_valid = False0;
320
321 tmp_win->squeeze_info = NULL((void*)0);
322 /*
323 * get the squeeze information; note that this does not have to be freed
324 * since it is coming from the screen list
325 */
326 if (HasShape) {
327 if (!LookInList (Scr->DontSqueezeTitleL, tmp_win->full_name,
328 &tmp_win->class)) {
329 tmp_win->squeeze_info = (SqueezeInfo *)
330 LookInList (Scr->SqueezeTitleL, tmp_win->full_name,
331 &tmp_win->class);
332 if (!tmp_win->squeeze_info) {
333 static SqueezeInfo default_squeeze = { J_LEFT1, 0, 0 };
334 if (Scr->SqueezeTitle)
335 tmp_win->squeeze_info = &default_squeeze;
336 }
337 }
338 }
339
340 tmp_win->old_bw = tmp_win->attr.border_width;
341
342 if (Scr->ClientBorderWidth) {
343 tmp_win->frame_bw = tmp_win->old_bw;
344 } else {
345 tmp_win->frame_bw = Scr->BorderWidth;
346 }
347 bw2 = tmp_win->frame_bw * 2;
348
349 tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
350 if (Scr->NoTitlebar)
351 tmp_win->title_height = 0;
352 if (LookInList(Scr->MakeTitle, tmp_win->full_name, &tmp_win->class))
353 tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
354 if (LookInList(Scr->NoTitle, tmp_win->full_name, &tmp_win->class))
355 tmp_win->title_height = 0;
356
357 /* if it is a transient window, don't put a title on it */
358 if (tmp_win->transient && !Scr->DecorateTransients)
359 tmp_win->title_height = 0;
360
361 if (LookInList(Scr->StartIconified, tmp_win->full_name, &tmp_win->class))
362 {
363 if (!tmp_win->wmhints)
364 {
365 tmp_win->wmhints = malloc(sizeof(XWMHints));
366 tmp_win->wmhints->flags = 0;
367 }
368 tmp_win->wmhints->initial_state = IconicState3;
369 tmp_win->wmhints->flags |= StateHint(1L << 1);
370 }
371
372 GetWindowSizeHints (tmp_win);
373
374 if (restoredFromPrevSession)
375 {
376 /*
377 * When restoring window positions from the previous session,
378 * we always use NorthWest gravity.
379 */
380
381 gravx = gravy = -1;
382 }
383 else
384 {
385 GetGravityOffsets (tmp_win, &gravx, &gravy);
386 }
387
388 /*
389 * Don't bother user if:
390 *
391 * o the window is a transient, or
392 *
393 * o a USPosition was requested, or
394 *
395 * o a PPosition was requested and UsePPosition is ON or
396 * NON_ZERO if the window is at other than (0,0)
397 */
398 ask_user = TRUE1;
399 if (tmp_win->transient ||
400 (tmp_win->hints.flags & USPosition(1L << 0)) ||
401 ((tmp_win->hints.flags & PPosition(1L << 2)) && Scr->UsePPosition &&
402 (Scr->UsePPosition == PPOS_ON1 ||
403 tmp_win->attr.x != 0 || tmp_win->attr.y != 0)))
404 ask_user = FALSE0;
405
406 /*
407 * do any prompting for position
408 */
409 if (HandlingEvents && ask_user && !restoredFromPrevSession) {
410 if (Scr->RandomPlacement) { /* just stick it somewhere */
411 if ((PlaceX + tmp_win->attr.width) > Scr->MyDisplayWidth)
412 PlaceX = 50;
413 if ((PlaceY + tmp_win->attr.height) > Scr->MyDisplayHeight)
414 PlaceY = 50;
415
416 tmp_win->attr.x = PlaceX;
417 tmp_win->attr.y = PlaceY;
418 PlaceX += 30;
419 PlaceY += 30;
420 } else { /* else prompt */
421 if (!(tmp_win->wmhints && tmp_win->wmhints->flags & StateHint(1L << 1) &&
422 tmp_win->wmhints->initial_state == IconicState3))
423 {
424 Boolint firsttime = True1;
425
426 /* better wait until all the mouse buttons have been
427 * released.
428 */
429 while (TRUE1)
430 {
431 XUngrabServer(dpy);
432 XSync(dpy, 0);
433 XGrabServer(dpy);
434
435 JunkMask = 0;
436 if (!XQueryPointer (dpy, Scr->Root, &JunkRoot,
437 &JunkChild, &JunkX, &JunkY,
438 &AddingX, &AddingY, &JunkMask))
439 JunkMask = 0;
440
441 JunkMask &= (Button1Mask(1<<8) | Button2Mask(1<<9) | Button3Mask(1<<10) |
442 Button4Mask(1<<11) | Button5Mask(1<<12));
443
444 /*
445 * watch out for changing screens
446 */
447 if (firsttime) {
448 if (JunkRoot != Scr->Root) {
449 register int scrnum;
450
451 for (scrnum = 0; scrnum < NumScreens; scrnum++) {
452 if (JunkRoot == RootWindow (dpy, scrnum)((&((_XPrivDisplay)(dpy))->screens[scrnum])->root)) break;
453 }
454
455 if (scrnum != NumScreens) PreviousScreen = scrnum;
456 }
457 firsttime = False0;
458 }
459
460 /*
461 * wait for buttons to come up; yuck
462 */
463 if (JunkMask != 0) continue;
464
465 /*
466 * this will cause a warp to the indicated root
467 */
468 stat = XGrabPointer(dpy, Scr->Root, False0,
469 ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3) |
470 PointerMotionMask(1L<<6) | PointerMotionHintMask(1L<<7),
471 GrabModeAsync1, GrabModeAsync1,
472 Scr->Root, UpperLeftCursor, CurrentTime0L);
473
474 if (stat == GrabSuccess0)
475 break;
476 }
477
478 width = (SIZE_HINDENT10 + MyFont_TextWidth (&Scr->SizeFont,
479 tmp_win->name, namelen));
480 height = Scr->SizeFont.height + SIZE_VINDENT2 * 2;
481
482 XResizeWindow (dpy, Scr->SizeWindow, width + SIZE_HINDENT10, height);
483 XMapRaised(dpy, Scr->SizeWindow);
484 InstallRootColormap();
485
486 MyFont_ChangeGC(Scr->DefaultC.fore, Scr->DefaultC.back,
487 &Scr->SizeFont);
488 MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
489 Scr->NormalGC,
490 SIZE_HINDENT10,
491 SIZE_VINDENT2 + Scr->SizeFont.ascent,
492 tmp_win->name, namelen);
493
494 AddingW = tmp_win->attr.width + bw2;
495 AddingH = tmp_win->attr.height + tmp_win->title_height + bw2;
496
497 if (Scr->DontMoveOff) {
498 /*
499 * Make sure the initial outline comes up on the screen.
500 */
501 if (AddingX < 0)
502 AddingX = 0;
503 if (AddingX > Scr->MyDisplayWidth - AddingW)
504 AddingX = Scr->MyDisplayWidth - AddingW;
505
506 if (AddingY < 0)
507 AddingY = 0;
508 if (AddingY > Scr->MyDisplayHeight - AddingH)
509 AddingY = Scr->MyDisplayHeight - AddingH;
510 }
511
512 MoveOutline(Scr->Root, AddingX, AddingY, AddingW, AddingH,
513 tmp_win->frame_bw, tmp_win->title_height);
514
515 while (TRUE1)
516 {
517 XMaskEvent(dpy, ButtonPressMask(1L<<2) | PointerMotionMask(1L<<6), &event);
518
519 if (Event.type == MotionNotify6) {
520 /* discard any extra motion events before a release */
521 while(XCheckMaskEvent(dpy,
522 ButtonMotionMask(1L<<13) | ButtonPressMask(1L<<2), &Event))
523 if (Event.type == ButtonPress4)
524 break;
525 }
526
527 if (event.type == ButtonPress4) {
528 AddingX = event.xbutton.x_root;
529 AddingY = event.xbutton.y_root;
530
531 /* DontMoveOff prohibits user form off-screen placement */
532 if (Scr->DontMoveOff)
533 {
534 int AddingR, AddingB;
535
536 AddingR = AddingX + AddingW;
537 AddingB = AddingY + AddingH;
538
539 if (AddingX < 0)
540 AddingX = 0;
541 if (AddingR > Scr->MyDisplayWidth)
542 AddingX = Scr->MyDisplayWidth - AddingW;
543
544 if (AddingY < 0)
545 AddingY = 0;
546 if (AddingB > Scr->MyDisplayHeight)
547 AddingY = Scr->MyDisplayHeight - AddingH;
548
549 }
550 break;
551 }
552
553 if (event.type != MotionNotify6) {
554 continue;
555 }
556
557 XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
558 &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
559
560 if (Scr->DontMoveOff)
561 {
562 int AddingR, AddingB;
563
564 AddingR = AddingX + AddingW;
565 AddingB = AddingY + AddingH;
566
567 if (AddingX < 0)
568 AddingX = 0;
569 if (AddingR > Scr->MyDisplayWidth)
570 AddingX = Scr->MyDisplayWidth - AddingW;
571
572 if (AddingY < 0)
573 AddingY = 0;
574 if (AddingB > Scr->MyDisplayHeight)
575 AddingY = Scr->MyDisplayHeight - AddingH;
576 }
577
578 MoveOutline(Scr->Root, AddingX, AddingY, AddingW, AddingH,
579 tmp_win->frame_bw, tmp_win->title_height);
580
581 }
582
583 if (event.xbutton.button == Button22) {
584 int lastx, lasty;
585
586 Scr->SizeStringOffset = width +
587 MyFont_TextWidth(&Scr->SizeFont, ": ", 2);
588 XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset +
589 Scr->SizeStringWidth, height);
590 MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
591 Scr->NormalGC, width,
592 SIZE_VINDENT2 + Scr->SizeFont.ascent,
593 ": ", 2);
594 if (0/*Scr->AutoRelativeResize*/) {
595 int dx = (tmp_win->attr.width / 4);
596 int dy = (tmp_win->attr.height / 4);
597
598#define HALF_AVE_CURSOR_SIZE 8 /* so that it is visible */
599 if (dx < HALF_AVE_CURSOR_SIZE) dx = HALF_AVE_CURSOR_SIZE;
600 if (dy < HALF_AVE_CURSOR_SIZE) dy = HALF_AVE_CURSOR_SIZE;
601#undef HALF_AVE_CURSOR_SIZE
602 dx += (tmp_win->frame_bw + 1);
603 dy += (bw2 + tmp_win->title_height + 1);
604 if (AddingX + dx >= Scr->MyDisplayWidth)
605 dx = Scr->MyDisplayWidth - AddingX - 1;
606 if (AddingY + dy >= Scr->MyDisplayHeight)
607 dy = Scr->MyDisplayHeight - AddingY - 1;
608 if (dx > 0 && dy > 0)
609 XWarpPointer (dpy, None0L, None0L, 0, 0, 0, 0, dx, dy);
610 } else {
611 XWarpPointer (dpy, None0L, Scr->Root, 0, 0, 0, 0,
612 AddingX + AddingW/2, AddingY + AddingH/2);
613 }
614 AddStartResize(tmp_win, AddingX, AddingY, AddingW, AddingH);
615
616 lastx = -10000;
617 lasty = -10000;
618 while (TRUE1)
619 {
620 XMaskEvent(dpy,
621 ButtonReleaseMask(1L<<3) | ButtonMotionMask(1L<<13), &event);
622
623 if (Event.type == MotionNotify6) {
624 /* discard any extra motion events before a release */
625 while(XCheckMaskEvent(dpy,
626 ButtonMotionMask(1L<<13) | ButtonReleaseMask(1L<<3), &Event))
627 if (Event.type == ButtonRelease5)
628 break;
629 }
630
631 if (event.type == ButtonRelease5)
632 {
633 AddEndResize(tmp_win);
634 break;
635 }
636
637 if (event.type != MotionNotify6) {
638 continue;
639 }
640
641 /*
642 * XXX - if we are going to do a loop, we ought to consider
643 * using multiple GXxor lines so that we don't need to
644 * grab the server.
645 */
646 XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
647 &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
648
649 if (lastx != AddingX || lasty != AddingY)
650 {
651 DoResize(AddingX, AddingY, tmp_win);
652
653 lastx = AddingX;
654 lasty = AddingY;
655 }
656
657 }
658 }
659 else if (event.xbutton.button == Button33)
660 {
661 int maxw = Scr->MyDisplayWidth - AddingX - bw2;
662 int maxh = Scr->MyDisplayHeight - AddingY - bw2;
663
664 /*
665 * Make window go to bottom of screen, and clip to right edge.
666 * This is useful when popping up large windows and fixed
667 * column text windows.
668 */
669 if (AddingW > maxw) AddingW = maxw;
670 AddingH = maxh;
671
672 ConstrainSize (tmp_win, &AddingW, &AddingH); /* w/o borders */
673 AddingW += bw2;
674 AddingH += bw2;
675 }
676 else
677 {
678 XMaskEvent(dpy, ButtonReleaseMask(1L<<3), &event);
679 }
680
681 MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
682 XUnmapWindow(dpy, Scr->SizeWindow);
683 UninstallRootColormap();
684 XUngrabPointer(dpy, CurrentTime0L);
685
686 tmp_win->attr.x = AddingX;
687 tmp_win->attr.y = AddingY + tmp_win->title_height;
688 tmp_win->attr.width = AddingW - bw2;
689 tmp_win->attr.height = AddingH - tmp_win->title_height - bw2;
690
691 XUngrabServer(dpy);
692 }
693 }
694 } else { /* put it where asked, mod title bar */
695 /* if the gravity is towards the top, move it by the title height */
696 if (gravy < 0) tmp_win->attr.y -= gravy * tmp_win->title_height;
697 }
698
699
700#ifdef DEBUG
701 fprintf(stderr__stderrp, " position window %d, %d %dx%d\n",
702 tmp_win->attr.x,
703 tmp_win->attr.y,
704 tmp_win->attr.width,
705 tmp_win->attr.height);
706#endif
707
708 if (!Scr->ClientBorderWidth) { /* need to adjust for twm borders */
709 int delta = tmp_win->attr.border_width - tmp_win->frame_bw;
710 tmp_win->attr.x += gravx * delta;
711 tmp_win->attr.y += gravy * delta;
712 }
713
714 tmp_win->title_width = tmp_win->attr.width;
715
716 if (tmp_win->old_bw) XSetWindowBorderWidth (dpy, tmp_win->w, 0);
717
718 tmp_win->name_width = MyFont_TextWidth(&Scr->TitleBarFont, tmp_win->name,
719 namelen);
720
721 if (!I18N_GetIconName(dpy, tmp_win->w, &name)) {
722 tmp_win->icon_name = strdup(tmp_win->name);
723 } else {
724 if (name == NULL((void*)0)) {
725 tmp_win->icon_name = strdup(tmp_win->name);
726 } else {
727 tmp_win->icon_name = strdup(name);
728 free(name);
729 }
730 }
731
732 tmp_win->iconified = FALSE0;
733 tmp_win->icon = FALSE0;
734 tmp_win->icon_on = FALSE0;
735
736 XGrabServer(dpy);
737
738 /*
739 * Make sure the client window still exists. We don't want to leave an
740 * orphan frame window if it doesn't. Since we now have the server
741 * grabbed, the window can't disappear later without having been
742 * reparented, so we'll get a DestroyNotify for it. We won't have
743 * gotten one for anything up to here, however.
744 */
745 if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY,
746 &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0)
747 {
748 free(tmp_win);
749 XUngrabServer(dpy);
750 return(NULL((void*)0));
751 }
752
753 /* add the window into the twm list */
754 tmp_win->next = Scr->TwmRoot.next;
755 if (Scr->TwmRoot.next != NULL((void*)0))
756 Scr->TwmRoot.next->prev = tmp_win;
757 tmp_win->prev = &Scr->TwmRoot;
758 Scr->TwmRoot.next = tmp_win;
759
760 /* get all the colors for the window */
761
762 tmp_win->border = Scr->BorderColor;
763 tmp_win->icon_border = Scr->IconBorderColor;
764 tmp_win->border_tile.fore = Scr->BorderTileC.fore;
765 tmp_win->border_tile.back = Scr->BorderTileC.back;
766 tmp_win->title.fore = Scr->TitleC.fore;
767 tmp_win->title.back = Scr->TitleC.back;
768 tmp_win->iconc.fore = Scr->IconC.fore;
769 tmp_win->iconc.back = Scr->IconC.back;
770
771 GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class,
772 &tmp_win->border);
773 GetColorFromList(Scr->IconBorderColorL, tmp_win->full_name, &tmp_win->class,
774 &tmp_win->icon_border);
775 GetColorFromList(Scr->BorderTileForegroundL, tmp_win->full_name,
776 &tmp_win->class, &tmp_win->border_tile.fore);
777 GetColorFromList(Scr->BorderTileBackgroundL, tmp_win->full_name,
778 &tmp_win->class, &tmp_win->border_tile.back);
779 GetColorFromList(Scr->TitleForegroundL, tmp_win->full_name, &tmp_win->class,
780 &tmp_win->title.fore);
781 GetColorFromList(Scr->TitleBackgroundL, tmp_win->full_name, &tmp_win->class,
782 &tmp_win->title.back);
783 GetColorFromList(Scr->IconForegroundL, tmp_win->full_name, &tmp_win->class,
784 &tmp_win->iconc.fore);
785 GetColorFromList(Scr->IconBackgroundL, tmp_win->full_name, &tmp_win->class,
786 &tmp_win->iconc.back);
787
788
789 /* create windows */
790
791 tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->frame_bw;
792 tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height +
793 tmp_win->old_bw - tmp_win->frame_bw;
794 tmp_win->frame_width = tmp_win->attr.width;
795 tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height;
796
797 valuemask = CWBackPixmap(1L<<0) | CWBorderPixel(1L<<3) | CWCursor(1L<<14) | CWEventMask(1L<<11);
798 attributes.background_pixmap = None0L;
799 attributes.border_pixel = tmp_win->border;
800 attributes.cursor = Scr->FrameCursor;
801 attributes.event_mask = (SubstructureRedirectMask(1L<<20) |
802 ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3) |
803 EnterWindowMask(1L<<4) | LeaveWindowMask(1L<<5));
804 if (tmp_win->attr.save_under) {
805 attributes.save_under = True1;
806 valuemask |= CWSaveUnder(1L<<10);
807 }
808
809 tmp_win->frame = XCreateWindow (dpy, Scr->Root, tmp_win->frame_x,
810 tmp_win->frame_y,
811 (unsigned int) tmp_win->frame_width,
812 (unsigned int) tmp_win->frame_height,
813 (unsigned int) tmp_win->frame_bw,
814 Scr->d_depth,
815 (unsigned int) CopyFromParent0L,
816 Scr->d_visual, valuemask, &attributes);
817
818 if (tmp_win->title_height)
819 {
820 valuemask = (CWEventMask(1L<<11) | CWBorderPixel(1L<<3) | CWBackPixel(1L<<1));
821 attributes.event_mask = (KeyPressMask(1L<<0) | ButtonPressMask(1L<<2) |
822 ButtonReleaseMask(1L<<3) | ExposureMask(1L<<15));
823 attributes.border_pixel = tmp_win->border;
824 attributes.background_pixel = tmp_win->title.back;
825 tmp_win->title_w = XCreateWindow (dpy, tmp_win->frame,
826 -tmp_win->frame_bw,
827 -tmp_win->frame_bw,
828 (unsigned int) tmp_win->attr.width,
829 (unsigned int) Scr->TitleHeight,
830 (unsigned int) tmp_win->frame_bw,
831 Scr->d_depth,
832 (unsigned int) CopyFromParent0L,
833 Scr->d_visual, valuemask,
834 &attributes);
835 }
836 else {
837 tmp_win->title_w = 0;
838 tmp_win->squeeze_info = NULL((void*)0);
839 }
840
841 if (tmp_win->highlight)
842 {
843 tmp_win->gray = XCreatePixmapFromBitmapData(dpy, Scr->Root,
844 gray_bits, gray_width2, gray_height2,
845 tmp_win->border_tile.fore, tmp_win->border_tile.back,
846 Scr->d_depth);
847
848 SetBorder (tmp_win, False0);
849 }
850 else
851 tmp_win->gray = None0L;
852
853
854 if (tmp_win->title_w) {
855 CreateWindowTitlebarButtons (tmp_win);
856 ComputeTitleLocation (tmp_win);
857 XMoveWindow (dpy, tmp_win->title_w,
858 tmp_win->title_x, tmp_win->title_y);
859 XDefineCursor(dpy, tmp_win->title_w, Scr->TitleCursor);
860 }
861
862 valuemask = (CWEventMask(1L<<11) | CWDontPropagate(1L<<12));
863 attributes.event_mask = (StructureNotifyMask(1L<<17) | PropertyChangeMask(1L<<22) |
864 ColormapChangeMask(1L<<23) | VisibilityChangeMask(1L<<16) |
865 EnterWindowMask(1L<<4) | LeaveWindowMask(1L<<5));
866 attributes.do_not_propagate_mask = ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3);
867 XChangeWindowAttributes (dpy, tmp_win->w, valuemask, &attributes);
868
869 if (HasShape)
870 XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask(1L << 0));
871
872 if (tmp_win->title_w) {
873 XMapWindow (dpy, tmp_win->title_w);
874 }
875
876 if (HasShape) {
877 int xws, yws, xbs, ybs;
878 unsigned wws, hws, wbs, hbs;
879 int boundingShaped, clipShaped;
880
881 XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask(1L << 0));
882 XShapeQueryExtents (dpy, tmp_win->w,
883 &boundingShaped, &xws, &yws, &wws, &hws,
884 &clipShaped, &xbs, &ybs, &wbs, &hbs);
885 tmp_win->wShaped = boundingShaped;
886 }
887
888 if (!tmp_win->iconmgr)
889 XAddToSaveSet(dpy, tmp_win->w);
890
891 XReparentWindow(dpy, tmp_win->w, tmp_win->frame, 0, tmp_win->title_height);
892 /*
893 * Reparenting generates an UnmapNotify event, followed by a MapNotify.
894 * Set the map state to FALSE to prevent a transition back to
895 * WithdrawnState in HandleUnmapNotify. Map state gets set correctly
896 * again in HandleMapNotify.
897 */
898 tmp_win->mapped = FALSE0;
899
900 SetupFrame (tmp_win, tmp_win->frame_x, tmp_win->frame_y,
901 tmp_win->frame_width, tmp_win->frame_height, -1, True1);
902
903 /* wait until the window is iconified and the icon window is mapped
904 * before creating the icon window
905 */
906 tmp_win->icon_w = (Window) 0;
907
908 if (!tmp_win->iconmgr)
909 {
910 GrabButtons(tmp_win);
911 GrabKeys(tmp_win);
912 }
913
914 (void) AddIconManager(tmp_win);
915
916 XSaveContext(dpy, tmp_win->w, TwmContext, (caddr_t) tmp_win);
917 XSaveContext(dpy, tmp_win->w, ScreenContext, (caddr_t) Scr);
918 XSaveContext(dpy, tmp_win->frame, TwmContext, (caddr_t) tmp_win);
919 XSaveContext(dpy, tmp_win->frame, ScreenContext, (caddr_t) Scr);
920 if (tmp_win->title_height)
921 {
922 int i;
923 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
924
925 XSaveContext(dpy, tmp_win->title_w, TwmContext, (caddr_t) tmp_win);
926 XSaveContext(dpy, tmp_win->title_w, ScreenContext, (caddr_t) Scr);
927 for (i = 0; i < nb; i++) {
928 XSaveContext(dpy, tmp_win->titlebuttons[i].window, TwmContext,
929 (caddr_t) tmp_win);
930 XSaveContext(dpy, tmp_win->titlebuttons[i].window, ScreenContext,
931 (caddr_t) Scr);
932 }
933 if (tmp_win->hilite_w)
934 {
935 XSaveContext(dpy, tmp_win->hilite_w, TwmContext, (caddr_t)tmp_win);
936 XSaveContext(dpy, tmp_win->hilite_w, ScreenContext, (caddr_t)Scr);
937 }
938 }
939
940 XUngrabServer(dpy);
941
942 /* if we were in the middle of a menu activated function, regrab
943 * the pointer
944 */
945 if (RootFunction)
946 ReGrab();
947
948 return (tmp_win);
949}
950
951
952/**
953 * checks to see if we should really put a twm frame on the window
954 *
955 * \return TRUE - go ahead and place the window
956 * \return FALSE - don't frame the window
957 * \param w the window to check
958 */
959int
960MappedNotOverride(Window w)
961{
962 XWindowAttributes wa;
963
964 XGetWindowAttributes(dpy, w, &wa);
965 return ((wa.map_state != IsUnmapped0) && (wa.override_redirect != True1));
966}
967
968
969/**
970 * attach default bindings so that naive users don't get messed up if they
971 * provide a minimal twmrc.
972 */
973static void do_add_binding (int button, int context, int modifier, int func)
974{
975 MouseButton *mb = &Scr->Mouse[button][context][modifier];
976
977 if (mb->func) return; /* already defined */
978
979 mb->func = func;
980 mb->item = NULL((void*)0);
981}
982
983void
984AddDefaultBindings (void)
985{
986 /*
987 * The bindings are stored in Scr->Mouse, indexed by
988 * Mouse[button_number][C_context][modifier].
989 */
990
991#define NoModifierMask 0
992
993 do_add_binding (Button11, C_TITLE1, NoModifierMask, F_MOVE8);
994 do_add_binding (Button11, C_ICON2, NoModifierMask, F_ICONIFY13);
995 do_add_binding (Button11, C_ICONMGR5, NoModifierMask, F_ICONIFY13);
996
997 do_add_binding (Button22, C_TITLE1, NoModifierMask, F_RAISELOWER25);
998 do_add_binding (Button22, C_ICON2, NoModifierMask, F_ICONIFY13);
999 do_add_binding (Button22, C_ICONMGR5, NoModifierMask, F_ICONIFY13);
1000
1001#undef NoModifierMask
1002}
1003
1004
1005
1006
1007/**
1008 * grab needed buttons for the window
1009 *
1010 * \param[in] tmp_win the twm window structure to use
1011 */
1012void
1013GrabButtons(TwmWindow *tmp_win)
1014{
1015 int i, j;
1016
1017 for (i = 0; i < MAX_BUTTONS16+1; i++)
1018 {
1019 for (j = 0; j < MOD_SIZE(((1<<0) | (1<<2) | (1<<3) | (1<<4) |
(1<<5) | (1<<6) | (1<<7)) + 1)
; j++)
1020 {
1021 if (Scr->Mouse[i][C_WINDOW0][j].func != 0)
1022 {
1023 /* twm used to do this grab on the application main window,
1024 * tmp_win->w . This was not ICCCM complient and was changed.
1025 */
1026 XGrabButton(dpy, i, j, tmp_win->frame,
1027 True1, ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3),
1028 GrabModeAsync1, GrabModeAsync1, None0L,
1029 Scr->FrameCursor);
1030 }
1031 }
1032 }
1033}
1034
1035/**
1036 * grab needed keys for the window
1037 *
1038 * \param[in] tmp_win the twm window structure to use
1039 */
1040void
1041GrabKeys(TwmWindow *tmp_win)
1042{
1043 FuncKey *tmp;
1044 IconMgr *p;
1045
1046 for (tmp = Scr->FuncKeyRoot.next; tmp != NULL((void*)0); tmp = tmp->next)
1047 {
1048 switch (tmp->cont)
1049 {
1050 case C_WINDOW0:
1051 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True1,
1052 GrabModeAsync1, GrabModeAsync1);
1053 break;
1054
1055 case C_ICON2:
1056 if (tmp_win->icon_w)
1057 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w, True1,
1058 GrabModeAsync1, GrabModeAsync1);
1059
1060 case C_TITLE1:
1061 if (tmp_win->title_w)
1062 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w, True1,
1063 GrabModeAsync1, GrabModeAsync1);
1064 break;
1065
1066 case C_NAME6:
1067 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True1,
1068 GrabModeAsync1, GrabModeAsync1);
1069 if (tmp_win->icon_w)
1070 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w, True1,
1071 GrabModeAsync1, GrabModeAsync1);
1072 if (tmp_win->title_w)
1073 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w, True1,
1074 GrabModeAsync1, GrabModeAsync1);
1075 break;
1076 /*
1077 case C_ROOT:
1078 XGrabKey(dpy, tmp->keycode, tmp->mods, Scr->Root, True,
1079 GrabModeAsync, GrabModeAsync);
1080 break;
1081 */
1082 }
1083 }
1084 for (tmp = Scr->FuncKeyRoot.next; tmp != NULL((void*)0); tmp = tmp->next)
1085 {
1086 if (tmp->cont == C_ICONMGR5 && !Scr->NoIconManagers)
1087 {
1088 for (p = &Scr->iconmgr; p != NULL((void*)0); p = p->next)
1089 {
1090 XUngrabKey(dpy, tmp->keycode, tmp->mods, p->twm_win->w);
1091 }
1092 }
1093 }
1094}
1095
1096static Window CreateHighlightWindow (TwmWindow *tmp_win)
1097{
1098 XSetWindowAttributes attributes; /* attributes for create windows */
1099 Pixmap pm = None0L;
1100 GC gc;
1101 XGCValues gcv;
1102 unsigned long valuemask;
1103 int h = (Scr->TitleHeight - 2 * Scr->FramePadding);
1104 Window w;
1105
1106
1107 /*
1108 * If a special highlight pixmap was given, use that. Otherwise,
1109 * use a nice, even gray pattern. The old horizontal lines look really
1110 * awful on interlaced monitors (as well as resembling other looks a
1111 * little bit too closely), but can be used by putting
1112 *
1113 * Pixmaps { TitleHighlight "hline2" }
1114 *
1115 * (or whatever the horizontal line bitmap is named) in the startup
1116 * file. If all else fails, use the foreground color to look like a
1117 * solid line.
1118 */
1119 if (!Scr->hilitePm) {
1120 Scr->hilitePm = XCreateBitmapFromData (dpy, tmp_win->title_w,
1121 gray_bits, gray_width2,
1122 gray_height2);
1123 Scr->hilite_pm_width = gray_width2;
1124 Scr->hilite_pm_height = gray_height2;
1125 }
1126 if (Scr->hilitePm) {
1127 pm = XCreatePixmap (dpy, tmp_win->title_w,
1128 Scr->hilite_pm_width, Scr->hilite_pm_height,
1129 Scr->d_depth);
1130 gcv.foreground = tmp_win->title.fore;
1131 gcv.background = tmp_win->title.back;
1132 gcv.graphics_exposures = False0;
1133 gc = XCreateGC (dpy, pm,
1134 (GCForeground(1L<<2)|GCBackground(1L<<3)|GCGraphicsExposures(1L<<16)),
1135 &gcv);
1136 if (gc) {
1137 XCopyPlane (dpy, Scr->hilitePm, pm, gc, 0, 0,
1138 Scr->hilite_pm_width, Scr->hilite_pm_height,
1139 0, 0, 1);
1140 XFreeGC (dpy, gc);
1141 } else {
1142 XFreePixmap (dpy, pm);
1143 pm = None0L;
1144 }
1145 }
1146 if (pm) {
1147 valuemask = CWBackPixmap(1L<<0);
1148 attributes.background_pixmap = pm;
1149 } else {
1150 valuemask = CWBackPixel(1L<<1);
1151 attributes.background_pixel = tmp_win->title.fore;
1152 }
1153
1154 w = XCreateWindow (dpy, tmp_win->title_w, 0, Scr->FramePadding,
1155 (unsigned int) Scr->TBInfo.width, (unsigned int) h,
1156 (unsigned int) 0,
1157 Scr->d_depth, (unsigned int) CopyFromParent0L,
1158 Scr->d_visual, valuemask, &attributes);
1159 if (pm) XFreePixmap (dpy, pm);
1160 return w;
1161}
1162
1163
1164void ComputeCommonTitleOffsets (void)
1165{
1166 int buttonwidth = (Scr->TBInfo.width + Scr->TBInfo.pad);
1167
1168 Scr->TBInfo.leftx = Scr->TBInfo.rightoff = Scr->FramePadding;
1169 if (Scr->TBInfo.nleft > 0)
1170 Scr->TBInfo.leftx += Scr->ButtonIndent;
1171 Scr->TBInfo.titlex = (Scr->TBInfo.leftx +
1172 (Scr->TBInfo.nleft * buttonwidth) - Scr->TBInfo.pad +
1173 Scr->TitlePadding);
1174 if (Scr->TBInfo.nright > 0)
1175 Scr->TBInfo.rightoff += (Scr->ButtonIndent +
1176 ((Scr->TBInfo.nright * buttonwidth) -
1177 Scr->TBInfo.pad));
1178 return;
1179}
1180
1181void ComputeWindowTitleOffsets (TwmWindow *tmp_win, int width, Boolint squeeze)
1182{
1183 tmp_win->highlightx = (Scr->TBInfo.titlex + tmp_win->name_width);
1184 if (tmp_win->hilite_w || Scr->TBInfo.nright > 0)
1185 tmp_win->highlightx += Scr->TitlePadding;
1186 tmp_win->rightx = width - Scr->TBInfo.rightoff;
1187 if (squeeze && tmp_win->squeeze_info) {
1188 int rx = (tmp_win->highlightx +
1189 (tmp_win->hilite_w
1190 ? Scr->TBInfo.width * 2 : 0) +
1191 (Scr->TBInfo.nright > 0 ? Scr->TitlePadding : 0) +
1192 Scr->FramePadding);
1193 if (rx < tmp_win->rightx) tmp_win->rightx = rx;
1194 }
1195 return;
1196}
1197
1198
1199/**
1200 * calculate the position of the title window. We need to take the frame_bw
1201 * into account since we want (0,0) of the title window to line up with (0,0)
1202 * of the frame window.
1203 */
1204void ComputeTitleLocation (register TwmWindow *tmp)
1205{
1206 tmp->title_x = -tmp->frame_bw;
1207 tmp->title_y = -tmp->frame_bw;
1208
1209 if (tmp->squeeze_info) {
1210 register SqueezeInfo *si = tmp->squeeze_info;
1211 int basex;
1212 int maxwidth = tmp->frame_width;
1213 int tw = tmp->title_width;
1214
1215 /*
1216 * figure label base from squeeze info (justification fraction)
1217 */
1218 if (si->denom == 0) { /* num is pixel based */
1219 if ((basex = si->num) == 0) { /* look for special cases */
1220 switch (si->justify) {
1221 case J_RIGHT3:
1222 basex = maxwidth;
1223 break;
1224 case J_CENTER2:
1225 basex = maxwidth / 2;
1226 break;
1227 }
1228 }
1229 } else { /* num/denom is fraction */
1230 basex = ((si->num * maxwidth) / si->denom);
1231 if (si->num < 0) basex += maxwidth;
1232 }
1233
1234 /*
1235 * adjust for left (nop), center, right justify and clip
1236 */
1237 switch (si->justify) {
1238 case J_CENTER2:
1239 basex -= tw / 2;
1240 break;
1241 case J_RIGHT3:
1242 basex -= tw - 1;
1243 break;
1244 }
1245 if (basex > maxwidth - tw + 1)
1246 basex = maxwidth - tw + 1;
1247 if (basex < 0) basex = 0;
1248
1249 tmp->title_x = basex - tmp->frame_bw;
1250 }
1251}
1252
1253
1254static void CreateWindowTitlebarButtons (TwmWindow *tmp_win)
1255{
1256 unsigned long valuemask; /* mask for create windows */
1257 XSetWindowAttributes attributes; /* attributes for create windows */
1258 int leftx, rightx, y;
1259 TitleButton *tb;
1260 int nb;
1261
1262 if (tmp_win->title_height == 0)
1263 {
1264 tmp_win->hilite_w = 0;
1265 return;
1266 }
1267
1268
1269 /*
1270 * create the title bar windows; let the event handler deal with painting
1271 * so that we don't have to spend two pixmaps (or deal with hashing)
1272 */
1273 ComputeWindowTitleOffsets (tmp_win, tmp_win->attr.width, False0);
1274
1275 leftx = y = Scr->TBInfo.leftx;
1276 rightx = tmp_win->rightx;
1277
1278 attributes.win_gravity = NorthWestGravity1;
1279 attributes.background_pixel = tmp_win->title.back;
1280 attributes.border_pixel = tmp_win->title.fore;
1281 attributes.event_mask = (ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3) |
1282 ExposureMask(1L<<15));
1283 attributes.cursor = Scr->ButtonCursor;
1284 valuemask = (CWWinGravity(1L<<5) | CWBackPixel(1L<<1) | CWBorderPixel(1L<<3) | CWEventMask(1L<<11) |
1285 CWCursor(1L<<14));
1286
1287 tmp_win->titlebuttons = NULL((void*)0);
1288 nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
1289 if (nb > 0) {
1290 tmp_win->titlebuttons = malloc (nb * sizeof(TBWindow));
1291 if (!tmp_win->titlebuttons) {
1292 fprintf (stderr__stderrp, "%s: unable to allocate %d titlebuttons\n",
1293 ProgramName, nb);
1294 } else {
1295 TBWindow *tbw;
1296 int boxwidth = (Scr->TBInfo.width + Scr->TBInfo.pad);
1297 unsigned int h = (Scr->TBInfo.width - Scr->TBInfo.border * 2);
1298
1299 for (tb = Scr->TBInfo.head, tbw = tmp_win->titlebuttons; tb;
1300 tb = tb->next, tbw++) {
1301 int x;
1302 if (tb->rightside) {
1303 x = rightx;
1304 rightx += boxwidth;
1305 attributes.win_gravity = NorthEastGravity3;
1306 } else {
1307 x = leftx;
1308 leftx += boxwidth;
1309 attributes.win_gravity = NorthWestGravity1;
1310 }
1311 tbw->window = XCreateWindow (dpy, tmp_win->title_w, x, y, h, h,
1312 (unsigned int) Scr->TBInfo.border,
1313 0, (unsigned int) CopyFromParent0L,
1314 (Visual *) CopyFromParent0L,
1315 valuemask, &attributes);
1316 tbw->info = tb;
1317 }
1318 }
1319 }
1320
1321 tmp_win->hilite_w = (tmp_win->titlehighlight
1322 ? CreateHighlightWindow (tmp_win) : None0L);
1323
1324 XMapSubwindows(dpy, tmp_win->title_w);
1325 if (tmp_win->hilite_w)
1326 XUnmapWindow(dpy, tmp_win->hilite_w);
1327 return;
1328}
1329
1330
1331void
1332SetHighlightPixmap (char *filename)
1333{
1334 Pixmap pm = GetBitmap (filename);
1335
1336 if (pm) {
1337 if (Scr->hilitePm) {
1338 XFreePixmap (dpy, Scr->hilitePm);
1339 }
1340 Scr->hilitePm = pm;
1341 Scr->hilite_pm_width = JunkWidth;
1342 Scr->hilite_pm_height = JunkHeight;
1343 }
1344}
1345
1346
1347void
1348FetchWmProtocols (TwmWindow *tmp)
1349{
1350 unsigned long flags = 0L;
1351 Atom *protocols = NULL((void*)0);
1352 int n;
1353
1354 if (XGetWMProtocols (dpy, tmp->w, &protocols, &n)) {
1355 register int i;
1356 register Atom *ap;
1357
1358 for (i = 0, ap = protocols; i < n; i++, ap++) {
1359 if (*ap == _XA_WM_TAKE_FOCUSTwmAtoms[5]) flags |= DoesWmTakeFocus(1L << 0);
1360 if (*ap == _XA_WM_SAVE_YOURSELFTwmAtoms[6]) flags |= DoesWmSaveYourself(1L << 1);
1361 if (*ap == _XA_WM_DELETE_WINDOWTwmAtoms[7]) flags |= DoesWmDeleteWindow(1L << 2);
1362 }
1363 if (protocols) XFree (protocols);
1364 }
1365 tmp->protocols = flags;
1366}
1367
1368TwmColormap *
1369CreateTwmColormap(Colormap c)
1370{
1371 TwmColormap *cmap;
1372 cmap = malloc(sizeof(TwmColormap));
1373 if (!cmap ||
1374 XSaveContext(dpy, c, ColormapContext, (caddr_t) cmap)) {
1375 if (cmap) free(cmap);
1376 return (NULL((void*)0));
1377 }
1378 cmap->c = c;
1379 cmap->state = 0;
1380 cmap->install_req = 0;
1381 cmap->w = None0L;
1382 cmap->refcnt = 1;
1383 return (cmap);
1384}
1385
1386ColormapWindow *
1387CreateColormapWindow(Window w, Boolint creating_parent, Boolint property_window)
1388{
1389 ColormapWindow *cwin;
1390 TwmColormap *cmap;
1391 XWindowAttributes attributes;
1392
1393 cwin = malloc(sizeof(ColormapWindow));
1394 if (cwin) {
1395 if (!XGetWindowAttributes(dpy, w, &attributes) ||
1396 XSaveContext(dpy, w, ColormapContext, (caddr_t) cwin)) {
1397 free(cwin);
1398 return (NULL((void*)0));
1399 }
1400
1401 if (XFindContext(dpy, attributes.colormap, ColormapContext,
1402 (caddr_t *)&cwin->colormap) == XCNOENT2) {
1403 cwin->colormap = cmap = CreateTwmColormap(attributes.colormap);
1404 if (!cmap) {
1405 XDeleteContext(dpy, w, ColormapContext);
1406 free(cwin);
1407 return (NULL((void*)0));
1408 }
1409 } else {
1410 cwin->colormap->refcnt++;
1411 }
1412
1413 cwin->w = w;
1414 /*
1415 * Assume that windows in colormap list are
1416 * obscured if we are creating the parent window.
1417 * Otherwise, we assume they are unobscured.
1418 */
1419 cwin->visibility = creating_parent ?
1420 VisibilityPartiallyObscured1 : VisibilityUnobscured0;
1421 cwin->refcnt = 1;
1422
1423 /*
1424 * If this is a ColormapWindow property window and we
1425 * are not monitoring ColormapNotify or VisibilityNotify
1426 * events, we need to.
1427 */
1428 if (property_window &&
1429 (attributes.your_event_mask &
1430 (ColormapChangeMask(1L<<23)|VisibilityChangeMask(1L<<16))) !=
1431 (ColormapChangeMask(1L<<23)|VisibilityChangeMask(1L<<16))) {
1432 XSelectInput(dpy, w, attributes.your_event_mask |
1433 (ColormapChangeMask(1L<<23)|VisibilityChangeMask(1L<<16)));
1434 }
1435 }
1436
1437 return (cwin);
1438}
1439
1440void
1441FetchWmColormapWindows (TwmWindow *tmp)
1442{
1443 register int i, j;
1444 Window *cmap_windows = NULL((void*)0);
1445 Boolint can_free_cmap_windows = False0;
1446 int number_cmap_windows = 0;
1447 ColormapWindow **cwins = NULL((void*)0);
1448 int previously_installed;
1449
1450 number_cmap_windows = 0;
1451
1452 if (/* SUPPRESS 560 */(previously_installed =
1
Taking false branch
1453 (Scr->cmapInfo.cmaps == &tmp->cmaps && tmp->cmaps.number_cwins))) {
1454 cwins = tmp->cmaps.cwins;
1455 for (i = 0; i < tmp->cmaps.number_cwins; i++)
1456 cwins[i]->colormap->state = 0;
1457 }
1458
1459 if (XGetWMColormapWindows (dpy, tmp->w, &cmap_windows,
3
Taking true branch
1460 &number_cmap_windows) &&
1461 number_cmap_windows > 0) {
2
Assuming 'number_cmap_windows' is > 0
1462
1463 can_free_cmap_windows = False0;
1464 /*
1465 * check if the top level is in the list, add to front if not
1466 */
1467 for (i = 0; i < number_cmap_windows; i++) {
4
Loop condition is true. Entering loop body
1468 if (cmap_windows[i] == tmp->w) break;
5
Taking true branch
6
Execution continues on line 1470
1469 }
1470 if (i == number_cmap_windows) { /* not in list */
7
Taking false branch
1471 Window *new_cmap_windows =
1472 malloc (sizeof(Window) * (number_cmap_windows + 1));
1473
1474 if (!new_cmap_windows) {
1475 fprintf (stderr__stderrp,
1476 "%s: unable to allocate %d element colormap window array\n",
1477 ProgramName, number_cmap_windows+1);
1478 goto done;
1479 }
1480 new_cmap_windows[0] = tmp->w; /* add to front */
1481 for (i = 0; i < number_cmap_windows; i++) { /* append rest */
1482 new_cmap_windows[i+1] = cmap_windows[i];
1483 }
1484 XFree (cmap_windows);
1485 can_free_cmap_windows = True1; /* do not use XFree any more */
1486 cmap_windows = new_cmap_windows;
1487 number_cmap_windows++;
1488 }
1489
1490 cwins = malloc(sizeof(ColormapWindow *) * number_cmap_windows);
8
Memory is allocated
1491 if (cwins) {
9
Assuming 'cwins' is non-null
10
Taking true branch
1492 for (i = 0; i < number_cmap_windows; i++) {
11
Loop condition is true. Entering loop body
18
Loop condition is false. Execution continues on line 1531
1493
1494 /*
1495 * Copy any existing entries into new list.
1496 */
1497 for (j = 0; j < tmp->cmaps.number_cwins; j++) {
12
Loop condition is false. Execution continues on line 1510
1498 if (tmp->cmaps.cwins[j]->w == cmap_windows[i]) {
1499 cwins[i] = tmp->cmaps.cwins[j];
1500 cwins[i]->refcnt++;
1501 break;
1502 }
1503 }
1504
1505 /*
1506 * If the colormap window is not being pointed by
1507 * some other applications colormap window list,
1508 * create a new entry.
1509 */
1510 if (j == tmp->cmaps.number_cwins) {
13
Taking true branch
1511 if (XFindContext(dpy, cmap_windows[i], ColormapContext,
14
Taking true branch
1512 (caddr_t *)&cwins[i]) == XCNOENT2) {
1513 if ((cwins[i] = CreateColormapWindow(cmap_windows[i],
15
Taking true branch
1514 (Boolint) tmp->cmaps.number_cwins == 0,
1515 True1)) == NULL((void*)0)) {
1516 int k;
1517 for (k = i + 1; k < number_cmap_windows; k++)
16
Assuming 'k' is >= 'number_cmap_windows'
17
Loop condition is false. Execution continues on line 1519
1518 cmap_windows[k-1] = cmap_windows[k];
1519 i--;
1520 number_cmap_windows--;
1521 }
1522 } else
1523 cwins[i]->refcnt++;
1524 }
1525 }
1526 }
1527 }
1528
1529 /* No else here, in case we bailed out of clause above.
1530 */
1531 if (number_cmap_windows == 0) {
19
Taking true branch
1532
1533 number_cmap_windows = 1;
1534
1535 cwins = malloc(sizeof(ColormapWindow *));
1536 if (XFindContext(dpy, tmp->w, ColormapContext, (caddr_t *)&cwins[0]) ==
20
Potential leak of memory pointed to by 'cwins'
1537 XCNOENT2) {
1538 cwins[0] = CreateColormapWindow(tmp->w,
1539 (Boolint) tmp->cmaps.number_cwins == 0, False0);
1540 if (cwins[0] == NULL((void*)0))
1541 number_cmap_windows = 0;
1542 } else
1543 cwins[0]->refcnt++;
1544 }
1545
1546 if (tmp->cmaps.number_cwins)
1547 free_cwins(tmp);
1548
1549 tmp->cmaps.cwins = cwins;
1550 tmp->cmaps.number_cwins = number_cmap_windows;
1551 if (number_cmap_windows > 1)
1552 tmp->cmaps.scoreboard =
1553 calloc(1, ColormapsScoreboardLength(&tmp->cmaps)((&tmp->cmaps)->number_cwins * ((&tmp->cmaps
)->number_cwins - 1) / 2)
);
1554
1555 if (previously_installed)
1556 InstallWindowColormaps(PropertyNotify28, (TwmWindow *) NULL((void*)0));
1557
1558 done:
1559 if (cmap_windows) {
1560 if (can_free_cmap_windows)
1561 free (cmap_windows);
1562 else
1563 XFree (cmap_windows);
1564 }
1565
1566 return;
1567}
1568
1569
1570void GetWindowSizeHints (TwmWindow *tmp)
1571{
1572 long supplied = 0;
1573
1574 if (!XGetWMNormalHints (dpy, tmp->w, &tmp->hints, &supplied))
1575 tmp->hints.flags = 0;
1576
1577 if (tmp->hints.flags & PResizeInc(1L << 6)) {
1578 if (tmp->hints.width_inc == 0) tmp->hints.width_inc = 1;
1579 if (tmp->hints.height_inc == 0) tmp->hints.height_inc = 1;
1580 }
1581
1582 if (!(supplied & PWinGravity(1L << 9)) && (tmp->hints.flags & USPosition(1L << 0))) {
1583 static int gravs[] = { SouthEastGravity9, SouthWestGravity7,
1584 NorthEastGravity3, NorthWestGravity1 };
1585 int right = tmp->attr.x + tmp->attr.width + 2 * tmp->old_bw;
1586 int bottom = tmp->attr.y + tmp->attr.height + 2 * tmp->old_bw;
1587 tmp->hints.win_gravity =
1588 gravs[((Scr->MyDisplayHeight - bottom < tmp->title_height) ? 0 : 2) |
1589 ((Scr->MyDisplayWidth - right < tmp->title_height) ? 0 : 1)];
1590 tmp->hints.flags |= PWinGravity(1L << 9);
1591 }
1592}