diff --git a/src/ItemManager.vala b/src/ItemManager.vala index f48074d4..7e616182 100644 --- a/src/ItemManager.vala +++ b/src/ItemManager.vala @@ -11,6 +11,7 @@ #if WORKSPACE_SWITCHER private Gtk.Separator separator; private DynamicWorkspaceIcon dynamic_workspace_item; + private Gtk.Revealer workspaces_scrollbar_revealer; #endif static construct { @@ -20,6 +21,12 @@ construct { var app_group = new ItemGroup (AppSystem.get_default ().apps, (obj) => new Launcher ((App) obj)); + var app_group_scrolled = new Gtk.ScrolledWindow () { + child = app_group, + vscrollbar_policy = NEVER, + propagate_natural_width = true + }; + var background_item = new BackgroundItem (); var background_group = new ItemGroup (background_item.group_model, (obj) => (BackgroundItem) obj); @@ -33,14 +40,47 @@ separator_box.append (new TopMargin ()); separator_box.append (separator); + var workspace_group_scrolled = new Gtk.ScrolledWindow () { + child = new ItemGroup (WorkspaceSystem.get_default ().workspaces, (obj) => new WorkspaceIconGroup ((Workspace) obj)), + hscrollbar_policy = EXTERNAL, + vscrollbar_policy = NEVER, + propagate_natural_width = true + }; + + /* + * Gtk.ScrolledWindow with scrollbar policy set to ALWAYS or AUTOMATIC reserves ~30px of space for scrollbar + * And it doesn't matter if the scrollbar is shown or not, the space is always reserved. + * Essentially, by default workspace_group_scrolled's minimum size is 30px, to avoid this + * we set scrollbar policy to EXTERNAL and handle scrollbar ourselves. + */ + + var workspaces_scrollbar = new Gtk.Scrollbar (HORIZONTAL, workspace_group_scrolled.hadjustment) { + vexpand = false, + valign = END + }; + + workspaces_scrollbar_revealer = new Gtk.Revealer () { + child = workspaces_scrollbar, + vexpand = false, + valign = END + }; + + update_workspaces_scrollbar_revealer (workspace_group_scrolled.hadjustment); + workspace_group_scrolled.hadjustment.changed.connect (update_workspaces_scrollbar_revealer); + + var scrollbar_overlay = new Gtk.Overlay () { + child = workspace_group_scrolled + }; + scrollbar_overlay.add_overlay (workspaces_scrollbar_revealer); + dynamic_workspace_item = new DynamicWorkspaceIcon (); #endif - append (app_group); + append (app_group_scrolled); append (background_group); #if WORKSPACE_SWITCHER append (separator_box); - append (new ItemGroup (WorkspaceSystem.get_default ().workspaces, (obj) => new WorkspaceIconGroup ((Workspace) obj))); + append (scrollbar_overlay); append (dynamic_workspace_item); #endif overflow = VISIBLE; @@ -160,4 +200,8 @@ warning ("Tried to move neither launcher nor icon group"); } } + + private void update_workspaces_scrollbar_revealer (Gtk.Adjustment adjustment) { + workspaces_scrollbar_revealer.reveal_child = adjustment.upper - adjustment.lower > adjustment.page_size; + } } diff --git a/src/MainWindow.vala b/src/MainWindow.vala index f54a6dcc..aa8dfe35 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -188,4 +188,34 @@ public class Dock.MainWindow : Gtk.ApplicationWindow { xdisplay.change_property (window, prop, X.XA_STRING, 8, 0, (uchar[]) value, value.length); } } + + public override void measure ( + Gtk.Orientation orientation, + int for_size, + out int minimum, + out int natural, + out int minimum_baseline, + out int natural_baseline + ) { + if (orientation != HORIZONTAL) { + base.measure (orientation, for_size, out minimum, out natural, out minimum_baseline, out natural_baseline); + return; + } + + minimum = minimum_baseline = natural_baseline = -1; + + var monitor_width = int.MAX; + unowned var surface = get_surface (); + if (surface != null) { + unowned var monitor = Gdk.Display.get_default ().get_monitor_at_surface (surface); + if (monitor != null) { + monitor_width = monitor.geometry.width; + } + } + + int item_manager_natural_width; + item_manager.measure (HORIZONTAL, -1, null, out item_manager_natural_width, null, null); + + natural = int.min (item_manager_natural_width, monitor_width - 2 * BottomMargin.get_size ()); + } }