mirror of
https://github.com/elementary/gala.git
synced 2024-12-24 17:53:19 +03:00
👕 Lint lib directory with vala-lint (#607)
This commit is contained in:
parent
50694796d4
commit
49d1d8ffab
@ -15,37 +15,34 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
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<string,Variant>? 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<string,Variant>? 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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,21 +15,20 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
342
lib/Plugin.vala
342
lib/Plugin.vala
@ -15,206 +15,196 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
public enum PluginFunction
|
||||
{
|
||||
ADDITION,
|
||||
WINDOW_SWITCHER,
|
||||
DESKTOP,
|
||||
WORKSPACE_VIEW,
|
||||
WINDOW_OVERVIEW
|
||||
}
|
||||
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 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;
|
||||
public struct PluginInfo {
|
||||
string name;
|
||||
string author;
|
||||
|
||||
/**
|
||||
* Type of your plugin class, has to be derived from the Plugin class.
|
||||
*/
|
||||
Type plugin_type;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* 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 ();
|
||||
/**
|
||||
* 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; }
|
||||
/**
|
||||
* 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 ();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* 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 ();
|
||||
}
|
||||
}
|
||||
if (!_freeze_track)
|
||||
update_region ();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _freeze_track = false;
|
||||
private Meta.Rectangle[]? _custom_region = null;
|
||||
private List<Clutter.Actor> tracked_actors = new List<Clutter.Actor> ();
|
||||
private bool _freeze_track = false;
|
||||
private Meta.Rectangle[]? _custom_region = null;
|
||||
private List<Clutter.Actor> tracked_actors = new List<Clutter.Actor> ();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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 ();
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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 ();
|
||||
}
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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;
|
||||
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];
|
||||
}
|
||||
}
|
||||
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);
|
||||
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;
|
||||
if (w == 0 || h == 0)
|
||||
continue;
|
||||
|
||||
regions[i++] = { (int) x, (int) y, (int) w, (int) h };
|
||||
}
|
||||
regions[i++] = { (int) x, (int) y, (int) w, (int) h };
|
||||
}
|
||||
|
||||
region = regions;
|
||||
region = regions;
|
||||
|
||||
region_changed ();
|
||||
}
|
||||
region_changed ();
|
||||
}
|
||||
|
||||
private void actor_allocation_changed (Clutter.ActorBox box, Clutter.AllocationFlags f)
|
||||
{
|
||||
if (!freeze_track)
|
||||
update_region ();
|
||||
}
|
||||
}
|
||||
private void actor_allocation_changed (Clutter.ActorBox box, Clutter.AllocationFlags f) {
|
||||
if (!freeze_track)
|
||||
update_region ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
665
lib/Utils.vala
665
lib/Utils.vala
@ -15,387 +15,392 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
public class Utils
|
||||
{
|
||||
// Cache xid:pixbuf and icon:pixbuf pairs to provide a faster way aquiring icons
|
||||
static HashTable<string, Gdk.Pixbuf> xid_pixbuf_cache;
|
||||
static HashTable<string, Gdk.Pixbuf> icon_pixbuf_cache;
|
||||
static uint cache_clear_timeout = 0;
|
||||
namespace Gala {
|
||||
public class Utils {
|
||||
// Cache xid:pixbuf and icon:pixbuf pairs to provide a faster way aquiring icons
|
||||
static HashTable<string, Gdk.Pixbuf> xid_pixbuf_cache;
|
||||
static HashTable<string, Gdk.Pixbuf> icon_pixbuf_cache;
|
||||
static uint cache_clear_timeout = 0;
|
||||
|
||||
static Gdk.Pixbuf? close_pixbuf = null;
|
||||
static Gdk.Pixbuf? resize_pixbuf = null;
|
||||
static Gdk.Pixbuf? close_pixbuf = null;
|
||||
static Gdk.Pixbuf? resize_pixbuf = null;
|
||||
|
||||
static construct
|
||||
{
|
||||
xid_pixbuf_cache = new HashTable<string, Gdk.Pixbuf> (str_hash, str_equal);
|
||||
icon_pixbuf_cache = new HashTable<string, Gdk.Pixbuf> (str_hash, str_equal);
|
||||
}
|
||||
static construct {
|
||||
xid_pixbuf_cache = new HashTable<string, Gdk.Pixbuf> (str_hash, str_equal);
|
||||
icon_pixbuf_cache = new HashTable<string, Gdk.Pixbuf> (str_hash, str_equal);
|
||||
}
|
||||
|
||||
Utils ()
|
||||
{
|
||||
}
|
||||
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 ();
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
/**
|
||||
* 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;
|
||||
});
|
||||
}
|
||||
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 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);
|
||||
/**
|
||||
* 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;
|
||||
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);
|
||||
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);
|
||||
xid_pixbuf_cache.set (xid_key, result);
|
||||
|
||||
return 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;
|
||||
/**
|
||||
* 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;
|
||||
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 (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) {
|
||||
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 (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 (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);
|
||||
if (not_cached)
|
||||
icon_pixbuf_cache.set (icon_key, image);
|
||||
|
||||
return 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 ();
|
||||
/**
|
||||
* 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);
|
||||
var window = display.get_tab_next (Meta.TabList.NORMAL,
|
||||
workspace, null, backward);
|
||||
|
||||
if (window == null)
|
||||
window = display.get_tab_current (Meta.TabList.NORMAL, workspace);
|
||||
if (window == null)
|
||||
window = display.get_tab_current (Meta.TabList.NORMAL, workspace);
|
||||
|
||||
return window;
|
||||
}
|
||||
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 ++;
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
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;
|
||||
/**
|
||||
* 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;
|
||||
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
|
||||
});
|
||||
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;
|
||||
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 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;
|
||||
var container = new Clutter.Actor ();
|
||||
container.set_size (inner_rect.width, inner_rect.height);
|
||||
container.content = canvas;
|
||||
|
||||
return container;
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ring the system bell, will most likely emit a <beep> 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);
|
||||
}
|
||||
/**
|
||||
* Ring the system bell, will most likely emit a <beep> 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 ()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
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 ();
|
||||
/**
|
||||
* 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;
|
||||
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 };
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
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 ();
|
||||
/**
|
||||
* 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;
|
||||
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 };
|
||||
}
|
||||
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;
|
||||
}
|
||||
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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
return gala_css;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,118 +15,109 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
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;
|
||||
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 ();
|
||||
}
|
||||
static construct {
|
||||
matcher = Bamf.Matcher.get_default ();
|
||||
}
|
||||
|
||||
public Meta.Window window { get; construct; }
|
||||
public int icon_size { get; construct; }
|
||||
public int scale { get; construct; }
|
||||
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;
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
_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;
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* 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 ();
|
||||
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;
|
||||
// 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);
|
||||
}
|
||||
update_texture (true);
|
||||
}
|
||||
|
||||
~WindowIcon ()
|
||||
{
|
||||
if (!loaded)
|
||||
matcher.view_opened.disconnect (retry_load);
|
||||
}
|
||||
~WindowIcon () {
|
||||
if (!loaded)
|
||||
matcher.view_opened.disconnect (retry_load);
|
||||
}
|
||||
|
||||
void retry_load (Bamf.View view)
|
||||
{
|
||||
var app = matcher.get_application_for_xid (xid);
|
||||
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);
|
||||
// retry only once
|
||||
loaded = true;
|
||||
matcher.view_opened.disconnect (retry_load);
|
||||
|
||||
if (app == null)
|
||||
return;
|
||||
if (app == null)
|
||||
return;
|
||||
|
||||
update_texture (false);
|
||||
}
|
||||
update_texture (false);
|
||||
}
|
||||
|
||||
void update_texture (bool initial)
|
||||
{
|
||||
var pixbuf = Gala.Utils.get_icon_for_xid (xid, icon_size, scale, !initial);
|
||||
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) {}
|
||||
}
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
void unmanaged (Meta.Window window) {
|
||||
destroy ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,162 +15,155 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
[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);
|
||||
/**
|
||||
* 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; }
|
||||
/**
|
||||
* 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 ()
|
||||
{
|
||||
}
|
||||
public ModalProxy () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Small utility to allow all keybindings
|
||||
*/
|
||||
public void allow_all_keybindings ()
|
||||
{
|
||||
keybinding_filter = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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; }
|
||||
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; }
|
||||
/**
|
||||
* 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; }
|
||||
/**
|
||||
* 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 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; }
|
||||
/**
|
||||
* 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; }
|
||||
/**
|
||||
* 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 ();
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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 ();
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user