resize.c revision c2535118
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 * window resizing borrowed from the "wm" window manager 56 * 57 * 11-Dec-87 Thomas E. LaStrange File created 58 * 59 ***********************************************************************/ 60 61#include <stdio.h> 62#include "twm.h" 63#include "parse.h" 64#include "util.h" 65#include "resize.h" 66#include "iconmgr.h" 67#include "add_window.h" 68#include "screen.h" 69#include "events.h" 70 71static void DisplaySize ( TwmWindow *tmp_win, int width, int height ); 72 73#define MINHEIGHT 0 /* had been 32 */ 74#define MINWIDTH 0 /* had been 60 */ 75 76static int dragx; /* all these variables are used */ 77static int dragy; /* in resize operations */ 78static int dragWidth; 79static int dragHeight; 80 81static int origx; 82static int origy; 83static int origWidth; 84static int origHeight; 85 86static int clampTop; 87static int clampBottom; 88static int clampLeft; 89static int clampRight; 90static int clampDX; 91static int clampDY; 92 93static int last_width; 94static int last_height; 95 96 97static void 98do_auto_clamp (TwmWindow *tmp_win, XEvent *evp) 99{ 100 Window junkRoot; 101 int x, y, h, v, junkbw; 102 unsigned int junkMask; 103 104 switch (evp->type) { 105 case ButtonPress: 106 x = evp->xbutton.x_root; 107 y = evp->xbutton.y_root; 108 break; 109 case KeyPress: 110 x = evp->xkey.x_root; 111 y = evp->xkey.y_root; 112 break; 113 default: 114 if (!XQueryPointer (dpy, Scr->Root, &junkRoot, &junkRoot, 115 &x, &y, &junkbw, &junkbw, &junkMask)) 116 return; 117 } 118 119 h = ((x - dragx) / (dragWidth < 3 ? 1 : (dragWidth / 3))); 120 v = ((y - dragy - tmp_win->title_height) / 121 (dragHeight < 3 ? 1 : (dragHeight / 3))); 122 123 if (h <= 0) { 124 clampLeft = 1; 125 clampDX = (x - dragx); 126 } else if (h >= 2) { 127 clampRight = 1; 128 clampDX = (x - dragx - dragWidth); 129 } 130 131 if (v <= 0) { 132 clampTop = 1; 133 clampDY = (y - dragy); 134 } else if (v >= 2) { 135 clampBottom = 1; 136 clampDY = (y - dragy - dragHeight); 137 } 138} 139 140 141/** 142 * begin a window resize operation 143 * \param ev the event structure (button press) 144 * \param tmp_win the TwmWindow pointer 145 * \param fromtitlebar action invoked from titlebar button 146 */ 147void 148StartResize(XEvent *evp, TwmWindow *tmp_win, Bool fromtitlebar) 149{ 150 Window junkRoot; 151 unsigned int junkbw, junkDepth; 152 153 ResizeWindow = tmp_win->frame; 154 XGrabServer(dpy); 155 XGrabPointer(dpy, Scr->Root, True, 156 ButtonPressMask | ButtonReleaseMask | 157 ButtonMotionMask | PointerMotionHintMask, 158 GrabModeAsync, GrabModeAsync, 159 Scr->Root, Scr->ResizeCursor, CurrentTime); 160 161 XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot, 162 &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&dragHeight, &junkbw, 163 &junkDepth); 164 dragx += tmp_win->frame_bw; 165 dragy += tmp_win->frame_bw; 166 origx = dragx; 167 origy = dragy; 168 origWidth = dragWidth; 169 origHeight = dragHeight; 170 clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0; 171 172 if (Scr->AutoRelativeResize && !fromtitlebar) 173 do_auto_clamp (tmp_win, evp); 174 175 Scr->SizeStringOffset = SIZE_HINDENT; 176 XResizeWindow (dpy, Scr->SizeWindow, 177 Scr->SizeStringWidth + SIZE_HINDENT * 2, 178 Scr->SizeFont.height + SIZE_VINDENT * 2); 179 XMapRaised(dpy, Scr->SizeWindow); 180 InstallRootColormap(); 181 last_width = 0; 182 last_height = 0; 183 DisplaySize(tmp_win, origWidth, origHeight); 184 MoveOutline (Scr->Root, dragx - tmp_win->frame_bw, 185 dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw, 186 dragHeight + 2 * tmp_win->frame_bw, 187 tmp_win->frame_bw, tmp_win->title_height); 188} 189 190 191 192void 193MenuStartResize(TwmWindow *tmp_win, int x, int y, int w, int h) 194{ 195 XGrabServer(dpy); 196 XGrabPointer(dpy, Scr->Root, True, 197 ButtonPressMask | ButtonMotionMask | PointerMotionMask, 198 GrabModeAsync, GrabModeAsync, 199 Scr->Root, Scr->ResizeCursor, CurrentTime); 200 dragx = x + tmp_win->frame_bw; 201 dragy = y + tmp_win->frame_bw; 202 origx = dragx; 203 origy = dragy; 204 dragWidth = origWidth = w; /* - 2 * tmp_win->frame_bw; */ 205 dragHeight = origHeight = h; /* - 2 * tmp_win->frame_bw; */ 206 clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0; 207 last_width = 0; 208 last_height = 0; 209 Scr->SizeStringOffset = SIZE_HINDENT; 210 XResizeWindow (dpy, Scr->SizeWindow, 211 Scr->SizeStringWidth + SIZE_HINDENT * 2, 212 Scr->SizeFont.height + SIZE_VINDENT * 2); 213 XMapRaised(dpy, Scr->SizeWindow); 214 DisplaySize(tmp_win, origWidth, origHeight); 215 MoveOutline (Scr->Root, dragx - tmp_win->frame_bw, 216 dragy - tmp_win->frame_bw, 217 dragWidth + 2 * tmp_win->frame_bw, 218 dragHeight + 2 * tmp_win->frame_bw, 219 tmp_win->frame_bw, tmp_win->title_height); 220} 221 222/** 223 * begin a windorew resize operation from AddWindow 224 * \param tmp_win the TwmWindow pointer 225 */ 226void 227AddStartResize(TwmWindow *tmp_win, int x, int y, int w, int h) 228{ 229 XGrabServer(dpy); 230 XGrabPointer(dpy, Scr->Root, True, 231 ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask, 232 GrabModeAsync, GrabModeAsync, 233 Scr->Root, Scr->ResizeCursor, CurrentTime); 234 235 dragx = x + tmp_win->frame_bw; 236 dragy = y + tmp_win->frame_bw; 237 origx = dragx; 238 origy = dragy; 239 dragWidth = origWidth = w - 2 * tmp_win->frame_bw; 240 dragHeight = origHeight = h - 2 * tmp_win->frame_bw; 241 clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0; 242/***** 243 if (Scr->AutoRelativeResize) { 244 clampRight = clampBottom = 1; 245 } 246*****/ 247 last_width = 0; 248 last_height = 0; 249 DisplaySize(tmp_win, origWidth, origHeight); 250} 251 252 253 254void 255MenuDoResize(int x_root, int y_root, TwmWindow *tmp_win) 256{ 257 int action; 258 259 action = 0; 260 261 x_root -= clampDX; 262 y_root -= clampDY; 263 264 if (clampTop) { 265 int delta = y_root - dragy; 266 if (dragHeight - delta < MINHEIGHT) { 267 delta = dragHeight - MINHEIGHT; 268 clampTop = 0; 269 } 270 dragy += delta; 271 dragHeight -= delta; 272 action = 1; 273 } 274 else if (y_root <= dragy/* || 275 y_root == findRootInfo(root)->rooty*/) { 276 dragy = y_root; 277 dragHeight = origy + origHeight - 278 y_root; 279 clampBottom = 0; 280 clampTop = 1; 281 clampDY = 0; 282 action = 1; 283 } 284 if (clampLeft) { 285 int delta = x_root - dragx; 286 if (dragWidth - delta < MINWIDTH) { 287 delta = dragWidth - MINWIDTH; 288 clampLeft = 0; 289 } 290 dragx += delta; 291 dragWidth -= delta; 292 action = 1; 293 } 294 else if (x_root <= dragx/* || 295 x_root == findRootInfo(root)->rootx*/) { 296 dragx = x_root; 297 dragWidth = origx + origWidth - 298 x_root; 299 clampRight = 0; 300 clampLeft = 1; 301 clampDX = 0; 302 action = 1; 303 } 304 if (clampBottom) { 305 int delta = y_root - dragy - dragHeight; 306 if (dragHeight + delta < MINHEIGHT) { 307 delta = MINHEIGHT - dragHeight; 308 clampBottom = 0; 309 } 310 dragHeight += delta; 311 action = 1; 312 } 313 else if (y_root >= dragy + dragHeight) { 314 dragy = origy; 315 dragHeight = 1 + y_root - dragy; 316 clampTop = 0; 317 clampBottom = 1; 318 clampDY = 0; 319 action = 1; 320 } 321 if (clampRight) { 322 int delta = x_root - dragx - dragWidth; 323 if (dragWidth + delta < MINWIDTH) { 324 delta = MINWIDTH - dragWidth; 325 clampRight = 0; 326 } 327 dragWidth += delta; 328 action = 1; 329 } 330 else if (x_root >= dragx + dragWidth) { 331 dragx = origx; 332 dragWidth = 1 + x_root - origx; 333 clampLeft = 0; 334 clampRight = 1; 335 clampDX = 0; 336 action = 1; 337 } 338 339 if (action) { 340 ConstrainSize (tmp_win, &dragWidth, &dragHeight); 341 if (clampLeft) 342 dragx = origx + origWidth - dragWidth; 343 if (clampTop) 344 dragy = origy + origHeight - dragHeight; 345 MoveOutline(Scr->Root, 346 dragx - tmp_win->frame_bw, 347 dragy - tmp_win->frame_bw, 348 dragWidth + 2 * tmp_win->frame_bw, 349 dragHeight + 2 * tmp_win->frame_bw, 350 tmp_win->frame_bw, tmp_win->title_height); 351 } 352 353 DisplaySize(tmp_win, dragWidth, dragHeight); 354} 355 356 357/** 358 * move the rubberband around. This is called for each motion event when 359 * we are resizing 360 * 361 * \param x_root the X corrdinate in the root window 362 * \param y_root the Y corrdinate in the root window 363 * \param tmp_win the current twm window 364 */ 365void 366DoResize(int x_root, int y_root, TwmWindow *tmp_win) 367{ 368 int action; 369 370 action = 0; 371 372 x_root -= clampDX; 373 y_root -= clampDY; 374 375 if (clampTop) { 376 int delta = y_root - dragy; 377 if (dragHeight - delta < MINHEIGHT) { 378 delta = dragHeight - MINHEIGHT; 379 clampTop = 0; 380 } 381 dragy += delta; 382 dragHeight -= delta; 383 action = 1; 384 } 385 else if (y_root <= dragy/* || 386 y_root == findRootInfo(root)->rooty*/) { 387 dragy = y_root; 388 dragHeight = origy + origHeight - 389 y_root; 390 clampBottom = 0; 391 clampTop = 1; 392 clampDY = 0; 393 action = 1; 394 } 395 if (clampLeft) { 396 int delta = x_root - dragx; 397 if (dragWidth - delta < MINWIDTH) { 398 delta = dragWidth - MINWIDTH; 399 clampLeft = 0; 400 } 401 dragx += delta; 402 dragWidth -= delta; 403 action = 1; 404 } 405 else if (x_root <= dragx/* || 406 x_root == findRootInfo(root)->rootx*/) { 407 dragx = x_root; 408 dragWidth = origx + origWidth - 409 x_root; 410 clampRight = 0; 411 clampLeft = 1; 412 clampDX = 0; 413 action = 1; 414 } 415 if (clampBottom) { 416 int delta = y_root - dragy - dragHeight; 417 if (dragHeight + delta < MINHEIGHT) { 418 delta = MINHEIGHT - dragHeight; 419 clampBottom = 0; 420 } 421 dragHeight += delta; 422 action = 1; 423 } 424 else if (y_root >= dragy + dragHeight - 1/* || 425 y_root == findRootInfo(root)->rooty 426 + findRootInfo(root)->rootheight - 1*/) { 427 dragy = origy; 428 dragHeight = 1 + y_root - dragy; 429 clampTop = 0; 430 clampBottom = 1; 431 clampDY = 0; 432 action = 1; 433 } 434 if (clampRight) { 435 int delta = x_root - dragx - dragWidth; 436 if (dragWidth + delta < MINWIDTH) { 437 delta = MINWIDTH - dragWidth; 438 clampRight = 0; 439 } 440 dragWidth += delta; 441 action = 1; 442 } 443 else if (x_root >= dragx + dragWidth - 1/* || 444 x_root == findRootInfo(root)->rootx + 445 findRootInfo(root)->rootwidth - 1*/) { 446 dragx = origx; 447 dragWidth = 1 + x_root - origx; 448 clampLeft = 0; 449 clampRight = 1; 450 clampDX = 0; 451 action = 1; 452 } 453 454 if (action) { 455 ConstrainSize (tmp_win, &dragWidth, &dragHeight); 456 if (clampLeft) 457 dragx = origx + origWidth - dragWidth; 458 if (clampTop) 459 dragy = origy + origHeight - dragHeight; 460 MoveOutline(Scr->Root, 461 dragx - tmp_win->frame_bw, 462 dragy - tmp_win->frame_bw, 463 dragWidth + 2 * tmp_win->frame_bw, 464 dragHeight + 2 * tmp_win->frame_bw, 465 tmp_win->frame_bw, tmp_win->title_height); 466 } 467 468 DisplaySize(tmp_win, dragWidth, dragHeight); 469} 470 471/** 472 * display the size in the dimensions window. 473 * 474 * \param tmp_win the current twm window 475 * \param width the width of the rubber band 476 * \param height the height of the rubber band 477 */ 478static void 479DisplaySize(TwmWindow *tmp_win, int width, int height) 480{ 481 char str[100]; 482 int dwidth; 483 int dheight; 484 485 if (last_width == width && last_height == height) 486 return; 487 488 last_width = width; 489 last_height = height; 490 491 dheight = height - tmp_win->title_height; 492 dwidth = width; 493 494 /* 495 * ICCCM says that PMinSize is the default is no PBaseSize is given, 496 * and vice-versa. 497 */ 498 if (tmp_win->hints.flags&(PMinSize|PBaseSize) && tmp_win->hints.flags & PResizeInc) 499 { 500 if (tmp_win->hints.flags & PBaseSize) { 501 dwidth -= tmp_win->hints.base_width; 502 dheight -= tmp_win->hints.base_height; 503 } else { 504 dwidth -= tmp_win->hints.min_width; 505 dheight -= tmp_win->hints.min_height; 506 } 507 } 508 509 if (tmp_win->hints.flags & PResizeInc) 510 { 511 dwidth /= tmp_win->hints.width_inc; 512 dheight /= tmp_win->hints.height_inc; 513 } 514 515 (void) snprintf (str, sizeof(str), " %4d x %-4d ", dwidth, dheight); 516 XRaiseWindow(dpy, Scr->SizeWindow); 517 MyFont_ChangeGC(Scr->DefaultC.fore, Scr->DefaultC.back, &Scr->SizeFont); 518 MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont, 519 Scr->NormalGC, Scr->SizeStringOffset, 520 Scr->SizeFont.ascent + SIZE_VINDENT, 521 str, 13); 522} 523 524/** 525 * finish the resize operation 526 */ 527void 528EndResize(void) 529{ 530 TwmWindow *tmp_win; 531 532#ifdef DEBUG 533 fprintf(stderr, "EndResize\n"); 534#endif 535 536 MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0); 537 XUnmapWindow(dpy, Scr->SizeWindow); 538 539 XFindContext(dpy, ResizeWindow, TwmContext, (caddr_t *)&tmp_win); 540 541 ConstrainSize (tmp_win, &dragWidth, &dragHeight); 542 543 if (dragWidth != tmp_win->frame_width || 544 dragHeight != tmp_win->frame_height) 545 tmp_win->zoomed = ZOOM_NONE; 546 547 SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, 548 dragWidth, dragHeight, -1); 549 550 if (tmp_win->iconmgr) 551 { 552 int ncols = tmp_win->iconmgrp->cur_columns; 553 if (ncols == 0) ncols = 1; 554 555 tmp_win->iconmgrp->width = (int) ((dragWidth * 556 (long) tmp_win->iconmgrp->columns) 557 / ncols); 558 PackIconManager(tmp_win->iconmgrp); 559 } 560 561 if (!Scr->NoRaiseResize) 562 XRaiseWindow(dpy, tmp_win->frame); 563 564 UninstallRootColormap(); 565 566 ResizeWindow = None; 567} 568 569void 570MenuEndResize(TwmWindow *tmp_win) 571{ 572 MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0); 573 XUnmapWindow(dpy, Scr->SizeWindow); 574 ConstrainSize (tmp_win, &dragWidth, &dragHeight); 575 AddingX = dragx - tmp_win->frame_bw; 576 AddingY = dragy - tmp_win->frame_bw; 577 AddingW = dragWidth;/* + (2 * tmp_win->frame_bw);*/ 578 AddingH = dragHeight;/* + (2 * tmp_win->frame_bw);*/ 579 SetupWindow (tmp_win, AddingX, AddingY, AddingW, AddingH, -1); 580} 581 582 583 584/** 585 * finish the resize operation for AddWindo<w 586 */ 587void 588AddEndResize(TwmWindow *tmp_win) 589{ 590 591#ifdef DEBUG 592 fprintf(stderr, "AddEndResize\n"); 593#endif 594 595 ConstrainSize (tmp_win, &dragWidth, &dragHeight); 596 AddingX = dragx - tmp_win->frame_bw; 597 AddingY = dragy - tmp_win->frame_bw; 598 AddingW = dragWidth + (2 * tmp_win->frame_bw); 599 AddingH = dragHeight + (2 * tmp_win->frame_bw); 600} 601 602/** 603 * adjust the given width and height to account for the constraints imposed 604 * by size hints. 605 * 606 * The general algorithm, especially the aspect ratio stuff, is 607 * borrowed from uwm's CheckConsistency routine. 608 */ 609void 610ConstrainSize (TwmWindow *tmp_win, int *widthp, int *heightp) 611{ 612#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) 613#define _min(a,b) (((a) < (b)) ? (a) : (b)) 614 615 int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta; 616 int baseWidth, baseHeight; 617 int dwidth = *widthp, dheight = *heightp; 618 619 620 dheight -= tmp_win->title_height; 621 622 if (tmp_win->hints.flags & PMinSize) { 623 minWidth = tmp_win->hints.min_width; 624 minHeight = tmp_win->hints.min_height; 625 } else if (tmp_win->hints.flags & PBaseSize) { 626 minWidth = tmp_win->hints.base_width; 627 minHeight = tmp_win->hints.base_height; 628 } else 629 minWidth = minHeight = 1; 630 631 if (tmp_win->hints.flags & PBaseSize) { 632 baseWidth = tmp_win->hints.base_width; 633 baseHeight = tmp_win->hints.base_height; 634 } else if (tmp_win->hints.flags & PMinSize) { 635 baseWidth = tmp_win->hints.min_width; 636 baseHeight = tmp_win->hints.min_height; 637 } else 638 baseWidth = baseHeight = 0; 639 640 641 if (tmp_win->hints.flags & PMaxSize) { 642 maxWidth = _min (Scr->MaxWindowWidth, tmp_win->hints.max_width); 643 maxHeight = _min (Scr->MaxWindowHeight, tmp_win->hints.max_height); 644 } else { 645 maxWidth = Scr->MaxWindowWidth; 646 maxHeight = Scr->MaxWindowHeight; 647 } 648 649 if (tmp_win->hints.flags & PResizeInc) { 650 xinc = tmp_win->hints.width_inc; 651 yinc = tmp_win->hints.height_inc; 652 } else 653 xinc = yinc = 1; 654 655 /* 656 * First, clamp to min and max values 657 */ 658 if (dwidth < minWidth) dwidth = minWidth; 659 if (dheight < minHeight) dheight = minHeight; 660 661 if (dwidth > maxWidth) dwidth = maxWidth; 662 if (dheight > maxHeight) dheight = maxHeight; 663 664 665 /* 666 * Second, fit to base + N * inc 667 */ 668 dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth; 669 dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight; 670 671 672 /* 673 * Third, adjust for aspect ratio 674 */ 675#define maxAspectX tmp_win->hints.max_aspect.x 676#define maxAspectY tmp_win->hints.max_aspect.y 677#define minAspectX tmp_win->hints.min_aspect.x 678#define minAspectY tmp_win->hints.min_aspect.y 679 /* 680 * The math looks like this: 681 * 682 * minAspectX dwidth maxAspectX 683 * ---------- <= ------- <= ---------- 684 * minAspectY dheight maxAspectY 685 * 686 * If that is multiplied out, then the width and height are 687 * invalid in the following situations: 688 * 689 * minAspectX * dheight > minAspectY * dwidth 690 * maxAspectX * dheight < maxAspectY * dwidth 691 * 692 */ 693 694 if (tmp_win->hints.flags & PAspect) 695 { 696 if (minAspectX * dheight > minAspectY * dwidth) 697 { 698 delta = makemult(minAspectX * dheight / minAspectY - dwidth, 699 xinc); 700 if (dwidth + delta <= maxWidth) dwidth += delta; 701 else 702 { 703 delta = makemult(dheight - dwidth*minAspectY/minAspectX, 704 yinc); 705 if (dheight - delta >= minHeight) dheight -= delta; 706 } 707 } 708 709 if (maxAspectX * dheight < maxAspectY * dwidth) 710 { 711 delta = makemult(dwidth * maxAspectY / maxAspectX - dheight, 712 yinc); 713 if (dheight + delta <= maxHeight) dheight += delta; 714 else 715 { 716 delta = makemult(dwidth - maxAspectX*dheight/maxAspectY, 717 xinc); 718 if (dwidth - delta >= minWidth) dwidth -= delta; 719 } 720 } 721 } 722 723 724 /* 725 * Fourth, account for border width and title height 726 */ 727 *widthp = dwidth; 728 *heightp = dheight + tmp_win->title_height; 729} 730 731 732/** 733 * set window sizes, this was called from either AddWindow, EndResize, or 734 * HandleConfigureNotify. 735 * 736 * Special Considerations: 737 * This routine will check to make sure the window is not completely off the 738 * display, if it is, it'll bring some of it back on. 739 * 740 * The tmp_win->frame_XXX variables should NOT be updated with the values of 741 * x,y,w,h prior to calling this routine, since the new values are compared 742 * against the old to see whether a synthetic ConfigureNotify event should be 743 * sent. (It should be sent if the window was moved but not resized.) 744 * 745 * \param tmp_win the TwmWindow pointer 746 * \param x the x coordinate of the upper-left outer corner of the frame 747 * \param y the y coordinate of the upper-left outer corner of the frame 748 * \param w the width of the frame window w/o border 749 * \param h the height of the frame window w/o border 750 * \param bw the border width of the frame window or -1 not to change 751 */ 752void SetupWindow (TwmWindow *tmp_win, int x, int y, int w, int h, int bw) 753{ 754 SetupFrame (tmp_win, x, y, w, h, bw, False); 755} 756 757/** 758 * \param sendEvent whether or not to force a send 759 */ 760void SetupFrame (TwmWindow *tmp_win, int x, int y, int w, int h, int bw, Bool sendEvent) 761{ 762 XEvent client_event; 763 XWindowChanges frame_wc, xwc; 764 unsigned long frame_mask, xwcm; 765 int title_width, title_height; 766 int reShape; 767 768#ifdef DEBUG 769 fprintf (stderr, "SetupWindow: x=%d, y=%d, w=%d, h=%d, bw=%d\n", 770 x, y, w, h, bw); 771#endif 772 773 if (x >= Scr->MyDisplayWidth) 774 x = Scr->MyDisplayWidth - 16; /* one "average" cursor width */ 775 if (y >= Scr->MyDisplayHeight) 776 y = Scr->MyDisplayHeight - 16; /* one "average" cursor width */ 777 if (bw < 0) 778 bw = tmp_win->frame_bw; /* -1 means current frame width */ 779 780 if (tmp_win->iconmgr) { 781 tmp_win->iconmgrp->width = w; 782 h = tmp_win->iconmgrp->height + tmp_win->title_height; 783 } 784 785 /* 786 * According to the July 27, 1988 ICCCM draft, we should send a 787 * "synthetic" ConfigureNotify event to the client if the window 788 * was moved but not resized. 789 */ 790 if (((x != tmp_win->frame_x || y != tmp_win->frame_y) && 791 (w == tmp_win->frame_width && h == tmp_win->frame_height)) || 792 (bw != tmp_win->frame_bw)) 793 sendEvent = TRUE; 794 795 xwcm = CWWidth; 796 title_width = xwc.width = w; 797 title_height = Scr->TitleHeight + bw; 798 799 ComputeWindowTitleOffsets (tmp_win, xwc.width, True); 800 801 reShape = (tmp_win->wShaped ? TRUE : FALSE); 802 if (tmp_win->squeeze_info) /* check for title shaping */ 803 { 804 title_width = tmp_win->rightx + Scr->TBInfo.rightoff; 805 if (title_width < xwc.width) 806 { 807 xwc.width = title_width; 808 if (tmp_win->frame_height != h || 809 tmp_win->frame_width != w || 810 tmp_win->frame_bw != bw || 811 title_width != tmp_win->title_width) 812 reShape = TRUE; 813 } 814 else 815 { 816 if (!tmp_win->wShaped) reShape = TRUE; 817 title_width = xwc.width; 818 } 819 } 820 821 tmp_win->title_width = title_width; 822 if (tmp_win->title_height) tmp_win->title_height = title_height; 823 824 if (tmp_win->title_w) { 825 if (bw != tmp_win->frame_bw) { 826 xwc.border_width = bw; 827 tmp_win->title_x = xwc.x = -bw; 828 tmp_win->title_y = xwc.y = -bw; 829 xwcm |= (CWX | CWY | CWBorderWidth); 830 } 831 832 XConfigureWindow(dpy, tmp_win->title_w, xwcm, &xwc); 833 } 834 835 if (tmp_win->attr.width != w) 836 tmp_win->widthEverChangedByUser = True; 837 838 if (tmp_win->attr.height != (h - tmp_win->title_height)) 839 tmp_win->heightEverChangedByUser = True; 840 841 tmp_win->attr.width = w; 842 tmp_win->attr.height = h - tmp_win->title_height; 843 844 XMoveResizeWindow (dpy, tmp_win->w, 0, tmp_win->title_height, 845 w, h - tmp_win->title_height); 846 847 /* 848 * fix up frame and assign size/location values in tmp_win 849 */ 850 frame_mask = 0; 851 if (bw != tmp_win->frame_bw) { 852 frame_wc.border_width = tmp_win->frame_bw = bw; 853 frame_mask |= CWBorderWidth; 854 } 855 frame_wc.x = tmp_win->frame_x = x; 856 frame_wc.y = tmp_win->frame_y = y; 857 frame_wc.width = tmp_win->frame_width = w; 858 frame_wc.height = tmp_win->frame_height = h; 859 frame_mask |= (CWX | CWY | CWWidth | CWHeight); 860 XConfigureWindow (dpy, tmp_win->frame, frame_mask, &frame_wc); 861 862 /* 863 * fix up highlight window 864 */ 865 if (tmp_win->title_height && tmp_win->hilite_w) 866 { 867 xwc.width = (tmp_win->rightx - tmp_win->highlightx); 868 if (Scr->TBInfo.nright > 0) xwc.width -= Scr->TitlePadding; 869 if (xwc.width <= 0) { 870 xwc.x = Scr->MyDisplayWidth; /* move offscreen */ 871 xwc.width = 1; 872 } else { 873 xwc.x = tmp_win->highlightx; 874 } 875 876 xwcm = CWX | CWWidth; 877 XConfigureWindow(dpy, tmp_win->hilite_w, xwcm, &xwc); 878 } 879 880 if (HasShape && reShape) { 881 SetFrameShape (tmp_win); 882 } 883 884 if (sendEvent) 885 { 886 client_event.type = ConfigureNotify; 887 client_event.xconfigure.display = dpy; 888 client_event.xconfigure.event = tmp_win->w; 889 client_event.xconfigure.window = tmp_win->w; 890 client_event.xconfigure.x = (x + tmp_win->frame_bw - tmp_win->old_bw); 891 client_event.xconfigure.y = (y + tmp_win->frame_bw + 892 tmp_win->title_height - tmp_win->old_bw); 893 client_event.xconfigure.width = tmp_win->frame_width; 894 client_event.xconfigure.height = tmp_win->frame_height - 895 tmp_win->title_height; 896 client_event.xconfigure.border_width = tmp_win->old_bw; 897 /* Real ConfigureNotify events say we're above title window, so ... */ 898 /* what if we don't have a title ????? */ 899 client_event.xconfigure.above = tmp_win->frame; 900 client_event.xconfigure.override_redirect = False; 901 XSendEvent(dpy, tmp_win->w, False, StructureNotifyMask, &client_event); 902 } 903} 904 905 906/** 907 * zooms window to full height of screen or to full height and width of screen. 908 * (Toggles so that it can undo the zoom - even when switching between fullzoom 909 * and vertical zoom.) 910 * 911 * \param tmp_win the TwmWindow pointer 912 */ 913void 914fullzoom(TwmWindow *tmp_win, int flag) 915{ 916 Window junkRoot; 917 unsigned int junkbw, junkDepth; 918 int basex, basey; 919 int frame_bw_times_2; 920 921 XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot, 922 &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&dragHeight, &junkbw, 923 &junkDepth); 924 925 basex = 0; 926 basey = 0; 927 928 if (tmp_win->zoomed == flag) 929 { 930 dragHeight = tmp_win->save_frame_height; 931 dragWidth = tmp_win->save_frame_width; 932 dragx = tmp_win->save_frame_x; 933 dragy = tmp_win->save_frame_y; 934 tmp_win->zoomed = ZOOM_NONE; 935 } 936 else 937 { 938 if (tmp_win->zoomed == ZOOM_NONE) 939 { 940 tmp_win->save_frame_x = dragx; 941 tmp_win->save_frame_y = dragy; 942 tmp_win->save_frame_width = dragWidth; 943 tmp_win->save_frame_height = dragHeight; 944 tmp_win->zoomed = flag; 945 } 946 else 947 tmp_win->zoomed = flag; 948 949 950 frame_bw_times_2 = 2*tmp_win->frame_bw; 951 952 switch (flag) 953 { 954 case ZOOM_NONE: 955 break; 956 case F_ZOOM: 957 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2; 958 dragy=basey; 959 break; 960 case F_HORIZOOM: 961 dragx = basex; 962 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2; 963 break; 964 case F_FULLZOOM: 965 dragx = basex; 966 dragy = basey; 967 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2; 968 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2; 969 break; 970 case F_LEFTZOOM: 971 dragx = basex; 972 dragy = basey; 973 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2; 974 dragWidth = Scr->MyDisplayWidth/2 - frame_bw_times_2; 975 break; 976 case F_RIGHTZOOM: 977 dragx = basex + Scr->MyDisplayWidth/2; 978 dragy = basey; 979 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2; 980 dragWidth = Scr->MyDisplayWidth/2 - frame_bw_times_2; 981 break; 982 case F_TOPZOOM: 983 dragx = basex; 984 dragy = basey; 985 dragHeight = Scr->MyDisplayHeight/2 - frame_bw_times_2; 986 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2; 987 break; 988 case F_BOTTOMZOOM: 989 dragx = basex; 990 dragy = basey + Scr->MyDisplayHeight/2; 991 dragHeight = Scr->MyDisplayHeight/2 - frame_bw_times_2; 992 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2; 993 break; 994 } 995 } 996 997 if (!Scr->NoRaiseResize) 998 XRaiseWindow(dpy, tmp_win->frame); 999 1000 ConstrainSize(tmp_win, &dragWidth, &dragHeight); 1001 1002 SetupWindow (tmp_win, dragx , dragy , dragWidth, dragHeight, -1); 1003 XUngrabPointer (dpy, CurrentTime); 1004 XUngrabServer (dpy); 1005} 1006 1007void 1008SetFrameShape (TwmWindow *tmp) 1009{ 1010 /* 1011 * see if the titlebar needs to move 1012 */ 1013 if (tmp->title_w) { 1014 int oldx = tmp->title_x, oldy = tmp->title_y; 1015 ComputeTitleLocation (tmp); 1016 if (oldx != tmp->title_x || oldy != tmp->title_y) 1017 XMoveWindow (dpy, tmp->title_w, tmp->title_x, tmp->title_y); 1018 } 1019 1020 /* 1021 * The frame consists of the shape of the contents window offset by 1022 * title_height or'ed with the shape of title_w (which is always 1023 * rectangular). 1024 */ 1025 if (tmp->wShaped) { 1026 /* 1027 * need to do general case 1028 */ 1029 XShapeCombineShape (dpy, tmp->frame, ShapeBounding, 1030 0, tmp->title_height, tmp->w, 1031 ShapeBounding, ShapeSet); 1032 if (tmp->title_w) { 1033 XShapeCombineShape (dpy, tmp->frame, ShapeBounding, 1034 tmp->title_x + tmp->frame_bw, 1035 tmp->title_y + tmp->frame_bw, 1036 tmp->title_w, ShapeBounding, 1037 ShapeUnion); 1038 } 1039 } else { 1040 /* 1041 * can optimize rectangular contents window 1042 */ 1043 if (tmp->squeeze_info) { 1044 XRectangle newBounding[2]; 1045 XRectangle newClip[2]; 1046 int fbw2 = 2 * tmp->frame_bw; 1047 1048 /* 1049 * Build the border clipping rectangles; one around title, one 1050 * around window. The title_[xy] field already have had frame_bw 1051 * subtracted off them so that they line up properly in the frame. 1052 * 1053 * The frame_width and frame_height do *not* include borders. 1054 */ 1055 /* border */ 1056 newBounding[0].x = tmp->title_x; 1057 newBounding[0].y = tmp->title_y; 1058 newBounding[0].width = tmp->title_width + fbw2; 1059 newBounding[0].height = tmp->title_height; 1060 newBounding[1].x = -tmp->frame_bw; 1061 newBounding[1].y = Scr->TitleHeight; 1062 newBounding[1].width = tmp->attr.width + fbw2; 1063 newBounding[1].height = tmp->attr.height + fbw2; 1064 XShapeCombineRectangles (dpy, tmp->frame, ShapeBounding, 0, 0, 1065 newBounding, 2, ShapeSet, YXBanded); 1066 /* insides */ 1067 newClip[0].x = tmp->title_x + tmp->frame_bw; 1068 newClip[0].y = 0; 1069 newClip[0].width = tmp->title_width; 1070 newClip[0].height = Scr->TitleHeight; 1071 newClip[1].x = 0; 1072 newClip[1].y = tmp->title_height; 1073 newClip[1].width = tmp->attr.width; 1074 newClip[1].height = tmp->attr.height; 1075 XShapeCombineRectangles (dpy, tmp->frame, ShapeClip, 0, 0, 1076 newClip, 2, ShapeSet, YXBanded); 1077 } else { 1078 (void) XShapeCombineMask (dpy, tmp->frame, ShapeBounding, 0, 0, 1079 None, ShapeSet); 1080 (void) XShapeCombineMask (dpy, tmp->frame, ShapeClip, 0, 0, 1081 None, ShapeSet); 1082 } 1083 } 1084} 1085 1086/* 1087 * Squeezed Title: 1088 * 1089 * tmp->title_x 1090 * 0 | 1091 * tmp->title_y ........+--------------+......... -+,- tmp->frame_bw 1092 * 0 : ......| +----------+ |....... : -++ 1093 * : : | | | | : : ||-Scr->TitleHeight 1094 * : : | | | | : : || 1095 * +-------+ +----------+ +--------+ -+|-tmp->title_height 1096 * | +---------------------------+ | --+ 1097 * | | | | 1098 * | | | | 1099 * | | | | 1100 * | | | | 1101 * | | | | 1102 * | +---------------------------+ | 1103 * +-------------------------------+ 1104 * 1105 * 1106 * Unsqueezed Title: 1107 * 1108 * tmp->title_x 1109 * | 0 1110 * tmp->title_y +-------------------------------+ -+,tmp->frame_bw 1111 * 0 | +---------------------------+ | -+' 1112 * | | | | |-Scr->TitleHeight 1113 * | | | | | 1114 * + +---------------------------+ + -+ 1115 * |-+---------------------------+-| 1116 * | | | | 1117 * | | | | 1118 * | | | | 1119 * | | | | 1120 * | | | | 1121 * | +---------------------------+ | 1122 * +-------------------------------+ 1123 * 1124 * 1125 * 1126 * Dimensions and Positions: 1127 * 1128 * frame orgin (0, 0) 1129 * frame upper left border (-tmp->frame_bw, -tmp->frame_bw) 1130 * frame size w/o border tmp->frame_width , tmp->frame_height 1131 * frame/title border width tmp->frame_bw 1132 * extra title height w/o bdr tmp->title_height = TitleHeight + frame_bw 1133 * title window height Scr->TitleHeight 1134 * title origin w/o border (tmp->title_x, tmp->title_y) 1135 * client origin (0, Scr->TitleHeight + tmp->frame_bw) 1136 * client size tmp->attr.width , tmp->attr.height 1137 * 1138 * When shaping, need to remember that the width and height of rectangles 1139 * are really deltax and deltay to lower right handle corner, so they need 1140 * to have -1 subtracted from would normally be the actual extents. 1141 */ 1142