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