Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/DBus.vala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class Gala.DBus {
SESSION, "io.elementary.gala", NONE,
(connection) => {
try {
connection.register_object ("/io/elementary/gala", WindowDragProvider.get_instance ());
connection.register_object ("/io/elementary/gala", WindowDragProvider.get_instance (wm.get_display ()));
} catch (Error e) {
warning (e.message);
}
Expand Down
2 changes: 2 additions & 0 deletions src/DesktopIntegration.vala
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ public class Gala.DesktopIntegration : GLib.Object {
public void move_window_to_workspace (uint64 uid, int index) throws DBusError, IOError {
var window = find_window_by_uid (uid);
window.change_workspace_by_index (index, false);

WindowDragProvider.get_instance (wm.get_display ()).handle_move (uid);
}

public void activate_workspace (int index) throws GLib.DBusError, GLib.IOError {
Expand Down
8 changes: 4 additions & 4 deletions src/Widgets/MultitaskingView/WindowClone.vala
Original file line number Diff line number Diff line change
Expand Up @@ -506,14 +506,14 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
}

if (hovered) {
WindowDragProvider.get_instance ().notify_enter (window.get_id ());
WindowDragProvider.get_instance (wm.get_display ()).notify_enter (window.get_id ());
} else {
WindowDragProvider.get_instance ().notify_leave ();
WindowDragProvider.get_instance (wm.get_display ()).notify_leave ();
}
}

private void destination_motion (Clutter.Actor destination, float x, float y) {
WindowDragProvider.get_instance ().notify_motion (x, y);
WindowDragProvider.get_instance (wm.get_display ()).notify_motion (x, y);
}

/**
Expand Down Expand Up @@ -549,7 +549,7 @@ public class Gala.WindowClone : ActorTarget, RootTarget {
did_move = true;
}
} else if (destination is Meta.WindowActor) {
WindowDragProvider.get_instance ().notify_dropped ();
WindowDragProvider.get_instance (display).notify_dropped ();
}

if (did_move) {
Expand Down
107 changes: 105 additions & 2 deletions src/WindowDragProvider.vala
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,93 @@
[DBus (name = "io.elementary.desktop.wm.WindowDragProvider")]
public class Gala.WindowDragProvider : Object {
private static GLib.Once<WindowDragProvider> instance;
public static WindowDragProvider get_instance () {
return instance.once (() => new WindowDragProvider ());
public static WindowDragProvider get_instance (Meta.Display display) {
return instance.once (() => new WindowDragProvider (display));
}

public signal void enter (uint64 window_id);
public signal void motion (int x, int y);
public signal void leave ();
public signal void dropped ();

[DBus (visible = false)]
public Meta.Display display { private get; construct; }

private ulong position_invalidated_id = 0;
private Meta.Window? previous_dock_window = null;
private Meta.Window? window_waiting_to_move = null;

public WindowDragProvider (Meta.Display display) {
Object (display: display);
}

construct {
display.grab_op_begin.connect ((grabbed_window, grab_op) => {
if (grab_op != MOVING) {
return;
}

#if HAS_MUTTER48
unowned var cursor_tracker = display.get_compositor ().get_backend ().get_cursor_tracker ();
#else
unowned var cursor_tracker = display.get_cursor_tracker ();
#endif
position_invalidated_id = cursor_tracker.position_invalidated.connect ((cursor_tracker) => {
Graphene.Point pointer;
cursor_tracker.get_pointer (out pointer, null);

foreach (unowned var window in display.list_all_windows ()) {
if (window.window_type != DOCK) {
continue;
}
var buffer_rect = window.get_buffer_rect ();
#if HAS_MUTTER48
if (buffer_rect.contains_pointf (pointer.x, pointer.y)) {
#else
if (buffer_rect.contains_rect ({ (int) pointer.x, (int) pointer.y, 0, 0})) {
#endif
if (previous_dock_window != window) {
notify_enter (grabbed_window.get_id ());
previous_dock_window = window;
} else {
notify_motion ((int) pointer.x - buffer_rect.x, (int) pointer.y - buffer_rect.y);
}

return;
}
}

if (previous_dock_window != null) {
notify_leave ();
previous_dock_window = null;
}
});
});

display.grab_op_end.connect ((grabbed_window, grab_op) => {
if (grab_op != MOVING) {
return;
}

if (position_invalidated_id > 0) {
#if HAS_MUTTER48
unowned var cursor_tracker = display.get_compositor ().get_backend ().get_cursor_tracker ();
#else
unowned var cursor_tracker = display.get_cursor_tracker ();
#endif
cursor_tracker.disconnect (position_invalidated_id);
position_invalidated_id = 0;

if (previous_dock_window != null) {
notify_dropped ();
notify_leave ();
previous_dock_window = null;
window_waiting_to_move = grabbed_window;
}
}
});
}

internal void notify_enter (uint64 window_id) {
enter (window_id);
}
Expand All @@ -32,4 +110,29 @@ public class Gala.WindowDragProvider : Object {
internal void notify_dropped () {
dropped ();
}

/**
* Handles centering the window on the workspace in case it was dragged directly to the dock.
* If we don't do that, the dragged window will sit awkwardly at the bottom of the monitor.
*/
internal void handle_move (uint64 uid) {
if (uid != window_waiting_to_move.get_id ()) {
warning ("WindowDragProvider: Windows id don't match");
window_waiting_to_move = null;
return;
}

var frame = window_waiting_to_move.get_frame_rect ();
var monitor_geometry = display.get_monitor_geometry (window_waiting_to_move.get_monitor ());

window_waiting_to_move.move_resize_frame (
true,
monitor_geometry.x + (monitor_geometry.width - frame.width) / 2,
monitor_geometry.y + (monitor_geometry.height - frame.height) / 2,
frame.width,
frame.height
);

window_waiting_to_move = null;
}
}