window: Introduce meta_window_get_tile_match()

Returns the matching tiled window. This is the topmost tiled window in a
complementary tile mode that is:

 - on the same monitor;
 - on the same workspace;
 - spanning the remaining monitor width;
 - there is no 3rd window stacked between both tiled windows that's
   partially visible in the common edge.

https://bugzilla.gnome.org/show_bug.cgi?id=643075
This commit is contained in:
Rui Matos 2012-02-24 17:08:55 +01:00
parent 13bc8f7a76
commit 2926323a9a
5 changed files with 139 additions and 0 deletions

View File

@ -121,6 +121,7 @@ meta_stack_add (MetaStack *stack,
window->desc, window->stack_position);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
void
@ -156,6 +157,7 @@ meta_stack_remove (MetaStack *stack,
GUINT_TO_POINTER (window->frame->xwindow));
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
void
@ -165,6 +167,7 @@ meta_stack_update_layer (MetaStack *stack,
stack->need_relayer = TRUE;
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
void
@ -174,6 +177,7 @@ meta_stack_update_transient (MetaStack *stack,
stack->need_constrain = TRUE;
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
/* raise/lower within a layer */
@ -185,6 +189,7 @@ meta_stack_raise (MetaStack *stack,
stack->n_positions - 1);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
void
@ -194,6 +199,7 @@ meta_stack_lower (MetaStack *stack,
meta_window_set_stack_position_no_sync (window, 0);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
void
@ -209,6 +215,26 @@ meta_stack_thaw (MetaStack *stack)
stack->freeze_count -= 1;
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
void
meta_stack_update_window_tile_matches (MetaStack *stack,
MetaWorkspace *workspace)
{
GList *windows;
if (stack->freeze_count > 0)
return;
windows = meta_stack_list_windows (stack, workspace);
while (windows)
{
meta_window_compute_tile_match ((MetaWindow *) windows->data);
windows = windows->next;
}
g_list_free (windows);
}
static gboolean
@ -1656,6 +1682,7 @@ meta_stack_set_positions (MetaStack *stack,
"Reset the stack positions of (nearly) all windows\n");
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
void
@ -1718,4 +1745,6 @@ meta_window_set_stack_position (MetaWindow *window,
{
meta_window_set_stack_position_no_sync (window, position);
stack_sync_to_server (window->screen->stack);
meta_stack_update_window_tile_matches (window->screen->stack,
window->screen->active_workspace);
}

View File

@ -383,4 +383,6 @@ GList* meta_stack_get_positions (MetaStack *stack);
void meta_stack_set_positions (MetaStack *stack,
GList *windows);
void meta_stack_update_window_tile_matches (MetaStack *stack,
MetaWorkspace *workspace);
#endif

View File

@ -410,6 +410,9 @@ struct _MetaWindow
/* Focused window that is (directly or indirectly) attached to this one */
MetaWindow *attached_focus_window;
/* The currently complementary tiled window, if any */
MetaWindow *tile_match;
};
struct _MetaWindowClass
@ -663,4 +666,6 @@ void meta_window_propagate_focus_appearance (MetaWindow *window,
gboolean meta_window_should_attach_to_parent (MetaWindow *window);
gboolean meta_window_can_tile_side_by_side (MetaWindow *window);
void meta_window_compute_tile_match (MetaWindow *window);
#endif

View File

@ -1167,6 +1167,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->monitor = meta_screen_get_monitor_for_window (window->screen, window);
window->tile_match = NULL;
if (window->override_redirect)
{
window->decorated = FALSE;
@ -5022,6 +5024,9 @@ meta_window_move_resize_internal (MetaWindow *window,
}
meta_window_foreach_transient (window, maybe_move_attached_dialog, NULL);
meta_stack_update_window_tile_matches (window->screen->stack,
window->screen->active_workspace);
}
/**
@ -10712,3 +10717,99 @@ meta_window_is_attached_dialog (MetaWindow *window)
{
return window->attached;
}
/**
* meta_window_get_tile_match:
*
* Returns the matching tiled window on the same monitor as @window. This is
* the topmost tiled window in a complementary tile mode that is:
*
* - on the same monitor;
* - on the same workspace;
* - spanning the remaining monitor width;
* - there is no 3rd window stacked between both tiled windows that's
* partially visible in the common edge.
*
* Return value: (transfer none) (allow-none): the matching tiled window or
* %NULL if it doesn't exist.
*/
MetaWindow *
meta_window_get_tile_match (MetaWindow *window)
{
return window->tile_match;
}
void
meta_window_compute_tile_match (MetaWindow *window)
{
MetaWindow *match;
MetaTileMode match_tile_mode;
MetaStack *stack;
window->tile_match = NULL;
if (window->shaded ||
window->minimized ||
!META_WINDOW_TILED_SIDE_BY_SIDE (window))
return;
if (META_WINDOW_TILED_LEFT (window))
match_tile_mode = META_TILE_RIGHT;
else if (META_WINDOW_TILED_RIGHT (window))
match_tile_mode = META_TILE_LEFT;
stack = window->screen->stack;
for (match = meta_stack_get_top (stack);
match;
match = meta_stack_get_below (stack, match, FALSE))
{
if (!match->shaded &&
!match->minimized &&
match->tile_mode == match_tile_mode &&
match->monitor == window->monitor &&
meta_window_get_workspace (match) == meta_window_get_workspace (window))
break;
}
if (match)
{
MetaWindow *above, *bottommost, *topmost;
MetaRectangle above_rect, bottommost_rect, topmost_rect;
if (meta_stack_windows_cmp (window->screen->stack, match, window) > 0)
{
topmost = match;
bottommost = window;
}
else
{
topmost = window;
bottommost = match;
}
meta_window_get_outer_rect (bottommost, &bottommost_rect);
meta_window_get_outer_rect (topmost, &topmost_rect);
/*
* If there's a window stacked in between which is partially visible
* behind the topmost tile we don't consider the tiles to match.
*/
for (above = meta_stack_get_above (stack, bottommost, FALSE);
above && above != topmost;
above = meta_stack_get_above (stack, above, FALSE))
{
if (above->minimized ||
above->monitor != window->monitor ||
meta_window_get_workspace (above) != meta_window_get_workspace (window))
continue;
meta_window_get_outer_rect (above, &above_rect);
if (meta_rectangle_overlap (&above_rect, &bottommost_rect) &&
meta_rectangle_overlap (&above_rect, &topmost_rect))
return;
}
window->tile_match = match;
}
}

View File

@ -169,4 +169,6 @@ MetaFrameType meta_window_get_frame_type (MetaWindow *window);
cairo_region_t *meta_window_get_frame_bounds (MetaWindow *window);
MetaWindow *meta_window_get_tile_match (MetaWindow *window);
#endif