diff --git a/data/org.pantheon.desktop.gala.gschema.xml b/data/org.pantheon.desktop.gala.gschema.xml index 4a39efa2..4560a082 100644 --- a/data/org.pantheon.desktop.gala.gschema.xml +++ b/data/org.pantheon.desktop.gala.gschema.xml @@ -15,11 +15,28 @@ - - false - Make the lower right a hot corner to reveal the manager - This turns the lower right corner to a hot corner, showing some icons allowing you to do tasks like window tiling + + + "None" + Action for the top left corner + + + "None" + Action for the top right corner + + + + "None" + Action for the bottom left corner + + + + "None" + Action for the bottom right corner + + + true Enable edge tiling when dropping windows on screen edges diff --git a/src/Actions.vala b/src/Actions.vala index ecea3154..1c4a1756 100644 --- a/src/Actions.vala +++ b/src/Actions.vala @@ -4,16 +4,16 @@ namespace Gala { public enum ActionType { - NONE, - SHOW_WORKSPACE_VIEW, - WORKSPACE_LEFT, - WORKSPACE_RIGHT, - MOVE_TO_WORKSPACE_LEFT, - MOVE_TO_WORKSPACE_RIGHT, - MAXIMIZE_CURRENT, - MINIMIZE_CURRENT, - CLOSE_CURRENT, - OPEN_LAUNCHER + NONE = 0, + SHOW_WORKSPACE_VIEW = 1, + WORKSPACE_LEFT = 2, + WORKSPACE_RIGHT = 3, + MOVE_TO_WORKSPACE_LEFT = 4, + MOVE_TO_WORKSPACE_RIGHT = 5, + MAXIMIZE_CURRENT = 6, + MINIMIZE_CURRENT = 7, + CLOSE_CURRENT = 8, + OPEN_LAUNCHER = 9 } public class Action @@ -22,6 +22,7 @@ namespace Gala { var screen = plugin.get_screen (); var display = screen.get_display (); + var current = display.get_focus_window (); switch (type) { case ActionType.SHOW_WORKSPACE_VIEW: @@ -34,19 +35,26 @@ namespace Gala plugin.workspace_view.switch_to_next_workspace (MotionDirection.RIGHT); break; case ActionType.MOVE_TO_WORKSPACE_LEFT: - plugin.move_window (display.get_focus_window (), MotionDirection.LEFT); + plugin.move_window (current, MotionDirection.LEFT); break; case ActionType.MOVE_TO_WORKSPACE_RIGHT: - plugin.move_window (display.get_focus_window (), MotionDirection.RIGHT); + plugin.move_window (current, MotionDirection.RIGHT); break; case ActionType.MAXIMIZE_CURRENT: - display.get_focus_window ().maximize (MaximizeFlags.HORIZONTAL | MaximizeFlags.VERTICAL); + if (current == null) + break; + if (current.get_maximized () == (MaximizeFlags.HORIZONTAL | MaximizeFlags.VERTICAL)) + current.unmaximize (MaximizeFlags.HORIZONTAL | MaximizeFlags.VERTICAL); + else + current.maximize (MaximizeFlags.HORIZONTAL | MaximizeFlags.VERTICAL); break; case ActionType.MINIMIZE_CURRENT: - display.get_focus_window ().minimize (); + if (current != null) + current.minimize (); break; case ActionType.CLOSE_CURRENT: - display.get_focus_window ().delete (display.get_current_time ()); + if (current != null) + current.delete (display.get_current_time ()); break; case ActionType.OPEN_LAUNCHER: try { diff --git a/src/Plugin.vala b/src/Plugin.vala index 0ef7b761..474042e3 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -116,32 +116,60 @@ namespace Gala Utils.reload_shadow (); ShadowSettings.get_default ().notify.connect (Utils.reload_shadow); - /*hot corner*/ + /*hot corner, getting enum values from GraniteServicesSettings did not work, so we use GSettings directly*/ var geometry = screen.get_monitor_geometry (screen.get_primary_monitor ()); - var hot_corner = new Clutter.Rectangle (); - hot_corner.x = geometry.x + geometry.width - 1; - hot_corner.y = geometry.y + geometry.height - 1; + var top_left = create_hotcorner (geometry.x, geometry.y); + top_left.enter_event.connect (() => { + Action.run (this, (ActionType)BehaviorSettings.get_default ().schema.get_enum ("hotcorner-topleft")); + return false; + }); + var top_right = create_hotcorner (geometry.x + geometry.width - 1, geometry.y); + top_right.enter_event.connect (() => { + Action.run (this, (ActionType)BehaviorSettings.get_default ().schema.get_enum ("hotcorner-topright")); + return false; + }); + var bottom_left = create_hotcorner (geometry.x, geometry.y + geometry.height - 1); + bottom_left.enter_event.connect (() => { + Action.run (this, (ActionType)BehaviorSettings.get_default ().schema.get_enum ("hotcorner-bottomleft")); + return false; + }); + var bottom_right = create_hotcorner (geometry.x + geometry.width - 1, geometry.y + geometry.height - 1); + bottom_right.enter_event.connect (() => { + Action.run (this, (ActionType)BehaviorSettings.get_default ().schema.get_enum ("hotcorner-bottomright")); + return false; + }); + + update_input_area (); + + BehaviorSettings.get_default ().notify["hotcorner-topleft"].connect (update_input_area); + BehaviorSettings.get_default ().notify["hotcorner-topright"].connect (update_input_area); + BehaviorSettings.get_default ().notify["hotcorner-bottomleft"].connect (update_input_area); + BehaviorSettings.get_default ().notify["hotcorner-bottomright"].connect (update_input_area); + BehaviorSettings.get_default ().schema.changed.connect ((key) => update_input_area ()); + } + + Clutter.Actor create_hotcorner (float x, float y) + { + var hot_corner = new Clutter.Actor (); + hot_corner.x = x; + hot_corner.y = y; hot_corner.width = 1; hot_corner.height = 1; hot_corner.opacity = 0; hot_corner.reactive = true; - hot_corner.enter_event.connect (() => { - workspace_view.show (); - return false; - }); + Compositor.get_stage_for_screen (get_screen ()).add_child (hot_corner); - stage.add_child (hot_corner); - - update_input_area (); - - BehaviorSettings.get_default ().notify["enable-manager-corner"].connect (update_input_area); + return hot_corner; } public void update_input_area () { - if (BehaviorSettings.get_default ().enable_manager_corner) + if (BehaviorSettings.get_default ().schema.get_enum ("hotcorner-topleft") != ActionType.NONE || + BehaviorSettings.get_default ().schema.get_enum ("hotcorner-topright") != ActionType.NONE || + BehaviorSettings.get_default ().schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE || + BehaviorSettings.get_default ().schema.get_enum ("hotcorner-bottomright") != ActionType.NONE) Utils.set_input_area (get_screen (), Utils.InputArea.HOT_CORNER); else Utils.set_input_area (get_screen (), Utils.InputArea.NONE); diff --git a/src/Settings.vala b/src/Settings.vala index 32257ed7..2fda1535 100644 --- a/src/Settings.vala +++ b/src/Settings.vala @@ -23,7 +23,11 @@ namespace Gala public string panel_main_menu_action { get; set; } public string toggle_recording_action { get; set; } public string overlay_action { get; set; } - public bool enable_manager_corner { get; set; } + + public ActionType hotcorner_topleft { get; set; } + public ActionType hotcorner_topright { get; set; } + public ActionType hotcorner_bottomleft { get; set; } + public ActionType hotcorner_bottomright { get; set; } static BehaviorSettings? instance = null; diff --git a/src/Utils.vala b/src/Utils.vala index 69a8fb3b..fb4806bc 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -105,24 +105,35 @@ namespace Gala.Utils { var display = screen.get_display (); - X.Xrectangle rect; + X.Xrectangle[] rects; int width, height; screen.get_size (out width, out height); var geometry = screen.get_monitor_geometry (screen.get_primary_monitor ()); switch (area) { case InputArea.FULLSCREEN: - rect = {0, 0, (ushort)width, (ushort)height}; + X.Xrectangle rect = {0, 0, (ushort)width, (ushort)height}; + rects = {rect}; break; - case InputArea.HOT_CORNER: //leave one pix in the bottom left - rect = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), 1, 1}; + case InputArea.HOT_CORNER: //if action type is none, make them 0 sized + short tl_size = (BehaviorSettings.get_default ().schema.get_enum ("hotcorner-topleft") != ActionType.NONE)?1:0; + short tr_size = (BehaviorSettings.get_default ().schema.get_enum ("hotcorner-topright") != ActionType.NONE)?1:0; + short bl_size = (BehaviorSettings.get_default ().schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE)?1:0; + short br_size = (BehaviorSettings.get_default ().schema.get_enum ("hotcorner-bottomright") != ActionType.NONE)?1:0; + + X.Xrectangle topleft = {(short)geometry.x, (short)geometry.y, tl_size, tl_size}; + X.Xrectangle topright = {(short)(geometry.x + geometry.width - 1), (short)geometry.y, tr_size, tr_size}; + X.Xrectangle bottomleft = {(short)geometry.x, (short)(geometry.y + geometry.height - 1), bl_size, bl_size}; + X.Xrectangle bottomright = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), br_size, br_size}; + + rects = {topleft, topright, bottomleft, bottomright}; break; default: Util.empty_stage_input_region (screen); return; } - var xregion = X.Fixes.create_region (display.get_xdisplay (), {rect}); + var xregion = X.Fixes.create_region (display.get_xdisplay (), rects); Util.set_stage_input_region (screen, xregion); }