diff --git a/lib/ActivatableComponent.vala b/lib/ActivatableComponent.vala
index c7b41600e..96ba987a6 100644
--- a/lib/ActivatableComponent.vala
+++ b/lib/ActivatableComponent.vala
@@ -15,37 +15,34 @@
// along with this program. If not, see .
//
-namespace Gala
-{
- /**
- * Implement this interface on your {@link Plugin} class if you want to
- * replace a component like the window overview or the multitasking view.
- * It allows gala to hook up functionality like hotcorners and dbus
- * invocation of your component.
- */
- public interface ActivatableComponent : Object
- {
- /**
- * The component was requested to be opened.
- *
- * @param hints The hashmap may contain special parameters that are useful
- * to the component. Currently, the only one implemented is the
- * 'all-windows' hint to the windowoverview.
- */
- public abstract void open (HashTable? hints = null);
+namespace Gala {
+ /**
+ * Implement this interface on your {@link Plugin} class if you want to
+ * replace a component like the window overview or the multitasking view.
+ * It allows gala to hook up functionality like hotcorners and dbus
+ * invocation of your component.
+ */
+ public interface ActivatableComponent : Object {
+ /**
+ * The component was requested to be opened.
+ *
+ * @param hints The hashmap may contain special parameters that are useful
+ * to the component. Currently, the only one implemented is the
+ * 'all-windows' hint to the windowoverview.
+ */
+ public abstract void open (HashTable? hints = null);
- /**
- * The component was requested to be closed.
- */
- public abstract void close ();
+ /**
+ * The component was requested to be closed.
+ */
+ public abstract void close ();
- /**
- * Should return whether the component is currently opened. Used mainly for
- * toggling by the window manager.
- *
- * @return Return true if the component is opened.
- */
- public abstract bool is_opened ();
- }
+ /**
+ * Should return whether the component is currently opened. Used mainly for
+ * toggling by the window manager.
+ *
+ * @return Return true if the component is opened.
+ */
+ public abstract bool is_opened ();
+ }
}
-
diff --git a/lib/Constants.vala b/lib/Constants.vala
index 995d1910f..3057ead30 100644
--- a/lib/Constants.vala
+++ b/lib/Constants.vala
@@ -15,21 +15,20 @@
// along with this program. If not, see .
//
-namespace Gala
-{
- [CCode (has_type_id = false)]
- public enum AnimationDuration {
- // Duration of the open animation
- OPEN = 350,
- // Duration of the close animation
- CLOSE = 195,
- // Duration of the minimize animation
- MINIMIZE = 200,
- // Duration of the menu mapping animation
- MENU_MAP = 150,
- // Duration of the snap animation as used by maximize/unmaximize
- SNAP = 250,
- // Duration of the workspace switch animation
- WORKSPACE_SWITCH = 300,
- }
+namespace Gala {
+ [CCode (has_type_id = false)]
+ public enum AnimationDuration {
+ // Duration of the open animation
+ OPEN = 350,
+ // Duration of the close animation
+ CLOSE = 195,
+ // Duration of the minimize animation
+ MINIMIZE = 200,
+ // Duration of the menu mapping animation
+ MENU_MAP = 150,
+ // Duration of the snap animation as used by maximize/unmaximize
+ SNAP = 250,
+ // Duration of the workspace switch animation
+ WORKSPACE_SWITCH = 300,
+ }
}
diff --git a/lib/Plugin.vala b/lib/Plugin.vala
index 9fb815456..1b3e95fd9 100644
--- a/lib/Plugin.vala
+++ b/lib/Plugin.vala
@@ -15,206 +15,196 @@
// along with this program. If not, see .
//
-namespace Gala
-{
- public enum PluginFunction
- {
- ADDITION,
- WINDOW_SWITCHER,
- DESKTOP,
- WORKSPACE_VIEW,
- WINDOW_OVERVIEW
- }
-
- public enum LoadPriority
- {
- /**
- * Have your plugin loaded immediately once gala has started
- */
- IMMEDIATE,
- /**
- * Allow gala to defer loading your plugin once it got the
- * major part of the initialization done
- */
- DEFERRED
- }
-
- public struct PluginInfo
- {
- string name;
- string author;
-
- /**
- * Type of your plugin class, has to be derived from the Plugin class.
- */
- Type plugin_type;
-
- /**
- * This property allows you to override default functionality of gala
- * so systems won't be instantiated next to each other. Use
- * PluginFunction.ADDITION if no special component is overridden.
- */
- PluginFunction provides;
-
- /**
- * Give gala a hint for when to load your plugin. Especially use DEFERRED
- * if you're adding a completely new ui component that's not directly
- * related to the wm.
- */
- LoadPriority load_priority;
-
- /**
- * You don't have to fill this field, it will be filled by gala with
- * the filename in which your module was found.
- */
- string module_name;
- }
-
- /**
- * This class has to be implemented by every plugin.
- * Additionally, the plugin module is required to have a register_plugin
- * function which returns a PluginInfo struct.
- * The plugin_type field has to be the type of your plugin class derived
- * from this class.
- */
- public abstract class Plugin : Object
- {
- /**
- * Emitted when update_region is called. Mainly for internal purposes.
- */
- public signal void region_changed ();
-
- /**
- * The region indicates an area where mouse events should be sent to
- * the stage, which means your actors, instead of the windows.
- *
- * It is calculated by the system whenever update_region is called.
- * You can influce it with the custom_region and the track_actor function.
- */
- public Meta.Rectangle[] region { get; private set; }
-
- /**
- * This list will be merged with the region property. See region for
- * more details. Changing this property will cause update_region to be
- * called. Default to null.
- */
- protected Meta.Rectangle[]? custom_region {
- get {
- return _custom_region;
- }
- protected set {
- _custom_region = value;
- update_region ();
- }
- }
-
- /**
- * Set this property to true while animating an actor if you have tracked
- * actors to prevent constant recalculations of the regions during an
- * animation.
- */
- protected bool freeze_track {
- get {
- return _freeze_track;
- }
- set {
- _freeze_track = value;
-
- if (!_freeze_track)
- update_region ();
- }
- }
-
- private bool _freeze_track = false;
- private Meta.Rectangle[]? _custom_region = null;
- private List tracked_actors = new List ();
-
- /**
- * Once this method is called you can start adding actors to the stage
- * via the windowmanager instance that is given to you.
- *
- * @param wm The window manager.
- */
- public abstract void initialize (WindowManager wm);
-
- /**
- * This method is currently not called in the code, however you should
- * still implement it to be compatible whenever we decide to use it.
- * It should make sure that everything your plugin added to the stage
- * is cleaned up.
- */
- public abstract void destroy ();
-
- /**
- * Listen to changes to the allocation of actor and update the region
- * accordingly. You may add multiple actors, their shapes will be
- * combined when one of them changes.
- *
- * @param actor The actor to be tracked
- */
- public void track_actor (Clutter.Actor actor)
- {
- tracked_actors.prepend (actor);
- actor.allocation_changed.connect (actor_allocation_changed);
-
- update_region ();
- }
-
- /**
- * Stop listening to allocation changes and remove the actor's
- * allocation from the region array.
- *
- * @param actor The actor to stop listening the changes on
- */
- public void untrack_actor (Clutter.Actor actor)
- {
- tracked_actors.remove (actor);
- actor.allocation_changed.disconnect (actor_allocation_changed);
- }
-
- /**
- * You can call this method to force the system to update the region that
- * is used by the window manager. It will automatically upon changes to
- * the custom_region property and when a tracked actor's allocation changes
- * unless freeze_track is set to true. You may need to call this function
- * after setting freeze_track back to false after an animation to make the
- * wm aware of the new position of the actor in question.
- */
- public void update_region ()
- {
- var has_custom = custom_region != null;
- var len = tracked_actors.length () + (has_custom ? custom_region.length : 0);
-
- Meta.Rectangle[] regions = new Meta.Rectangle[len];
- var i = 0;
-
- if (has_custom) {
- for (var j = 0; j < custom_region.length; j++) {
- regions[i++] = custom_region[j];
- }
- }
-
- foreach (var actor in tracked_actors) {
- float x, y, w, h;
- actor.get_transformed_position (out x, out y);
- actor.get_transformed_size (out w, out h);
-
- if (w == 0 || h == 0)
- continue;
-
- regions[i++] = { (int) x, (int) y, (int) w, (int) h };
- }
-
- region = regions;
-
- region_changed ();
- }
-
- private void actor_allocation_changed (Clutter.ActorBox box, Clutter.AllocationFlags f)
- {
- if (!freeze_track)
- update_region ();
- }
- }
+namespace Gala {
+ public enum PluginFunction {
+ ADDITION,
+ WINDOW_SWITCHER,
+ DESKTOP,
+ WORKSPACE_VIEW,
+ WINDOW_OVERVIEW
+ }
+
+ public enum LoadPriority {
+ /**
+ * Have your plugin loaded immediately once gala has started
+ */
+ IMMEDIATE,
+ /**
+ * Allow gala to defer loading your plugin once it got the
+ * major part of the initialization done
+ */
+ DEFERRED
+ }
+
+ public struct PluginInfo {
+ string name;
+ string author;
+
+ /**
+ * Type of your plugin class, has to be derived from the Plugin class.
+ */
+ Type plugin_type;
+
+ /**
+ * This property allows you to override default functionality of gala
+ * so systems won't be instantiated next to each other. Use
+ * PluginFunction.ADDITION if no special component is overridden.
+ */
+ PluginFunction provides;
+
+ /**
+ * Give gala a hint for when to load your plugin. Especially use DEFERRED
+ * if you're adding a completely new ui component that's not directly
+ * related to the wm.
+ */
+ LoadPriority load_priority;
+
+ /**
+ * You don't have to fill this field, it will be filled by gala with
+ * the filename in which your module was found.
+ */
+ string module_name;
+ }
+
+ /**
+ * This class has to be implemented by every plugin.
+ * Additionally, the plugin module is required to have a register_plugin
+ * function which returns a PluginInfo struct.
+ * The plugin_type field has to be the type of your plugin class derived
+ * from this class.
+ */
+ public abstract class Plugin : Object {
+ /**
+ * Emitted when update_region is called. Mainly for internal purposes.
+ */
+ public signal void region_changed ();
+
+ /**
+ * The region indicates an area where mouse events should be sent to
+ * the stage, which means your actors, instead of the windows.
+ *
+ * It is calculated by the system whenever update_region is called.
+ * You can influce it with the custom_region and the track_actor function.
+ */
+ public Meta.Rectangle[] region { get; private set; }
+
+ /**
+ * This list will be merged with the region property. See region for
+ * more details. Changing this property will cause update_region to be
+ * called. Default to null.
+ */
+ protected Meta.Rectangle[]? custom_region {
+ get {
+ return _custom_region;
+ }
+ protected set {
+ _custom_region = value;
+ update_region ();
+ }
+ }
+
+ /**
+ * Set this property to true while animating an actor if you have tracked
+ * actors to prevent constant recalculations of the regions during an
+ * animation.
+ */
+ protected bool freeze_track {
+ get {
+ return _freeze_track;
+ }
+ set {
+ _freeze_track = value;
+
+ if (!_freeze_track)
+ update_region ();
+ }
+ }
+
+ private bool _freeze_track = false;
+ private Meta.Rectangle[]? _custom_region = null;
+ private List tracked_actors = new List ();
+
+ /**
+ * Once this method is called you can start adding actors to the stage
+ * via the windowmanager instance that is given to you.
+ *
+ * @param wm The window manager.
+ */
+ public abstract void initialize (WindowManager wm);
+
+ /**
+ * This method is currently not called in the code, however you should
+ * still implement it to be compatible whenever we decide to use it.
+ * It should make sure that everything your plugin added to the stage
+ * is cleaned up.
+ */
+ public abstract void destroy ();
+
+ /**
+ * Listen to changes to the allocation of actor and update the region
+ * accordingly. You may add multiple actors, their shapes will be
+ * combined when one of them changes.
+ *
+ * @param actor The actor to be tracked
+ */
+ public void track_actor (Clutter.Actor actor) {
+ tracked_actors.prepend (actor);
+ actor.allocation_changed.connect (actor_allocation_changed);
+
+ update_region ();
+ }
+
+ /**
+ * Stop listening to allocation changes and remove the actor's
+ * allocation from the region array.
+ *
+ * @param actor The actor to stop listening the changes on
+ */
+ public void untrack_actor (Clutter.Actor actor) {
+ tracked_actors.remove (actor);
+ actor.allocation_changed.disconnect (actor_allocation_changed);
+ }
+
+ /**
+ * You can call this method to force the system to update the region that
+ * is used by the window manager. It will automatically upon changes to
+ * the custom_region property and when a tracked actor's allocation changes
+ * unless freeze_track is set to true. You may need to call this function
+ * after setting freeze_track back to false after an animation to make the
+ * wm aware of the new position of the actor in question.
+ */
+ public void update_region () {
+ var has_custom = custom_region != null;
+ var len = tracked_actors.length () + (has_custom ? custom_region.length : 0);
+
+ Meta.Rectangle[] regions = new Meta.Rectangle[len];
+ var i = 0;
+
+ if (has_custom) {
+ for (var j = 0; j < custom_region.length; j++) {
+ regions[i++] = custom_region[j];
+ }
+ }
+
+ foreach (var actor in tracked_actors) {
+ float x, y, w, h;
+ actor.get_transformed_position (out x, out y);
+ actor.get_transformed_size (out w, out h);
+
+ if (w == 0 || h == 0)
+ continue;
+
+ regions[i++] = { (int) x, (int) y, (int) w, (int) h };
+ }
+
+ region = regions;
+
+ region_changed ();
+ }
+
+ private void actor_allocation_changed (Clutter.ActorBox box, Clutter.AllocationFlags f) {
+ if (!freeze_track)
+ update_region ();
+ }
+ }
}
-
diff --git a/lib/Utils.vala b/lib/Utils.vala
index ec6ff7ca1..0a05aff50 100644
--- a/lib/Utils.vala
+++ b/lib/Utils.vala
@@ -15,387 +15,392 @@
// along with this program. If not, see .
//
-namespace Gala
-{
- public class Utils
- {
- // Cache xid:pixbuf and icon:pixbuf pairs to provide a faster way aquiring icons
- static HashTable xid_pixbuf_cache;
- static HashTable icon_pixbuf_cache;
- static uint cache_clear_timeout = 0;
-
- static Gdk.Pixbuf? close_pixbuf = null;
- static Gdk.Pixbuf? resize_pixbuf = null;
-
- static construct
- {
- xid_pixbuf_cache = new HashTable (str_hash, str_equal);
- icon_pixbuf_cache = new HashTable (str_hash, str_equal);
- }
-
- Utils ()
- {
- }
-
- /**
- * Clean icon caches
- */
- static void clean_icon_cache (uint32[] xids)
- {
- var list = xid_pixbuf_cache.get_keys ();
- var pixbuf_list = icon_pixbuf_cache.get_values ();
- var icon_list = icon_pixbuf_cache.get_keys ();
-
- foreach (var xid_key in list) {
- var xid = (uint32)uint64.parse (xid_key.split ("::")[0]);
- if (!(xid in xids)) {
- var pixbuf = xid_pixbuf_cache.get (xid_key);
- for (var j = 0; j < pixbuf_list.length (); j++) {
- if (pixbuf_list.nth_data (j) == pixbuf) {
- xid_pixbuf_cache.remove (icon_list.nth_data (j));
- }
- }
-
- xid_pixbuf_cache.remove (xid_key);
- }
- }
- }
-
- /**
- * Marks the given xids as no longer needed, the corresponding icons
- * may be freed now. Mainly for internal purposes.
- *
- * @param xids The xids of the window that no longer need icons
- */
- public static void request_clean_icon_cache (uint32[] xids)
- {
- if (cache_clear_timeout > 0)
- GLib.Source.remove (cache_clear_timeout);
-
- cache_clear_timeout = Timeout.add_seconds (30, () => {
- cache_clear_timeout = 0;
- Idle.add (() => {
- clean_icon_cache (xids);
- return false;
- });
- return false;
- });
- }
-
- /**
- * Returns a pixbuf for the application of this window or a default icon
- *
- * @param window The window to get an icon for
- * @param size The size of the icon
- * @param scale The desired scale of the icon
- * @param ignore_cache Should not be necessary in most cases, if you care about the icon
- * being loaded correctly, you should consider using the WindowIcon class
- */
- public static Gdk.Pixbuf get_icon_for_window (Meta.Window window, int size, int scale = 1, bool ignore_cache = false)
- {
- return get_icon_for_xid ((uint32)window.get_xwindow (), size, scale, ignore_cache);
- }
-
- /**
- * Returns a pixbuf for a given xid or a default icon
- *
- * @see get_icon_for_window
- */
- public static Gdk.Pixbuf get_icon_for_xid (uint32 xid, int size, int scale = 1, bool ignore_cache = false)
- {
- Gdk.Pixbuf? result = null;
- var xid_key = "%u::%i".printf (xid, size);
-
- if (!ignore_cache && (result = xid_pixbuf_cache.get (xid_key)) != null)
- return result;
-
- var app = Bamf.Matcher.get_default ().get_application_for_xid (xid);
- result = get_icon_for_application (app, size, scale, ignore_cache);
-
- xid_pixbuf_cache.set (xid_key, result);
-
- return result;
- }
-
- /**
- * Returns a pixbuf for this application or a default icon
- *
- * @see get_icon_for_window
- */
- static Gdk.Pixbuf get_icon_for_application (Bamf.Application? app, int size, int scale = 1,
- bool ignore_cache = false)
- {
- Gdk.Pixbuf? image = null;
- bool not_cached = false;
-
- string? icon = null;
- string? icon_key = null;
-
- if (app != null && app.get_desktop_file () != null) {
- var appinfo = new DesktopAppInfo.from_filename (app.get_desktop_file ());
- if (appinfo != null) {
- icon = Plank.DrawingService.get_icon_from_gicon (appinfo.get_icon ());
- icon_key = "%s::%i::%i".printf (icon, size, scale);
- if (ignore_cache || (image = icon_pixbuf_cache.get (icon_key)) == null) {
- var scaled_size = size * scale;
- var surface = Plank.DrawingService.load_icon_for_scale (icon, scaled_size, scaled_size, scale);
- image = Gdk.pixbuf_get_from_surface (surface, 0, 0, scaled_size, scaled_size);
- not_cached = true;
- }
- }
- }
-
- if (image == null) {
- try {
- unowned Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
- icon = "application-default-icon";
- icon_key = "%s::%i::%i".printf (icon, size, scale);
- if ((image = icon_pixbuf_cache.get (icon_key)) == null) {
- image = icon_theme.load_icon_for_scale (icon, size, scale, 0);
- not_cached = true;
- }
- } catch (Error e) {
- warning (e.message);
- }
- }
-
- if (image == null) {
- icon = "";
- icon_key = "::%i".printf (size);
- if ((image = icon_pixbuf_cache.get (icon_key)) == null) {
- image = new Gdk.Pixbuf (Gdk.Colorspace.RGB, true, 8, size, size);
- image.fill (0x00000000);
- not_cached = true;
- }
- }
-
- if (size * scale != image.width || size * scale != image.height)
- image = Plank.DrawingService.ar_scale (image, size * scale, size * scale);
-
- if (not_cached)
- icon_pixbuf_cache.set (icon_key, image);
-
- return image;
- }
-
- /**
- * Get the next window that should be active on a workspace right now. Based on
- * stacking order
- *
- * @param workspace The workspace on which to find the window
- * @param backward Whether to get the previous one instead
- */
- public static Meta.Window get_next_window (Meta.Workspace workspace, bool backward = false)
- {
- var screen = workspace.get_screen ();
- var display = screen.get_display ();
-
- var window = display.get_tab_next (Meta.TabList.NORMAL,
- workspace, null, backward);
-
- if (window == null)
- window = display.get_tab_current (Meta.TabList.NORMAL, workspace);
-
- return window;
- }
-
- /**
- * Get the number of toplevel windows on a workspace excluding those that are
- * on all workspaces
- *
- * @param workspace The workspace on which to count the windows
- */
- public static uint get_n_windows (Meta.Workspace workspace)
- {
- var n = 0;
- foreach (weak Meta.Window window in workspace.list_windows ()) {
- if (window.on_all_workspaces)
- continue;
- if (window.window_type == Meta.WindowType.NORMAL ||
- window.window_type == Meta.WindowType.DIALOG ||
- window.window_type == Meta.WindowType.MODAL_DIALOG)
- n ++;
- }
-
- return n;
- }
-
- /**
- * Creates an actor showing the current contents of the given WindowActor.
- *
- * @param actor The actor from which to create a shnapshot
- * @param inner_rect The inner (actually visible) rectangle of the window
- * @param outer_rect The outer (input region) rectangle of the window
- *
- * @return A copy of the actor at that time or %NULL
- */
- public static Clutter.Actor? get_window_actor_snapshot (Meta.WindowActor actor, Meta.Rectangle inner_rect, Meta.Rectangle outer_rect)
- {
- var texture = actor.get_texture () as Meta.ShapedTexture;
-
- if (texture == null)
- return null;
-
- var surface = texture.get_image ({
- inner_rect.x - outer_rect.x,
- inner_rect.y - outer_rect.y,
- inner_rect.width,
- inner_rect.height
- });
-
- if (surface == null)
- return null;
-
- var canvas = new Clutter.Canvas ();
- var handler = canvas.draw.connect ((cr) => {
- cr.set_source_surface (surface, 0, 0);
- cr.paint ();
- return false;
- });
- canvas.set_size (inner_rect.width, inner_rect.height);
- SignalHandler.disconnect (canvas, handler);
-
- var container = new Clutter.Actor ();
- container.set_size (inner_rect.width, inner_rect.height);
- container.content = canvas;
-
- return container;
- }
-
- /**
- * Ring the system bell, will most likely emit a error sound or, if the
- * audible bell is disabled, flash the screen
- *
- * @param screen The screen to flash, if necessary
- */
- public static void bell (Meta.Screen screen)
- {
- if (Meta.Prefs.bell_is_audible ())
- Gdk.beep ();
- else
- screen.get_display ().get_compositor ().flash_screen (screen);
- }
-
- public static int get_ui_scaling_factor ()
- {
+namespace Gala {
+ public class Utils {
+ // Cache xid:pixbuf and icon:pixbuf pairs to provide a faster way aquiring icons
+ static HashTable xid_pixbuf_cache;
+ static HashTable icon_pixbuf_cache;
+ static uint cache_clear_timeout = 0;
+
+ static Gdk.Pixbuf? close_pixbuf = null;
+ static Gdk.Pixbuf? resize_pixbuf = null;
+
+ static construct {
+ xid_pixbuf_cache = new HashTable (str_hash, str_equal);
+ icon_pixbuf_cache = new HashTable (str_hash, str_equal);
+ }
+
+ Utils () {
+ }
+
+ /**
+ * Clean icon caches
+ */
+ static void clean_icon_cache (uint32[] xids) {
+ var list = xid_pixbuf_cache.get_keys ();
+ var pixbuf_list = icon_pixbuf_cache.get_values ();
+ var icon_list = icon_pixbuf_cache.get_keys ();
+
+ foreach (var xid_key in list) {
+ var xid = (uint32)uint64.parse (xid_key.split ("::")[0]);
+ if (!(xid in xids)) {
+ var pixbuf = xid_pixbuf_cache.get (xid_key);
+ for (var j = 0; j < pixbuf_list.length (); j++) {
+ if (pixbuf_list.nth_data (j) == pixbuf) {
+ xid_pixbuf_cache.remove (icon_list.nth_data (j));
+ }
+ }
+
+ xid_pixbuf_cache.remove (xid_key);
+ }
+ }
+ }
+
+ /**
+ * Marks the given xids as no longer needed, the corresponding icons
+ * may be freed now. Mainly for internal purposes.
+ *
+ * @param xids The xids of the window that no longer need icons
+ */
+ public static void request_clean_icon_cache (uint32[] xids) {
+ if (cache_clear_timeout > 0)
+ GLib.Source.remove (cache_clear_timeout);
+
+ cache_clear_timeout = Timeout.add_seconds (30, () => {
+ cache_clear_timeout = 0;
+ Idle.add (() => {
+ clean_icon_cache (xids);
+ return false;
+ });
+ return false;
+ });
+ }
+
+ /**
+ * Returns a pixbuf for the application of this window or a default icon
+ *
+ * @param window The window to get an icon for
+ * @param size The size of the icon
+ * @param scale The desired scale of the icon
+ * @param ignore_cache Should not be necessary in most cases, if you care about the icon
+ * being loaded correctly, you should consider using the WindowIcon class
+ */
+ public static Gdk.Pixbuf get_icon_for_window (
+ Meta.Window window,
+ int size,
+ int scale = 1,
+ bool ignore_cache = false
+ ) {
+ return get_icon_for_xid ((uint32)window.get_xwindow (), size, scale, ignore_cache);
+ }
+
+ /**
+ * Returns a pixbuf for a given xid or a default icon
+ *
+ * @see get_icon_for_window
+ */
+ public static Gdk.Pixbuf get_icon_for_xid (uint32 xid, int size, int scale = 1, bool ignore_cache = false) {
+ Gdk.Pixbuf? result = null;
+ var xid_key = "%u::%i".printf (xid, size);
+
+ if (!ignore_cache && (result = xid_pixbuf_cache.get (xid_key)) != null)
+ return result;
+
+ var app = Bamf.Matcher.get_default ().get_application_for_xid (xid);
+ result = get_icon_for_application (app, size, scale, ignore_cache);
+
+ xid_pixbuf_cache.set (xid_key, result);
+
+ return result;
+ }
+
+ /**
+ * Returns a pixbuf for this application or a default icon
+ *
+ * @see get_icon_for_window
+ */
+ static Gdk.Pixbuf get_icon_for_application (
+ Bamf.Application? app,
+ int size,
+ int scale = 1,
+ bool ignore_cache = false
+ ) {
+ Gdk.Pixbuf? image = null;
+ bool not_cached = false;
+
+ string? icon = null;
+ string? icon_key = null;
+
+ if (app != null && app.get_desktop_file () != null) {
+ var appinfo = new DesktopAppInfo.from_filename (app.get_desktop_file ());
+ if (appinfo != null) {
+ icon = Plank.DrawingService.get_icon_from_gicon (appinfo.get_icon ());
+ icon_key = "%s::%i::%i".printf (icon, size, scale);
+ if (ignore_cache || (image = icon_pixbuf_cache.get (icon_key)) == null) {
+ var scaled_size = size * scale;
+ var surface = Plank.DrawingService.load_icon_for_scale (icon, scaled_size, scaled_size, scale);
+ image = Gdk.pixbuf_get_from_surface (surface, 0, 0, scaled_size, scaled_size);
+ not_cached = true;
+ }
+ }
+ }
+
+ if (image == null) {
+ try {
+ unowned Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
+ icon = "application-default-icon";
+ icon_key = "%s::%i::%i".printf (icon, size, scale);
+ if ((image = icon_pixbuf_cache.get (icon_key)) == null) {
+ image = icon_theme.load_icon_for_scale (icon, size, scale, 0);
+ not_cached = true;
+ }
+ } catch (Error e) {
+ warning (e.message);
+ }
+ }
+
+ if (image == null) {
+ icon = "";
+ icon_key = "::%i".printf (size);
+ if ((image = icon_pixbuf_cache.get (icon_key)) == null) {
+ image = new Gdk.Pixbuf (Gdk.Colorspace.RGB, true, 8, size, size);
+ image.fill (0x00000000);
+ not_cached = true;
+ }
+ }
+
+ if (size * scale != image.width || size * scale != image.height)
+ image = Plank.DrawingService.ar_scale (image, size * scale, size * scale);
+
+ if (not_cached)
+ icon_pixbuf_cache.set (icon_key, image);
+
+ return image;
+ }
+
+ /**
+ * Get the next window that should be active on a workspace right now. Based on
+ * stacking order
+ *
+ * @param workspace The workspace on which to find the window
+ * @param backward Whether to get the previous one instead
+ */
+ public static Meta.Window get_next_window (Meta.Workspace workspace, bool backward = false) {
+ var screen = workspace.get_screen ();
+ var display = screen.get_display ();
+
+ var window = display.get_tab_next (Meta.TabList.NORMAL,
+ workspace, null, backward);
+
+ if (window == null)
+ window = display.get_tab_current (Meta.TabList.NORMAL, workspace);
+
+ return window;
+ }
+
+ /**
+ * Get the number of toplevel windows on a workspace excluding those that are
+ * on all workspaces
+ *
+ * @param workspace The workspace on which to count the windows
+ */
+ public static uint get_n_windows (Meta.Workspace workspace) {
+ var n = 0;
+ foreach (weak Meta.Window window in workspace.list_windows ()) {
+ if (window.on_all_workspaces)
+ continue;
+ if (
+ window.window_type == Meta.WindowType.NORMAL ||
+ window.window_type == Meta.WindowType.DIALOG ||
+ window.window_type == Meta.WindowType.MODAL_DIALOG)
+ n ++;
+ }
+
+ return n;
+ }
+
+ /**
+ * Creates an actor showing the current contents of the given WindowActor.
+ *
+ * @param actor The actor from which to create a shnapshot
+ * @param inner_rect The inner (actually visible) rectangle of the window
+ * @param outer_rect The outer (input region) rectangle of the window
+ *
+ * @return A copy of the actor at that time or %NULL
+ */
+ public static Clutter.Actor? get_window_actor_snapshot (
+ Meta.WindowActor actor,
+ Meta.Rectangle inner_rect,
+ Meta.Rectangle outer_rect
+ ) {
+ var texture = actor.get_texture () as Meta.ShapedTexture;
+
+ if (texture == null)
+ return null;
+
+ var surface = texture.get_image ({
+ inner_rect.x - outer_rect.x,
+ inner_rect.y - outer_rect.y,
+ inner_rect.width,
+ inner_rect.height
+ });
+
+ if (surface == null)
+ return null;
+
+ var canvas = new Clutter.Canvas ();
+ var handler = canvas.draw.connect ((cr) => {
+ cr.set_source_surface (surface, 0, 0);
+ cr.paint ();
+ return false;
+ });
+ canvas.set_size (inner_rect.width, inner_rect.height);
+ SignalHandler.disconnect (canvas, handler);
+
+ var container = new Clutter.Actor ();
+ container.set_size (inner_rect.width, inner_rect.height);
+ container.content = canvas;
+
+ return container;
+ }
+
+ /**
+ * Ring the system bell, will most likely emit a error sound or, if the
+ * audible bell is disabled, flash the screen
+ *
+ * @param screen The screen to flash, if necessary
+ */
+ public static void bell (Meta.Screen screen) {
+ if (Meta.Prefs.bell_is_audible ())
+ Gdk.beep ();
+ else
+ screen.get_display ().get_compositor ().flash_screen (screen);
+ }
+
+ public static int get_ui_scaling_factor () {
#if HAS_MUTTER326
- return Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
+ return Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
- return 1;
+ return 1;
#endif
- }
-
- /**
- * Returns the pixbuf that is used for close buttons throughout gala at a
- * size of 36px
- *
- * @return the close button pixbuf or null if it failed to load
- */
- public static Gdk.Pixbuf? get_close_button_pixbuf ()
- {
- var height = 36 * Utils.get_ui_scaling_factor ();
- if (close_pixbuf == null || close_pixbuf.height != height) {
- try {
- close_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (Config.RESOURCEPATH + "/buttons/close.svg", -1, height, true);
- } catch (Error e) {
- warning (e.message);
- return null;
- }
- }
-
- return close_pixbuf;
- }
-
- /**
- * Creates a new reactive ClutterActor at 36px with the close pixbuf
- *
- * @return The close button actor
- */
- public static Clutter.Actor create_close_button ()
- {
- var texture = new Clutter.Texture ();
- var pixbuf = get_close_button_pixbuf ();
-
- texture.reactive = true;
-
- if (pixbuf != null) {
- try {
- texture.set_from_rgb_data (pixbuf.get_pixels (), pixbuf.get_has_alpha (),
- pixbuf.get_width (), pixbuf.get_height (),
- pixbuf.get_rowstride (), (pixbuf.get_has_alpha () ? 4 : 3), 0);
- } catch (Error e) {}
- } else {
- // we'll just make this red so there's at least something as an
- // indicator that loading failed. Should never happen and this
- // works as good as some weird fallback-image-failed-to-load pixbuf
- var scale = Utils.get_ui_scaling_factor ();
- texture.set_size (36 * scale, 36 * scale);
- texture.background_color = { 255, 0, 0, 255 };
- }
-
- return texture;
- }
- /**
- * Returns the pixbuf that is used for resize buttons throughout gala at a
- * size of 36px
- *
- * @return the close button pixbuf or null if it failed to load
- */
- public static Gdk.Pixbuf? get_resize_button_pixbuf ()
- {
- var height = 36 * Utils.get_ui_scaling_factor ();
- if (resize_pixbuf == null || resize_pixbuf.height != height) {
- var scale = Utils.get_ui_scaling_factor ();
- try {
- resize_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (Config.RESOURCEPATH + "/buttons/resize.svg", -1, height, true);
- } catch (Error e) {
- warning (e.message);
- return null;
- }
- }
-
- return resize_pixbuf;
- }
-
- /**
- * Creates a new reactive ClutterActor at 36px with the resize pixbuf
- *
- * @return The resize button actor
- */
- public static Clutter.Actor create_resize_button ()
- {
- var texture = new Clutter.Texture ();
- var pixbuf = get_resize_button_pixbuf ();
-
- texture.reactive = true;
-
- if (pixbuf != null) {
- try {
- texture.set_from_rgb_data (pixbuf.get_pixels (), pixbuf.get_has_alpha (),
- pixbuf.get_width (), pixbuf.get_height (),
- pixbuf.get_rowstride (), (pixbuf.get_has_alpha () ? 4 : 3), 0);
- } catch (Error e) {}
- } else {
- // we'll just make this red so there's at least something as an
- // indicator that loading failed. Should never happen and this
- // works as good as some weird fallback-image-failed-to-load pixbuf
- var scale = Utils.get_ui_scaling_factor ();
- texture.set_size (36 * scale, 36 * scale);
- texture.background_color = { 255, 0, 0, 255 };
- }
-
- return texture;
- }
-
- static Gtk.CssProvider gala_css = null;
- public static unowned Gtk.CssProvider? get_gala_css ()
- {
- if (gala_css == null) {
- gala_css = new Gtk.CssProvider ();
- gala_css.load_from_resource ("/io/elementary/desktop/gala/gala.css");
- }
-
- return gala_css;
- }
- }
+ }
+
+ /**
+ * Returns the pixbuf that is used for close buttons throughout gala at a
+ * size of 36px
+ *
+ * @return the close button pixbuf or null if it failed to load
+ */
+ public static Gdk.Pixbuf? get_close_button_pixbuf () {
+ var height = 36 * Utils.get_ui_scaling_factor ();
+ if (close_pixbuf == null || close_pixbuf.height != height) {
+ try {
+ close_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (
+ Config.RESOURCEPATH + "/buttons/close.svg",
+ -1,
+ height,
+ true
+ );
+ } catch (Error e) {
+ warning (e.message);
+ return null;
+ }
+ }
+
+ return close_pixbuf;
+ }
+
+ /**
+ * Creates a new reactive ClutterActor at 36px with the close pixbuf
+ *
+ * @return The close button actor
+ */
+ public static Clutter.Actor create_close_button () {
+ var texture = new Clutter.Texture ();
+ var pixbuf = get_close_button_pixbuf ();
+
+ texture.reactive = true;
+
+ if (pixbuf != null) {
+ try {
+ texture.set_from_rgb_data (pixbuf.get_pixels (), pixbuf.get_has_alpha (),
+ pixbuf.get_width (), pixbuf.get_height (),
+ pixbuf.get_rowstride (), (pixbuf.get_has_alpha () ? 4 : 3), 0);
+ } catch (Error e) {}
+ } else {
+ // we'll just make this red so there's at least something as an
+ // indicator that loading failed. Should never happen and this
+ // works as good as some weird fallback-image-failed-to-load pixbuf
+ var scale = Utils.get_ui_scaling_factor ();
+ texture.set_size (36 * scale, 36 * scale);
+ texture.background_color = { 255, 0, 0, 255 };
+ }
+
+ return texture;
+ }
+ /**
+ * Returns the pixbuf that is used for resize buttons throughout gala at a
+ * size of 36px
+ *
+ * @return the close button pixbuf or null if it failed to load
+ */
+ public static Gdk.Pixbuf? get_resize_button_pixbuf () {
+ var height = 36 * Utils.get_ui_scaling_factor ();
+ if (resize_pixbuf == null || resize_pixbuf.height != height) {
+ var scale = Utils.get_ui_scaling_factor ();
+ try {
+ resize_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (
+ Config.RESOURCEPATH + "/buttons/resize.svg",
+ -1,
+ height,
+ true
+ );
+ } catch (Error e) {
+ warning (e.message);
+ return null;
+ }
+ }
+
+ return resize_pixbuf;
+ }
+
+ /**
+ * Creates a new reactive ClutterActor at 36px with the resize pixbuf
+ *
+ * @return The resize button actor
+ */
+ public static Clutter.Actor create_resize_button () {
+ var texture = new Clutter.Texture ();
+ var pixbuf = get_resize_button_pixbuf ();
+
+ texture.reactive = true;
+
+ if (pixbuf != null) {
+ try {
+ texture.set_from_rgb_data (pixbuf.get_pixels (), pixbuf.get_has_alpha (),
+ pixbuf.get_width (), pixbuf.get_height (),
+ pixbuf.get_rowstride (), (pixbuf.get_has_alpha () ? 4 : 3), 0);
+ } catch (Error e) {}
+ } else {
+ // we'll just make this red so there's at least something as an
+ // indicator that loading failed. Should never happen and this
+ // works as good as some weird fallback-image-failed-to-load pixbuf
+ var scale = Utils.get_ui_scaling_factor ();
+ texture.set_size (36 * scale, 36 * scale);
+ texture.background_color = { 255, 0, 0, 255 };
+ }
+
+ return texture;
+ }
+
+ static Gtk.CssProvider gala_css = null;
+ public static unowned Gtk.CssProvider? get_gala_css () {
+ if (gala_css == null) {
+ gala_css = new Gtk.CssProvider ();
+ gala_css.load_from_resource ("/io/elementary/desktop/gala/gala.css");
+ }
+
+ return gala_css;
+ }
+ }
}
diff --git a/lib/WindowIcon.vala b/lib/WindowIcon.vala
index 3171d0cd0..99831ef57 100644
--- a/lib/WindowIcon.vala
+++ b/lib/WindowIcon.vala
@@ -15,118 +15,109 @@
// along with this program. If not, see .
//
-namespace Gala
-{
- /**
- * Creates a new ClutterTexture with an icon for the window at the given size.
- * This is recommended way to grab an icon for a window as this method will make
- * sure the icon is updated if it becomes available at a later point.
- */
- public class WindowIcon : Clutter.Texture
- {
- static Bamf.Matcher matcher;
-
- static construct
- {
- matcher = Bamf.Matcher.get_default ();
- }
-
- public Meta.Window window { get; construct; }
- public int icon_size { get; construct; }
- public int scale { get; construct; }
-
- /**
- * If set to true, the SafeWindowClone will destroy itself when the connected
- * window is unmanaged
- */
- public bool destroy_on_unmanaged {
- get {
- return _destroy_on_unmanaged;
- }
- construct set {
- if (_destroy_on_unmanaged == value)
- return;
-
- _destroy_on_unmanaged = value;
- if (_destroy_on_unmanaged)
- window.unmanaged.connect (unmanaged);
- else
- window.unmanaged.disconnect (unmanaged);
- }
- }
-
- bool _destroy_on_unmanaged = false;
- bool loaded = false;
- uint32 xid;
-
- /**
- * Creates a new WindowIcon
- *
- * @param window The window for which to create the icon
- * @param icon_size The size of the icon in pixels
- * @param scale The desired scale of the icon
- * @param destroy_on_unmanaged see destroy_on_unmanaged property
- */
- public WindowIcon (Meta.Window window, int icon_size, int scale = 1, bool destroy_on_unmanaged = false)
- {
- Object (window: window,
- icon_size: icon_size,
- destroy_on_unmanaged: destroy_on_unmanaged,
- scale: scale);
- }
-
- construct
- {
- width = icon_size * scale;
- height = icon_size * scale;
- xid = (uint32) window.get_xwindow ();
-
- // new windows often reach mutter earlier than bamf, that's why
- // we have to wait until the next window opens and hope that it's
- // ours so we can get a proper icon instead of the default fallback.
- var app = matcher.get_application_for_xid (xid);
- if (app == null)
- matcher.view_opened.connect (retry_load);
- else
- loaded = true;
-
- update_texture (true);
- }
-
- ~WindowIcon ()
- {
- if (!loaded)
- matcher.view_opened.disconnect (retry_load);
- }
-
- void retry_load (Bamf.View view)
- {
- var app = matcher.get_application_for_xid (xid);
-
- // retry only once
- loaded = true;
- matcher.view_opened.disconnect (retry_load);
-
- if (app == null)
- return;
-
- update_texture (false);
- }
-
- void update_texture (bool initial)
- {
- var pixbuf = Gala.Utils.get_icon_for_xid (xid, icon_size, scale, !initial);
-
- try {
- set_from_rgb_data (pixbuf.get_pixels (), pixbuf.get_has_alpha (),
- pixbuf.get_width (), pixbuf.get_height (),
- pixbuf.get_rowstride (), (pixbuf.get_has_alpha () ? 4 : 3), 0);
- } catch (Error e) {}
- }
-
- void unmanaged (Meta.Window window)
- {
- destroy ();
- }
- }
+namespace Gala {
+ /**
+ * Creates a new ClutterTexture with an icon for the window at the given size.
+ * This is recommended way to grab an icon for a window as this method will make
+ * sure the icon is updated if it becomes available at a later point.
+ */
+ public class WindowIcon : Clutter.Texture {
+ static Bamf.Matcher matcher;
+
+ static construct {
+ matcher = Bamf.Matcher.get_default ();
+ }
+
+ public Meta.Window window { get; construct; }
+ public int icon_size { get; construct; }
+ public int scale { get; construct; }
+
+ /**
+ * If set to true, the SafeWindowClone will destroy itself when the connected
+ * window is unmanaged
+ */
+ public bool destroy_on_unmanaged {
+ get {
+ return _destroy_on_unmanaged;
+ }
+ construct set {
+ if (_destroy_on_unmanaged == value)
+ return;
+
+ _destroy_on_unmanaged = value;
+ if (_destroy_on_unmanaged)
+ window.unmanaged.connect (unmanaged);
+ else
+ window.unmanaged.disconnect (unmanaged);
+ }
+ }
+
+ bool _destroy_on_unmanaged = false;
+ bool loaded = false;
+ uint32 xid;
+
+ /**
+ * Creates a new WindowIcon
+ *
+ * @param window The window for which to create the icon
+ * @param icon_size The size of the icon in pixels
+ * @param scale The desired scale of the icon
+ * @param destroy_on_unmanaged see destroy_on_unmanaged property
+ */
+ public WindowIcon (Meta.Window window, int icon_size, int scale = 1, bool destroy_on_unmanaged = false) {
+ Object (window: window,
+ icon_size: icon_size,
+ destroy_on_unmanaged: destroy_on_unmanaged,
+ scale: scale);
+ }
+
+ construct {
+ width = icon_size * scale;
+ height = icon_size * scale;
+ xid = (uint32) window.get_xwindow ();
+
+ // new windows often reach mutter earlier than bamf, that's why
+ // we have to wait until the next window opens and hope that it's
+ // ours so we can get a proper icon instead of the default fallback.
+ var app = matcher.get_application_for_xid (xid);
+ if (app == null)
+ matcher.view_opened.connect (retry_load);
+ else
+ loaded = true;
+
+ update_texture (true);
+ }
+
+ ~WindowIcon () {
+ if (!loaded)
+ matcher.view_opened.disconnect (retry_load);
+ }
+
+ void retry_load (Bamf.View view) {
+ var app = matcher.get_application_for_xid (xid);
+
+ // retry only once
+ loaded = true;
+ matcher.view_opened.disconnect (retry_load);
+
+ if (app == null)
+ return;
+
+ update_texture (false);
+ }
+
+ void update_texture (bool initial) {
+ var pixbuf = Gala.Utils.get_icon_for_xid (xid, icon_size, scale, !initial);
+
+ try {
+ set_from_rgb_data (pixbuf.get_pixels (), pixbuf.get_has_alpha (),
+ pixbuf.get_width (), pixbuf.get_height (),
+ pixbuf.get_rowstride (), (pixbuf.get_has_alpha () ? 4 : 3), 0);
+ } catch (Error e) {}
+ }
+
+ void unmanaged (Meta.Window window) {
+ destroy ();
+ }
+ }
}
diff --git a/lib/WindowManager.vala b/lib/WindowManager.vala
index 993d4cf84..368629851 100644
--- a/lib/WindowManager.vala
+++ b/lib/WindowManager.vala
@@ -15,162 +15,155 @@
// along with this program. If not, see .
//
-namespace Gala
-{
- public enum ActionType
- {
- NONE = 0,
- SHOW_WORKSPACE_VIEW,
- MAXIMIZE_CURRENT,
- MINIMIZE_CURRENT,
- OPEN_LAUNCHER,
- CUSTOM_COMMAND,
- WINDOW_OVERVIEW,
- WINDOW_OVERVIEW_ALL,
- SWITCH_TO_WORKSPACE_LAST,
- START_MOVE_CURRENT,
- START_RESIZE_CURRENT,
- TOGGLE_ALWAYS_ON_TOP_CURRENT,
- TOGGLE_ALWAYS_ON_VISIBLE_WORKSPACE_CURRENT,
- MOVE_CURRENT_WORKSPACE_LEFT,
- MOVE_CURRENT_WORKSPACE_RIGHT,
- CLOSE_CURRENT
- }
-
- [Flags]
- public enum WindowFlags
- {
- NONE = 0,
- CAN_MINIMIZE,
- CAN_MAXIMIZE,
- IS_MAXIMIZED,
- ALLOWS_MOVE,
- ALLOWS_RESIZE,
- ALWAYS_ON_TOP,
- ON_ALL_WORKSPACES,
- CAN_CLOSE
- }
-
- /**
- * 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; owned set; default = () => true; }
-
- public ModalProxy ()
- {
- }
-
- /**
- * Small utility to allow all keybindings
- */
- public void allow_all_keybindings ()
- {
- keybinding_filter = null;
- }
- }
-
- public interface WindowManager : Meta.Plugin
- {
- /**
- * 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 Clutter.Actor ui_group { get; protected set; }
-
- /**
- * 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; }
-
- /**
- * Whether animations should be displayed.
- */
- public abstract bool enable_animations { 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);
- }
+namespace Gala {
+ public enum ActionType {
+ NONE = 0,
+ SHOW_WORKSPACE_VIEW,
+ MAXIMIZE_CURRENT,
+ MINIMIZE_CURRENT,
+ OPEN_LAUNCHER,
+ CUSTOM_COMMAND,
+ WINDOW_OVERVIEW,
+ WINDOW_OVERVIEW_ALL,
+ SWITCH_TO_WORKSPACE_LAST,
+ START_MOVE_CURRENT,
+ START_RESIZE_CURRENT,
+ TOGGLE_ALWAYS_ON_TOP_CURRENT,
+ TOGGLE_ALWAYS_ON_VISIBLE_WORKSPACE_CURRENT,
+ MOVE_CURRENT_WORKSPACE_LEFT,
+ MOVE_CURRENT_WORKSPACE_RIGHT,
+ CLOSE_CURRENT
+ }
+
+ [Flags]
+ public enum WindowFlags {
+ NONE = 0,
+ CAN_MINIMIZE,
+ CAN_MAXIMIZE,
+ IS_MAXIMIZED,
+ ALLOWS_MOVE,
+ ALLOWS_RESIZE,
+ ALWAYS_ON_TOP,
+ ON_ALL_WORKSPACES,
+ CAN_CLOSE
+ }
+
+ /**
+ * 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; owned set; default = () => true; }
+
+ public ModalProxy () {
+ }
+
+ /**
+ * Small utility to allow all keybindings
+ */
+ public void allow_all_keybindings () {
+ keybinding_filter = null;
+ }
+ }
+
+ public interface WindowManager : Meta.Plugin {
+ /**
+ * 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 Clutter.Actor ui_group { get; protected set; }
+
+ /**
+ * 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; }
+
+ /**
+ * Whether animations should be displayed.
+ */
+ public abstract bool enable_animations { 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);
+ }
}