add_window.c revision 645f5050
1/*****************************************************************************/ 2/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ 3/** Salt Lake City, Utah **/ 4/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ 5/** Cambridge, Massachusetts **/ 6/** **/ 7/** All Rights Reserved **/ 8/** **/ 9/** Permission to use, copy, modify, and distribute this software and **/ 10/** its documentation for any purpose and without fee is hereby **/ 11/** granted, provided that the above copyright notice appear in all **/ 12/** copies and that both that copyright notice and this permis- **/ 13/** sion notice appear in supporting documentation, and that the **/ 14/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ 15/** in publicity pertaining to distribution of the software without **/ 16/** specific, written prior permission. **/ 17/** **/ 18/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ 19/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ 20/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ 21/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ 22/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ 23/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ 24/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ 25/** OR PERFORMANCE OF THIS SOFTWARE. **/ 26/*****************************************************************************/ 27 28/* 29 * [ ctwm ] 30 * 31 * Copyright 1992 Claude Lecommandeur. 32 * 33 * Permission to use, copy, modify and distribute this software [ctwm] and 34 * its documentation for any purpose is hereby granted without fee, provided 35 * that the above copyright notice appear in all copies and that both that 36 * copyright notice and this permission notice appear in supporting documen- 37 * tation, and that the name of Claude Lecommandeur not be used in adverti- 38 * sing or publicity pertaining to distribution of the software without 39 * specific, written prior permission. Claude Lecommandeur make no represen- 40 * tations about the suitability of this software for any purpose. It is 41 * provided "as is" without express or implied warranty. 42 * 43 * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 44 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 45 * EVENT SHALL Claude Lecommandeur BE LIABLE FOR ANY SPECIAL, INDIRECT OR 46 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 47 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 48 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 49 * PERFORMANCE OF THIS SOFTWARE. 50 * 51 * Author: Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ] 52 */ 53 54/********************************************************************** 55 * 56 * $XConsortium: add_window.c,v 1.153 91/07/10 13:17:26 dave Exp $ 57 * 58 * Add a new window, put the titlbar and other stuff around 59 * the window 60 * 61 * 31-Mar-88 Tom LaStrange Initial Version. 62 * 63 * Do the necessary modification to be integrated in ctwm. 64 * Can no longer be used for the standard twm. 65 * 66 * 22-April-92 Claude Lecommandeur. 67 * 68 **********************************************************************/ 69 70#include <stdio.h> 71#include <string.h> 72#ifndef VMS 73#include <sys/time.h> 74#else 75#include <time.h> 76#endif 77#if defined(AIXV3) || defined(_SYSTYPE_SVR4) || defined(ibm) || defined __QNX__ 78#include <sys/select.h> 79#endif 80#include "twm.h" 81#ifdef VMS 82#include <decw$include/Xatom.h> 83#else 84#include <X11/Xatom.h> 85#endif 86#include "add_window.h" 87#include "windowbox.h" 88#include "util.h" 89#include "resize.h" 90#include "parse.h" 91#include "list.h" 92#include "events.h" 93#include "menus.h" 94#include "screen.h" 95#include "icons.h" 96#include "iconmgr.h" 97#include "session.h" 98#include "mwmhints.h" 99 100#define gray_width 2 101#define gray_height 2 102static unsigned char gray_bits[] = { 103 0x02, 0x01}; 104static unsigned char black_bits[] = { 105 0xFF, 0xFF}; 106 107int AddingX; 108int AddingY; 109unsigned int AddingW; 110unsigned int AddingH; 111 112static int PlaceX = -1; 113static int PlaceY = -1; 114static void CreateWindowTitlebarButtons(TwmWindow *tmp_win); 115void DealWithNonSensicalGeometries(Display *dpy, Window vroot, TwmWindow *tmp_win); 116 117static void splitWindowRegionEntry (WindowEntry *we, 118 int grav1, int grav2, 119 int w, int h); 120static WindowEntry *findWindowEntry (WorkSpace *wl, 121 TwmWindow *tmp_win, 122 WindowRegion **wrp); 123static WindowEntry *prevWindowEntry (WindowEntry *we, 124 WindowRegion *wr); 125static void mergeWindowEntries (WindowEntry *old, WindowEntry *we); 126 127char NoName[] = "Untitled"; /* name if no name is specified */ 128int resizeWhenAdd; 129 130extern Atom _OL_WIN_ATTR; 131 132#if defined(__hpux) && !defined(_XPG4_EXTENDED) 133# define FDSET int* 134#else 135# define FDSET fd_set* 136#endif 137/************************************************************************ 138 * 139 * Procedure: 140 * GetGravityOffsets - map gravity to (x,y) offset signs for adding 141 * to x and y when window is mapped to get proper placement. 142 * 143 ************************************************************************ 144 */ 145 146void GetGravityOffsets (TwmWindow *tmp, /* window from which to get gravity */ 147 int *xp, int *yp) /* return values */ 148{ 149 static struct _gravity_offset { 150 int x, y; 151 } gravity_offsets[11] = { 152 { 0, 0 }, /* ForgetGravity */ 153 { -1, -1 }, /* NorthWestGravity */ 154 { 0, -1 }, /* NorthGravity */ 155 { 1, -1 }, /* NorthEastGravity */ 156 { -1, 0 }, /* WestGravity */ 157 { 0, 0 }, /* CenterGravity */ 158 { 1, 0 }, /* EastGravity */ 159 { -1, 1 }, /* SouthWestGravity */ 160 { 0, 1 }, /* SouthGravity */ 161 { 1, 1 }, /* SouthEastGravity */ 162 { 0, 0 }, /* StaticGravity */ 163 }; 164 register int g = ((tmp->hints.flags & PWinGravity) 165 ? tmp->hints.win_gravity : NorthWestGravity); 166 167 if (g < ForgetGravity || g > StaticGravity) { 168 *xp = *yp = 0; 169 } else { 170 *xp = gravity_offsets[g].x; 171 *yp = gravity_offsets[g].y; 172 } 173} 174 175 176 177 178/*********************************************************************** 179 * 180 * Procedure: 181 * AddWindow - add a new window to the twm list 182 * 183 * Returned Value: 184 * (TwmWindow *) - pointer to the TwmWindow structure 185 * 186 * Inputs: 187 * w - the window id of the window to add 188 * iconm - flag to tell if this is an icon manager window 189 * 0 --> normal window. 190 * 1 --> icon manager. 191 * 2 --> window box; 192 * else --> iconmgr; 193 * 194 * iconp - pointer to icon manager struct 195 * 196 *********************************************************************** 197 */ 198 199TwmWindow *AddWindow(Window w, int iconm, IconMgr *iconp) 200{ 201 virtualScreen *vs; 202 TwmWindow *tmp_win; /* new twm window structure */ 203 int stat; 204 XEvent event; 205 unsigned long valuemask; /* mask for create windows */ 206 XSetWindowAttributes attributes; /* attributes for create windows */ 207 int width, height; /* tmp variable */ 208 int ask_user; /* don't know where to put the window */ 209 int gravx, gravy; /* gravity signs for positioning */ 210 int namelen; 211 int bw2; 212 short saved_x, saved_y, restore_icon_x, restore_icon_y; 213 unsigned short saved_width, saved_height; 214 Bool restore_iconified = 0; 215 Bool restore_icon_info_present = 0; 216 int restoredFromPrevSession; 217 Bool width_ever_changed_by_user; 218 Bool height_ever_changed_by_user; 219 int saved_occupation; /* <== [ Matthew McNeill Feb 1997 ] == */ 220 Bool random_placed = False; 221 int found = 0; 222#ifndef VMS 223 fd_set mask; 224 int fd; 225 struct timeval timeout; 226#endif 227 XRectangle ink_rect; 228 XRectangle logical_rect; 229 WindowBox *winbox; 230 int iswinbox = 0; 231 int iswman = 0; 232 Window vroot; 233 234#ifdef DEBUG 235 fprintf(stderr, "AddWindow: w = 0x%x\n", w); 236#endif 237 238 if (!captive && RedirectToCaptive (w)) return (NULL); 239 240 /* allocate space for the twm window */ 241 tmp_win = (TwmWindow *)calloc(1, sizeof(TwmWindow)); 242 if (tmp_win == 0) 243 { 244 fprintf (stderr, "%s: Unable to allocate memory to manage window ID %lx.\n", 245 ProgramName, w); 246 return NULL; 247 } 248 switch (iconm) { 249 case 0 : iswinbox = 0; break; 250 case 1 : iswinbox = 0; break; 251 case 2 : iswinbox = 1; iconm = 0; break; 252 case 3 : iswman = 1; iconm = 0; break; 253 default : iswinbox = 0; iswman = 0; iconm = 1; break; 254 } 255 tmp_win->w = w; 256 tmp_win->zoomed = ZOOM_NONE; 257 tmp_win->iconmgr = iconm; 258 tmp_win->iconmgrp = iconp; 259 tmp_win->wspmgr = iswman; 260 tmp_win->iswinbox = iswinbox; 261 tmp_win->vs = NULL; 262 tmp_win->old_parent_vs = NULL; 263 tmp_win->savevs = NULL; 264 tmp_win->cmaps.number_cwins = 0; 265 tmp_win->savegeometry.width = -1; 266 267 XSelectInput(dpy, tmp_win->w, PropertyChangeMask); 268 XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr); 269 tmp_win->name = (char*) GetWMPropertyString(tmp_win->w, XA_WM_NAME); 270 tmp_win->class = NoClass; 271 XGetClassHint(dpy, tmp_win->w, &tmp_win->class); 272 FetchWmProtocols (tmp_win); 273 FetchWmColormapWindows (tmp_win); 274 275 if (GetWindowConfig (tmp_win, 276 &saved_x, &saved_y, &saved_width, &saved_height, 277 &restore_iconified, &restore_icon_info_present, 278 &restore_icon_x, &restore_icon_y, 279 &width_ever_changed_by_user, &height_ever_changed_by_user, 280 &saved_occupation)) /* <== [ Matthew McNeill Feb 1997 ] == */ 281 { 282 tmp_win->attr.x = saved_x; 283 tmp_win->attr.y = saved_y; 284 285 tmp_win->widthEverChangedByUser = width_ever_changed_by_user; 286 tmp_win->heightEverChangedByUser = height_ever_changed_by_user; 287 288 if (width_ever_changed_by_user) 289 tmp_win->attr.width = saved_width; 290 291 if (height_ever_changed_by_user) 292 tmp_win->attr.height = saved_height; 293 294 restoredFromPrevSession = 1; 295 } 296 else 297 { 298 tmp_win->widthEverChangedByUser = False; 299 tmp_win->heightEverChangedByUser = False; 300 301 restoredFromPrevSession = 0; 302 } 303 304 /* 305 * do initial clip; should look at window gravity 306 */ 307 if (tmp_win->attr.width > Scr->MaxWindowWidth) 308 tmp_win->attr.width = Scr->MaxWindowWidth; 309 if (tmp_win->attr.height > Scr->MaxWindowHeight) 310 tmp_win->attr.height = Scr->MaxWindowHeight; 311 312 tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w); 313 314 if (tmp_win->wmhints) 315 { 316 if (restore_iconified) 317 { 318 tmp_win->wmhints->initial_state = IconicState; 319 tmp_win->wmhints->flags |= StateHint; 320 } 321 322 if (restore_icon_info_present) 323 { 324 tmp_win->wmhints->icon_x = restore_icon_x; 325 tmp_win->wmhints->icon_y = restore_icon_y; 326 tmp_win->wmhints->flags |= IconPositionHint; 327 } 328 } 329 330 if (tmp_win->wmhints) tmp_win->wmhints->input = True; 331 /* CL: Having with not willing focus 332 cause problems with AutoSqueeze and a few others 333 things. So I suppress it. And the whole focus thing 334 is buggy anyway */ 335 if (tmp_win->wmhints && !(tmp_win->wmhints->flags & InputHint)) 336 tmp_win->wmhints->input = True; 337 if (tmp_win->wmhints && (tmp_win->wmhints->flags & WindowGroupHint)) { 338 tmp_win->group = tmp_win->wmhints->window_group; 339 if (tmp_win->group) { 340 /* 341 * GTK windows often have a spurious "group leader" window which is 342 * never reported to us and therefore does not really exist. This 343 * is annoying because we treat group members a lot like transient 344 * windows. Look for that here. It is in fact a duplicate of the 345 * WM_CLIENT_LEADER property. 346 */ 347 if (tmp_win->group != w && !GetTwmWindow(tmp_win->group)) { 348 tmp_win->group = 0; 349 } 350 } 351 } else 352 tmp_win->group = 0; 353 354 /* 355 * The July 27, 1988 draft of the ICCCM ignores the size and position 356 * fields in the WM_NORMAL_HINTS property. 357 */ 358 359 tmp_win->transient = Transient(tmp_win->w, &tmp_win->transientfor); 360 361 tmp_win->nameChanged = 0; 362 if (tmp_win->name == NULL) 363 tmp_win->name = NoName; 364 if (tmp_win->class.res_name == NULL) 365 tmp_win->class.res_name = NoName; 366 if (tmp_win->class.res_class == NULL) 367 tmp_win->class.res_class = NoName; 368 369 /* 370 * full_name seems to exist only because in the conditional code below, 371 * name is sometimes changed. In all other cases, name and full_name 372 * seem to be identical. Is that worth it? 373 */ 374 tmp_win->full_name = tmp_win->name; 375#ifdef CLAUDE 376 if (strstr (tmp_win->name, " - Mozilla")) { 377 char *moz = strstr (tmp_win->name, " - Mozilla"); 378 *moz = '\0'; 379 } 380#endif 381 namelen = strlen (tmp_win->name); 382 383 if (LookInList(Scr->IgnoreTransientL, tmp_win->full_name, &tmp_win->class)) 384 tmp_win->transient = 0; 385 386 tmp_win->highlight = Scr->Highlight && 387 (!LookInList(Scr->NoHighlight, tmp_win->full_name, 388 &tmp_win->class)); 389 390 tmp_win->stackmode = Scr->StackMode && 391 (!LookInList(Scr->NoStackModeL, tmp_win->full_name, 392 &tmp_win->class)); 393 394 tmp_win->ontoppriority = (LookInList(Scr->AlwaysOnTopL, 395 tmp_win->full_name, &tmp_win->class)) ? ONTOP_MAX : ONTOP_DEFAULT; 396 397 tmp_win->titlehighlight = Scr->TitleHighlight && 398 (!LookInList(Scr->NoTitleHighlight, tmp_win->full_name, 399 &tmp_win->class)); 400 401 tmp_win->auto_raise = Scr->AutoRaiseDefault || 402 LookInList(Scr->AutoRaise, tmp_win->full_name, 403 &tmp_win->class); 404 if (tmp_win->auto_raise) Scr->NumAutoRaises++; 405 406 tmp_win->auto_lower = Scr->AutoLowerDefault || 407 LookInList(Scr->AutoLower, tmp_win->full_name, 408 &tmp_win->class); 409 if (tmp_win->auto_lower) Scr->NumAutoLowers++; 410 411 tmp_win->iconify_by_unmapping = Scr->IconifyByUnmapping; 412 if (Scr->IconifyByUnmapping) 413 { 414 tmp_win->iconify_by_unmapping = iconm ? FALSE : 415 !LookInList(Scr->DontIconify, tmp_win->full_name, 416 &tmp_win->class); 417 } 418 tmp_win->iconify_by_unmapping = tmp_win->iconify_by_unmapping || 419 LookInList(Scr->IconifyByUn, tmp_win->full_name, &tmp_win->class); 420 421 if (LookInList (Scr->UnmapByMovingFarAway, tmp_win->full_name, &tmp_win->class)) 422 tmp_win->UnmapByMovingFarAway = True; 423 else 424 tmp_win->UnmapByMovingFarAway = False; 425 426 if (LookInList (Scr->DontSetInactive, tmp_win->full_name, &tmp_win->class)) 427 tmp_win->DontSetInactive = True; 428 else 429 tmp_win->DontSetInactive = False; 430 431 if (LookInList (Scr->AutoSqueeze, tmp_win->full_name, &tmp_win->class)) 432 tmp_win->AutoSqueeze = True; 433 else 434 tmp_win->AutoSqueeze = False; 435 436 if (LookInList (Scr->StartSqueezed, tmp_win->full_name, &tmp_win->class)) 437 tmp_win->StartSqueezed = True; 438 else 439 tmp_win->StartSqueezed = False; 440 441 if (Scr->AlwaysSqueezeToGravity 442 || LookInList (Scr->AlwaysSqueezeToGravityL, tmp_win->full_name, &tmp_win->class)) 443 tmp_win->AlwaysSqueezeToGravity = True; 444 else 445 tmp_win->AlwaysSqueezeToGravity = False; 446 447 if (tmp_win->transient || tmp_win->group) { 448 TwmWindow *t = NULL; 449 if (tmp_win->transient) t = GetTwmWindow(tmp_win->transientfor); 450 if (!t && tmp_win->group) t = GetTwmWindow(tmp_win->group); 451 if (t) tmp_win->UnmapByMovingFarAway = t->UnmapByMovingFarAway; 452 } 453 if ((Scr->WindowRingAll && !iswman && 454 !LookInList(Scr->WindowRingExcludeL, tmp_win->full_name, &tmp_win->class)) || 455 LookInList(Scr->WindowRingL, tmp_win->full_name, &tmp_win->class)) { 456 if (Scr->Ring) { 457 tmp_win->ring.next = Scr->Ring->ring.next; 458 if (Scr->Ring->ring.next->ring.prev) 459 Scr->Ring->ring.next->ring.prev = tmp_win; 460 Scr->Ring->ring.next = tmp_win; 461 tmp_win->ring.prev = Scr->Ring; 462 } else { 463 tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win; 464 } 465 } else 466 tmp_win->ring.next = tmp_win->ring.prev = NULL; 467 tmp_win->ring.cursor_valid = False; 468 469 tmp_win->squeeze_info = NULL; 470 tmp_win->squeeze_info_copied = 0; 471 /* 472 * get the squeeze information; note that this does not have to be freed 473 * since it is coming from the screen list 474 */ 475 if (HasShape) { 476 if (!LookInList (Scr->DontSqueezeTitleL, tmp_win->full_name, 477 &tmp_win->class)) { 478 tmp_win->squeeze_info = (SqueezeInfo *) 479 LookInList (Scr->SqueezeTitleL, tmp_win->full_name, 480 &tmp_win->class); 481 if (!tmp_win->squeeze_info) { 482 static SqueezeInfo default_squeeze = { J_LEFT, 0, 0 }; 483 if (Scr->SqueezeTitle) 484 tmp_win->squeeze_info = &default_squeeze; 485 } 486 } 487 } 488 489 tmp_win->old_bw = tmp_win->attr.border_width; 490 491 { 492 MotifWmHints mwmHints; 493 Boolean have_title; 494 495 GetMWMHints(tmp_win->w, &mwmHints); 496 497 tmp_win->frame_bw3D = Scr->ThreeDBorderWidth; 498 if (((mwmHints.flags & MWM_HINTS_DECORATIONS) && 499 (mwmHints.decorations & MWM_DECOR_BORDER) == 0) 500 || LookInList(Scr->NoBorder, tmp_win->full_name, &tmp_win->class)) { 501 tmp_win->frame_bw = 0; 502 tmp_win->frame_bw3D = 0; 503 } else if (tmp_win->frame_bw3D != 0) { 504 tmp_win->frame_bw = 0; 505 Scr->ClientBorderWidth = FALSE; 506 } else if (Scr->ClientBorderWidth) { 507 tmp_win->frame_bw = tmp_win->old_bw; 508 } else { 509 tmp_win->frame_bw = Scr->BorderWidth; 510 } 511 bw2 = tmp_win->frame_bw * 2; 512 513 514 have_title = True; 515 if (mwmHints.flags & MWM_HINTS_DECORATIONS) 516 have_title = (mwmHints.decorations & MWM_DECOR_TITLE) != 0; 517 if (Scr->NoTitlebar) 518 have_title = False; 519 if (LookInList(Scr->MakeTitle, tmp_win->full_name, &tmp_win->class)) 520 have_title = True; 521 if (LookInList(Scr->NoTitle, tmp_win->full_name, &tmp_win->class)) 522 have_title = False; 523 524 if (have_title) { 525 tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw; 526 } else { 527 tmp_win->title_height = 0; 528 } 529 } 530 531 tmp_win->OpaqueMove = Scr->DoOpaqueMove; 532 if (LookInList(Scr->OpaqueMoveList, tmp_win->full_name, &tmp_win->class)) 533 tmp_win->OpaqueMove = TRUE; 534 else 535 if (LookInList(Scr->NoOpaqueMoveList, tmp_win->full_name, &tmp_win->class)) 536 tmp_win->OpaqueMove = FALSE; 537 538 tmp_win->OpaqueResize = Scr->DoOpaqueResize; 539 if (LookInList(Scr->OpaqueResizeList, tmp_win->full_name, &tmp_win->class)) 540 tmp_win->OpaqueResize = TRUE; 541 else 542 if (LookInList(Scr->NoOpaqueResizeList, tmp_win->full_name, &tmp_win->class)) 543 tmp_win->OpaqueResize = FALSE; 544 545 /* if it is a transient window, don't put a title on it */ 546 if (tmp_win->transient && !Scr->DecorateTransients) 547 tmp_win->title_height = 0; 548 549 if (LookInList(Scr->StartIconified, tmp_win->full_name, &tmp_win->class)) 550 { 551 if (!tmp_win->wmhints) 552 { 553 tmp_win->wmhints = (XWMHints *)malloc(sizeof(XWMHints)); 554 tmp_win->wmhints->flags = 0; 555 } 556 tmp_win->wmhints->initial_state = IconicState; 557 tmp_win->wmhints->flags |= StateHint; 558 } 559 560 GetWindowSizeHints (tmp_win); 561 562 if (restoredFromPrevSession) 563 { 564 /* 565 * When restoring window positions from the previous session, 566 * we always use NorthWest gravity. 567 */ 568 569 gravx = gravy = -1; 570 } 571 else 572 { 573 GetGravityOffsets (tmp_win, &gravx, &gravy); 574 } 575 576 /* 577 * Don't bother user if: 578 * 579 * o the window is a transient, or 580 * 581 * o a USPosition was requested, or 582 * 583 * o a PPosition was requested and UsePPosition is ON or 584 * NON_ZERO if the window is at other than (0,0) 585 */ 586 ask_user = TRUE; 587 if (tmp_win->transient || 588 (tmp_win->hints.flags & USPosition) || 589 ((tmp_win->hints.flags & PPosition) && Scr->UsePPosition && 590 (Scr->UsePPosition == PPOS_ON || 591 tmp_win->attr.x != 0 || tmp_win->attr.y != 0))) 592 ask_user = FALSE; 593 594 /*===============[ Matthew McNeill 1997 ]==========================* 595 * added the occupation parameter to this function call so that the 596 * occupation can be set up in a specific state if desired 597 * (restore session for example) 598 */ 599 600 /* note, this is where tmp_win->vs get setup, among other things */ 601 602 if (restoredFromPrevSession) { 603 SetupOccupation (tmp_win, saved_occupation); 604 } else 605 SetupOccupation (tmp_win, 0); 606 /*=================================================================*/ 607 608 tmp_win->frame_width = tmp_win->attr.width + 2 * tmp_win->frame_bw3D; 609 tmp_win->frame_height = tmp_win->attr.height + 2 * tmp_win->frame_bw3D + 610 tmp_win->title_height; 611 ConstrainSize (tmp_win, &tmp_win->frame_width, &tmp_win->frame_height); 612 winbox = findWindowBox (tmp_win); 613 if (PlaceWindowInRegion (tmp_win, &(tmp_win->attr.x), &(tmp_win->attr.y))) { 614 ask_user = False; 615 } 616 if (LookInList (Scr->WindowGeometries, tmp_win->full_name, &tmp_win->class)) { 617 char *geom; 618 int mask_; 619 geom = LookInList (Scr->WindowGeometries, tmp_win->full_name, &tmp_win->class); 620 mask_ = XParseGeometry (geom, &tmp_win->attr.x, &tmp_win->attr.y, 621 (unsigned int*) &tmp_win->attr.width, 622 (unsigned int*) &tmp_win->attr.height); 623 624 if (mask_ & XNegative) tmp_win->attr.x += Scr->rootw - tmp_win->attr.width; 625 if (mask_ & YNegative) tmp_win->attr.y += Scr->rooth - tmp_win->attr.height; 626 ask_user = False; 627 } 628 629 if (XFindContext (dpy, w, VirtScreenContext, (XPointer *)&vs) == XCSUCCESS) 630 vroot = vs->window; 631 else 632 if (tmp_win->vs) 633 vroot = tmp_win->vs->window; 634 else 635 vroot = Scr->Root; 636 if (winbox) vroot = winbox->window; 637 638 /* 639 * do any prompting for position 640 */ 641 642 if (HandlingEvents && ask_user && !restoredFromPrevSession) { 643 if ((Scr->RandomPlacement == RP_ALL) || 644 ((Scr->RandomPlacement == RP_UNMAPPED) && 645 ((tmp_win->wmhints && (tmp_win->wmhints->initial_state == IconicState)) || 646 (! visible (tmp_win))))) { /* just stick it somewhere */ 647 648#ifdef DEBUG 649 fprintf(stderr, 650 "DEBUG[RandomPlacement]: win: %dx%d+%d+%d, screen: %dx%d, title height: %d, random: +%d+%d\n", 651 tmp_win->attr.width, tmp_win->attr.height, 652 tmp_win->attr.x, tmp_win->attr.y, 653 Scr->rootw, Scr->rooth, 654 tmp_win->title_height, 655 PlaceX, PlaceY); 656#endif 657 658 /* Initiallise PlaceX and PlaceY */ 659 if (PlaceX < 0 && PlaceY < 0) { 660 if (Scr->RandomDisplacementX >= 0) 661 PlaceX = Scr->BorderLeft + 5; 662 else 663 PlaceX = Scr->rootw - tmp_win->attr.width - Scr->BorderRight - 5; 664 if (Scr->RandomDisplacementY >= 0) 665 PlaceY = Scr->BorderTop + 5; 666 else 667 PlaceY = Scr->rooth - tmp_win->attr.height - tmp_win->title_height 668 - Scr->BorderBottom - 5; 669 } 670 671 /* For a positive horizontal displacement, if the right edge 672 of the window would fall outside of the screen, start over 673 by placing the left edge of the window 5 pixels inside 674 the left edge of the screen.*/ 675 if (Scr->RandomDisplacementX >= 0 676 && (PlaceX + tmp_win->attr.width 677 > Scr->rootw - Scr->BorderRight - 5)) 678 PlaceX = Scr->BorderLeft + 5; 679 680 /* For a negative horizontal displacement, if the left edge 681 of the window would fall outside of the screen, start over 682 by placing the right edge of the window 5 pixels inside 683 the right edge of the screen.*/ 684 if (Scr->RandomDisplacementX < 0 && PlaceX < Scr->BorderLeft + 5) 685 PlaceX = Scr->rootw - tmp_win->attr.width - Scr->BorderRight - 5; 686 687 /* For a positive vertical displacement, if the bottom edge 688 of the window would fall outside of the screen, start over 689 by placing the top edge of the window 5 pixels inside the 690 top edge of the screen. Because we add the title height 691 further down, we need to count with it here as well. */ 692 if (Scr->RandomDisplacementY >= 0 693 && (PlaceY + tmp_win->attr.height + tmp_win->title_height 694 > Scr->rooth - Scr->BorderBottom - 5)) 695 PlaceY = Scr->BorderTop + 5; 696 697 /* For a negative vertical displacement, if the top edge of 698 the window would fall outside of the screen, start over by 699 placing the bottom edge of the window 5 pixels inside the 700 bottom edge of the screen. Because we add the title height 701 further down, we need to count with it here as well. */ 702 if (Scr->RandomDisplacementY < 0 && PlaceY < Scr->BorderTop + 5) 703 PlaceY = Scr->rooth - tmp_win->attr.height - tmp_win->title_height 704 - Scr->BorderBottom - 5; 705 706 /* Assign the current random placement to the new window, as 707 a preliminary measure. Add the title height so things will 708 look right. */ 709 tmp_win->attr.x = PlaceX; 710 tmp_win->attr.y = PlaceY + tmp_win->title_height; 711 712 /* If the window is not supposed to move off the screen, check 713 that it's still within the screen, and if not, attempt to 714 correct the situation. */ 715 if (Scr->DontMoveOff) { 716 int available; 717 718#ifdef DEBUG 719 fprintf(stderr, 720 "DEBUG[DontMoveOff]: win: %dx%d+%d+%d, screen: %dx%d, bw2: %d, bw3D: %d\n", 721 tmp_win->attr.width, tmp_win->attr.height, 722 tmp_win->attr.x, tmp_win->attr.y, 723 Scr->rootw, Scr->rooth, 724 bw2, tmp_win->frame_bw3D); 725#endif 726 727 /* If the right edge of the window is outside the right edge 728 of the screen, we need to move the window left. Note that 729 this can only happen with windows that are less than 50 730 pixels less wide than the screen. */ 731 if ((tmp_win->attr.x + tmp_win->attr.width) > Scr->rootw) { 732 available = Scr->rootw - tmp_win->attr.width 733 - 2 * (bw2 + tmp_win->frame_bw3D); 734 735#ifdef DEBUG 736 fprintf(stderr, "DEBUG[DontMoveOff]: availableX: %d\n", 737 available); 738#endif 739 740 /* If the window is wider than the screen or exactly the width 741 of the screen, the availability is exactly 0. The result 742 will be to have the window placed as much to the left as 743 possible. */ 744 if (available <= 0) available = 0; 745 746 /* Place the window exactly between the left and right edge of 747 the screen when possible. If available was originally less 748 than zero, it means the window's left edge will be against 749 the screen's left edge, and the window's right edge will be 750 outside the screen. */ 751 tmp_win->attr.x = available / 2; 752 } 753 754 /* If the bottom edge of the window is outside the bottom edge 755 of the screen, we need to move the window up. Note that 756 this can only happen with windows that are less than 50 757 pixels less tall than the screen. Don't forget to count 758 with the title height and the frame widths. */ 759 if ((tmp_win->attr.y + tmp_win->attr.height) > Scr->rooth) { 760 available = Scr->rooth - tmp_win->attr.height 761 - tmp_win->title_height - 2 * (bw2 + tmp_win->frame_bw3D); 762 763#ifdef DEBUG 764 fprintf(stderr, "DEBUG[DontMoveOff]: availableY: %d\n", 765 available); 766#endif 767 768 /* If the window is taller than the screen or exactly the 769 height of the screen, the availability is exactly 0. 770 The result will be to have the window placed as much to 771 the top as possible. */ 772 if (available <= 0) available = 0; 773 774 /* Place the window exactly between the top and bottom edge of 775 the screen when possible. If available was originally less 776 than zero, it means the window's top edge will be against 777 the screen's top edge, and the window's bottom edge will be 778 outside the screen. Again, don't forget to add the title 779 height. */ 780 tmp_win->attr.y = available / 2 + tmp_win->title_height; 781 } 782 783#ifdef DEBUG 784 fprintf(stderr, 785 "DEBUG[DontMoveOff]: win: %dx%d+%d+%d, screen: %dx%d\n", 786 tmp_win->attr.width, tmp_win->attr.height, 787 tmp_win->attr.x, tmp_win->attr.y, 788 Scr->rootw, Scr->rooth); 789#endif 790 } 791 792 /* We know that if the window's left edge has moved compared to 793 PlaceX, it will have moved to the left. If it was moved less 794 than 15 pixel either way, change the next "random position" 795 30 pixels down and right. */ 796 if (PlaceX - tmp_win->attr.x < 15 797 || PlaceY - (tmp_win->attr.y - tmp_win->title_height) < 15) { 798 PlaceX += Scr->RandomDisplacementX; 799 PlaceY += Scr->RandomDisplacementY; 800 } 801 802 random_placed = True; 803 } else { /* else prompt */ 804 if (!(tmp_win->wmhints && tmp_win->wmhints->flags & StateHint && 805 tmp_win->wmhints->initial_state == IconicState)) 806 { 807 Bool firsttime = True; 808 809 /* better wait until all the mouse buttons have been 810 * released. 811 */ 812 while (TRUE) 813 { 814 XUngrabServer(dpy); 815 XSync(dpy, 0); 816 XGrabServer(dpy); 817 818 JunkMask = 0; 819 if (!XQueryPointer (dpy, Scr->Root, &JunkRoot, 820 &JunkChild, &JunkX, &JunkY, 821 &AddingX, &AddingY, &JunkMask)) 822 JunkMask = 0; 823 824 JunkMask &= (Button1Mask | Button2Mask | Button3Mask | 825 Button4Mask | Button5Mask); 826 827 /* 828 * watch out for changing screens 829 */ 830 if (firsttime) { 831 if (JunkRoot != Scr->Root) { 832 register int scrnum; 833 for (scrnum = 0; scrnum < NumScreens; scrnum++) { 834 if (JunkRoot == RootWindow (dpy, scrnum)) break; 835 } 836 if (scrnum != NumScreens) PreviousScreen = scrnum; 837 } 838 if (Scr->currentvs) { 839 vroot = Scr->currentvs->window; 840 } 841 firsttime = False; 842 } 843 if (winbox) vroot = winbox->window; 844 845 /* 846 * wait for buttons to come up; yuck 847 */ 848 if (JunkMask != 0) continue; 849 850 /* 851 * this will cause a warp to the indicated root 852 */ 853 stat = XGrabPointer(dpy, vroot, False, 854 ButtonPressMask | ButtonReleaseMask | 855 PointerMotionMask | PointerMotionHintMask, 856 GrabModeAsync, GrabModeAsync, 857 vroot, UpperLeftCursor, CurrentTime); 858 if (stat == GrabSuccess) break; 859 } 860 861 XmbTextExtents(Scr->SizeFont.font_set, 862 tmp_win->name, namelen, 863 &ink_rect, &logical_rect); 864 width = SIZE_HINDENT + ink_rect.width; 865 height = logical_rect.height + SIZE_VINDENT * 2; 866 XmbTextExtents(Scr->SizeFont.font_set, 867 ": ", 2, &logical_rect, &logical_rect); 868 Scr->SizeStringOffset = width + logical_rect.width; 869 870 XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset + 871 Scr->SizeStringWidth + SIZE_HINDENT, height); 872 XMapRaised(dpy, Scr->SizeWindow); 873 InstallRootColormap(); 874 FB(Scr->DefaultC.fore, Scr->DefaultC.back); 875 XmbDrawImageString (dpy, Scr->SizeWindow, Scr->SizeFont.font_set, 876 Scr->NormalGC, SIZE_HINDENT, 877 SIZE_VINDENT + Scr->SizeFont.ascent, 878 tmp_win->name, namelen); 879 880 if (winbox) ConstrainedToWinBox (tmp_win, AddingX, AddingY, &AddingX, &AddingY); 881 882 AddingW = tmp_win->attr.width + bw2 + 2 * tmp_win->frame_bw3D; 883 AddingH = tmp_win->attr.height + tmp_win->title_height + 884 bw2 + 2 * tmp_win->frame_bw3D; 885 MoveOutline(vroot,AddingX, AddingY, AddingW, AddingH, 886 tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D); 887 888 XmbDrawImageString (dpy, Scr->SizeWindow, Scr->SizeFont.font_set, 889 Scr->NormalGC, width, 890 SIZE_VINDENT + Scr->SizeFont.ascent, ": ", 2); 891 DisplayPosition (tmp_win, AddingX, AddingY); 892 893 tmp_win->frame_width = AddingW; 894 tmp_win->frame_height = AddingH; 895 /*SetFocus ((TwmWindow *) NULL, CurrentTime);*/ 896 while (TRUE) 897 { 898#ifndef VMS /* I'll try to implement this later. RL */ 899 if (Scr->OpenWindowTimeout) { 900 fd = ConnectionNumber (dpy); 901 while (!XCheckMaskEvent (dpy, ButtonMotionMask | ButtonPressMask, &event)) { 902 FD_ZERO (&mask); 903 FD_SET (fd, &mask); 904 timeout.tv_sec = Scr->OpenWindowTimeout; 905 timeout.tv_usec = 0; 906 found = select (fd + 1, (FDSET)&mask, (FDSET)0, (FDSET)0, &timeout); 907 if (found == 0) break; 908 } 909 if (found == 0) break; 910 } else { 911#else 912 { 913#endif 914 found = 1; 915 XMaskEvent(dpy, ButtonPressMask | PointerMotionMask, &event); 916 } 917 if (event.type == MotionNotify) { 918 /* discard any extra motion events before a release */ 919 while(XCheckMaskEvent(dpy, 920 ButtonMotionMask | ButtonPressMask, &event)) 921 if (event.type == ButtonPress) 922 break; 923 } 924 FixRootEvent (&event); 925 if (event.type == ButtonPress) { 926 AddingX = event.xbutton.x_root; 927 AddingY = event.xbutton.y_root; 928 929 TryToGrid (tmp_win, &AddingX, &AddingY); 930 if (Scr->PackNewWindows) TryToPack (tmp_win, &AddingX, &AddingY); 931 932 /* DontMoveOff prohibits user form off-screen placement */ 933 if (Scr->DontMoveOff) 934 { 935 ConstrainByBorders (tmp_win, &AddingX, AddingW, &AddingY, AddingH); 936 } 937 break; 938 } 939 940 if (event.type != MotionNotify) { 941 continue; 942 } 943 944 XQueryPointer(dpy, vroot, &JunkRoot, &JunkChild, 945 &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask); 946 947 TryToGrid (tmp_win, &AddingX, &AddingY); 948 if (Scr->PackNewWindows) TryToPack (tmp_win, &AddingX, &AddingY); 949 if (Scr->DontMoveOff) 950 { 951 ConstrainByBorders (tmp_win, &AddingX, AddingW, &AddingY, AddingH); 952 } 953 MoveOutline(vroot, AddingX, AddingY, AddingW, AddingH, 954 tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D); 955 956 DisplayPosition (tmp_win, AddingX, AddingY); 957 } 958 959 if (found) { 960 if (event.xbutton.button == Button2) { 961 int lastx, lasty; 962 963 XmbTextExtents(Scr->SizeFont.font_set, 964 ": ", 2, &logical_rect, &logical_rect); 965 Scr->SizeStringOffset = width + logical_rect.width; 966 967 XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset + 968 Scr->SizeStringWidth + SIZE_HINDENT, height); 969 970 XmbDrawImageString(dpy, Scr->SizeWindow, Scr->SizeFont.font_set, 971 Scr->NormalGC, width, 972 SIZE_VINDENT + Scr->SizeFont.ascent, ": ", 2); 973 974 if (0/*Scr->AutoRelativeResize*/) { 975 int dx = (tmp_win->attr.width / 4); 976 int dy = (tmp_win->attr.height / 4); 977 978#define HALF_AVE_CURSOR_SIZE 8 /* so that it is visible */ 979 if (dx < HALF_AVE_CURSOR_SIZE + Scr->BorderLeft) 980 dx = HALF_AVE_CURSOR_SIZE + Scr->BorderLeft; 981 if (dy < HALF_AVE_CURSOR_SIZE + Scr->BorderTop) 982 dy = HALF_AVE_CURSOR_SIZE + Scr->BorderTop; 983#undef HALF_AVE_CURSOR_SIZE 984 dx += (tmp_win->frame_bw + 1); 985 dy += (bw2 + tmp_win->title_height + 1); 986 if (AddingX + dx >= Scr->rootw - Scr->BorderRight) 987 dx = Scr->rootw - Scr->BorderRight - AddingX - 1; 988 if (AddingY + dy >= Scr->rooth - Scr->BorderBottom) 989 dy = Scr->rooth - Scr->BorderBottom - AddingY - 1; 990 if (dx > 0 && dy > 0) 991 XWarpPointer (dpy, None, None, 0, 0, 0, 0, dx, dy); 992 } else { 993 XWarpPointer (dpy, None, vroot, 0, 0, 0, 0, 994 AddingX + AddingW/2, AddingY + AddingH/2); 995 } 996 AddStartResize(tmp_win, AddingX, AddingY, AddingW, AddingH); 997 998 lastx = -10000; 999 lasty = -10000; 1000 while (TRUE) 1001 { 1002 XMaskEvent(dpy, 1003 ButtonReleaseMask | ButtonMotionMask, &event); 1004 1005 if (event.type == MotionNotify) { 1006 /* discard any extra motion events before a release */ 1007 while(XCheckMaskEvent(dpy, 1008 ButtonMotionMask | ButtonReleaseMask, &event)) 1009 if (event.type == ButtonRelease) 1010 break; 1011 } 1012 FixRootEvent (&event); 1013 1014 if (event.type == ButtonRelease) 1015 { 1016 AddEndResize(tmp_win); 1017 break; 1018 } 1019 1020 if (event.type != MotionNotify) { 1021 continue; 1022 } 1023 1024 /* 1025 * XXX - if we are going to do a loop, we ought to consider 1026 * using multiple GXxor lines so that we don't need to 1027 * grab the server. 1028 */ 1029 XQueryPointer(dpy, vroot, &JunkRoot, &JunkChild, 1030 &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask); 1031 1032 if (lastx != AddingX || lasty != AddingY) 1033 { 1034 resizeWhenAdd = TRUE; 1035 DoResize(AddingX, AddingY, tmp_win); 1036 resizeWhenAdd = FALSE; 1037 1038 lastx = AddingX; 1039 lasty = AddingY; 1040 } 1041 1042 } 1043 } 1044 else if (event.xbutton.button == Button3) 1045 { 1046 int maxw = Scr->rootw - Scr->BorderRight - AddingX - bw2; 1047 int maxh = Scr->rooth - Scr->BorderBottom - AddingY - bw2; 1048 1049 /* 1050 * Make window go to bottom of screen, and clip to right edge. 1051 * This is useful when popping up large windows and fixed 1052 * column text windows. 1053 */ 1054 if (AddingW > maxw) AddingW = maxw; 1055 AddingH = maxh; 1056 1057 ConstrainSize (tmp_win, &AddingW, &AddingH); /* w/o borders */ 1058 AddingW += bw2; 1059 AddingH += bw2; 1060 XMaskEvent(dpy, ButtonReleaseMask, &event); 1061 } 1062 else 1063 { 1064 XMaskEvent(dpy, ButtonReleaseMask, &event); 1065 } 1066 } 1067 MoveOutline(vroot, 0, 0, 0, 0, 0, 0); 1068 XUnmapWindow(dpy, Scr->SizeWindow); 1069 UninstallRootColormap(); 1070 XUngrabPointer(dpy, CurrentTime); 1071 1072 tmp_win->attr.x = AddingX; 1073 tmp_win->attr.y = AddingY + tmp_win->title_height; 1074 tmp_win->attr.width = AddingW - bw2 - 2 * tmp_win->frame_bw3D; 1075 tmp_win->attr.height = AddingH - tmp_win->title_height - 1076 bw2 - 2 * tmp_win->frame_bw3D; 1077 1078 XUngrabServer(dpy); 1079 } 1080 } 1081 } else { /* put it where asked, mod title bar */ 1082 /* if the gravity is towards the top, move it by the title height */ 1083 if (gravy < 0) tmp_win->attr.y -= gravy * tmp_win->title_height; 1084 } 1085 1086#ifdef DEBUG 1087 fprintf(stderr, " position window %d, %d %dx%d\n", 1088 tmp_win->attr.x, 1089 tmp_win->attr.y, 1090 tmp_win->attr.width, 1091 tmp_win->attr.height); 1092#endif 1093 1094 if (!Scr->ClientBorderWidth) { /* need to adjust for twm borders */ 1095 int delta = tmp_win->attr.border_width - tmp_win->frame_bw - tmp_win->frame_bw3D; 1096 tmp_win->attr.x += gravx * delta; 1097 tmp_win->attr.y += gravy * delta; 1098 } 1099 1100 tmp_win->title_width = tmp_win->attr.width; 1101 1102 tmp_win->icon_name = (char*) GetWMPropertyString(tmp_win->w, XA_WM_ICON_NAME); 1103 if (!tmp_win->icon_name) 1104 tmp_win->icon_name = tmp_win->name; 1105 1106#ifdef CLAUDE 1107 if (strstr (tmp_win->icon_name, " - Mozilla")) { 1108 char *moz = strstr (tmp_win->icon_name, " - Mozilla"); 1109 *moz = '\0'; 1110 } 1111#endif 1112 1113 XmbTextExtents (Scr->TitleBarFont.font_set, tmp_win->name, namelen, &ink_rect, &logical_rect); 1114 tmp_win->name_width = logical_rect.width; 1115 1116 if (tmp_win->old_bw) XSetWindowBorderWidth (dpy, tmp_win->w, 0); 1117 1118 tmp_win->squeezed = FALSE; 1119 tmp_win->iconified = FALSE; 1120 tmp_win->isicon = FALSE; 1121 tmp_win->icon_on = FALSE; 1122 1123 XGrabServer(dpy); 1124 1125 /* 1126 * Make sure the client window still exists. We don't want to leave an 1127 * orphan frame window if it doesn't. Since we now have the server 1128 * grabbed, the window can't disappear later without having been 1129 * reparented, so we'll get a DestroyNotify for it. We won't have 1130 * gotten one for anything up to here, however. 1131 */ 1132 if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY, 1133 &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0) 1134 { 1135 TwmWindow *prev = tmp_win->ring.prev, *next = tmp_win->ring.next; 1136 1137 if (prev) prev->ring.next = next; 1138 if (next) next->ring.prev = prev; 1139 if (Scr->Ring == tmp_win) Scr->Ring = (next != tmp_win ? next : (TwmWindow *) NULL); 1140 if (!Scr->Ring || Scr->RingLeader == tmp_win) Scr->RingLeader = Scr->Ring; 1141 1142 free((char *)tmp_win); 1143 XUngrabServer(dpy); 1144 return(NULL); 1145 } 1146 1147 /* add the window into the twm list */ 1148 tmp_win->next = Scr->FirstWindow; 1149 if (Scr->FirstWindow != NULL) 1150 Scr->FirstWindow->prev = tmp_win; 1151 tmp_win->prev = NULL; 1152 Scr->FirstWindow = tmp_win; 1153 1154 /* get all the colors for the window */ 1155 1156 tmp_win->borderC.fore = Scr->BorderColorC.fore; 1157 tmp_win->borderC.back = Scr->BorderColorC.back; 1158 tmp_win->border_tile.fore = Scr->BorderTileC.fore; 1159 tmp_win->border_tile.back = Scr->BorderTileC.back; 1160 tmp_win->title.fore = Scr->TitleC.fore; 1161 tmp_win->title.back = Scr->TitleC.back; 1162 1163 GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class, 1164 &tmp_win->borderC.fore); 1165 GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class, 1166 &tmp_win->borderC.back); 1167 GetColorFromList(Scr->BorderTileForegroundL, tmp_win->full_name, 1168 &tmp_win->class, &tmp_win->border_tile.fore); 1169 GetColorFromList(Scr->BorderTileBackgroundL, tmp_win->full_name, 1170 &tmp_win->class, &tmp_win->border_tile.back); 1171 GetColorFromList(Scr->TitleForegroundL, tmp_win->full_name, &tmp_win->class, 1172 &tmp_win->title.fore); 1173 GetColorFromList(Scr->TitleBackgroundL, tmp_win->full_name, &tmp_win->class, 1174 &tmp_win->title.back); 1175 1176 if (Scr->use3Dtitles && !Scr->BeNiceToColormap) GetShadeColors (&tmp_win->title); 1177 if (Scr->use3Dborders && !Scr->BeNiceToColormap) { 1178 GetShadeColors (&tmp_win->borderC); 1179 GetShadeColors (&tmp_win->border_tile); 1180 } 1181 /* create windows */ 1182 1183 tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->frame_bw 1184 - tmp_win->frame_bw3D; 1185 tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height + 1186 tmp_win->old_bw - tmp_win->frame_bw - tmp_win->frame_bw3D; 1187 tmp_win->frame_width = tmp_win->attr.width + 2 * tmp_win->frame_bw3D; 1188 tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height + 1189 2 * tmp_win->frame_bw3D; 1190 1191 ConstrainSize (tmp_win, &tmp_win->frame_width, &tmp_win->frame_height); 1192 if (random_placed) 1193 ConstrainByBorders (tmp_win, &tmp_win->frame_x, tmp_win->frame_width, 1194 &tmp_win->frame_y, tmp_win->frame_height); 1195 1196 valuemask = CWBackPixmap | CWBorderPixel | CWCursor | CWEventMask | CWBackPixel; 1197 attributes.background_pixmap = None; 1198 attributes.border_pixel = tmp_win->border_tile.back; 1199 attributes.background_pixel = tmp_win->border_tile.back; 1200 attributes.cursor = Scr->FrameCursor; 1201 attributes.event_mask = (SubstructureRedirectMask | 1202 ButtonPressMask | ButtonReleaseMask | 1203 EnterWindowMask | LeaveWindowMask | ExposureMask); 1204 if (Scr->BorderCursors) attributes.event_mask |= PointerMotionMask; 1205 if (tmp_win->attr.save_under) { 1206 attributes.save_under = True; 1207 valuemask |= CWSaveUnder; 1208 } 1209 if (tmp_win->hints.flags & PWinGravity) { 1210 attributes.win_gravity = tmp_win->hints.win_gravity; 1211 valuemask |= CWWinGravity; 1212 } 1213 1214 if ((tmp_win->frame_x > Scr->rootw) || 1215 (tmp_win->frame_y > Scr->rooth) || 1216 ((int)(tmp_win->frame_x + tmp_win->frame_width) < 0) || 1217 ((int)(tmp_win->frame_y + tmp_win->frame_height) < 0)) { 1218 tmp_win->frame_x = 0; 1219 tmp_win->frame_y = 0; 1220 } 1221 1222 DealWithNonSensicalGeometries(dpy, vroot, tmp_win); 1223 1224 tmp_win->frame = XCreateWindow (dpy, vroot, tmp_win->frame_x, tmp_win->frame_y, 1225 (unsigned int) tmp_win->frame_width, 1226 (unsigned int) tmp_win->frame_height, 1227 (unsigned int) tmp_win->frame_bw, 1228 Scr->d_depth, 1229 (unsigned int) CopyFromParent, 1230 Scr->d_visual, valuemask, &attributes); 1231 1232 if (tmp_win->title_height) 1233 { 1234 valuemask = (CWEventMask | CWDontPropagate | CWBorderPixel | CWBackPixel); 1235 attributes.event_mask = (KeyPressMask | ButtonPressMask | 1236 ButtonReleaseMask | ExposureMask); 1237 attributes.do_not_propagate_mask = PointerMotionMask; 1238 attributes.border_pixel = tmp_win->borderC.back; 1239 attributes.background_pixel = tmp_win->title.back; 1240 tmp_win->title_w = XCreateWindow (dpy, tmp_win->frame, 1241 tmp_win->frame_bw3D - tmp_win->frame_bw, 1242 tmp_win->frame_bw3D - tmp_win->frame_bw, 1243 (unsigned int) tmp_win->attr.width, 1244 (unsigned int) Scr->TitleHeight, 1245 (unsigned int) tmp_win->frame_bw, 1246 Scr->d_depth, 1247 (unsigned int) CopyFromParent, 1248 Scr->d_visual, valuemask, 1249 &attributes); 1250 } 1251 else { 1252 tmp_win->title_w = 0; 1253 tmp_win->squeeze_info = NULL; 1254 } 1255 1256 if (tmp_win->highlight) 1257 { 1258 if (Scr->use3Dtitles && (Scr->Monochrome != COLOR)) 1259 tmp_win->gray = XCreatePixmapFromBitmapData(dpy, vroot, 1260 (char*)black_bits, gray_width, gray_height, 1261 tmp_win->border_tile.fore, tmp_win->border_tile.back, 1262 Scr->d_depth); 1263 else 1264 tmp_win->gray = XCreatePixmapFromBitmapData(dpy, vroot, 1265 (char*)gray_bits, gray_width, gray_height, 1266 tmp_win->border_tile.fore, tmp_win->border_tile.back, 1267 Scr->d_depth); 1268 1269 tmp_win->hasfocusvisible = True; 1270 SetFocusVisualAttributes (tmp_win, False); 1271 } 1272 else 1273 tmp_win->gray = None; 1274 1275 RaiseWindow(tmp_win); 1276 1277 if (tmp_win->title_w) { 1278 ComputeTitleLocation (tmp_win); 1279 CreateWindowTitlebarButtons (tmp_win); 1280 XMoveWindow (dpy, tmp_win->title_w, 1281 tmp_win->title_x, tmp_win->title_y); 1282 XDefineCursor(dpy, tmp_win->title_w, Scr->TitleCursor); 1283 } 1284 else { 1285 tmp_win->title_x = tmp_win->frame_bw3D - tmp_win->frame_bw; 1286 tmp_win->title_y = tmp_win->frame_bw3D - tmp_win->frame_bw; 1287 } 1288 1289 valuemask = (CWEventMask | CWDontPropagate); 1290 attributes.event_mask = (StructureNotifyMask | PropertyChangeMask | 1291 ColormapChangeMask | VisibilityChangeMask | 1292 FocusChangeMask | 1293 EnterWindowMask | LeaveWindowMask); 1294 attributes.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask; 1295 XChangeWindowAttributes (dpy, tmp_win->w, valuemask, &attributes); 1296 1297 if (HasShape) 1298 XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask); 1299 1300 if (tmp_win->title_w) { 1301 XMapWindow (dpy, tmp_win->title_w); 1302 } 1303 1304 if (HasShape) { 1305 int xws, yws, xbs, ybs; 1306 unsigned wws, hws, wbs, hbs; 1307 int boundingShaped, clipShaped; 1308 1309 XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask); 1310 XShapeQueryExtents (dpy, tmp_win->w, 1311 &boundingShaped, &xws, &yws, &wws, &hws, 1312 &clipShaped, &xbs, &ybs, &wbs, &hbs); 1313 tmp_win->wShaped = boundingShaped; 1314 } 1315 1316 if (!tmp_win->iconmgr &&! iswman && 1317 (tmp_win->w != Scr->workSpaceMgr.occupyWindow->w)) 1318 XAddToSaveSet(dpy, tmp_win->w); 1319 1320 XReparentWindow(dpy, tmp_win->w, tmp_win->frame, tmp_win->frame_bw3D, 1321 tmp_win->title_height + tmp_win->frame_bw3D); 1322 /* 1323 * Reparenting generates an UnmapNotify event, followed by a MapNotify. 1324 * Set the map state to FALSE to prevent a transition back to 1325 * WithdrawnState in HandleUnmapNotify. Map state gets set correctly 1326 * again in HandleMapNotify. 1327 */ 1328 tmp_win->mapped = FALSE; 1329 1330 SetupFrame (tmp_win, tmp_win->frame_x, tmp_win->frame_y, 1331 tmp_win->frame_width, tmp_win->frame_height, -1, True); 1332 1333 /* wait until the window is iconified and the icon window is mapped 1334 * before creating the icon window 1335 */ 1336 tmp_win->icon = (Icon*) 0; 1337 tmp_win->iconslist = (name_list*) 0; 1338 1339 if (!tmp_win->iconmgr) 1340 { 1341 GrabButtons(tmp_win); 1342 GrabKeys(tmp_win); 1343 } 1344 1345 (void) AddIconManager(tmp_win); 1346 1347 XSaveContext(dpy, tmp_win->w, TwmContext, (XPointer) tmp_win); 1348 XSaveContext(dpy, tmp_win->w, ScreenContext, (XPointer) Scr); 1349 XSaveContext(dpy, tmp_win->frame, TwmContext, (XPointer) tmp_win); 1350 XSaveContext(dpy, tmp_win->frame, ScreenContext, (XPointer) Scr); 1351 1352 if (tmp_win->title_height) 1353 { 1354 int i; 1355 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; 1356 1357 XSaveContext(dpy, tmp_win->title_w, TwmContext, (XPointer) tmp_win); 1358 XSaveContext(dpy, tmp_win->title_w, ScreenContext, (XPointer) Scr); 1359 for (i = 0; i < nb; i++) { 1360 XSaveContext(dpy, tmp_win->titlebuttons[i].window, TwmContext, 1361 (XPointer) tmp_win); 1362 XSaveContext(dpy, tmp_win->titlebuttons[i].window, ScreenContext, 1363 (XPointer) Scr); 1364 } 1365 if (tmp_win->hilite_wl) 1366 { 1367 XSaveContext(dpy, tmp_win->hilite_wl, TwmContext, (XPointer)tmp_win); 1368 XSaveContext(dpy, tmp_win->hilite_wl, ScreenContext, (XPointer)Scr); 1369 } 1370 if (tmp_win->hilite_wr) 1371 { 1372 XSaveContext(dpy, tmp_win->hilite_wr, TwmContext, (XPointer)tmp_win); 1373 XSaveContext(dpy, tmp_win->hilite_wr, ScreenContext, (XPointer)Scr); 1374 } 1375 if (tmp_win->lolite_wl) 1376 { 1377 XSaveContext(dpy, tmp_win->lolite_wl, TwmContext, (XPointer)tmp_win); 1378 XSaveContext(dpy, tmp_win->lolite_wl, ScreenContext, (XPointer)Scr); 1379 } 1380 if (tmp_win->lolite_wr) 1381 { 1382 XSaveContext(dpy, tmp_win->lolite_wr, TwmContext, (XPointer)tmp_win); 1383 XSaveContext(dpy, tmp_win->lolite_wr, ScreenContext, (XPointer)Scr); 1384 } 1385 } 1386 1387 XUngrabServer(dpy); 1388 1389 /* if we were in the middle of a menu activated function, regrab 1390 * the pointer 1391 */ 1392 if (RootFunction) ReGrab(); 1393 if (!iswman) WMapAddWindow (tmp_win); 1394 SetPropsIfCaptiveCtwm (tmp_win); 1395 savegeometry (tmp_win); 1396 return (tmp_win); 1397} 1398 1399/*********************************************************************** 1400 * 1401 * Procedure: 1402 * GetTwmWindow - finds the TwmWindow structure associated with 1403 * a Window (if any), or NULL. 1404 * 1405 * Returned Value: 1406 * NULL - it is not a Window we know about 1407 * otherwise- the TwmWindow * 1408 * 1409 * Inputs: 1410 * w - the window to check 1411 * 1412 * Note: 1413 * This is a relatively cheap function since it does not involve 1414 * communication with the server. Probably faster than walking 1415 * the list of TwmWindows, since the lookup is by a hash table. 1416 * 1417 *********************************************************************** 1418 */ 1419TwmWindow *GetTwmWindow(Window w) 1420{ 1421 TwmWindow *twmwin; 1422 int stat; 1423 1424 stat = XFindContext(dpy, w, TwmContext, (XPointer *)&twmwin); 1425 if (stat == XCNOENT) 1426 twmwin = NULL; 1427 1428 return twmwin; 1429} 1430 1431/*********************************************************************** 1432 * 1433 * Procedure: 1434 * MappedNotOverride - checks to see if we should really 1435 * put a twm frame on the window 1436 * 1437 * Returned Value: 1438 * TRUE - go ahead and frame the window 1439 * FALSE - don't frame the window 1440 * 1441 * Inputs: 1442 * w - the window to check 1443 * 1444 *********************************************************************** 1445 */ 1446 1447int MappedNotOverride(Window w) 1448{ 1449 XWindowAttributes wa; 1450 1451 XGetWindowAttributes(dpy, w, &wa); 1452 return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True)); 1453} 1454 1455 1456/*********************************************************************** 1457 * 1458 * Procedure: 1459 * AddDefaultBindings - attach default bindings so that naive users 1460 * don't get messed up if they provide a minimal twmrc. 1461 */ 1462static void do_add_binding (int button, int context, int modifier, int func) 1463{ 1464 AddFuncButton (button, context, modifier, func, NULL, NULL); 1465} 1466 1467void AddDefaultBindings (void) 1468{ 1469#define NoModifierMask 0 1470 1471 do_add_binding (Button1, C_TITLE, NoModifierMask, F_MOVE); 1472 do_add_binding (Button1, C_ICON, NoModifierMask, F_ICONIFY); 1473 do_add_binding (Button1, C_ICONMGR, NoModifierMask, F_ICONIFY); 1474 1475 do_add_binding (Button2, C_TITLE, NoModifierMask, F_RAISELOWER); 1476 do_add_binding (Button2, C_ICON, NoModifierMask, F_ICONIFY); 1477 do_add_binding (Button2, C_ICONMGR, NoModifierMask, F_ICONIFY); 1478 1479#undef NoModifierMask 1480} 1481 1482 1483 1484 1485/*********************************************************************** 1486 * 1487 * Procedure: 1488 * GrabButtons - grab needed buttons for the window 1489 * 1490 * Inputs: 1491 * tmp_win - the twm window structure to use 1492 * 1493 *********************************************************************** 1494 */ 1495 1496#define AltMask (Alt1Mask | Alt2Mask | Alt3Mask | Alt4Mask | Alt5Mask) 1497#define grabbutton(button, modifier, window, pointer_mode) \ 1498 XGrabButton (dpy, button, modifier, window, \ 1499 True, ButtonPressMask | ButtonReleaseMask, \ 1500 pointer_mode, GrabModeAsync, None, \ 1501 Scr->FrameCursor); 1502 1503void GrabButtons(TwmWindow *tmp_win) 1504{ 1505 FuncButton *tmp; 1506 int i; 1507 unsigned int ModifierMask[8] = { ShiftMask, ControlMask, LockMask, 1508 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, 1509 Mod5Mask }; 1510 1511 for (tmp = Scr->FuncButtonRoot.next; tmp != NULL; tmp = tmp->next) { 1512 if ((tmp->cont != C_WINDOW) || (tmp->func == 0)) continue; 1513 grabbutton (tmp->num, tmp->mods, tmp_win->frame, GrabModeAsync); 1514 1515 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) { 1516 grabbutton (tmp->num, tmp->mods | LockMask, tmp_win->frame, GrabModeAsync); 1517 } 1518 for (i = 0 ; i < 8 ; i++) { 1519 if ((Scr->IgnoreModifier & ModifierMask [i]) && !(tmp->mods & ModifierMask [i])) 1520 grabbutton (tmp->num, tmp->mods | ModifierMask [i], 1521 tmp_win->frame, GrabModeAsync); 1522 } 1523 } 1524 if (Scr->ClickToFocus) { 1525 grabbutton (AnyButton, None, tmp_win->w, GrabModeSync); 1526 for (i = 0 ; i < 8 ; i++) { 1527 grabbutton (AnyButton, ModifierMask [i], tmp_win->w, GrabModeSync); 1528 } 1529 } else 1530 if (Scr->RaiseOnClick) { 1531 grabbutton (Scr->RaiseOnClickButton, None, tmp_win->w, GrabModeSync); 1532 for (i = 0 ; i < 8 ; i++) { 1533 grabbutton (Scr->RaiseOnClickButton, 1534 ModifierMask [i], tmp_win->w, GrabModeSync); 1535 } 1536 } 1537} 1538 1539/*********************************************************************** 1540 * 1541 * Procedure: 1542 * GrabKeys - grab needed keys for the window 1543 * 1544 * Inputs: 1545 * tmp_win - the twm window structure to use 1546 * 1547 *********************************************************************** 1548 */ 1549 1550#define MAX_KEYCODE 256 1551#define grabkey(funckey, modifier, window) \ 1552 XGrabKey(dpy, funckey->keycode, funckey->mods | modifier, window, True, \ 1553 GrabModeAsync, GrabModeAsync); 1554#define ungrabkey(funckey, modifier, window) \ 1555 XUngrabKey (dpy, funckey->keycode, funckey->mods | modifier, window); 1556 1557void GrabKeys(TwmWindow *tmp_win) 1558{ 1559 FuncKey *tmp; 1560 IconMgr *p; 1561 int i; 1562 unsigned int ModifierMask[8] = { ShiftMask, ControlMask, LockMask, 1563 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, 1564 Mod5Mask }; 1565 1566 for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) 1567 { 1568 switch (tmp->cont) 1569 { 1570 case C_WINDOW: 1571 /* case C_WORKSPACE: */ 1572 if (tmp->mods & AltMask) break; 1573 grabkey (tmp, 0, tmp_win->w); 1574 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) 1575 grabkey (tmp, LockMask, tmp_win->w); 1576 for (i = 0 ; i < 8 ; i++) { 1577 if ((Scr->IgnoreModifier & ModifierMask [i]) && 1578 !(tmp->mods & ModifierMask [i])) 1579 grabkey (tmp, ModifierMask [i], tmp_win->w); 1580 } 1581 break; 1582 1583 case C_ICON: 1584 if (!tmp_win->icon || tmp_win->icon->w) break; 1585 grabkey (tmp, 0, tmp_win->icon->w); 1586 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) 1587 grabkey (tmp, LockMask, tmp_win->icon->w); 1588 for (i = 0 ; i < 8 ; i++) { 1589 if ((Scr->IgnoreModifier & ModifierMask [i]) && 1590 !(tmp->mods & ModifierMask [i])) 1591 grabkey (tmp, ModifierMask [i], tmp_win->icon->w); 1592 } 1593 break; 1594 1595 case C_TITLE: 1596 if (!tmp_win->title_w) break; 1597 grabkey (tmp, 0, tmp_win->title_w); 1598 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) 1599 grabkey (tmp, LockMask, tmp_win->title_w); 1600 for (i = 0 ; i < 8 ; i++) { 1601 if ((Scr->IgnoreModifier & ModifierMask [i]) && 1602 !(tmp->mods & ModifierMask [i])) 1603 grabkey (tmp, ModifierMask [i], tmp_win->title_w); 1604 } 1605 break; 1606 1607 case C_NAME: 1608 grabkey (tmp, 0, tmp_win->w); 1609 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) { 1610 grabkey (tmp, LockMask, tmp_win->w); 1611 } 1612 for (i = 0 ; i < 8 ; i++) { 1613 if ((Scr->IgnoreModifier & ModifierMask [i]) && 1614 !(tmp->mods & ModifierMask [i])) 1615 grabkey (tmp, ModifierMask [i], tmp_win->w); 1616 } 1617 if (tmp_win->icon && tmp_win->icon->w) { 1618 grabkey (tmp, 0, tmp_win->icon->w); 1619 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) 1620 grabkey (tmp, LockMask, tmp_win->icon->w); 1621 for (i = 0 ; i < 8 ; i++) { 1622 if ((Scr->IgnoreModifier & ModifierMask [i]) && 1623 !(tmp->mods & ModifierMask [i])) 1624 grabkey (tmp, ModifierMask [i], tmp_win->icon->w); 1625 } 1626 } 1627 if (tmp_win->title_w) { 1628 grabkey (tmp, 0, tmp_win->title_w); 1629 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) 1630 grabkey (tmp, LockMask, tmp_win->title_w); 1631 for (i = 0 ; i < 8 ; i++) { 1632 if ((Scr->IgnoreModifier & ModifierMask [i]) && 1633 !(tmp->mods & ModifierMask [i])) 1634 grabkey (tmp, ModifierMask [i], tmp_win->title_w); 1635 } 1636 } 1637 break; 1638 /* 1639 case C_ROOT: 1640 XGrabKey(dpy, tmp->keycode, tmp->mods, Scr->Root, True, 1641 GrabModeAsync, GrabModeAsync); 1642 break; 1643 */ 1644 } 1645 } 1646 for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) 1647 { 1648 if (tmp->cont == C_ICONMGR && !Scr->NoIconManagers) 1649 { 1650 for (p = Scr->iconmgr; p != NULL; p = p->next) { 1651 ungrabkey (tmp, 0, p->twm_win->w); 1652 if (Scr->IgnoreLockModifier && !(tmp->mods & LockMask)) 1653 ungrabkey (tmp, LockMask, p->twm_win->w); 1654 for (i = 0 ; i < 8 ; i++) { 1655 if ((Scr->IgnoreModifier & ModifierMask [i]) && 1656 !(tmp->mods & ModifierMask [i])) 1657 ungrabkey (tmp, ModifierMask [i], p->twm_win->w); 1658 } 1659 } 1660 } 1661 } 1662} 1663 1664void ComputeCommonTitleOffsets (void) 1665{ 1666 int buttonwidth = (Scr->TBInfo.width + Scr->TBInfo.pad); 1667 1668 Scr->TBInfo.leftx = Scr->TBInfo.rightoff = Scr->FramePadding; 1669 if (Scr->TBInfo.nleft > 0) Scr->TBInfo.leftx += Scr->ButtonIndent; 1670 if (Scr->TBInfo.nright > 0) Scr->TBInfo.rightoff += (Scr->ButtonIndent + 1671 (Scr->TBInfo.nright * buttonwidth) - 1672 Scr->TBInfo.pad); 1673 1674 Scr->TBInfo.titlex = (Scr->TBInfo.leftx + 1675 (Scr->TBInfo.nleft * buttonwidth) - 1676 Scr->TBInfo.pad + 1677 Scr->TitlePadding); 1678} 1679 1680static void CreateHighlightWindows (TwmWindow *tmp_win) 1681{ 1682 XSetWindowAttributes attributes; /* attributes for create windows */ 1683 GC gc; 1684 XGCValues gcv; 1685 unsigned long valuemask; 1686 int h = (Scr->TitleHeight - 2 * Scr->FramePadding); 1687 int y = Scr->FramePadding; 1688 1689 if (! tmp_win->titlehighlight) { 1690 tmp_win->hilite_wl = (Window) 0; 1691 tmp_win->hilite_wr = (Window) 0; 1692 return; 1693 } 1694 /* 1695 * If a special highlight pixmap was given, use that. Otherwise, 1696 * use a nice, even gray pattern. The old horizontal lines look really 1697 * awful on interlaced monitors (as well as resembling other looks a 1698 * little bit too closely), but can be used by putting 1699 * 1700 * Pixmaps { TitleHighlight "hline2" } 1701 * 1702 * (or whatever the horizontal line bitmap is named) in the startup 1703 * file. If all else fails, use the foreground color to look like a 1704 * solid line. 1705 */ 1706 1707 if (! tmp_win->HiliteImage) { 1708 if (Scr->HighlightPixmapName) { 1709 tmp_win->HiliteImage = GetImage (Scr->HighlightPixmapName, tmp_win->title); 1710 } 1711 } 1712 if (! tmp_win->HiliteImage) { 1713 Pixmap pm = None; 1714 Pixmap bm = None; 1715 1716 if (Scr->use3Dtitles && (Scr->Monochrome != COLOR)) 1717 bm = XCreateBitmapFromData (dpy, tmp_win->title_w, 1718 (char*)black_bits, gray_width, gray_height); 1719 else 1720 bm = XCreateBitmapFromData (dpy, tmp_win->title_w, 1721 (char*)gray_bits, gray_width, gray_height); 1722 1723 pm = XCreatePixmap (dpy, tmp_win->title_w, gray_width, gray_height, Scr->d_depth); 1724 gcv.foreground = tmp_win->title.fore; 1725 gcv.background = tmp_win->title.back; 1726 gcv.graphics_exposures = False; 1727 gc = XCreateGC (dpy, pm, (GCForeground|GCBackground|GCGraphicsExposures), &gcv); 1728 if (gc) { 1729 XCopyPlane (dpy, bm, pm, gc, 0, 0, gray_width, gray_height, 0, 0, 1); 1730 tmp_win->HiliteImage = (Image*) malloc (sizeof (struct _Image)); 1731 tmp_win->HiliteImage->pixmap = pm; 1732 tmp_win->HiliteImage->width = gray_width; 1733 tmp_win->HiliteImage->height = gray_height; 1734 tmp_win->HiliteImage->mask = None; 1735 tmp_win->HiliteImage->next = None; 1736 XFreeGC (dpy, gc); 1737 } else { 1738 XFreePixmap (dpy, pm); 1739 pm = None; 1740 } 1741 XFreePixmap (dpy, bm); 1742 } 1743 if (tmp_win->HiliteImage) { 1744 valuemask = CWBackPixmap; 1745 attributes.background_pixmap = tmp_win->HiliteImage->pixmap; 1746 } else { 1747 valuemask = CWBackPixel; 1748 attributes.background_pixel = tmp_win->title.fore; 1749 } 1750 1751 if (Scr->use3Dtitles) { 1752 y += Scr->TitleShadowDepth; 1753 h -= 2 * Scr->TitleShadowDepth; 1754 } 1755 if (Scr->TitleJustification == J_LEFT) 1756 tmp_win->hilite_wl = (Window) 0; 1757 else 1758 tmp_win->hilite_wl = XCreateWindow (dpy, tmp_win->title_w, 0, y, 1759 (unsigned int) Scr->TBInfo.width, (unsigned int) h, 1760 (unsigned int) 0, Scr->d_depth, (unsigned int) CopyFromParent, 1761 Scr->d_visual, valuemask, &attributes); 1762 1763 if (Scr->TitleJustification == J_RIGHT) 1764 tmp_win->hilite_wr = (Window) 0; 1765 else 1766 tmp_win->hilite_wr = XCreateWindow (dpy, tmp_win->title_w, 0, y, 1767 (unsigned int) Scr->TBInfo.width, (unsigned int) h, 1768 (unsigned int) 0, Scr->d_depth, (unsigned int) CopyFromParent, 1769 Scr->d_visual, valuemask, &attributes); 1770} 1771 1772void DeleteHighlightWindows(TwmWindow *tmp_win) 1773{ 1774 if (tmp_win->HiliteImage) { 1775 if (Scr->HighlightPixmapName) { 1776 /* 1777 * Image obtained from GetImage(): it is in a cache 1778 * so we don't need to free it. There will not be multiple 1779 * copies if the same xpm:foo image is requested again. 1780 */ 1781 } else { 1782 XFreePixmap (dpy, tmp_win->HiliteImage->pixmap); 1783 free(tmp_win->HiliteImage); 1784 } 1785 tmp_win->HiliteImage = NULL; 1786 } 1787} 1788 1789static void CreateLowlightWindows (TwmWindow *tmp_win) 1790{ 1791 XSetWindowAttributes attributes; /* attributes for create windows */ 1792 unsigned long valuemask; 1793 int h = (Scr->TitleHeight - 2 * Scr->FramePadding); 1794 int y = Scr->FramePadding; 1795 ColorPair cp; 1796 1797 if (!Scr->UseSunkTitlePixmap || ! tmp_win->titlehighlight) { 1798 tmp_win->lolite_wl = (Window) 0; 1799 tmp_win->lolite_wr = (Window) 0; 1800 return; 1801 } 1802 /* 1803 * If a special highlight pixmap was given, use that. Otherwise, 1804 * use a nice, even gray pattern. The old horizontal lines look really 1805 * awful on interlaced monitors (as well as resembling other looks a 1806 * little bit too closely), but can be used by putting 1807 * 1808 * Pixmaps { TitleHighlight "hline2" } 1809 * 1810 * (or whatever the horizontal line bitmap is named) in the startup 1811 * file. If all else fails, use the foreground color to look like a 1812 * solid line. 1813 */ 1814 1815 if (! tmp_win->LoliteImage) { 1816 if (Scr->HighlightPixmapName) { 1817 cp = tmp_win->title; 1818 cp.shadc = tmp_win->title.shadd; 1819 cp.shadd = tmp_win->title.shadc; 1820 tmp_win->LoliteImage = GetImage (Scr->HighlightPixmapName, cp); 1821 } 1822 } 1823 if (tmp_win->LoliteImage) { 1824 valuemask = CWBackPixmap; 1825 attributes.background_pixmap = tmp_win->LoliteImage->pixmap; 1826 } else { 1827 valuemask = CWBackPixel; 1828 attributes.background_pixel = tmp_win->title.fore; 1829 } 1830 1831 if (Scr->use3Dtitles) { 1832 y += 2; 1833 h -= 4; 1834 } 1835 if (Scr->TitleJustification == J_LEFT) 1836 tmp_win->lolite_wl = (Window) 0; 1837 else 1838 tmp_win->lolite_wl = XCreateWindow (dpy, tmp_win->title_w, 0, y, 1839 (unsigned int) Scr->TBInfo.width, (unsigned int) h, 1840 (unsigned int) 0, Scr->d_depth, (unsigned int) CopyFromParent, 1841 Scr->d_visual, valuemask, &attributes); 1842 1843 if (Scr->TitleJustification == J_RIGHT) 1844 tmp_win->lolite_wr = (Window) 0; 1845 else 1846 tmp_win->lolite_wr = XCreateWindow (dpy, tmp_win->title_w, 0, y, 1847 (unsigned int) Scr->TBInfo.width, (unsigned int) h, 1848 (unsigned int) 0, Scr->d_depth, (unsigned int) CopyFromParent, 1849 Scr->d_visual, valuemask, &attributes); 1850} 1851 1852 1853void ComputeWindowTitleOffsets (TwmWindow *tmp_win, unsigned int width, 1854 Bool squeeze) 1855{ 1856 int titlew = width - Scr->TBInfo.titlex - Scr->TBInfo.rightoff; 1857 1858 switch (Scr->TitleJustification) { 1859 case J_LEFT : 1860 tmp_win->name_x = Scr->TBInfo.titlex; 1861 if (Scr->use3Dtitles) tmp_win->name_x += Scr->TitleShadowDepth + 2; 1862 break; 1863 case J_CENTER : 1864 tmp_win->name_x = Scr->TBInfo.titlex + (titlew - tmp_win->name_width) / 2; 1865 break; 1866 case J_RIGHT : 1867 tmp_win->name_x = Scr->TBInfo.titlex + titlew - tmp_win->name_width; 1868 if (Scr->use3Dtitles) tmp_win->name_x -= Scr->TitleShadowDepth - 2; 1869 break; 1870 } 1871 if (Scr->use3Dtitles) { 1872 if (tmp_win->name_x < (Scr->TBInfo.titlex + 2 * Scr->TitleShadowDepth)) 1873 tmp_win->name_x = Scr->TBInfo.titlex + 2 * Scr->TitleShadowDepth; 1874 } 1875 else 1876 if (tmp_win->name_x < Scr->TBInfo.titlex) { 1877 tmp_win->name_x = Scr->TBInfo.titlex; 1878 } 1879 tmp_win->highlightxl = Scr->TBInfo.titlex; 1880 tmp_win->highlightxr = tmp_win->name_x + tmp_win->name_width + 2; 1881 1882 if (Scr->use3Dtitles) { 1883 tmp_win->highlightxl += Scr->TitleShadowDepth; 1884 } 1885 if (tmp_win->hilite_wr || Scr->TBInfo.nright > 0) 1886 tmp_win->highlightxr += Scr->TitlePadding; 1887 tmp_win->rightx = width - Scr->TBInfo.rightoff; 1888 if (squeeze && tmp_win->squeeze_info && !tmp_win->squeezed) { 1889 int rx = (tmp_win->highlightxr + 1890 (tmp_win->hilite_wr 1891 ? Scr->TBInfo.width * 2 : 0) + 1892 (Scr->TBInfo.nright > 0 ? Scr->TitlePadding : 0) + 1893 Scr->FramePadding); 1894 if (rx < tmp_win->rightx) tmp_win->rightx = rx; 1895 } 1896 return; 1897} 1898 1899 1900/* 1901 * ComputeTitleLocation - calculate the position of the title window; we need 1902 * to take the frame_bw into account since we want (0,0) of the title window 1903 * to line up with (0,0) of the frame window. 1904 */ 1905void ComputeTitleLocation (register TwmWindow *tmp) 1906{ 1907 tmp->title_x = tmp->frame_bw3D - tmp->frame_bw; 1908 tmp->title_y = tmp->frame_bw3D - tmp->frame_bw; 1909 1910 if (tmp->squeeze_info && !tmp->squeezed) { 1911 register SqueezeInfo *si = tmp->squeeze_info; 1912 int basex; 1913 int maxwidth = tmp->frame_width; 1914 int tw = tmp->title_width + 2 * tmp->frame_bw3D; 1915 1916 /* 1917 * figure label base from squeeze info (justification fraction) 1918 */ 1919 if (si->denom == 0) { /* num is pixel based */ 1920 basex = si->num; 1921 } else { /* num/denom is fraction */ 1922 basex = ((si->num * maxwidth) / si->denom); 1923 } 1924 if (si->num < 0) 1925 basex += maxwidth; 1926 1927 /* 1928 * adjust for left (nop), center, right justify and clip 1929 */ 1930 switch (si->justify) { 1931 case J_CENTER: 1932 basex -= tw / 2; 1933 break; 1934 case J_RIGHT: 1935 basex -= tw - 1; 1936 break; 1937 } 1938 if (basex > maxwidth - tw) 1939 basex = maxwidth - tw; 1940 if (basex < 0) basex = 0; 1941 1942 tmp->title_x = basex - tmp->frame_bw + tmp->frame_bw3D; 1943 } 1944} 1945 1946 1947static void CreateWindowTitlebarButtons (TwmWindow *tmp_win) 1948{ 1949 unsigned long valuemask; /* mask for create windows */ 1950 XSetWindowAttributes attributes; /* attributes for create windows */ 1951 int leftx, rightx, y; 1952 TitleButton *tb; 1953 int nb; 1954 1955 if (tmp_win->title_height == 0) 1956 { 1957 tmp_win->hilite_wl = (Window) 0; 1958 tmp_win->hilite_wr = (Window) 0; 1959 tmp_win->lolite_wl = (Window) 0; 1960 tmp_win->lolite_wr = (Window) 0; 1961 return; 1962 } 1963 1964 1965 /* 1966 * create the title bar windows; let the event handler deal with painting 1967 * so that we don't have to spend two pixmaps (or deal with hashing) 1968 */ 1969 ComputeWindowTitleOffsets (tmp_win, tmp_win->attr.width, False); 1970 1971 leftx = y = Scr->TBInfo.leftx; 1972 rightx = tmp_win->rightx; 1973 1974 attributes.win_gravity = NorthWestGravity; 1975 attributes.background_pixel = tmp_win->title.back; 1976 attributes.border_pixel = tmp_win->title.fore; 1977 attributes.event_mask = (ButtonPressMask | ButtonReleaseMask | 1978 ExposureMask); 1979 attributes.cursor = Scr->ButtonCursor; 1980 valuemask = (CWWinGravity | CWBackPixel | CWBorderPixel | CWEventMask | 1981 CWCursor); 1982 1983 tmp_win->titlebuttons = NULL; 1984 nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; 1985 if (nb > 0) { 1986 tmp_win->titlebuttons = (TBWindow *) malloc (nb * sizeof(TBWindow)); 1987 if (!tmp_win->titlebuttons) { 1988 fprintf (stderr, "%s: unable to allocate %d titlebuttons\n", 1989 ProgramName, nb); 1990 } else { 1991 TBWindow *tbw; 1992 int boxwidth = (Scr->TBInfo.width + Scr->TBInfo.pad); 1993 unsigned int h = (Scr->TBInfo.width - Scr->TBInfo.border * 2); 1994 1995 for (tb = Scr->TBInfo.head, tbw = tmp_win->titlebuttons; tb; 1996 tb = tb->next, tbw++) { 1997 int x; 1998 if (tb->rightside) { 1999 x = rightx; 2000 rightx += boxwidth; 2001 attributes.win_gravity = NorthEastGravity; 2002 } else { 2003 x = leftx; 2004 leftx += boxwidth; 2005 attributes.win_gravity = NorthWestGravity; 2006 } 2007 tbw->window = XCreateWindow (dpy, tmp_win->title_w, x, y, h, h, 2008 (unsigned int) Scr->TBInfo.border, 2009 0, (unsigned int) CopyFromParent, 2010 (Visual *) CopyFromParent, 2011 valuemask, &attributes); 2012 tbw->image = GetImage (tb->name, tmp_win->title); 2013 if (! tbw->image) { 2014 tbw->image = GetImage (TBPM_QUESTION, tmp_win->title); 2015 if (! tbw->image) { /* cannot happen (see util.c) */ 2016 fprintf (stderr, "%s: unable to add titlebar button \"%s\"\n", 2017 ProgramName, tb->name); 2018 } 2019 } 2020 tbw->info = tb; 2021 } 2022 } 2023 } 2024 2025 CreateHighlightWindows (tmp_win); 2026 CreateLowlightWindows (tmp_win); 2027 XMapSubwindows(dpy, tmp_win->title_w); 2028 if (tmp_win->hilite_wl) XUnmapWindow(dpy, tmp_win->hilite_wl); 2029 if (tmp_win->hilite_wr) XUnmapWindow(dpy, tmp_win->hilite_wr); 2030 if (tmp_win->lolite_wl) XMapWindow(dpy, tmp_win->lolite_wl); 2031 if (tmp_win->lolite_wr) XMapWindow(dpy, tmp_win->lolite_wr); 2032 return; 2033} 2034 2035void SetHighlightPixmap (char *filename) 2036{ 2037#ifdef VMS 2038 char *ftemp; 2039 ftemp = (char *) malloc((strlen(filename)+1)*sizeof(char)); 2040 Scr->HighlightPixmapName = strcpy (ftemp,filename); 2041#else 2042 Scr->HighlightPixmapName = (char*) strdup (filename); 2043#endif 2044} 2045 2046 2047void FetchWmProtocols (TwmWindow *tmp) 2048{ 2049 unsigned long flags = 0L; 2050 Atom *protocols = NULL; 2051 int n; 2052 2053 if (XGetWMProtocols (dpy, tmp->w, &protocols, &n)) { 2054 register int i; 2055 register Atom *ap; 2056 2057 for (i = 0, ap = protocols; i < n; i++, ap++) { 2058 if (*ap == _XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus; 2059 if (*ap == _XA_WM_SAVE_YOURSELF) flags |= DoesWmSaveYourself; 2060 if (*ap == _XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow; 2061 } 2062 if (protocols) XFree ((char *) protocols); 2063 } 2064 tmp->protocols = flags; 2065} 2066 2067TwmColormap *CreateTwmColormap(Colormap c) 2068{ 2069 TwmColormap *cmap; 2070 cmap = (TwmColormap *) malloc(sizeof(TwmColormap)); 2071 if (!cmap || 2072 XSaveContext(dpy, c, ColormapContext, (XPointer) cmap)) { 2073 if (cmap) free((char *) cmap); 2074 return (NULL); 2075 } 2076 cmap->c = c; 2077 cmap->state = 0; 2078 cmap->install_req = 0; 2079 cmap->w = None; 2080 cmap->refcnt = 1; 2081 return (cmap); 2082} 2083 2084ColormapWindow *CreateColormapWindow(Window w, 2085 Bool creating_parent, 2086 Bool property_window) 2087{ 2088 ColormapWindow *cwin; 2089 TwmColormap *cmap; 2090 XWindowAttributes attributes; 2091 2092 cwin = (ColormapWindow *) malloc(sizeof(ColormapWindow)); 2093 if (cwin) { 2094 if (!XGetWindowAttributes(dpy, w, &attributes) || 2095 XSaveContext(dpy, w, ColormapContext, (XPointer) cwin)) { 2096 free((char *) cwin); 2097 return (NULL); 2098 } 2099 2100 if (XFindContext(dpy, attributes.colormap, ColormapContext, 2101 (XPointer *)&cwin->colormap) == XCNOENT) { 2102 cwin->colormap = cmap = CreateTwmColormap(attributes.colormap); 2103 if (!cmap) { 2104 XDeleteContext(dpy, w, ColormapContext); 2105 free((char *) cwin); 2106 return (NULL); 2107 } 2108 } else { 2109 cwin->colormap->refcnt++; 2110 } 2111 2112 cwin->w = w; 2113 /* 2114 * Assume that windows in colormap list are 2115 * obscured if we are creating the parent window. 2116 * Otherwise, we assume they are unobscured. 2117 */ 2118 cwin->visibility = creating_parent ? 2119 VisibilityPartiallyObscured : VisibilityUnobscured; 2120 cwin->refcnt = 1; 2121 2122 /* 2123 * If this is a ColormapWindow property window and we 2124 * are not monitoring ColormapNotify or VisibilityNotify 2125 * events, we need to. 2126 */ 2127 if (property_window && 2128 (attributes.your_event_mask & 2129 (ColormapChangeMask|VisibilityChangeMask)) != 2130 (ColormapChangeMask|VisibilityChangeMask)) { 2131 XSelectInput(dpy, w, attributes.your_event_mask | 2132 (ColormapChangeMask|VisibilityChangeMask)); 2133 } 2134 } 2135 2136 return (cwin); 2137} 2138 2139int FetchWmColormapWindows (TwmWindow *tmp) 2140{ 2141 register int i, j; 2142 Window *cmap_windows = NULL; 2143 Bool can_free_cmap_windows = False; 2144 int number_cmap_windows = 0; 2145 ColormapWindow **cwins = NULL; 2146 int previously_installed; 2147 2148 number_cmap_windows = 0; 2149 2150 if (/* SUPPRESS 560 */ 2151 (previously_installed = 2152 (Scr->cmapInfo.cmaps == &tmp->cmaps && tmp->cmaps.number_cwins))) { 2153 cwins = tmp->cmaps.cwins; 2154 for (i = 0; i < tmp->cmaps.number_cwins; i++) 2155 cwins[i]->colormap->state = 0; 2156 } 2157 2158 if (XGetWMColormapWindows (dpy, tmp->w, &cmap_windows, 2159 &number_cmap_windows) && 2160 number_cmap_windows > 0) { 2161 2162 can_free_cmap_windows = False; 2163 /* 2164 * check if the top level is in the list, add to front if not 2165 */ 2166 for (i = 0; i < number_cmap_windows; i++) { 2167 if (cmap_windows[i] == tmp->w) break; 2168 } 2169 if (i == number_cmap_windows) { /* not in list */ 2170 Window *new_cmap_windows = 2171 (Window *) malloc (sizeof(Window) * (number_cmap_windows + 1)); 2172 2173 if (!new_cmap_windows) { 2174 fprintf (stderr, 2175 "%s: unable to allocate %d element colormap window array\n", 2176 ProgramName, number_cmap_windows+1); 2177 goto done; 2178 } 2179 new_cmap_windows[0] = tmp->w; /* add to front */ 2180 for (i = 0; i < number_cmap_windows; i++) { /* append rest */ 2181 new_cmap_windows[i+1] = cmap_windows[i]; 2182 } 2183 XFree ((char *) cmap_windows); 2184 can_free_cmap_windows = True; /* do not use XFree any more */ 2185 cmap_windows = new_cmap_windows; 2186 number_cmap_windows++; 2187 } 2188 2189 cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *) * 2190 number_cmap_windows); 2191 if (cwins) { 2192 for (i = 0; i < number_cmap_windows; i++) { 2193 2194 /* 2195 * Copy any existing entries into new list. 2196 */ 2197 for (j = 0; j < tmp->cmaps.number_cwins; j++) { 2198 if (tmp->cmaps.cwins[j]->w == cmap_windows[i]) { 2199 cwins[i] = tmp->cmaps.cwins[j]; 2200 cwins[i]->refcnt++; 2201 break; 2202 } 2203 } 2204 2205 /* 2206 * If the colormap window is not being pointed by 2207 * some other applications colormap window list, 2208 * create a new entry. 2209 */ 2210 if (j == tmp->cmaps.number_cwins) { 2211 if (XFindContext(dpy, cmap_windows[i], ColormapContext, 2212 (XPointer *)&cwins[i]) == XCNOENT) { 2213 if ((cwins[i] = CreateColormapWindow(cmap_windows[i], 2214 (Bool) tmp->cmaps.number_cwins == 0, 2215 True)) == NULL) { 2216 int k; 2217 for (k = i + 1; k < number_cmap_windows; k++) 2218 cmap_windows[k-1] = cmap_windows[k]; 2219 i--; 2220 number_cmap_windows--; 2221 } 2222 } else 2223 cwins[i]->refcnt++; 2224 } 2225 } 2226 } 2227 } 2228 2229 /* No else here, in case we bailed out of clause above. 2230 */ 2231 if (number_cmap_windows == 0) { 2232 2233 number_cmap_windows = 1; 2234 2235 cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *)); 2236 if (XFindContext(dpy, tmp->w, ColormapContext, (XPointer *)&cwins[0]) == 2237 XCNOENT) 2238 cwins[0] = CreateColormapWindow(tmp->w, 2239 (Bool) tmp->cmaps.number_cwins == 0, False); 2240 else 2241 cwins[0]->refcnt++; 2242 } 2243 2244 if (tmp->cmaps.number_cwins) 2245 free_cwins(tmp); 2246 2247 tmp->cmaps.cwins = cwins; 2248 tmp->cmaps.number_cwins = number_cmap_windows; 2249 if (number_cmap_windows > 1) 2250 tmp->cmaps.scoreboard = 2251 (char *) calloc(1, ColormapsScoreboardLength(&tmp->cmaps)); 2252 2253 if (previously_installed) { 2254 InstallColormaps(PropertyNotify, NULL); 2255 } 2256 2257 done: 2258 if (cmap_windows) { 2259 if (can_free_cmap_windows) 2260 free ((char *) cmap_windows); 2261 else 2262 XFree ((char *) cmap_windows); 2263 } 2264 2265 return (0); 2266} 2267 2268 2269void GetWindowSizeHints (TwmWindow *tmp) 2270{ 2271 long supplied = 0; 2272 XSizeHints *hints = &tmp->hints; 2273 2274 if (!XGetWMNormalHints (dpy, tmp->w, hints, &supplied)) 2275 hints->flags = 0; 2276 2277 if (hints->flags & PResizeInc) { 2278 if (hints->width_inc == 0) hints->width_inc = 1; 2279 if (hints->height_inc == 0) hints->height_inc = 1; 2280 } 2281 2282 if (!(supplied & PWinGravity) && (hints->flags & USPosition)) { 2283 static int gravs[] = { SouthEastGravity, SouthWestGravity, 2284 NorthEastGravity, NorthWestGravity }; 2285 int right = tmp->attr.x + tmp->attr.width + 2 * tmp->old_bw; 2286 int bottom = tmp->attr.y + tmp->attr.height + 2 * tmp->old_bw; 2287 hints->win_gravity = 2288 gravs[((Scr->rooth - bottom < 2289 tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 2) | 2290 ((Scr->rootw - right < 2291 tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 1)]; 2292 hints->flags |= PWinGravity; 2293 } 2294 2295 /* Check for min size < max size */ 2296 if ((hints->flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize)) { 2297 if (hints->max_width < hints->min_width) { 2298 if (hints->max_width > 0) { 2299 hints->min_width = hints->max_width; 2300 } else if (hints->min_width > 0) { 2301 hints->max_width = hints->min_width; 2302 } else { 2303 hints->max_width = hints->min_width = 1; 2304 } 2305 } 2306 2307 if (hints->max_height < hints->min_height) { 2308 if (hints->max_height > 0) { 2309 hints->min_height = hints->max_height; 2310 } else if (hints->min_height > 0) { 2311 hints->max_height = hints->min_height; 2312 } else { 2313 hints->max_height = hints->min_height = 1; 2314 } 2315 } 2316 } 2317} 2318 2319void AnimateButton (TBWindow *tbw) 2320{ 2321 Image *image; 2322 XSetWindowAttributes attr; 2323 2324 image = tbw->image; 2325 attr.background_pixmap = image->pixmap; 2326 XChangeWindowAttributes (dpy, tbw->window, CWBackPixmap, &attr); 2327 XClearWindow (dpy, tbw->window); 2328 tbw->image = image->next; 2329} 2330 2331void AnimateHighlight (TwmWindow *t) 2332{ 2333 Image *image; 2334 XSetWindowAttributes attr; 2335 2336 image = t->HiliteImage; 2337 attr.background_pixmap = image->pixmap; 2338 if (t->hilite_wl) { 2339 XChangeWindowAttributes (dpy, t->hilite_wl, CWBackPixmap, &attr); 2340 XClearWindow (dpy, t->hilite_wl); 2341 } 2342 if (t->hilite_wr) { 2343 XChangeWindowAttributes (dpy, t->hilite_wr, CWBackPixmap, &attr); 2344 XClearWindow (dpy, t->hilite_wr); 2345 } 2346 t->HiliteImage = image->next; 2347} 2348 2349name_list **AddWindowRegion (char *geom, int grav1, int grav2) 2350{ 2351 WindowRegion *wr; 2352 int mask; 2353 2354 wr = (WindowRegion*) malloc (sizeof (WindowRegion)); 2355 wr->next = NULL; 2356 2357 if (!Scr->FirstWindowRegion) Scr->FirstWindowRegion = wr; 2358 2359 wr->entries = NULL; 2360 wr->clientlist = NULL; 2361 wr->grav1 = grav1; 2362 wr->grav2 = grav2; 2363 wr->x = wr->y = wr->w = wr->h = 0; 2364 2365 mask = XParseGeometry (geom, &wr->x, &wr->y, (unsigned int*) &wr->w, 2366 (unsigned int*) &wr->h); 2367 2368 if (mask & XNegative) wr->x += Scr->rootw - wr->w; 2369 if (mask & YNegative) wr->y += Scr->rooth - wr->h; 2370 2371 return (&(wr->clientlist)); 2372} 2373 2374void CreateWindowRegions (void) { 2375 WindowRegion *wr, *wr1 = NULL, *wr2 = NULL; 2376 WorkSpace *wl; 2377 2378 for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) { 2379 wl->FirstWindowRegion = NULL; 2380 wr2 = NULL; 2381 for (wr = Scr->FirstWindowRegion; wr != NULL; wr = wr->next) { 2382 wr1 = (WindowRegion*) malloc (sizeof (WindowRegion)); 2383 *wr1 = *wr; 2384 wr1->entries = (WindowEntry*) malloc (sizeof (WindowEntry)); 2385 wr1->entries->next = 0; 2386 wr1->entries->x = wr1->x; 2387 wr1->entries->y = wr1->y; 2388 wr1->entries->w = wr1->w; 2389 wr1->entries->h = wr1->h; 2390 wr1->entries->twm_win = (TwmWindow*) 0; 2391 wr1->entries->used = 0; 2392 if (wr2) wr2->next = wr1; else wl->FirstWindowRegion = wr1; 2393 wr2 = wr1; 2394 } 2395 if (wr1) wr1->next = NULL; 2396 } 2397} 2398 2399 2400Bool PlaceWindowInRegion (TwmWindow *tmp_win, int *final_x, int *final_y) 2401{ 2402 WindowRegion *wr; 2403 WindowEntry *we; 2404 int w, h; 2405 WorkSpace *wl; 2406 2407 if (!Scr->FirstWindowRegion) return (False); 2408 for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) { 2409 if (OCCUPY (tmp_win, wl)) break; 2410 } 2411 if (!wl) return (False); 2412 w = tmp_win->frame_width; 2413 h = tmp_win->frame_height; 2414 we = (WindowEntry*) 0; 2415 for (wr = wl->FirstWindowRegion; wr; wr = wr->next) { 2416 if (LookInList (wr->clientlist, tmp_win->full_name, &tmp_win->class)) { 2417 for (we = wr->entries; we; we=we->next) { 2418 if (we->used) continue; 2419 if (we->w >= w && we->h >= h) break; 2420 } 2421 if (we) break; 2422 } 2423 } 2424 tmp_win->wr = (WindowRegion*) 0; 2425 if (!we) return (False); 2426 2427 splitWindowRegionEntry (we, wr->grav1, wr->grav2, w, h); 2428 we->used = 1; 2429 we->twm_win = tmp_win; 2430 *final_x = we->x; 2431 *final_y = we->y; 2432 tmp_win->wr = wr; 2433 return (True); 2434} 2435 2436static void splitWindowRegionEntry (WindowEntry *we, int grav1, int grav2, 2437 int w, int h) 2438{ 2439 WindowEntry *new; 2440 2441 switch (grav1) { 2442 case D_NORTH: 2443 case D_SOUTH: 2444 if (w != we->w) splitWindowRegionEntry (we, grav2, grav1, w, we->h); 2445 if (h != we->h) { 2446 new = (WindowEntry *) malloc (sizeof (WindowEntry)); 2447 new->twm_win = 0; 2448 new->used = 0; 2449 new->next = we->next; 2450 we->next = new; 2451 new->x = we->x; 2452 new->h = (we->h - h); 2453 new->w = we->w; 2454 we->h = h; 2455 if (grav1 == D_SOUTH) { 2456 new->y = we->y; 2457 we->y = new->y + new->h; 2458 } else 2459 new->y = we->y + we->h; 2460 } 2461 break; 2462 case D_EAST: 2463 case D_WEST: 2464 if (h != we->h) splitWindowRegionEntry (we, grav2, grav1, we->w, h); 2465 if (w != we->w) { 2466 new = (WindowEntry *) malloc (sizeof (WindowEntry)); 2467 new->twm_win = 0; 2468 new->used = 0; 2469 new->next = we->next; 2470 we->next = new; 2471 new->y = we->y; 2472 new->w = (we->w - w); 2473 new->h = we->h; 2474 we->w = w; 2475 if (grav1 == D_EAST) { 2476 new->x = we->x; 2477 we->x = new->x + new->w; 2478 } else 2479 new->x = we->x + we->w; 2480 } 2481 break; 2482 } 2483} 2484 2485static WindowEntry *findWindowEntry (WorkSpace *wl, TwmWindow *tmp_win, 2486 WindowRegion **wrp) 2487{ 2488 WindowRegion *wr; 2489 WindowEntry *we; 2490 2491 for (wr = wl->FirstWindowRegion; wr; wr = wr->next) { 2492 for (we = wr->entries; we; we=we->next) { 2493 if (we->twm_win == tmp_win) { 2494 if (wrp) *wrp = wr; 2495 return we; 2496 } 2497 } 2498 } 2499 return (WindowEntry*) 0; 2500} 2501 2502static WindowEntry *prevWindowEntry (WindowEntry *we, WindowRegion *wr) 2503{ 2504 WindowEntry *wp; 2505 2506 if (we == wr->entries) return 0; 2507 for (wp = wr->entries; wp->next != we; wp=wp->next); 2508 return wp; 2509} 2510 2511static void mergeWindowEntries (WindowEntry *old, WindowEntry *we) 2512{ 2513 if (old->y == we->y) { 2514 we->w = old->w + we->w; 2515 if (old->x < we->x) we->x = old->x; 2516 } else { 2517 we->h = old->h + we->h; 2518 if (old->y < we->y) we->y = old->y; 2519 } 2520} 2521 2522void RemoveWindowFromRegion (TwmWindow *tmp_win) 2523{ 2524 WindowEntry *we, *wp, *wn; 2525 WindowRegion *wr; 2526 WorkSpace *wl; 2527 2528 if (!Scr->FirstWindowRegion) return; 2529 we = (WindowEntry*) 0; 2530 for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) { 2531 we = findWindowEntry (wl, tmp_win, &wr); 2532 if (we) break; 2533 } 2534 if (!we) return; 2535 2536 we->twm_win = 0; 2537 we->used = 0; 2538 wp = prevWindowEntry (we, wr); 2539 wn = we->next; 2540 for (;;) { 2541 if (wp && wp->used == 0 && 2542 ((wp->x == we->x && wp->w == we->w) || 2543 (wp->y == we->y && wp->h == we->h))) { 2544 wp->next = we->next; 2545 mergeWindowEntries (we, wp); 2546 free ((char *) we); 2547 we = wp; 2548 wp = prevWindowEntry (wp, wr); 2549 } else 2550 if (wn && wn->used == 0 && 2551 ((wn->x == we->x && wn->w == we->w) || 2552 (wn->y == we->y && wn->h == we->h))) { 2553 we->next = wn->next; 2554 mergeWindowEntries (wn, we); 2555 free ((char *) wn); 2556 wn = we->next; 2557 } else break; 2558 } 2559} 2560 2561/* 2562 * This is largely for Xinerama support with VirtualScreens. 2563 * In this case, windows may be on something other then the main screen 2564 * on startup, or the mapping may be relative to the right side of the 2565 * screen, which is on a different monitor, which will cause issues with 2566 * the virtual screens. 2567 * 2568 * It probably needs to be congnizant of windows that are actually owned by 2569 * other workspaces, and ignore them (this needs to be revisited), or perhaps 2570 * that functionality is appropriate in AddWindow(). This needs to be dug into 2571 * more deply. 2572 * 2573 * this approach assumes screens that are next to each other horizontally, 2574 * Other possibilities need to be investigated and accounted for. 2575 */ 2576void DealWithNonSensicalGeometries(Display *mydpy, Window vroot, TwmWindow *tmp_win) 2577{ 2578 Window vvroot; 2579 int x,y; 2580 unsigned int w,h; 2581 unsigned int j; 2582 virtualScreen *myvs, *vs; 2583 int dropx = 0; 2584 2585 if(! vroot) 2586 return; 2587 2588 if(!(XGetGeometry(mydpy, vroot, &vvroot, &x, &y, &w, &h, &j, &j))) 2589 return; 2590 2591 myvs = findIfVScreenOf(x, y); 2592 2593 /* 2594 * probably need to rethink this for unmapped vs's. ugh. 2595 */ 2596 if(!myvs) 2597 return; 2598 2599 for(vs = myvs->next; vs; vs = vs->next) { 2600 dropx += vs->w; 2601 } 2602 2603 for(vs = Scr->vScreenList; vs && vs != myvs; vs = vs->next) { 2604 dropx -= vs->w; 2605 } 2606 2607 if(tmp_win->frame_x > 0 && tmp_win->frame_x >= w) { 2608 tmp_win->frame_x -= abs(dropx); 2609 } else { 2610} 2611 2612} 2613