DnD: Stop using captured_event in Mutter 42 (#1468)

This commit is contained in:
David Hewitt 2022-10-06 21:32:04 +01:00 committed by GitHub
parent a12c1a1c47
commit 47c4e8346b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 206 additions and 1 deletions

View File

@ -103,6 +103,13 @@ namespace Gala {
float last_x;
float last_y;
#if HAS_MUTTER42
Grab? grab = null;
static unowned Actor? grabbed_actor = null;
InputDevice? grabbed_device = null;
ulong on_event_id = 0;
#endif
/**
* Create a new DragDropAction
*
@ -141,7 +148,9 @@ namespace Gala {
void release_actor (Actor actor) {
if (DragDropActionType.SOURCE in drag_type) {
#if !HAS_MUTTER42
actor.button_press_event.disconnect (source_clicked);
#endif
var source_list = sources.@get (drag_id);
source_list.remove (actor);
@ -155,7 +164,9 @@ namespace Gala {
void connect_actor (Actor actor) {
if (DragDropActionType.SOURCE in drag_type) {
#if !HAS_MUTTER42
actor.button_press_event.connect (source_clicked);
#endif
var source_list = sources.@get (drag_id);
if (source_list == null) {
@ -182,6 +193,190 @@ namespace Gala {
destination_crossed (destination, is_hovered);
}
#if HAS_MUTTER42
public override bool handle_event (Event event) {
switch (event.get_type ()) {
case EventType.BUTTON_PRESS:
if (event.get_button () != 1) {
actor_clicked (event.get_button ());
return false;
}
if (grabbed_actor != null) {
return false;
}
grab_actor (actor, event.get_device ());
clicked = true;
float x, y;
event.get_coords (out x, out y);
last_x = x;
last_y = y;
return true;
case EventType.BUTTON_RELEASE:
if (!dragging) {
float x, y, ex, ey;
event.get_coords (out ex, out ey);
actor.get_transformed_position (out x, out y);
// release has happened within bounds of actor
if (x < ex && x + actor.width > ex && y < ey && y + actor.height > ey) {
actor_clicked (event.get_button ());
}
ungrab_actor ();
clicked = false;
dragging = false;
return true;
} else if (dragging) {
if (hovered != null) {
finish ();
} else {
cancel ();
}
return true;
}
break;
default:
break;
}
return base.handle_event (event);
}
void grab_actor (Actor actor, InputDevice device) {
if (grabbed_actor != null) {
critical ("Tried to grab an actor with a grab already in progress");
}
grab = actor.get_stage ().grab (actor);
grabbed_actor = actor;
grabbed_device = device;
on_event_id = actor.event.connect (on_event);
}
void ungrab_actor () {
if (on_event_id == 0 || grabbed_actor == null) {
return;
}
if (grab != null) {
grab.dismiss ();
grab = null;
}
grabbed_device = null;
grabbed_actor.disconnect (on_event_id);
on_event_id = 0;
grabbed_actor = null;
}
bool on_event (Clutter.Event event) {
var device = event.get_device ();
if (grabbed_device != null &&
device != grabbed_device &&
device.get_device_type () != InputDeviceType.KEYBOARD_DEVICE) {
return false;
}
switch (event.get_type ()) {
case EventType.KEY_PRESS:
if (event.get_key_symbol () == Key.Escape) {
cancel ();
}
break;
case EventType.MOTION:
float x, y;
event.get_coords (out x, out y);
if (!dragging && clicked) {
var drag_threshold = Clutter.Settings.get_default ().dnd_drag_threshold;
if (Math.fabsf (last_x - x) > drag_threshold || Math.fabsf (last_y - y) > drag_threshold) {
handle = drag_begin (x, y);
if (handle == null) {
ungrab_actor ();
critical ("No handle has been returned by the started signal, aborting drag.");
return false;
}
clicked = false;
dragging = true;
ungrab_actor ();
grab_actor (handle, event.get_device ());
handle.reactive = false;
var source_list = sources.@get (drag_id);
if (source_list != null) {
var dest_list = destinations[drag_id];
foreach (var actor in source_list) {
// Do not unset reactivity on destinations
if (dest_list == null || actor in dest_list) {
continue;
}
actor.reactive = false;
}
}
}
return true;
} else if (dragging) {
handle.x -= last_x - x;
handle.y -= last_y - y;
last_x = x;
last_y = y;
var stage = actor.get_stage ();
var actor = stage.get_actor_at_pos (PickMode.REACTIVE, (int) x, (int) y);
DragDropAction action = null;
// if we're allowed to bubble and this actor is not a destination, check its parents
if (actor != null && (action = get_drag_drop_action (actor)) == null && allow_bubbling) {
while ((actor = actor.get_parent ()) != stage) {
if ((action = get_drag_drop_action (actor)) != null)
break;
}
}
// didn't change, no need to do anything
if (actor == hovered)
return true;
if (action == null) {
// apparently we left ours if we had one before
if (hovered != null) {
emit_crossed (hovered, false);
hovered = null;
}
return true;
}
// signal the previous one that we left it
if (hovered != null) {
emit_crossed (hovered, false);
}
// tell the new one that it is hovered
hovered = actor;
emit_crossed (hovered, true);
return true;
}
break;
}
return false;
}
#else
bool source_clicked (ButtonEvent event) {
if (event.button != 1) {
actor_clicked (event.button);
@ -314,6 +509,7 @@ namespace Gala {
return false;
}
#endif
/**
* Looks for a DragDropAction instance if this actor has one or NULL.
@ -382,8 +578,13 @@ namespace Gala {
}
}
if (dragging)
if (dragging) {
#if HAS_MUTTER42
ungrab_actor ();
#else
actor.get_stage ().captured_event.disconnect (follow_move);
#endif
}
dragging = false;
}

View File

@ -464,6 +464,10 @@ public class Gala.WindowClone : Clutter.Actor {
}
public override bool enter_event (Clutter.CrossingEvent event) {
if (drag_action.dragging) {
return false;
}
close_button.opacity = in_slot_animation ? 0 : 255;
window_title.opacity = in_slot_animation ? 0 : 255;
return false;