Move out generic math parts out of the native barrier implementation
In order to reuse some vector math for pointer confinement, move out those parts to its own file, introducing the types old types "MetaVector2" and "MetaLine2" outside of meta-barrier-native.c, as well as introducing MetaBorder which is a line, with a blocking direction. https://bugzilla.gnome.org/show_bug.cgi?id=744104
This commit is contained in:
parent
bc8ec2d90d
commit
f0f638d2bd
@ -112,6 +112,8 @@ libmutter_la_SOURCES = \
|
||||
core/boxes.c \
|
||||
core/boxes-private.h \
|
||||
meta/boxes.h \
|
||||
core/meta-border.c \
|
||||
core/meta-border.h \
|
||||
compositor/clutter-utils.c \
|
||||
compositor/clutter-utils.h \
|
||||
compositor/cogl-utils.c \
|
||||
|
@ -26,6 +26,8 @@
|
||||
#ifndef META_BARRIER_PRIVATE_H
|
||||
#define META_BARRIER_PRIVATE_H
|
||||
|
||||
#include "core/meta-border.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_BARRIER_IMPL (meta_barrier_impl_get_type ())
|
||||
@ -67,14 +69,7 @@ G_END_DECLS
|
||||
struct _MetaBarrierPrivate
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
|
||||
MetaBarrierDirection directions;
|
||||
|
||||
MetaBorder border;
|
||||
MetaBarrierImpl *impl;
|
||||
};
|
||||
|
||||
|
@ -61,19 +61,20 @@ meta_barrier_get_property (GObject *object,
|
||||
g_value_set_object (value, priv->display);
|
||||
break;
|
||||
case PROP_X1:
|
||||
g_value_set_int (value, priv->x1);
|
||||
g_value_set_int (value, priv->border.line.a.x);
|
||||
break;
|
||||
case PROP_Y1:
|
||||
g_value_set_int (value, priv->y1);
|
||||
g_value_set_int (value, priv->border.line.a.y);
|
||||
break;
|
||||
case PROP_X2:
|
||||
g_value_set_int (value, priv->x2);
|
||||
g_value_set_int (value, priv->border.line.b.x);
|
||||
break;
|
||||
case PROP_Y2:
|
||||
g_value_set_int (value, priv->y2);
|
||||
g_value_set_int (value, priv->border.line.b.y);
|
||||
break;
|
||||
case PROP_DIRECTIONS:
|
||||
g_value_set_flags (value, priv->directions);
|
||||
g_value_set_flags (value,
|
||||
meta_border_get_allows_directions (&priv->border));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@ -95,19 +96,20 @@ meta_barrier_set_property (GObject *object,
|
||||
priv->display = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_X1:
|
||||
priv->x1 = g_value_get_int (value);
|
||||
priv->border.line.a.x = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_Y1:
|
||||
priv->y1 = g_value_get_int (value);
|
||||
priv->border.line.a.y = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_X2:
|
||||
priv->x2 = g_value_get_int (value);
|
||||
priv->border.line.b.x = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_Y2:
|
||||
priv->y2 = g_value_get_int (value);
|
||||
priv->border.line.b.y = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_DIRECTIONS:
|
||||
priv->directions = g_value_get_flags (value);
|
||||
meta_border_set_allows_directions (&priv->border,
|
||||
g_value_get_flags (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@ -166,7 +168,8 @@ meta_barrier_constructed (GObject *object)
|
||||
MetaBarrier *barrier = META_BARRIER (object);
|
||||
MetaBarrierPrivate *priv = barrier->priv;
|
||||
|
||||
g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2);
|
||||
g_return_if_fail (priv->border.line.a.x == priv->border.line.b.x ||
|
||||
priv->border.line.a.y == priv->border.line.b.y);
|
||||
|
||||
#if defined(HAVE_NATIVE_BACKEND)
|
||||
if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
|
||||
|
@ -93,126 +93,18 @@ next_serial (void)
|
||||
return barrier_serial;
|
||||
}
|
||||
|
||||
typedef struct _Vector2
|
||||
{
|
||||
float x, y;
|
||||
} Vector2;
|
||||
|
||||
static float
|
||||
vector2_cross_product (Vector2 a, Vector2 b)
|
||||
{
|
||||
return a.x * b.y - a.y * b.x;
|
||||
}
|
||||
|
||||
static Vector2
|
||||
vector2_add (Vector2 a, Vector2 b)
|
||||
{
|
||||
return (Vector2) {
|
||||
.x = a.x + b.x,
|
||||
.y = a.y + b.y,
|
||||
};
|
||||
}
|
||||
|
||||
static Vector2
|
||||
vector2_subtract (Vector2 a, Vector2 b)
|
||||
{
|
||||
return (Vector2) {
|
||||
.x = a.x - b.x,
|
||||
.y = a.y - b.y,
|
||||
};
|
||||
}
|
||||
|
||||
static Vector2
|
||||
vector2_multiply_constant (float c, Vector2 a)
|
||||
{
|
||||
return (Vector2) {
|
||||
.x = c * a.x,
|
||||
.y = c * a.y,
|
||||
};
|
||||
}
|
||||
|
||||
typedef struct _Line2
|
||||
{
|
||||
Vector2 a;
|
||||
Vector2 b;
|
||||
} Line2;
|
||||
|
||||
static gboolean
|
||||
lines_intersect (Line2 *line1, Line2 *line2, Vector2 *intersection)
|
||||
{
|
||||
Vector2 p = line1->a;
|
||||
Vector2 r = vector2_subtract (line1->b, line1->a);
|
||||
Vector2 q = line2->a;
|
||||
Vector2 s = vector2_subtract (line2->b, line2->a);
|
||||
float rxs;
|
||||
float sxr;
|
||||
float t;
|
||||
float u;
|
||||
|
||||
/*
|
||||
* The line (p, r) and (q, s) intersects where
|
||||
*
|
||||
* p + t r = q + u s
|
||||
*
|
||||
* Calculate t:
|
||||
*
|
||||
* (p + t r) × s = (q + u s) × s
|
||||
* p × s + t (r × s) = q × s + u (s × s)
|
||||
* p × s + t (r × s) = q × s
|
||||
* t (r × s) = q × s - p × s
|
||||
* t (r × s) = (q - p) × s
|
||||
* t = ((q - p) × s) / (r × s)
|
||||
*
|
||||
* Using the same method, for u we get:
|
||||
*
|
||||
* u = ((p - q) × r) / (s × r)
|
||||
*/
|
||||
|
||||
rxs = vector2_cross_product (r, s);
|
||||
sxr = vector2_cross_product (s, r);
|
||||
|
||||
/* If r × s = 0 then the lines are either parallel or collinear. */
|
||||
if (fabs ( rxs) < DBL_MIN)
|
||||
return FALSE;
|
||||
|
||||
t = vector2_cross_product (vector2_subtract (q, p), s) / rxs;
|
||||
u = vector2_cross_product (vector2_subtract (p, q), r) / sxr;
|
||||
|
||||
|
||||
/* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
|
||||
if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
|
||||
return FALSE;
|
||||
|
||||
*intersection = vector2_add (p, vector2_multiply_constant (t, r));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_barrier_horizontal (MetaBarrier *barrier)
|
||||
{
|
||||
return barrier->priv->y1 == barrier->priv->y2;
|
||||
return meta_border_is_horizontal (&barrier->priv->border);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_barrier_blocking_directions (MetaBarrier *barrier,
|
||||
MetaBarrierDirection directions)
|
||||
{
|
||||
/* Barriers doesn't block parallel motions. */
|
||||
if (is_barrier_horizontal (barrier))
|
||||
{
|
||||
if ((directions & (META_BARRIER_DIRECTION_POSITIVE_Y |
|
||||
META_BARRIER_DIRECTION_NEGATIVE_Y)) == 0)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((directions & (META_BARRIER_DIRECTION_POSITIVE_X |
|
||||
META_BARRIER_DIRECTION_NEGATIVE_X)) == 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (barrier->priv->directions & directions) != directions;
|
||||
return meta_border_is_blocking_directions (&barrier->priv->border,
|
||||
directions);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -224,31 +116,16 @@ dismiss_pointer (MetaBarrierImplNative *self)
|
||||
priv->state = META_BARRIER_STATE_LEFT;
|
||||
}
|
||||
|
||||
static Line2
|
||||
barrier_to_line (MetaBarrier *barrier)
|
||||
{
|
||||
return (Line2) {
|
||||
.a = (Vector2) {
|
||||
.x = MIN (barrier->priv->x1, barrier->priv->x2),
|
||||
.y = MIN (barrier->priv->y1, barrier->priv->y2),
|
||||
},
|
||||
.b = (Vector2) {
|
||||
.x = MAX (barrier->priv->x1, barrier->priv->x2),
|
||||
.y = MAX (barrier->priv->y1, barrier->priv->y2),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the hit box for a held motion. The hit box is a 2 px wide region
|
||||
* in the opposite direction of every direction the barrier blocks. The purpose
|
||||
* of this is to allow small movements without receiving a "left" signal. This
|
||||
* heuristic comes from the X.org pointer barrier implementation.
|
||||
*/
|
||||
static Line2
|
||||
static MetaLine2
|
||||
calculate_barrier_hit_box (MetaBarrier *barrier)
|
||||
{
|
||||
Line2 hit_box = barrier_to_line (barrier);
|
||||
MetaLine2 hit_box = barrier->priv->border.line;
|
||||
|
||||
if (is_barrier_horizontal (barrier))
|
||||
{
|
||||
@ -273,7 +150,8 @@ calculate_barrier_hit_box (MetaBarrier *barrier)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_within_box (Line2 box, Vector2 point)
|
||||
is_within_box (MetaLine2 box,
|
||||
MetaVector2 point)
|
||||
{
|
||||
return (point.x >= box.a.x && point.x < box.b.x &&
|
||||
point.y >= box.a.y && point.y < box.b.y);
|
||||
@ -288,8 +166,8 @@ maybe_release_barrier (gpointer key,
|
||||
MetaBarrierImplNativePrivate *priv =
|
||||
meta_barrier_impl_native_get_instance_private (self);
|
||||
MetaBarrier *barrier = priv->barrier;
|
||||
Line2 *motion = user_data;
|
||||
Line2 hit_box;
|
||||
MetaLine2 *motion = user_data;
|
||||
MetaLine2 hit_box;
|
||||
|
||||
if (priv->state != META_BARRIER_STATE_HELD)
|
||||
return;
|
||||
@ -297,8 +175,10 @@ maybe_release_barrier (gpointer key,
|
||||
/* Release if we end up outside barrier end points. */
|
||||
if (is_barrier_horizontal (barrier))
|
||||
{
|
||||
if (motion->b.x > MAX (barrier->priv->x1, barrier->priv->x2) ||
|
||||
motion->b.x < MIN (barrier->priv->x1, barrier->priv->x2))
|
||||
if (motion->b.x > MAX (barrier->priv->border.line.a.x,
|
||||
barrier->priv->border.line.b.x) ||
|
||||
motion->b.x < MIN (barrier->priv->border.line.a.x,
|
||||
barrier->priv->border.line.b.x))
|
||||
{
|
||||
dismiss_pointer (self);
|
||||
return;
|
||||
@ -306,8 +186,10 @@ maybe_release_barrier (gpointer key,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (motion->b.y > MAX (barrier->priv->y1, barrier->priv->y2) ||
|
||||
motion->b.y < MIN (barrier->priv->y1, barrier->priv->y2))
|
||||
if (motion->b.y > MAX (barrier->priv->border.line.a.y,
|
||||
barrier->priv->border.line.b.y) ||
|
||||
motion->b.y < MIN (barrier->priv->border.line.a.y,
|
||||
barrier->priv->border.line.b.y))
|
||||
{
|
||||
dismiss_pointer (self);
|
||||
return;
|
||||
@ -330,7 +212,7 @@ maybe_release_barriers (MetaBarrierManagerNative *manager,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
Line2 motion = {
|
||||
MetaLine2 motion = {
|
||||
.a = {
|
||||
.x = prev_x,
|
||||
.y = prev_y,
|
||||
@ -350,7 +232,7 @@ typedef struct _MetaClosestBarrierData
|
||||
{
|
||||
struct
|
||||
{
|
||||
Line2 motion;
|
||||
MetaLine2 motion;
|
||||
MetaBarrierDirection directions;
|
||||
} in;
|
||||
|
||||
@ -371,8 +253,7 @@ update_closest_barrier (gpointer key,
|
||||
meta_barrier_impl_native_get_instance_private (self);
|
||||
MetaBarrier *barrier = priv->barrier;
|
||||
MetaClosestBarrierData *data = user_data;
|
||||
Line2 barrier_line;
|
||||
Vector2 intersection;
|
||||
MetaVector2 intersection;
|
||||
float dx, dy;
|
||||
float distance_2;
|
||||
|
||||
@ -391,17 +272,9 @@ update_closest_barrier (gpointer key,
|
||||
|
||||
/* Check if the motion intersects with the barrier, and retrieve the
|
||||
* intersection point if any. */
|
||||
barrier_line = (Line2) {
|
||||
.a = {
|
||||
.x = barrier->priv->x1,
|
||||
.y = barrier->priv->y1
|
||||
},
|
||||
.b = {
|
||||
.x = barrier->priv->x2,
|
||||
.y = barrier->priv->y2
|
||||
},
|
||||
};
|
||||
if (!lines_intersect (&barrier_line, &data->in.motion, &intersection))
|
||||
if (!meta_line2_intersects_with (&barrier->priv->border.line,
|
||||
&data->in.motion,
|
||||
&intersection))
|
||||
return;
|
||||
|
||||
/* Calculate the distance to the barrier and keep track of the closest
|
||||
@ -570,9 +443,9 @@ clamp_to_barrier (MetaBarrierImplNative *self,
|
||||
if (is_barrier_horizontal (barrier))
|
||||
{
|
||||
if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_Y)
|
||||
*y = barrier->priv->y1;
|
||||
*y = barrier->priv->border.line.a.y;
|
||||
else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_Y)
|
||||
*y = barrier->priv->y1;
|
||||
*y = barrier->priv->border.line.a.y;
|
||||
|
||||
priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_Y |
|
||||
META_BARRIER_DIRECTION_NEGATIVE_Y);
|
||||
@ -582,9 +455,9 @@ clamp_to_barrier (MetaBarrierImplNative *self,
|
||||
else
|
||||
{
|
||||
if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_X)
|
||||
*x = barrier->priv->x1;
|
||||
*x = barrier->priv->border.line.a.x;
|
||||
else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_X)
|
||||
*x = barrier->priv->x1;
|
||||
*x = barrier->priv->border.line.a.x;
|
||||
|
||||
priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_X |
|
||||
META_BARRIER_DIRECTION_NEGATIVE_X);
|
||||
|
@ -107,6 +107,7 @@ meta_barrier_impl_x11_new (MetaBarrier *barrier)
|
||||
MetaDisplay *display = barrier->priv->display;
|
||||
Display *dpy;
|
||||
Window root;
|
||||
unsigned int allowed_motion_dirs;
|
||||
|
||||
if (display == NULL)
|
||||
{
|
||||
@ -121,12 +122,14 @@ meta_barrier_impl_x11_new (MetaBarrier *barrier)
|
||||
dpy = display->xdisplay;
|
||||
root = DefaultRootWindow (dpy);
|
||||
|
||||
allowed_motion_dirs =
|
||||
meta_border_get_allows_directions (&barrier->priv->border);
|
||||
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
|
||||
barrier->priv->x1,
|
||||
barrier->priv->y1,
|
||||
barrier->priv->x2,
|
||||
barrier->priv->y2,
|
||||
barrier->priv->directions,
|
||||
barrier->priv->border.line.a.x,
|
||||
barrier->priv->border.line.a.y,
|
||||
barrier->priv->border.line.b.x,
|
||||
barrier->priv->border.line.b.y,
|
||||
allowed_motion_dirs,
|
||||
0, NULL);
|
||||
|
||||
g_hash_table_insert (display->xids, &priv->xbarrier, barrier);
|
||||
|
154
src/core/meta-border.c
Normal file
154
src/core/meta-border.c
Normal file
@ -0,0 +1,154 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/meta-border.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
static inline float
|
||||
meta_vector2_cross_product (const MetaVector2 a,
|
||||
const MetaVector2 b)
|
||||
{
|
||||
return a.x * b.y - a.y * b.x;
|
||||
}
|
||||
|
||||
static inline MetaVector2
|
||||
meta_vector2_add (const MetaVector2 a,
|
||||
const MetaVector2 b)
|
||||
{
|
||||
return (MetaVector2) {
|
||||
.x = a.x + b.x,
|
||||
.y = a.y + b.y,
|
||||
};
|
||||
}
|
||||
|
||||
static inline MetaVector2
|
||||
meta_vector2_multiply_constant (const float c,
|
||||
const MetaVector2 a)
|
||||
{
|
||||
return (MetaVector2) {
|
||||
.x = c * a.x,
|
||||
.y = c * a.y,
|
||||
};
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_line2_intersects_with (const MetaLine2 *line1,
|
||||
const MetaLine2 *line2,
|
||||
MetaVector2 *intersection)
|
||||
{
|
||||
MetaVector2 p = line1->a;
|
||||
MetaVector2 r = meta_vector2_subtract (line1->b, line1->a);
|
||||
MetaVector2 q = line2->a;
|
||||
MetaVector2 s = meta_vector2_subtract (line2->b, line2->a);
|
||||
float rxs;
|
||||
float sxr;
|
||||
float t;
|
||||
float u;
|
||||
|
||||
/*
|
||||
* The line (p, r) and (q, s) intersects where
|
||||
*
|
||||
* p + t r = q + u s
|
||||
*
|
||||
* Calculate t:
|
||||
*
|
||||
* (p + t r) × s = (q + u s) × s
|
||||
* p × s + t (r × s) = q × s + u (s × s)
|
||||
* p × s + t (r × s) = q × s
|
||||
* t (r × s) = q × s - p × s
|
||||
* t (r × s) = (q - p) × s
|
||||
* t = ((q - p) × s) / (r × s)
|
||||
*
|
||||
* Using the same method, for u we get:
|
||||
*
|
||||
* u = ((p - q) × r) / (s × r)
|
||||
*/
|
||||
|
||||
rxs = meta_vector2_cross_product (r, s);
|
||||
sxr = meta_vector2_cross_product (s, r);
|
||||
|
||||
/* If r × s = 0 then the lines are either parallel or collinear. */
|
||||
if (fabs (rxs) < DBL_MIN)
|
||||
return FALSE;
|
||||
|
||||
t = meta_vector2_cross_product (meta_vector2_subtract (q, p), s) / rxs;
|
||||
u = meta_vector2_cross_product (meta_vector2_subtract (p, q), r) / sxr;
|
||||
|
||||
/* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
|
||||
if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
|
||||
return FALSE;
|
||||
|
||||
*intersection = meta_vector2_add (p, meta_vector2_multiply_constant (t, r));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_border_is_horizontal (MetaBorder *border)
|
||||
{
|
||||
return border->line.a.y == border->line.b.y;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_border_is_blocking_directions (MetaBorder *border,
|
||||
MetaBorderMotionDirection directions)
|
||||
{
|
||||
if (meta_border_is_horizontal (border))
|
||||
{
|
||||
if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y)) == 0)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X)) == 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (~border->blocking_directions & directions) != directions;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
meta_border_get_allows_directions (MetaBorder *border)
|
||||
{
|
||||
return ~border->blocking_directions &
|
||||
(META_BORDER_MOTION_DIRECTION_POSITIVE_X |
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_border_set_allows_directions (MetaBorder *border, unsigned int directions)
|
||||
{
|
||||
border->blocking_directions =
|
||||
~directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
84
src/core/meta-border.h
Normal file
84
src/core/meta-border.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef META_BORDER_H
|
||||
#define META_BORDER_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_X = 1 << 0,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y = 1 << 1,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X = 1 << 2,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y = 1 << 3,
|
||||
} MetaBorderMotionDirection;
|
||||
|
||||
typedef struct _MetaVector2
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
} MetaVector2;
|
||||
|
||||
typedef struct _MetaLine2
|
||||
{
|
||||
MetaVector2 a;
|
||||
MetaVector2 b;
|
||||
} MetaLine2;
|
||||
|
||||
typedef struct _MetaBorder
|
||||
{
|
||||
MetaLine2 line;
|
||||
MetaBorderMotionDirection blocking_directions;
|
||||
} MetaBorder;
|
||||
|
||||
static inline MetaVector2
|
||||
meta_vector2_subtract (const MetaVector2 a,
|
||||
const MetaVector2 b)
|
||||
{
|
||||
return (MetaVector2) {
|
||||
.x = a.x - b.x,
|
||||
.y = a.y - b.y,
|
||||
};
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_line2_intersects_with (const MetaLine2 *line1,
|
||||
const MetaLine2 *line2,
|
||||
MetaVector2 *intersection);
|
||||
|
||||
gboolean
|
||||
meta_border_is_horizontal (MetaBorder *border);
|
||||
|
||||
gboolean
|
||||
meta_border_is_blocking_directions (MetaBorder *border,
|
||||
MetaBorderMotionDirection directions);
|
||||
|
||||
unsigned int
|
||||
meta_border_get_allows_directions (MetaBorder *border);
|
||||
|
||||
void
|
||||
meta_border_set_allows_directions (MetaBorder *border, unsigned int directions);
|
||||
|
||||
#endif /* META_BORDER_H */
|
Loading…
Reference in New Issue
Block a user