jcs ratpoison hax
at jcs 1100 lines 27 kB view raw
1/* Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts <sabetts@vcn.bc.ca> 2 * 3 * This file is part of ratpoison. 4 * 5 * ratpoison is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2, or (at your option) 8 * any later version. 9 * 10 * ratpoison is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this software; see the file COPYING. If not, write to 17 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 * Boston, MA 02111-1307 USA 19 * 20 * 21 * Functions for handling window splitting and tiling. 22 */ 23 24#include <unistd.h> 25#include <string.h> 26 27#include "ratpoison.h" 28 29#define VERTICALLY 0 30#define HORIZONTALLY 1 31 32static void 33update_last_access (rp_frame *frame) 34{ 35 static int counter = 0; 36 37 frame->last_access = counter; 38 counter++; 39} 40 41rp_frame * 42current_frame (void) 43{ 44 rp_screen *s = rp_current_screen; 45 return screen_get_frame (s, s->current_frame); 46} 47 48void 49cleanup_frame (rp_frame *frame) 50{ 51 rp_window *win; 52 rp_screen *screen; 53 screen = frames_screen(frame); 54 55 win = find_window_other (screen); 56 if (win == NULL) 57 { 58 set_frames_window (frame, NULL); 59 return; 60 } 61 62 set_frames_window (frame, win); 63 64 maximize (win); 65 unhide_window (win); 66 67 68 if (!window_is_transient (win)) 69 hide_others (win); 70} 71 72rp_window * 73set_frames_window (rp_frame *frame, rp_window *win) 74{ 75 int last_win; 76 77 last_win = frame->win_number; 78 if (win) 79 { 80 frame->win_number = win->number; 81 win->frame_number = frame->number; 82 if (win->sticky_frame >= 0) 83 win->sticky_frame = frame->number; 84 85 /* We need to make sure that win and frame are on the same screen, 86 * since with Xrandr, windows can move from one screen to another. 87 */ 88 win->scr = frames_screen(frame); 89 } 90 else 91 { 92 frame->win_number = EMPTY; 93 } 94 95 return find_window_number (last_win); 96} 97 98rp_screen * 99frames_screen (rp_frame *frame) 100{ 101 rp_frame *cur_frame; 102 rp_screen *cur_screen; 103 104 list_for_each_entry (cur_screen, &rp_screens, node) 105 { 106 list_for_each_entry (cur_frame, &cur_screen->frames, node) 107 { 108 if (frame == cur_frame) 109 return cur_screen; 110 } 111 } 112 113 /* This SHOULD be impossible to get to. FIXME: It'll crash higher up if we 114 return NULL. */ 115 return NULL; 116} 117 118void 119maximize_all_windows_in_frame (rp_frame *frame) 120{ 121 rp_window *win; 122 123 list_for_each_entry (win, &rp_mapped_window, node) 124 { 125 if (win->frame_number == frame->number) 126 { 127 maximize (win); 128 } 129 } 130} 131 132/* Make the frame occupy the entire screen */ 133static void 134maximize_frame (rp_frame *frame) 135{ 136 rp_screen *s = frames_screen (frame); 137 138 frame->x = defaults.padding_left; 139 frame->y = defaults.padding_top; 140 141 frame->width = screen_width (s); 142 frame->height = screen_height (s); 143} 144 145/* Create a full screen frame */ 146static void 147create_initial_frame (rp_screen *screen) 148{ 149 rp_frame *frame; 150 151 frame = frame_new (screen); 152 screen->current_frame = frame->number; 153 list_add_tail (&frame->node, &screen->frames); 154 155 update_last_access (frame); 156 157 maximize_frame (frame); 158 set_frames_window (frame, NULL); 159} 160 161void 162init_frame_lists (void) 163{ 164 rp_screen *cur; 165 166 list_for_each_entry (cur, &rp_screens, node) 167 { 168 init_frame_list (cur); 169 } 170} 171 172void 173init_frame_list (rp_screen *screen) 174{ 175 INIT_LIST_HEAD (&screen->frames); 176 177 create_initial_frame(screen); 178} 179 180rp_frame * 181find_last_frame (void) 182{ 183 rp_frame *cur_frame, *last = NULL; 184 rp_screen *cur_screen; 185 int last_access = -1; 186 187 list_for_each_entry (cur_screen, &rp_screens, node) 188 { 189 list_for_each_entry (cur_frame, &cur_screen->frames, node) 190 { 191 if (cur_frame->number != rp_current_screen->current_frame && 192 cur_frame->last_access > last_access) 193 { 194 last_access = cur_frame->last_access; 195 last = cur_frame; 196 } 197 } 198 } 199 200 return last; 201} 202 203/* Return the frame that contains the window. */ 204rp_frame * 205find_windows_frame (rp_window *win) 206{ 207 rp_screen *s; 208 rp_frame *cur; 209 210 s = win->scr; 211 212 list_for_each_entry (cur, &s->frames, node) 213 { 214 if (cur->win_number == win->number) return cur; 215 } 216 217 return NULL; 218} 219 220int 221num_frames (rp_screen *s) 222{ 223 return list_size (&s->frames); 224} 225 226rp_frame * 227find_frame_next (rp_frame *frame) 228{ 229 if (frame == NULL) return NULL; 230 return list_next_entry (frame, &frames_screen (frame)->frames, node); 231} 232 233rp_frame * 234find_frame_prev (rp_frame *frame) 235{ 236 if (frame == NULL) return NULL; 237 return list_prev_entry (frame, &frames_screen (frame)->frames, node); 238} 239 240rp_window * 241current_window (void) 242{ 243 if (current_frame()) 244 return find_window_number (current_frame()->win_number); 245 else 246 return NULL; 247} 248 249static int 250window_fits_in_frame (rp_window *win, rp_frame *frame) 251{ 252 /* If the window has minimum size hints, make sure they are smaller 253 than the frame. */ 254 if (win->hints->flags & PMinSize) 255 { 256 if (win->hints->min_width > frame->width 257 || 258 win->hints->min_height > frame->height) 259 { 260 return 0; 261 } 262 } 263 264 return 1; 265} 266 267/* Search the list of mapped windows for a window that will fit in the 268 specified frame. */ 269rp_window * 270find_window_for_frame (rp_frame *frame) 271{ 272 rp_screen *s = frames_screen (frame); 273 int last_access = 0; 274 rp_window_elem *most_recent = NULL; 275 rp_window_elem *cur; 276 277 list_for_each_entry (cur, &rp_current_group->mapped_windows, node) 278 { 279 if ((cur->win->scr == s || rp_have_xrandr) 280 && cur->win != current_window() 281 && !find_windows_frame (cur->win) 282 && cur->win->last_access >= last_access 283 && window_fits_in_frame (cur->win, frame) 284 && cur->win->frame_number == EMPTY 285 && (cur->win->sticky_frame == EMPTY || cur->win->sticky_frame == frame->number)) 286 { 287 most_recent = cur; 288 last_access = cur->win->last_access; 289 } 290 } 291 292 if (most_recent) 293 return most_recent->win; 294 295 return NULL; 296} 297 298/* Splits the frame in 2. if way is 0 then split vertically otherwise 299 split it horizontally. */ 300static void 301split_frame (rp_frame *frame, int way, int pixels) 302{ 303 rp_screen *s; 304 rp_window *win; 305 rp_frame *new_frame; 306 307 s = frames_screen (frame); 308 309 /* Make our new frame. */ 310 new_frame = frame_new (s); 311 312 /* Add the frame to the frameset. */ 313 list_add (&new_frame->node, &current_frame()->node); 314 315 set_frames_window (new_frame, NULL); 316 317 if (way == HORIZONTALLY) 318 { 319 new_frame->x = frame->x; 320 new_frame->y = frame->y + pixels; 321 new_frame->width = frame->width; 322 new_frame->height = frame->height - pixels; 323 324 frame->height = pixels; 325 } 326 else 327 { 328 new_frame->x = frame->x + pixels; 329 new_frame->y = frame->y; 330 new_frame->width = frame->width - pixels; 331 new_frame->height = frame->height; 332 333 frame->width = pixels; 334 } 335 336 win = find_window_for_frame (new_frame); 337 if (win) 338 { 339 PRINT_DEBUG (("Found a window for the frame!\n")); 340 341 set_frames_window (new_frame, win); 342 343 maximize (win); 344 unhide_window (win); 345 } 346 else 347 { 348 PRINT_DEBUG (("No window fits the frame.\n")); 349 350 set_frames_window (new_frame, NULL); 351 } 352 353 /* resize the existing frame */ 354 if (frame->win_number != EMPTY) 355 { 356 maximize_all_windows_in_frame (frame); 357 XRaiseWindow (dpy, find_window_number (frame->win_number)->w); 358 } 359 360 update_bar (s); 361 show_frame_indicator(0); 362} 363 364/* Splits the window vertically leaving the original with 'pixels' 365 pixels . */ 366void 367v_split_frame (rp_frame *frame, int pixels) 368{ 369 split_frame (frame, VERTICALLY, pixels); 370} 371 372/* Splits the frame horizontally leaving the original with 'pixels' 373 pixels . */ 374void 375h_split_frame (rp_frame *frame, int pixels) 376{ 377 split_frame (frame, HORIZONTALLY, pixels); 378} 379 380void 381remove_all_splits (void) 382{ 383 struct list_head *tmp, *iter; 384 rp_screen *s = rp_current_screen; 385 rp_frame *frame; 386 rp_window *win; 387 388 /* Hide all the windows not in the current frame. */ 389 list_for_each_entry (win, &rp_mapped_window, node) 390 { 391 if (win->frame_number != s->current_frame && win->scr == s) 392 hide_window (win); 393 } 394 395 /* Delete all the frames except the current one. */ 396 list_for_each_safe_entry (frame, iter, tmp, &s->frames, node) 397 { 398 if (frame->number != s->current_frame) 399 { 400 list_del (&frame->node); 401 frame_free (s, frame); 402 } 403 } 404 405 /* Maximize the frame and the windows in the frame. */ 406 maximize_frame (current_frame()); 407 maximize_all_windows_in_frame (current_frame()); 408} 409 410/* Shrink the size of the frame to fit it's current window. */ 411void 412resize_shrink_to_window (rp_frame *frame) 413{ 414 rp_window *win; 415 416 if (frame->win_number == EMPTY) return; 417 418 win = find_window_number (frame->win_number); 419 420 resize_frame_horizontally (frame, win->width + win->border*2 + defaults.gap*2 - frame->width); 421 resize_frame_vertically (frame, win->height + win->border*2 + defaults.gap*2 - frame->height); 422} 423 424/* resize_frame is a generic frame resizer that can resize vertically, 425 horizontally, to the right, to the left, etc. It all depends on the 426 functions passed to it. Returns -1 if the resize failed, 0 for 427 success. */ 428static int 429resize_frame (rp_frame *frame, rp_frame *pusher, int diff, 430 int (*c1)(rp_frame *), int (c2)(rp_frame *), 431 int (*c3)(rp_frame *), int (c4)(rp_frame *), 432 void (*resize1)(rp_frame *, int), 433 void (*resize2)(rp_frame *, int), 434 int (*resize3)(rp_frame *, rp_frame *, int)) 435{ 436 rp_screen *s = frames_screen (frame); 437 rp_frame *cur; 438 439 /* Loop through the frames and determine which ones are affected by 440 resizing frame. */ 441 list_for_each_entry (cur, &s->frames, node) 442 { 443 if (cur == frame || cur == pusher) continue; 444 /* If cur is touching frame along the axis that is being 445 moved then this frame is affected by the resize. */ 446 if ((*c1)(cur) == (*c3)(frame)) 447 { 448 /* If the frame can't get any smaller, then fail. */ 449 if (diff > 0 450 && abs ((*c3)(cur) - (*c1)(cur)) - diff <= defaults.gap*2 + defaults.window_border_width*2) 451 return -1; 452 /* Test for this circumstance: 453 --+ 454 | |+-+ 455 |f||c| 456 | |+-+ 457 --+ 458 459 In this case, resizing cur will not affect any other 460 frames, so just do the resize. 461 */ 462 if (((*c2)(cur) >= (*c2)(frame)) 463 && (*c4)(cur) <= (*c4)(frame)) 464 { 465 (*resize2)(cur, -diff); 466 maximize_all_windows_in_frame (cur); 467 } 468 /* Otherwise, cur's corners are either strictly outside 469 frame's corners, or one of them is inside and the other 470 isn't. In either of these cases, resizing cur will affect 471 other adjacent frames, so find them and resize them first 472 (recursive step) and then resize cur. */ 473 else if (((*c2)(cur) < (*c2)(frame) 474 && (*c4)(cur) > (*c4)(frame)) 475 || ((*c2)(cur) >= (*c2)(frame) 476 && (*c2)(cur) < (*c4)(frame)) 477 || ((*c4)(cur) > (*c2)(frame) 478 && (*c4)(cur) <= (*c4)(frame))) 479 { 480 /* Attempt to resize cur. */ 481 if (resize3 (cur, frame, -diff) == -1) 482 return -1; 483 } 484 } 485 } 486 487 /* Finally, resize the frame and the windows inside. */ 488 (*resize1) (frame, diff); 489 maximize_all_windows_in_frame (frame); 490 491 return 0; 492} 493 494static int resize_frame_bottom (rp_frame *frame, rp_frame *pusher, int diff); 495static int resize_frame_top (rp_frame *frame, rp_frame *pusher, int diff); 496static int resize_frame_left (rp_frame *frame, rp_frame *pusher, int diff); 497static int resize_frame_right (rp_frame *frame, rp_frame *pusher, int diff); 498 499/* Resize frame by moving it's right side. */ 500static int 501resize_frame_right (rp_frame *frame, rp_frame *pusher, int diff) 502{ 503 return resize_frame (frame, pusher, diff, 504 frame_left, frame_top, frame_right, frame_bottom, 505 frame_resize_right, frame_resize_left, resize_frame_left); 506} 507 508/* Resize frame by moving it's left side. */ 509static int 510resize_frame_left (rp_frame *frame, rp_frame *pusher, int diff) 511{ 512 return resize_frame (frame, pusher, diff, 513 frame_right, frame_top, frame_left, frame_bottom, 514 frame_resize_left, frame_resize_right, resize_frame_right); 515} 516 517/* Resize frame by moving it's top side. */ 518static int 519resize_frame_top (rp_frame *frame, rp_frame *pusher, int diff) 520{ 521 return resize_frame (frame, pusher, diff, 522 frame_bottom, frame_left, frame_top, frame_right, 523 frame_resize_up, frame_resize_down, resize_frame_bottom); 524} 525 526/* Resize frame by moving it's bottom side. */ 527static int 528resize_frame_bottom (rp_frame *frame, rp_frame *pusher, int diff) 529{ 530 return resize_frame (frame, pusher, diff, 531 frame_top, frame_left, frame_bottom, frame_right, 532 frame_resize_down, frame_resize_up, resize_frame_top); 533} 534 535/* Resize frame diff pixels by expanding it to the right. If the frame 536 is against the right side of the screen, expand it to the left. */ 537void 538resize_frame_horizontally (rp_frame *frame, int diff) 539{ 540 int (*resize_fn)(rp_frame *, rp_frame*, int); 541 struct list_head *l; 542 rp_screen *s = frames_screen (frame); 543 544 if (num_frames (s) < 2 || diff == 0) 545 return; 546 547 if (frame_width (frame) + diff <= defaults.gap*2 + defaults.window_border_width*2) 548 return; 549 550 /* Find out which resize function to use. */ 551 if (frame_right (frame) < screen_right (s)) 552 { 553 resize_fn = resize_frame_right; 554 } 555 else if (frame_left (frame) > screen_left (s)) 556 { 557 resize_fn = resize_frame_left; 558 } 559 else 560 { 561 return; 562 } 563 564 /* Copy the frameset. If the resize fails, then we restore the 565 original one. */ 566 l = screen_copy_frameset (s); 567 568 if ((*resize_fn) (frame, NULL, diff) == -1) 569 { 570 screen_restore_frameset (s, l); 571 } 572 else 573 { 574 frameset_free (l); 575 } 576 577 /* It's our responsibility to free this. */ 578 free (l); 579} 580 581/* Resize frame diff pixels by expanding it down. If the frame is 582 against the bottom of the screen, expand it up. */ 583void 584resize_frame_vertically (rp_frame *frame, int diff) 585{ 586 int (*resize_fn)(rp_frame *, rp_frame*, int); 587 struct list_head *l; 588 rp_screen *s = frames_screen (frame); 589 590 if (num_frames (s) < 2 || diff == 0) 591 return; 592 593 if (frame_height (frame) + diff <= defaults.gap*2 + defaults.window_border_width*2) 594 return; 595 596 /* Find out which resize function to use. */ 597 if (frame_bottom (frame) < screen_bottom (s)) 598 { 599 resize_fn = resize_frame_bottom; 600 } 601 else if (frame_top (frame) > screen_top (s)) 602 { 603 resize_fn = resize_frame_top; 604 } 605 else 606 { 607 return; 608 } 609 610 /* Copy the frameset. If the resize fails, then we restore the 611 original one. */ 612 l = screen_copy_frameset (s); 613 614 if ((*resize_fn) (frame, NULL, diff) == -1) 615 { 616 screen_restore_frameset (s, l); 617 } 618 else 619 { 620 frameset_free (l); 621 } 622 623 /* It's our responsibility to free this. */ 624 free (l); 625} 626 627static int 628frame_is_below (rp_frame *src, rp_frame *frame) 629{ 630 if (frame->y > src->y) return 1; 631 return 0; 632} 633 634static int 635frame_is_above (rp_frame *src, rp_frame *frame) 636{ 637 if (frame->y < src->y) return 1; 638 return 0; 639} 640 641static int 642frame_is_left (rp_frame *src, rp_frame *frame) 643{ 644 if (frame->x < src->x) return 1; 645 return 0; 646} 647 648static int 649frame_is_right (rp_frame *src, rp_frame *frame) 650{ 651 if (frame->x > src->x) return 1; 652 return 0; 653} 654 655static int 656total_frame_area (rp_screen *s) 657{ 658 int area = 0; 659 rp_frame *cur; 660 661 list_for_each_entry (cur, &s->frames, node) 662 { 663 area += cur->width * cur->height; 664 } 665 666 return area; 667} 668 669/* Return 1 if frames f1 and f2 overlap */ 670static int 671frames_overlap (rp_frame *f1, rp_frame *f2) 672{ 673 if (f1->x >= f2->x + f2->width 674 || f1->y >= f2->y + f2->height 675 || f2->x >= f1->x + f1->width 676 || f2->y >= f1->y + f1->height) 677 { 678 return 0; 679 } 680 return 1; 681} 682 683/* Return 1 if w's frame overlaps any other window's frame */ 684static int 685frame_overlaps (rp_frame *frame) 686{ 687 rp_screen *s; 688 rp_frame *cur; 689 690 s = frames_screen (frame); 691 692 list_for_each_entry (cur, &s->frames, node) 693 { 694 if (cur != frame && frames_overlap (cur, frame)) 695 { 696 return 1; 697 } 698 } 699 return 0; 700} 701 702void 703remove_frame (rp_frame *frame) 704{ 705 rp_screen *s; 706 int area; 707 rp_frame *cur; 708 rp_window *win; 709 710 if (frame == NULL) return; 711 712 s = frames_screen (frame); 713 714 area = total_frame_area(s); 715 PRINT_DEBUG (("Total Area: %d\n", area)); 716 717 list_del (&frame->node); 718 win = find_window_number (frame->win_number); 719 hide_window (win); 720 hide_others (win); 721 722 list_for_each_entry (cur, &s->frames, node) 723 { 724 rp_frame tmp_frame; 725 int fits = 0; 726 727/* if (cur->win_number != EMPTY) */ 728/* { */ 729/* PRINT_DEBUG (("Trying frame containing window '%s'\n", window_name (cur->win))); */ 730/* } */ 731/* else */ 732/* { */ 733/* PRINT_DEBUG (("Trying some empty frame\n")); */ 734/* } */ 735 736 /* Backup the frame */ 737 memcpy (&tmp_frame, cur, sizeof (rp_frame)); 738 739 if (frame_is_below (frame, cur) 740 || frame_is_above (frame, cur)) 741 { 742 if (frame_is_below (frame, cur)) 743 cur->y = frame->y; 744 cur->height += frame->height; 745 } 746 747 PRINT_DEBUG (("Attempting vertical Frame y=%d height=%d\n", cur->y, cur->height)); 748 PRINT_DEBUG (("New Total Area: %d\n", total_frame_area(s))); 749 750 /* If the area is bigger than before, the frame takes up too 751 much space. If the current frame and the deleted frame DON'T 752 overlap then the current window took up just the right amount 753 of space but didn't take up the space left behind by the 754 deleted window. If any active frames overlap, it could have 755 taken up the right amount of space, overlaps with the deleted 756 frame but obviously didn't fit. */ 757 if (total_frame_area(s) > area || !frames_overlap (cur, frame) || frame_overlaps (cur)) 758 { 759 PRINT_DEBUG (("Didn't fit vertically\n")); 760 761 /* Restore the current window's frame */ 762 memcpy (cur, &tmp_frame, sizeof (rp_frame)); 763 } 764 else 765 { 766 PRINT_DEBUG (("It fit vertically!!\n")); 767 768 /* update the frame backup */ 769 memcpy (&tmp_frame, cur, sizeof (rp_frame)); 770 fits = 1; 771 } 772 773 if (frame_is_left (frame, cur) 774 || frame_is_right (frame, cur)) 775 { 776 if (frame_is_right (frame, cur)) 777 cur->x = frame->x; 778 cur->width += frame->width; 779 } 780 781 PRINT_DEBUG (("Attempting horizontal Frame x=%d width=%d\n", cur->x, cur->width)); 782 PRINT_DEBUG (("New Total Area: %d\n", total_frame_area(s))); 783 784 /* Same test as the vertical test, above. */ 785 if (total_frame_area(s) > area || !frames_overlap (cur, frame) || frame_overlaps (cur)) 786 { 787 PRINT_DEBUG (("Didn't fit horizontally\n")); 788 789 /* Restore the current window's frame */ 790 memcpy (cur, &tmp_frame, sizeof (rp_frame)); 791 } 792 else 793 { 794 PRINT_DEBUG (("It fit horizontally!!\n")); 795 fits = 1; 796 } 797 798 if (fits) 799 { 800 /* The current frame fits into the new space so keep its 801 new frame parameters and maximize the window to fit 802 the new frame size. */ 803 if (cur->win_number != EMPTY) 804 { 805 rp_window *new = find_window_number (cur->win_number); 806 maximize_all_windows_in_frame (cur); 807 XRaiseWindow (dpy, new->w); 808 } 809 } 810 else 811 { 812 memcpy (cur, &tmp_frame, sizeof (rp_frame)); 813 } 814 } 815 816 frame_free (s, frame); 817} 818 819/* Switch the input focus to another frame, and therefore a different 820 window. */ 821void 822set_active_frame (rp_frame *frame, int force_indicator) 823{ 824 rp_screen *old_s = rp_current_screen; 825 rp_screen *s = frames_screen (frame); 826 int old = rp_current_screen->current_frame; 827 rp_window *win, *old_win; 828 rp_frame *old_frame; 829 830 win = find_window_number (frame->win_number); 831 old_frame = current_frame(); 832 if (old_frame) 833 { 834 old_win = find_window_number (old_frame->win_number); 835 } 836 else 837 { 838 old_win = NULL; 839 } 840 841 /* Make the switch */ 842 give_window_focus (win, old_win); 843 update_last_access (frame); 844 s->current_frame = frame->number; 845 846 /* If frame->win == NULL, then rp_current_screen is not updated. */ 847 rp_current_screen = s; 848 849 update_bar (s); 850 851 /* Possibly show the frame indicator. */ 852 if ((old != s->current_frame && num_frames(s) > 1) 853 || s != old_s) 854 { 855 if (s != old_s) 856 force_indicator = 1; 857 858 show_frame_indicator(force_indicator); 859 860 /* run the frame switch hook. We call it in here because this is 861 when a frame switch ACTUALLY (for sure) happens. */ 862 hook_run (&rp_switch_frame_hook); 863 } 864 865 /* If the frame has no window to give focus to, give the key window 866 focus. */ 867 if(frame->win_number == EMPTY) 868 { 869 set_window_focus (s->key_window); 870 } 871 872 /* Call the switchscreen hook, when appropriate. */ 873 if (s != old_s) 874 hook_run (&rp_switch_screen_hook); 875} 876 877void 878exchange_with_frame (rp_frame *cur, rp_frame *frame) 879{ 880 rp_window *win,*last_win; 881 882 if (frame == NULL || frame == cur) return; 883 884 /* Exchange the windows in the frames */ 885 win = find_window_number (cur->win_number); 886 last_win = set_frames_window (frame, win); 887 set_frames_window (cur, last_win); 888 889 /* Make sure the windows comes up full screen */ 890 if (last_win) 891 maximize (last_win); 892 if (win) 893 { 894 maximize (win); 895 /* Make sure the program bar is always on the top */ 896 update_window_names (win->scr, defaults.window_fmt); 897 } 898 899 /* Make the switch */ 900 update_last_access (frame); 901 902 set_active_frame(frame, 0); 903} 904 905 906void 907blank_frame (rp_frame *frame) 908{ 909 rp_screen *s; 910 rp_window *win; 911 912 if (frame->win_number == EMPTY) return; 913 914 s = frames_screen (frame); 915 916 win = find_window_number (frame->win_number); 917 hide_window (win); 918 hide_others (win); 919 920 set_frames_window (frame, NULL); 921 922 update_bar (s); 923 924 /* Give the key window focus. */ 925 set_window_focus (frames_screen(frame)->key_window); 926} 927 928void 929hide_frame_indicator (void) 930{ 931 rp_screen *cur; 932 933 list_for_each_entry (cur, &rp_screens, node) 934 { 935 XUnmapWindow (dpy, cur->frame_window); 936 } 937} 938 939void 940show_frame_indicator (int force) 941{ 942 if (num_frames (rp_current_screen) > 1 || force) 943 { 944 hide_frame_indicator (); 945 if (defaults.frame_indicator_timeout != -1) 946 { 947 show_frame_message (defaults.frame_fmt); 948 alarm (defaults.frame_indicator_timeout); 949 } 950 } 951} 952 953void 954show_frame_message (char *msg) 955{ 956 rp_screen *s = rp_current_screen; 957 int width, height; 958 rp_frame *frame; 959 rp_window *win; 960 rp_window_elem *elem = NULL; 961 struct sbuf *msgbuf; 962 963 frame = current_frame(); 964 win = current_window (); 965 if (win) 966 { 967 rp_group *g; 968 969 g = groups_find_group_by_window (win); 970 elem = group_find_window (&g->mapped_windows, win); 971 } 972 973 /* A frame doesn't always contain a window. */ 974 msgbuf = sbuf_new (0); 975 if (elem) 976 format_string (msg, elem, msgbuf); 977 else 978 { 979 sbuf_concat (msgbuf, EMPTY_FRAME_MESSAGE); 980 } 981 982 width = defaults.bar_x_padding * 2 983 + rp_text_width (s, msgbuf->data, msgbuf->len); 984 height = (FONT_HEIGHT (s) + defaults.bar_y_padding * 2); 985 986 /* We don't want another frame indicator to be displayed on another 987 * screen at the same time, so we hide it before bringing it back again. 988 */ 989 hide_frame_indicator (); 990 991 XMoveResizeWindow (dpy, s->frame_window, 992 s->left + frame->x + frame->width / 2 - width / 2, 993 s->top + frame->y + frame->height / 2 - height / 2, 994 width, height); 995 996 XMapRaised (dpy, s->frame_window); 997 XClearWindow (dpy, s->frame_window); 998 XSync (dpy, False); 999 1000 rp_draw_string (s, s->frame_window, STYLE_NORMAL, 1001 defaults.bar_x_padding, 1002 defaults.bar_y_padding + FONT_ASCENT(s), 1003 msgbuf->data, msgbuf->len); 1004 1005 sbuf_free (msgbuf); 1006} 1007 1008rp_frame * 1009find_frame_up (rp_frame *frame) 1010{ 1011 rp_screen *s; 1012 rp_frame *cur; 1013 1014 list_for_each_entry (s, &rp_screens, node) 1015 { 1016 list_for_each_entry (cur, &s->frames, node) 1017 { 1018 if (frame_top_abs (frame) == frame_bottom_abs (cur)) 1019 if (frame_right_abs (frame) >= frame_left_abs (cur) && frame_left_abs (frame) <= frame_right_abs (cur)) 1020 return cur; 1021 } 1022 } 1023 1024 return NULL; 1025} 1026 1027rp_frame * 1028find_frame_down (rp_frame *frame) 1029{ 1030 rp_screen *s; 1031 rp_frame *cur; 1032 1033 list_for_each_entry (s, &rp_screens, node) 1034 { 1035 list_for_each_entry (cur, &s->frames, node) 1036 { 1037 if (frame_bottom_abs (frame) == frame_top_abs (cur)) 1038 if (frame_right_abs (frame) >= frame_left_abs (cur) && frame_left_abs (frame) <= frame_right_abs (cur)) 1039 return cur; 1040 } 1041 } 1042 1043 return NULL; 1044} 1045 1046rp_frame * 1047find_frame_left (rp_frame *frame) 1048{ 1049 rp_screen *s; 1050 rp_frame *cur; 1051 1052 list_for_each_entry (s, &rp_screens, node) 1053 { 1054 list_for_each_entry (cur, &s->frames, node) 1055 { 1056 if (frame_left_abs (frame) == frame_right_abs (cur)) 1057 if (frame_bottom_abs (frame) >= frame_top_abs (cur) && frame_top_abs (frame) <= frame_bottom_abs (cur)) 1058 return cur; 1059 } 1060 } 1061 1062 return NULL; 1063} 1064 1065rp_frame * 1066find_frame_right (rp_frame *frame) 1067{ 1068 rp_screen *s; 1069 rp_frame *cur; 1070 1071 list_for_each_entry (s, &rp_screens, node) 1072 { 1073 list_for_each_entry (cur, &s->frames, node) 1074 { 1075 if (frame_right_abs (frame) == frame_left_abs (cur)) 1076 if (frame_bottom_abs (frame) >= frame_top_abs (cur) && frame_top_abs (frame) <= frame_bottom_abs (cur)) 1077 return cur; 1078 } 1079 } 1080 1081 return NULL; 1082} 1083 1084rp_frame * 1085find_frame_number (int num) 1086{ 1087 rp_frame *cur_frame; 1088 rp_screen *cur_screen; 1089 1090 list_for_each_entry (cur_screen, &rp_screens, node) 1091 { 1092 list_for_each_entry (cur_frame, &cur_screen->frames, node) 1093 { 1094 if (cur_frame->number == num) 1095 return cur_frame; 1096 } 1097 } 1098 1099 return NULL; 1100}