Skip to content
Draft
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
4 changes: 4 additions & 0 deletions data/Application.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ bottom-margin {
min-height: 9px;
}

horizontal-margin {
min-width: 9px;
}

launcher {
padding: 6px;
padding-bottom: 0px;
Expand Down
2 changes: 2 additions & 0 deletions src/BaseItem.vala
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ public class Dock.BaseItem : Gtk.Box {
public void calculate_dnd_move (BaseItem source, double x, double y) {
var launcher_manager = ItemManager.get_default ();
launcher_manager.move_launcher_after (source, (int) get_index ());
var workspace_manager = WorkspaceManager.get_default ();
workspace_manager.move_launcher_after (source, (int) get_index ());
}

private bool on_drop (Value val) {
Expand Down
30 changes: 30 additions & 0 deletions src/HorizontalMargin.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-License-Identifier: GPL-3.0
* SPDX-FileCopyrightText: 2026 elementary, Inc. (https://elementary.io)
*/

public class HorizontalMargin : Gtk.Widget {
private static GLib.List<unowned HorizontalMargin> instances = new GLib.List<unowned HorizontalMargin> ();

class construct {
set_css_name ("horizontal-margin");
}

construct {
instances.append (this);
}

~HorizontalMargin () {
instances.remove (this);
}

public new static int get_size () {
foreach (var instance in instances) {
if (instance.get_realized ()) {
return instance.get_width ();
}
}

return 0;
}
}
27 changes: 2 additions & 25 deletions src/ItemManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@

private DynamicWorkspaceIcon dynamic_workspace_item;

#if WORKSPACE_SWITCHER
private Gtk.Separator separator;
#endif

static construct {
settings = new Settings ("io.elementary.dock");
}
Expand All @@ -29,23 +25,9 @@
var background_item = new BackgroundItem ();
var background_group = new ItemGroup (background_item.group_model, (obj) => (BackgroundItem) obj);

#if WORKSPACE_SWITCHER
dynamic_workspace_item = new DynamicWorkspaceIcon ();

separator = new Gtk.Separator (VERTICAL) {
valign = START,
margin_top = Launcher.PADDING,
};
settings.bind ("icon-size", separator, "height-request", GET);
#endif

append (app_group);
append (background_group);
#if WORKSPACE_SWITCHER
append (separator);
append (new ItemGroup (WorkspaceSystem.get_default ().workspaces, (obj) => new WorkspaceIconGroup ((Workspace) obj)));
append (dynamic_workspace_item);
#endif

overflow = VISIBLE;

var drop_target_file = new Gtk.DropTarget (typeof (File), COPY) {
Expand Down Expand Up @@ -148,19 +130,14 @@
map.connect (() => {
AppSystem.get_default ().load.begin ();
background_item.load ();
#if WORKSPACE_SWITCHER
WorkspaceSystem.get_default ().load.begin ();
#endif
});
}

public void move_launcher_after (BaseItem source, int target_index) {
if (source is Launcher) {
AppSystem.get_default ().reorder_app (source.app, target_index);
} else if (source is WorkspaceIconGroup) {
WorkspaceSystem.get_default ().reorder_workspace (source.workspace, target_index);
} else {
warning ("Tried to move neither launcher nor icon group");
info ("Tried to move not a launcher");
}
}

Expand Down
62 changes: 45 additions & 17 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,47 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
resizable = false;
titlebar = new Gtk.Label ("") { visible = false };

var dock_box = new Gtk.Box (VERTICAL, 0);
dock_box.append (new Container ());
dock_box.append (new BottomMargin ());
/* Launcher */

var launcher_container = new Gtk.Box (VERTICAL, 0);
launcher_container.append (new Container ());
launcher_container.append (new BottomMargin ());

// // Don't clip launchers to dock background https://github.com/elementary/dock/issues/275
var launcher_overlay = new Gtk.Overlay () {
child = launcher_container
};
unowned var launcher_manager = ItemManager.get_default ();
launcher_overlay.add_overlay (launcher_manager);

var launcher_size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.BOTH);
launcher_size_group.add_widget (launcher_container);
launcher_size_group.add_widget (launcher_manager);

/* Workspace */

var workspace_manager = WorkspaceManager.get_default ();
var workspace_container = new Gtk.Box (VERTICAL, 0);
workspace_container.append (new Container ());
workspace_container.append (new BottomMargin ());

// Don't clip launchers to dock background https://github.com/elementary/dock/issues/275
var overlay = new Gtk.Overlay () {
child = dock_box
var workspace_overlay = new Gtk.Overlay () {
child = workspace_container
};
overlay.add_overlay (launcher_manager);
workspace_overlay.add_overlay (workspace_manager);

var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.BOTH);
size_group.add_widget (dock_box);
size_group.add_widget (launcher_manager);
var workspace_size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.BOTH);
workspace_size_group.add_widget (workspace_container);
workspace_size_group.add_widget (workspace_manager);

child = overlay;
/* Full dock */

var docks_box = new Gtk.Box (HORIZONTAL, 0);
docks_box.append (launcher_overlay);
docks_box.append (new HorizontalMargin ());
docks_box.append (workspace_overlay);

child = docks_box;

remove_css_class ("background");

Expand Down Expand Up @@ -85,7 +109,6 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
remove_css_class ("reduce-transparency");
} else {
add_css_class ("reduce-transparency");

}
}

Expand Down Expand Up @@ -113,7 +136,9 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
// manually set shadow width since the additional margin we add to avoid icons clipping when
// bouncing isn't added by default and instead counts to the frame
var item_manager_width = ItemManager.get_default ().get_width ();
var shadow_size = (surface.width - item_manager_width) / 2;
var hztl_margin_width = HorizontalMargin.get_size ();
var workspace_manager_width = WorkspaceManager.get_default ().get_width ();
var shadow_size = (surface.width - item_manager_width - hztl_margin_width - workspace_manager_width) / 2;
var top_margin = TOP_MARGIN + shadow_size - 1;
size.set_shadow_width (shadow_size, shadow_size, top_margin, shadow_size);
});
Expand All @@ -122,12 +147,14 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
// manually set input region since container's shadow are is the content of the window
// and it still gets window events
var item_manager_width = ItemManager.get_default ().get_width ();
var shadow_size = (width - item_manager_width) / 2;
var hztl_margin_width = HorizontalMargin.get_size ();
var workspace_manager_width = WorkspaceManager.get_default ().get_width ();
var shadow_size = (width - item_manager_width - hztl_margin_width - workspace_manager_width) / 2;
var top_margin = TOP_MARGIN + shadow_size;
surface.set_input_region (new Cairo.Region.rectangle ({
shadow_size,
top_margin,
item_manager_width,
item_manager_width + workspace_manager_width,
height - top_margin
}));

Expand All @@ -148,6 +175,7 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {

if (panel != null) {
panel.add_blur (0, 0, 0, BottomMargin.get_size (), border_radius);

} else {
update_panel_x11 ();
}
Expand All @@ -159,8 +187,8 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
unowned var wl_display = ((Gdk.Wayland.Display) display).get_wl_display ();
var wl_registry = wl_display.get_registry ();
wl_registry.add_listener (
registry_listener,
this
registry_listener,
this
);

if (wl_display.roundtrip () < 0) {
Expand Down
74 changes: 74 additions & 0 deletions src/WorkspaceManager.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* SPDX-License-Identifier: GPL-3.0
* SPDX-FileCopyrightText: 2026 elementary, Inc. (https://elementary.io)
*/

public class Dock.WorkspaceManager : Gtk.Box {
private static Settings settings;

private static GLib.Once<WorkspaceManager> instance;
public static unowned WorkspaceManager get_default () {
return instance.once (() => { return new WorkspaceManager (); });
}

private DynamicWorkspaceIcon dynamic_workspace_item;

static construct {
settings = new Settings ("io.elementary.dock");
}

construct {
dynamic_workspace_item = new DynamicWorkspaceIcon ();

append (new ItemGroup (WorkspaceSystem.get_default ().workspaces, (obj) => new WorkspaceIconGroup ((Workspace) obj)));
append (dynamic_workspace_item);

overflow = VISIBLE;

var drop_target_file = new Gtk.DropTarget (typeof (File), COPY) {
preload = true
};
add_controller (drop_target_file);

double drop_x, drop_y;
drop_target_file.enter.connect ((x, y) => {
drop_x = x;
drop_y = y;
return COPY;
});

drop_target_file.notify["value"].connect (() => {
if (drop_target_file.get_value () == null) {
return;
}

if (drop_target_file.get_value ().get_object () == null) {
return;
}

if (!(drop_target_file.get_value ().get_object () is File)) {
return;
}

var file = (File) drop_target_file.get_value ().get_object ();
var app_info = new DesktopAppInfo.from_filename (file.get_path ());

if (app_info == null) {
return;
}
});

map.connect (() => {
WorkspaceSystem.get_default ().load.begin ();
});
}

public void move_launcher_after (BaseItem source, int target_index) {
if (source is WorkspaceIconGroup) {
WorkspaceSystem.get_default ().reorder_workspace (source.workspace, target_index);
} else {
info ("Tried to move not an icon group");
return;
}
}
}
2 changes: 2 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ sources = [
'BaseIconGroup.vala',
'BaseItem.vala',
'BottomMargin.vala',
'HorizontalMargin.vala',
'ContainerItem.vala',
'ItemGroup.vala',
'ItemManager.vala',
'WorkspaceManager.vala',
'MainWindow.vala',
'RenderNodeWalker.vala',
'AppSystem' / 'App.vala',
Expand Down