core: Add support for custom window placement rules
Add support for assigning a window a custom window placement rule used for calculating the initial window position as well as defining how a window is constrained. The custom rule is a declarative rule which defines a set of parameters which the placing algorithm and constrain algorithm uses for calculating the position of a window. It is meant to be used to implement positioning of menus and other popup windows created via Wayland. A custom placement rule replaces any other placement or constraint rule. https://bugzilla.gnome.org/show_bug.cgi?id=769936
This commit is contained in:
parent
9fb891d216
commit
8833991201
@ -102,6 +102,7 @@ typedef enum
|
|||||||
PRIORITY_SIZE_HINTS_LIMITS = 3,
|
PRIORITY_SIZE_HINTS_LIMITS = 3,
|
||||||
PRIORITY_TITLEBAR_VISIBLE = 4,
|
PRIORITY_TITLEBAR_VISIBLE = 4,
|
||||||
PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4,
|
PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4,
|
||||||
|
PRIORITY_CUSTOM_RULE = 4,
|
||||||
PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */
|
PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */
|
||||||
} ConstraintPriority;
|
} ConstraintPriority;
|
||||||
|
|
||||||
@ -144,6 +145,10 @@ static gboolean do_screen_and_monitor_relative_constraints (MetaWindow *wind
|
|||||||
GList *region_spanning_rectangles,
|
GList *region_spanning_rectangles,
|
||||||
ConstraintInfo *info,
|
ConstraintInfo *info,
|
||||||
gboolean check_only);
|
gboolean check_only);
|
||||||
|
static gboolean constrain_custom_rule (MetaWindow *window,
|
||||||
|
ConstraintInfo *info,
|
||||||
|
ConstraintPriority priority,
|
||||||
|
gboolean check_only);
|
||||||
static gboolean constrain_modal_dialog (MetaWindow *window,
|
static gboolean constrain_modal_dialog (MetaWindow *window,
|
||||||
ConstraintInfo *info,
|
ConstraintInfo *info,
|
||||||
ConstraintPriority priority,
|
ConstraintPriority priority,
|
||||||
@ -211,6 +216,7 @@ typedef struct {
|
|||||||
} Constraint;
|
} Constraint;
|
||||||
|
|
||||||
static const Constraint all_constraints[] = {
|
static const Constraint all_constraints[] = {
|
||||||
|
{constrain_custom_rule, "constrain_custom_rule"},
|
||||||
{constrain_modal_dialog, "constrain_modal_dialog"},
|
{constrain_modal_dialog, "constrain_modal_dialog"},
|
||||||
{constrain_maximization, "constrain_maximization"},
|
{constrain_maximization, "constrain_maximization"},
|
||||||
{constrain_tiling, "constrain_tiling"},
|
{constrain_tiling, "constrain_tiling"},
|
||||||
@ -641,6 +647,222 @@ get_size_limits (MetaWindow *window,
|
|||||||
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
|
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
placement_rule_flip_horizontally (MetaPlacementRule *placement_rule)
|
||||||
|
{
|
||||||
|
if (placement_rule->anchor & META_PLACEMENT_ANCHOR_LEFT)
|
||||||
|
{
|
||||||
|
placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_LEFT;
|
||||||
|
placement_rule->anchor |= META_PLACEMENT_ANCHOR_RIGHT;
|
||||||
|
}
|
||||||
|
else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_RIGHT)
|
||||||
|
{
|
||||||
|
placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_RIGHT;
|
||||||
|
placement_rule->anchor |= META_PLACEMENT_ANCHOR_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placement_rule->gravity & META_PLACEMENT_GRAVITY_LEFT)
|
||||||
|
{
|
||||||
|
placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_LEFT;
|
||||||
|
placement_rule->gravity |= META_PLACEMENT_GRAVITY_RIGHT;
|
||||||
|
}
|
||||||
|
else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_RIGHT)
|
||||||
|
{
|
||||||
|
placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_RIGHT;
|
||||||
|
placement_rule->gravity |= META_PLACEMENT_GRAVITY_LEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
placement_rule_flip_vertically (MetaPlacementRule *placement_rule)
|
||||||
|
{
|
||||||
|
if (placement_rule->anchor & META_PLACEMENT_ANCHOR_TOP)
|
||||||
|
{
|
||||||
|
placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_TOP;
|
||||||
|
placement_rule->anchor |= META_PLACEMENT_ANCHOR_BOTTOM;
|
||||||
|
}
|
||||||
|
else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_BOTTOM)
|
||||||
|
{
|
||||||
|
placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_BOTTOM;
|
||||||
|
placement_rule->anchor |= META_PLACEMENT_ANCHOR_TOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placement_rule->gravity & META_PLACEMENT_GRAVITY_TOP)
|
||||||
|
{
|
||||||
|
placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_TOP;
|
||||||
|
placement_rule->gravity |= META_PLACEMENT_GRAVITY_BOTTOM;
|
||||||
|
}
|
||||||
|
else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_BOTTOM)
|
||||||
|
{
|
||||||
|
placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_BOTTOM;
|
||||||
|
placement_rule->gravity |= META_PLACEMENT_GRAVITY_TOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
try_flip_window_position (MetaWindow *window,
|
||||||
|
ConstraintInfo *info,
|
||||||
|
MetaPlacementRule *placement_rule,
|
||||||
|
MetaPlacementConstraintAdjustment constraint_adjustment,
|
||||||
|
MetaRectangle *rect,
|
||||||
|
MetaRectangle *intersection)
|
||||||
|
{
|
||||||
|
MetaPlacementRule flipped_rule = *placement_rule;;
|
||||||
|
MetaRectangle flipped_rect;
|
||||||
|
MetaRectangle flipped_intersection;
|
||||||
|
|
||||||
|
switch (constraint_adjustment)
|
||||||
|
{
|
||||||
|
case META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X:
|
||||||
|
placement_rule_flip_horizontally (&flipped_rule);
|
||||||
|
break;
|
||||||
|
case META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y:
|
||||||
|
placement_rule_flip_vertically (&flipped_rule);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
flipped_rect = info->current;
|
||||||
|
meta_window_process_placement (window, &flipped_rule,
|
||||||
|
&flipped_rect.x, &flipped_rect.y);
|
||||||
|
meta_rectangle_intersect (&flipped_rect, &info->work_area_monitor,
|
||||||
|
&flipped_intersection);
|
||||||
|
|
||||||
|
if ((constraint_adjustment == META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X &&
|
||||||
|
flipped_intersection.width == flipped_rect.width) ||
|
||||||
|
(constraint_adjustment == META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y &&
|
||||||
|
flipped_intersection.height == flipped_rect.height))
|
||||||
|
{
|
||||||
|
*placement_rule = flipped_rule;
|
||||||
|
*rect = flipped_rect;
|
||||||
|
*intersection = flipped_intersection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_custom_rule_satisfied (ConstraintInfo *info,
|
||||||
|
MetaPlacementRule *placement_rule,
|
||||||
|
MetaRectangle *intersection)
|
||||||
|
{
|
||||||
|
uint32_t x_constrain_actions, y_constrain_actions;
|
||||||
|
|
||||||
|
x_constrain_actions = (META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X |
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X);
|
||||||
|
y_constrain_actions = (META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y |
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y);
|
||||||
|
if ((placement_rule->constraint_adjustment & x_constrain_actions &&
|
||||||
|
info->current.width != intersection->width) ||
|
||||||
|
(placement_rule->constraint_adjustment & y_constrain_actions &&
|
||||||
|
info->current.height != intersection->height))
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
constrain_custom_rule (MetaWindow *window,
|
||||||
|
ConstraintInfo *info,
|
||||||
|
ConstraintPriority priority,
|
||||||
|
gboolean check_only)
|
||||||
|
{
|
||||||
|
MetaPlacementRule *placement_rule;
|
||||||
|
MetaRectangle intersection;
|
||||||
|
gboolean constraint_satisfied;
|
||||||
|
MetaPlacementRule current_rule;
|
||||||
|
|
||||||
|
if (priority > PRIORITY_CUSTOM_RULE)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
placement_rule = meta_window_get_placement_rule (window);
|
||||||
|
if (!placement_rule)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (!meta_rectangle_could_fit_rect (&info->work_area_monitor,
|
||||||
|
&info->current))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
meta_rectangle_intersect (&info->current, &info->work_area_monitor,
|
||||||
|
&intersection);
|
||||||
|
|
||||||
|
constraint_satisfied = is_custom_rule_satisfied (info,
|
||||||
|
placement_rule,
|
||||||
|
&intersection);
|
||||||
|
|
||||||
|
if (constraint_satisfied || check_only)
|
||||||
|
return constraint_satisfied;
|
||||||
|
|
||||||
|
current_rule = *placement_rule;
|
||||||
|
|
||||||
|
if (info->current.width != intersection.width &&
|
||||||
|
(current_rule.constraint_adjustment &
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X))
|
||||||
|
{
|
||||||
|
try_flip_window_position (window, info, ¤t_rule,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X,
|
||||||
|
&info->current, &intersection);
|
||||||
|
}
|
||||||
|
if (info->current.height != intersection.height &&
|
||||||
|
(current_rule.constraint_adjustment &
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y))
|
||||||
|
{
|
||||||
|
try_flip_window_position (window, info, ¤t_rule,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y,
|
||||||
|
&info->current, &intersection);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_rectangle_intersect (&info->current, &info->work_area_monitor,
|
||||||
|
&intersection);
|
||||||
|
constraint_satisfied = is_custom_rule_satisfied (info,
|
||||||
|
placement_rule,
|
||||||
|
&intersection);
|
||||||
|
|
||||||
|
if (constraint_satisfied)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (current_rule.constraint_adjustment &
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X)
|
||||||
|
{
|
||||||
|
if (info->current.x != intersection.x)
|
||||||
|
info->current.x = intersection.x;
|
||||||
|
else if (info->current.width != intersection.width)
|
||||||
|
info->current.x -= info->current.width - intersection.width;
|
||||||
|
}
|
||||||
|
if (current_rule.constraint_adjustment &
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
|
||||||
|
{
|
||||||
|
if (info->current.y != intersection.y)
|
||||||
|
info->current.y = intersection.y;
|
||||||
|
else if (info->current.height != intersection.height)
|
||||||
|
info->current.y -= info->current.height - intersection.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_rectangle_intersect (&info->current, &info->work_area_monitor,
|
||||||
|
&intersection);
|
||||||
|
constraint_satisfied = is_custom_rule_satisfied (info,
|
||||||
|
placement_rule,
|
||||||
|
&intersection);
|
||||||
|
|
||||||
|
if (constraint_satisfied)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (current_rule.constraint_adjustment &
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X)
|
||||||
|
{
|
||||||
|
info->current.x = intersection.x;
|
||||||
|
info->current.width = intersection.width;
|
||||||
|
}
|
||||||
|
if (current_rule.constraint_adjustment &
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y)
|
||||||
|
{
|
||||||
|
info->current.y = intersection.y;
|
||||||
|
info->current.height = intersection.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
constrain_modal_dialog (MetaWindow *window,
|
constrain_modal_dialog (MetaWindow *window,
|
||||||
ConstraintInfo *info,
|
ConstraintInfo *info,
|
||||||
@ -652,7 +874,8 @@ constrain_modal_dialog (MetaWindow *window,
|
|||||||
MetaRectangle child_rect, parent_rect;
|
MetaRectangle child_rect, parent_rect;
|
||||||
gboolean constraint_already_satisfied;
|
gboolean constraint_already_satisfied;
|
||||||
|
|
||||||
if (!meta_window_is_attached_dialog (window))
|
if (!meta_window_is_attached_dialog (window) ||
|
||||||
|
meta_window_get_placement_rule (window))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* We want to center the dialog on the parent, including the decorations
|
/* We want to center the dialog on the parent, including the decorations
|
||||||
@ -1230,7 +1453,8 @@ constrain_to_single_monitor (MetaWindow *window,
|
|||||||
window->screen->n_monitor_infos == 1 ||
|
window->screen->n_monitor_infos == 1 ||
|
||||||
!window->require_on_single_monitor ||
|
!window->require_on_single_monitor ||
|
||||||
!window->frame ||
|
!window->frame ||
|
||||||
info->is_user_action)
|
info->is_user_action ||
|
||||||
|
meta_window_get_placement_rule (window))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Have a helper function handle the constraint for us */
|
/* Have a helper function handle the constraint for us */
|
||||||
@ -1257,7 +1481,8 @@ constrain_fully_onscreen (MetaWindow *window,
|
|||||||
window->type == META_WINDOW_DOCK ||
|
window->type == META_WINDOW_DOCK ||
|
||||||
window->fullscreen ||
|
window->fullscreen ||
|
||||||
!window->require_fully_onscreen ||
|
!window->require_fully_onscreen ||
|
||||||
info->is_user_action)
|
info->is_user_action ||
|
||||||
|
meta_window_get_placement_rule (window))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Have a helper function handle the constraint for us */
|
/* Have a helper function handle the constraint for us */
|
||||||
@ -1296,7 +1521,8 @@ constrain_titlebar_visible (MetaWindow *window,
|
|||||||
window->type == META_WINDOW_DOCK ||
|
window->type == META_WINDOW_DOCK ||
|
||||||
window->fullscreen ||
|
window->fullscreen ||
|
||||||
!window->require_titlebar_visible ||
|
!window->require_titlebar_visible ||
|
||||||
unconstrained_user_action)
|
unconstrained_user_action ||
|
||||||
|
meta_window_get_placement_rule (window))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Determine how much offscreen things are allowed. We first need to
|
/* Determine how much offscreen things are allowed. We first need to
|
||||||
@ -1373,7 +1599,8 @@ constrain_partially_onscreen (MetaWindow *window,
|
|||||||
* "onscreen" by their own strut).
|
* "onscreen" by their own strut).
|
||||||
*/
|
*/
|
||||||
if (window->type == META_WINDOW_DESKTOP ||
|
if (window->type == META_WINDOW_DESKTOP ||
|
||||||
window->type == META_WINDOW_DOCK)
|
window->type == META_WINDOW_DOCK ||
|
||||||
|
meta_window_get_placement_rule (window))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Determine how much offscreen things are allowed. We first need to
|
/* Determine how much offscreen things are allowed. We first need to
|
||||||
|
@ -598,6 +598,61 @@ find_first_fit (MetaWindow *window,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_process_placement (MetaWindow *window,
|
||||||
|
MetaPlacementRule *placement_rule,
|
||||||
|
int *x,
|
||||||
|
int *y)
|
||||||
|
{
|
||||||
|
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||||
|
MetaRectangle parent_rect;
|
||||||
|
MetaRectangle anchor_rect;
|
||||||
|
int window_width, window_height;
|
||||||
|
|
||||||
|
window_width = placement_rule->width;
|
||||||
|
window_height = placement_rule->height;
|
||||||
|
meta_window_get_frame_rect (parent, &parent_rect);
|
||||||
|
|
||||||
|
anchor_rect = (MetaRectangle) {
|
||||||
|
.x = parent_rect.x + placement_rule->anchor_rect.x,
|
||||||
|
.y = parent_rect.y + placement_rule->anchor_rect.y,
|
||||||
|
.width = placement_rule->anchor_rect.width,
|
||||||
|
.height = placement_rule->anchor_rect.height,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Place at anchor point. */
|
||||||
|
if (placement_rule->anchor & META_PLACEMENT_ANCHOR_LEFT)
|
||||||
|
*x = anchor_rect.x;
|
||||||
|
else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_RIGHT)
|
||||||
|
*x = anchor_rect.x + anchor_rect.width;
|
||||||
|
else
|
||||||
|
*x = anchor_rect.x + (anchor_rect.width / 2);
|
||||||
|
if (placement_rule->anchor & META_PLACEMENT_ANCHOR_TOP)
|
||||||
|
*y = anchor_rect.y;
|
||||||
|
else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_BOTTOM)
|
||||||
|
*y = anchor_rect.y + anchor_rect.height;
|
||||||
|
else
|
||||||
|
*y = anchor_rect.y + (anchor_rect.height / 2);
|
||||||
|
|
||||||
|
/* Shift according to gravity. */
|
||||||
|
if (placement_rule->gravity & META_PLACEMENT_GRAVITY_LEFT)
|
||||||
|
*x -= window_width;
|
||||||
|
else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_RIGHT)
|
||||||
|
*x = *x;
|
||||||
|
else
|
||||||
|
*x -= window_width / 2;
|
||||||
|
if (placement_rule->gravity & META_PLACEMENT_GRAVITY_TOP)
|
||||||
|
*y -= window_height;
|
||||||
|
else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_BOTTOM)
|
||||||
|
*y = *y;
|
||||||
|
else
|
||||||
|
*y -= window_height / 2;
|
||||||
|
|
||||||
|
/* Offset according to offset. */
|
||||||
|
*x += placement_rule->offset_x;
|
||||||
|
*y += placement_rule->offset_y;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_window_place (MetaWindow *window,
|
meta_window_place (MetaWindow *window,
|
||||||
int x,
|
int x,
|
||||||
@ -610,6 +665,16 @@ meta_window_place (MetaWindow *window,
|
|||||||
|
|
||||||
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
||||||
|
|
||||||
|
/* If the window has a custom placement rule, always run only that. */
|
||||||
|
if (window->placement_rule)
|
||||||
|
{
|
||||||
|
meta_window_process_placement (window,
|
||||||
|
window->placement_rule,
|
||||||
|
&x, &y);
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
switch (window->type)
|
switch (window->type)
|
||||||
{
|
{
|
||||||
/* Run placement algorithm on these. */
|
/* Run placement algorithm on these. */
|
||||||
|
@ -25,6 +25,11 @@
|
|||||||
#include "window-private.h"
|
#include "window-private.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
|
void meta_window_process_placement (MetaWindow *window,
|
||||||
|
MetaPlacementRule *placement_rule,
|
||||||
|
int *x,
|
||||||
|
int *y);
|
||||||
|
|
||||||
void meta_window_place (MetaWindow *window,
|
void meta_window_place (MetaWindow *window,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
|
@ -88,6 +88,47 @@ typedef enum
|
|||||||
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
|
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
|
||||||
} MetaMoveResizeResultFlags;
|
} MetaMoveResizeResultFlags;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_PLACEMENT_GRAVITY_NONE = 0,
|
||||||
|
META_PLACEMENT_GRAVITY_TOP = 1 << 0,
|
||||||
|
META_PLACEMENT_GRAVITY_BOTTOM = 1 << 1,
|
||||||
|
META_PLACEMENT_GRAVITY_LEFT = 1 << 2,
|
||||||
|
META_PLACEMENT_GRAVITY_RIGHT = 1 << 3,
|
||||||
|
} MetaPlacementGravity;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_PLACEMENT_ANCHOR_NONE = 0,
|
||||||
|
META_PLACEMENT_ANCHOR_TOP = 1 << 0,
|
||||||
|
META_PLACEMENT_ANCHOR_BOTTOM = 1 << 1,
|
||||||
|
META_PLACEMENT_ANCHOR_LEFT = 1 << 2,
|
||||||
|
META_PLACEMENT_ANCHOR_RIGHT = 1 << 3,
|
||||||
|
} MetaPlacementAnchor;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_NONE = 0,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1 << 0,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 1 << 1,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X = 1 << 2,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y = 1 << 3,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X = 1 << 4,
|
||||||
|
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 1 << 5,
|
||||||
|
} MetaPlacementConstraintAdjustment;
|
||||||
|
|
||||||
|
typedef struct _MetaPlacementRule
|
||||||
|
{
|
||||||
|
MetaRectangle anchor_rect;
|
||||||
|
MetaPlacementGravity gravity;
|
||||||
|
MetaPlacementAnchor anchor;
|
||||||
|
MetaPlacementConstraintAdjustment constraint_adjustment;
|
||||||
|
int offset_x;
|
||||||
|
int offset_y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} MetaPlacementRule;
|
||||||
|
|
||||||
struct _MetaWindow
|
struct _MetaWindow
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
@ -448,6 +489,8 @@ struct _MetaWindow
|
|||||||
|
|
||||||
/* Bypass compositor hints */
|
/* Bypass compositor hints */
|
||||||
guint bypass_compositor;
|
guint bypass_compositor;
|
||||||
|
|
||||||
|
MetaPlacementRule *placement_rule;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaWindowClass
|
struct _MetaWindowClass
|
||||||
@ -698,4 +741,8 @@ gboolean meta_window_has_pointer (MetaWindow *window);
|
|||||||
|
|
||||||
void meta_window_emit_size_changed (MetaWindow *window);
|
void meta_window_emit_size_changed (MetaWindow *window);
|
||||||
|
|
||||||
|
MetaPlacementRule *meta_window_get_placement_rule (MetaWindow *window);
|
||||||
|
|
||||||
|
void meta_window_force_placement (MetaWindow *window);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,8 +84,6 @@ static void set_net_wm_state (MetaWindow *window);
|
|||||||
static void meta_window_set_above (MetaWindow *window,
|
static void meta_window_set_above (MetaWindow *window,
|
||||||
gboolean new_value);
|
gboolean new_value);
|
||||||
|
|
||||||
static void meta_window_force_placement (MetaWindow *window);
|
|
||||||
|
|
||||||
static void meta_window_show (MetaWindow *window);
|
static void meta_window_show (MetaWindow *window);
|
||||||
static void meta_window_hide (MetaWindow *window);
|
static void meta_window_hide (MetaWindow *window);
|
||||||
|
|
||||||
@ -296,6 +294,7 @@ meta_window_finalize (GObject *object)
|
|||||||
g_free (window->gtk_window_object_path);
|
g_free (window->gtk_window_object_path);
|
||||||
g_free (window->gtk_app_menu_object_path);
|
g_free (window->gtk_app_menu_object_path);
|
||||||
g_free (window->gtk_menubar_object_path);
|
g_free (window->gtk_menubar_object_path);
|
||||||
|
g_free (window->placement_rule);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_window_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_window_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@ -2168,7 +2167,7 @@ window_would_be_covered (const MetaWindow *newbie)
|
|||||||
return FALSE; /* none found */
|
return FALSE; /* none found */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
meta_window_force_placement (MetaWindow *window)
|
meta_window_force_placement (MetaWindow *window)
|
||||||
{
|
{
|
||||||
if (window->placed)
|
if (window->placed)
|
||||||
@ -7883,3 +7882,9 @@ meta_window_emit_size_changed (MetaWindow *window)
|
|||||||
{
|
{
|
||||||
g_signal_emit (window, window_signals[SIZE_CHANGED], 0);
|
g_signal_emit (window, window_signals[SIZE_CHANGED], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaPlacementRule *
|
||||||
|
meta_window_get_placement_rule (MetaWindow *window)
|
||||||
|
{
|
||||||
|
return window->placement_rule;
|
||||||
|
}
|
||||||
|
@ -640,3 +640,16 @@ meta_window_wayland_place_relative_to (MetaWindow *window,
|
|||||||
other->buffer_rect.y + (y * monitor_scale));
|
other->buffer_rect.y + (y * monitor_scale));
|
||||||
window->placed = TRUE;
|
window->placed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_place_with_placement_rule (MetaWindow *window,
|
||||||
|
MetaPlacementRule *placement_rule)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&window->placement_rule, g_free);
|
||||||
|
window->placement_rule = g_new0 (MetaPlacementRule, 1);
|
||||||
|
*window->placement_rule = *placement_rule;
|
||||||
|
|
||||||
|
window->unconstrained_rect.width = placement_rule->width;
|
||||||
|
window->unconstrained_rect.height = placement_rule->height;
|
||||||
|
meta_window_force_placement (window);
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#ifndef META_WINDOW_WAYLAND_H
|
#ifndef META_WINDOW_WAYLAND_H
|
||||||
#define META_WINDOW_WAYLAND_H
|
#define META_WINDOW_WAYLAND_H
|
||||||
|
|
||||||
|
#include "core/window-private.h"
|
||||||
#include <meta/window.h>
|
#include <meta/window.h>
|
||||||
#include "wayland/meta-wayland-types.h"
|
#include "wayland/meta-wayland-types.h"
|
||||||
|
|
||||||
@ -57,4 +58,7 @@ void meta_window_wayland_place_relative_to (MetaWindow *window,
|
|||||||
int x,
|
int x,
|
||||||
int y);
|
int y);
|
||||||
|
|
||||||
|
void meta_window_place_with_placement_rule (MetaWindow *window,
|
||||||
|
MetaPlacementRule *placement_rule);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user