mirror of
https://github.com/elementary/gala.git
synced 2024-09-11 07:05:30 +03:00
add proper multimonitor support if workspaces-only-on-primary is enabled
This commit is contained in:
parent
efa173fda1
commit
933f8d5576
@ -15,6 +15,8 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
using Clutter;
|
||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public enum DragDropActionType
|
public enum DragDropActionType
|
||||||
@ -25,6 +27,8 @@ namespace Gala
|
|||||||
|
|
||||||
public class DragDropAction : Clutter.Action
|
public class DragDropAction : Clutter.Action
|
||||||
{
|
{
|
||||||
|
static Gee.HashMap<string,Gee.LinkedList<Actor>>? sources = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A drag has been started. You have to connect to this signal and
|
* A drag has been started. You have to connect to this signal and
|
||||||
* return an actor that is transformed during the drag operation.
|
* return an actor that is transformed during the drag operation.
|
||||||
@ -33,7 +37,7 @@ namespace Gala
|
|||||||
* @param y The global y coordinate where the action was activated
|
* @param y The global y coordinate where the action was activated
|
||||||
* @return A ClutterActor that serves as handle
|
* @return A ClutterActor that serves as handle
|
||||||
*/
|
*/
|
||||||
public signal Clutter.Actor drag_begin (float x, float y);
|
public signal Actor drag_begin (float x, float y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A drag has been canceled. You may want to consider cleaning up
|
* A drag has been canceled. You may want to consider cleaning up
|
||||||
@ -46,7 +50,7 @@ namespace Gala
|
|||||||
*
|
*
|
||||||
* @param actor The actor on which the drag finished
|
* @param actor The actor on which the drag finished
|
||||||
*/
|
*/
|
||||||
public signal void drag_end (Clutter.Actor actor);
|
public signal void drag_end (Actor actor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The destination has been crossed
|
* The destination has been crossed
|
||||||
@ -61,7 +65,7 @@ namespace Gala
|
|||||||
* @param destination The destination actor that has been crossed
|
* @param destination The destination actor that has been crossed
|
||||||
* @param hovered Whether the actor is now hovered or has just been left
|
* @param hovered Whether the actor is now hovered or has just been left
|
||||||
*/
|
*/
|
||||||
public signal void destination_crossed (Clutter.Actor destination, bool hovered);
|
public signal void destination_crossed (Actor destination, bool hovered);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source has been clicked, but the movement was not larger than
|
* The source has been clicked, but the movement was not larger than
|
||||||
@ -81,7 +85,7 @@ namespace Gala
|
|||||||
*/
|
*/
|
||||||
public string drag_id { get; construct; }
|
public string drag_id { get; construct; }
|
||||||
|
|
||||||
public Clutter.Actor handle { get; private set; }
|
public Actor handle { get; private set; }
|
||||||
/**
|
/**
|
||||||
* Indicates whether a drag action is currently active
|
* Indicates whether a drag action is currently active
|
||||||
*/
|
*/
|
||||||
@ -93,9 +97,8 @@ namespace Gala
|
|||||||
*/
|
*/
|
||||||
public bool allow_bubbling { get; set; default = true; }
|
public bool allow_bubbling { get; set; default = true; }
|
||||||
|
|
||||||
Clutter.Actor? hovered = null;
|
Actor? hovered = null;
|
||||||
bool clicked = false;
|
bool clicked = false;
|
||||||
bool actor_was_reactive = false;
|
|
||||||
float last_x;
|
float last_x;
|
||||||
float last_y;
|
float last_y;
|
||||||
|
|
||||||
@ -110,6 +113,9 @@ namespace Gala
|
|||||||
public DragDropAction (DragDropActionType type, string id)
|
public DragDropAction (DragDropActionType type, string id)
|
||||||
{
|
{
|
||||||
Object (drag_type : type, drag_id : id);
|
Object (drag_type : type, drag_id : id);
|
||||||
|
|
||||||
|
if (sources == null)
|
||||||
|
sources = new Gee.HashMap<string,Gee.LinkedList<Actor>> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
~DragDropAction ()
|
~DragDropAction ()
|
||||||
@ -118,7 +124,7 @@ namespace Gala
|
|||||||
release_actor (actor);
|
release_actor (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void set_actor (Clutter.Actor? new_actor)
|
public override void set_actor (Actor? new_actor)
|
||||||
{
|
{
|
||||||
if (actor != null) {
|
if (actor != null) {
|
||||||
release_actor (actor);
|
release_actor (actor);
|
||||||
@ -131,27 +137,38 @@ namespace Gala
|
|||||||
base.set_actor (new_actor);
|
base.set_actor (new_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_actor (Clutter.Actor actor)
|
void release_actor (Actor actor)
|
||||||
{
|
{
|
||||||
if (drag_type == DragDropActionType.SOURCE) {
|
if (drag_type == DragDropActionType.SOURCE) {
|
||||||
actor.button_press_event.disconnect (source_clicked);
|
actor.button_press_event.disconnect (source_clicked);
|
||||||
|
|
||||||
|
var source_list = sources.@get (drag_id);
|
||||||
|
source_list.remove (actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect_actor (Clutter.Actor actor)
|
void connect_actor (Actor actor)
|
||||||
{
|
{
|
||||||
if (drag_type == DragDropActionType.SOURCE) {
|
if (drag_type == DragDropActionType.SOURCE) {
|
||||||
actor.button_press_event.connect (source_clicked);
|
actor.button_press_event.connect (source_clicked);
|
||||||
|
|
||||||
|
var source_list = sources.@get (drag_id);
|
||||||
|
if (source_list == null) {
|
||||||
|
source_list = new Gee.LinkedList<Actor> ();
|
||||||
|
sources.@set (drag_id, source_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
source_list.add (actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_crossed (Clutter.Actor destination, bool hovered)
|
void emit_crossed (Actor destination, bool hovered)
|
||||||
{
|
{
|
||||||
get_drag_drop_action (destination).crossed (hovered);
|
get_drag_drop_action (destination).crossed (hovered);
|
||||||
destination_crossed (destination, hovered);
|
destination_crossed (destination, hovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool source_clicked (Clutter.ButtonEvent event)
|
bool source_clicked (ButtonEvent event)
|
||||||
{
|
{
|
||||||
if (event.button != 1) {
|
if (event.button != 1) {
|
||||||
actor_clicked (event.button);
|
actor_clicked (event.button);
|
||||||
@ -166,12 +183,12 @@ namespace Gala
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool follow_move (Clutter.Event event)
|
bool follow_move (Event event)
|
||||||
{
|
{
|
||||||
// still determining if we actually want to start a drag action
|
// still determining if we actually want to start a drag action
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
switch (event.get_type ()) {
|
switch (event.get_type ()) {
|
||||||
case Clutter.EventType.MOTION:
|
case EventType.MOTION:
|
||||||
float x, y;
|
float x, y;
|
||||||
event.get_coords (out x, out y);
|
event.get_coords (out x, out y);
|
||||||
|
|
||||||
@ -184,14 +201,20 @@ namespace Gala
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor_was_reactive = handle.reactive;
|
|
||||||
handle.reactive = false;
|
handle.reactive = false;
|
||||||
|
|
||||||
clicked = false;
|
clicked = false;
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
|
||||||
|
var source_list = sources.@get (drag_id);
|
||||||
|
if (source_list != null) {
|
||||||
|
foreach (var actor in source_list) {
|
||||||
|
actor.reactive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case Clutter.EventType.BUTTON_RELEASE:
|
case EventType.BUTTON_RELEASE:
|
||||||
float x, y, ex, ey;
|
float x, y, ex, ey;
|
||||||
event.get_coords (out ex, out ey);
|
event.get_coords (out ex, out ey);
|
||||||
actor.get_transformed_position (out x, out y);
|
actor.get_transformed_position (out x, out y);
|
||||||
@ -211,12 +234,12 @@ namespace Gala
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (event.get_type ()) {
|
switch (event.get_type ()) {
|
||||||
case Clutter.EventType.KEY_PRESS:
|
case EventType.KEY_PRESS:
|
||||||
if (event.get_key_code () == Clutter.Key.Escape) {
|
if (event.get_key_code () == Key.Escape) {
|
||||||
cancel ();
|
cancel ();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case Clutter.EventType.MOTION:
|
case EventType.MOTION:
|
||||||
float x, y;
|
float x, y;
|
||||||
event.get_coords (out x, out y);
|
event.get_coords (out x, out y);
|
||||||
handle.x -= last_x - x;
|
handle.x -= last_x - x;
|
||||||
@ -225,7 +248,7 @@ namespace Gala
|
|||||||
last_y = y;
|
last_y = y;
|
||||||
|
|
||||||
var stage = actor.get_stage ();
|
var stage = actor.get_stage ();
|
||||||
var actor = actor.get_stage ().get_actor_at_pos (Clutter.PickMode.REACTIVE, (int)x, (int)y);
|
var actor = actor.get_stage ().get_actor_at_pos (PickMode.REACTIVE, (int)x, (int)y);
|
||||||
DragDropAction action = null;
|
DragDropAction action = null;
|
||||||
// if we're allowed to bubble and we this actor is not a destination, check its parents
|
// if we're allowed to bubble and we this actor is not a destination, check its parents
|
||||||
if (actor != null && (action = get_drag_drop_action (actor)) == null && allow_bubbling) {
|
if (actor != null && (action = get_drag_drop_action (actor)) == null && allow_bubbling) {
|
||||||
@ -259,15 +282,15 @@ namespace Gala
|
|||||||
emit_crossed (hovered, true);
|
emit_crossed (hovered, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case Clutter.EventType.BUTTON_RELEASE:
|
case EventType.BUTTON_RELEASE:
|
||||||
if (hovered != null) {
|
if (hovered != null) {
|
||||||
finish ();
|
finish ();
|
||||||
} else {
|
} else {
|
||||||
cancel ();
|
cancel ();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case Clutter.EventType.ENTER:
|
case EventType.ENTER:
|
||||||
case Clutter.EventType.LEAVE:
|
case EventType.LEAVE:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +303,7 @@ namespace Gala
|
|||||||
*
|
*
|
||||||
* @return the DragDropAction instance on this actor or NULL
|
* @return the DragDropAction instance on this actor or NULL
|
||||||
*/
|
*/
|
||||||
DragDropAction? get_drag_drop_action (Clutter.Actor actor)
|
DragDropAction? get_drag_drop_action (Actor actor)
|
||||||
{
|
{
|
||||||
DragDropAction? drop_action = null;
|
DragDropAction? drop_action = null;
|
||||||
|
|
||||||
@ -302,12 +325,7 @@ namespace Gala
|
|||||||
*/
|
*/
|
||||||
public void cancel ()
|
public void cancel ()
|
||||||
{
|
{
|
||||||
if (dragging) {
|
cleanup ();
|
||||||
actor.get_stage ().captured_event.disconnect (follow_move);
|
|
||||||
}
|
|
||||||
|
|
||||||
dragging = false;
|
|
||||||
actor.reactive = actor_was_reactive;
|
|
||||||
|
|
||||||
drag_canceled ();
|
drag_canceled ();
|
||||||
}
|
}
|
||||||
@ -317,12 +335,24 @@ namespace Gala
|
|||||||
// make sure they reset the style or whatever they changed when hovered
|
// make sure they reset the style or whatever they changed when hovered
|
||||||
emit_crossed (hovered, false);
|
emit_crossed (hovered, false);
|
||||||
|
|
||||||
actor.get_stage ().captured_event.disconnect (follow_move);
|
cleanup ();
|
||||||
|
|
||||||
dragging = false;
|
|
||||||
actor.reactive = actor_was_reactive;
|
|
||||||
|
|
||||||
drag_end (hovered);
|
drag_end (hovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cleanup ()
|
||||||
|
{
|
||||||
|
var source_list = sources.@get (drag_id);
|
||||||
|
if (source_list != null) {
|
||||||
|
foreach (var actor in source_list) {
|
||||||
|
actor.reactive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dragging)
|
||||||
|
actor.get_stage ().captured_event.disconnect (follow_move);
|
||||||
|
|
||||||
|
dragging = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,12 @@ namespace Gala
|
|||||||
{
|
{
|
||||||
public class InternalUtils
|
public class InternalUtils
|
||||||
{
|
{
|
||||||
|
public static bool workspaces_only_on_primary ()
|
||||||
|
{
|
||||||
|
return Prefs.get_dynamic_workspaces ()
|
||||||
|
&& Prefs.get_workspaces_only_on_primary ();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reload shadow settings
|
* Reload shadow settings
|
||||||
*/
|
*/
|
||||||
|
@ -55,6 +55,7 @@ gala_VALASOURCES = \
|
|||||||
Widgets/WorkspaceThumb.vala \
|
Widgets/WorkspaceThumb.vala \
|
||||||
Widgets/WorkspaceView.vala \
|
Widgets/WorkspaceView.vala \
|
||||||
Widgets/MultitaskingView/IconGroup.vala \
|
Widgets/MultitaskingView/IconGroup.vala \
|
||||||
|
Widgets/MultitaskingView/MonitorClone.vala \
|
||||||
Widgets/MultitaskingView/MultitaskingView.vala \
|
Widgets/MultitaskingView/MultitaskingView.vala \
|
||||||
Widgets/MultitaskingView/TiledWindowContainer.vala \
|
Widgets/MultitaskingView/TiledWindowContainer.vala \
|
||||||
Widgets/MultitaskingView/Workspace.vala \
|
Widgets/MultitaskingView/Workspace.vala \
|
||||||
|
90
src/Widgets/MultitaskingView/MonitorClone.vala
Normal file
90
src/Widgets/MultitaskingView/MonitorClone.vala
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
using Clutter;
|
||||||
|
using Meta;
|
||||||
|
|
||||||
|
namespace Gala
|
||||||
|
{
|
||||||
|
public class MonitorClone : Actor
|
||||||
|
{
|
||||||
|
public WindowManager wm { get; construct; }
|
||||||
|
public Screen screen { get; construct; }
|
||||||
|
public int monitor { get; construct; }
|
||||||
|
|
||||||
|
public signal void window_selected (Window window);
|
||||||
|
|
||||||
|
TiledWorkspaceContainer window_container;
|
||||||
|
Background background;
|
||||||
|
|
||||||
|
public MonitorClone (WindowManager wm, Screen screen, int monitor)
|
||||||
|
{
|
||||||
|
Object (wm: wm, monitor: monitor, screen: screen);
|
||||||
|
|
||||||
|
reactive = true;
|
||||||
|
|
||||||
|
background = new Background (screen, monitor, BackgroundSettings.get_default ().schema);
|
||||||
|
background.set_easing_duration (300);
|
||||||
|
|
||||||
|
window_container = new TiledWorkspaceContainer (wm.window_stacking_order);
|
||||||
|
window_container.window_selected.connect ((w) => { window_selected (w); });
|
||||||
|
|
||||||
|
wm.windows_restacked.connect (() => {
|
||||||
|
window_container.stacking_order = wm.window_stacking_order;
|
||||||
|
});
|
||||||
|
|
||||||
|
screen.window_entered_monitor.connect (window_entered);
|
||||||
|
screen.window_left_monitor.connect (window_left);
|
||||||
|
|
||||||
|
foreach (var window_actor in Compositor.get_window_actors (screen)) {
|
||||||
|
var window = window_actor.get_meta_window ();
|
||||||
|
if (window.get_monitor () == monitor) {
|
||||||
|
window_entered (monitor, window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_child (background);
|
||||||
|
add_child (window_container);
|
||||||
|
|
||||||
|
var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
||||||
|
add_action (drop);
|
||||||
|
|
||||||
|
update_allocation ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update_allocation ()
|
||||||
|
{
|
||||||
|
var monitor_geometry = screen.get_monitor_geometry (monitor);
|
||||||
|
|
||||||
|
set_position (monitor_geometry.x, monitor_geometry.y);
|
||||||
|
set_size (monitor_geometry.width, monitor_geometry.height);
|
||||||
|
window_container.set_size (monitor_geometry.width, monitor_geometry.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open ()
|
||||||
|
{
|
||||||
|
window_container.opened = true;
|
||||||
|
// background.opacity = 0; TODO consider this option
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close ()
|
||||||
|
{
|
||||||
|
window_container.opened = false;
|
||||||
|
background.opacity = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_left (int window_monitor, Window window)
|
||||||
|
{
|
||||||
|
if (window_monitor != monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window_container.remove_window (window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_entered (int window_monitor, Window window)
|
||||||
|
{
|
||||||
|
if (window_monitor != monitor || window.window_type != WindowType.NORMAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window_container.add_window (window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,8 @@ namespace Gala
|
|||||||
public WindowManager wm { get; construct set; }
|
public WindowManager wm { get; construct set; }
|
||||||
public bool opened { get; private set; default = false; }
|
public bool opened { get; private set; default = false; }
|
||||||
|
|
||||||
|
List<MonitorClone> window_containers_monitors;
|
||||||
|
|
||||||
Actor icon_groups;
|
Actor icon_groups;
|
||||||
Actor workspaces;
|
Actor workspaces;
|
||||||
|
|
||||||
@ -40,6 +42,67 @@ namespace Gala
|
|||||||
screen.workspace_switched.connect_after ((from, to, direction) => {
|
screen.workspace_switched.connect_after ((from, to, direction) => {
|
||||||
update_positions (opened);
|
update_positions (opened);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window_containers_monitors = new List<MonitorClone> ();
|
||||||
|
update_monitors ();
|
||||||
|
screen.monitors_changed.connect (update_monitors);
|
||||||
|
|
||||||
|
Prefs.add_listener ((pref) => {
|
||||||
|
if (pref == Preference.WORKSPACES_ONLY_ON_PRIMARY) {
|
||||||
|
update_monitors ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Prefs.get_dynamic_workspaces () ||
|
||||||
|
(pref != Preference.DYNAMIC_WORKSPACES && pref != Preference.NUM_WORKSPACES))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Idle.add (() => {
|
||||||
|
unowned List<Workspace> existing_workspaces = screen.get_workspaces ();
|
||||||
|
|
||||||
|
foreach (var child in workspaces.get_children ()) {
|
||||||
|
var workspace_clone = child as WorkspaceClone;
|
||||||
|
if (existing_workspaces.index (workspace_clone.workspace) < 0) {
|
||||||
|
workspace_clone.window_selected.disconnect (window_selected);
|
||||||
|
workspace_clone.selected.disconnect (activate_workspace);
|
||||||
|
workspace_clone.icon_group.destroy ();
|
||||||
|
workspace_clone.destroy ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_monitors ();
|
||||||
|
update_positions ();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_monitors ()
|
||||||
|
{
|
||||||
|
foreach (var monitor_clone in window_containers_monitors)
|
||||||
|
monitor_clone.destroy ();
|
||||||
|
|
||||||
|
var primary = screen.get_primary_monitor ();
|
||||||
|
|
||||||
|
if (InternalUtils.workspaces_only_on_primary ()) {
|
||||||
|
for (var monitor = 0; monitor < screen.get_n_monitors (); monitor++) {
|
||||||
|
if (monitor == primary)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var monitor_clone = new MonitorClone (wm, screen, monitor);
|
||||||
|
monitor_clone.window_selected.connect (window_selected);
|
||||||
|
monitor_clone.visible = opened;
|
||||||
|
|
||||||
|
window_containers_monitors.append (monitor_clone);
|
||||||
|
wm.ui_group.add_child (monitor_clone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var primary_geometry = screen.get_monitor_geometry (primary);
|
||||||
|
|
||||||
|
set_position (primary_geometry.x, primary_geometry.y);
|
||||||
|
set_size (primary_geometry.width, primary_geometry.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void key_focus_out ()
|
public override void key_focus_out ()
|
||||||
@ -221,12 +284,13 @@ namespace Gala
|
|||||||
|
|
||||||
var opening = opened;
|
var opening = opened;
|
||||||
|
|
||||||
unowned List<Meta.WindowActor> windows = Meta.Compositor.get_window_actors (screen);
|
foreach (var container in window_containers_monitors) {
|
||||||
var primary_monitor = screen.get_primary_monitor ();
|
if (opening) {
|
||||||
var monitor = screen.get_monitor_geometry (primary_monitor);
|
container.visible = true;
|
||||||
|
container.open ();
|
||||||
set_position (monitor.x, monitor.y);
|
} else
|
||||||
set_size (monitor.width, monitor.height);
|
container.close ();
|
||||||
|
}
|
||||||
|
|
||||||
if (opening) {
|
if (opening) {
|
||||||
wm.begin_modal ();
|
wm.begin_modal ();
|
||||||
@ -238,7 +302,7 @@ namespace Gala
|
|||||||
show ();
|
show ();
|
||||||
grab_key_focus ();
|
grab_key_focus ();
|
||||||
|
|
||||||
icon_groups.y = monitor.height - WorkspaceClone.BOTTOM_OFFSET + 20;
|
icon_groups.y = height - WorkspaceClone.BOTTOM_OFFSET + 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find active workspace clone and raise it, so there are no overlaps while transitioning
|
// find active workspace clone and raise it, so there are no overlaps while transitioning
|
||||||
@ -265,6 +329,10 @@ namespace Gala
|
|||||||
|
|
||||||
if (!opening) {
|
if (!opening) {
|
||||||
Timeout.add (290, () => {
|
Timeout.add (290, () => {
|
||||||
|
foreach (var container in window_containers_monitors) {
|
||||||
|
container.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
hide ();
|
hide ();
|
||||||
|
|
||||||
wm.background_group.show ();
|
wm.background_group.show ();
|
||||||
|
@ -136,11 +136,9 @@ namespace Gala
|
|||||||
set_child_above_sibling (close_button, clone);
|
set_child_above_sibling (close_button, clone);
|
||||||
set_child_above_sibling (window_icon, clone);
|
set_child_above_sibling (window_icon, clone);
|
||||||
|
|
||||||
|
transition_to_original_state (false);
|
||||||
|
|
||||||
var outer_rect = window.get_outer_rect ();
|
var outer_rect = window.get_outer_rect ();
|
||||||
|
|
||||||
set_position (outer_rect.x, outer_rect.y);
|
|
||||||
set_size (outer_rect.width, outer_rect.height);
|
|
||||||
|
|
||||||
add_effect_with_name ("shadow", new ShadowEffect (outer_rect.width, outer_rect.height, 40, 5));
|
add_effect_with_name ("shadow", new ShadowEffect (outer_rect.width, outer_rect.height, 40, 5));
|
||||||
#if HAS_MUTTER312
|
#if HAS_MUTTER312
|
||||||
window.size_changed.connect (update_shadow_size);
|
window.size_changed.connect (update_shadow_size);
|
||||||
@ -156,6 +154,8 @@ namespace Gala
|
|||||||
opacity = 0;
|
opacity = 0;
|
||||||
take_slot (slot);
|
take_slot (slot);
|
||||||
opacity = 255;
|
opacity = 255;
|
||||||
|
|
||||||
|
request_reposition ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +171,9 @@ namespace Gala
|
|||||||
|
|
||||||
shadow_update_timeout = 0;
|
shadow_update_timeout = 0;
|
||||||
|
|
||||||
|
// if there was a size change it makes sense to recalculate the positions
|
||||||
|
request_reposition ();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -179,10 +182,16 @@ namespace Gala
|
|||||||
{
|
{
|
||||||
var outer_rect = window.get_outer_rect ();
|
var outer_rect = window.get_outer_rect ();
|
||||||
|
|
||||||
|
float offset_x = 0, offset_y = 0;
|
||||||
|
|
||||||
|
var parent = get_parent ();
|
||||||
|
if (parent != null)
|
||||||
|
parent.get_transformed_position (out offset_x, out offset_y);
|
||||||
|
|
||||||
set_easing_mode (AnimationMode.EASE_IN_OUT_CUBIC);
|
set_easing_mode (AnimationMode.EASE_IN_OUT_CUBIC);
|
||||||
set_easing_duration (animate ? 300 : 0);
|
set_easing_duration (animate ? 300 : 0);
|
||||||
|
|
||||||
set_position (outer_rect.x, outer_rect.y);
|
set_position (outer_rect.x - offset_x, outer_rect.y - offset_y);
|
||||||
set_size (outer_rect.width, outer_rect.height);
|
set_size (outer_rect.width, outer_rect.height);
|
||||||
|
|
||||||
window_icon.opacity = 0;
|
window_icon.opacity = 0;
|
||||||
@ -334,7 +343,8 @@ namespace Gala
|
|||||||
|
|
||||||
var icon_group = destination as IconGroup;
|
var icon_group = destination as IconGroup;
|
||||||
|
|
||||||
if (icon_group.workspace == window.get_workspace ())
|
if (icon_group.workspace == window.get_workspace ()
|
||||||
|
&& window.get_monitor () == window.get_screen ().get_primary_monitor ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var scale = hovered ? 0.1 : 0.4;
|
var scale = hovered ? 0.1 : 0.4;
|
||||||
@ -367,15 +377,30 @@ namespace Gala
|
|||||||
workspace = (destination as IconGroup).workspace;
|
workspace = (destination as IconGroup).workspace;
|
||||||
} else if (destination is FramedBackground) {
|
} else if (destination is FramedBackground) {
|
||||||
workspace = (destination.get_parent () as WorkspaceClone).workspace;
|
workspace = (destination.get_parent () as WorkspaceClone).workspace;
|
||||||
|
} else if (destination is MonitorClone) {
|
||||||
|
window.move_to_monitor ((destination as MonitorClone).monitor);
|
||||||
|
unmanaged ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool did_move = false;
|
||||||
|
|
||||||
|
var primary = window.get_screen ().get_primary_monitor ();
|
||||||
|
if (window.get_monitor () != primary) {
|
||||||
|
window.move_to_monitor (primary);
|
||||||
|
did_move = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workspace != null && workspace != window.get_workspace ()) {
|
if (workspace != null && workspace != window.get_workspace ()) {
|
||||||
window.change_workspace (workspace);
|
window.change_workspace (workspace);
|
||||||
|
did_move = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (did_move)
|
||||||
unmanaged ();
|
unmanaged ();
|
||||||
} else {
|
else
|
||||||
// if we're dropped at the place where we came from interpret as cancel
|
// if we're dropped at the place where we came from interpret as cancel
|
||||||
drag_canceled ();
|
drag_canceled ();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drag_canceled ()
|
void drag_canceled ()
|
||||||
@ -401,10 +426,10 @@ namespace Gala
|
|||||||
{
|
{
|
||||||
public signal void window_selected (Meta.Window window);
|
public signal void window_selected (Meta.Window window);
|
||||||
|
|
||||||
public int padding_top { get; set; }
|
public int padding_top { get; set; default = 12; }
|
||||||
public int padding_left { get; set; }
|
public int padding_left { get; set; default = 12; }
|
||||||
public int padding_right { get; set; }
|
public int padding_right { get; set; default = 12; }
|
||||||
public int padding_bottom { get; set; }
|
public int padding_bottom { get; set; default = 12; }
|
||||||
|
|
||||||
HashTable<int,int> _stacking_order;
|
HashTable<int,int> _stacking_order;
|
||||||
public HashTable<int,int> stacking_order {
|
public HashTable<int,int> stacking_order {
|
||||||
@ -502,6 +527,8 @@ namespace Gala
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reflow ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_selected_cb (TiledWindow tiled)
|
void window_selected_cb (TiledWindow tiled)
|
||||||
|
@ -29,10 +29,14 @@ namespace Gala
|
|||||||
*/
|
*/
|
||||||
public bool remove_workspace_immediately { get; set; default = false; }
|
public bool remove_workspace_immediately { get; set; default = false; }
|
||||||
|
|
||||||
|
Gee.LinkedList<Workspace> workspaces_marked_removed;
|
||||||
|
|
||||||
public WorkspaceManager (Screen screen)
|
public WorkspaceManager (Screen screen)
|
||||||
{
|
{
|
||||||
Object (screen: screen);
|
Object (screen: screen);
|
||||||
|
|
||||||
|
workspaces_marked_removed = new Gee.LinkedList<Workspace> ();
|
||||||
|
|
||||||
if (Prefs.get_dynamic_workspaces ())
|
if (Prefs.get_dynamic_workspaces ())
|
||||||
screen.override_workspace_layout (ScreenCorner.TOPLEFT, false, 1, -1);
|
screen.override_workspace_layout (ScreenCorner.TOPLEFT, false, 1, -1);
|
||||||
|
|
||||||
@ -41,8 +45,29 @@ namespace Gala
|
|||||||
|
|
||||||
Prefs.add_listener (prefs_listener);
|
Prefs.add_listener (prefs_listener);
|
||||||
|
|
||||||
screen.workspace_added.connect (workspace_added);
|
|
||||||
screen.workspace_switched.connect_after (workspace_switched);
|
screen.workspace_switched.connect_after (workspace_switched);
|
||||||
|
screen.workspace_added.connect (workspace_added);
|
||||||
|
screen.workspace_removed.connect_after (() => {
|
||||||
|
unowned List<Workspace> existing_workspaces = screen.get_workspaces ();
|
||||||
|
|
||||||
|
var it = workspaces_marked_removed.iterator ();
|
||||||
|
while (it.next ()) {
|
||||||
|
if (existing_workspaces.index (it.@get ()) < 0)
|
||||||
|
it.remove ();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
screen.window_left_monitor.connect ((monitor, window) => {
|
||||||
|
if (InternalUtils.workspaces_only_on_primary ()
|
||||||
|
&& monitor == screen.get_primary_monitor ())
|
||||||
|
window_removed (window.get_workspace (), window);
|
||||||
|
});
|
||||||
|
|
||||||
|
screen.window_entered_monitor.connect ((monitor, window) => {
|
||||||
|
if (InternalUtils.workspaces_only_on_primary ()
|
||||||
|
&& monitor == screen.get_primary_monitor ())
|
||||||
|
window_added (window.get_workspace (), window);
|
||||||
|
});
|
||||||
|
|
||||||
// make sure the last workspace has no windows on it
|
// make sure the last workspace has no windows on it
|
||||||
if (Prefs.get_dynamic_workspaces ()
|
if (Prefs.get_dynamic_workspaces ()
|
||||||
@ -125,23 +150,6 @@ namespace Gala
|
|||||||
// if the last workspace has a window, we need to append a new workspace
|
// if the last workspace has a window, we need to append a new workspace
|
||||||
if (Utils.get_n_windows (screen.get_workspace_by_index (screen.get_n_workspaces () - 1)) > 0)
|
if (Utils.get_n_windows (screen.get_workspace_by_index (screen.get_n_workspaces () - 1)) > 0)
|
||||||
append_workspace ();
|
append_workspace ();
|
||||||
|
|
||||||
} else if ((pref == Preference.DYNAMIC_WORKSPACES
|
|
||||||
|| pref == Preference.NUM_WORKSPACES)
|
|
||||||
&& !Prefs.get_dynamic_workspaces ()) {
|
|
||||||
|
|
||||||
var time = screen.get_display ().get_current_time ();
|
|
||||||
var n_workspaces = screen.get_n_workspaces ();
|
|
||||||
|
|
||||||
/* TODO check if this is still needed
|
|
||||||
// only need to listen for the case when workspaces were removed.
|
|
||||||
// Any other case will be caught by the workspace_added signal.
|
|
||||||
// For some reason workspace_removed is not emitted, when changing the workspace number
|
|
||||||
if (Prefs.get_num_workspaces () < n_workspaces) {
|
|
||||||
for (int i = Prefs.get_num_workspaces () - 1; i < n_workspaces; i++) {
|
|
||||||
screen.remove_workspace (screen.get_workspace_by_index (i), time);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +179,13 @@ namespace Gala
|
|||||||
next.activate (time);
|
next.activate (time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// workspace has already been removed
|
||||||
|
if (workspace in workspaces_marked_removed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaces_marked_removed.add (workspace);
|
||||||
|
|
||||||
screen.remove_workspace (workspace, time);
|
screen.remove_workspace (workspace, time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user