mirror of
https://github.com/elementary/gala.git
synced 2024-09-11 07:05:30 +03:00
Add docs to WindowManager interface, rework modal mode handling API and add functionality to control keybinding filtering
Add interface to properly replace core components.
This commit is contained in:
parent
41de35783b
commit
1e684669fb
@ -1,6 +1,7 @@
|
||||
include $(top_srcdir)/Makefile.common
|
||||
|
||||
libgala_doc_files = \
|
||||
$(top_srcdir)/lib/ActivatableComponent.vala \
|
||||
$(top_srcdir)/lib/Plugin.vala \
|
||||
$(top_srcdir)/lib/Utils.vala \
|
||||
$(top_srcdir)/lib/WindowManager.vala \
|
||||
|
@ -32,6 +32,7 @@ libgala_la_LIBADD = \
|
||||
$(NULL)
|
||||
|
||||
libgala_la_VALASOURCES = \
|
||||
ActivatableComponent.vala \
|
||||
Plugin.vala \
|
||||
Utils.vala \
|
||||
WindowManager.vala \
|
||||
|
@ -29,23 +29,121 @@ namespace Gala
|
||||
WINDOW_OVERVIEW_ALL
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that should return true if the given shortcut should be blocked.
|
||||
*/
|
||||
public delegate bool KeybindingFilter (Meta.KeyBinding binding);
|
||||
|
||||
/**
|
||||
* A minimal class mostly used to identify your call to {@link WindowManager.push_modal} and used
|
||||
* to end your modal mode again with {@link WindowManager.pop_modal}
|
||||
*/
|
||||
public class ModalProxy : Object
|
||||
{
|
||||
/**
|
||||
* A function which is called whenever a keybinding is pressed. If you supply a custom
|
||||
* one you can filter out those that'd you like to be passed through and block all others.
|
||||
* Defaults to blocking all.
|
||||
* @see KeybindingFilter
|
||||
*/
|
||||
public KeybindingFilter? keybinding_filter { get; set; default = () => true; }
|
||||
|
||||
public ModalProxy ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Small utility to allow all keybindings
|
||||
*/
|
||||
public void allow_all_keybindings ()
|
||||
{
|
||||
keybinding_filter = null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface WindowManager : Meta.Plugin
|
||||
{
|
||||
public abstract Clutter.Actor ui_group { get; protected set; }
|
||||
public abstract Clutter.Stage stage { get; protected set; }
|
||||
public abstract Clutter.Actor window_group { get; protected set; }
|
||||
public abstract Clutter.Actor top_window_group { get; protected set; }
|
||||
public abstract Meta.BackgroundGroup background_group { get; protected set; }
|
||||
/**
|
||||
* If true all keybindings will be blocked while modal mode is active.
|
||||
* This is the container you'll most likely want to add your component to. It wraps
|
||||
* every other container listed in this interface and is a direct child of the stage.
|
||||
*/
|
||||
public abstract bool block_keybindings_in_modal { get; set; default = true; }
|
||||
public abstract Clutter.Actor ui_group { get; protected set; }
|
||||
|
||||
public abstract void begin_modal ();
|
||||
public abstract void end_modal ();
|
||||
/**
|
||||
* The stage of the window manager
|
||||
*/
|
||||
public abstract Clutter.Stage stage { get; protected set; }
|
||||
|
||||
/**
|
||||
* A group containting all 'usual' windows
|
||||
* @see top_window_group
|
||||
*/
|
||||
public abstract Clutter.Actor window_group { get; protected set; }
|
||||
|
||||
/**
|
||||
* The top window group contains special windows that are always placed on top
|
||||
* like fullscreen windows.
|
||||
*/
|
||||
public abstract Clutter.Actor top_window_group { get; protected set; }
|
||||
|
||||
/**
|
||||
* The background group is a container for the background actors forming the wallpaper
|
||||
*/
|
||||
public abstract Meta.BackgroundGroup background_group { get; protected set; }
|
||||
|
||||
/**
|
||||
* Enters the modal mode, which means that all events are directed to the stage instead
|
||||
* of the windows. This is the only way to receive keyboard events besides shortcut listeners.
|
||||
*
|
||||
* @return a {@link ModalProxy} which is needed to end the modal mode again and provides some
|
||||
* some basic control on the behavior of the window manager while it is in modal mode.
|
||||
*/
|
||||
public abstract ModalProxy push_modal ();
|
||||
|
||||
/**
|
||||
* May exit the modal mode again, unless another component has called {@link push_modal}
|
||||
*
|
||||
* @param proxy The {@link ModalProxy} received from {@link push_modal}
|
||||
*/
|
||||
public abstract void pop_modal (ModalProxy proxy);
|
||||
|
||||
/**
|
||||
* Returns whether the window manager is currently in modal mode.
|
||||
* @see push_modal
|
||||
*/
|
||||
public abstract bool is_modal ();
|
||||
|
||||
/**
|
||||
* Tests if a given {@link ModalProxy} is valid and may be popped. Should not be necessary
|
||||
* to use this function in most cases, but it may be helpful for debugging. Gala catches
|
||||
* invalid proxies as well and emits a warning in that case.
|
||||
*
|
||||
* @param proxy The {@link ModalProxy} to check
|
||||
* @return Returns true if the prox is valid
|
||||
*/
|
||||
public abstract bool modal_proxy_valid (ModalProxy proxy);
|
||||
|
||||
/**
|
||||
* Tells the window manager to perform the given action.
|
||||
*
|
||||
* @param type The type of action to perform
|
||||
*/
|
||||
public abstract void perform_action (ActionType type);
|
||||
|
||||
/**
|
||||
* Moves the window to the workspace next to its current workspace in the given direction.
|
||||
* Gala currently only supports LEFT and RIGHT.
|
||||
*
|
||||
* @param window The window to be moved
|
||||
* @param direction The direction in which to move the window
|
||||
*/
|
||||
public abstract void move_window (Meta.Window? window, Meta.MotionDirection direction);
|
||||
|
||||
/**
|
||||
* Switches to the next workspace in the given direction.
|
||||
*
|
||||
* @param direction The direction in which to switch
|
||||
*/
|
||||
public abstract void switch_to_next_workspace (Meta.MotionDirection direction);
|
||||
}
|
||||
}
|
||||
|
@ -199,6 +199,11 @@ namespace Gala
|
||||
load_later_plugins.clear ();
|
||||
}
|
||||
|
||||
public Plugin? get_plugin (string id)
|
||||
{
|
||||
return plugins.lookup (id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all plugins and grab their regions, update the regions
|
||||
* array accordingly and emit the regions_changed signal.
|
||||
|
@ -25,7 +25,7 @@ namespace Gala
|
||||
* preparing the wm, opening the components and holds containers for
|
||||
* the icon groups, the WorkspaceClones and the MonitorClones.
|
||||
*/
|
||||
public class MultitaskingView : Actor
|
||||
public class MultitaskingView : Actor, ActivatableComponent
|
||||
{
|
||||
const int HIDING_DURATION = 300;
|
||||
const int SMOOTH_SCROLL_DELAY = 500;
|
||||
@ -33,6 +33,7 @@ namespace Gala
|
||||
public WindowManager wm { get; construct; }
|
||||
|
||||
Meta.Screen screen;
|
||||
ModalProxy modal_proxy;
|
||||
bool opened = false;
|
||||
bool animating = false;
|
||||
|
||||
@ -391,12 +392,42 @@ namespace Gala
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public bool is_opened ()
|
||||
{
|
||||
return opened;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void open (Gee.HashMap<string,GLib.Value?>? hints = null)
|
||||
{
|
||||
if (opened)
|
||||
return;
|
||||
|
||||
toggle ();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void close ()
|
||||
{
|
||||
if (!opened)
|
||||
return;
|
||||
|
||||
toggle ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the view open or closed. Takes care of all the wm related tasks, like
|
||||
* starting the modal mode and hiding the WindowGroup. Finally tells all components
|
||||
* to animate to their positions.
|
||||
*/
|
||||
public void toggle ()
|
||||
void toggle ()
|
||||
{
|
||||
if (animating)
|
||||
return;
|
||||
@ -415,8 +446,8 @@ namespace Gala
|
||||
}
|
||||
|
||||
if (opening) {
|
||||
wm.begin_modal ();
|
||||
wm.block_keybindings_in_modal = false;
|
||||
modal_proxy = wm.push_modal ();
|
||||
modal_proxy.keybinding_filter = keybinding_filter;
|
||||
|
||||
wm.background_group.hide ();
|
||||
wm.window_group.hide ();
|
||||
@ -464,8 +495,7 @@ namespace Gala
|
||||
wm.window_group.show ();
|
||||
wm.top_window_group.show ();
|
||||
|
||||
wm.block_keybindings_in_modal = true;
|
||||
wm.end_modal ();
|
||||
wm.pop_modal (modal_proxy);
|
||||
|
||||
animating = false;
|
||||
|
||||
@ -478,6 +508,19 @@ namespace Gala
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool keybinding_filter (KeyBinding binding)
|
||||
{
|
||||
var action = Prefs.get_keybinding_action (binding.get_name ());
|
||||
switch (action) {
|
||||
case KeyBindingAction.WORKSPACE_LEFT:
|
||||
case KeyBindingAction.WORKSPACE_RIGHT:
|
||||
case KeyBindingAction.SHOW_DESKTOP:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace Gala
|
||||
|
||||
public delegate void WindowPlacer (Actor window, Meta.Rectangle rect);
|
||||
|
||||
public class WindowOverview : Actor
|
||||
public class WindowOverview : Actor, ActivatableComponent
|
||||
{
|
||||
const int BORDER = 10;
|
||||
const int TOP_GAP = 30;
|
||||
@ -39,6 +39,7 @@ namespace Gala
|
||||
|
||||
Meta.Screen screen;
|
||||
|
||||
ModalProxy modal_proxy;
|
||||
bool ready;
|
||||
|
||||
// the workspaces which we expose right now
|
||||
@ -53,7 +54,7 @@ namespace Gala
|
||||
{
|
||||
screen = wm.get_screen ();
|
||||
|
||||
screen.workspace_switched.connect (() => close (false));
|
||||
screen.workspace_switched.connect (close);
|
||||
screen.restacked.connect (restack_windows);
|
||||
|
||||
visible = false;
|
||||
@ -69,7 +70,7 @@ namespace Gala
|
||||
public override bool key_press_event (Clutter.KeyEvent event)
|
||||
{
|
||||
if (event.keyval == Clutter.Key.Escape) {
|
||||
close (true);
|
||||
close ();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -79,27 +80,41 @@ namespace Gala
|
||||
|
||||
public override void key_focus_out ()
|
||||
{
|
||||
close (false);
|
||||
close ();
|
||||
}
|
||||
|
||||
public override bool button_release_event (Clutter.ButtonEvent event)
|
||||
{
|
||||
if (event.button == 1)
|
||||
close (true);
|
||||
close ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void open (bool animate = true, bool all_windows = false)
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public bool is_opened ()
|
||||
{
|
||||
return visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* You may specify 'all-windows' in hints to expose all windows
|
||||
*/
|
||||
public void open (Gee.HashMap<string,GLib.Value?>? hints = null)
|
||||
{
|
||||
if (!ready)
|
||||
return;
|
||||
|
||||
if (visible) {
|
||||
close (true);
|
||||
close ();
|
||||
return;
|
||||
}
|
||||
|
||||
var all_windows = hints != null && hints.has_key ("all-windows");
|
||||
|
||||
var used_windows = new SList<Window> ();
|
||||
|
||||
workspaces = new List<Workspace> ();
|
||||
@ -152,8 +167,8 @@ namespace Gala
|
||||
|
||||
grab_key_focus ();
|
||||
|
||||
wm.block_keybindings_in_modal = false;
|
||||
wm.begin_modal ();
|
||||
modal_proxy = wm.push_modal ();
|
||||
modal_proxy.keybinding_filter = keybinding_filter;
|
||||
|
||||
visible = true;
|
||||
|
||||
@ -189,6 +204,13 @@ namespace Gala
|
||||
ready = true;
|
||||
}
|
||||
|
||||
bool keybinding_filter (KeyBinding binding)
|
||||
{
|
||||
var name = binding.get_name ();
|
||||
return name != "expose-windows"
|
||||
&& name != "expose-all-windows";
|
||||
}
|
||||
|
||||
void restack_windows (Screen screen)
|
||||
{
|
||||
foreach (var child in get_children ())
|
||||
@ -240,9 +262,9 @@ namespace Gala
|
||||
{
|
||||
if (window.get_workspace () == screen.get_active_workspace ()) {
|
||||
window.activate (screen.get_display ().get_current_time ());
|
||||
close (true);
|
||||
close ();
|
||||
} else {
|
||||
close (true);
|
||||
close ();
|
||||
//wait for the animation to finish before switching
|
||||
Timeout.add (400, () => {
|
||||
window.get_workspace ().activate_with_focus (window, screen.get_display ().get_current_time ());
|
||||
@ -251,7 +273,10 @@ namespace Gala
|
||||
}
|
||||
}
|
||||
|
||||
void close (bool animate)
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void close ()
|
||||
{
|
||||
if (!visible || !ready)
|
||||
return;
|
||||
@ -264,21 +289,17 @@ namespace Gala
|
||||
|
||||
ready = false;
|
||||
|
||||
wm.end_modal ();
|
||||
wm.block_keybindings_in_modal = true;
|
||||
wm.pop_modal (modal_proxy);
|
||||
|
||||
foreach (var child in get_children ()) {
|
||||
((WindowCloneContainer) child).close ();
|
||||
}
|
||||
|
||||
if (animate) {
|
||||
Clutter.Threads.Timeout.add (300, () => {
|
||||
cleanup ();
|
||||
|
||||
return false;
|
||||
});
|
||||
} else
|
||||
Clutter.Threads.Timeout.add (300, () => {
|
||||
cleanup ();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void cleanup ()
|
||||
|
@ -38,6 +38,7 @@ namespace Gala
|
||||
BindConstraint h_constraint;
|
||||
|
||||
bool closing = false;
|
||||
ModalProxy modal_proxy;
|
||||
|
||||
//estimated value, if possible
|
||||
float dock_width = 0.0f;
|
||||
@ -167,7 +168,7 @@ namespace Gala
|
||||
current_window = null;
|
||||
}
|
||||
|
||||
wm.end_modal ();
|
||||
wm.pop_modal (modal_proxy);
|
||||
|
||||
dock.animate (AnimationMode.EASE_OUT_CUBIC, 250, width:dest_width, opacity : 0).
|
||||
completed.connect (() => {
|
||||
@ -464,7 +465,7 @@ namespace Gala
|
||||
});
|
||||
|
||||
closing = false;
|
||||
wm.begin_modal ();
|
||||
modal_proxy = wm.push_modal ();
|
||||
|
||||
bool backward = (binding.get_name () == "switch-windows-backward");
|
||||
|
||||
|
@ -21,19 +21,36 @@ namespace Gala
|
||||
{
|
||||
public class WindowManagerGala : Meta.Plugin, WindowManager
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Clutter.Actor ui_group { get; protected set; }
|
||||
public Clutter.Stage stage { get; protected set; }
|
||||
public Clutter.Actor window_group { get; protected set; }
|
||||
public Clutter.Actor top_window_group { get; protected set; }
|
||||
public Meta.BackgroundGroup background_group { get; protected set; }
|
||||
|
||||
public bool block_keybindings_in_modal { get; set; default = true; }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Clutter.Stage stage { get; protected set; }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Clutter.Actor window_group { get; protected set; }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Clutter.Actor top_window_group { get; protected set; }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Meta.BackgroundGroup background_group { get; protected set; }
|
||||
|
||||
Meta.PluginInfo info;
|
||||
|
||||
WindowSwitcher? winswitcher = null;
|
||||
MultitaskingView? workspace_view = null;
|
||||
WindowOverview? window_overview = null;
|
||||
ActivatableComponent? workspace_view = null;
|
||||
ActivatableComponent? window_overview = null;
|
||||
|
||||
// used to detect which corner was used to trigger an action
|
||||
Clutter.Actor? last_hotcorner;
|
||||
@ -41,7 +58,7 @@ namespace Gala
|
||||
|
||||
Window? moving; //place for the window that is being moved over
|
||||
|
||||
int modal_count = 0; //count of modal modes overlaying each other
|
||||
Gee.LinkedList<ModalProxy> modal_stack = new Gee.LinkedList<ModalProxy> ();
|
||||
|
||||
Gee.HashSet<Meta.WindowActor> minimizing = new Gee.HashSet<Meta.WindowActor> ();
|
||||
Gee.HashSet<Meta.WindowActor> maximizing = new Gee.HashSet<Meta.WindowActor> ();
|
||||
@ -203,35 +220,50 @@ namespace Gala
|
||||
|
||||
if (plugin_manager.workspace_view_provider == null) {
|
||||
workspace_view = new MultitaskingView (this);
|
||||
ui_group.add_child (workspace_view);
|
||||
|
||||
KeyBinding.set_custom_handler ("show-desktop", () => {
|
||||
workspace_view.toggle ();
|
||||
});
|
||||
ui_group.add_child ((Clutter.Actor) workspace_view);
|
||||
} else if (plugin_manager.workspace_view_provider is ActivatableComponent) {
|
||||
workspace_view = (ActivatableComponent) plugin_manager.get_plugin (plugin_manager.workspace_view_provider);
|
||||
}
|
||||
|
||||
KeyBinding.set_custom_handler ("show-desktop", () => {
|
||||
if (workspace_view.is_opened ())
|
||||
workspace_view.close ();
|
||||
else
|
||||
workspace_view.open ();
|
||||
});
|
||||
|
||||
if (plugin_manager.window_switcher_provider == null) {
|
||||
winswitcher = new WindowSwitcher (this);
|
||||
ui_group.add_child (winswitcher);
|
||||
|
||||
//FIXME we have to investigate this. Apparently alt-tab is now bound to switch-applications
|
||||
// instead of windows, which we should probably handle too
|
||||
KeyBinding.set_custom_handler ("switch-applications", winswitcher.handle_switch_windows);
|
||||
KeyBinding.set_custom_handler ("switch-applications-backward", winswitcher.handle_switch_windows);
|
||||
}
|
||||
|
||||
if (plugin_manager.window_overview_provider == null) {
|
||||
window_overview = new WindowOverview (this);
|
||||
ui_group.add_child (window_overview);
|
||||
ui_group.add_child ((Clutter.Actor) window_overview);
|
||||
|
||||
screen.get_display ().add_keybinding ("expose-windows", KeybindingSettings.get_default ().schema, 0, () => {
|
||||
window_overview.open (true);
|
||||
});
|
||||
screen.get_display ().add_keybinding ("expose-all-windows", KeybindingSettings.get_default ().schema, 0, () => {
|
||||
window_overview.open (true, true);
|
||||
});
|
||||
} else if (plugin_manager.window_overview_provider is ActivatableComponent) {
|
||||
window_overview = (ActivatableComponent) plugin_manager.get_plugin (plugin_manager.window_overview_provider);
|
||||
}
|
||||
|
||||
screen.get_display ().add_keybinding ("expose-windows", KeybindingSettings.get_default ().schema, 0, () => {
|
||||
if (window_overview.is_opened ())
|
||||
window_overview.close ();
|
||||
else
|
||||
window_overview.open ();
|
||||
});
|
||||
screen.get_display ().add_keybinding ("expose-all-windows", KeybindingSettings.get_default ().schema, 0, () => {
|
||||
if (window_overview.is_opened ())
|
||||
window_overview.close ();
|
||||
else {
|
||||
var hints = new Gee.HashMap<string,GLib.Value?> ();
|
||||
hints.@set ("all-windows", true);
|
||||
window_overview.open (hints);
|
||||
}
|
||||
});
|
||||
|
||||
update_input_area ();
|
||||
|
||||
stage.show ();
|
||||
@ -297,6 +329,9 @@ namespace Gala
|
||||
switch_to_next_workspace (direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void switch_to_next_workspace (MotionDirection direction)
|
||||
{
|
||||
var screen = get_screen ();
|
||||
@ -348,7 +383,7 @@ namespace Gala
|
||||
}
|
||||
}
|
||||
|
||||
if (modal_count > 0)
|
||||
if (is_modal ())
|
||||
InternalUtils.set_input_area (screen, InputArea.FULLSCREEN);
|
||||
else
|
||||
InternalUtils.set_input_area (screen, InputArea.DEFAULT);
|
||||
@ -378,6 +413,9 @@ namespace Gala
|
||||
screen.get_workspace_by_index (index).activate (screen.get_display ().get_current_time ());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void move_window (Window? window, MotionDirection direction)
|
||||
{
|
||||
if (window == null)
|
||||
@ -403,42 +441,69 @@ namespace Gala
|
||||
next.activate_with_focus (window, display.get_current_time ());
|
||||
}
|
||||
|
||||
public new void begin_modal ()
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ModalProxy push_modal ()
|
||||
{
|
||||
modal_count ++;
|
||||
if (modal_count > 1)
|
||||
return;
|
||||
var proxy = new ModalProxy ();
|
||||
|
||||
modal_stack.offer_head (proxy);
|
||||
|
||||
// modal already active
|
||||
if (modal_stack.size > 2)
|
||||
return proxy;
|
||||
|
||||
var screen = get_screen ();
|
||||
var display = screen.get_display ();
|
||||
var time = screen.get_display ().get_current_time ();
|
||||
|
||||
update_input_area ();
|
||||
#if HAS_MUTTER310
|
||||
base.begin_modal (0, display.get_current_time ());
|
||||
begin_modal (0, time);
|
||||
#else
|
||||
base.begin_modal (x_get_stage_window (Compositor.get_stage_for_screen (screen)), {}, 0, display.get_current_time ());
|
||||
begin_modal (x_get_stage_window (Compositor.get_stage_for_screen (screen)), {}, 0, time);
|
||||
#endif
|
||||
|
||||
Meta.Util.disable_unredirect_for_screen (screen);
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
public new void end_modal ()
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void pop_modal (ModalProxy proxy)
|
||||
{
|
||||
modal_count --;
|
||||
if (modal_count > 0)
|
||||
if (!modal_stack.remove (proxy)) {
|
||||
warning ("Attempted to remove a modal proxy that was not in the stack");
|
||||
return;
|
||||
}
|
||||
|
||||
if (modal_stack.size > 0)
|
||||
return;
|
||||
|
||||
update_input_area ();
|
||||
|
||||
var screen = get_screen ();
|
||||
base.end_modal (screen.get_display ().get_current_time ());
|
||||
end_modal (screen.get_display ().get_current_time ());
|
||||
|
||||
Meta.Util.enable_unredirect_for_screen (screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public bool is_modal ()
|
||||
{
|
||||
return (modal_count > 0);
|
||||
return modal_stack.size > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public bool modal_proxy_valid (ModalProxy proxy)
|
||||
{
|
||||
return proxy in modal_stack;
|
||||
}
|
||||
|
||||
public void get_current_cursor_position (out int x, out int y)
|
||||
@ -459,6 +524,9 @@ namespace Gala
|
||||
win.clear_effects ();*/
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void perform_action (ActionType type)
|
||||
{
|
||||
var screen = get_screen ();
|
||||
@ -467,7 +535,13 @@ namespace Gala
|
||||
|
||||
switch (type) {
|
||||
case ActionType.SHOW_WORKSPACE_VIEW:
|
||||
workspace_view.toggle ();
|
||||
if (workspace_view == null)
|
||||
break;
|
||||
|
||||
if (workspace_view.is_opened ())
|
||||
workspace_view.close ();
|
||||
else
|
||||
workspace_view.open ();
|
||||
break;
|
||||
case ActionType.MAXIMIZE_CURRENT:
|
||||
if (current == null || current.window_type != WindowType.NORMAL)
|
||||
@ -518,10 +592,25 @@ namespace Gala
|
||||
}
|
||||
break;
|
||||
case ActionType.WINDOW_OVERVIEW:
|
||||
window_overview.open (true);
|
||||
if (window_overview == null)
|
||||
break;
|
||||
|
||||
if (window_overview.is_opened ())
|
||||
window_overview.close ();
|
||||
else
|
||||
window_overview.open ();
|
||||
break;
|
||||
case ActionType.WINDOW_OVERVIEW_ALL:
|
||||
window_overview.open (true, true);
|
||||
if (window_overview == null)
|
||||
break;
|
||||
|
||||
if (window_overview.is_opened ())
|
||||
window_overview.close ();
|
||||
else {
|
||||
var hints = new Gee.HashMap<string,GLib.Value?> ();
|
||||
hints.@set ("all-windows", true);
|
||||
window_overview.open (hints);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning ("Trying to run unknown action");
|
||||
@ -1149,7 +1238,11 @@ namespace Gala
|
||||
|
||||
public override bool keybinding_filter (Meta.KeyBinding binding)
|
||||
{
|
||||
return block_keybindings_in_modal && modal_count > 0;
|
||||
var modal_proxy = modal_stack.peek_head ();
|
||||
|
||||
return is_modal ()
|
||||
&& modal_proxy.keybinding_filter != null
|
||||
&& modal_proxy.keybinding_filter (binding);
|
||||
}
|
||||
|
||||
#if HAS_MUTTER310
|
||||
|
Loading…
Reference in New Issue
Block a user