00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "boxes.h"
00030 #include "util.h"
00031 #include <X11/Xutil.h>
00032
00033 char*
00034 meta_rectangle_to_string (const MetaRectangle *rect,
00035 char *output)
00036 {
00037
00038
00039
00040
00041 g_snprintf (output, RECT_LENGTH, "%d,%d +%d,%d",
00042 rect->x, rect->y, rect->width, rect->height);
00043
00044 return output;
00045 }
00046
00047 char*
00048 meta_rectangle_region_to_string (GList *region,
00049 const char *separator_string,
00050 char *output)
00051 {
00052
00053
00054
00055
00056
00057 char rect_string[RECT_LENGTH];
00058
00059 GList *tmp = region;
00060 char *cur = output;
00061
00062 if (region == NULL)
00063 g_snprintf (output, 10, "(EMPTY)");
00064
00065 while (tmp)
00066 {
00067 MetaRectangle *rect = tmp->data;
00068 g_snprintf (rect_string, RECT_LENGTH, "[%d,%d +%d,%d]",
00069 rect->x, rect->y, rect->width, rect->height);
00070 cur = g_stpcpy (cur, rect_string);
00071 tmp = tmp->next;
00072 if (tmp)
00073 cur = g_stpcpy (cur, separator_string);
00074 }
00075
00076 return output;
00077 }
00078
00079 char*
00080 meta_rectangle_edge_to_string (const MetaEdge *edge,
00081 char *output)
00082 {
00083
00084
00085
00086
00087
00088
00089
00090 g_snprintf (output, EDGE_LENGTH, "[%d,%d +%d,%d], %2d, %2d",
00091 edge->rect.x, edge->rect.y, edge->rect.width, edge->rect.height,
00092 edge->side_type, edge->edge_type);
00093
00094 return output;
00095 }
00096
00097 char*
00098 meta_rectangle_edge_list_to_string (GList *edge_list,
00099 const char *separator_string,
00100 char *output)
00101 {
00102
00103
00104
00105
00106
00107
00108
00109
00110 char rect_string[EDGE_LENGTH];
00111
00112 char *cur = output;
00113 GList *tmp = edge_list;
00114
00115 if (edge_list == NULL)
00116 g_snprintf (output, 10, "(EMPTY)");
00117
00118 while (tmp)
00119 {
00120 MetaEdge *edge = tmp->data;
00121 MetaRectangle *rect = &edge->rect;
00122 g_snprintf (rect_string, EDGE_LENGTH, "([%d,%d +%d,%d], %2d, %2d)",
00123 rect->x, rect->y, rect->width, rect->height,
00124 edge->side_type, edge->edge_type);
00125 cur = g_stpcpy (cur, rect_string);
00126 tmp = tmp->next;
00127 if (tmp)
00128 cur = g_stpcpy (cur, separator_string);
00129 }
00130
00131 return output;
00132 }
00133
00134 MetaRectangle
00135 meta_rect (int x, int y, int width, int height)
00136 {
00137 MetaRectangle temporary;
00138 temporary.x = x;
00139 temporary.y = y;
00140 temporary.width = width;
00141 temporary.height = height;
00142
00143 return temporary;
00144 }
00145
00146 int
00147 meta_rectangle_area (const MetaRectangle *rect)
00148 {
00149 g_return_val_if_fail (rect != NULL, 0);
00150 return rect->width * rect->height;
00151 }
00152
00153 gboolean
00154 meta_rectangle_intersect (const MetaRectangle *src1,
00155 const MetaRectangle *src2,
00156 MetaRectangle *dest)
00157 {
00158 int dest_x, dest_y;
00159 int dest_w, dest_h;
00160 int return_val;
00161
00162 g_return_val_if_fail (src1 != NULL, FALSE);
00163 g_return_val_if_fail (src2 != NULL, FALSE);
00164 g_return_val_if_fail (dest != NULL, FALSE);
00165
00166 return_val = FALSE;
00167
00168 dest_x = MAX (src1->x, src2->x);
00169 dest_y = MAX (src1->y, src2->y);
00170 dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x;
00171 dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y;
00172
00173 if (dest_w > 0 && dest_h > 0)
00174 {
00175 dest->x = dest_x;
00176 dest->y = dest_y;
00177 dest->width = dest_w;
00178 dest->height = dest_h;
00179 return_val = TRUE;
00180 }
00181 else
00182 {
00183 dest->width = 0;
00184 dest->height = 0;
00185 }
00186
00187 return return_val;
00188 }
00189
00190 gboolean
00191 meta_rectangle_equal (const MetaRectangle *src1,
00192 const MetaRectangle *src2)
00193 {
00194 return ((src1->x == src2->x) &&
00195 (src1->y == src2->y) &&
00196 (src1->width == src2->width) &&
00197 (src1->height == src2->height));
00198 }
00199
00200 gboolean
00201 meta_rectangle_overlap (const MetaRectangle *rect1,
00202 const MetaRectangle *rect2)
00203 {
00204 g_return_val_if_fail (rect1 != NULL, FALSE);
00205 g_return_val_if_fail (rect2 != NULL, FALSE);
00206
00207 return !((rect1->x + rect1->width <= rect2->x) ||
00208 (rect2->x + rect2->width <= rect1->x) ||
00209 (rect1->y + rect1->height <= rect2->y) ||
00210 (rect2->y + rect2->height <= rect1->y));
00211 }
00212
00213 gboolean
00214 meta_rectangle_vert_overlap (const MetaRectangle *rect1,
00215 const MetaRectangle *rect2)
00216 {
00217 return (rect1->y < rect2->y + rect2->height &&
00218 rect2->y < rect1->y + rect1->height);
00219 }
00220
00221 gboolean
00222 meta_rectangle_horiz_overlap (const MetaRectangle *rect1,
00223 const MetaRectangle *rect2)
00224 {
00225 return (rect1->x < rect2->x + rect2->width &&
00226 rect2->x < rect1->x + rect1->width);
00227 }
00228
00229 gboolean
00230 meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect,
00231 const MetaRectangle *inner_rect)
00232 {
00233 return (outer_rect->width >= inner_rect->width &&
00234 outer_rect->height >= inner_rect->height);
00235 }
00236
00237 gboolean
00238 meta_rectangle_contains_rect (const MetaRectangle *outer_rect,
00239 const MetaRectangle *inner_rect)
00240 {
00241 return
00242 inner_rect->x >= outer_rect->x &&
00243 inner_rect->y >= outer_rect->y &&
00244 inner_rect->x + inner_rect->width <= outer_rect->x + outer_rect->width &&
00245 inner_rect->y + inner_rect->height <= outer_rect->y + outer_rect->height;
00246 }
00247
00248 void
00249 meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
00250 MetaRectangle *rect,
00251 int gravity,
00252 int new_width,
00253 int new_height)
00254 {
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 int adjust = 0;
00281 switch (gravity)
00282 {
00283 case NorthWestGravity:
00284 case WestGravity:
00285 case SouthWestGravity:
00286 rect->x = old_rect->x;
00287 break;
00288
00289 case NorthGravity:
00290 case CenterGravity:
00291 case SouthGravity:
00292
00293
00294
00295 new_width -= (old_rect->width - new_width) % 2;
00296 rect->x = old_rect->x + (old_rect->width - new_width)/2;
00297 break;
00298
00299 case NorthEastGravity:
00300 case EastGravity:
00301 case SouthEastGravity:
00302 rect->x = old_rect->x + (old_rect->width - new_width);
00303 break;
00304
00305 case StaticGravity:
00306 default:
00307 rect->x = old_rect->x;
00308 break;
00309 }
00310 rect->width = new_width;
00311
00312
00313 adjust = 0;
00314 switch (gravity)
00315 {
00316 case NorthWestGravity:
00317 case NorthGravity:
00318 case NorthEastGravity:
00319 rect->y = old_rect->y;
00320 break;
00321
00322 case WestGravity:
00323 case CenterGravity:
00324 case EastGravity:
00325
00326
00327
00328 new_height -= (old_rect->height - new_height) % 2;
00329 rect->y = old_rect->y + (old_rect->height - new_height)/2;
00330 break;
00331
00332 case SouthWestGravity:
00333 case SouthGravity:
00334 case SouthEastGravity:
00335 rect->y = old_rect->y + (old_rect->height - new_height);
00336 break;
00337
00338 case StaticGravity:
00339 default:
00340 rect->y = old_rect->y;
00341 break;
00342 }
00343 rect->height = new_height;
00344 }
00345
00346
00347 static GList*
00348 merge_spanning_rects_in_region (GList *region)
00349 {
00350
00351
00352
00353
00354
00355 GList* compare;
00356 compare = region;
00357
00358 if (region == NULL)
00359 {
00360 meta_warning ("Region to merge was empty! Either you have a some "
00361 "pathological STRUT list or there's a bug somewhere!\n");
00362 return NULL;
00363 }
00364
00365 while (compare && compare->next)
00366 {
00367 MetaRectangle *a = compare->data;
00368 GList *other = compare->next;
00369
00370 g_assert (a->width > 0 && a->height > 0);
00371
00372 while (other)
00373 {
00374 MetaRectangle *b = other->data;
00375 GList *delete_me = NULL;
00376
00377 g_assert (b->width > 0 && b->height > 0);
00378
00379
00380 if (meta_rectangle_contains_rect (a, b))
00381 {
00382 delete_me = other;
00383 }
00384
00385 else if (meta_rectangle_contains_rect (a, b))
00386 {
00387 delete_me = compare;
00388 }
00389
00390 else if (a->y == b->y && a->height == b->height)
00391 {
00392
00393 if (meta_rectangle_overlap (a, b))
00394 {
00395 int new_x = MIN (a->x, b->x);
00396 a->width = MAX (a->x + a->width, b->x + b->width) - new_x;
00397 a->x = new_x;
00398 delete_me = other;
00399 }
00400
00401 else if (a->x + a->width == b->x || a->x == b->x + b->width)
00402 {
00403 int new_x = MIN (a->x, b->x);
00404 a->width = MAX (a->x + a->width, b->x + b->width) - new_x;
00405 a->x = new_x;
00406 delete_me = other;
00407 }
00408 }
00409
00410 else if (a->x == b->x && a->width == b->width)
00411 {
00412
00413 if (meta_rectangle_overlap (a, b))
00414 {
00415 int new_y = MIN (a->y, b->y);
00416 a->height = MAX (a->y + a->height, b->y + b->height) - new_y;
00417 a->y = new_y;
00418 delete_me = other;
00419 }
00420
00421 else if (a->y + a->height == b->y || a->y == b->y + b->height)
00422 {
00423 int new_y = MIN (a->y, b->y);
00424 a->height = MAX (a->y + a->height, b->y + b->height) - new_y;
00425 a->y = new_y;
00426 delete_me = other;
00427 }
00428 }
00429
00430 other = other->next;
00431
00432
00433 if (delete_me != NULL)
00434 {
00435
00436 if (compare == delete_me)
00437 {
00438 compare = compare->next;
00439 other = compare->next;
00440 a = compare->data;
00441 }
00442
00443
00444 g_free (delete_me->data);
00445 region = g_list_delete_link (region, delete_me);
00446 }
00447
00448 }
00449
00450 compare = compare->next;
00451 }
00452
00453 return region;
00454 }
00455
00456
00457 static gint
00458 compare_rect_areas (gconstpointer a, gconstpointer b)
00459 {
00460 const MetaRectangle *a_rect = (gconstpointer) a;
00461 const MetaRectangle *b_rect = (gconstpointer) b;
00462
00463 int a_area = meta_rectangle_area (a_rect);
00464 int b_area = meta_rectangle_area (b_rect);
00465
00466 return b_area - a_area;
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 GList*
00488 meta_rectangle_get_minimal_spanning_set_for_region (
00489 const MetaRectangle *basic_rect,
00490 const GSList *all_struts)
00491 {
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 GList *ret;
00529 GList *tmp_list;
00530 const GSList *strut_iter;
00531 MetaRectangle *temp_rect;
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 temp_rect = g_new (MetaRectangle, 1);
00545 *temp_rect = *basic_rect;
00546 ret = g_list_prepend (NULL, temp_rect);
00547
00548 strut_iter = all_struts;
00549 for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
00550 {
00551 GList *rect_iter;
00552 MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
00553
00554 tmp_list = ret;
00555 ret = NULL;
00556 rect_iter = tmp_list;
00557 while (rect_iter)
00558 {
00559 MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
00560 if (!meta_rectangle_overlap (rect, strut_rect))
00561 ret = g_list_prepend (ret, rect);
00562 else
00563 {
00564
00565 if (BOX_LEFT (*rect) < BOX_LEFT (*strut_rect))
00566 {
00567 temp_rect = g_new (MetaRectangle, 1);
00568 *temp_rect = *rect;
00569 temp_rect->width = BOX_LEFT (*strut_rect) - BOX_LEFT (*rect);
00570 ret = g_list_prepend (ret, temp_rect);
00571 }
00572
00573 if (BOX_RIGHT (*rect) > BOX_RIGHT (*strut_rect))
00574 {
00575 int new_x;
00576 temp_rect = g_new (MetaRectangle, 1);
00577 *temp_rect = *rect;
00578 new_x = BOX_RIGHT (*strut_rect);
00579 temp_rect->width = BOX_RIGHT(*rect) - new_x;
00580 temp_rect->x = new_x;
00581 ret = g_list_prepend (ret, temp_rect);
00582 }
00583
00584 if (BOX_TOP (*rect) < BOX_TOP (*strut_rect))
00585 {
00586 temp_rect = g_new (MetaRectangle, 1);
00587 *temp_rect = *rect;
00588 temp_rect->height = BOX_TOP (*strut_rect) - BOX_TOP (*rect);
00589 ret = g_list_prepend (ret, temp_rect);
00590 }
00591
00592 if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*strut_rect))
00593 {
00594 int new_y;
00595 temp_rect = g_new (MetaRectangle, 1);
00596 *temp_rect = *rect;
00597 new_y = BOX_BOTTOM (*strut_rect);
00598 temp_rect->height = BOX_BOTTOM (*rect) - new_y;
00599 temp_rect->y = new_y;
00600 ret = g_list_prepend (ret, temp_rect);
00601 }
00602 g_free (rect);
00603 }
00604 rect_iter = rect_iter->next;
00605 }
00606 g_list_free (tmp_list);
00607 }
00608
00609
00610 ret = g_list_sort (ret, compare_rect_areas);
00611
00612
00613 ret = merge_spanning_rects_in_region (ret);
00614
00615 return ret;
00616 }
00617
00618 GList*
00619 meta_rectangle_expand_region (GList *region,
00620 const int left_expand,
00621 const int right_expand,
00622 const int top_expand,
00623 const int bottom_expand)
00624 {
00625 return meta_rectangle_expand_region_conditionally (region,
00626 left_expand,
00627 right_expand,
00628 top_expand,
00629 bottom_expand,
00630 0,
00631 0);
00632 }
00633
00634 GList*
00635 meta_rectangle_expand_region_conditionally (GList *region,
00636 const int left_expand,
00637 const int right_expand,
00638 const int top_expand,
00639 const int bottom_expand,
00640 const int min_x,
00641 const int min_y)
00642 {
00643 GList *tmp_list = region;
00644 while (tmp_list)
00645 {
00646 MetaRectangle *rect = (MetaRectangle*) tmp_list->data;
00647 if (rect->width >= min_x)
00648 {
00649 rect->x -= left_expand;
00650 rect->width += (left_expand + right_expand);
00651 }
00652 if (rect->height >= min_y)
00653 {
00654 rect->y -= top_expand;
00655 rect->height += (top_expand + bottom_expand);
00656 }
00657 tmp_list = tmp_list->next;
00658 }
00659
00660 return region;
00661 }
00662
00663 void
00664 meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect,
00665 const MetaRectangle *expand_to,
00666 const MetaDirection direction,
00667 const GSList *all_struts)
00668 {
00669 const GSList *strut_iter;
00670
00671
00672
00673
00674
00675
00676 g_assert ((direction == META_DIRECTION_HORIZONTAL) ^
00677 (direction == META_DIRECTION_VERTICAL ));
00678
00679 if (direction == META_DIRECTION_HORIZONTAL)
00680 {
00681 rect->x = expand_to->x;
00682 rect->width = expand_to->width;
00683 }
00684 else
00685 {
00686 rect->y = expand_to->y;
00687 rect->height = expand_to->height;
00688 }
00689
00690
00691
00692 for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
00693 {
00694 MetaStrut *strut = (MetaStrut*) strut_iter->data;
00695
00696
00697 if (!meta_rectangle_overlap (&strut->rect, rect))
00698 continue;
00699
00700 if (direction == META_DIRECTION_HORIZONTAL)
00701 {
00702 if (strut->side == META_SIDE_LEFT)
00703 {
00704 int offset = BOX_RIGHT(strut->rect) - BOX_LEFT(*rect);
00705 rect->x += offset;
00706 rect->width -= offset;
00707 }
00708 else if (strut->side == META_SIDE_RIGHT)
00709 {
00710 int offset = BOX_RIGHT (*rect) - BOX_LEFT(strut->rect);
00711 rect->width -= offset;
00712 }
00713
00714 }
00715 else
00716 {
00717 if (strut->side == META_SIDE_TOP)
00718 {
00719 int offset = BOX_BOTTOM(strut->rect) - BOX_TOP(*rect);
00720 rect->y += offset;
00721 rect->height -= offset;
00722 }
00723 else if (strut->side == META_SIDE_BOTTOM)
00724 {
00725 int offset = BOX_BOTTOM(*rect) - BOX_TOP(strut->rect);
00726 rect->height -= offset;
00727 }
00728
00729 }
00730 }
00731 }
00732
00733 void
00734 meta_rectangle_free_list_and_elements (GList *filled_list)
00735 {
00736 g_list_foreach (filled_list,
00737 (void (*)(gpointer,gpointer))&g_free,
00738 NULL);
00739 g_list_free (filled_list);
00740 }
00741
00742 gboolean
00743 meta_rectangle_could_fit_in_region (const GList *spanning_rects,
00744 const MetaRectangle *rect)
00745 {
00746 const GList *temp;
00747 gboolean could_fit;
00748
00749 temp = spanning_rects;
00750 could_fit = FALSE;
00751 while (!could_fit && temp != NULL)
00752 {
00753 could_fit = could_fit || meta_rectangle_could_fit_rect (temp->data, rect);
00754 temp = temp->next;
00755 }
00756
00757 return could_fit;
00758 }
00759
00760 gboolean
00761 meta_rectangle_contained_in_region (const GList *spanning_rects,
00762 const MetaRectangle *rect)
00763 {
00764 const GList *temp;
00765 gboolean contained;
00766
00767 temp = spanning_rects;
00768 contained = FALSE;
00769 while (!contained && temp != NULL)
00770 {
00771 contained = contained || meta_rectangle_contains_rect (temp->data, rect);
00772 temp = temp->next;
00773 }
00774
00775 return contained;
00776 }
00777
00778 gboolean
00779 meta_rectangle_overlaps_with_region (const GList *spanning_rects,
00780 const MetaRectangle *rect)
00781 {
00782 const GList *temp;
00783 gboolean overlaps;
00784
00785 temp = spanning_rects;
00786 overlaps = FALSE;
00787 while (!overlaps && temp != NULL)
00788 {
00789 overlaps = overlaps || meta_rectangle_overlap (temp->data, rect);
00790 temp = temp->next;
00791 }
00792
00793 return overlaps;
00794 }
00795
00796
00797 void
00798 meta_rectangle_clamp_to_fit_into_region (const GList *spanning_rects,
00799 FixedDirections fixed_directions,
00800 MetaRectangle *rect,
00801 const MetaRectangle *min_size)
00802 {
00803 const GList *temp;
00804 const MetaRectangle *best_rect = NULL;
00805 int best_overlap = 0;
00806
00807
00808
00809
00810 for (temp = spanning_rects; temp; temp = temp->next)
00811 {
00812 MetaRectangle *compare_rect = temp->data;
00813 int maximal_overlap_amount_for_compare;
00814
00815
00816
00817
00818 if ((fixed_directions & FIXED_DIRECTION_X) &&
00819 (compare_rect->x > rect->x ||
00820 compare_rect->x + compare_rect->width < rect->x + rect->width))
00821 continue;
00822
00823
00824
00825
00826 if ((fixed_directions & FIXED_DIRECTION_Y) &&
00827 (compare_rect->y > rect->y ||
00828 compare_rect->y + compare_rect->height < rect->y + rect->height))
00829 continue;
00830
00831
00832 if (compare_rect->width < min_size->width ||
00833 compare_rect->height < min_size->height)
00834 continue;
00835
00836
00837 maximal_overlap_amount_for_compare =
00838 MIN (rect->width, compare_rect->width) *
00839 MIN (rect->height, compare_rect->height);
00840
00841
00842 if (maximal_overlap_amount_for_compare > best_overlap)
00843 {
00844 best_rect = compare_rect;
00845 best_overlap = maximal_overlap_amount_for_compare;
00846 }
00847 }
00848
00849
00850 if (best_rect == NULL)
00851 {
00852 meta_warning ("No rect whose size to clamp to found!\n");
00853
00854
00855 if (!(fixed_directions & FIXED_DIRECTION_X))
00856 rect->width = min_size->width;
00857 if (!(fixed_directions & FIXED_DIRECTION_Y))
00858 rect->height = min_size->height;
00859 }
00860 else
00861 {
00862 rect->width = MIN (rect->width, best_rect->width);
00863 rect->height = MIN (rect->height, best_rect->height);
00864 }
00865 }
00866
00867 void
00868 meta_rectangle_clip_to_region (const GList *spanning_rects,
00869 FixedDirections fixed_directions,
00870 MetaRectangle *rect)
00871 {
00872 const GList *temp;
00873 const MetaRectangle *best_rect = NULL;
00874 int best_overlap = 0;
00875
00876
00877
00878
00879 for (temp = spanning_rects; temp; temp = temp->next)
00880 {
00881 MetaRectangle *compare_rect = temp->data;
00882 MetaRectangle overlap;
00883 int maximal_overlap_amount_for_compare;
00884
00885
00886
00887
00888 if ((fixed_directions & FIXED_DIRECTION_X) &&
00889 (compare_rect->x > rect->x ||
00890 compare_rect->x + compare_rect->width < rect->x + rect->width))
00891 continue;
00892
00893
00894
00895
00896 if ((fixed_directions & FIXED_DIRECTION_Y) &&
00897 (compare_rect->y > rect->y ||
00898 compare_rect->y + compare_rect->height < rect->y + rect->height))
00899 continue;
00900
00901
00902 meta_rectangle_intersect (rect, compare_rect, &overlap);
00903 maximal_overlap_amount_for_compare = meta_rectangle_area (&overlap);
00904
00905
00906 if (maximal_overlap_amount_for_compare > best_overlap)
00907 {
00908 best_rect = compare_rect;
00909 best_overlap = maximal_overlap_amount_for_compare;
00910 }
00911 }
00912
00913
00914 if (best_rect == NULL)
00915 meta_warning ("No rect to clip to found!\n");
00916 else
00917 {
00918
00919
00920
00921 if (!(fixed_directions & FIXED_DIRECTION_X))
00922 {
00923
00924 int new_x = MAX (rect->x, best_rect->x);
00925 rect->width = MIN ((rect->x + rect->width) - new_x,
00926 (best_rect->x + best_rect->width) - new_x);
00927 rect->x = new_x;
00928 }
00929
00930
00931
00932
00933 if (!(fixed_directions & FIXED_DIRECTION_Y))
00934 {
00935
00936 int new_y = MAX (rect->y, best_rect->y);
00937 rect->height = MIN ((rect->y + rect->height) - new_y,
00938 (best_rect->y + best_rect->height) - new_y);
00939 rect->y = new_y;
00940 }
00941 }
00942 }
00943
00944 void
00945 meta_rectangle_shove_into_region (const GList *spanning_rects,
00946 FixedDirections fixed_directions,
00947 MetaRectangle *rect)
00948 {
00949 const GList *temp;
00950 const MetaRectangle *best_rect = NULL;
00951 int best_overlap = 0;
00952 int shortest_distance = G_MAXINT;
00953
00954
00955
00956
00957
00958 for (temp = spanning_rects; temp; temp = temp->next)
00959 {
00960 MetaRectangle *compare_rect = temp->data;
00961 int maximal_overlap_amount_for_compare;
00962 int dist_to_compare;
00963
00964
00965
00966
00967 if ((fixed_directions & FIXED_DIRECTION_X) &&
00968 (compare_rect->x > rect->x ||
00969 compare_rect->x + compare_rect->width < rect->x + rect->width))
00970 continue;
00971
00972
00973
00974
00975 if ((fixed_directions & FIXED_DIRECTION_Y) &&
00976 (compare_rect->y > rect->y ||
00977 compare_rect->y + compare_rect->height < rect->y + rect->height))
00978 continue;
00979
00980
00981 maximal_overlap_amount_for_compare =
00982 MIN (rect->width, compare_rect->width) *
00983 MIN (rect->height, compare_rect->height);
00984
00985
00986 dist_to_compare = 0;
00987 if (compare_rect->x > rect->x)
00988 dist_to_compare += compare_rect->x - rect->x;
00989 if (compare_rect->x + compare_rect->width < rect->x + rect->width)
00990 dist_to_compare += (rect->x + rect->width) -
00991 (compare_rect->x + compare_rect->width);
00992 if (compare_rect->y > rect->y)
00993 dist_to_compare += compare_rect->y - rect->y;
00994 if (compare_rect->y + compare_rect->height < rect->y + rect->height)
00995 dist_to_compare += (rect->y + rect->height) -
00996 (compare_rect->y + compare_rect->height);
00997
00998
00999 if ((maximal_overlap_amount_for_compare > best_overlap) ||
01000 (maximal_overlap_amount_for_compare == best_overlap &&
01001 dist_to_compare < shortest_distance))
01002 {
01003 best_rect = compare_rect;
01004 best_overlap = maximal_overlap_amount_for_compare;
01005 shortest_distance = dist_to_compare;
01006 }
01007 }
01008
01009
01010 if (best_rect == NULL)
01011 meta_warning ("No rect to shove into found!\n");
01012 else
01013 {
01014
01015
01016
01017 if (!(fixed_directions & FIXED_DIRECTION_X))
01018 {
01019
01020 if (best_rect->x > rect->x)
01021 rect->x = best_rect->x;
01022
01023
01024 if (best_rect->x + best_rect->width < rect->x + rect->width)
01025 rect->x = (best_rect->x + best_rect->width) - rect->width;
01026 }
01027
01028
01029
01030
01031 if (!(fixed_directions & FIXED_DIRECTION_Y))
01032 {
01033
01034 if (best_rect->y > rect->y)
01035 rect->y = best_rect->y;
01036
01037
01038 if (best_rect->y + best_rect->height < rect->y + rect->height)
01039 rect->y = (best_rect->y + best_rect->height) - rect->height;
01040 }
01041 }
01042 }
01043
01044 void
01045 meta_rectangle_find_linepoint_closest_to_point (double x1,
01046 double y1,
01047 double x2,
01048 double y2,
01049 double px,
01050 double py,
01051 double *valx,
01052 double *valy)
01053 {
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090 double diffx, diffy, den;
01091 diffx = x2 - x1;
01092 diffy = y2 - y1;
01093 den = diffx * diffx + diffy * diffy;
01094
01095 *valx = (py * diffx * diffy + px * diffx * diffx +
01096 y2 * x1 * diffy - y1 * x2 * diffy) / den;
01097 *valy = (px * diffx * diffy + py * diffy * diffy +
01098 x2 * y1 * diffx - x1 * y2 * diffx) / den;
01099 }
01100
01101
01102
01103
01104
01105
01106
01107 gboolean
01108 meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge)
01109 {
01110
01111
01112
01113
01114
01115
01116 switch (edge->side_type)
01117 {
01118 case META_DIRECTION_LEFT:
01119 case META_DIRECTION_RIGHT:
01120 return BOX_TOP (*rect) <= BOX_BOTTOM (edge->rect) &&
01121 BOX_TOP (edge->rect) <= BOX_BOTTOM (*rect);
01122 case META_DIRECTION_TOP:
01123 case META_DIRECTION_BOTTOM:
01124 return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) &&
01125 BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect);
01126 default:
01127 g_assert_not_reached ();
01128 }
01129 }
01130
01131 static GList*
01132 get_rect_minus_overlap (const GList *rect_in_list,
01133 MetaRectangle *overlap)
01134 {
01135 MetaRectangle *temp;
01136 MetaRectangle *rect = rect_in_list->data;
01137 GList *ret = NULL;
01138
01139 if (BOX_LEFT (*rect) < BOX_LEFT (*overlap))
01140 {
01141 temp = g_new (MetaRectangle, 1);
01142 *temp = *rect;
01143 temp->width = BOX_LEFT (*overlap) - BOX_LEFT (*rect);
01144 ret = g_list_prepend (ret, temp);
01145 }
01146 if (BOX_RIGHT (*rect) > BOX_RIGHT (*overlap))
01147 {
01148 temp = g_new (MetaRectangle, 1);
01149 *temp = *rect;
01150 temp->x = BOX_RIGHT (*overlap);
01151 temp->width = BOX_RIGHT (*rect) - BOX_RIGHT (*overlap);
01152 ret = g_list_prepend (ret, temp);
01153 }
01154 if (BOX_TOP (*rect) < BOX_TOP (*overlap))
01155 {
01156 temp = g_new (MetaRectangle, 1);
01157 temp->x = overlap->x;
01158 temp->width = overlap->width;
01159 temp->y = BOX_TOP (*rect);
01160 temp->height = BOX_TOP (*overlap) - BOX_TOP (*rect);
01161 ret = g_list_prepend (ret, temp);
01162 }
01163 if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*overlap))
01164 {
01165 temp = g_new (MetaRectangle, 1);
01166 temp->x = overlap->x;
01167 temp->width = overlap->width;
01168 temp->y = BOX_BOTTOM (*overlap);
01169 temp->height = BOX_BOTTOM (*rect) - BOX_BOTTOM (*overlap);
01170 ret = g_list_prepend (ret, temp);
01171 }
01172
01173 return ret;
01174 }
01175
01176 static GList*
01177 replace_rect_with_list (GList *old_element,
01178 GList *new_list)
01179 {
01180 GList *ret;
01181 g_assert (old_element != NULL);
01182
01183 if (!new_list)
01184 {
01185
01186 ret = g_list_remove_link (old_element, old_element);
01187 }
01188 else
01189 {
01190
01191 ret = new_list;
01192 if (old_element->prev)
01193 {
01194 old_element->prev->next = new_list;
01195 new_list->prev = old_element->prev;
01196 }
01197 if (old_element->next)
01198 {
01199 GList *tmp = g_list_last (new_list);
01200 old_element->next->prev = tmp;
01201 tmp->next = old_element->next;
01202 }
01203 }
01204
01205
01206 g_free (old_element->data);
01207 g_list_free_1 (old_element);
01208 return ret;
01209 }
01210
01211
01212
01213
01214
01215
01216
01217 static GList*
01218 get_disjoint_strut_rect_list_in_region (const GSList *old_struts,
01219 const MetaRectangle *region)
01220 {
01221 GList *strut_rects;
01222 GList *tmp;
01223
01224
01225 strut_rects = NULL;
01226 while (old_struts)
01227 {
01228 MetaRectangle *cur = &((MetaStrut*)old_struts->data)->rect;
01229 MetaRectangle *copy = g_new (MetaRectangle, 1);
01230 *copy = *cur;
01231 if (meta_rectangle_intersect (copy, region, copy))
01232 strut_rects = g_list_prepend (strut_rects, copy);
01233 else
01234 g_free (copy);
01235
01236 old_struts = old_struts->next;
01237 }
01238
01239
01240
01241
01242 tmp = strut_rects;
01243 while (tmp)
01244 {
01245 GList *compare;
01246
01247 MetaRectangle *cur = tmp->data;
01248
01249 compare = tmp->next;
01250 while (compare)
01251 {
01252 MetaRectangle *comp = compare->data;
01253 MetaRectangle overlap;
01254
01255 if (meta_rectangle_intersect (cur, comp, &overlap))
01256 {
01257
01258
01259
01260 GList *cur_leftover = get_rect_minus_overlap (tmp, &overlap);
01261 GList *comp_leftover = get_rect_minus_overlap (compare, &overlap);
01262
01263
01264 MetaRectangle *overlap_allocated = g_new (MetaRectangle, 1);
01265 *overlap_allocated = overlap;
01266 cur_leftover = g_list_prepend (cur_leftover, overlap_allocated);
01267
01268
01269 if (strut_rects == tmp)
01270 {
01271 strut_rects = replace_rect_with_list (tmp, cur_leftover);
01272 tmp = strut_rects;
01273 }
01274 else
01275 tmp = replace_rect_with_list (tmp, cur_leftover);
01276 compare = replace_rect_with_list (compare, comp_leftover);
01277
01278 if (compare == NULL)
01279 break;
01280
01281 cur = tmp->data;
01282 }
01283
01284 compare = compare->next;
01285 }
01286
01287 tmp = tmp->next;
01288 }
01289
01290 return strut_rects;
01291 }
01292
01293 gint
01294 meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b)
01295 {
01296 const MetaEdge *a_edge_rect = (gconstpointer) a;
01297 const MetaEdge *b_edge_rect = (gconstpointer) b;
01298 int a_compare, b_compare;
01299
01300
01301
01302
01303 g_assert ((a_edge_rect->rect.width == 0 && b_edge_rect->rect.width == 0) ||
01304 (a_edge_rect->rect.height == 0 && b_edge_rect->rect.height == 0));
01305
01306 a_compare = b_compare = 0;
01307
01308 if (a_edge_rect->side_type == META_DIRECTION_LEFT ||
01309 a_edge_rect->side_type == META_DIRECTION_RIGHT)
01310 {
01311 a_compare = a_edge_rect->rect.x;
01312 b_compare = b_edge_rect->rect.x;
01313 if (a_compare == b_compare)
01314 {
01315 a_compare = a_edge_rect->rect.y;
01316 b_compare = b_edge_rect->rect.y;
01317 }
01318 }
01319 else if (a_edge_rect->side_type == META_DIRECTION_TOP ||
01320 a_edge_rect->side_type == META_DIRECTION_BOTTOM)
01321 {
01322 a_compare = a_edge_rect->rect.y;
01323 b_compare = b_edge_rect->rect.y;
01324 if (a_compare == b_compare)
01325 {
01326 a_compare = a_edge_rect->rect.x;
01327 b_compare = b_edge_rect->rect.x;
01328 }
01329 }
01330 else
01331 g_assert ("Some idiot wanted to sort sides of different types.\n");
01332
01333 return a_compare - b_compare;
01334 }
01335
01336
01337 gint
01338 meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b)
01339 {
01340 const MetaEdge *a_edge_rect = (gconstpointer) a;
01341 const MetaEdge *b_edge_rect = (gconstpointer) b;
01342
01343 int a_compare, b_compare;
01344
01345 a_compare = a_edge_rect->side_type;
01346 b_compare = b_edge_rect->side_type;
01347
01348 if (a_compare == b_compare)
01349 return meta_rectangle_edge_cmp_ignore_type (a, b);
01350
01351 return a_compare - b_compare;
01352 }
01353
01354
01355 static gboolean
01356 edges_overlap (const MetaEdge *edge1,
01357 const MetaEdge *edge2)
01358 {
01359 if (edge1->rect.width == 0 && edge2->rect.width == 0)
01360 {
01361 return meta_rectangle_vert_overlap (&edge1->rect, &edge2->rect) &&
01362 edge1->rect.x == edge2->rect.x;
01363 }
01364 else if (edge1->rect.height == 0 && edge2->rect.height == 0)
01365 {
01366 return meta_rectangle_horiz_overlap (&edge1->rect, &edge2->rect) &&
01367 edge1->rect.y == edge2->rect.y;
01368 }
01369 else
01370 {
01371 return FALSE;
01372 }
01373 }
01374
01375 static gboolean
01376 rectangle_and_edge_intersection (const MetaRectangle *rect,
01377 const MetaEdge *edge,
01378 MetaEdge *overlap,
01379 int *handle_type)
01380 {
01381 const MetaRectangle *rect2 = &edge->rect;
01382 MetaRectangle *result = &overlap->rect;
01383 gboolean intersect = TRUE;
01384
01385
01386 overlap->edge_type = -1;
01387 overlap->side_type = -1;
01388
01389
01390 result->x = MAX (rect->x, rect2->x);
01391 result->y = MAX (rect->y, rect2->y);
01392 result->width = MIN (BOX_RIGHT (*rect), BOX_RIGHT (*rect2)) - result->x;
01393 result->height = MIN (BOX_BOTTOM (*rect), BOX_BOTTOM (*rect2)) - result->y;
01394
01395
01396
01397
01398 if ((result->width < 0 || result->height < 0) ||
01399 (result->width == 0 && result->height == 0))
01400 {
01401 result->width = 0;
01402 result->height = 0;
01403 intersect = FALSE;
01404 }
01405 else
01406 {
01407
01408
01409
01410
01411
01412
01413
01414 switch (edge->side_type)
01415 {
01416 case META_DIRECTION_LEFT:
01417 if (result->x == rect->x)
01418 *handle_type = 1;
01419 else if (result->x == BOX_RIGHT (*rect))
01420 *handle_type = -1;
01421 else
01422 *handle_type = 0;
01423 break;
01424 case META_DIRECTION_RIGHT:
01425 if (result->x == rect->x)
01426 *handle_type = -1;
01427 else if (result->x == BOX_RIGHT (*rect))
01428 *handle_type = 1;
01429 else
01430 *handle_type = 0;
01431 break;
01432 case META_DIRECTION_TOP:
01433 if (result->y == rect->y)
01434 *handle_type = 1;
01435 else if (result->y == BOX_BOTTOM (*rect))
01436 *handle_type = -1;
01437 else
01438 *handle_type = 0;
01439 break;
01440 case META_DIRECTION_BOTTOM:
01441 if (result->y == rect->y)
01442 *handle_type = -1;
01443 else if (result->y == BOX_BOTTOM (*rect))
01444 *handle_type = 1;
01445 else
01446 *handle_type = 0;
01447 break;
01448 default:
01449 g_assert_not_reached ();
01450 }
01451 }
01452 return intersect;
01453 }
01454
01455
01456
01457
01458
01459 static GList*
01460 add_edges (GList *cur_edges,
01461 const MetaRectangle *rect,
01462 gboolean rect_is_internal)
01463 {
01464 MetaEdge *temp_edge;
01465 int i;
01466
01467 for (i=0; i<4; i++)
01468 {
01469 temp_edge = g_new (MetaEdge, 1);
01470 temp_edge->rect = *rect;
01471 switch (i)
01472 {
01473 case 0:
01474 temp_edge->side_type =
01475 rect_is_internal ? META_DIRECTION_LEFT : META_DIRECTION_RIGHT;
01476 temp_edge->rect.width = 0;
01477 break;
01478 case 1:
01479 temp_edge->side_type =
01480 rect_is_internal ? META_DIRECTION_RIGHT : META_DIRECTION_LEFT;
01481 temp_edge->rect.x += temp_edge->rect.width;
01482 temp_edge->rect.width = 0;
01483 break;
01484 case 2:
01485 temp_edge->side_type =
01486 rect_is_internal ? META_DIRECTION_TOP : META_DIRECTION_BOTTOM;
01487 temp_edge->rect.height = 0;
01488 break;
01489 case 3:
01490 temp_edge->side_type =
01491 rect_is_internal ? META_DIRECTION_BOTTOM : META_DIRECTION_TOP;
01492 temp_edge->rect.y += temp_edge->rect.height;
01493 temp_edge->rect.height = 0;
01494 break;
01495 }
01496 temp_edge->edge_type = META_EDGE_SCREEN;
01497 cur_edges = g_list_prepend (cur_edges, temp_edge);
01498 }
01499
01500 return cur_edges;
01501 }
01502
01503
01504
01505
01506 static GList*
01507 split_edge (GList *cur_list,
01508 const MetaEdge *old_edge,
01509 const MetaEdge *remove)
01510 {
01511 MetaEdge *temp_edge;
01512 switch (old_edge->side_type)
01513 {
01514 case META_DIRECTION_LEFT:
01515 case META_DIRECTION_RIGHT:
01516 g_assert (meta_rectangle_vert_overlap (&old_edge->rect, &remove->rect));
01517 if (BOX_TOP (old_edge->rect) < BOX_TOP (remove->rect))
01518 {
01519 temp_edge = g_new (MetaEdge, 1);
01520 *temp_edge = *old_edge;
01521 temp_edge->rect.height = BOX_TOP (remove->rect)
01522 - BOX_TOP (old_edge->rect);
01523 cur_list = g_list_prepend (cur_list, temp_edge);
01524 }
01525 if (BOX_BOTTOM (old_edge->rect) > BOX_BOTTOM (remove->rect))
01526 {
01527 temp_edge = g_new (MetaEdge, 1);
01528 *temp_edge = *old_edge;
01529 temp_edge->rect.y = BOX_BOTTOM (remove->rect);
01530 temp_edge->rect.height = BOX_BOTTOM (old_edge->rect)
01531 - BOX_BOTTOM (remove->rect);
01532 cur_list = g_list_prepend (cur_list, temp_edge);
01533 }
01534 break;
01535 case META_DIRECTION_TOP:
01536 case META_DIRECTION_BOTTOM:
01537 g_assert (meta_rectangle_horiz_overlap (&old_edge->rect, &remove->rect));
01538 if (BOX_LEFT (old_edge->rect) < BOX_LEFT (remove->rect))
01539 {
01540 temp_edge = g_new (MetaEdge, 1);
01541 *temp_edge = *old_edge;
01542 temp_edge->rect.width = BOX_LEFT (remove->rect)
01543 - BOX_LEFT (old_edge->rect);
01544 cur_list = g_list_prepend (cur_list, temp_edge);
01545 }
01546 if (BOX_RIGHT (old_edge->rect) > BOX_RIGHT (remove->rect))
01547 {
01548 temp_edge = g_new (MetaEdge, 1);
01549 *temp_edge = *old_edge;
01550 temp_edge->rect.x = BOX_RIGHT (remove->rect);
01551 temp_edge->rect.width = BOX_RIGHT (old_edge->rect)
01552 - BOX_RIGHT (remove->rect);
01553 cur_list = g_list_prepend (cur_list, temp_edge);
01554 }
01555 break;
01556 default:
01557 g_assert_not_reached ();
01558 }
01559
01560 return cur_list;
01561 }
01562
01563
01564
01565
01566 static void
01567 fix_up_edges (MetaRectangle *rect, MetaEdge *edge,
01568 GList **strut_edges, GList **edge_splits,
01569 gboolean *edge_needs_removal)
01570 {
01571 MetaEdge overlap;
01572 int handle_type;
01573
01574 if (!rectangle_and_edge_intersection (rect, edge, &overlap, &handle_type))
01575 return;
01576
01577 if (handle_type == 0 || handle_type == 1)
01578 {
01579
01580 *edge_splits = split_edge (*edge_splits, edge, &overlap);
01581 *edge_needs_removal = TRUE;
01582 }
01583
01584 if (handle_type == -1 || handle_type == 1)
01585 {
01586
01587
01588 GList *tmp = *strut_edges;
01589 while (tmp)
01590 {
01591 MetaEdge *cur = tmp->data;
01592
01593 if (edges_overlap (cur, &overlap))
01594 {
01595 GList *delete_me = tmp;
01596
01597
01598 *strut_edges = split_edge (*strut_edges, cur, &overlap);
01599
01600
01601 tmp = tmp->next;
01602 g_free (cur);
01603 *strut_edges = g_list_delete_link (*strut_edges, delete_me);
01604 }
01605 else
01606 tmp = tmp->next;
01607 }
01608 }
01609 }
01610
01611
01612
01613
01614 GList*
01615 meta_rectangle_remove_intersections_with_boxes_from_edges (
01616 GList *edges,
01617 const GSList *rectangles)
01618 {
01619 const GSList *rect_iter;
01620 const int opposing = 1;
01621
01622
01623 rect_iter = rectangles;
01624 while (rect_iter)
01625 {
01626 MetaRectangle *rect = rect_iter->data;
01627 GList *edge_iter = edges;
01628 while (edge_iter)
01629 {
01630 MetaEdge *edge = edge_iter->data;
01631 MetaEdge overlap;
01632 int handle;
01633 gboolean edge_iter_advanced = FALSE;
01634
01635
01636 if (rectangle_and_edge_intersection (rect, edge, &overlap, &handle))
01637 {
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651 if (handle != opposing)
01652 {
01653
01654 GList *delete_me = edge_iter;
01655 edge_iter = edge_iter->next;
01656 edge_iter_advanced = TRUE;
01657
01658
01659 edges = split_edge (edges, edge, &overlap);
01660
01661
01662 g_free (edge);
01663 edges = g_list_delete_link (edges, delete_me);
01664 }
01665 }
01666
01667 if (!edge_iter_advanced)
01668 edge_iter = edge_iter->next;
01669 }
01670
01671 rect_iter = rect_iter->next;
01672 }
01673
01674 return edges;
01675 }
01676
01677
01678 GList*
01679 meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
01680 const GSList *all_struts)
01681 {
01682 GList *ret;
01683 GList *fixed_strut_rects;
01684 GList *edge_iter;
01685 const GList *strut_rect_iter;
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703 fixed_strut_rects =
01704 get_disjoint_strut_rect_list_in_region (all_struts, basic_rect);
01705
01706
01707 ret = add_edges (NULL, basic_rect, TRUE);
01708
01709 strut_rect_iter = fixed_strut_rects;
01710 while (strut_rect_iter)
01711 {
01712 MetaRectangle *strut_rect = (MetaRectangle*) strut_rect_iter->data;
01713
01714
01715 GList *new_strut_edges = add_edges (NULL, strut_rect, FALSE);
01716
01717 edge_iter = ret;
01718 while (edge_iter)
01719 {
01720 MetaEdge *cur_edge = edge_iter->data;
01721 GList *splits_of_cur_edge = NULL;
01722 gboolean edge_needs_removal = FALSE;
01723
01724 fix_up_edges (strut_rect, cur_edge,
01725 &new_strut_edges, &splits_of_cur_edge,
01726 &edge_needs_removal);
01727
01728 if (edge_needs_removal)
01729 {
01730
01731 GList *delete_me = edge_iter;
01732 edge_iter = edge_iter->next;
01733 g_free (cur_edge);
01734 ret = g_list_delete_link (ret, delete_me);
01735
01736
01737 ret = g_list_concat (splits_of_cur_edge, ret);
01738 }
01739 else
01740 {
01741 edge_iter = edge_iter->next;
01742 }
01743
01744
01745 }
01746
01747 ret = g_list_concat (new_strut_edges, ret);
01748 strut_rect_iter = strut_rect_iter->next;
01749 }
01750
01751
01752 ret = g_list_sort (ret, meta_rectangle_edge_cmp);
01753
01754
01755 meta_rectangle_free_list_and_elements (fixed_strut_rects);
01756
01757 return ret;
01758 }
01759
01760 GList*
01761 meta_rectangle_find_nonintersected_xinerama_edges (
01762 const GList *xinerama_rects,
01763 const GSList *all_struts)
01764 {
01765
01766
01767
01768
01769
01770 GList *ret;
01771 const GList *cur;
01772 GSList *temp_rects;
01773
01774
01775 ret = NULL;
01776
01777
01778
01779
01780 cur = xinerama_rects;
01781 while (cur)
01782 {
01783 MetaRectangle *cur_rect = cur->data;
01784 const GList *compare = xinerama_rects;
01785 while (compare)
01786 {
01787 MetaRectangle *compare_rect = compare->data;
01788
01789
01790 if (meta_rectangle_vert_overlap(cur_rect, compare_rect))
01791 {
01792 MetaDirection side_type;
01793 int y = MAX (cur_rect->y, compare_rect->y);
01794 int height = MIN (BOX_BOTTOM (*cur_rect) - y,
01795 BOX_BOTTOM (*compare_rect) - y);
01796 int width = 0;
01797 int x;
01798
01799 if (BOX_LEFT (*cur_rect) == BOX_RIGHT (*compare_rect))
01800 {
01801
01802 x = BOX_LEFT (*cur_rect);
01803 side_type = META_DIRECTION_LEFT;
01804 }
01805 else if (BOX_RIGHT (*cur_rect) == BOX_LEFT (*compare_rect))
01806 {
01807
01808 x = BOX_RIGHT (*cur_rect);
01809 side_type = META_DIRECTION_RIGHT;
01810 }
01811 else
01812
01813 x = INT_MIN;
01814
01815
01816 if (x != INT_MIN)
01817 {
01818
01819
01820
01821
01822 MetaEdge *new_edge = g_new (MetaEdge, 1);
01823
01824 new_edge->rect = meta_rect (x, y, width, height);
01825 new_edge->side_type = side_type;
01826 new_edge->edge_type = META_EDGE_XINERAMA;
01827
01828 ret = g_list_prepend (ret, new_edge);
01829 }
01830 }
01831
01832
01833 if (meta_rectangle_horiz_overlap(cur_rect, compare_rect))
01834 {
01835 MetaDirection side_type;
01836 int x = MAX (cur_rect->x, compare_rect->x);
01837 int width = MIN (BOX_RIGHT (*cur_rect) - x,
01838 BOX_RIGHT (*compare_rect) - x);
01839 int height = 0;
01840 int y;
01841
01842 if (BOX_TOP (*cur_rect) == BOX_BOTTOM (*compare_rect))
01843 {
01844
01845 y = BOX_TOP (*cur_rect);
01846 side_type = META_DIRECTION_TOP;
01847 }
01848 else if (BOX_BOTTOM (*cur_rect) == BOX_TOP (*compare_rect))
01849 {
01850
01851 y = BOX_BOTTOM (*cur_rect);
01852 side_type = META_DIRECTION_BOTTOM;
01853 }
01854 else
01855
01856 y = INT_MIN;
01857
01858
01859 if (y != INT_MIN)
01860 {
01861
01862
01863
01864
01865 MetaEdge *new_edge = g_new (MetaEdge, 1);
01866
01867 new_edge->rect = meta_rect (x, y, width, height);
01868 new_edge->side_type = side_type;
01869 new_edge->edge_type = META_EDGE_XINERAMA;
01870
01871 ret = g_list_prepend (ret, new_edge);
01872 }
01873 }
01874
01875 compare = compare->next;
01876 }
01877 cur = cur->next;
01878 }
01879
01880 temp_rects = NULL;
01881 for (; all_struts; all_struts = all_struts->next)
01882 temp_rects = g_slist_prepend (temp_rects,
01883 &((MetaStrut*)all_struts->data)->rect);
01884 ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret,
01885 temp_rects);
01886 g_slist_free (temp_rects);
01887
01888
01889 ret = g_list_sort (ret, meta_rectangle_edge_cmp);
01890
01891 return ret;
01892 }