diff --git a/wingpanel/schemas/io.elementary.desktop.wingpanel.gschema.xml b/wingpanel-qq/schemas/io.elementary.desktop.wingpanel.gschema.xml index c81abd5..890e277 100644 --- a/wingpanel/schemas/io.elementary.desktop.wingpanel.gschema.xml +++ b/wingpanel-qq/schemas/io.elementary.desktop.wingpanel.gschema.xml @@ -6,5 +6,23 @@ Sets if the panel uses transparency. Disable this to provide higher contrasts and make indicators better readable. + + + + + + + + + 'Disabled' + Sets if and how the panel will autohide. + Enable this to increase available desktop area and reduce clutter. + + + + 200 + Sets how long before the panel will autohide in milliseconds. + Increase or decrease this value to your preference. + diff --git a/wingpanel/src/PanelWindow.vala b/wingpanel-qq/src/PanelWindow.vala index c48b5ea..81ec2f2 100644 --- a/wingpanel/src/PanelWindow.vala +++ b/wingpanel-qq/src/PanelWindow.vala @@ -21,6 +21,9 @@ public class Wingpanel.PanelWindow : Gtk.Window { public Services.PopoverManager popover_manager; private Widgets.Panel panel; + + uint timeout; + private int monitor_number; private int monitor_width; private int monitor_height; @@ -30,6 +33,11 @@ public class Wingpanel.PanelWindow : Gtk.Window { private bool expanded = false; private int panel_displacement; private uint shrink_timeout = 0; + private bool hiding = false; + private bool strut = true; + private string autohide = Services.PanelSettings.get_default ().autohide; + private int autohide_delay = Services.PanelSettings.get_default ().delay; + private Wnck.Screen wnck_screen = Wnck.Screen.get_default (); public PanelWindow (Gtk.Application application) { Object ( @@ -71,17 +79,40 @@ public class Wingpanel.PanelWindow : Gtk.Window { application.add_accelerator ("Tab", "app.cycle", null); application.add_accelerator ("Tab", "app.cycle-back", null); + Services.PanelSettings.get_default ().notify["autohide"].connect (() => { + autohide = Services.PanelSettings.get_default ().autohide; + update_autohide_mode (); + }); + + Services.PanelSettings.get_default ().notify["delay"].connect (() => { + autohide_delay = Services.PanelSettings.get_default ().delay; + }); + add (panel); } private bool animation_step () { - if (panel_displacement <= panel_height * (-1)) { - return false; + if (hiding) { + if (panel_displacement >= -1 || popover_manager.current_indicator != null) { + timeout = 0; + if (strut == true) { + update_panel_dimensions (); + } + return false; + } + panel_displacement++; + } else { + if (panel_displacement <= panel_height * (-1)) { + timeout = 0; + if (strut == true) { + update_panel_dimensions (); + } + return false; + } + panel_displacement--; } - panel_displacement--; - - update_panel_dimensions (); + animate_panel (); return true; } @@ -91,7 +115,174 @@ public class Wingpanel.PanelWindow : Gtk.Window { Services.BackgroundManager.initialize (this.monitor_number, panel_height); - Timeout.add (300 / panel_height, animation_step); + update_autohide_mode (); + } + + private void active_window_changed (Wnck.Window? prev_active_window) { + unowned Wnck.Window? active_window = wnck_screen.get_active_window(); + if (autohide == "Dodge" || autohide == "Dodge-Float") + update_visibility_active_change (active_window); + + if (prev_active_window != null) + prev_active_window.state_changed.disconnect (active_window_state_changed); + if (active_window != null) + active_window.state_changed.connect (active_window_state_changed); + } + + private void active_workspace_changed (Wnck.Workspace? prev_active_workspace) { + unowned Wnck.Window? active_window = wnck_screen.get_active_window(); + if (autohide == "Dodge" || autohide == "Dodge-Float") + update_visibility_active_change (active_window); + } + + private void viewports_changed (Wnck.Screen? screen) { + unowned Wnck.Window? active_window = wnck_screen.get_active_window(); + if (autohide == "Dodge" || autohide == "Dodge-Float") + update_visibility_active_change (active_window); + } + + private void active_window_state_changed (Wnck.Window? window, + Wnck.WindowState changed_mask, Wnck.WindowState new_state) { + if (autohide == "Dodge" || autohide == "Dodge-Float") + update_visibility_active_change (window); + } + + private void update_visibility_active_change (Wnck.Window? active_window) { + if (should_hide_active_change (active_window)) { + hide_panel (); + } else { + show_panel (); + } + } + + private bool should_hide_active_change (Wnck.Window? active_window) { + unowned Wnck.Workspace active_workspace = wnck_screen.get_active_workspace (); + + return ((active_window != null) && !active_window.is_minimized () && right_type (active_window) + && active_window.is_visible_on_workspace (active_workspace) + && active_window.is_in_viewport (active_workspace) + && (active_window.get_window_type () == Wnck.WindowType.DIALOG) ? + would_intersect_shown_panel (active_window) : + (in_panel_x_range (active_window) && is_maximized_at_all (active_window))); + } + + private bool would_intersect_shown_panel (Wnck.Window? window) { + Gdk.Rectangle shown_panel_rect = Gdk.Rectangle (); + shown_panel_rect.x = monitor_x; + shown_panel_rect.y = monitor_y; + shown_panel_rect.width = monitor_width; + shown_panel_rect.height = panel_height; + + int xp, yp, widthp, heightp; + window.get_geometry (out xp, out yp, out widthp, out heightp); + + Gdk.Rectangle window_rect = Gdk.Rectangle (); + window_rect.x = xp; + window_rect.width = widthp; + if (strut && is_maximized_at_all (window)) { + window_rect.y = yp - panel_height; + window_rect.height = heightp + panel_height; + } else { + window_rect.y = yp; + window_rect.height = heightp; + } + + return window_rect.intersect (shown_panel_rect, null); + } + + private bool in_panel_x_range (Wnck.Window? window) { + int xp, yp, widthp, heightp; + window.get_geometry (out xp, out yp, out widthp, out heightp); + if (xp > monitor_x) + return (monitor_x + monitor_width > xp); + else if (xp < monitor_x) + return (xp + widthp > monitor_x); + else + return (xp + widthp > 0 && monitor_x + monitor_width > 0); + } + + private bool right_type (Wnck.Window? active_window) { + unowned Wnck.WindowType type = active_window.get_window_type (); + return (type == Wnck.WindowType.NORMAL || type == Wnck.WindowType.DIALOG + || type == Wnck.WindowType.TOOLBAR || type == Wnck.WindowType.UTILITY); + } + + private bool is_maximized_at_all (Wnck.Window window) { + return (window.is_maximized_horizontally () + || window.is_maximized_vertically () + || window.is_fullscreen ()); + } + + private bool hide_panel () { + if (timeout > 0) { + Source.remove (timeout); + } + if (autohide == "Dodge" || autohide == "Dodge-Float") { + if (!should_hide_active_change (wnck_screen.get_active_window())) { + return true; + } + } + if (popover_manager.current_indicator == null) { + Thread.usleep (autohide_delay * 1000); + } + strut = true; + hiding = true; + timeout = Timeout.add (100 / panel_height, animation_step); + return true; + } + + private bool show_panel () { + if (timeout > 0) { + Source.remove (timeout); + } + if (popover_manager.current_indicator == null && autohide != "Disabled") { + Thread.usleep (autohide_delay * 1000); + } + if (autohide == "Dodge-Float" || autohide == "Float") { + strut = false; + } else { + strut = true; + } + hiding = false; + if (autohide == "Disabled") { + timeout = Timeout.add (300 / panel_height, animation_step); + } else { + timeout = Timeout.add (100 / panel_height, animation_step); + } + return true; + } + + private void update_autohide_mode () { + switch (autohide) { + case "Disabled": + this.enter_notify_event.disconnect (show_panel); + this.motion_notify_event.disconnect (show_panel); + this.leave_notify_event.disconnect (hide_panel); + wnck_screen.active_window_changed.disconnect (active_window_changed); + wnck_screen.active_workspace_changed.disconnect (active_workspace_changed); + wnck_screen.viewports_changed.disconnect (viewports_changed); + show_panel (); + break; + case "Dodge": + case "Dodge-Float": + this.enter_notify_event.connect (show_panel); + this.motion_notify_event.connect (show_panel); + this.leave_notify_event.connect (hide_panel); + wnck_screen.active_window_changed.connect (active_window_changed); + wnck_screen.active_workspace_changed.connect (active_workspace_changed); + wnck_screen.viewports_changed.connect (viewports_changed); + show_panel (); + break; + default: + this.enter_notify_event.connect (show_panel); + this.motion_notify_event.connect (show_panel); + this.leave_notify_event.connect (hide_panel); + wnck_screen.active_window_changed.disconnect (active_window_changed); + wnck_screen.active_workspace_changed.disconnect (active_workspace_changed); + wnck_screen.viewports_changed.disconnect (viewports_changed); + hide_panel (); + break; + } } private void update_panel_dimensions () { @@ -114,6 +196,24 @@ public class Wingpanel.PanelWindow : Gtk.Window { update_struts (); } + private void animate_panel () { + panel_height = panel.get_allocated_height (); + + monitor_number = screen.get_primary_monitor (); + Gdk.Rectangle monitor_dimensions; + this.screen.get_monitor_geometry (monitor_number, out monitor_dimensions); + + monitor_width = monitor_dimensions.width; + monitor_height = monitor_dimensions.height; + + this.set_size_request (monitor_width, (popover_manager.current_indicator != null ? monitor_height : -1)); + + monitor_x = monitor_dimensions.x; + monitor_y = monitor_dimensions.y; + + this.move (monitor_x, monitor_y - (panel_height + panel_displacement)); + } + private void update_visual () { var visual = this.screen.get_rgba_visual (); diff --git a/wingpanel/src/Services/Settings.vala b/wingpanel-qq/src/Services/Settings.vala index 3bcd0a7..eeecbb8 100644 --- a/wingpanel/src/Services/Settings.vala +++ b/wingpanel-qq/src/Services/Settings.vala @@ -23,6 +23,10 @@ namespace Wingpanel.Services { public bool use_transparency { get; set; } + public string autohide { get; set; } + + public int delay { get; set; } + public PanelSettings () { base ("io.elementary.desktop.wingpanel"); } --- src/wingpanel/CMakeLists.txt~ 2018-09-17 00:14:55.430071710 +0900 +++ src/wingpanel/CMakeLists.txt 2018-09-17 00:34:08.600075830 +0900 @@ -76,6 +76,7 @@ gee-0.8 gmodule-2.0 gtk+-3.0 + libwnck-3.0 ) set (LIB_PKG @@ -84,11 +85,15 @@ gee-0.8 gmodule-2.0 gtk+-3.0>=3.22 + libwnck-3.0>=3.24 ) find_package(PkgConfig) pkg_check_modules (LIB REQUIRED ${LIB_PKG}) +add_definitions (-DWNCK_I_KNOW_THIS_IS_UNSTABLE ${WNCK_CFLAGS}) +link_libraries (${WNCK_LIBRARIES}) + set (GLOBAL_VALAC_OPTIONS --vapidir=${CMAKE_BINARY_DIR}/lib --vapidir=vapi diff --git a/.travis.yml b/.travis.yml index dddddf1..4efb6c0 100644 --- src/wingpanel/.travis.yml +++ src/wingpanel/.travis.yml @@ -4,7 +4,7 @@ services: - docker env: - - DEPENDENCY_PACKAGES="cmake libgala-dev libgee-0.8-dev libgirepository1.0-dev libglib2.0-dev libgranite-dev libgtk-3-dev valac" + - DEPENDENCY_PACKAGES="cmake libgala-dev libgee-0.8-dev libgirepository1.0-dev libglib2.0-dev libgranite-dev libgtk-3-dev libwnck-3-dev valac" install: - docker pull elementary/docker:juno-unstable