mirror of
https://github.com/elementary/gala.git
synced 2024-11-23 20:07:21 +03:00
Refactoring to avoid nested classes and multi-class files
Additionally don't expose plank in libgala
This commit is contained in:
parent
88ef7e47e0
commit
d588328a03
@ -35,6 +35,7 @@ libgala_la_VALASOURCES = \
|
||||
ActivatableComponent.vala \
|
||||
Plugin.vala \
|
||||
Utils.vala \
|
||||
WindowIcon.vala \
|
||||
WindowManager.vala \
|
||||
$(NULL)
|
||||
|
||||
|
162
lib/Utils.vala
162
lib/Utils.vala
@ -32,6 +32,10 @@ namespace Gala
|
||||
icon_pixbuf_cache = new HashTable<string, Gdk.Pixbuf> (str_hash, str_equal);
|
||||
}
|
||||
|
||||
Utils ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean icon caches
|
||||
*/
|
||||
@ -77,114 +81,6 @@ namespace Gala
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GtkClutterTexture 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 : GtkClutter.Texture
|
||||
{
|
||||
static Bamf.Matcher matcher;
|
||||
|
||||
static construct
|
||||
{
|
||||
matcher = Bamf.Matcher.get_default ();
|
||||
}
|
||||
|
||||
public Meta.Window window { get; construct; }
|
||||
public int icon_size { 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 destroy_on_unmanaged @see destroy_on_unmanaged
|
||||
*/
|
||||
public WindowIcon (Meta.Window window, int icon_size, bool destroy_on_unmanaged = false)
|
||||
{
|
||||
Object (window: window,
|
||||
icon_size: icon_size,
|
||||
destroy_on_unmanaged: destroy_on_unmanaged);
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
width = icon_size;
|
||||
height = icon_size;
|
||||
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 = get_icon_for_xid (xid, icon_size, !initial);
|
||||
|
||||
try {
|
||||
set_from_pixbuf (pixbuf);
|
||||
} catch (Error e) {}
|
||||
}
|
||||
|
||||
void unmanaged (Meta.Window window)
|
||||
{
|
||||
destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pixbuf for the application of this window or a default icon
|
||||
*
|
||||
@ -392,55 +288,5 @@ namespace Gala
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to a PlankDrawingDockTheme and PlankDockPrefereces
|
||||
*/
|
||||
public class DockThemeManager : Object
|
||||
{
|
||||
Plank.DockPreferences? dock_settings = null;
|
||||
Plank.Drawing.DockTheme? dock_theme = null;
|
||||
|
||||
public signal void dock_theme_changed (Plank.Drawing.DockTheme? old_theme,
|
||||
Plank.Drawing.DockTheme new_theme);
|
||||
|
||||
DockThemeManager ()
|
||||
{
|
||||
var file = Environment.get_user_config_dir () + "/plank/dock1/settings";
|
||||
|
||||
dock_settings = new Plank.DockPreferences.with_filename (file);
|
||||
dock_settings.notify["Theme"].connect (load_dock_theme);
|
||||
}
|
||||
|
||||
public Plank.Drawing.DockTheme get_dock_theme ()
|
||||
{
|
||||
if (dock_theme == null)
|
||||
load_dock_theme ();
|
||||
|
||||
return dock_theme;
|
||||
}
|
||||
|
||||
public Plank.DockPreferences get_dock_settings ()
|
||||
{
|
||||
return dock_settings;
|
||||
}
|
||||
|
||||
void load_dock_theme ()
|
||||
{
|
||||
var new_theme = new Plank.Drawing.DockTheme (dock_settings.Theme);
|
||||
new_theme.load ("dock");
|
||||
dock_theme_changed (dock_theme, new_theme);
|
||||
dock_theme = new_theme;
|
||||
}
|
||||
|
||||
static DockThemeManager? instance = null;
|
||||
public static DockThemeManager get_default ()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new DockThemeManager ();
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
127
lib/WindowIcon.vala
Normal file
127
lib/WindowIcon.vala
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
/**
|
||||
* Creates a new GtkClutterTexture 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 : GtkClutter.Texture
|
||||
{
|
||||
static Bamf.Matcher matcher;
|
||||
|
||||
static construct
|
||||
{
|
||||
matcher = Bamf.Matcher.get_default ();
|
||||
}
|
||||
|
||||
public Meta.Window window { get; construct; }
|
||||
public int icon_size { 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 destroy_on_unmanaged @see destroy_on_unmanaged
|
||||
*/
|
||||
public WindowIcon (Meta.Window window, int icon_size, bool destroy_on_unmanaged = false)
|
||||
{
|
||||
Object (window: window,
|
||||
icon_size: icon_size,
|
||||
destroy_on_unmanaged: destroy_on_unmanaged);
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
width = icon_size;
|
||||
height = icon_size;
|
||||
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, !initial);
|
||||
|
||||
try {
|
||||
set_from_pixbuf (pixbuf);
|
||||
} catch (Error e) {}
|
||||
}
|
||||
|
||||
void unmanaged (Meta.Window window)
|
||||
{
|
||||
destroy ();
|
||||
}
|
||||
}
|
||||
}
|
70
src/DockThemeManager.vala
Normal file
70
src/DockThemeManager.vala
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
/**
|
||||
* Provides access to a PlankDrawingDockTheme and PlankDockPrefereces
|
||||
*/
|
||||
public class DockThemeManager : Object
|
||||
{
|
||||
static DockThemeManager? instance = null;
|
||||
|
||||
public static DockThemeManager get_default ()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new DockThemeManager ();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
Plank.DockPreferences? dock_settings = null;
|
||||
Plank.Drawing.DockTheme? dock_theme = null;
|
||||
|
||||
public signal void dock_theme_changed (Plank.Drawing.DockTheme? old_theme,
|
||||
Plank.Drawing.DockTheme new_theme);
|
||||
|
||||
DockThemeManager ()
|
||||
{
|
||||
var file = Environment.get_user_config_dir () + "/plank/dock1/settings";
|
||||
|
||||
dock_settings = new Plank.DockPreferences.with_filename (file);
|
||||
dock_settings.notify["Theme"].connect (load_dock_theme);
|
||||
}
|
||||
|
||||
public Plank.Drawing.DockTheme get_dock_theme ()
|
||||
{
|
||||
if (dock_theme == null)
|
||||
load_dock_theme ();
|
||||
|
||||
return dock_theme;
|
||||
}
|
||||
|
||||
public Plank.DockPreferences get_dock_settings ()
|
||||
{
|
||||
return dock_settings;
|
||||
}
|
||||
|
||||
void load_dock_theme ()
|
||||
{
|
||||
var new_theme = new Plank.Drawing.DockTheme (dock_settings.Theme);
|
||||
new_theme.load ("dock");
|
||||
dock_theme_changed (dock_theme, new_theme);
|
||||
dock_theme = new_theme;
|
||||
}
|
||||
}
|
||||
}
|
@ -32,6 +32,7 @@ gala_LDADD = \
|
||||
|
||||
gala_VALASOURCES = \
|
||||
DBus.vala \
|
||||
DockThemeManager.vala \
|
||||
DragDropAction.vala \
|
||||
InternalUtils.vala \
|
||||
Main.vala \
|
||||
@ -49,10 +50,12 @@ gala_VALASOURCES = \
|
||||
Widgets/MultitaskingView.vala \
|
||||
Widgets/WindowClone.vala \
|
||||
Widgets/WindowCloneContainer.vala \
|
||||
Widgets/WindowIconActor.vala \
|
||||
Widgets/WindowMenu.vala \
|
||||
Widgets/WindowOverview.vala \
|
||||
Widgets/WindowSwitcher.vala \
|
||||
Widgets/WorkspaceClone.vala \
|
||||
Widgets/WorkspaceInsertThumb.vala \
|
||||
$(NULL)
|
||||
|
||||
gala_background = \
|
||||
|
@ -21,177 +21,7 @@ using Meta;
|
||||
namespace Gala
|
||||
{
|
||||
/**
|
||||
* Private class which is basically just a container for the actual
|
||||
* icon and takes care of blending the same icon in different sizes
|
||||
* over each other and various animations related to the icons
|
||||
*/
|
||||
class WindowIcon : Actor
|
||||
{
|
||||
public Window window { get; construct; }
|
||||
|
||||
int _icon_size;
|
||||
/**
|
||||
* The icon size of the WindowIcon. Once set the new icon will be
|
||||
* faded over the old one and the actor animates to the new size.
|
||||
*/
|
||||
public int icon_size {
|
||||
get {
|
||||
return _icon_size;
|
||||
}
|
||||
set {
|
||||
if (value == _icon_size)
|
||||
return;
|
||||
|
||||
_icon_size = value;
|
||||
|
||||
set_size (_icon_size, _icon_size);
|
||||
|
||||
fade_new_icon ();
|
||||
}
|
||||
}
|
||||
|
||||
bool _temporary;
|
||||
/**
|
||||
* Mark the WindowIcon as temporary. Only effect of this is that a pulse
|
||||
* animation will be played on the actor. Used while DnDing window thumbs
|
||||
* over the group.
|
||||
*/
|
||||
public bool temporary {
|
||||
get {
|
||||
return _temporary;
|
||||
}
|
||||
set {
|
||||
if (_temporary && !value) {
|
||||
remove_transition ("pulse");
|
||||
} else if (!_temporary && value) {
|
||||
var transition = new TransitionGroup ();
|
||||
transition.duration = 800;
|
||||
transition.auto_reverse = true;
|
||||
transition.repeat_count = -1;
|
||||
transition.progress_mode = AnimationMode.LINEAR;
|
||||
|
||||
var opacity_transition = new PropertyTransition ("opacity");
|
||||
opacity_transition.set_from_value (100);
|
||||
opacity_transition.set_to_value (255);
|
||||
opacity_transition.auto_reverse = true;
|
||||
|
||||
var scale_x_transition = new PropertyTransition ("scale-x");
|
||||
scale_x_transition.set_from_value (0.8);
|
||||
scale_x_transition.set_to_value (1.1);
|
||||
scale_x_transition.auto_reverse = true;
|
||||
|
||||
var scale_y_transition = new PropertyTransition ("scale-y");
|
||||
scale_y_transition.set_from_value (0.8);
|
||||
scale_y_transition.set_to_value (1.1);
|
||||
scale_y_transition.auto_reverse = true;
|
||||
|
||||
transition.add_transition (opacity_transition);
|
||||
transition.add_transition (scale_x_transition);
|
||||
transition.add_transition (scale_y_transition);
|
||||
|
||||
add_transition ("pulse", transition);
|
||||
}
|
||||
|
||||
_temporary = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool initial = true;
|
||||
|
||||
Utils.WindowIcon? icon = null;
|
||||
Utils.WindowIcon? old_icon = null;
|
||||
|
||||
public WindowIcon (Window window)
|
||||
{
|
||||
Object (window: window);
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
set_pivot_point (0.5f, 0.5f);
|
||||
set_easing_mode (AnimationMode.EASE_OUT_ELASTIC);
|
||||
set_easing_duration (800);
|
||||
|
||||
window.notify["on-all-workspaces"].connect (on_all_workspaces_changed);
|
||||
}
|
||||
|
||||
~WindowIcon ()
|
||||
{
|
||||
window.notify["on-all-workspaces"].disconnect (on_all_workspaces_changed);
|
||||
}
|
||||
|
||||
void on_all_workspaces_changed ()
|
||||
{
|
||||
// we don't display windows that are on all workspaces
|
||||
if (window.on_all_workspaces)
|
||||
destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to set both position and size of the icon
|
||||
*
|
||||
* @param x The x coordinate to which to animate to
|
||||
* @param y The y coordinate to which to animate to
|
||||
* @param size The size to which to animate to and display the icon in
|
||||
*/
|
||||
public void place (float x, float y, int size)
|
||||
{
|
||||
if (initial) {
|
||||
save_easing_state ();
|
||||
set_easing_duration (10);
|
||||
}
|
||||
|
||||
set_position (x, y);
|
||||
icon_size = size;
|
||||
|
||||
if (initial) {
|
||||
restore_easing_state ();
|
||||
initial = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fades out the old icon and fades in the new icon
|
||||
*/
|
||||
void fade_new_icon ()
|
||||
{
|
||||
var new_icon = new Utils.WindowIcon (window, icon_size);
|
||||
new_icon.add_constraint (new BindConstraint (this, BindCoordinate.SIZE, 0));
|
||||
new_icon.opacity = 0;
|
||||
|
||||
add_child (new_icon);
|
||||
|
||||
new_icon.set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||
new_icon.set_easing_duration (500);
|
||||
|
||||
if (icon == null) {
|
||||
icon = new_icon;
|
||||
} else {
|
||||
old_icon = icon;
|
||||
}
|
||||
|
||||
new_icon.opacity = 255;
|
||||
|
||||
if (old_icon != null) {
|
||||
old_icon.opacity = 0;
|
||||
var transition = old_icon.get_transition ("opacity");
|
||||
if (transition != null) {
|
||||
transition.completed.connect (() => {
|
||||
old_icon.destroy ();
|
||||
old_icon = null;
|
||||
});
|
||||
} else {
|
||||
old_icon.destroy ();
|
||||
old_icon = null;
|
||||
}
|
||||
}
|
||||
|
||||
icon = new_icon;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Container for WindowIcons which takes care of the scaling and positioning.
|
||||
* Container for WindowIconActors which takes care of the scaling and positioning.
|
||||
* It also decides whether to draw the container shape, a plus sign or an ellipsis.
|
||||
* Lastly it also includes the drawing code for the active highlight.
|
||||
*/
|
||||
@ -410,7 +240,7 @@ namespace Gala
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all currently added WindowIcons
|
||||
* Remove all currently added WindowIconActors
|
||||
*/
|
||||
public void clear ()
|
||||
{
|
||||
@ -418,17 +248,17 @@ namespace Gala
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WindowIcon for the given window and adds it to the group
|
||||
* Creates a WindowIconActor for the given window and adds it to the group
|
||||
*
|
||||
* @param window The MetaWindow for which to create the WindowIcon
|
||||
* @param window The MetaWindow for which to create the WindowIconActor
|
||||
* @param no_redraw If you add multiple windows at once you may want to consider
|
||||
* settings this to true and when done calling redraw() manually
|
||||
* @param temporary Mark the WindowIcon as temporary. Used for windows dragged over
|
||||
* @param temporary Mark the WindowIconActor as temporary. Used for windows dragged over
|
||||
* the group.
|
||||
*/
|
||||
public void add_window (Window window, bool no_redraw = false, bool temporary = false)
|
||||
{
|
||||
var new_window = new WindowIcon (window);
|
||||
var new_window = new WindowIconActor (window);
|
||||
|
||||
new_window.save_easing_state ();
|
||||
new_window.set_easing_duration (0);
|
||||
@ -443,14 +273,14 @@ namespace Gala
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the WindowIcon for a MetaWindow from the group
|
||||
* Remove the WindowIconActor for a MetaWindow from the group
|
||||
*
|
||||
* @param animate Whether to fade the icon out before removing it
|
||||
*/
|
||||
public void remove_window (Window window, bool animate = true)
|
||||
{
|
||||
foreach (var child in icon_container.get_children ()) {
|
||||
unowned WindowIcon w = (WindowIcon) child;
|
||||
unowned WindowIconActor w = (WindowIconActor) child;
|
||||
if (w.window == window) {
|
||||
if (animate) {
|
||||
w.set_easing_mode (AnimationMode.LINEAR);
|
||||
@ -513,7 +343,7 @@ namespace Gala
|
||||
|
||||
// single icon => big icon
|
||||
if (n_windows == 1) {
|
||||
var icon = (WindowIcon) icon_container.get_child_at_index (0);
|
||||
var icon = (WindowIconActor) icon_container.get_child_at_index (0);
|
||||
icon.place (0, 0, 64);
|
||||
|
||||
return false;
|
||||
@ -607,7 +437,7 @@ namespace Gala
|
||||
var x = x_offset;
|
||||
var y = y_offset;
|
||||
for (var i = 0; i < n_windows; i++) {
|
||||
var window = (WindowIcon) icon_container.get_child_at_index (i);
|
||||
var window = (WindowIconActor) icon_container.get_child_at_index (i);
|
||||
|
||||
// draw an ellipsis at the 9th position if we need one
|
||||
if (show_ellipsis && i == 8) {
|
||||
|
@ -20,111 +20,6 @@ using Meta;
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
public class WorkspaceInsertThumb : Actor
|
||||
{
|
||||
public const int EXPAND_DELAY = 300;
|
||||
|
||||
public int workspace_index { get; construct set; }
|
||||
public bool expanded { get; private set; default = false; }
|
||||
|
||||
uint expand_timeout = 0;
|
||||
|
||||
public WorkspaceInsertThumb (int workspace_index)
|
||||
{
|
||||
Object (workspace_index: workspace_index);
|
||||
|
||||
width = IconGroupContainer.SPACING;
|
||||
height = IconGroupContainer.GROUP_WIDTH;
|
||||
y = (IconGroupContainer.GROUP_WIDTH - IconGroupContainer.SPACING) / 2;
|
||||
opacity = 0;
|
||||
set_pivot_point (0.5f, 0.5f);
|
||||
reactive = true;
|
||||
|
||||
layout_manager = new BinLayout (BinAlignment.CENTER);
|
||||
|
||||
var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
||||
drop.crossed.connect ((hovered) => {
|
||||
if (!Prefs.get_dynamic_workspaces ())
|
||||
return;
|
||||
|
||||
if (!hovered) {
|
||||
if (expand_timeout != 0) {
|
||||
Source.remove (expand_timeout);
|
||||
expand_timeout = 0;
|
||||
}
|
||||
|
||||
transform (false);
|
||||
} else
|
||||
expand_timeout = Timeout.add (EXPAND_DELAY, expand);
|
||||
});
|
||||
|
||||
add_action (drop);
|
||||
}
|
||||
|
||||
public void set_window_thumb (Window window)
|
||||
{
|
||||
destroy_all_children ();
|
||||
|
||||
var icon = new Utils.WindowIcon (window, IconGroupContainer.GROUP_WIDTH);
|
||||
icon.x_align = ActorAlign.CENTER;
|
||||
add_child (icon);
|
||||
}
|
||||
|
||||
bool expand ()
|
||||
{
|
||||
expand_timeout = 0;
|
||||
|
||||
transform (true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void transform (bool expand)
|
||||
{
|
||||
save_easing_state ();
|
||||
set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||
set_easing_duration (200);
|
||||
|
||||
if (!expand) {
|
||||
remove_transition ("pulse");
|
||||
opacity = 0;
|
||||
width = IconGroupContainer.SPACING;
|
||||
expanded = false;
|
||||
} else {
|
||||
add_pulse_animation ();
|
||||
opacity = 200;
|
||||
width = IconGroupContainer.GROUP_WIDTH + IconGroupContainer.SPACING * 2;
|
||||
expanded = true;
|
||||
}
|
||||
|
||||
restore_easing_state ();
|
||||
}
|
||||
|
||||
void add_pulse_animation ()
|
||||
{
|
||||
var transition = new TransitionGroup ();
|
||||
transition.duration = 800;
|
||||
transition.auto_reverse = true;
|
||||
transition.repeat_count = -1;
|
||||
transition.progress_mode = AnimationMode.LINEAR;
|
||||
|
||||
var scale_x_transition = new PropertyTransition ("scale-x");
|
||||
scale_x_transition.set_from_value (0.8);
|
||||
scale_x_transition.set_to_value (1.1);
|
||||
scale_x_transition.auto_reverse = true;
|
||||
|
||||
var scale_y_transition = new PropertyTransition ("scale-y");
|
||||
scale_y_transition.set_from_value (0.8);
|
||||
scale_y_transition.set_to_value (1.1);
|
||||
scale_y_transition.auto_reverse = true;
|
||||
|
||||
transition.add_transition (scale_x_transition);
|
||||
transition.add_transition (scale_y_transition);
|
||||
|
||||
add_transition ("pulse", transition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class contains the icon groups at the bottom and will take
|
||||
* care of displaying actors for inserting windows between the groups
|
||||
|
@ -131,7 +131,7 @@ namespace Gala
|
||||
return false;
|
||||
});
|
||||
|
||||
window_icon = new Utils.WindowIcon (window, WINDOW_ICON_SIZE);
|
||||
window_icon = new WindowIcon (window, WINDOW_ICON_SIZE);
|
||||
window_icon.opacity = 0;
|
||||
window_icon.set_pivot_point (0.5f, 0.5f);
|
||||
|
||||
|
193
src/Widgets/WindowIconActor.vala
Normal file
193
src/Widgets/WindowIconActor.vala
Normal file
@ -0,0 +1,193 @@
|
||||
//
|
||||
// Copyright (C) 2014 Tom Beckmann
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
using Clutter;
|
||||
using Meta;
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
/**
|
||||
* Private class which is basically just a container for the actual
|
||||
* icon and takes care of blending the same icon in different sizes
|
||||
* over each other and various animations related to the icons
|
||||
*/
|
||||
public class WindowIconActor : Actor
|
||||
{
|
||||
public Window window { get; construct; }
|
||||
|
||||
int _icon_size;
|
||||
/**
|
||||
* The icon size of the WindowIcon. Once set the new icon will be
|
||||
* faded over the old one and the actor animates to the new size.
|
||||
*/
|
||||
public int icon_size {
|
||||
get {
|
||||
return _icon_size;
|
||||
}
|
||||
set {
|
||||
if (value == _icon_size)
|
||||
return;
|
||||
|
||||
_icon_size = value;
|
||||
|
||||
set_size (_icon_size, _icon_size);
|
||||
|
||||
fade_new_icon ();
|
||||
}
|
||||
}
|
||||
|
||||
bool _temporary;
|
||||
/**
|
||||
* Mark the WindowIcon as temporary. Only effect of this is that a pulse
|
||||
* animation will be played on the actor. Used while DnDing window thumbs
|
||||
* over the group.
|
||||
*/
|
||||
public bool temporary {
|
||||
get {
|
||||
return _temporary;
|
||||
}
|
||||
set {
|
||||
if (_temporary && !value) {
|
||||
remove_transition ("pulse");
|
||||
} else if (!_temporary && value) {
|
||||
var transition = new TransitionGroup ();
|
||||
transition.duration = 800;
|
||||
transition.auto_reverse = true;
|
||||
transition.repeat_count = -1;
|
||||
transition.progress_mode = AnimationMode.LINEAR;
|
||||
|
||||
var opacity_transition = new PropertyTransition ("opacity");
|
||||
opacity_transition.set_from_value (100);
|
||||
opacity_transition.set_to_value (255);
|
||||
opacity_transition.auto_reverse = true;
|
||||
|
||||
var scale_x_transition = new PropertyTransition ("scale-x");
|
||||
scale_x_transition.set_from_value (0.8);
|
||||
scale_x_transition.set_to_value (1.1);
|
||||
scale_x_transition.auto_reverse = true;
|
||||
|
||||
var scale_y_transition = new PropertyTransition ("scale-y");
|
||||
scale_y_transition.set_from_value (0.8);
|
||||
scale_y_transition.set_to_value (1.1);
|
||||
scale_y_transition.auto_reverse = true;
|
||||
|
||||
transition.add_transition (opacity_transition);
|
||||
transition.add_transition (scale_x_transition);
|
||||
transition.add_transition (scale_y_transition);
|
||||
|
||||
add_transition ("pulse", transition);
|
||||
}
|
||||
|
||||
_temporary = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool initial = true;
|
||||
|
||||
WindowIcon? icon = null;
|
||||
WindowIcon? old_icon = null;
|
||||
|
||||
public WindowIconActor (Window window)
|
||||
{
|
||||
Object (window: window);
|
||||
}
|
||||
|
||||
construct
|
||||
{
|
||||
set_pivot_point (0.5f, 0.5f);
|
||||
set_easing_mode (AnimationMode.EASE_OUT_ELASTIC);
|
||||
set_easing_duration (800);
|
||||
|
||||
window.notify["on-all-workspaces"].connect (on_all_workspaces_changed);
|
||||
}
|
||||
|
||||
~WindowIconActor ()
|
||||
{
|
||||
window.notify["on-all-workspaces"].disconnect (on_all_workspaces_changed);
|
||||
}
|
||||
|
||||
void on_all_workspaces_changed ()
|
||||
{
|
||||
// we don't display windows that are on all workspaces
|
||||
if (window.on_all_workspaces)
|
||||
destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to set both position and size of the icon
|
||||
*
|
||||
* @param x The x coordinate to which to animate to
|
||||
* @param y The y coordinate to which to animate to
|
||||
* @param size The size to which to animate to and display the icon in
|
||||
*/
|
||||
public void place (float x, float y, int size)
|
||||
{
|
||||
if (initial) {
|
||||
save_easing_state ();
|
||||
set_easing_duration (10);
|
||||
}
|
||||
|
||||
set_position (x, y);
|
||||
icon_size = size;
|
||||
|
||||
if (initial) {
|
||||
restore_easing_state ();
|
||||
initial = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fades out the old icon and fades in the new icon
|
||||
*/
|
||||
void fade_new_icon ()
|
||||
{
|
||||
var new_icon = new WindowIcon (window, icon_size);
|
||||
new_icon.add_constraint (new BindConstraint (this, BindCoordinate.SIZE, 0));
|
||||
new_icon.opacity = 0;
|
||||
|
||||
add_child (new_icon);
|
||||
|
||||
new_icon.set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||
new_icon.set_easing_duration (500);
|
||||
|
||||
if (icon == null) {
|
||||
icon = new_icon;
|
||||
} else {
|
||||
old_icon = icon;
|
||||
}
|
||||
|
||||
new_icon.opacity = 255;
|
||||
|
||||
if (old_icon != null) {
|
||||
old_icon.opacity = 0;
|
||||
var transition = old_icon.get_transition ("opacity");
|
||||
if (transition != null) {
|
||||
transition.completed.connect (() => {
|
||||
old_icon.destroy ();
|
||||
old_icon = null;
|
||||
});
|
||||
} else {
|
||||
old_icon.destroy ();
|
||||
old_icon = null;
|
||||
}
|
||||
}
|
||||
|
||||
icon = new_icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ namespace Gala
|
||||
|
||||
public WindowManager wm { get; construct; }
|
||||
|
||||
Utils.WindowIcon? current_window = null;
|
||||
WindowIcon? current_window = null;
|
||||
|
||||
Actor window_clones;
|
||||
List<Actor> clone_sort_order;
|
||||
@ -276,7 +276,7 @@ namespace Gala
|
||||
}
|
||||
|
||||
bool clicked_icon (Clutter.ButtonEvent event) {
|
||||
unowned Utils.WindowIcon icon = (Utils.WindowIcon) event.source;
|
||||
unowned WindowIcon icon = (WindowIcon) event.source;
|
||||
|
||||
if (current_window != icon) {
|
||||
current_window = icon;
|
||||
@ -306,9 +306,9 @@ namespace Gala
|
||||
}
|
||||
|
||||
if (actor == current_window) {
|
||||
current_window = (Utils.WindowIcon) current_window.get_next_sibling ();
|
||||
current_window = (WindowIcon) current_window.get_next_sibling ();
|
||||
if (current_window == null)
|
||||
current_window = (Utils.WindowIcon) dock.get_first_child ();
|
||||
current_window = (WindowIcon) dock.get_first_child ();
|
||||
|
||||
dim_windows ();
|
||||
}
|
||||
@ -493,7 +493,7 @@ namespace Gala
|
||||
close_cleanup ();
|
||||
}
|
||||
|
||||
Utils.WindowIcon? add_window (Window window)
|
||||
WindowIcon? add_window (Window window)
|
||||
{
|
||||
var actor = window.get_compositor_private () as WindowActor;
|
||||
if (actor == null)
|
||||
@ -507,7 +507,7 @@ namespace Gala
|
||||
|
||||
window_clones.add_child (clone);
|
||||
|
||||
var icon = new Utils.WindowIcon (window, dock_settings.IconSize, true);
|
||||
var icon = new WindowIcon (window, dock_settings.IconSize, true);
|
||||
icon.reactive = true;
|
||||
icon.opacity = 100;
|
||||
icon.x_expand = true;
|
||||
@ -545,7 +545,7 @@ namespace Gala
|
||||
}
|
||||
|
||||
foreach (var actor in dock.get_children ()) {
|
||||
unowned Utils.WindowIcon icon = (Utils.WindowIcon) actor;
|
||||
unowned WindowIcon icon = (WindowIcon) actor;
|
||||
icon.save_easing_state ();
|
||||
icon.set_easing_duration (100);
|
||||
icon.set_easing_mode (AnimationMode.LINEAR);
|
||||
@ -602,7 +602,7 @@ namespace Gala
|
||||
clone_sort_order = window_clones.get_children ().copy ();
|
||||
|
||||
if (current_window == null)
|
||||
current_window = (Utils.WindowIcon) dock.get_child_at_index (0);
|
||||
current_window = (WindowIcon) dock.get_child_at_index (0);
|
||||
|
||||
// hide the others
|
||||
foreach (var actor in Compositor.get_window_actors (screen)) {
|
||||
@ -624,7 +624,7 @@ namespace Gala
|
||||
return true;
|
||||
}
|
||||
|
||||
Utils.WindowIcon next_window (Workspace workspace, bool backward)
|
||||
WindowIcon next_window (Workspace workspace, bool backward)
|
||||
{
|
||||
Actor actor;
|
||||
if (!backward) {
|
||||
@ -637,7 +637,7 @@ namespace Gala
|
||||
actor = dock.get_last_child ();
|
||||
}
|
||||
|
||||
return (Utils.WindowIcon) actor;
|
||||
return (WindowIcon) actor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
128
src/Widgets/WorkspaceInsertThumb.vala
Normal file
128
src/Widgets/WorkspaceInsertThumb.vala
Normal file
@ -0,0 +1,128 @@
|
||||
//
|
||||
// Copyright (C) 2014 Tom Beckmann
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
using Clutter;
|
||||
using Meta;
|
||||
|
||||
namespace Gala
|
||||
{
|
||||
public class WorkspaceInsertThumb : Actor
|
||||
{
|
||||
public const int EXPAND_DELAY = 300;
|
||||
|
||||
public int workspace_index { get; construct set; }
|
||||
public bool expanded { get; private set; default = false; }
|
||||
|
||||
uint expand_timeout = 0;
|
||||
|
||||
public WorkspaceInsertThumb (int workspace_index)
|
||||
{
|
||||
Object (workspace_index: workspace_index);
|
||||
|
||||
width = IconGroupContainer.SPACING;
|
||||
height = IconGroupContainer.GROUP_WIDTH;
|
||||
y = (IconGroupContainer.GROUP_WIDTH - IconGroupContainer.SPACING) / 2;
|
||||
opacity = 0;
|
||||
set_pivot_point (0.5f, 0.5f);
|
||||
reactive = true;
|
||||
|
||||
layout_manager = new BinLayout (BinAlignment.CENTER);
|
||||
|
||||
var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
||||
drop.crossed.connect ((hovered) => {
|
||||
if (!Prefs.get_dynamic_workspaces ())
|
||||
return;
|
||||
|
||||
if (!hovered) {
|
||||
if (expand_timeout != 0) {
|
||||
Source.remove (expand_timeout);
|
||||
expand_timeout = 0;
|
||||
}
|
||||
|
||||
transform (false);
|
||||
} else
|
||||
expand_timeout = Timeout.add (EXPAND_DELAY, expand);
|
||||
});
|
||||
|
||||
add_action (drop);
|
||||
}
|
||||
|
||||
public void set_window_thumb (Window window)
|
||||
{
|
||||
destroy_all_children ();
|
||||
|
||||
var icon = new WindowIcon (window, IconGroupContainer.GROUP_WIDTH);
|
||||
icon.x_align = ActorAlign.CENTER;
|
||||
add_child (icon);
|
||||
}
|
||||
|
||||
bool expand ()
|
||||
{
|
||||
expand_timeout = 0;
|
||||
|
||||
transform (true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void transform (bool expand)
|
||||
{
|
||||
save_easing_state ();
|
||||
set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||
set_easing_duration (200);
|
||||
|
||||
if (!expand) {
|
||||
remove_transition ("pulse");
|
||||
opacity = 0;
|
||||
width = IconGroupContainer.SPACING;
|
||||
expanded = false;
|
||||
} else {
|
||||
add_pulse_animation ();
|
||||
opacity = 200;
|
||||
width = IconGroupContainer.GROUP_WIDTH + IconGroupContainer.SPACING * 2;
|
||||
expanded = true;
|
||||
}
|
||||
|
||||
restore_easing_state ();
|
||||
}
|
||||
|
||||
void add_pulse_animation ()
|
||||
{
|
||||
var transition = new TransitionGroup ();
|
||||
transition.duration = 800;
|
||||
transition.auto_reverse = true;
|
||||
transition.repeat_count = -1;
|
||||
transition.progress_mode = AnimationMode.LINEAR;
|
||||
|
||||
var scale_x_transition = new PropertyTransition ("scale-x");
|
||||
scale_x_transition.set_from_value (0.8);
|
||||
scale_x_transition.set_to_value (1.1);
|
||||
scale_x_transition.auto_reverse = true;
|
||||
|
||||
var scale_y_transition = new PropertyTransition ("scale-y");
|
||||
scale_y_transition.set_from_value (0.8);
|
||||
scale_y_transition.set_to_value (1.1);
|
||||
scale_y_transition.auto_reverse = true;
|
||||
|
||||
transition.add_transition (scale_x_transition);
|
||||
transition.add_transition (scale_y_transition);
|
||||
|
||||
add_transition ("pulse", transition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user