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