mirror of
https://github.com/brl/mutter.git
synced 2025-03-25 04:33:52 +00:00
barrier: Add ways to make barriers sticky
A sticky barrier means that a pointer in motion intersecting a barrier doesn't move once having hit it. The intention with this is to allow an input capture clients to continue a motion once a barrier is hit. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2628>
This commit is contained in:
parent
a8b013b006
commit
221ac2af76
@ -58,6 +58,8 @@ MetaBackend * meta_barrier_get_backend (MetaBarrier *barrier);
|
|||||||
|
|
||||||
MetaBorder * meta_barrier_get_border (MetaBarrier *barrier);
|
MetaBorder * meta_barrier_get_border (MetaBarrier *barrier);
|
||||||
|
|
||||||
|
MetaBarrierFlags meta_barrier_get_flags (MetaBarrier *barrier);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* META_BARRIER_PRIVATE_H */
|
#endif /* META_BARRIER_PRIVATE_H */
|
||||||
|
@ -28,6 +28,7 @@ typedef struct _MetaBarrierPrivate
|
|||||||
MetaBackend *backend;
|
MetaBackend *backend;
|
||||||
MetaBorder border;
|
MetaBorder border;
|
||||||
MetaBarrierImpl *impl;
|
MetaBarrierImpl *impl;
|
||||||
|
MetaBarrierFlags flags;
|
||||||
} MetaBarrierPrivate;
|
} MetaBarrierPrivate;
|
||||||
|
|
||||||
static void initable_iface_init (GInitableIface *initable_iface);
|
static void initable_iface_init (GInitableIface *initable_iface);
|
||||||
@ -60,6 +61,7 @@ enum
|
|||||||
PROP_X2,
|
PROP_X2,
|
||||||
PROP_Y2,
|
PROP_Y2,
|
||||||
PROP_DIRECTIONS,
|
PROP_DIRECTIONS,
|
||||||
|
PROP_FLAGS,
|
||||||
|
|
||||||
PROP_LAST,
|
PROP_LAST,
|
||||||
};
|
};
|
||||||
@ -125,6 +127,9 @@ meta_barrier_get_property (GObject *object,
|
|||||||
g_value_set_flags (value,
|
g_value_set_flags (value,
|
||||||
meta_border_get_allows_directions (&priv->border));
|
meta_border_get_allows_directions (&priv->border));
|
||||||
break;
|
break;
|
||||||
|
case PROP_FLAGS:
|
||||||
|
g_value_set_flags (value, priv->flags);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -170,6 +175,9 @@ meta_barrier_set_property (GObject *object,
|
|||||||
meta_border_set_allows_directions (&priv->border,
|
meta_border_set_allows_directions (&priv->border,
|
||||||
g_value_get_flags (value));
|
g_value_get_flags (value));
|
||||||
break;
|
break;
|
||||||
|
case PROP_FLAGS:
|
||||||
|
priv->flags = g_value_get_flags (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -362,6 +370,15 @@ meta_barrier_class_init (MetaBarrierClass *klass)
|
|||||||
G_PARAM_READWRITE |
|
G_PARAM_READWRITE |
|
||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_STATIC_STRINGS);
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
obj_props[PROP_FLAGS] =
|
||||||
|
g_param_spec_flags ("flags",
|
||||||
|
"Flags",
|
||||||
|
"Flags for manipulating barrier behavior",
|
||||||
|
META_TYPE_BARRIER_FLAGS,
|
||||||
|
META_BARRIER_FLAG_NONE,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||||
|
|
||||||
@ -426,6 +443,7 @@ meta_barrier_new (MetaBackend *backend,
|
|||||||
int x2,
|
int x2,
|
||||||
int y2,
|
int y2,
|
||||||
MetaBarrierDirection directions,
|
MetaBarrierDirection directions,
|
||||||
|
MetaBarrierFlags flags,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
return g_initable_new (META_TYPE_BARRIER,
|
return g_initable_new (META_TYPE_BARRIER,
|
||||||
@ -436,6 +454,7 @@ meta_barrier_new (MetaBackend *backend,
|
|||||||
"x2", x2,
|
"x2", x2,
|
||||||
"y2", y2,
|
"y2", y2,
|
||||||
"directions", directions,
|
"directions", directions,
|
||||||
|
"flags", flags,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,6 +488,14 @@ meta_barrier_get_border (MetaBarrier *barrier)
|
|||||||
return &priv->border;
|
return &priv->border;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaBarrierFlags
|
||||||
|
meta_barrier_get_flags (MetaBarrier *barrier)
|
||||||
|
{
|
||||||
|
MetaBarrierPrivate *priv = meta_barrier_get_instance_private (barrier);
|
||||||
|
|
||||||
|
return priv->flags;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_barrier_impl_class_init (MetaBarrierImplClass *klass)
|
meta_barrier_impl_class_init (MetaBarrierImplClass *klass)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +44,7 @@ struct _MetaBarrierManagerNative
|
|||||||
{
|
{
|
||||||
GHashTable *barriers;
|
GHashTable *barriers;
|
||||||
GMutex mutex;
|
GMutex mutex;
|
||||||
|
MetaBarrierImplNative *pointer_trap;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -504,6 +505,38 @@ clamp_to_barrier (MetaBarrierImplNative *self,
|
|||||||
self->state = META_BARRIER_STATE_HIT;
|
self->state = META_BARRIER_STATE_HIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
stick_to_barrier (MetaBarrierImplNative *self,
|
||||||
|
MetaBarrierDirection motion_dir,
|
||||||
|
float prev_x,
|
||||||
|
float prev_y,
|
||||||
|
float *x,
|
||||||
|
float *y)
|
||||||
|
{
|
||||||
|
MetaLine2 motion = {
|
||||||
|
.a = { .x = prev_x, .y = prev_y },
|
||||||
|
.b = { .x = *x, .y = *y },
|
||||||
|
};
|
||||||
|
MetaBorder *border = meta_barrier_get_border (self->barrier);
|
||||||
|
MetaVector2 intersection;
|
||||||
|
|
||||||
|
if (meta_line2_intersects_with (&motion, &border->line,
|
||||||
|
&intersection))
|
||||||
|
{
|
||||||
|
*x = intersection.x;
|
||||||
|
*y = intersection.y;
|
||||||
|
|
||||||
|
self->blocked_dir = motion_dir;
|
||||||
|
self->state = META_BARRIER_STATE_HIT;
|
||||||
|
self->manager->pointer_trap = self;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager,
|
meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager,
|
||||||
ClutterInputDevice *device,
|
ClutterInputDevice *device,
|
||||||
@ -524,11 +557,18 @@ meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager,
|
|||||||
device, NULL, &prev_pos, NULL))
|
device, NULL, &prev_pos, NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_mutex_lock (&manager->mutex);
|
|
||||||
|
|
||||||
prev_x = prev_pos.x;
|
prev_x = prev_pos.x;
|
||||||
prev_y = prev_pos.y;
|
prev_y = prev_pos.y;
|
||||||
|
|
||||||
|
if (manager->pointer_trap)
|
||||||
|
{
|
||||||
|
*x = prev_pos.x;
|
||||||
|
*y = prev_pos.y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mutex_lock (&manager->mutex);
|
||||||
|
|
||||||
/* Get the direction of the motion vector. */
|
/* Get the direction of the motion vector. */
|
||||||
if (prev_x < *x)
|
if (prev_x < *x)
|
||||||
motion_dir |= META_BARRIER_DIRECTION_POSITIVE_X;
|
motion_dir |= META_BARRIER_DIRECTION_POSITIVE_X;
|
||||||
@ -548,7 +588,18 @@ meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager,
|
|||||||
*x, *y,
|
*x, *y,
|
||||||
motion_dir,
|
motion_dir,
|
||||||
&barrier_impl))
|
&barrier_impl))
|
||||||
clamp_to_barrier (barrier_impl, &motion_dir, x, y);
|
{
|
||||||
|
MetaBarrier *barrier = barrier_impl->barrier;
|
||||||
|
|
||||||
|
if (meta_barrier_get_flags (barrier) & META_BARRIER_FLAG_STICKY)
|
||||||
|
{
|
||||||
|
if (stick_to_barrier (barrier_impl, motion_dir,
|
||||||
|
prev_x, prev_y, x, y))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
clamp_to_barrier (barrier_impl, &motion_dir, x, y);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -590,7 +641,10 @@ meta_barrier_impl_native_release (MetaBarrierImpl *impl,
|
|||||||
|
|
||||||
if (self->state == META_BARRIER_STATE_HELD &&
|
if (self->state == META_BARRIER_STATE_HELD &&
|
||||||
event->event_id == self->trigger_serial)
|
event->event_id == self->trigger_serial)
|
||||||
self->state = META_BARRIER_STATE_RELEASE;
|
{
|
||||||
|
self->state = META_BARRIER_STATE_RELEASE;
|
||||||
|
self->manager->pointer_trap = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -599,6 +653,8 @@ meta_barrier_impl_native_destroy (MetaBarrierImpl *impl)
|
|||||||
MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
|
MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
|
||||||
|
|
||||||
g_mutex_lock (&self->manager->mutex);
|
g_mutex_lock (&self->manager->mutex);
|
||||||
|
if (self->manager->pointer_trap == self)
|
||||||
|
self->manager->pointer_trap = NULL;
|
||||||
g_hash_table_remove (self->manager->barriers, self);
|
g_hash_table_remove (self->manager->barriers, self);
|
||||||
g_mutex_unlock (&self->manager->mutex);
|
g_mutex_unlock (&self->manager->mutex);
|
||||||
g_main_context_unref (self->main_context);
|
g_main_context_unref (self->main_context);
|
||||||
|
@ -26,6 +26,12 @@ typedef enum
|
|||||||
META_BARRIER_DIRECTION_NEGATIVE_Y = 1 << 3,
|
META_BARRIER_DIRECTION_NEGATIVE_Y = 1 << 3,
|
||||||
} MetaBarrierDirection;
|
} MetaBarrierDirection;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_BARRIER_FLAG_NONE = 1 << 0,
|
||||||
|
META_BARRIER_FLAG_STICKY = 1 << 1,
|
||||||
|
} MetaBarrierFlags;
|
||||||
|
|
||||||
#define META_TYPE_BARRIER (meta_barrier_get_type ())
|
#define META_TYPE_BARRIER (meta_barrier_get_type ())
|
||||||
META_EXPORT
|
META_EXPORT
|
||||||
G_DECLARE_DERIVABLE_TYPE (MetaBarrier, meta_barrier,
|
G_DECLARE_DERIVABLE_TYPE (MetaBarrier, meta_barrier,
|
||||||
@ -45,6 +51,7 @@ MetaBarrier * meta_barrier_new (MetaBackend *backend,
|
|||||||
int x2,
|
int x2,
|
||||||
int y2,
|
int y2,
|
||||||
MetaBarrierDirection directions,
|
MetaBarrierDirection directions,
|
||||||
|
MetaBarrierFlags flags,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
META_EXPORT
|
META_EXPORT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user