mirror of
https://github.com/elementary/gala.git
synced 2024-09-11 07:05:30 +03:00
Convert all tabs to spaces (#684)
This commit is contained in:
parent
548ec08d89
commit
97cb42fb2d
@ -20,209 +20,209 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala.Plugins.MaskCorners
|
namespace Gala.Plugins.MaskCorners
|
||||||
{
|
{
|
||||||
public class Main : Gala.Plugin
|
public class Main : Gala.Plugin
|
||||||
{
|
{
|
||||||
Gala.WindowManager? wm = null;
|
Gala.WindowManager? wm = null;
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
Display display;
|
Display display;
|
||||||
#else
|
#else
|
||||||
Screen screen;
|
Screen screen;
|
||||||
#endif
|
#endif
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
List<Actor>[] cornermasks;
|
List<Actor>[] cornermasks;
|
||||||
int corner_radius = 4;
|
int corner_radius = 4;
|
||||||
|
|
||||||
public override void initialize (Gala.WindowManager wm)
|
public override void initialize (Gala.WindowManager wm)
|
||||||
{
|
{
|
||||||
this.wm = wm;
|
this.wm = wm;
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display = wm.get_display ();
|
display = wm.get_display ();
|
||||||
#else
|
#else
|
||||||
screen = wm.get_screen ();
|
screen = wm.get_screen ();
|
||||||
#endif
|
#endif
|
||||||
settings = Settings.get_default ();
|
settings = Settings.get_default ();
|
||||||
|
|
||||||
setup_cornermasks ();
|
setup_cornermasks ();
|
||||||
|
|
||||||
settings.changed.connect (resetup_cornermasks);
|
settings.changed.connect (resetup_cornermasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void destroy ()
|
public override void destroy ()
|
||||||
{
|
{
|
||||||
destroy_cornermasks ();
|
destroy_cornermasks ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_cornermasks ()
|
void setup_cornermasks ()
|
||||||
{
|
{
|
||||||
if (!settings.enable)
|
if (!settings.enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
int n_monitors = display.get_n_monitors ();
|
int n_monitors = display.get_n_monitors ();
|
||||||
#else
|
#else
|
||||||
int n_monitors = screen.get_n_monitors ();
|
int n_monitors = screen.get_n_monitors ();
|
||||||
#endif
|
#endif
|
||||||
cornermasks = new List<Actor>[n_monitors];
|
cornermasks = new List<Actor>[n_monitors];
|
||||||
corner_radius = settings.corner_radius * scale;
|
corner_radius = settings.corner_radius * scale;
|
||||||
|
|
||||||
if (settings.only_on_primary) {
|
if (settings.only_on_primary) {
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
add_cornermasks (display.get_primary_monitor ());
|
add_cornermasks (display.get_primary_monitor ());
|
||||||
#else
|
#else
|
||||||
add_cornermasks (screen.get_primary_monitor ());
|
add_cornermasks (screen.get_primary_monitor ());
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
for (int m = 0; m < n_monitors; m++)
|
for (int m = 0; m < n_monitors; m++)
|
||||||
add_cornermasks (m);
|
add_cornermasks (m);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
if (settings.disable_on_fullscreen)
|
if (settings.disable_on_fullscreen)
|
||||||
display.in_fullscreen_changed.connect (fullscreen_changed);
|
display.in_fullscreen_changed.connect (fullscreen_changed);
|
||||||
|
|
||||||
unowned Meta.MonitorManager monitor_manager = Meta.MonitorManager.@get ();
|
unowned Meta.MonitorManager monitor_manager = Meta.MonitorManager.@get ();
|
||||||
monitor_manager.monitors_changed.connect (resetup_cornermasks);
|
monitor_manager.monitors_changed.connect (resetup_cornermasks);
|
||||||
|
|
||||||
display.gl_video_memory_purged.connect (resetup_cornermasks);
|
display.gl_video_memory_purged.connect (resetup_cornermasks);
|
||||||
#else
|
#else
|
||||||
if (settings.disable_on_fullscreen)
|
if (settings.disable_on_fullscreen)
|
||||||
screen.in_fullscreen_changed.connect (fullscreen_changed);
|
screen.in_fullscreen_changed.connect (fullscreen_changed);
|
||||||
|
|
||||||
screen.monitors_changed.connect (resetup_cornermasks);
|
screen.monitors_changed.connect (resetup_cornermasks);
|
||||||
|
|
||||||
screen.get_display ().gl_video_memory_purged.connect (resetup_cornermasks);
|
screen.get_display ().gl_video_memory_purged.connect (resetup_cornermasks);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_cornermasks ()
|
void destroy_cornermasks ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.gl_video_memory_purged.disconnect (resetup_cornermasks);
|
display.gl_video_memory_purged.disconnect (resetup_cornermasks);
|
||||||
#else
|
#else
|
||||||
screen.get_display ().gl_video_memory_purged.disconnect (resetup_cornermasks);
|
screen.get_display ().gl_video_memory_purged.disconnect (resetup_cornermasks);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.MonitorManager monitor_manager = Meta.MonitorManager.@get ();
|
unowned Meta.MonitorManager monitor_manager = Meta.MonitorManager.@get ();
|
||||||
monitor_manager.monitors_changed.disconnect (resetup_cornermasks);
|
monitor_manager.monitors_changed.disconnect (resetup_cornermasks);
|
||||||
display.in_fullscreen_changed.disconnect (fullscreen_changed);
|
display.in_fullscreen_changed.disconnect (fullscreen_changed);
|
||||||
#else
|
#else
|
||||||
screen.monitors_changed.disconnect (resetup_cornermasks);
|
screen.monitors_changed.disconnect (resetup_cornermasks);
|
||||||
screen.in_fullscreen_changed.disconnect (fullscreen_changed);
|
screen.in_fullscreen_changed.disconnect (fullscreen_changed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
foreach (unowned List<Actor> list in cornermasks) {
|
foreach (unowned List<Actor> list in cornermasks) {
|
||||||
foreach (Actor actor in list)
|
foreach (Actor actor in list)
|
||||||
actor.destroy ();
|
actor.destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetup_cornermasks ()
|
void resetup_cornermasks ()
|
||||||
{
|
{
|
||||||
destroy_cornermasks ();
|
destroy_cornermasks ();
|
||||||
setup_cornermasks ();
|
setup_cornermasks ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fullscreen_changed ()
|
void fullscreen_changed ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
for (int i = 0; i < display.get_n_monitors (); i++) {
|
for (int i = 0; i < display.get_n_monitors (); i++) {
|
||||||
foreach (Actor actor in cornermasks[i]) {
|
foreach (Actor actor in cornermasks[i]) {
|
||||||
if (display.get_monitor_in_fullscreen (i))
|
if (display.get_monitor_in_fullscreen (i))
|
||||||
actor.hide ();
|
actor.hide ();
|
||||||
else
|
else
|
||||||
actor.show ();
|
actor.show ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for (int i = 0; i < screen.get_n_monitors (); i++) {
|
for (int i = 0; i < screen.get_n_monitors (); i++) {
|
||||||
foreach (Actor actor in cornermasks[i]) {
|
foreach (Actor actor in cornermasks[i]) {
|
||||||
if (screen.get_monitor_in_fullscreen (i))
|
if (screen.get_monitor_in_fullscreen (i))
|
||||||
actor.hide ();
|
actor.hide ();
|
||||||
else
|
else
|
||||||
actor.show ();
|
actor.show ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_cornermasks (int monitor_no)
|
void add_cornermasks (int monitor_no)
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var monitor_geometry = display.get_monitor_geometry (monitor_no);
|
var monitor_geometry = display.get_monitor_geometry (monitor_no);
|
||||||
#else
|
#else
|
||||||
var monitor_geometry = screen.get_monitor_geometry (monitor_no);
|
var monitor_geometry = screen.get_monitor_geometry (monitor_no);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Canvas canvas = new Canvas ();
|
Canvas canvas = new Canvas ();
|
||||||
canvas.set_size (corner_radius, corner_radius);
|
canvas.set_size (corner_radius, corner_radius);
|
||||||
canvas.draw.connect (draw_cornermask);
|
canvas.draw.connect (draw_cornermask);
|
||||||
canvas.invalidate ();
|
canvas.invalidate ();
|
||||||
|
|
||||||
Actor actor = new Actor ();
|
Actor actor = new Actor ();
|
||||||
actor.set_content (canvas);
|
actor.set_content (canvas);
|
||||||
actor.set_size (corner_radius, corner_radius);
|
actor.set_size (corner_radius, corner_radius);
|
||||||
actor.set_position (monitor_geometry.x, monitor_geometry.y);
|
actor.set_position (monitor_geometry.x, monitor_geometry.y);
|
||||||
actor.set_pivot_point ((float) 0.5, (float) 0.5);
|
actor.set_pivot_point ((float) 0.5, (float) 0.5);
|
||||||
|
|
||||||
cornermasks[monitor_no].append (actor);
|
cornermasks[monitor_no].append (actor);
|
||||||
wm.stage.add_child (actor);
|
wm.stage.add_child (actor);
|
||||||
|
|
||||||
for (int p = 1; p < 4; p++) {
|
for (int p = 1; p < 4; p++) {
|
||||||
Clone clone = new Clone (actor);
|
Clone clone = new Clone (actor);
|
||||||
clone.rotation_angle_z = p * 90;
|
clone.rotation_angle_z = p * 90;
|
||||||
|
|
||||||
switch (p) {
|
switch (p) {
|
||||||
case 1:
|
case 1:
|
||||||
clone.set_position (monitor_geometry.x + monitor_geometry.width, monitor_geometry.y);
|
clone.set_position (monitor_geometry.x + monitor_geometry.width, monitor_geometry.y);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
clone.set_position (monitor_geometry.x + monitor_geometry.width, monitor_geometry.y + monitor_geometry.height);
|
clone.set_position (monitor_geometry.x + monitor_geometry.width, monitor_geometry.y + monitor_geometry.height);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
clone.set_position (monitor_geometry.x, monitor_geometry.y + monitor_geometry.height);
|
clone.set_position (monitor_geometry.x, monitor_geometry.y + monitor_geometry.height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cornermasks[monitor_no].append (clone);
|
cornermasks[monitor_no].append (clone);
|
||||||
wm.stage.add_child (clone);
|
wm.stage.add_child (clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool draw_cornermask (Cairo.Context context)
|
bool draw_cornermask (Cairo.Context context)
|
||||||
{
|
{
|
||||||
var buffer = new Granite.Drawing.BufferSurface (corner_radius, corner_radius);
|
var buffer = new Granite.Drawing.BufferSurface (corner_radius, corner_radius);
|
||||||
var buffer_context = buffer.context;
|
var buffer_context = buffer.context;
|
||||||
|
|
||||||
buffer_context.arc (corner_radius, corner_radius, corner_radius, Math.PI, 1.5 * Math.PI);
|
buffer_context.arc (corner_radius, corner_radius, corner_radius, Math.PI, 1.5 * Math.PI);
|
||||||
buffer_context.line_to (0, 0);
|
buffer_context.line_to (0, 0);
|
||||||
buffer_context.line_to (0, corner_radius);
|
buffer_context.line_to (0, corner_radius);
|
||||||
buffer_context.set_source_rgb (0, 0, 0);
|
buffer_context.set_source_rgb (0, 0, 0);
|
||||||
buffer_context.fill ();
|
buffer_context.fill ();
|
||||||
|
|
||||||
context.set_operator (Cairo.Operator.CLEAR);
|
context.set_operator (Cairo.Operator.CLEAR);
|
||||||
context.paint ();
|
context.paint ();
|
||||||
context.set_operator (Cairo.Operator.OVER);
|
context.set_operator (Cairo.Operator.OVER);
|
||||||
context.set_source_surface (buffer.surface, 0, 0);
|
context.set_source_surface (buffer.surface, 0, 0);
|
||||||
context.paint ();
|
context.paint ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gala.PluginInfo register_plugin ()
|
public Gala.PluginInfo register_plugin ()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
"Mask Corners",
|
"Mask Corners",
|
||||||
"Gala Developers",
|
"Gala Developers",
|
||||||
typeof (Gala.Plugins.MaskCorners.Main),
|
typeof (Gala.Plugins.MaskCorners.Main),
|
||||||
Gala.PluginFunction.ADDITION,
|
Gala.PluginFunction.ADDITION,
|
||||||
Gala.LoadPriority.IMMEDIATE
|
Gala.LoadPriority.IMMEDIATE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,26 +17,26 @@
|
|||||||
|
|
||||||
namespace Gala.Plugins.MaskCorners
|
namespace Gala.Plugins.MaskCorners
|
||||||
{
|
{
|
||||||
class Settings : Granite.Services.Settings
|
class Settings : Granite.Services.Settings
|
||||||
{
|
{
|
||||||
static Settings? instance = null;
|
static Settings? instance = null;
|
||||||
|
|
||||||
public static unowned Settings get_default ()
|
public static unowned Settings get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new Settings ();
|
instance = new Settings ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool enable { get; set; default = true; }
|
public bool enable { get; set; default = true; }
|
||||||
public int corner_radius { get; set; default = 4; }
|
public int corner_radius { get; set; default = 4; }
|
||||||
public bool disable_on_fullscreen { get; set; default = true; }
|
public bool disable_on_fullscreen { get; set; default = true; }
|
||||||
public bool only_on_primary { get; set; default = false; }
|
public bool only_on_primary { get; set; default = false; }
|
||||||
|
|
||||||
Settings ()
|
Settings ()
|
||||||
{
|
{
|
||||||
base (Config.SCHEMA + ".mask-corners");
|
base (Config.SCHEMA + ".mask-corners");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,115 +20,115 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala.Plugins.Notify
|
namespace Gala.Plugins.Notify
|
||||||
{
|
{
|
||||||
public class ConfirmationNotification : Notification
|
public class ConfirmationNotification : Notification
|
||||||
{
|
{
|
||||||
const int DURATION = 2000;
|
const int DURATION = 2000;
|
||||||
const int PROGRESS_HEIGHT = 6;
|
const int PROGRESS_HEIGHT = 6;
|
||||||
|
|
||||||
public bool has_progress { get; private set; }
|
public bool has_progress { get; private set; }
|
||||||
|
|
||||||
int _progress;
|
int _progress;
|
||||||
public int progress {
|
public int progress {
|
||||||
get {
|
get {
|
||||||
return _progress;
|
return _progress;
|
||||||
}
|
}
|
||||||
private set {
|
private set {
|
||||||
_progress = value;
|
_progress = value;
|
||||||
content.invalidate ();
|
content.invalidate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string confirmation_type { get; private set; }
|
public string confirmation_type { get; private set; }
|
||||||
|
|
||||||
int old_progress;
|
int old_progress;
|
||||||
|
|
||||||
public ConfirmationNotification (uint32 id, Gdk.Pixbuf? icon, bool icon_only,
|
public ConfirmationNotification (uint32 id, Gdk.Pixbuf? icon, bool icon_only,
|
||||||
int progress, string confirmation_type)
|
int progress, string confirmation_type)
|
||||||
{
|
{
|
||||||
Object (id: id, icon: icon, urgency: NotificationUrgency.LOW, expire_timeout: DURATION);
|
Object (id: id, icon: icon, urgency: NotificationUrgency.LOW, expire_timeout: DURATION);
|
||||||
|
|
||||||
this.icon_only = icon_only;
|
this.icon_only = icon_only;
|
||||||
this.has_progress = progress > -1;
|
this.has_progress = progress > -1;
|
||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
this.confirmation_type = confirmation_type;
|
this.confirmation_type = confirmation_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void update_allocation (out float content_height, AllocationFlags flags)
|
public override void update_allocation (out float content_height, AllocationFlags flags)
|
||||||
{
|
{
|
||||||
content_height = ICON_SIZE * style_context.get_scale ();
|
content_height = ICON_SIZE * style_context.get_scale ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void draw_content (Cairo.Context cr)
|
public override void draw_content (Cairo.Context cr)
|
||||||
{
|
{
|
||||||
if (!has_progress)
|
if (!has_progress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var scale = style_context.get_scale ();
|
var scale = style_context.get_scale ();
|
||||||
var scaled_margin = MARGIN * scale;
|
var scaled_margin = MARGIN * scale;
|
||||||
var scaled_width = WIDTH * scale;
|
var scaled_width = WIDTH * scale;
|
||||||
var x = (MARGIN + PADDING + ICON_SIZE + SPACING) * scale;
|
var x = (MARGIN + PADDING + ICON_SIZE + SPACING) * scale;
|
||||||
var y = (MARGIN + PADDING + (ICON_SIZE - PROGRESS_HEIGHT) / 2) * scale;
|
var y = (MARGIN + PADDING + (ICON_SIZE - PROGRESS_HEIGHT) / 2) * scale;
|
||||||
var width = scaled_width - x - scaled_margin;
|
var width = scaled_width - x - scaled_margin;
|
||||||
|
|
||||||
if (!transitioning)
|
if (!transitioning)
|
||||||
draw_progress_bar (cr, x, y, width, progress);
|
draw_progress_bar (cr, x, y, width, progress);
|
||||||
else {
|
else {
|
||||||
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, scaled_margin, scaled_margin, scaled_width - scaled_margin * 2, ICON_SIZE * scale + PADDING * 2 * scale, 4 * scale);
|
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, scaled_margin, scaled_margin, scaled_width - scaled_margin * 2, ICON_SIZE * scale + PADDING * 2 * scale, 4 * scale);
|
||||||
cr.clip ();
|
cr.clip ();
|
||||||
|
|
||||||
draw_progress_bar (cr, x, y + animation_slide_y_offset, width, old_progress);
|
draw_progress_bar (cr, x, y + animation_slide_y_offset, width, old_progress);
|
||||||
draw_progress_bar (cr, x, y + animation_slide_y_offset - animation_slide_height, width, progress);
|
draw_progress_bar (cr, x, y + animation_slide_y_offset - animation_slide_height, width, progress);
|
||||||
|
|
||||||
cr.reset_clip ();
|
cr.reset_clip ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_progress_bar (Cairo.Context cr, int x, float y, int width, int progress)
|
void draw_progress_bar (Cairo.Context cr, int x, float y, int width, int progress)
|
||||||
{
|
{
|
||||||
var fraction = (int) Math.floor (progress.clamp (0, 100) / 100.0 * width);
|
var fraction = (int) Math.floor (progress.clamp (0, 100) / 100.0 * width);
|
||||||
|
|
||||||
var scale = style_context.get_scale ();
|
var scale = style_context.get_scale ();
|
||||||
var scaled_progress_height = PROGRESS_HEIGHT * scale;
|
var scaled_progress_height = PROGRESS_HEIGHT * scale;
|
||||||
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, width,
|
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, width,
|
||||||
scaled_progress_height, scaled_progress_height / 2);
|
scaled_progress_height, scaled_progress_height / 2);
|
||||||
cr.set_source_rgb (0.8, 0.8, 0.8);
|
cr.set_source_rgb (0.8, 0.8, 0.8);
|
||||||
cr.fill ();
|
cr.fill ();
|
||||||
|
|
||||||
if (progress > 0) {
|
if (progress > 0) {
|
||||||
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, fraction,
|
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, fraction,
|
||||||
scaled_progress_height, scaled_progress_height / 2);
|
scaled_progress_height, scaled_progress_height / 2);
|
||||||
cr.set_source_rgb (0.3, 0.3, 0.3);
|
cr.set_source_rgb (0.3, 0.3, 0.3);
|
||||||
cr.fill ();
|
cr.fill ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void update_slide_animation ()
|
protected override void update_slide_animation ()
|
||||||
{
|
{
|
||||||
// just trigger the draw function, which will move our progress bar down
|
// just trigger the draw function, which will move our progress bar down
|
||||||
content.invalidate ();
|
content.invalidate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update (Gdk.Pixbuf? icon, int progress, string confirmation_type,
|
public void update (Gdk.Pixbuf? icon, int progress, string confirmation_type,
|
||||||
bool icon_only)
|
bool icon_only)
|
||||||
{
|
{
|
||||||
if (this.confirmation_type != confirmation_type) {
|
if (this.confirmation_type != confirmation_type) {
|
||||||
this.confirmation_type = confirmation_type;
|
this.confirmation_type = confirmation_type;
|
||||||
|
|
||||||
old_progress = this.progress;
|
old_progress = this.progress;
|
||||||
|
|
||||||
var scale = style_context.get_scale ();
|
var scale = style_context.get_scale ();
|
||||||
play_update_transition ((ICON_SIZE + PADDING * 2) * scale);
|
play_update_transition ((ICON_SIZE + PADDING * 2) * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.icon_only != icon_only) {
|
if (this.icon_only != icon_only) {
|
||||||
this.icon_only = icon_only;
|
this.icon_only = icon_only;
|
||||||
queue_relayout ();
|
queue_relayout ();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.has_progress = progress > -1;
|
this.has_progress = progress > -1;
|
||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
|
|
||||||
update_base (icon, DURATION);
|
update_base (icon, DURATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,97 +20,97 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala.Plugins.Notify
|
namespace Gala.Plugins.Notify
|
||||||
{
|
{
|
||||||
public class Main : Gala.Plugin
|
public class Main : Gala.Plugin
|
||||||
{
|
{
|
||||||
Gala.WindowManager? wm = null;
|
Gala.WindowManager? wm = null;
|
||||||
|
|
||||||
NotifyServer server;
|
NotifyServer server;
|
||||||
NotificationStack stack;
|
NotificationStack stack;
|
||||||
|
|
||||||
public override void initialize (Gala.WindowManager wm)
|
public override void initialize (Gala.WindowManager wm)
|
||||||
{
|
{
|
||||||
this.wm = wm;
|
this.wm = wm;
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = wm.get_display ();
|
unowned Meta.Display display = wm.get_display ();
|
||||||
#else
|
#else
|
||||||
var screen = wm.get_screen ();
|
var screen = wm.get_screen ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
stack = new NotificationStack (display);
|
stack = new NotificationStack (display);
|
||||||
#else
|
#else
|
||||||
stack = new NotificationStack (screen);
|
stack = new NotificationStack (screen);
|
||||||
#endif
|
#endif
|
||||||
wm.ui_group.add_child (stack);
|
wm.ui_group.add_child (stack);
|
||||||
track_actor (stack);
|
track_actor (stack);
|
||||||
|
|
||||||
stack.animations_changed.connect ((running) => {
|
stack.animations_changed.connect ((running) => {
|
||||||
freeze_track = running;
|
freeze_track = running;
|
||||||
});
|
});
|
||||||
|
|
||||||
server = new NotifyServer (stack);
|
server = new NotifyServer (stack);
|
||||||
|
|
||||||
update_position ();
|
update_position ();
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.MonitorManager monitor_manager = Meta.MonitorManager.@get ();
|
unowned Meta.MonitorManager monitor_manager = Meta.MonitorManager.@get ();
|
||||||
monitor_manager.monitors_changed.connect (update_position);
|
monitor_manager.monitors_changed.connect (update_position);
|
||||||
display.workareas_changed.connect (update_position);
|
display.workareas_changed.connect (update_position);
|
||||||
#else
|
#else
|
||||||
screen.monitors_changed.connect (update_position);
|
screen.monitors_changed.connect (update_position);
|
||||||
screen.workareas_changed.connect (update_position);
|
screen.workareas_changed.connect (update_position);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.freedesktop.Notifications", BusNameOwnerFlags.NONE,
|
Bus.own_name (BusType.SESSION, "org.freedesktop.Notifications", BusNameOwnerFlags.NONE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/freedesktop/Notifications", server);
|
connection.register_object ("/org/freedesktop/Notifications", server);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
warning ("Registring notification server failed: %s", e.message);
|
warning ("Registring notification server failed: %s", e.message);
|
||||||
destroy ();
|
destroy ();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
(con, name) => {
|
(con, name) => {
|
||||||
warning ("Could not aquire bus %s", name);
|
warning ("Could not aquire bus %s", name);
|
||||||
destroy ();
|
destroy ();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_position ()
|
void update_position ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = wm.get_display ();
|
unowned Meta.Display display = wm.get_display ();
|
||||||
var primary = display.get_primary_monitor ();
|
var primary = display.get_primary_monitor ();
|
||||||
var area = display.get_workspace_manager ().get_active_workspace ().get_work_area_for_monitor (primary);
|
var area = display.get_workspace_manager ().get_active_workspace ().get_work_area_for_monitor (primary);
|
||||||
#else
|
#else
|
||||||
var screen = wm.get_screen ();
|
var screen = wm.get_screen ();
|
||||||
var primary = screen.get_primary_monitor ();
|
var primary = screen.get_primary_monitor ();
|
||||||
var area = screen.get_active_workspace ().get_work_area_for_monitor (primary);
|
var area = screen.get_active_workspace ().get_work_area_for_monitor (primary);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stack.x = area.x + area.width - stack.width;
|
stack.x = area.x + area.width - stack.width;
|
||||||
stack.y = area.y;
|
stack.y = area.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void destroy ()
|
public override void destroy ()
|
||||||
{
|
{
|
||||||
if (wm == null)
|
if (wm == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
untrack_actor (stack);
|
untrack_actor (stack);
|
||||||
stack.destroy ();
|
stack.destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gala.PluginInfo register_plugin ()
|
public Gala.PluginInfo register_plugin ()
|
||||||
{
|
{
|
||||||
return Gala.PluginInfo () {
|
return Gala.PluginInfo () {
|
||||||
name = "Notify",
|
name = "Notify",
|
||||||
author = "Gala Developers",
|
author = "Gala Developers",
|
||||||
plugin_type = typeof (Gala.Plugins.Notify.Main),
|
plugin_type = typeof (Gala.Plugins.Notify.Main),
|
||||||
provides = Gala.PluginFunction.ADDITION,
|
provides = Gala.PluginFunction.ADDITION,
|
||||||
load_priority = Gala.LoadPriority.IMMEDIATE
|
load_priority = Gala.LoadPriority.IMMEDIATE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,354 +20,354 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala.Plugins.Notify
|
namespace Gala.Plugins.Notify
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Wrapper class only containing the summary and body label. Allows us to
|
* Wrapper class only containing the summary and body label. Allows us to
|
||||||
* instantiate the content very easily for when we need to slide the old
|
* instantiate the content very easily for when we need to slide the old
|
||||||
* and new content down.
|
* and new content down.
|
||||||
*/
|
*/
|
||||||
class NormalNotificationContent : Actor
|
class NormalNotificationContent : Actor
|
||||||
{
|
{
|
||||||
static Regex entity_regex;
|
static Regex entity_regex;
|
||||||
static Regex tag_regex;
|
static Regex tag_regex;
|
||||||
|
|
||||||
static construct
|
static construct
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
entity_regex = new Regex ("&(?!amp;|quot;|apos;|lt;|gt;)");
|
entity_regex = new Regex ("&(?!amp;|quot;|apos;|lt;|gt;)");
|
||||||
tag_regex = new Regex ("<(?!\\/?[biu]>)");
|
tag_regex = new Regex ("<(?!\\/?[biu]>)");
|
||||||
} catch (Error e) {}
|
} catch (Error e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int LABEL_SPACING = 2;
|
const int LABEL_SPACING = 2;
|
||||||
|
|
||||||
Text summary_label;
|
Text summary_label;
|
||||||
Text body_label;
|
Text body_label;
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
summary_label = new Text.with_text (null, "");
|
summary_label = new Text.with_text (null, "");
|
||||||
summary_label.line_wrap = true;
|
summary_label.line_wrap = true;
|
||||||
summary_label.use_markup = true;
|
summary_label.use_markup = true;
|
||||||
summary_label.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
summary_label.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
||||||
|
|
||||||
body_label = new Text.with_text (null, "");
|
body_label = new Text.with_text (null, "");
|
||||||
body_label.line_wrap = true;
|
body_label.line_wrap = true;
|
||||||
body_label.use_markup = true;
|
body_label.use_markup = true;
|
||||||
body_label.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
body_label.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
||||||
|
|
||||||
var style_path = new Gtk.WidgetPath ();
|
var style_path = new Gtk.WidgetPath ();
|
||||||
style_path.append_type (typeof (Gtk.Window));
|
style_path.append_type (typeof (Gtk.Window));
|
||||||
style_path.append_type (typeof (Gtk.EventBox));
|
style_path.append_type (typeof (Gtk.EventBox));
|
||||||
style_path.iter_add_class (1, "gala-notification");
|
style_path.iter_add_class (1, "gala-notification");
|
||||||
style_path.append_type (typeof (Gtk.Label));
|
style_path.append_type (typeof (Gtk.Label));
|
||||||
|
|
||||||
var label_style_context = new Gtk.StyleContext ();
|
var label_style_context = new Gtk.StyleContext ();
|
||||||
label_style_context.add_provider (Gala.Utils.get_gala_css (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
|
label_style_context.add_provider (Gala.Utils.get_gala_css (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
|
||||||
label_style_context.set_path (style_path);
|
label_style_context.set_path (style_path);
|
||||||
|
|
||||||
Gdk.RGBA color;
|
Gdk.RGBA color;
|
||||||
|
|
||||||
label_style_context.save ();
|
label_style_context.save ();
|
||||||
label_style_context.add_class ("title");
|
label_style_context.add_class ("title");
|
||||||
color = label_style_context.get_color (Gtk.StateFlags.NORMAL);
|
color = label_style_context.get_color (Gtk.StateFlags.NORMAL);
|
||||||
summary_label.color = {
|
summary_label.color = {
|
||||||
(uint8) (color.red * 255),
|
(uint8) (color.red * 255),
|
||||||
(uint8) (color.green * 255),
|
(uint8) (color.green * 255),
|
||||||
(uint8) (color.blue * 255),
|
(uint8) (color.blue * 255),
|
||||||
(uint8) (color.alpha * 255)
|
(uint8) (color.alpha * 255)
|
||||||
};
|
};
|
||||||
label_style_context.restore ();
|
label_style_context.restore ();
|
||||||
|
|
||||||
label_style_context.save ();
|
label_style_context.save ();
|
||||||
label_style_context.add_class ("label");
|
label_style_context.add_class ("label");
|
||||||
color = label_style_context.get_color (Gtk.StateFlags.NORMAL);
|
color = label_style_context.get_color (Gtk.StateFlags.NORMAL);
|
||||||
body_label.color = {
|
body_label.color = {
|
||||||
(uint8) (color.red * 255),
|
(uint8) (color.red * 255),
|
||||||
(uint8) (color.green * 255),
|
(uint8) (color.green * 255),
|
||||||
(uint8) (color.blue * 255),
|
(uint8) (color.blue * 255),
|
||||||
(uint8) (color.alpha * 255)
|
(uint8) (color.alpha * 255)
|
||||||
};
|
};
|
||||||
label_style_context.restore ();
|
label_style_context.restore ();
|
||||||
|
|
||||||
add_child (summary_label);
|
add_child (summary_label);
|
||||||
add_child (body_label);
|
add_child (body_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_values (string summary, string body)
|
public void set_values (string summary, string body)
|
||||||
{
|
{
|
||||||
summary_label.set_markup ("<b>%s</b>".printf (fix_markup (summary)));
|
summary_label.set_markup ("<b>%s</b>".printf (fix_markup (summary)));
|
||||||
body_label.set_markup (fix_markup (body));
|
body_label.set_markup (fix_markup (body));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
|
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
|
||||||
{
|
{
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
float label_height;
|
float label_height;
|
||||||
get_allocation_values (null, null, null, null, out label_height, null, scale);
|
get_allocation_values (null, null, null, null, out label_height, null, scale);
|
||||||
|
|
||||||
min_height = nat_height = label_height;
|
min_height = nat_height = label_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void allocate (ActorBox box, AllocationFlags flags)
|
public override void allocate (ActorBox box, AllocationFlags flags)
|
||||||
{
|
{
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
float label_x, label_width, summary_height, body_height, label_height, label_y;
|
float label_x, label_width, summary_height, body_height, label_height, label_y;
|
||||||
get_allocation_values (out label_x, out label_width, out summary_height,
|
get_allocation_values (out label_x, out label_width, out summary_height,
|
||||||
out body_height, out label_height, out label_y, scale);
|
out body_height, out label_height, out label_y, scale);
|
||||||
|
|
||||||
var summary_alloc = ActorBox ();
|
var summary_alloc = ActorBox ();
|
||||||
summary_alloc.set_origin (label_x, label_y);
|
summary_alloc.set_origin (label_x, label_y);
|
||||||
summary_alloc.set_size (label_width, summary_height);
|
summary_alloc.set_size (label_width, summary_height);
|
||||||
summary_label.allocate (summary_alloc, flags);
|
summary_label.allocate (summary_alloc, flags);
|
||||||
|
|
||||||
var body_alloc = ActorBox ();
|
var body_alloc = ActorBox ();
|
||||||
body_alloc.set_origin (label_x, label_y + summary_height + LABEL_SPACING * scale);
|
body_alloc.set_origin (label_x, label_y + summary_height + LABEL_SPACING * scale);
|
||||||
body_alloc.set_size (label_width, body_height);
|
body_alloc.set_size (label_width, body_height);
|
||||||
body_label.allocate (body_alloc, flags);
|
body_label.allocate (body_alloc, flags);
|
||||||
|
|
||||||
base.allocate (box, flags);
|
base.allocate (box, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_allocation_values (out float label_x, out float label_width, out float summary_height,
|
void get_allocation_values (out float label_x, out float label_width, out float summary_height,
|
||||||
out float body_height, out float label_height, out float label_y, int scale)
|
out float body_height, out float label_height, out float label_y, int scale)
|
||||||
{
|
{
|
||||||
var height = Notification.ICON_SIZE * scale;
|
var height = Notification.ICON_SIZE * scale;
|
||||||
var margin = Notification.MARGIN * scale;
|
var margin = Notification.MARGIN * scale;
|
||||||
var padding = Notification.PADDING * scale;
|
var padding = Notification.PADDING * scale;
|
||||||
var spacing = Notification.SPACING * scale;
|
var spacing = Notification.SPACING * scale;
|
||||||
|
|
||||||
label_x = margin + padding + height + spacing;
|
label_x = margin + padding + height + spacing;
|
||||||
label_width = Notification.WIDTH * scale - label_x - margin - spacing;
|
label_width = Notification.WIDTH * scale - label_x - margin - spacing;
|
||||||
|
|
||||||
summary_label.get_preferred_height (label_width, null, out summary_height);
|
summary_label.get_preferred_height (label_width, null, out summary_height);
|
||||||
body_label.get_preferred_height (label_width, null, out body_height);
|
body_label.get_preferred_height (label_width, null, out body_height);
|
||||||
|
|
||||||
label_height = summary_height + LABEL_SPACING * scale + body_height;
|
label_height = summary_height + LABEL_SPACING * scale + body_height;
|
||||||
label_y = margin + padding;
|
label_y = margin + padding;
|
||||||
// center
|
// center
|
||||||
if (label_height < height) {
|
if (label_height < height) {
|
||||||
label_y += (height - (int) label_height) / 2;
|
label_y += (height - (int) label_height) / 2;
|
||||||
label_height = height;
|
label_height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copied from gnome-shell, fixes the mess of markup that is sent to us
|
* Copied from gnome-shell, fixes the mess of markup that is sent to us
|
||||||
*/
|
*/
|
||||||
string fix_markup (string markup)
|
string fix_markup (string markup)
|
||||||
{
|
{
|
||||||
var text = markup;
|
var text = markup;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
text = entity_regex.replace (markup, markup.length, 0, "&");
|
text = entity_regex.replace (markup, markup.length, 0, "&");
|
||||||
text = tag_regex.replace (text, text.length, 0, "<");
|
text = tag_regex.replace (text, text.length, 0, "<");
|
||||||
} catch (Error e) {}
|
} catch (Error e) {}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NormalNotification : Notification
|
public class NormalNotification : Notification
|
||||||
{
|
{
|
||||||
public string summary { get; construct set; }
|
public string summary { get; construct set; }
|
||||||
public string body { get; construct set; }
|
public string body { get; construct set; }
|
||||||
public uint32 sender_pid { get; construct; }
|
public uint32 sender_pid { get; construct; }
|
||||||
public string[] notification_actions { get; construct set; }
|
public string[] notification_actions { get; construct set; }
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
#else
|
#else
|
||||||
public Screen screen { get; construct; }
|
public Screen screen { get; construct; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Actor content_container;
|
Actor content_container;
|
||||||
NormalNotificationContent notification_content;
|
NormalNotificationContent notification_content;
|
||||||
NormalNotificationContent? old_notification_content = null;
|
NormalNotificationContent? old_notification_content = null;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public NormalNotification (Meta.Display display, uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
public NormalNotification (Meta.Display display, uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
||||||
NotificationUrgency urgency, int32 expire_timeout, uint32 pid, string[] actions)
|
NotificationUrgency urgency, int32 expire_timeout, uint32 pid, string[] actions)
|
||||||
{
|
{
|
||||||
Object (
|
Object (
|
||||||
id: id,
|
id: id,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
urgency: urgency,
|
urgency: urgency,
|
||||||
expire_timeout: expire_timeout,
|
expire_timeout: expire_timeout,
|
||||||
display: display,
|
display: display,
|
||||||
summary: summary,
|
summary: summary,
|
||||||
body: body,
|
body: body,
|
||||||
sender_pid: pid,
|
sender_pid: pid,
|
||||||
notification_actions: actions
|
notification_actions: actions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public NormalNotification (Screen screen, uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
public NormalNotification (Screen screen, uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
||||||
NotificationUrgency urgency, int32 expire_timeout, uint32 pid, string[] actions)
|
NotificationUrgency urgency, int32 expire_timeout, uint32 pid, string[] actions)
|
||||||
{
|
{
|
||||||
Object (
|
Object (
|
||||||
id: id,
|
id: id,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
urgency: urgency,
|
urgency: urgency,
|
||||||
expire_timeout: expire_timeout,
|
expire_timeout: expire_timeout,
|
||||||
screen: screen,
|
screen: screen,
|
||||||
summary: summary,
|
summary: summary,
|
||||||
body: body,
|
body: body,
|
||||||
sender_pid: pid,
|
sender_pid: pid,
|
||||||
notification_actions: actions
|
notification_actions: actions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
content_container = new Actor ();
|
content_container = new Actor ();
|
||||||
|
|
||||||
notification_content = new NormalNotificationContent ();
|
notification_content = new NormalNotificationContent ();
|
||||||
notification_content.set_values (summary, body);
|
notification_content.set_values (summary, body);
|
||||||
|
|
||||||
content_container.add_child (notification_content);
|
content_container.add_child (notification_content);
|
||||||
insert_child_below (content_container, null);
|
insert_child_below (content_container, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update (string summary, string body, Gdk.Pixbuf? icon, int32 expire_timeout,
|
public void update (string summary, string body, Gdk.Pixbuf? icon, int32 expire_timeout,
|
||||||
string[] actions)
|
string[] actions)
|
||||||
{
|
{
|
||||||
var visible_change = this.summary != summary || this.body != body;
|
var visible_change = this.summary != summary || this.body != body;
|
||||||
|
|
||||||
if (visible_change) {
|
if (visible_change) {
|
||||||
if (old_notification_content != null)
|
if (old_notification_content != null)
|
||||||
old_notification_content.destroy ();
|
old_notification_content.destroy ();
|
||||||
|
|
||||||
old_notification_content = new NormalNotificationContent ();
|
old_notification_content = new NormalNotificationContent ();
|
||||||
old_notification_content.set_values (this.summary, this.body);
|
old_notification_content.set_values (this.summary, this.body);
|
||||||
|
|
||||||
content_container.add_child (old_notification_content);
|
content_container.add_child (old_notification_content);
|
||||||
|
|
||||||
this.summary = summary;
|
this.summary = summary;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
notification_content.set_values (summary, body);
|
notification_content.set_values (summary, body);
|
||||||
|
|
||||||
float content_height, old_content_height;
|
float content_height, old_content_height;
|
||||||
notification_content.get_preferred_height (0, null, out content_height);
|
notification_content.get_preferred_height (0, null, out content_height);
|
||||||
old_notification_content.get_preferred_height (0, null, out old_content_height);
|
old_notification_content.get_preferred_height (0, null, out old_content_height);
|
||||||
|
|
||||||
content_height = float.max (content_height, old_content_height);
|
content_height = float.max (content_height, old_content_height);
|
||||||
|
|
||||||
play_update_transition (content_height + PADDING * 2 * style_context.get_scale ());
|
play_update_transition (content_height + PADDING * 2 * style_context.get_scale ());
|
||||||
|
|
||||||
get_transition ("switch").completed.connect (() => {
|
get_transition ("switch").completed.connect (() => {
|
||||||
if (old_notification_content != null)
|
if (old_notification_content != null)
|
||||||
old_notification_content.destroy ();
|
old_notification_content.destroy ();
|
||||||
old_notification_content = null;
|
old_notification_content = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
notification_actions = actions;
|
notification_actions = actions;
|
||||||
update_base (icon, expire_timeout);
|
update_base (icon, expire_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void update_slide_animation ()
|
protected override void update_slide_animation ()
|
||||||
{
|
{
|
||||||
if (old_notification_content != null)
|
if (old_notification_content != null)
|
||||||
old_notification_content.y = animation_slide_y_offset;
|
old_notification_content.y = animation_slide_y_offset;
|
||||||
|
|
||||||
notification_content.y = animation_slide_y_offset - animation_slide_height;
|
notification_content.y = animation_slide_y_offset - animation_slide_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void update_allocation (out float content_height, AllocationFlags flags)
|
public override void update_allocation (out float content_height, AllocationFlags flags)
|
||||||
{
|
{
|
||||||
var box = ActorBox ();
|
var box = ActorBox ();
|
||||||
box.set_origin (0, 0);
|
box.set_origin (0, 0);
|
||||||
box.set_size (width, height);
|
box.set_size (width, height);
|
||||||
|
|
||||||
content_container.allocate (box, flags);
|
content_container.allocate (box, flags);
|
||||||
|
|
||||||
// the for_width is not needed in our implementation of get_preferred_height as we
|
// the for_width is not needed in our implementation of get_preferred_height as we
|
||||||
// assume a constant width
|
// assume a constant width
|
||||||
notification_content.get_preferred_height (0, null, out content_height);
|
notification_content.get_preferred_height (0, null, out content_height);
|
||||||
|
|
||||||
var scale = style_context.get_scale ();
|
var scale = style_context.get_scale ();
|
||||||
var scaled_margin = MARGIN * scale;
|
var scaled_margin = MARGIN * scale;
|
||||||
|
|
||||||
content_container.set_clip (scaled_margin, scaled_margin, scaled_margin * 2 + WIDTH * scale, content_height + PADDING * 2 * scale);
|
content_container.set_clip (scaled_margin, scaled_margin, scaled_margin * 2 + WIDTH * scale, content_height + PADDING * 2 * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
|
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
|
||||||
{
|
{
|
||||||
float content_height;
|
float content_height;
|
||||||
notification_content.get_preferred_height (for_width, null, out content_height);
|
notification_content.get_preferred_height (for_width, null, out content_height);
|
||||||
|
|
||||||
min_height = nat_height = content_height + (MARGIN + PADDING) * 2 * style_context.get_scale ();
|
min_height = nat_height = content_height + (MARGIN + PADDING) * 2 * style_context.get_scale ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void activate ()
|
public override void activate ()
|
||||||
{
|
{
|
||||||
// we currently only support the default action, which can be triggered by clicking
|
// we currently only support the default action, which can be triggered by clicking
|
||||||
// on the notification according to spec
|
// on the notification according to spec
|
||||||
for (var i = 0; i < notification_actions.length; i += 2) {
|
for (var i = 0; i < notification_actions.length; i += 2) {
|
||||||
if (notification_actions[i] == "default") {
|
if (notification_actions[i] == "default") {
|
||||||
action_invoked (id, "default");
|
action_invoked (id, "default");
|
||||||
dismiss ();
|
dismiss ();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no default action has been set, we fallback to trying to find a window for the
|
// if no default action has been set, we fallback to trying to find a window for the
|
||||||
// notification's sender process
|
// notification's sender process
|
||||||
unowned Meta.Window? window = get_window ();
|
unowned Meta.Window? window = get_window ();
|
||||||
if (window != null) {
|
if (window != null) {
|
||||||
unowned Meta.Workspace workspace = window.get_workspace ();
|
unowned Meta.Workspace workspace = window.get_workspace ();
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var time = display.get_current_time ();
|
var time = display.get_current_time ();
|
||||||
|
|
||||||
if (workspace != display.get_workspace_manager ().get_active_workspace ())
|
if (workspace != display.get_workspace_manager ().get_active_workspace ())
|
||||||
workspace.activate_with_focus (window, time);
|
workspace.activate_with_focus (window, time);
|
||||||
else
|
else
|
||||||
window.activate (time);
|
window.activate (time);
|
||||||
#else
|
#else
|
||||||
var time = screen.get_display ().get_current_time ();
|
var time = screen.get_display ().get_current_time ();
|
||||||
|
|
||||||
if (workspace != screen.get_active_workspace ())
|
if (workspace != screen.get_active_workspace ())
|
||||||
workspace.activate_with_focus (window, time);
|
workspace.activate_with_focus (window, time);
|
||||||
else
|
else
|
||||||
window.activate (time);
|
window.activate (time);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dismiss ();
|
dismiss ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unowned Meta.Window? get_window ()
|
unowned Meta.Window? get_window ()
|
||||||
{
|
{
|
||||||
if (sender_pid == 0)
|
if (sender_pid == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned GLib.List<Meta.WindowActor> actors = display.get_window_actors ();
|
unowned GLib.List<Meta.WindowActor> actors = display.get_window_actors ();
|
||||||
#else
|
#else
|
||||||
unowned GLib.List<Meta.WindowActor> actors = screen.get_window_actors ();
|
unowned GLib.List<Meta.WindowActor> actors = screen.get_window_actors ();
|
||||||
#endif
|
#endif
|
||||||
foreach (unowned Meta.WindowActor actor in actors) {
|
foreach (unowned Meta.WindowActor actor in actors) {
|
||||||
if (actor.is_destroyed ())
|
if (actor.is_destroyed ())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
unowned Meta.Window window = actor.get_meta_window ();
|
unowned Meta.Window window = actor.get_meta_window ();
|
||||||
|
|
||||||
// the windows are sorted by stacking order when returned
|
// the windows are sorted by stacking order when returned
|
||||||
// from meta_get_window_actors, so we can just pick the first
|
// from meta_get_window_actors, so we can just pick the first
|
||||||
// one we find and have a pretty good match
|
// one we find and have a pretty good match
|
||||||
if (window.get_pid () == sender_pid)
|
if (window.get_pid () == sender_pid)
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dismiss ()
|
void dismiss ()
|
||||||
{
|
{
|
||||||
closed (id, NotificationClosedReason.DISMISSED);
|
closed (id, NotificationClosedReason.DISMISSED);
|
||||||
close ();
|
close ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,384 +20,384 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala.Plugins.Notify
|
namespace Gala.Plugins.Notify
|
||||||
{
|
{
|
||||||
public abstract class Notification : Actor
|
public abstract class Notification : Actor
|
||||||
{
|
{
|
||||||
public const int WIDTH = 300;
|
public const int WIDTH = 300;
|
||||||
public const int ICON_SIZE = 48;
|
public const int ICON_SIZE = 48;
|
||||||
public const int MARGIN = 12;
|
public const int MARGIN = 12;
|
||||||
|
|
||||||
public const int SPACING = 6;
|
public const int SPACING = 6;
|
||||||
public const int PADDING = 4;
|
public const int PADDING = 4;
|
||||||
|
|
||||||
public signal void action_invoked (uint32 id, string action);
|
public signal void action_invoked (uint32 id, string action);
|
||||||
public signal void closed (uint32 id, uint32 reason);
|
public signal void closed (uint32 id, uint32 reason);
|
||||||
|
|
||||||
public uint32 id { get; construct; }
|
public uint32 id { get; construct; }
|
||||||
public Gdk.Pixbuf? icon { get; construct set; }
|
public Gdk.Pixbuf? icon { get; construct set; }
|
||||||
public NotificationUrgency urgency { get; construct; }
|
public NotificationUrgency urgency { get; construct; }
|
||||||
public int32 expire_timeout { get; construct set; }
|
public int32 expire_timeout { get; construct set; }
|
||||||
|
|
||||||
public uint64 relevancy_time { get; private set; }
|
public uint64 relevancy_time { get; private set; }
|
||||||
public bool being_destroyed { get; private set; default = false; }
|
public bool being_destroyed { get; private set; default = false; }
|
||||||
|
|
||||||
protected bool icon_only { get; protected set; default = false; }
|
protected bool icon_only { get; protected set; default = false; }
|
||||||
protected Clutter.Texture icon_texture { get; private set; }
|
protected Clutter.Texture icon_texture { get; private set; }
|
||||||
protected Actor icon_container { get; private set; }
|
protected Actor icon_container { get; private set; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether we're currently sliding content for an update animation
|
* Whether we're currently sliding content for an update animation
|
||||||
*/
|
*/
|
||||||
protected bool transitioning { get; private set; default = false; }
|
protected bool transitioning { get; private set; default = false; }
|
||||||
|
|
||||||
Clutter.Actor close_button;
|
Clutter.Actor close_button;
|
||||||
|
|
||||||
protected Gtk.StyleContext style_context { get; private set; }
|
protected Gtk.StyleContext style_context { get; private set; }
|
||||||
|
|
||||||
uint remove_timeout = 0;
|
uint remove_timeout = 0;
|
||||||
|
|
||||||
// temporary things needed for the slide transition
|
// temporary things needed for the slide transition
|
||||||
protected float animation_slide_height { get; private set; }
|
protected float animation_slide_height { get; private set; }
|
||||||
Clutter.Texture old_texture;
|
Clutter.Texture old_texture;
|
||||||
float _animation_slide_y_offset = 0.0f;
|
float _animation_slide_y_offset = 0.0f;
|
||||||
public float animation_slide_y_offset {
|
public float animation_slide_y_offset {
|
||||||
get {
|
get {
|
||||||
return _animation_slide_y_offset;
|
return _animation_slide_y_offset;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
_animation_slide_y_offset = value;
|
_animation_slide_y_offset = value;
|
||||||
|
|
||||||
icon_texture.y = -animation_slide_height + _animation_slide_y_offset;
|
icon_texture.y = -animation_slide_height + _animation_slide_y_offset;
|
||||||
old_texture.y = _animation_slide_y_offset;
|
old_texture.y = _animation_slide_y_offset;
|
||||||
|
|
||||||
update_slide_animation ();
|
update_slide_animation ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Notification (uint32 id, Gdk.Pixbuf? icon, NotificationUrgency urgency,
|
protected Notification (uint32 id, Gdk.Pixbuf? icon, NotificationUrgency urgency,
|
||||||
int32 expire_timeout)
|
int32 expire_timeout)
|
||||||
{
|
{
|
||||||
Object (
|
Object (
|
||||||
id: id,
|
id: id,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
urgency: urgency,
|
urgency: urgency,
|
||||||
expire_timeout: expire_timeout
|
expire_timeout: expire_timeout
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
relevancy_time = new DateTime.now_local ().to_unix ();
|
relevancy_time = new DateTime.now_local ().to_unix ();
|
||||||
width = (WIDTH + MARGIN * 2) * scale;
|
width = (WIDTH + MARGIN * 2) * scale;
|
||||||
reactive = true;
|
reactive = true;
|
||||||
set_pivot_point (0.5f, 0.5f);
|
set_pivot_point (0.5f, 0.5f);
|
||||||
|
|
||||||
icon_texture = new Clutter.Texture ();
|
icon_texture = new Clutter.Texture ();
|
||||||
icon_texture.set_pivot_point (0.5f, 0.5f);
|
icon_texture.set_pivot_point (0.5f, 0.5f);
|
||||||
|
|
||||||
icon_container = new Actor ();
|
icon_container = new Actor ();
|
||||||
icon_container.add_child (icon_texture);
|
icon_container.add_child (icon_texture);
|
||||||
|
|
||||||
close_button = Utils.create_close_button ();
|
close_button = Utils.create_close_button ();
|
||||||
close_button.opacity = 0;
|
close_button.opacity = 0;
|
||||||
close_button.reactive = true;
|
close_button.reactive = true;
|
||||||
close_button.set_easing_duration (300);
|
close_button.set_easing_duration (300);
|
||||||
|
|
||||||
var close_click = new ClickAction ();
|
var close_click = new ClickAction ();
|
||||||
close_click.clicked.connect (() => {
|
close_click.clicked.connect (() => {
|
||||||
closed (id, NotificationClosedReason.DISMISSED);
|
closed (id, NotificationClosedReason.DISMISSED);
|
||||||
close ();
|
close ();
|
||||||
});
|
});
|
||||||
close_button.add_action (close_click);
|
close_button.add_action (close_click);
|
||||||
|
|
||||||
add_child (icon_container);
|
add_child (icon_container);
|
||||||
add_child (close_button);
|
add_child (close_button);
|
||||||
|
|
||||||
var style_path = new Gtk.WidgetPath ();
|
var style_path = new Gtk.WidgetPath ();
|
||||||
style_path.append_type (typeof (Gtk.Window));
|
style_path.append_type (typeof (Gtk.Window));
|
||||||
style_path.append_type (typeof (Gtk.EventBox));
|
style_path.append_type (typeof (Gtk.EventBox));
|
||||||
|
|
||||||
style_context = new Gtk.StyleContext ();
|
style_context = new Gtk.StyleContext ();
|
||||||
style_context.add_provider (Gala.Utils.get_gala_css (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
|
style_context.add_provider (Gala.Utils.get_gala_css (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
|
||||||
style_context.add_class ("gala-notification");
|
style_context.add_class ("gala-notification");
|
||||||
style_context.set_path (style_path);
|
style_context.set_path (style_path);
|
||||||
style_context.set_scale (scale);
|
style_context.set_scale (scale);
|
||||||
|
|
||||||
var label_style_path = style_path.copy ();
|
var label_style_path = style_path.copy ();
|
||||||
label_style_path.iter_add_class (1, "gala-notification");
|
label_style_path.iter_add_class (1, "gala-notification");
|
||||||
label_style_path.append_type (typeof (Gtk.Label));
|
label_style_path.append_type (typeof (Gtk.Label));
|
||||||
|
|
||||||
var canvas = new Canvas ();
|
var canvas = new Canvas ();
|
||||||
canvas.draw.connect (draw);
|
canvas.draw.connect (draw);
|
||||||
content = canvas;
|
content = canvas;
|
||||||
|
|
||||||
set_values ();
|
set_values ();
|
||||||
|
|
||||||
var click = new ClickAction ();
|
var click = new ClickAction ();
|
||||||
click.clicked.connect (() => {
|
click.clicked.connect (() => {
|
||||||
activate ();
|
activate ();
|
||||||
});
|
});
|
||||||
add_action (click);
|
add_action (click);
|
||||||
|
|
||||||
open ();
|
open ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open () {
|
public void open () {
|
||||||
var entry = new TransitionGroup ();
|
var entry = new TransitionGroup ();
|
||||||
entry.remove_on_complete = true;
|
entry.remove_on_complete = true;
|
||||||
entry.duration = 400;
|
entry.duration = 400;
|
||||||
|
|
||||||
var opacity_transition = new PropertyTransition ("opacity");
|
var opacity_transition = new PropertyTransition ("opacity");
|
||||||
opacity_transition.set_from_value (0);
|
opacity_transition.set_from_value (0);
|
||||||
opacity_transition.set_to_value (255);
|
opacity_transition.set_to_value (255);
|
||||||
|
|
||||||
var flip_transition = new KeyframeTransition ("rotation-angle-x");
|
var flip_transition = new KeyframeTransition ("rotation-angle-x");
|
||||||
flip_transition.set_from_value (90.0);
|
flip_transition.set_from_value (90.0);
|
||||||
flip_transition.set_to_value (0.0);
|
flip_transition.set_to_value (0.0);
|
||||||
flip_transition.set_key_frames ({ 0.6 });
|
flip_transition.set_key_frames ({ 0.6 });
|
||||||
flip_transition.set_values ({ -10.0 });
|
flip_transition.set_values ({ -10.0 });
|
||||||
|
|
||||||
entry.add_transition (opacity_transition);
|
entry.add_transition (opacity_transition);
|
||||||
entry.add_transition (flip_transition);
|
entry.add_transition (flip_transition);
|
||||||
add_transition ("entry", entry);
|
add_transition ("entry", entry);
|
||||||
|
|
||||||
switch (urgency) {
|
switch (urgency) {
|
||||||
case NotificationUrgency.LOW:
|
case NotificationUrgency.LOW:
|
||||||
case NotificationUrgency.NORMAL:
|
case NotificationUrgency.NORMAL:
|
||||||
return;
|
return;
|
||||||
case NotificationUrgency.CRITICAL:
|
case NotificationUrgency.CRITICAL:
|
||||||
var icon_entry = new TransitionGroup ();
|
var icon_entry = new TransitionGroup ();
|
||||||
icon_entry.duration = 1000;
|
icon_entry.duration = 1000;
|
||||||
icon_entry.remove_on_complete = true;
|
icon_entry.remove_on_complete = true;
|
||||||
icon_entry.progress_mode = AnimationMode.EASE_IN_OUT_CUBIC;
|
icon_entry.progress_mode = AnimationMode.EASE_IN_OUT_CUBIC;
|
||||||
|
|
||||||
double[] keyframes = { 0.2, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
|
double[] keyframes = { 0.2, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
|
||||||
GLib.Value[] scale = { 0.0, 1.2, 1.6, 1.6, 1.6, 1.6, 1.2, 1.0 };
|
GLib.Value[] scale = { 0.0, 1.2, 1.6, 1.6, 1.6, 1.6, 1.2, 1.0 };
|
||||||
|
|
||||||
var rotate_transition = new KeyframeTransition ("rotation-angle-z");
|
var rotate_transition = new KeyframeTransition ("rotation-angle-z");
|
||||||
rotate_transition.set_from_value (30.0);
|
rotate_transition.set_from_value (30.0);
|
||||||
rotate_transition.set_to_value (0.0);
|
rotate_transition.set_to_value (0.0);
|
||||||
rotate_transition.set_key_frames (keyframes);
|
rotate_transition.set_key_frames (keyframes);
|
||||||
rotate_transition.set_values ({ 30.0, -30.0, 30.0, -20.0, 10.0, -5.0, 2.0, 0.0 });
|
rotate_transition.set_values ({ 30.0, -30.0, 30.0, -20.0, 10.0, -5.0, 2.0, 0.0 });
|
||||||
|
|
||||||
var scale_x_transition = new KeyframeTransition ("scale-x");
|
var scale_x_transition = new KeyframeTransition ("scale-x");
|
||||||
scale_x_transition.set_from_value (0.0);
|
scale_x_transition.set_from_value (0.0);
|
||||||
scale_x_transition.set_to_value (1.0);
|
scale_x_transition.set_to_value (1.0);
|
||||||
scale_x_transition.set_key_frames (keyframes);
|
scale_x_transition.set_key_frames (keyframes);
|
||||||
scale_x_transition.set_values (scale);
|
scale_x_transition.set_values (scale);
|
||||||
|
|
||||||
var scale_y_transition = new KeyframeTransition ("scale-y");
|
var scale_y_transition = new KeyframeTransition ("scale-y");
|
||||||
scale_y_transition.set_from_value (0.0);
|
scale_y_transition.set_from_value (0.0);
|
||||||
scale_y_transition.set_to_value (1.0);
|
scale_y_transition.set_to_value (1.0);
|
||||||
scale_y_transition.set_key_frames (keyframes);
|
scale_y_transition.set_key_frames (keyframes);
|
||||||
scale_y_transition.set_values (scale);
|
scale_y_transition.set_values (scale);
|
||||||
|
|
||||||
icon_entry.add_transition (rotate_transition);
|
icon_entry.add_transition (rotate_transition);
|
||||||
icon_entry.add_transition (scale_x_transition);
|
icon_entry.add_transition (scale_x_transition);
|
||||||
icon_entry.add_transition (scale_y_transition);
|
icon_entry.add_transition (scale_y_transition);
|
||||||
|
|
||||||
icon_texture.add_transition ("entry", icon_entry);
|
icon_texture.add_transition ("entry", icon_entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close ()
|
public void close ()
|
||||||
{
|
{
|
||||||
set_easing_duration (100);
|
set_easing_duration (100);
|
||||||
|
|
||||||
set_easing_mode (AnimationMode.EASE_IN_QUAD);
|
set_easing_mode (AnimationMode.EASE_IN_QUAD);
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
|
|
||||||
x = (WIDTH + MARGIN * 2) * style_context.get_scale ();
|
x = (WIDTH + MARGIN * 2) * style_context.get_scale ();
|
||||||
|
|
||||||
being_destroyed = true;
|
being_destroyed = true;
|
||||||
var transition = get_transition ("x");
|
var transition = get_transition ("x");
|
||||||
if (transition != null)
|
if (transition != null)
|
||||||
transition.completed.connect (() => destroy ());
|
transition.completed.connect (() => destroy ());
|
||||||
else
|
else
|
||||||
destroy ();
|
destroy ();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void update_base (Gdk.Pixbuf? icon, int32 expire_timeout)
|
protected void update_base (Gdk.Pixbuf? icon, int32 expire_timeout)
|
||||||
{
|
{
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.expire_timeout = expire_timeout;
|
this.expire_timeout = expire_timeout;
|
||||||
this.relevancy_time = new DateTime.now_local ().to_unix ();
|
this.relevancy_time = new DateTime.now_local ().to_unix ();
|
||||||
|
|
||||||
set_values ();
|
set_values ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_values ()
|
void set_values ()
|
||||||
{
|
{
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
try {
|
try {
|
||||||
icon_texture.set_from_rgb_data (icon.get_pixels (), icon.get_has_alpha (),
|
icon_texture.set_from_rgb_data (icon.get_pixels (), icon.get_has_alpha (),
|
||||||
icon.get_width (), icon.get_height (),
|
icon.get_width (), icon.get_height (),
|
||||||
icon.get_rowstride (), (icon.get_has_alpha () ? 4 : 3), 0);
|
icon.get_rowstride (), (icon.get_has_alpha () ? 4 : 3), 0);
|
||||||
} catch (Error e) {}
|
} catch (Error e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_timeout ();
|
set_timeout ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_timeout ()
|
void set_timeout ()
|
||||||
{
|
{
|
||||||
// crtitical notifications have to be dismissed manually
|
// crtitical notifications have to be dismissed manually
|
||||||
if (expire_timeout <= 0 || urgency == NotificationUrgency.CRITICAL)
|
if (expire_timeout <= 0 || urgency == NotificationUrgency.CRITICAL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clear_timeout ();
|
clear_timeout ();
|
||||||
|
|
||||||
remove_timeout = Timeout.add (expire_timeout, () => {
|
remove_timeout = Timeout.add (expire_timeout, () => {
|
||||||
closed (id, NotificationClosedReason.EXPIRED);
|
closed (id, NotificationClosedReason.EXPIRED);
|
||||||
close ();
|
close ();
|
||||||
remove_timeout = 0;
|
remove_timeout = 0;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_timeout ()
|
void clear_timeout ()
|
||||||
{
|
{
|
||||||
if (remove_timeout != 0) {
|
if (remove_timeout != 0) {
|
||||||
Source.remove (remove_timeout);
|
Source.remove (remove_timeout);
|
||||||
remove_timeout = 0;
|
remove_timeout = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool enter_event (CrossingEvent event)
|
public override bool enter_event (CrossingEvent event)
|
||||||
{
|
{
|
||||||
close_button.opacity = 255;
|
close_button.opacity = 255;
|
||||||
|
|
||||||
clear_timeout ();
|
clear_timeout ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool leave_event (CrossingEvent event)
|
public override bool leave_event (CrossingEvent event)
|
||||||
{
|
{
|
||||||
close_button.opacity = 0;
|
close_button.opacity = 0;
|
||||||
|
|
||||||
// TODO consider decreasing the timeout now or calculating the remaining
|
// TODO consider decreasing the timeout now or calculating the remaining
|
||||||
set_timeout ();
|
set_timeout ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void activate ()
|
public virtual void activate ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void draw_content (Cairo.Context cr)
|
public virtual void draw_content (Cairo.Context cr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void update_allocation (out float content_height, AllocationFlags flags);
|
public abstract void update_allocation (out float content_height, AllocationFlags flags);
|
||||||
|
|
||||||
public override void allocate (ActorBox box, AllocationFlags flags)
|
public override void allocate (ActorBox box, AllocationFlags flags)
|
||||||
{
|
{
|
||||||
var icon_alloc = ActorBox ();
|
var icon_alloc = ActorBox ();
|
||||||
|
|
||||||
var scale = style_context.get_scale ();
|
var scale = style_context.get_scale ();
|
||||||
var scaled_width = WIDTH * scale;
|
var scaled_width = WIDTH * scale;
|
||||||
var scaled_icon_size = ICON_SIZE * scale;
|
var scaled_icon_size = ICON_SIZE * scale;
|
||||||
var scaled_margin_padding = (MARGIN + PADDING) * scale;
|
var scaled_margin_padding = (MARGIN + PADDING) * scale;
|
||||||
icon_alloc.set_origin (icon_only ? (scaled_width - scaled_icon_size) / 2 : scaled_margin_padding, scaled_margin_padding);
|
icon_alloc.set_origin (icon_only ? (scaled_width - scaled_icon_size) / 2 : scaled_margin_padding, scaled_margin_padding);
|
||||||
icon_alloc.set_size (scaled_icon_size, scaled_icon_size);
|
icon_alloc.set_size (scaled_icon_size, scaled_icon_size);
|
||||||
icon_container.allocate (icon_alloc, flags);
|
icon_container.allocate (icon_alloc, flags);
|
||||||
|
|
||||||
var close_alloc = ActorBox ();
|
var close_alloc = ActorBox ();
|
||||||
close_alloc.set_origin (scaled_margin_padding - close_button.width / 2,
|
close_alloc.set_origin (scaled_margin_padding - close_button.width / 2,
|
||||||
scaled_margin_padding - close_button.height / 2);
|
scaled_margin_padding - close_button.height / 2);
|
||||||
close_alloc.set_size (close_button.width, close_button.height);
|
close_alloc.set_size (close_button.width, close_button.height);
|
||||||
close_button.allocate (close_alloc, flags);
|
close_button.allocate (close_alloc, flags);
|
||||||
|
|
||||||
float content_height;
|
float content_height;
|
||||||
update_allocation (out content_height, flags);
|
update_allocation (out content_height, flags);
|
||||||
box.set_size (MARGIN * 2 * scale + scaled_width, scaled_margin_padding * 2 + content_height);
|
box.set_size (MARGIN * 2 * scale + scaled_width, scaled_margin_padding * 2 + content_height);
|
||||||
|
|
||||||
base.allocate (box, flags);
|
base.allocate (box, flags);
|
||||||
|
|
||||||
var canvas = (Canvas) content;
|
var canvas = (Canvas) content;
|
||||||
var canvas_width = (int) box.get_width ();
|
var canvas_width = (int) box.get_width ();
|
||||||
var canvas_height = (int) box.get_height ();
|
var canvas_height = (int) box.get_height ();
|
||||||
if (canvas.width != canvas_width || canvas.height != canvas_height)
|
if (canvas.width != canvas_width || canvas.height != canvas_height)
|
||||||
canvas.set_size (canvas_width, canvas_height);
|
canvas.set_size (canvas_width, canvas_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
|
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
|
||||||
{
|
{
|
||||||
min_height = nat_height = (ICON_SIZE + (MARGIN + PADDING) * 2) * style_context.get_scale ();
|
min_height = nat_height = (ICON_SIZE + (MARGIN + PADDING) * 2) * style_context.get_scale ();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void play_update_transition (float slide_height)
|
protected void play_update_transition (float slide_height)
|
||||||
{
|
{
|
||||||
Transition transition;
|
Transition transition;
|
||||||
if ((transition = get_transition ("switch")) != null) {
|
if ((transition = get_transition ("switch")) != null) {
|
||||||
transition.completed ();
|
transition.completed ();
|
||||||
remove_transition ("switch");
|
remove_transition ("switch");
|
||||||
}
|
}
|
||||||
|
|
||||||
animation_slide_height = slide_height;
|
animation_slide_height = slide_height;
|
||||||
|
|
||||||
var scale = style_context.get_scale ();
|
var scale = style_context.get_scale ();
|
||||||
var scaled_padding = PADDING * scale;
|
var scaled_padding = PADDING * scale;
|
||||||
var scaled_icon_size = ICON_SIZE * scale;
|
var scaled_icon_size = ICON_SIZE * scale;
|
||||||
old_texture = new Clutter.Texture ();
|
old_texture = new Clutter.Texture ();
|
||||||
icon_container.add_child (old_texture);
|
icon_container.add_child (old_texture);
|
||||||
icon_container.set_clip (0, -scaled_padding, scaled_icon_size, scaled_icon_size + scaled_padding * 2);
|
icon_container.set_clip (0, -scaled_padding, scaled_icon_size, scaled_icon_size + scaled_padding * 2);
|
||||||
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
try {
|
try {
|
||||||
old_texture.set_from_rgb_data (icon.get_pixels (), icon.get_has_alpha (),
|
old_texture.set_from_rgb_data (icon.get_pixels (), icon.get_has_alpha (),
|
||||||
icon.get_width (), icon.get_height (),
|
icon.get_width (), icon.get_height (),
|
||||||
icon.get_rowstride (), (icon.get_has_alpha () ? 4 : 3), 0);
|
icon.get_rowstride (), (icon.get_has_alpha () ? 4 : 3), 0);
|
||||||
} catch (Error e) {}
|
} catch (Error e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
transition = new PropertyTransition ("animation-slide-y-offset");
|
transition = new PropertyTransition ("animation-slide-y-offset");
|
||||||
transition.duration = 200;
|
transition.duration = 200;
|
||||||
transition.progress_mode = AnimationMode.EASE_IN_OUT_QUAD;
|
transition.progress_mode = AnimationMode.EASE_IN_OUT_QUAD;
|
||||||
transition.set_from_value (0.0f);
|
transition.set_from_value (0.0f);
|
||||||
transition.set_to_value (animation_slide_height);
|
transition.set_to_value (animation_slide_height);
|
||||||
transition.remove_on_complete = true;
|
transition.remove_on_complete = true;
|
||||||
|
|
||||||
transition.completed.connect (() => {
|
transition.completed.connect (() => {
|
||||||
old_texture.destroy ();
|
old_texture.destroy ();
|
||||||
icon_container.remove_clip ();
|
icon_container.remove_clip ();
|
||||||
_animation_slide_y_offset = 0;
|
_animation_slide_y_offset = 0;
|
||||||
transitioning = false;
|
transitioning = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
add_transition ("switch", transition);
|
add_transition ("switch", transition);
|
||||||
transitioning = true;
|
transitioning = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void update_slide_animation ()
|
protected virtual void update_slide_animation ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool draw (Cairo.Context cr)
|
bool draw (Cairo.Context cr)
|
||||||
{
|
{
|
||||||
var canvas = (Canvas) content;
|
var canvas = (Canvas) content;
|
||||||
|
|
||||||
var scale = style_context.get_scale ();
|
var scale = style_context.get_scale ();
|
||||||
var x = MARGIN;
|
var x = MARGIN;
|
||||||
var y = MARGIN;
|
var y = MARGIN;
|
||||||
var width = canvas.width / scale - MARGIN * 2;
|
var width = canvas.width / scale - MARGIN * 2;
|
||||||
var height = canvas.height / scale - MARGIN * 2;
|
var height = canvas.height / scale - MARGIN * 2;
|
||||||
cr.set_operator (Cairo.Operator.CLEAR);
|
cr.set_operator (Cairo.Operator.CLEAR);
|
||||||
cr.paint ();
|
cr.paint ();
|
||||||
cr.set_operator (Cairo.Operator.OVER);
|
cr.set_operator (Cairo.Operator.OVER);
|
||||||
|
|
||||||
cr.save ();
|
cr.save ();
|
||||||
cr.scale (scale, scale);
|
cr.scale (scale, scale);
|
||||||
style_context.render_background (cr, x, y, width, height);
|
style_context.render_background (cr, x, y, width, height);
|
||||||
style_context.render_frame (cr, x, y, width, height);
|
style_context.render_frame (cr, x, y, width, height);
|
||||||
cr.restore ();
|
cr.restore ();
|
||||||
|
|
||||||
draw_content (cr);
|
draw_content (cr);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,99 +20,99 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala.Plugins.Notify
|
namespace Gala.Plugins.Notify
|
||||||
{
|
{
|
||||||
public class NotificationStack : Actor
|
public class NotificationStack : Actor
|
||||||
{
|
{
|
||||||
// we need to keep a small offset to the top, because we clip the container to
|
// we need to keep a small offset to the top, because we clip the container to
|
||||||
// its allocations and the close button would be off for the first notification
|
// its allocations and the close button would be off for the first notification
|
||||||
const int TOP_OFFSET = 2;
|
const int TOP_OFFSET = 2;
|
||||||
const int ADDITIONAL_MARGIN = 12;
|
const int ADDITIONAL_MARGIN = 12;
|
||||||
|
|
||||||
public signal void animations_changed (bool running);
|
public signal void animations_changed (bool running);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
|
|
||||||
public NotificationStack (Meta.Display display)
|
public NotificationStack (Meta.Display display)
|
||||||
{
|
{
|
||||||
Object (display: display);
|
Object (display: display);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public Screen screen { get; construct; }
|
public Screen screen { get; construct; }
|
||||||
|
|
||||||
public new float width
|
public new float width
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
return (Notification.WIDTH + 2 * Notification.MARGIN + ADDITIONAL_MARGIN) * scale;
|
return (Notification.WIDTH + 2 * Notification.MARGIN + ADDITIONAL_MARGIN) * scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotificationStack (Screen screen)
|
public NotificationStack (Screen screen)
|
||||||
{
|
{
|
||||||
Object (screen: screen);
|
Object (screen: screen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
clip_to_allocation = true;
|
clip_to_allocation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show_notification (Notification notification)
|
public void show_notification (Notification notification)
|
||||||
{
|
{
|
||||||
animations_changed (true);
|
animations_changed (true);
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
|
|
||||||
// raise ourselves when we got something to show
|
// raise ourselves when we got something to show
|
||||||
get_parent ().set_child_above_sibling (this, null);
|
get_parent ().set_child_above_sibling (this, null);
|
||||||
|
|
||||||
// we have a shoot-over on the start of the close animation, which gets clipped
|
// we have a shoot-over on the start of the close animation, which gets clipped
|
||||||
// unless we make our container a bit wider and move the notifications over
|
// unless we make our container a bit wider and move the notifications over
|
||||||
notification.margin_left = ADDITIONAL_MARGIN * scale;
|
notification.margin_left = ADDITIONAL_MARGIN * scale;
|
||||||
|
|
||||||
notification.notify["being-destroyed"].connect (() => {
|
notification.notify["being-destroyed"].connect (() => {
|
||||||
animations_changed (true);
|
animations_changed (true);
|
||||||
});
|
});
|
||||||
|
|
||||||
notification.destroy.connect (() => {
|
notification.destroy.connect (() => {
|
||||||
animations_changed (false);
|
animations_changed (false);
|
||||||
update_positions ();
|
update_positions ();
|
||||||
});
|
});
|
||||||
|
|
||||||
notification.get_transition ("entry").completed.connect (() => {
|
notification.get_transition ("entry").completed.connect (() => {
|
||||||
animations_changed (false);
|
animations_changed (false);
|
||||||
});
|
});
|
||||||
|
|
||||||
float height;
|
float height;
|
||||||
notification.get_preferred_height (Notification.WIDTH * scale, out height, null);
|
notification.get_preferred_height (Notification.WIDTH * scale, out height, null);
|
||||||
update_positions (height);
|
update_positions (height);
|
||||||
|
|
||||||
notification.y = TOP_OFFSET * scale;
|
notification.y = TOP_OFFSET * scale;
|
||||||
insert_child_at_index (notification, 0);
|
insert_child_at_index (notification, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_positions (float add_y = 0.0f)
|
void update_positions (float add_y = 0.0f)
|
||||||
{
|
{
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
var y = add_y + TOP_OFFSET * scale;
|
var y = add_y + TOP_OFFSET * scale;
|
||||||
var i = get_n_children ();
|
var i = get_n_children ();
|
||||||
var delay_step = i > 0 ? 150 / i : 0;
|
var delay_step = i > 0 ? 150 / i : 0;
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
if (((Notification) child).being_destroyed)
|
if (((Notification) child).being_destroyed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
child.save_easing_state ();
|
child.save_easing_state ();
|
||||||
child.set_easing_mode (AnimationMode.EASE_OUT_BACK);
|
child.set_easing_mode (AnimationMode.EASE_OUT_BACK);
|
||||||
child.set_easing_duration (200);
|
child.set_easing_duration (200);
|
||||||
child.set_easing_delay ((i--) * delay_step);
|
child.set_easing_delay ((i--) * delay_step);
|
||||||
|
|
||||||
child.y = y;
|
child.y = y;
|
||||||
child.restore_easing_state ();
|
child.restore_easing_state ();
|
||||||
|
|
||||||
y += child.height;
|
y += child.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,23 +20,23 @@
|
|||||||
|
|
||||||
namespace Gala.Plugins.Notify
|
namespace Gala.Plugins.Notify
|
||||||
{
|
{
|
||||||
public class NotifySettings : Granite.Services.Settings
|
public class NotifySettings : Granite.Services.Settings
|
||||||
{
|
{
|
||||||
public bool do_not_disturb { get; set; }
|
public bool do_not_disturb { get; set; }
|
||||||
|
|
||||||
static NotifySettings? instance = null;
|
static NotifySettings? instance = null;
|
||||||
|
|
||||||
private NotifySettings ()
|
private NotifySettings ()
|
||||||
{
|
{
|
||||||
base (Config.SCHEMA + ".notifications");
|
base (Config.SCHEMA + ".notifications");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unowned NotifySettings get_default ()
|
public static unowned NotifySettings get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new NotifySettings ();
|
instance = new NotifySettings ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,216 +17,216 @@
|
|||||||
|
|
||||||
public class Gala.Plugins.PIP.Plugin : Gala.Plugin
|
public class Gala.Plugins.PIP.Plugin : Gala.Plugin
|
||||||
{
|
{
|
||||||
private const int MIN_SELECTION_SIZE = 30;
|
private const int MIN_SELECTION_SIZE = 30;
|
||||||
|
|
||||||
private Gee.ArrayList<PopupWindow> windows;
|
private Gee.ArrayList<PopupWindow> windows;
|
||||||
private Gala.WindowManager? wm = null;
|
private Gala.WindowManager? wm = null;
|
||||||
private SelectionArea? selection_area;
|
private SelectionArea? selection_area;
|
||||||
|
|
||||||
static inline bool meta_rectangle_contains (Meta.Rectangle rect, int x, int y)
|
static inline bool meta_rectangle_contains (Meta.Rectangle rect, int x, int y)
|
||||||
{
|
{
|
||||||
return x >= rect.x && x < rect.x + rect.width
|
return x >= rect.x && x < rect.x + rect.width
|
||||||
&& y >= rect.y && y < rect.y + rect.height;
|
&& y >= rect.y && y < rect.y + rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
windows = new Gee.ArrayList<PopupWindow> ();
|
windows = new Gee.ArrayList<PopupWindow> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void initialize (Gala.WindowManager wm)
|
public override void initialize (Gala.WindowManager wm)
|
||||||
{
|
{
|
||||||
this.wm = wm;
|
this.wm = wm;
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var display = wm.get_display ();
|
var display = wm.get_display ();
|
||||||
#else
|
#else
|
||||||
var display = wm.get_screen ().get_display ();
|
var display = wm.get_screen ().get_display ();
|
||||||
#endif
|
#endif
|
||||||
var settings = new GLib.Settings (Config.SCHEMA + ".keybindings");
|
var settings = new GLib.Settings (Config.SCHEMA + ".keybindings");
|
||||||
|
|
||||||
display.add_keybinding ("pip", settings, Meta.KeyBindingFlags.NONE, (Meta.KeyHandlerFunc) on_initiate);
|
display.add_keybinding ("pip", settings, Meta.KeyBindingFlags.NONE, (Meta.KeyHandlerFunc) on_initiate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void destroy ()
|
public override void destroy ()
|
||||||
{
|
{
|
||||||
clear_selection_area ();
|
clear_selection_area ();
|
||||||
|
|
||||||
foreach (var popup_window in windows) {
|
foreach (var popup_window in windows) {
|
||||||
untrack_window (popup_window);
|
untrack_window (popup_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
windows.clear ();
|
windows.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (instance_pos = -1)]
|
[CCode (instance_pos = -1)]
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
void on_initiate (Meta.Display display, Meta.Window? window, Clutter.KeyEvent event,
|
void on_initiate (Meta.Display display, Meta.Window? window, Clutter.KeyEvent event,
|
||||||
Meta.KeyBinding binding)
|
Meta.KeyBinding binding)
|
||||||
#else
|
#else
|
||||||
void on_initiate (Meta.Display display, Meta.Screen screen,
|
void on_initiate (Meta.Display display, Meta.Screen screen,
|
||||||
Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding)
|
Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
selection_area = new SelectionArea (wm);
|
selection_area = new SelectionArea (wm);
|
||||||
selection_area.selected.connect (on_selection_actor_selected);
|
selection_area.selected.connect (on_selection_actor_selected);
|
||||||
selection_area.captured.connect (on_selection_actor_captured);
|
selection_area.captured.connect (on_selection_actor_captured);
|
||||||
selection_area.closed.connect (clear_selection_area);
|
selection_area.closed.connect (clear_selection_area);
|
||||||
|
|
||||||
track_actor (selection_area);
|
track_actor (selection_area);
|
||||||
wm.ui_group.add_child (selection_area);
|
wm.ui_group.add_child (selection_area);
|
||||||
|
|
||||||
selection_area.start_selection ();
|
selection_area.start_selection ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_selection_actor_selected (int x, int y)
|
private void on_selection_actor_selected (int x, int y)
|
||||||
{
|
{
|
||||||
clear_selection_area ();
|
clear_selection_area ();
|
||||||
select_window_at (x, y);
|
select_window_at (x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_selection_actor_captured (int x, int y, int width, int height)
|
private void on_selection_actor_captured (int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
clear_selection_area ();
|
clear_selection_area ();
|
||||||
|
|
||||||
if (width < MIN_SELECTION_SIZE || height < MIN_SELECTION_SIZE) {
|
if (width < MIN_SELECTION_SIZE || height < MIN_SELECTION_SIZE) {
|
||||||
select_window_at (x, y);
|
select_window_at (x, y);
|
||||||
} else {
|
} else {
|
||||||
var active = get_active_window_actor ();
|
var active = get_active_window_actor ();
|
||||||
if (active != null) {
|
if (active != null) {
|
||||||
int point_x = x - (int)active.x;
|
int point_x = x - (int)active.x;
|
||||||
int point_y = y - (int)active.y;
|
int point_y = y - (int)active.y;
|
||||||
|
|
||||||
var rect = Clutter.Rect.alloc ();
|
var rect = Clutter.Rect.alloc ();
|
||||||
var clip = rect.init (point_x, point_y, width, height);
|
var clip = rect.init (point_x, point_y, width, height);
|
||||||
|
|
||||||
var popup_window = new PopupWindow (wm, active, clip);
|
var popup_window = new PopupWindow (wm, active, clip);
|
||||||
popup_window.show.connect (on_popup_window_show);
|
popup_window.show.connect (on_popup_window_show);
|
||||||
popup_window.hide.connect (on_popup_window_hide);
|
popup_window.hide.connect (on_popup_window_hide);
|
||||||
add_window (popup_window);
|
add_window (popup_window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_popup_window_show (Clutter.Actor popup_window)
|
private void on_popup_window_show (Clutter.Actor popup_window)
|
||||||
{
|
{
|
||||||
track_actor (popup_window);
|
track_actor (popup_window);
|
||||||
update_region ();
|
update_region ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_popup_window_hide (Clutter.Actor popup_window)
|
private void on_popup_window_hide (Clutter.Actor popup_window)
|
||||||
{
|
{
|
||||||
untrack_actor (popup_window);
|
untrack_actor (popup_window);
|
||||||
update_region ();
|
update_region ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void select_window_at (int x, int y)
|
private void select_window_at (int x, int y)
|
||||||
{
|
{
|
||||||
var selected = get_window_actor_at (x, y);
|
var selected = get_window_actor_at (x, y);
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
var popup_window = new PopupWindow (wm, selected, null);
|
var popup_window = new PopupWindow (wm, selected, null);
|
||||||
popup_window.show.connect (on_popup_window_show);
|
popup_window.show.connect (on_popup_window_show);
|
||||||
popup_window.hide.connect (on_popup_window_hide);
|
popup_window.hide.connect (on_popup_window_hide);
|
||||||
add_window (popup_window);
|
add_window (popup_window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clear_selection_area ()
|
private void clear_selection_area ()
|
||||||
{
|
{
|
||||||
if (selection_area != null) {
|
if (selection_area != null) {
|
||||||
untrack_actor (selection_area);
|
untrack_actor (selection_area);
|
||||||
update_region ();
|
update_region ();
|
||||||
|
|
||||||
selection_area.destroy ();
|
selection_area.destroy ();
|
||||||
selection_area = null;
|
selection_area = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Meta.WindowActor? get_window_actor_at (int x, int y)
|
private Meta.WindowActor? get_window_actor_at (int x, int y)
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = wm.get_display ();
|
unowned Meta.Display display = wm.get_display ();
|
||||||
unowned List<Meta.WindowActor> actors = display.get_window_actors ();
|
unowned List<Meta.WindowActor> actors = display.get_window_actors ();
|
||||||
#else
|
#else
|
||||||
var screen = wm.get_screen ();
|
var screen = wm.get_screen ();
|
||||||
unowned List<Meta.WindowActor> actors = screen.get_window_actors ();
|
unowned List<Meta.WindowActor> actors = screen.get_window_actors ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var copy = actors.copy ();
|
var copy = actors.copy ();
|
||||||
copy.reverse ();
|
copy.reverse ();
|
||||||
|
|
||||||
weak Meta.WindowActor? selected = null;
|
weak Meta.WindowActor? selected = null;
|
||||||
copy.@foreach ((actor) => {
|
copy.@foreach ((actor) => {
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var window = actor.get_meta_window ();
|
var window = actor.get_meta_window ();
|
||||||
var rect = window.get_frame_rect ();
|
var rect = window.get_frame_rect ();
|
||||||
|
|
||||||
if (!actor.is_destroyed () && !window.is_hidden () && !window.is_skip_taskbar () && meta_rectangle_contains (rect, x, y)) {
|
if (!actor.is_destroyed () && !window.is_hidden () && !window.is_skip_taskbar () && meta_rectangle_contains (rect, x, y)) {
|
||||||
selected = actor;
|
selected = actor;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Meta.WindowActor? get_active_window_actor ()
|
private Meta.WindowActor? get_active_window_actor ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = wm.get_display ();
|
unowned Meta.Display display = wm.get_display ();
|
||||||
unowned List<Meta.WindowActor> actors = display.get_window_actors ();
|
unowned List<Meta.WindowActor> actors = display.get_window_actors ();
|
||||||
#else
|
#else
|
||||||
var screen = wm.get_screen ();
|
var screen = wm.get_screen ();
|
||||||
unowned List<Meta.WindowActor> actors = screen.get_window_actors ();
|
unowned List<Meta.WindowActor> actors = screen.get_window_actors ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var copy = actors.copy ();
|
var copy = actors.copy ();
|
||||||
copy.reverse ();
|
copy.reverse ();
|
||||||
|
|
||||||
weak Meta.WindowActor? active = null;
|
weak Meta.WindowActor? active = null;
|
||||||
actors.@foreach ((actor) => {
|
actors.@foreach ((actor) => {
|
||||||
if (active != null) {
|
if (active != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var window = actor.get_meta_window ();
|
var window = actor.get_meta_window ();
|
||||||
if (!actor.is_destroyed () && !window.is_hidden () && !window.is_skip_taskbar () && window.has_focus ()) {
|
if (!actor.is_destroyed () && !window.is_hidden () && !window.is_skip_taskbar () && window.has_focus ()) {
|
||||||
active = actor;
|
active = actor;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void add_window (PopupWindow popup_window)
|
private void add_window (PopupWindow popup_window)
|
||||||
{
|
{
|
||||||
popup_window.closed.connect (() => remove_window (popup_window));
|
popup_window.closed.connect (() => remove_window (popup_window));
|
||||||
windows.add (popup_window);
|
windows.add (popup_window);
|
||||||
wm.ui_group.add_child (popup_window);
|
wm.ui_group.add_child (popup_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void remove_window (PopupWindow popup_window)
|
private void remove_window (PopupWindow popup_window)
|
||||||
{
|
{
|
||||||
windows.remove (popup_window);
|
windows.remove (popup_window);
|
||||||
untrack_window (popup_window);
|
untrack_window (popup_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void untrack_window (PopupWindow popup_window)
|
private void untrack_window (PopupWindow popup_window)
|
||||||
{
|
{
|
||||||
untrack_actor (popup_window);
|
untrack_actor (popup_window);
|
||||||
update_region ();
|
update_region ();
|
||||||
popup_window.destroy ();
|
popup_window.destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gala.PluginInfo register_plugin ()
|
public Gala.PluginInfo register_plugin ()
|
||||||
{
|
{
|
||||||
return Gala.PluginInfo () {
|
return Gala.PluginInfo () {
|
||||||
name = "Popup Window",
|
name = "Popup Window",
|
||||||
author = "Adam Bieńkowski <donadigos159@gmail.com>",
|
author = "Adam Bieńkowski <donadigos159@gmail.com>",
|
||||||
plugin_type = typeof (Gala.Plugins.PIP.Plugin),
|
plugin_type = typeof (Gala.Plugins.PIP.Plugin),
|
||||||
provides = Gala.PluginFunction.ADDITION,
|
provides = Gala.PluginFunction.ADDITION,
|
||||||
load_priority = Gala.LoadPriority.IMMEDIATE
|
load_priority = Gala.LoadPriority.IMMEDIATE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
public class Gala.Plugins.PIP.MoveAction : Clutter.DragAction
|
public class Gala.Plugins.PIP.MoveAction : Clutter.DragAction
|
||||||
{
|
{
|
||||||
public signal void move ();
|
public signal void move ();
|
||||||
|
|
||||||
public override bool drag_progress (Clutter.Actor actor, float delta_x, float delta_y)
|
public override bool drag_progress (Clutter.Actor actor, float delta_x, float delta_y)
|
||||||
{
|
{
|
||||||
move ();
|
move ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,452 +17,452 @@
|
|||||||
|
|
||||||
public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor
|
public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor
|
||||||
{
|
{
|
||||||
private int button_size;
|
private int button_size;
|
||||||
private int container_margin;
|
private int container_margin;
|
||||||
private const int SHADOW_SIZE = 100;
|
private const int SHADOW_SIZE = 100;
|
||||||
private const uint FADE_OUT_TIMEOUT = 200;
|
private const uint FADE_OUT_TIMEOUT = 200;
|
||||||
private const float MINIMUM_SCALE = 0.1f;
|
private const float MINIMUM_SCALE = 0.1f;
|
||||||
private const float MAXIMUM_SCALE = 1.0f;
|
private const float MAXIMUM_SCALE = 1.0f;
|
||||||
private const int SCREEN_MARGIN = 0;
|
private const int SCREEN_MARGIN = 0;
|
||||||
|
|
||||||
public signal void closed ();
|
public signal void closed ();
|
||||||
|
|
||||||
public Gala.WindowManager wm { get; construct; }
|
public Gala.WindowManager wm { get; construct; }
|
||||||
public Meta.WindowActor window_actor { get; construct; }
|
public Meta.WindowActor window_actor { get; construct; }
|
||||||
public Clutter.Rect? container_clip { get; construct; }
|
public Clutter.Rect? container_clip { get; construct; }
|
||||||
|
|
||||||
private Clutter.Actor clone;
|
private Clutter.Actor clone;
|
||||||
private Clutter.Actor container;
|
private Clutter.Actor container;
|
||||||
private Clutter.Actor close_button;
|
private Clutter.Actor close_button;
|
||||||
private Clutter.Actor resize_button;
|
private Clutter.Actor resize_button;
|
||||||
private Clutter.Actor resize_handle;
|
private Clutter.Actor resize_handle;
|
||||||
private Clutter.ClickAction close_action;
|
private Clutter.ClickAction close_action;
|
||||||
private Clutter.DragAction resize_action;
|
private Clutter.DragAction resize_action;
|
||||||
private MoveAction move_action;
|
private MoveAction move_action;
|
||||||
|
|
||||||
private bool dragging = false;
|
private bool dragging = false;
|
||||||
private bool clicked = false;
|
private bool clicked = false;
|
||||||
|
|
||||||
private int x_offset_press = 0;
|
private int x_offset_press = 0;
|
||||||
private int y_offset_press = 0;
|
private int y_offset_press = 0;
|
||||||
|
|
||||||
private float begin_resize_width = 0.0f;
|
private float begin_resize_width = 0.0f;
|
||||||
private float begin_resize_height = 0.0f;
|
private float begin_resize_height = 0.0f;
|
||||||
|
|
||||||
static unowned Meta.Window? previous_focus = null;
|
static unowned Meta.Window? previous_focus = null;
|
||||||
|
|
||||||
// From https://opensourcehacker.com/2011/12/01/calculate-aspect-ratio-conserving-resize-for-images-in-javascript/
|
// From https://opensourcehacker.com/2011/12/01/calculate-aspect-ratio-conserving-resize-for-images-in-javascript/
|
||||||
static void calculate_aspect_ratio_size_fit (float src_width, float src_height, float max_width, float max_height,
|
static void calculate_aspect_ratio_size_fit (float src_width, float src_height, float max_width, float max_height,
|
||||||
out float width, out float height)
|
out float width, out float height)
|
||||||
{
|
{
|
||||||
float ratio = float.min (max_width / src_width, max_height / src_height);
|
float ratio = float.min (max_width / src_width, max_height / src_height);
|
||||||
width = src_width * ratio;
|
width = src_width * ratio;
|
||||||
height = src_height * ratio;
|
height = src_height * ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_window_is_normal (Meta.Window window)
|
static bool get_window_is_normal (Meta.Window window)
|
||||||
{
|
{
|
||||||
var window_type = window.get_window_type ();
|
var window_type = window.get_window_type ();
|
||||||
return window_type == Meta.WindowType.NORMAL
|
return window_type == Meta.WindowType.NORMAL
|
||||||
|| window_type == Meta.WindowType.DIALOG
|
|| window_type == Meta.WindowType.DIALOG
|
||||||
|| window_type == Meta.WindowType.MODAL_DIALOG;
|
|| window_type == Meta.WindowType.MODAL_DIALOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_current_cursor_position (out int x, out int y)
|
static void get_current_cursor_position (out int x, out int y)
|
||||||
{
|
{
|
||||||
Gdk.Display.get_default ().get_device_manager ().get_client_pointer ().get_position (null, out x, out y);
|
Gdk.Display.get_default ().get_device_manager ().get_client_pointer ().get_position (null, out x, out y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PopupWindow (Gala.WindowManager wm, Meta.WindowActor window_actor, Clutter.Rect? container_clip)
|
public PopupWindow (Gala.WindowManager wm, Meta.WindowActor window_actor, Clutter.Rect? container_clip)
|
||||||
{
|
{
|
||||||
Object (wm: wm, window_actor: window_actor, container_clip: container_clip);
|
Object (wm: wm, window_actor: window_actor, container_clip: container_clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
var scale = Utils.get_ui_scaling_factor ();
|
var scale = Utils.get_ui_scaling_factor ();
|
||||||
button_size = 36 * scale;
|
button_size = 36 * scale;
|
||||||
container_margin = button_size / 2;
|
container_margin = button_size / 2;
|
||||||
|
|
||||||
reactive = true;
|
reactive = true;
|
||||||
|
|
||||||
set_pivot_point (0.5f, 0.5f);
|
set_pivot_point (0.5f, 0.5f);
|
||||||
set_easing_mode (Clutter.AnimationMode.EASE_IN_QUAD);
|
set_easing_mode (Clutter.AnimationMode.EASE_IN_QUAD);
|
||||||
|
|
||||||
var window = window_actor.get_meta_window ();
|
var window = window_actor.get_meta_window ();
|
||||||
window.unmanaged.connect (on_close_click_clicked);
|
window.unmanaged.connect (on_close_click_clicked);
|
||||||
window.notify["appears-focused"].connect (() => {
|
window.notify["appears-focused"].connect (() => {
|
||||||
Idle.add (() => {
|
Idle.add (() => {
|
||||||
update_window_focus ();
|
update_window_focus ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
clone = new Clutter.Clone (window_actor);
|
clone = new Clutter.Clone (window_actor);
|
||||||
|
|
||||||
move_action = new MoveAction ();
|
move_action = new MoveAction ();
|
||||||
move_action.drag_begin.connect (on_move_begin);
|
move_action.drag_begin.connect (on_move_begin);
|
||||||
move_action.drag_end.connect (on_move_end);
|
move_action.drag_end.connect (on_move_end);
|
||||||
move_action.move.connect (on_move);
|
move_action.move.connect (on_move);
|
||||||
|
|
||||||
container = new Clutter.Actor ();
|
container = new Clutter.Actor ();
|
||||||
container.reactive = true;
|
container.reactive = true;
|
||||||
container.set_scale (0.35f, 0.35f);
|
container.set_scale (0.35f, 0.35f);
|
||||||
container.clip_rect = container_clip;
|
container.clip_rect = container_clip;
|
||||||
container.add_effect (new ShadowEffect (SHADOW_SIZE, 2));
|
container.add_effect (new ShadowEffect (SHADOW_SIZE, 2));
|
||||||
container.add_child (clone);
|
container.add_child (clone);
|
||||||
container.add_action (move_action);
|
container.add_action (move_action);
|
||||||
|
|
||||||
if (container_clip == null) {
|
if (container_clip == null) {
|
||||||
window_actor.notify["allocation"].connect (on_allocation_changed);
|
window_actor.notify["allocation"].connect (on_allocation_changed);
|
||||||
container.set_position (container_margin, container_margin);
|
container.set_position (container_margin, container_margin);
|
||||||
update_clone_clip ();
|
update_clone_clip ();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_size ();
|
update_size ();
|
||||||
update_container_position ();
|
update_container_position ();
|
||||||
|
|
||||||
Meta.Rectangle monitor_rect;
|
Meta.Rectangle monitor_rect;
|
||||||
get_current_monitor_rect (out monitor_rect);
|
get_current_monitor_rect (out monitor_rect);
|
||||||
|
|
||||||
float x_position, y_position;
|
float x_position, y_position;
|
||||||
if (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL) {
|
if (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL) {
|
||||||
x_position = SCREEN_MARGIN + monitor_rect.x;
|
x_position = SCREEN_MARGIN + monitor_rect.x;
|
||||||
} else {
|
} else {
|
||||||
x_position = monitor_rect.width + monitor_rect.x - SCREEN_MARGIN - width;
|
x_position = monitor_rect.width + monitor_rect.x - SCREEN_MARGIN - width;
|
||||||
}
|
}
|
||||||
y_position = monitor_rect.height + monitor_rect.y - SCREEN_MARGIN - height;
|
y_position = monitor_rect.height + monitor_rect.y - SCREEN_MARGIN - height;
|
||||||
|
|
||||||
set_position (x_position, y_position);
|
set_position (x_position, y_position);
|
||||||
|
|
||||||
close_action = new Clutter.ClickAction ();
|
close_action = new Clutter.ClickAction ();
|
||||||
close_action.clicked.connect (on_close_click_clicked);
|
close_action.clicked.connect (on_close_click_clicked);
|
||||||
|
|
||||||
close_button = Gala.Utils.create_close_button ();
|
close_button = Gala.Utils.create_close_button ();
|
||||||
close_button.opacity = 0;
|
close_button.opacity = 0;
|
||||||
close_button.reactive = true;
|
close_button.reactive = true;
|
||||||
close_button.set_easing_duration (300);
|
close_button.set_easing_duration (300);
|
||||||
close_button.add_action (close_action);
|
close_button.add_action (close_action);
|
||||||
|
|
||||||
resize_action = new Clutter.DragAction ();
|
resize_action = new Clutter.DragAction ();
|
||||||
resize_action.drag_begin.connect (on_resize_drag_begin);
|
resize_action.drag_begin.connect (on_resize_drag_begin);
|
||||||
resize_action.drag_end.connect (on_resize_drag_end);
|
resize_action.drag_end.connect (on_resize_drag_end);
|
||||||
resize_action.drag_motion.connect (on_resize_drag_motion);
|
resize_action.drag_motion.connect (on_resize_drag_motion);
|
||||||
|
|
||||||
resize_handle = new Clutter.Actor ();
|
resize_handle = new Clutter.Actor ();
|
||||||
resize_handle.set_size (button_size, button_size);
|
resize_handle.set_size (button_size, button_size);
|
||||||
resize_handle.set_pivot_point (0.5f, 0.5f);
|
resize_handle.set_pivot_point (0.5f, 0.5f);
|
||||||
resize_handle.set_position (width - button_size, height - button_size);
|
resize_handle.set_position (width - button_size, height - button_size);
|
||||||
resize_handle.reactive = true;
|
resize_handle.reactive = true;
|
||||||
resize_handle.add_action (resize_action);
|
resize_handle.add_action (resize_action);
|
||||||
|
|
||||||
resize_button = Utils.create_resize_button ();
|
resize_button = Utils.create_resize_button ();
|
||||||
resize_button.set_pivot_point (0.5f, 0.5f);
|
resize_button.set_pivot_point (0.5f, 0.5f);
|
||||||
resize_button.set_position (width - button_size, height - button_size);
|
resize_button.set_position (width - button_size, height - button_size);
|
||||||
resize_button.opacity = 0;
|
resize_button.opacity = 0;
|
||||||
resize_button.reactive = true;
|
resize_button.reactive = true;
|
||||||
|
|
||||||
add_child (container);
|
add_child (container);
|
||||||
add_child (close_button);
|
add_child (close_button);
|
||||||
add_child (resize_button);
|
add_child (resize_button);
|
||||||
add_child (resize_handle);
|
add_child (resize_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void show ()
|
public override void show ()
|
||||||
{
|
{
|
||||||
base.show ();
|
base.show ();
|
||||||
|
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
|
|
||||||
set_easing_duration (200);
|
set_easing_duration (200);
|
||||||
opacity = 255;
|
opacity = 255;
|
||||||
|
|
||||||
set_easing_duration (0);
|
set_easing_duration (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void hide ()
|
public override void hide ()
|
||||||
{
|
{
|
||||||
opacity = 255;
|
opacity = 255;
|
||||||
|
|
||||||
set_easing_duration (200);
|
set_easing_duration (200);
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
|
|
||||||
set_easing_duration (0);
|
set_easing_duration (0);
|
||||||
|
|
||||||
ulong completed_id = 0UL;
|
ulong completed_id = 0UL;
|
||||||
completed_id = transitions_completed.connect (() => {
|
completed_id = transitions_completed.connect (() => {
|
||||||
disconnect (completed_id);
|
disconnect (completed_id);
|
||||||
base.hide ();
|
base.hide ();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool enter_event (Clutter.CrossingEvent event)
|
public override bool enter_event (Clutter.CrossingEvent event)
|
||||||
{
|
{
|
||||||
close_button.opacity = 255;
|
close_button.opacity = 255;
|
||||||
|
|
||||||
resize_button.set_easing_duration (300);
|
resize_button.set_easing_duration (300);
|
||||||
resize_button.opacity = 255;
|
resize_button.opacity = 255;
|
||||||
resize_button.set_easing_duration (0);
|
resize_button.set_easing_duration (0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool leave_event (Clutter.CrossingEvent event)
|
public override bool leave_event (Clutter.CrossingEvent event)
|
||||||
{
|
{
|
||||||
close_button.opacity = 0;
|
close_button.opacity = 0;
|
||||||
|
|
||||||
resize_button.set_easing_duration (300);
|
resize_button.set_easing_duration (300);
|
||||||
resize_button.opacity = 0;
|
resize_button.opacity = 0;
|
||||||
resize_button.set_easing_duration (0);
|
resize_button.set_easing_duration (0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_move_begin ()
|
private void on_move_begin ()
|
||||||
{
|
{
|
||||||
int px, py;
|
int px, py;
|
||||||
get_current_cursor_position (out px, out py);
|
get_current_cursor_position (out px, out py);
|
||||||
|
|
||||||
x_offset_press = (int)(px - x);
|
x_offset_press = (int)(px - x);
|
||||||
y_offset_press = (int)(py - y);
|
y_offset_press = (int)(py - y);
|
||||||
|
|
||||||
clicked = true;
|
clicked = true;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_move_end ()
|
private void on_move_end ()
|
||||||
{
|
{
|
||||||
clicked = false;
|
clicked = false;
|
||||||
|
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
update_screen_position ();
|
update_screen_position ();
|
||||||
dragging = false;
|
dragging = false;
|
||||||
} else {
|
} else {
|
||||||
activate ();
|
activate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_move ()
|
private void on_move ()
|
||||||
{
|
{
|
||||||
if (!clicked) {
|
if (!clicked) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float motion_x, motion_y;
|
float motion_x, motion_y;
|
||||||
move_action.get_motion_coords (out motion_x, out motion_y);
|
move_action.get_motion_coords (out motion_x, out motion_y);
|
||||||
|
|
||||||
x = (int)motion_x - x_offset_press;
|
x = (int)motion_x - x_offset_press;
|
||||||
y = (int)motion_y - y_offset_press;
|
y = (int)motion_y - y_offset_press;
|
||||||
|
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
dragging = true;
|
dragging = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_resize_drag_begin (Clutter.Actor actor, float event_x, float event_y, Clutter.ModifierType type)
|
private void on_resize_drag_begin (Clutter.Actor actor, float event_x, float event_y, Clutter.ModifierType type)
|
||||||
{
|
{
|
||||||
begin_resize_width = width;
|
begin_resize_width = width;
|
||||||
begin_resize_height = height;
|
begin_resize_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_resize_drag_end (Clutter.Actor actor, float event_x, float event_y, Clutter.ModifierType type)
|
private void on_resize_drag_end (Clutter.Actor actor, float event_x, float event_y, Clutter.ModifierType type)
|
||||||
{
|
{
|
||||||
reposition_resize_handle ();
|
reposition_resize_handle ();
|
||||||
update_screen_position ();
|
update_screen_position ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_resize_drag_motion (Clutter.Actor actor, float delta_x, float delta_y)
|
private void on_resize_drag_motion (Clutter.Actor actor, float delta_x, float delta_y)
|
||||||
{
|
{
|
||||||
float press_x, press_y;
|
float press_x, press_y;
|
||||||
resize_action.get_press_coords (out press_x, out press_y);
|
resize_action.get_press_coords (out press_x, out press_y);
|
||||||
|
|
||||||
int motion_x, motion_y;
|
int motion_x, motion_y;
|
||||||
get_current_cursor_position (out motion_x, out motion_y);
|
get_current_cursor_position (out motion_x, out motion_y);
|
||||||
|
|
||||||
float diff_x = motion_x - press_x;
|
float diff_x = motion_x - press_x;
|
||||||
float diff_y = motion_y - press_y;
|
float diff_y = motion_y - press_y;
|
||||||
|
|
||||||
width = begin_resize_width + diff_x;
|
width = begin_resize_width + diff_x;
|
||||||
height = begin_resize_height + diff_y;
|
height = begin_resize_height + diff_y;
|
||||||
|
|
||||||
update_container_scale ();
|
update_container_scale ();
|
||||||
update_size ();
|
update_size ();
|
||||||
reposition_resize_button ();
|
reposition_resize_button ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_allocation_changed ()
|
private void on_allocation_changed ()
|
||||||
{
|
{
|
||||||
update_clone_clip ();
|
update_clone_clip ();
|
||||||
update_size ();
|
update_size ();
|
||||||
reposition_resize_button ();
|
reposition_resize_button ();
|
||||||
reposition_resize_handle ();
|
reposition_resize_handle ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_close_click_clicked ()
|
private void on_close_click_clicked ()
|
||||||
{
|
{
|
||||||
set_easing_duration (FADE_OUT_TIMEOUT);
|
set_easing_duration (FADE_OUT_TIMEOUT);
|
||||||
|
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
|
|
||||||
Clutter.Threads.Timeout.add (FADE_OUT_TIMEOUT, () => {
|
Clutter.Threads.Timeout.add (FADE_OUT_TIMEOUT, () => {
|
||||||
closed ();
|
closed ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_window_focus ()
|
private void update_window_focus ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Window focus_window = wm.get_display ().get_focus_window ();
|
unowned Meta.Window focus_window = wm.get_display ().get_focus_window ();
|
||||||
#else
|
#else
|
||||||
unowned Meta.Window focus_window = wm.get_screen ().get_display ().get_focus_window ();
|
unowned Meta.Window focus_window = wm.get_screen ().get_display ().get_focus_window ();
|
||||||
#endif
|
#endif
|
||||||
if ((focus_window != null && !get_window_is_normal (focus_window))
|
if ((focus_window != null && !get_window_is_normal (focus_window))
|
||||||
|| (previous_focus != null && !get_window_is_normal (previous_focus))) {
|
|| (previous_focus != null && !get_window_is_normal (previous_focus))) {
|
||||||
previous_focus = focus_window;
|
previous_focus = focus_window;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var window = window_actor.get_meta_window ();
|
var window = window_actor.get_meta_window ();
|
||||||
if (window.appears_focused) {
|
if (window.appears_focused) {
|
||||||
hide ();
|
hide ();
|
||||||
} else if (!window_actor.is_destroyed ()) {
|
} else if (!window_actor.is_destroyed ()) {
|
||||||
show ();
|
show ();
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_focus = focus_window;
|
previous_focus = focus_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_size ()
|
private void update_size ()
|
||||||
{
|
{
|
||||||
if (container_clip != null) {
|
if (container_clip != null) {
|
||||||
width = (int)(container_clip.get_width () * container.scale_x + button_size);
|
width = (int)(container_clip.get_width () * container.scale_x + button_size);
|
||||||
height = (int)(container_clip.get_height () * container.scale_y + button_size);
|
height = (int)(container_clip.get_height () * container.scale_y + button_size);
|
||||||
} else {
|
} else {
|
||||||
width = (int)(container.width * container.scale_x + button_size);
|
width = (int)(container.width * container.scale_x + button_size);
|
||||||
height = (int)(container.height * container.scale_y + button_size);
|
height = (int)(container.height * container.scale_y + button_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_clone_clip ()
|
private void update_clone_clip ()
|
||||||
{
|
{
|
||||||
var rect = window_actor.get_meta_window ().get_frame_rect ();
|
var rect = window_actor.get_meta_window ().get_frame_rect ();
|
||||||
|
|
||||||
float x_offset = rect.x - window_actor.x;
|
float x_offset = rect.x - window_actor.x;
|
||||||
float y_offset = rect.y - window_actor.y;
|
float y_offset = rect.y - window_actor.y;
|
||||||
clone.set_clip (x_offset, y_offset, rect.width, rect.height);
|
clone.set_clip (x_offset, y_offset, rect.width, rect.height);
|
||||||
clone.set_position (-x_offset, -y_offset);
|
clone.set_position (-x_offset, -y_offset);
|
||||||
|
|
||||||
container.set_size (rect.width, rect.height);
|
container.set_size (rect.width, rect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_container_scale ()
|
private void update_container_scale ()
|
||||||
{
|
{
|
||||||
float src_width;
|
float src_width;
|
||||||
float src_height;
|
float src_height;
|
||||||
if (container_clip != null) {
|
if (container_clip != null) {
|
||||||
src_width = container_clip.get_width ();
|
src_width = container_clip.get_width ();
|
||||||
src_height = container_clip.get_height ();
|
src_height = container_clip.get_height ();
|
||||||
} else {
|
} else {
|
||||||
src_width = container.width;
|
src_width = container.width;
|
||||||
src_height = container.height;
|
src_height = container.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
float max_width = width - button_size;
|
float max_width = width - button_size;
|
||||||
float max_height = height - button_size;
|
float max_height = height - button_size;
|
||||||
|
|
||||||
float new_width, new_height;
|
float new_width, new_height;
|
||||||
calculate_aspect_ratio_size_fit (
|
calculate_aspect_ratio_size_fit (
|
||||||
src_width, src_height,
|
src_width, src_height,
|
||||||
max_width, max_height,
|
max_width, max_height,
|
||||||
out new_width, out new_height
|
out new_width, out new_height
|
||||||
);
|
);
|
||||||
|
|
||||||
float window_width, window_height;
|
float window_width, window_height;
|
||||||
get_target_window_size (out window_width, out window_height);
|
get_target_window_size (out window_width, out window_height);
|
||||||
|
|
||||||
float new_scale_x = new_width / window_width;
|
float new_scale_x = new_width / window_width;
|
||||||
float new_scale_y = new_height / window_height;
|
float new_scale_y = new_height / window_height;
|
||||||
|
|
||||||
container.scale_x = new_scale_x.clamp (MINIMUM_SCALE, MAXIMUM_SCALE);
|
container.scale_x = new_scale_x.clamp (MINIMUM_SCALE, MAXIMUM_SCALE);
|
||||||
container.scale_y = new_scale_y.clamp (MINIMUM_SCALE, MAXIMUM_SCALE);
|
container.scale_y = new_scale_y.clamp (MINIMUM_SCALE, MAXIMUM_SCALE);
|
||||||
|
|
||||||
update_container_position ();
|
update_container_position ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_container_position ()
|
private void update_container_position ()
|
||||||
{
|
{
|
||||||
if (container_clip != null) {
|
if (container_clip != null) {
|
||||||
container.x = (float)(-container_clip.get_x () * container.scale_x + container_margin);
|
container.x = (float)(-container_clip.get_x () * container.scale_x + container_margin);
|
||||||
container.y = (float)(-container_clip.get_y () * container.scale_y + container_margin);
|
container.y = (float)(-container_clip.get_y () * container.scale_y + container_margin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_screen_position ()
|
private void update_screen_position ()
|
||||||
{
|
{
|
||||||
Meta.Rectangle monitor_rect;
|
Meta.Rectangle monitor_rect;
|
||||||
get_current_monitor_rect (out monitor_rect);
|
get_current_monitor_rect (out monitor_rect);
|
||||||
|
|
||||||
int monitor_x = monitor_rect.x;
|
int monitor_x = monitor_rect.x;
|
||||||
int monitor_y = monitor_rect.y;
|
int monitor_y = monitor_rect.y;
|
||||||
int monitor_width = monitor_rect.width;
|
int monitor_width = monitor_rect.width;
|
||||||
int monitor_height = monitor_rect.height;
|
int monitor_height = monitor_rect.height;
|
||||||
|
|
||||||
set_easing_duration (300);
|
set_easing_duration (300);
|
||||||
set_easing_mode (Clutter.AnimationMode.EASE_OUT_BACK);
|
set_easing_mode (Clutter.AnimationMode.EASE_OUT_BACK);
|
||||||
|
|
||||||
var screen_limit_start = SCREEN_MARGIN + monitor_x;
|
var screen_limit_start = SCREEN_MARGIN + monitor_x;
|
||||||
var screen_limit_end = monitor_width + monitor_x - SCREEN_MARGIN - width;
|
var screen_limit_end = monitor_width + monitor_x - SCREEN_MARGIN - width;
|
||||||
|
|
||||||
x = x.clamp (screen_limit_start, screen_limit_end);
|
x = x.clamp (screen_limit_start, screen_limit_end);
|
||||||
|
|
||||||
screen_limit_start = SCREEN_MARGIN + monitor_y;
|
screen_limit_start = SCREEN_MARGIN + monitor_y;
|
||||||
screen_limit_end = monitor_height + monitor_y - SCREEN_MARGIN - height;
|
screen_limit_end = monitor_height + monitor_y - SCREEN_MARGIN - height;
|
||||||
|
|
||||||
y = y.clamp (screen_limit_start, screen_limit_end);
|
y = y.clamp (screen_limit_start, screen_limit_end);
|
||||||
|
|
||||||
set_easing_mode (Clutter.AnimationMode.EASE_IN_QUAD);
|
set_easing_mode (Clutter.AnimationMode.EASE_IN_QUAD);
|
||||||
set_easing_duration (0);
|
set_easing_duration (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reposition_resize_button ()
|
private void reposition_resize_button ()
|
||||||
{
|
{
|
||||||
resize_button.set_position (width - button_size, height - button_size);
|
resize_button.set_position (width - button_size, height - button_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reposition_resize_handle ()
|
private void reposition_resize_handle ()
|
||||||
{
|
{
|
||||||
resize_handle.set_position (width - button_size, height - button_size);
|
resize_handle.set_position (width - button_size, height - button_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void get_current_monitor_rect (out Meta.Rectangle rect)
|
private void get_current_monitor_rect (out Meta.Rectangle rect)
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var display = wm.get_display ();
|
var display = wm.get_display ();
|
||||||
rect = display.get_monitor_geometry (display.get_current_monitor ());
|
rect = display.get_monitor_geometry (display.get_current_monitor ());
|
||||||
#else
|
#else
|
||||||
var screen = wm.get_screen ();
|
var screen = wm.get_screen ();
|
||||||
rect = screen.get_monitor_geometry (screen.get_current_monitor ());
|
rect = screen.get_monitor_geometry (screen.get_current_monitor ());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private void get_target_window_size (out float width, out float height)
|
private void get_target_window_size (out float width, out float height)
|
||||||
{
|
{
|
||||||
if (container_clip != null) {
|
if (container_clip != null) {
|
||||||
width = container_clip.get_width ();
|
width = container_clip.get_width ();
|
||||||
height = container_clip.get_height ();
|
height = container_clip.get_height ();
|
||||||
} else if (clone.has_clip) {
|
} else if (clone.has_clip) {
|
||||||
float clone_clip_width = 0.0f, clone_clip_height = 0.0f;
|
float clone_clip_width = 0.0f, clone_clip_height = 0.0f;
|
||||||
clone.get_clip (null, null, out clone_clip_width, out clone_clip_height);
|
clone.get_clip (null, null, out clone_clip_width, out clone_clip_height);
|
||||||
width = clone_clip_width;
|
width = clone_clip_width;
|
||||||
height = clone_clip_height;
|
height = clone_clip_height;
|
||||||
} else {
|
} else {
|
||||||
width = clone.width;
|
width = clone.width;
|
||||||
height = clone.height;
|
height = clone.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void activate ()
|
private void activate ()
|
||||||
{
|
{
|
||||||
var window = window_actor.get_meta_window ();
|
var window = window_actor.get_meta_window ();
|
||||||
window.activate (Clutter.get_current_event_time ());
|
window.activate (Clutter.get_current_event_time ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,170 +17,170 @@
|
|||||||
|
|
||||||
public class Gala.Plugins.PIP.SelectionArea : Clutter.Actor
|
public class Gala.Plugins.PIP.SelectionArea : Clutter.Actor
|
||||||
{
|
{
|
||||||
public signal void captured (int x, int y, int width, int height);
|
public signal void captured (int x, int y, int width, int height);
|
||||||
public signal void selected (int x, int y);
|
public signal void selected (int x, int y);
|
||||||
public signal void closed ();
|
public signal void closed ();
|
||||||
|
|
||||||
public Gala.WindowManager wm { get; construct; }
|
public Gala.WindowManager wm { get; construct; }
|
||||||
|
|
||||||
private Gala.ModalProxy? modal_proxy;
|
private Gala.ModalProxy? modal_proxy;
|
||||||
private Gdk.Point start_point;
|
private Gdk.Point start_point;
|
||||||
private Gdk.Point end_point;
|
private Gdk.Point end_point;
|
||||||
private bool dragging = false;
|
private bool dragging = false;
|
||||||
private bool clicked = false;
|
private bool clicked = false;
|
||||||
|
|
||||||
public SelectionArea (Gala.WindowManager wm)
|
public SelectionArea (Gala.WindowManager wm)
|
||||||
{
|
{
|
||||||
Object (wm: wm);
|
Object (wm: wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
start_point = { 0, 0 };
|
start_point = { 0, 0 };
|
||||||
end_point = { 0, 0 };
|
end_point = { 0, 0 };
|
||||||
visible = true;
|
visible = true;
|
||||||
reactive = true;
|
reactive = true;
|
||||||
|
|
||||||
int screen_width, screen_height;
|
int screen_width, screen_height;
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
wm.get_display ().get_size (out screen_width, out screen_height);
|
wm.get_display ().get_size (out screen_width, out screen_height);
|
||||||
#else
|
#else
|
||||||
wm.get_screen ().get_size (out screen_width, out screen_height);
|
wm.get_screen ().get_size (out screen_width, out screen_height);
|
||||||
#endif
|
#endif
|
||||||
width = screen_width;
|
width = screen_width;
|
||||||
height = screen_height;
|
height = screen_height;
|
||||||
|
|
||||||
var canvas = new Clutter.Canvas ();
|
var canvas = new Clutter.Canvas ();
|
||||||
canvas.set_size (screen_width, screen_height);
|
canvas.set_size (screen_width, screen_height);
|
||||||
canvas.draw.connect (draw_area);
|
canvas.draw.connect (draw_area);
|
||||||
set_content (canvas);
|
set_content (canvas);
|
||||||
|
|
||||||
canvas.invalidate ();
|
canvas.invalidate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool key_press_event (Clutter.KeyEvent e)
|
public override bool key_press_event (Clutter.KeyEvent e)
|
||||||
{
|
{
|
||||||
if (e.keyval == Clutter.Key.Escape) {
|
if (e.keyval == Clutter.Key.Escape) {
|
||||||
close ();
|
close ();
|
||||||
closed ();
|
closed ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool button_press_event (Clutter.ButtonEvent e)
|
public override bool button_press_event (Clutter.ButtonEvent e)
|
||||||
{
|
{
|
||||||
if (dragging || e.button != 1) {
|
if (dragging || e.button != 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
clicked = true;
|
clicked = true;
|
||||||
|
|
||||||
start_point.x = (int) e.x;
|
start_point.x = (int) e.x;
|
||||||
start_point.y = (int) e.y;
|
start_point.y = (int) e.y;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool button_release_event (Clutter.ButtonEvent e)
|
public override bool button_release_event (Clutter.ButtonEvent e)
|
||||||
{
|
{
|
||||||
if (e.button != 1) {
|
if (e.button != 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
selected ((int) e.x, (int) e.y);
|
selected ((int) e.x, (int) e.y);
|
||||||
close ();
|
close ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dragging = false;
|
dragging = false;
|
||||||
clicked = false;
|
clicked = false;
|
||||||
|
|
||||||
int x, y, w, h;
|
int x, y, w, h;
|
||||||
get_selection_rectangle (out x, out y, out w, out h);
|
get_selection_rectangle (out x, out y, out w, out h);
|
||||||
close ();
|
close ();
|
||||||
start_point = { 0, 0 };
|
start_point = { 0, 0 };
|
||||||
end_point = { 0, 0 };
|
end_point = { 0, 0 };
|
||||||
this.hide ();
|
this.hide ();
|
||||||
content.invalidate ();
|
content.invalidate ();
|
||||||
|
|
||||||
captured (x, y, w, h);
|
captured (x, y, w, h);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool motion_event (Clutter.MotionEvent e)
|
public override bool motion_event (Clutter.MotionEvent e)
|
||||||
{
|
{
|
||||||
if (!clicked) {
|
if (!clicked) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
end_point.x = (int) e.x;
|
end_point.x = (int) e.x;
|
||||||
end_point.y = (int) e.y;
|
end_point.y = (int) e.y;
|
||||||
content.invalidate ();
|
content.invalidate ();
|
||||||
|
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
dragging = true;
|
dragging = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close ()
|
public void close ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
wm.get_display ().set_cursor (Meta.Cursor.DEFAULT);
|
wm.get_display ().set_cursor (Meta.Cursor.DEFAULT);
|
||||||
#else
|
#else
|
||||||
wm.get_screen ().set_cursor (Meta.Cursor.DEFAULT);
|
wm.get_screen ().set_cursor (Meta.Cursor.DEFAULT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (modal_proxy != null) {
|
if (modal_proxy != null) {
|
||||||
wm.pop_modal (modal_proxy);
|
wm.pop_modal (modal_proxy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start_selection ()
|
public void start_selection ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
wm.get_display ().set_cursor (Meta.Cursor.CROSSHAIR);
|
wm.get_display ().set_cursor (Meta.Cursor.CROSSHAIR);
|
||||||
#else
|
#else
|
||||||
wm.get_screen ().set_cursor (Meta.Cursor.CROSSHAIR);
|
wm.get_screen ().set_cursor (Meta.Cursor.CROSSHAIR);
|
||||||
#endif
|
#endif
|
||||||
grab_key_focus ();
|
grab_key_focus ();
|
||||||
|
|
||||||
modal_proxy = wm.push_modal ();
|
modal_proxy = wm.push_modal ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void get_selection_rectangle (out int x, out int y, out int width, out int height)
|
private void get_selection_rectangle (out int x, out int y, out int width, out int height)
|
||||||
{
|
{
|
||||||
x = int.min (start_point.x, end_point.x);
|
x = int.min (start_point.x, end_point.x);
|
||||||
y = int.min (start_point.y, end_point.y);
|
y = int.min (start_point.y, end_point.y);
|
||||||
width = (start_point.x - end_point.x).abs ();
|
width = (start_point.x - end_point.x).abs ();
|
||||||
height = (start_point.y - end_point.y).abs ();
|
height = (start_point.y - end_point.y).abs ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool draw_area (Cairo.Context ctx)
|
private bool draw_area (Cairo.Context ctx)
|
||||||
{
|
{
|
||||||
Clutter.cairo_clear (ctx);
|
Clutter.cairo_clear (ctx);
|
||||||
|
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y, w, h;
|
int x, y, w, h;
|
||||||
get_selection_rectangle (out x, out y, out w, out h);
|
get_selection_rectangle (out x, out y, out w, out h);
|
||||||
|
|
||||||
ctx.rectangle (x, y, w, h);
|
ctx.rectangle (x, y, w, h);
|
||||||
ctx.set_source_rgba (0.1, 0.1, 0.1, 0.2);
|
ctx.set_source_rgba (0.1, 0.1, 0.1, 0.2);
|
||||||
ctx.fill ();
|
ctx.fill ();
|
||||||
|
|
||||||
ctx.rectangle (x, y, w, h);
|
ctx.rectangle (x, y, w, h);
|
||||||
ctx.set_source_rgb (0.7, 0.7, 0.7);
|
ctx.set_source_rgb (0.7, 0.7, 0.7);
|
||||||
ctx.set_line_width (1.0);
|
ctx.set_line_width (1.0);
|
||||||
ctx.stroke ();
|
ctx.stroke ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,135 +19,135 @@ using Clutter;
|
|||||||
|
|
||||||
namespace Gala.Plugins.PIP
|
namespace Gala.Plugins.PIP
|
||||||
{
|
{
|
||||||
public class ShadowEffect : Effect
|
public class ShadowEffect : Effect
|
||||||
{
|
{
|
||||||
private class Shadow
|
private class Shadow
|
||||||
{
|
{
|
||||||
public int users;
|
public int users;
|
||||||
public Cogl.Texture texture;
|
public Cogl.Texture texture;
|
||||||
|
|
||||||
public Shadow (Cogl.Texture _texture)
|
public Shadow (Cogl.Texture _texture)
|
||||||
{
|
{
|
||||||
texture = _texture;
|
texture = _texture;
|
||||||
users = 1;
|
users = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the sizes of the textures often repeat, especially for the background actor
|
// the sizes of the textures often repeat, especially for the background actor
|
||||||
// so we keep a cache to avoid creating the same texture all over again.
|
// so we keep a cache to avoid creating the same texture all over again.
|
||||||
static Gee.HashMap<string,Shadow> shadow_cache;
|
static Gee.HashMap<string,Shadow> shadow_cache;
|
||||||
|
|
||||||
static construct
|
static construct
|
||||||
{
|
{
|
||||||
shadow_cache = new Gee.HashMap<string,Shadow> ();
|
shadow_cache = new Gee.HashMap<string,Shadow> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int shadow_size { get; construct; }
|
public int shadow_size { get; construct; }
|
||||||
public int shadow_spread { get; construct; }
|
public int shadow_spread { get; construct; }
|
||||||
|
|
||||||
public float scale_factor { get; set; default = 1; }
|
public float scale_factor { get; set; default = 1; }
|
||||||
public uint8 shadow_opacity { get; set; default = 255; }
|
public uint8 shadow_opacity { get; set; default = 255; }
|
||||||
|
|
||||||
Cogl.Material material;
|
Cogl.Material material;
|
||||||
string? current_key = null;
|
string? current_key = null;
|
||||||
|
|
||||||
public ShadowEffect (int shadow_size, int shadow_spread)
|
public ShadowEffect (int shadow_size, int shadow_spread)
|
||||||
{
|
{
|
||||||
Object (shadow_size: shadow_size, shadow_spread: shadow_spread);
|
Object (shadow_size: shadow_size, shadow_spread: shadow_spread);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
material = new Cogl.Material ();
|
material = new Cogl.Material ();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ShadowEffect ()
|
~ShadowEffect ()
|
||||||
{
|
{
|
||||||
if (current_key != null)
|
if (current_key != null)
|
||||||
decrement_shadow_users (current_key);
|
decrement_shadow_users (current_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cogl.Texture? get_shadow (int width, int height, int shadow_size, int shadow_spread)
|
Cogl.Texture? get_shadow (int width, int height, int shadow_size, int shadow_spread)
|
||||||
{
|
{
|
||||||
var old_key = current_key;
|
var old_key = current_key;
|
||||||
|
|
||||||
current_key = "%ix%i:%i:%i".printf (width, height, shadow_size, shadow_spread);
|
current_key = "%ix%i:%i:%i".printf (width, height, shadow_size, shadow_spread);
|
||||||
if (old_key == current_key)
|
if (old_key == current_key)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (old_key != null)
|
if (old_key != null)
|
||||||
decrement_shadow_users (old_key);
|
decrement_shadow_users (old_key);
|
||||||
|
|
||||||
Shadow? shadow = null;
|
Shadow? shadow = null;
|
||||||
if ((shadow = shadow_cache.@get (current_key)) != null) {
|
if ((shadow = shadow_cache.@get (current_key)) != null) {
|
||||||
shadow.users++;
|
shadow.users++;
|
||||||
return shadow.texture;
|
return shadow.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill a new texture for this size
|
// fill a new texture for this size
|
||||||
var buffer = new Granite.Drawing.BufferSurface (width, height);
|
var buffer = new Granite.Drawing.BufferSurface (width, height);
|
||||||
buffer.context.rectangle (shadow_size - shadow_spread, shadow_size - shadow_spread,
|
buffer.context.rectangle (shadow_size - shadow_spread, shadow_size - shadow_spread,
|
||||||
width - shadow_size * 2 + shadow_spread * 2, height - shadow_size * 2 + shadow_spread * 2);
|
width - shadow_size * 2 + shadow_spread * 2, height - shadow_size * 2 + shadow_spread * 2);
|
||||||
buffer.context.set_source_rgba (0, 0, 0, 0.7);
|
buffer.context.set_source_rgba (0, 0, 0, 0.7);
|
||||||
buffer.context.fill ();
|
buffer.context.fill ();
|
||||||
|
|
||||||
buffer.exponential_blur (shadow_size / 2);
|
buffer.exponential_blur (shadow_size / 2);
|
||||||
|
|
||||||
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
|
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
|
||||||
var cr = new Cairo.Context (surface);
|
var cr = new Cairo.Context (surface);
|
||||||
|
|
||||||
cr.set_source_surface (buffer.surface, 0, 0);
|
cr.set_source_surface (buffer.surface, 0, 0);
|
||||||
cr.paint ();
|
cr.paint ();
|
||||||
|
|
||||||
var texture = new Cogl.Texture.from_data (width, height, 0, Cogl.PixelFormat.BGRA_8888_PRE,
|
var texture = new Cogl.Texture.from_data (width, height, 0, Cogl.PixelFormat.BGRA_8888_PRE,
|
||||||
Cogl.PixelFormat.ANY, surface.get_stride (), surface.get_data ());
|
Cogl.PixelFormat.ANY, surface.get_stride (), surface.get_data ());
|
||||||
|
|
||||||
shadow_cache.@set (current_key, new Shadow (texture));
|
shadow_cache.@set (current_key, new Shadow (texture));
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decrement_shadow_users (string key)
|
void decrement_shadow_users (string key)
|
||||||
{
|
{
|
||||||
var shadow = shadow_cache.@get (key);
|
var shadow = shadow_cache.@get (key);
|
||||||
|
|
||||||
if (shadow == null)
|
if (shadow == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (--shadow.users == 0)
|
if (--shadow.users == 0)
|
||||||
shadow_cache.unset (key);
|
shadow_cache.unset (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void paint (EffectPaintFlags flags)
|
public override void paint (EffectPaintFlags flags)
|
||||||
{
|
{
|
||||||
var bounding_box = get_bounding_box ();
|
var bounding_box = get_bounding_box ();
|
||||||
var shadow = get_shadow ((int) (bounding_box.x2 - bounding_box.x1), (int) (bounding_box.y2 - bounding_box.y1),
|
var shadow = get_shadow ((int) (bounding_box.x2 - bounding_box.x1), (int) (bounding_box.y2 - bounding_box.y1),
|
||||||
shadow_size, shadow_spread);
|
shadow_size, shadow_spread);
|
||||||
|
|
||||||
if (shadow != null)
|
if (shadow != null)
|
||||||
material.set_layer (0, shadow);
|
material.set_layer (0, shadow);
|
||||||
|
|
||||||
var opacity = actor.get_paint_opacity () * shadow_opacity / 255;
|
var opacity = actor.get_paint_opacity () * shadow_opacity / 255;
|
||||||
var alpha = Cogl.Color.from_4ub (255, 255, 255, opacity);
|
var alpha = Cogl.Color.from_4ub (255, 255, 255, opacity);
|
||||||
alpha.premultiply ();
|
alpha.premultiply ();
|
||||||
|
|
||||||
material.set_color (alpha);
|
material.set_color (alpha);
|
||||||
|
|
||||||
Cogl.set_source (material);
|
Cogl.set_source (material);
|
||||||
Cogl.rectangle (bounding_box.x1, bounding_box.y1, bounding_box.x2, bounding_box.y2);
|
Cogl.rectangle (bounding_box.x1, bounding_box.y1, bounding_box.x2, bounding_box.y2);
|
||||||
|
|
||||||
actor.continue_paint ();
|
actor.continue_paint ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ActorBox get_bounding_box ()
|
public virtual ActorBox get_bounding_box ()
|
||||||
{
|
{
|
||||||
var size = shadow_size * scale_factor;
|
var size = shadow_size * scale_factor;
|
||||||
var bounding_box = ActorBox ();
|
var bounding_box = ActorBox ();
|
||||||
|
|
||||||
bounding_box.set_origin (-size, -size);
|
bounding_box.set_origin (-size, -size);
|
||||||
bounding_box.set_size (actor.width + size * 2, actor.height + size * 2);
|
bounding_box.set_size (actor.width + size * 2, actor.height + size * 2);
|
||||||
|
|
||||||
return bounding_box;
|
return bounding_box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,79 +22,79 @@
|
|||||||
|
|
||||||
namespace Gala.Plugins.Template
|
namespace Gala.Plugins.Template
|
||||||
{
|
{
|
||||||
public class Main : Gala.Plugin
|
public class Main : Gala.Plugin
|
||||||
{
|
{
|
||||||
const int PADDING = 50;
|
const int PADDING = 50;
|
||||||
|
|
||||||
Gala.WindowManager? wm = null;
|
Gala.WindowManager? wm = null;
|
||||||
Clutter.Actor red_box;
|
Clutter.Actor red_box;
|
||||||
|
|
||||||
// This function is called as soon as Gala has started and gives you
|
// This function is called as soon as Gala has started and gives you
|
||||||
// an instance of the GalaWindowManager class.
|
// an instance of the GalaWindowManager class.
|
||||||
public override void initialize (Gala.WindowManager wm)
|
public override void initialize (Gala.WindowManager wm)
|
||||||
{
|
{
|
||||||
// we will save the instance to our wm property so we can use it later again
|
// we will save the instance to our wm property so we can use it later again
|
||||||
// especially helpful when you have larger plugins with more functions,
|
// especially helpful when you have larger plugins with more functions,
|
||||||
// we won't need it here
|
// we won't need it here
|
||||||
this.wm = wm;
|
this.wm = wm;
|
||||||
|
|
||||||
// for demonstration purposes we'll add a red quad to the stage which will
|
// for demonstration purposes we'll add a red quad to the stage which will
|
||||||
// turn green when clicked
|
// turn green when clicked
|
||||||
red_box = new Clutter.Actor ();
|
red_box = new Clutter.Actor ();
|
||||||
red_box.set_size (100, 100);
|
red_box.set_size (100, 100);
|
||||||
red_box.background_color = { 255, 0, 0, 255 };
|
red_box.background_color = { 255, 0, 0, 255 };
|
||||||
red_box.reactive = true;
|
red_box.reactive = true;
|
||||||
red_box.button_press_event.connect (turn_green);
|
red_box.button_press_event.connect (turn_green);
|
||||||
|
|
||||||
// we want to place it in the lower right of the primary monitor with a bit
|
// we want to place it in the lower right of the primary monitor with a bit
|
||||||
// of padding. refer to vapi/libmutter.vapi in gala's source for something
|
// of padding. refer to vapi/libmutter.vapi in gala's source for something
|
||||||
// remotely similar to a documentation
|
// remotely similar to a documentation
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var display = wm.get_display ();
|
var display = wm.get_display ();
|
||||||
var rect = display.get_monitor_geometry (display.get_primary_monitor ());
|
var rect = display.get_monitor_geometry (display.get_primary_monitor ());
|
||||||
#else
|
#else
|
||||||
var screen = wm.get_screen ();
|
var screen = wm.get_screen ();
|
||||||
var rect = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
var rect = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
red_box.x = rect.x + rect.width - red_box.width - PADDING;
|
red_box.x = rect.x + rect.width - red_box.width - PADDING;
|
||||||
red_box.y = rect.y + rect.height - red_box.height - PADDING;
|
red_box.y = rect.y + rect.height - red_box.height - PADDING;
|
||||||
|
|
||||||
// to order Gala to deliver mouse events to our box instead of the underlying
|
// to order Gala to deliver mouse events to our box instead of the underlying
|
||||||
// windows, we need to mark the region where the quad is located.
|
// windows, we need to mark the region where the quad is located.
|
||||||
// The plugin class offers an utility function for this purpose, the track_actor
|
// The plugin class offers an utility function for this purpose, the track_actor
|
||||||
// function. It will update the region with the allocation of the actor
|
// function. It will update the region with the allocation of the actor
|
||||||
// whenever its allocation changes. Make sure to set freeze_track to
|
// whenever its allocation changes. Make sure to set freeze_track to
|
||||||
// true while animating the actor to not make gala update the region
|
// true while animating the actor to not make gala update the region
|
||||||
// every single frame.
|
// every single frame.
|
||||||
// You can also handle the region manually by setting the custom_region
|
// You can also handle the region manually by setting the custom_region
|
||||||
// property. The tracked actors and custom regions will be merged by
|
// property. The tracked actors and custom regions will be merged by
|
||||||
// the plugin.
|
// the plugin.
|
||||||
track_actor (red_box);
|
track_actor (red_box);
|
||||||
|
|
||||||
// now we'll add our box into the ui_group. This is where all the shell
|
// now we'll add our box into the ui_group. This is where all the shell
|
||||||
// elements and also the windows and backgrouds are located.
|
// elements and also the windows and backgrouds are located.
|
||||||
wm.ui_group.add_child (red_box);
|
wm.ui_group.add_child (red_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool turn_green (Clutter.ButtonEvent event)
|
bool turn_green (Clutter.ButtonEvent event)
|
||||||
{
|
{
|
||||||
red_box.background_color = { 0, 255, 0, 255 };
|
red_box.background_color = { 0, 255, 0, 255 };
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is actually not even called by Gala at the moment,
|
// This function is actually not even called by Gala at the moment,
|
||||||
// still it might be a good idea to implement it anyway to make sure
|
// still it might be a good idea to implement it anyway to make sure
|
||||||
// your plugin is compatible in case we'd add disabling specific plugins
|
// your plugin is compatible in case we'd add disabling specific plugins
|
||||||
// in the future
|
// in the future
|
||||||
public override void destroy ()
|
public override void destroy ()
|
||||||
{
|
{
|
||||||
// here you would destroy actors you added to the stage or remove
|
// here you would destroy actors you added to the stage or remove
|
||||||
// keybindings
|
// keybindings
|
||||||
|
|
||||||
red_box.destroy ();
|
red_box.destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this little function just tells Gala which class of those you may have in
|
// this little function just tells Gala which class of those you may have in
|
||||||
@ -104,20 +104,20 @@ namespace Gala.Plugins.Template
|
|||||||
// no duplicate functionality.
|
// no duplicate functionality.
|
||||||
public Gala.PluginInfo register_plugin ()
|
public Gala.PluginInfo register_plugin ()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"template-plugin", // the plugin's name
|
"template-plugin", // the plugin's name
|
||||||
"Tom Beckmann <tomjonabc@gmail.com>", // you, the author
|
"Tom Beckmann <tomjonabc@gmail.com>", // you, the author
|
||||||
typeof (Gala.Plugins.Template.Main), // the type of your plugin class
|
typeof (Gala.Plugins.Template.Main), // the type of your plugin class
|
||||||
|
|
||||||
Gala.PluginFunction.ADDITION, // the function which your plugin
|
Gala.PluginFunction.ADDITION, // the function which your plugin
|
||||||
// fulfils, ADDITION means nothing
|
// fulfils, ADDITION means nothing
|
||||||
// specific
|
// specific
|
||||||
|
|
||||||
Gala.LoadPriority.IMMEDIATE // indicates whether your plugin's
|
Gala.LoadPriority.IMMEDIATE // indicates whether your plugin's
|
||||||
// start can be delayed until gala
|
// start can be delayed until gala
|
||||||
// has loaded the important stuff or
|
// has loaded the important stuff or
|
||||||
// if you want your plugin to start
|
// if you want your plugin to start
|
||||||
// right away. False means wait.
|
// right away. False means wait.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,147 +17,147 @@
|
|||||||
|
|
||||||
namespace Gala.Plugins.Zoom
|
namespace Gala.Plugins.Zoom
|
||||||
{
|
{
|
||||||
public class Main : Gala.Plugin
|
public class Main : Gala.Plugin
|
||||||
{
|
{
|
||||||
const uint MOUSE_POLL_TIME = 50;
|
const uint MOUSE_POLL_TIME = 50;
|
||||||
|
|
||||||
Gala.WindowManager? wm = null;
|
Gala.WindowManager? wm = null;
|
||||||
|
|
||||||
uint mouse_poll_timer = 0;
|
uint mouse_poll_timer = 0;
|
||||||
float current_zoom = 1.0f;
|
float current_zoom = 1.0f;
|
||||||
ulong wins_handler_id = 0UL;
|
ulong wins_handler_id = 0UL;
|
||||||
|
|
||||||
public override void initialize (Gala.WindowManager wm)
|
public override void initialize (Gala.WindowManager wm)
|
||||||
{
|
{
|
||||||
this.wm = wm;
|
this.wm = wm;
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var display = wm.get_display ();
|
var display = wm.get_display ();
|
||||||
#else
|
#else
|
||||||
var display = wm.get_screen ().get_display ();
|
var display = wm.get_screen ().get_display ();
|
||||||
#endif
|
#endif
|
||||||
var schema = new GLib.Settings (Config.SCHEMA + ".keybindings");
|
var schema = new GLib.Settings (Config.SCHEMA + ".keybindings");
|
||||||
|
|
||||||
display.add_keybinding ("zoom-in", schema, 0, (Meta.KeyHandlerFunc) zoom_in);
|
display.add_keybinding ("zoom-in", schema, 0, (Meta.KeyHandlerFunc) zoom_in);
|
||||||
display.add_keybinding ("zoom-out", schema, 0, (Meta.KeyHandlerFunc) zoom_out);
|
display.add_keybinding ("zoom-out", schema, 0, (Meta.KeyHandlerFunc) zoom_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void destroy ()
|
public override void destroy ()
|
||||||
{
|
{
|
||||||
if (wm == null)
|
if (wm == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var display = wm.get_display ();
|
var display = wm.get_display ();
|
||||||
#else
|
#else
|
||||||
var display = wm.get_screen ().get_display ();
|
var display = wm.get_screen ().get_display ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
display.remove_keybinding ("zoom-in");
|
display.remove_keybinding ("zoom-in");
|
||||||
display.remove_keybinding ("zoom-out");
|
display.remove_keybinding ("zoom-out");
|
||||||
|
|
||||||
if (mouse_poll_timer > 0)
|
if (mouse_poll_timer > 0)
|
||||||
Source.remove (mouse_poll_timer);
|
Source.remove (mouse_poll_timer);
|
||||||
mouse_poll_timer = 0;
|
mouse_poll_timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (instance_pos = -1)]
|
[CCode (instance_pos = -1)]
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
void zoom_in (Meta.Display display, Meta.Window? window,
|
void zoom_in (Meta.Display display, Meta.Window? window,
|
||||||
Clutter.KeyEvent event, Meta.KeyBinding binding)
|
Clutter.KeyEvent event, Meta.KeyBinding binding)
|
||||||
#else
|
#else
|
||||||
void zoom_in (Meta.Display display, Meta.Screen screen,
|
void zoom_in (Meta.Display display, Meta.Screen screen,
|
||||||
Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding)
|
Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
zoom (true);
|
zoom (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (instance_pos = -1)]
|
[CCode (instance_pos = -1)]
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
void zoom_out (Meta.Display display, Meta.Window? window,
|
void zoom_out (Meta.Display display, Meta.Window? window,
|
||||||
Clutter.KeyEvent event, Meta.KeyBinding binding)
|
Clutter.KeyEvent event, Meta.KeyBinding binding)
|
||||||
#else
|
#else
|
||||||
void zoom_out (Meta.Display display, Meta.Screen screen,
|
void zoom_out (Meta.Display display, Meta.Screen screen,
|
||||||
Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding)
|
Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
zoom (false);
|
zoom (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void zoom (bool @in)
|
void zoom (bool @in)
|
||||||
{
|
{
|
||||||
// Nothing to do if zooming out of our bounds is requested
|
// Nothing to do if zooming out of our bounds is requested
|
||||||
if (current_zoom <= 1.0f && !@in)
|
if (current_zoom <= 1.0f && !@in)
|
||||||
return;
|
return;
|
||||||
else if (current_zoom >= 2.5f && @in)
|
else if (current_zoom >= 2.5f && @in)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var wins = wm.ui_group;
|
var wins = wm.ui_group;
|
||||||
|
|
||||||
// Add timer to poll current mouse position to reposition window-group
|
// Add timer to poll current mouse position to reposition window-group
|
||||||
// to show requested zoomed area
|
// to show requested zoomed area
|
||||||
if (mouse_poll_timer == 0) {
|
if (mouse_poll_timer == 0) {
|
||||||
float mx, my;
|
float mx, my;
|
||||||
var client_pointer = Gdk.Display.get_default ().get_device_manager ().get_client_pointer ();
|
var client_pointer = Gdk.Display.get_default ().get_device_manager ().get_client_pointer ();
|
||||||
client_pointer.get_position (null, out mx, out my);
|
client_pointer.get_position (null, out mx, out my);
|
||||||
wins.set_pivot_point (mx / wins.width, my / wins.height);
|
wins.set_pivot_point (mx / wins.width, my / wins.height);
|
||||||
|
|
||||||
mouse_poll_timer = Timeout.add (MOUSE_POLL_TIME, () => {
|
mouse_poll_timer = Timeout.add (MOUSE_POLL_TIME, () => {
|
||||||
client_pointer.get_position (null, out mx, out my);
|
client_pointer.get_position (null, out mx, out my);
|
||||||
var new_pivot = Clutter.Point.alloc ();
|
var new_pivot = Clutter.Point.alloc ();
|
||||||
new_pivot.init (mx / wins.width, my / wins.height);
|
new_pivot.init (mx / wins.width, my / wins.height);
|
||||||
if (wins.pivot_point.equals (new_pivot))
|
if (wins.pivot_point.equals (new_pivot))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
wins.save_easing_state ();
|
wins.save_easing_state ();
|
||||||
wins.set_easing_mode (Clutter.AnimationMode.LINEAR);
|
wins.set_easing_mode (Clutter.AnimationMode.LINEAR);
|
||||||
wins.set_easing_duration (MOUSE_POLL_TIME);
|
wins.set_easing_duration (MOUSE_POLL_TIME);
|
||||||
wins.pivot_point = new_pivot;
|
wins.pivot_point = new_pivot;
|
||||||
wins.restore_easing_state ();
|
wins.restore_easing_state ();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
current_zoom += (@in ? 0.5f : -0.5f);
|
current_zoom += (@in ? 0.5f : -0.5f);
|
||||||
|
|
||||||
if (current_zoom <= 1.0f) {
|
if (current_zoom <= 1.0f) {
|
||||||
current_zoom = 1.0f;
|
current_zoom = 1.0f;
|
||||||
|
|
||||||
if (mouse_poll_timer > 0)
|
if (mouse_poll_timer > 0)
|
||||||
Source.remove (mouse_poll_timer);
|
Source.remove (mouse_poll_timer);
|
||||||
mouse_poll_timer = 0;
|
mouse_poll_timer = 0;
|
||||||
|
|
||||||
wins.save_easing_state ();
|
wins.save_easing_state ();
|
||||||
wins.set_easing_mode (Clutter.AnimationMode.EASE_OUT_CUBIC);
|
wins.set_easing_mode (Clutter.AnimationMode.EASE_OUT_CUBIC);
|
||||||
wins.set_easing_duration (300);
|
wins.set_easing_duration (300);
|
||||||
wins.set_scale (1.0f, 1.0f);
|
wins.set_scale (1.0f, 1.0f);
|
||||||
wins.restore_easing_state ();
|
wins.restore_easing_state ();
|
||||||
|
|
||||||
wins_handler_id = wins.transitions_completed.connect (() => {
|
wins_handler_id = wins.transitions_completed.connect (() => {
|
||||||
wins.disconnect (wins_handler_id);
|
wins.disconnect (wins_handler_id);
|
||||||
wins.set_pivot_point (0.0f, 0.0f);
|
wins.set_pivot_point (0.0f, 0.0f);
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wins.save_easing_state ();
|
wins.save_easing_state ();
|
||||||
wins.set_easing_mode (Clutter.AnimationMode.EASE_OUT_CUBIC);
|
wins.set_easing_mode (Clutter.AnimationMode.EASE_OUT_CUBIC);
|
||||||
wins.set_easing_duration (300);
|
wins.set_easing_duration (300);
|
||||||
wins.set_scale (current_zoom, current_zoom);
|
wins.set_scale (current_zoom, current_zoom);
|
||||||
wins.restore_easing_state ();
|
wins.restore_easing_state ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gala.PluginInfo register_plugin ()
|
public Gala.PluginInfo register_plugin ()
|
||||||
{
|
{
|
||||||
return Gala.PluginInfo () {
|
return Gala.PluginInfo () {
|
||||||
name = "Zoom",
|
name = "Zoom",
|
||||||
author = "Gala Developers",
|
author = "Gala Developers",
|
||||||
plugin_type = typeof (Gala.Plugins.Zoom.Main),
|
plugin_type = typeof (Gala.Plugins.Zoom.Main),
|
||||||
provides = Gala.PluginFunction.ADDITION,
|
provides = Gala.PluginFunction.ADDITION,
|
||||||
load_priority = Gala.LoadPriority.IMMEDIATE
|
load_priority = Gala.LoadPriority.IMMEDIATE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,60 +17,60 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class Animation : Object
|
public class Animation : Object
|
||||||
{
|
{
|
||||||
public string filename { get; construct; }
|
public string filename { get; construct; }
|
||||||
public string[] key_frame_files { get; private set; default = {}; }
|
public string[] key_frame_files { get; private set; default = {}; }
|
||||||
public double transition_progress { get; private set; default = 0.0; }
|
public double transition_progress { get; private set; default = 0.0; }
|
||||||
public double transition_duration { get; private set; default = 0.0; }
|
public double transition_duration { get; private set; default = 0.0; }
|
||||||
public bool loaded { get; private set; default = false; }
|
public bool loaded { get; private set; default = false; }
|
||||||
|
|
||||||
Gnome.BGSlideShow? show = null;
|
Gnome.BGSlideShow? show = null;
|
||||||
|
|
||||||
public Animation (string filename)
|
public Animation (string filename)
|
||||||
{
|
{
|
||||||
Object (filename: filename);
|
Object (filename: filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void load ()
|
public async void load ()
|
||||||
{
|
{
|
||||||
show = new Gnome.BGSlideShow (filename);
|
show = new Gnome.BGSlideShow (filename);
|
||||||
|
|
||||||
show.load_async (null, (obj, res) => {
|
show.load_async (null, (obj, res) => {
|
||||||
loaded = true;
|
loaded = true;
|
||||||
|
|
||||||
load.callback ();
|
load.callback ();
|
||||||
});
|
});
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update (Meta.Rectangle monitor)
|
public void update (Meta.Rectangle monitor)
|
||||||
{
|
{
|
||||||
string[] key_frame_files = {};
|
string[] key_frame_files = {};
|
||||||
|
|
||||||
if (show == null)
|
if (show == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (show.get_num_slides () < 1)
|
if (show.get_num_slides () < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double progress, duration;
|
double progress, duration;
|
||||||
bool is_fixed;
|
bool is_fixed;
|
||||||
string file1, file2;
|
string file1, file2;
|
||||||
show.get_current_slide (monitor.width, monitor.height, out progress, out duration, out is_fixed, out file1, out file2);
|
show.get_current_slide (monitor.width, monitor.height, out progress, out duration, out is_fixed, out file1, out file2);
|
||||||
|
|
||||||
transition_duration = duration;
|
transition_duration = duration;
|
||||||
transition_progress = progress;
|
transition_progress = progress;
|
||||||
|
|
||||||
if (file1 != null)
|
if (file1 != null)
|
||||||
key_frame_files += file1;
|
key_frame_files += file1;
|
||||||
|
|
||||||
if (file2 != null)
|
if (file2 != null)
|
||||||
key_frame_files += file2;
|
key_frame_files += file2;
|
||||||
|
|
||||||
this.key_frame_files = key_frame_files;
|
this.key_frame_files = key_frame_files;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,274 +17,274 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class Background : Object
|
public class Background : Object
|
||||||
{
|
{
|
||||||
const double ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
|
const double ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
|
||||||
const double ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
|
const double ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
|
||||||
|
|
||||||
public signal void changed ();
|
public signal void changed ();
|
||||||
public signal void loaded ();
|
public signal void loaded ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
#else
|
#else
|
||||||
public Meta.Screen screen { get; construct; }
|
public Meta.Screen screen { get; construct; }
|
||||||
#endif
|
#endif
|
||||||
public int monitor_index { get; construct; }
|
public int monitor_index { get; construct; }
|
||||||
public BackgroundSource background_source { get; construct; }
|
public BackgroundSource background_source { get; construct; }
|
||||||
public bool is_loaded { get; private set; default = false; }
|
public bool is_loaded { get; private set; default = false; }
|
||||||
public GDesktop.BackgroundStyle style { get; construct; }
|
public GDesktop.BackgroundStyle style { get; construct; }
|
||||||
public string? filename { get; construct; }
|
public string? filename { get; construct; }
|
||||||
public Meta.Background background { get; private set; }
|
public Meta.Background background { get; private set; }
|
||||||
|
|
||||||
Animation? animation = null;
|
Animation? animation = null;
|
||||||
Gee.HashMap<string,ulong> file_watches;
|
Gee.HashMap<string,ulong> file_watches;
|
||||||
Cancellable cancellable;
|
Cancellable cancellable;
|
||||||
uint update_animation_timeout_id = 0;
|
uint update_animation_timeout_id = 0;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Background (Meta.Display display, int monitor_index, string? filename,
|
public Background (Meta.Display display, int monitor_index, string? filename,
|
||||||
BackgroundSource background_source, GDesktop.BackgroundStyle style)
|
BackgroundSource background_source, GDesktop.BackgroundStyle style)
|
||||||
{
|
{
|
||||||
Object (display: display,
|
Object (display: display,
|
||||||
monitor_index: monitor_index,
|
monitor_index: monitor_index,
|
||||||
background_source: background_source,
|
background_source: background_source,
|
||||||
style: style,
|
style: style,
|
||||||
filename: filename);
|
filename: filename);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public Background (Meta.Screen screen, int monitor_index, string? filename,
|
public Background (Meta.Screen screen, int monitor_index, string? filename,
|
||||||
BackgroundSource background_source, GDesktop.BackgroundStyle style)
|
BackgroundSource background_source, GDesktop.BackgroundStyle style)
|
||||||
{
|
{
|
||||||
Object (screen: screen,
|
Object (screen: screen,
|
||||||
monitor_index: monitor_index,
|
monitor_index: monitor_index,
|
||||||
background_source: background_source,
|
background_source: background_source,
|
||||||
style: style,
|
style: style,
|
||||||
filename: filename);
|
filename: filename);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
background = new Meta.Background (display);
|
background = new Meta.Background (display);
|
||||||
#else
|
#else
|
||||||
background = new Meta.Background (screen);
|
background = new Meta.Background (screen);
|
||||||
#endif
|
#endif
|
||||||
background.set_data<unowned Background> ("delegate", this);
|
background.set_data<unowned Background> ("delegate", this);
|
||||||
|
|
||||||
file_watches = new Gee.HashMap<string,ulong> ();
|
file_watches = new Gee.HashMap<string,ulong> ();
|
||||||
cancellable = new Cancellable ();
|
cancellable = new Cancellable ();
|
||||||
|
|
||||||
background_source.changed.connect (settings_changed);
|
background_source.changed.connect (settings_changed);
|
||||||
|
|
||||||
load ();
|
load ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy ()
|
public void destroy ()
|
||||||
{
|
{
|
||||||
cancellable.cancel ();
|
cancellable.cancel ();
|
||||||
remove_animation_timeout ();
|
remove_animation_timeout ();
|
||||||
|
|
||||||
var cache = BackgroundCache.get_default ();
|
var cache = BackgroundCache.get_default ();
|
||||||
|
|
||||||
foreach (var watch in file_watches.values) {
|
foreach (var watch in file_watches.values) {
|
||||||
SignalHandler.disconnect (cache, watch);
|
SignalHandler.disconnect (cache, watch);
|
||||||
}
|
}
|
||||||
|
|
||||||
background_source.changed.disconnect (settings_changed);
|
background_source.changed.disconnect (settings_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update_resolution ()
|
public void update_resolution ()
|
||||||
{
|
{
|
||||||
if (animation != null) {
|
if (animation != null) {
|
||||||
remove_animation_timeout ();
|
remove_animation_timeout ();
|
||||||
update_animation ();
|
update_animation ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_loaded ()
|
void set_loaded ()
|
||||||
{
|
{
|
||||||
if (is_loaded)
|
if (is_loaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
|
|
||||||
Idle.add (() => {
|
Idle.add (() => {
|
||||||
loaded ();
|
loaded ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_pattern ()
|
void load_pattern ()
|
||||||
{
|
{
|
||||||
string color_string;
|
string color_string;
|
||||||
var settings = background_source.settings;
|
var settings = background_source.settings;
|
||||||
|
|
||||||
color_string = settings.get_string ("primary-color");
|
color_string = settings.get_string ("primary-color");
|
||||||
var color = Clutter.Color.from_string (color_string);
|
var color = Clutter.Color.from_string (color_string);
|
||||||
|
|
||||||
color_string = settings.get_string("secondary-color");
|
color_string = settings.get_string("secondary-color");
|
||||||
var second_color = Clutter.Color.from_string (color_string);
|
var second_color = Clutter.Color.from_string (color_string);
|
||||||
|
|
||||||
var shading_type = settings.get_enum ("color-shading-type");
|
var shading_type = settings.get_enum ("color-shading-type");
|
||||||
|
|
||||||
if (shading_type == GDesktop.BackgroundShading.SOLID)
|
if (shading_type == GDesktop.BackgroundShading.SOLID)
|
||||||
background.set_color (color);
|
background.set_color (color);
|
||||||
else
|
else
|
||||||
background.set_gradient ((GDesktop.BackgroundShading) shading_type, color, second_color);
|
background.set_gradient ((GDesktop.BackgroundShading) shading_type, color, second_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_file (string filename)
|
void watch_file (string filename)
|
||||||
{
|
{
|
||||||
if (file_watches.has_key (filename))
|
if (file_watches.has_key (filename))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var cache = BackgroundCache.get_default ();
|
var cache = BackgroundCache.get_default ();
|
||||||
|
|
||||||
cache.monitor_file (filename);
|
cache.monitor_file (filename);
|
||||||
|
|
||||||
file_watches[filename] = cache.file_changed.connect ((changed_file) => {
|
file_watches[filename] = cache.file_changed.connect ((changed_file) => {
|
||||||
if (changed_file == filename) {
|
if (changed_file == filename) {
|
||||||
var image_cache = Meta.BackgroundImageCache.get_default ();
|
var image_cache = Meta.BackgroundImageCache.get_default ();
|
||||||
image_cache.purge (File.new_for_path (changed_file));
|
image_cache.purge (File.new_for_path (changed_file));
|
||||||
changed ();
|
changed ();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_animation_timeout ()
|
void remove_animation_timeout ()
|
||||||
{
|
{
|
||||||
if (update_animation_timeout_id != 0) {
|
if (update_animation_timeout_id != 0) {
|
||||||
Source.remove (update_animation_timeout_id);
|
Source.remove (update_animation_timeout_id);
|
||||||
update_animation_timeout_id = 0;
|
update_animation_timeout_id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_animation ()
|
void update_animation ()
|
||||||
{
|
{
|
||||||
update_animation_timeout_id = 0;
|
update_animation_timeout_id = 0;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
animation.update (display.get_monitor_geometry (monitor_index));
|
animation.update (display.get_monitor_geometry (monitor_index));
|
||||||
#else
|
#else
|
||||||
animation.update (screen.get_monitor_geometry (monitor_index));
|
animation.update (screen.get_monitor_geometry (monitor_index));
|
||||||
#endif
|
#endif
|
||||||
var files = animation.key_frame_files;
|
var files = animation.key_frame_files;
|
||||||
|
|
||||||
Clutter.Callback finish = () => {
|
Clutter.Callback finish = () => {
|
||||||
set_loaded ();
|
set_loaded ();
|
||||||
|
|
||||||
if (files.length > 1)
|
if (files.length > 1)
|
||||||
background.set_blend (File.new_for_path (files[0]), File.new_for_path (files[1]), animation.transition_progress, style);
|
background.set_blend (File.new_for_path (files[0]), File.new_for_path (files[1]), animation.transition_progress, style);
|
||||||
else if (files.length > 0)
|
else if (files.length > 0)
|
||||||
background.set_file (File.new_for_path (files[0]), style);
|
background.set_file (File.new_for_path (files[0]), style);
|
||||||
else
|
else
|
||||||
background.set_file (null, style);
|
background.set_file (null, style);
|
||||||
|
|
||||||
queue_update_animation ();
|
queue_update_animation ();
|
||||||
};
|
};
|
||||||
|
|
||||||
var cache = Meta.BackgroundImageCache.get_default ();
|
var cache = Meta.BackgroundImageCache.get_default ();
|
||||||
var num_pending_images = files.length;
|
var num_pending_images = files.length;
|
||||||
for (var i = 0; i < files.length; i++) {
|
for (var i = 0; i < files.length; i++) {
|
||||||
watch_file (files[i]);
|
watch_file (files[i]);
|
||||||
|
|
||||||
var image = cache.load (File.new_for_path (files[i]));
|
var image = cache.load (File.new_for_path (files[i]));
|
||||||
|
|
||||||
if (image.is_loaded ()) {
|
if (image.is_loaded ()) {
|
||||||
num_pending_images--;
|
num_pending_images--;
|
||||||
if (num_pending_images == 0)
|
if (num_pending_images == 0)
|
||||||
finish (null);
|
finish (null);
|
||||||
} else {
|
} else {
|
||||||
ulong handler = 0;
|
ulong handler = 0;
|
||||||
handler = image.loaded.connect (() => {
|
handler = image.loaded.connect (() => {
|
||||||
SignalHandler.disconnect (image, handler);
|
SignalHandler.disconnect (image, handler);
|
||||||
if (--num_pending_images == 0)
|
if (--num_pending_images == 0)
|
||||||
finish (null);
|
finish (null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void queue_update_animation () {
|
void queue_update_animation () {
|
||||||
if (update_animation_timeout_id != 0)
|
if (update_animation_timeout_id != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cancellable == null || cancellable.is_cancelled ())
|
if (cancellable == null || cancellable.is_cancelled ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (animation.transition_duration == 0)
|
if (animation.transition_duration == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var n_steps = 255.0 / ANIMATION_OPACITY_STEP_INCREMENT;
|
var n_steps = 255.0 / ANIMATION_OPACITY_STEP_INCREMENT;
|
||||||
var time_per_step = (animation.transition_duration * 1000) / n_steps;
|
var time_per_step = (animation.transition_duration * 1000) / n_steps;
|
||||||
|
|
||||||
var interval = (uint32) Math.fmax (ANIMATION_MIN_WAKEUP_INTERVAL * 1000, time_per_step);
|
var interval = (uint32) Math.fmax (ANIMATION_MIN_WAKEUP_INTERVAL * 1000, time_per_step);
|
||||||
|
|
||||||
if (interval > uint32.MAX)
|
if (interval > uint32.MAX)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
update_animation_timeout_id = Timeout.add (interval, () => {
|
update_animation_timeout_id = Timeout.add (interval, () => {
|
||||||
update_animation_timeout_id = 0;
|
update_animation_timeout_id = 0;
|
||||||
update_animation ();
|
update_animation ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async void load_animation (string filename)
|
async void load_animation (string filename)
|
||||||
{
|
{
|
||||||
animation = yield BackgroundCache.get_default ().get_animation (filename);
|
animation = yield BackgroundCache.get_default ().get_animation (filename);
|
||||||
|
|
||||||
if (animation == null || cancellable.is_cancelled ()) {
|
if (animation == null || cancellable.is_cancelled ()) {
|
||||||
set_loaded();
|
set_loaded();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_animation ();
|
update_animation ();
|
||||||
watch_file (filename);
|
watch_file (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_image (string filename)
|
void load_image (string filename)
|
||||||
{
|
{
|
||||||
background.set_file (File.new_for_path (filename), style);
|
background.set_file (File.new_for_path (filename), style);
|
||||||
watch_file (filename);
|
watch_file (filename);
|
||||||
|
|
||||||
var cache = Meta.BackgroundImageCache.get_default ();
|
var cache = Meta.BackgroundImageCache.get_default ();
|
||||||
var image = cache.load (File.new_for_path (filename));
|
var image = cache.load (File.new_for_path (filename));
|
||||||
if (image.is_loaded ())
|
if (image.is_loaded ())
|
||||||
set_loaded();
|
set_loaded();
|
||||||
else {
|
else {
|
||||||
ulong handler = 0;
|
ulong handler = 0;
|
||||||
handler = image.loaded.connect (() => {
|
handler = image.loaded.connect (() => {
|
||||||
set_loaded ();
|
set_loaded ();
|
||||||
SignalHandler.disconnect (image, handler);
|
SignalHandler.disconnect (image, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_file (string filename)
|
void load_file (string filename)
|
||||||
{
|
{
|
||||||
if (filename.has_suffix (".xml"))
|
if (filename.has_suffix (".xml"))
|
||||||
load_animation.begin (filename);
|
load_animation.begin (filename);
|
||||||
else
|
else
|
||||||
load_image (filename);
|
load_image (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load ()
|
void load ()
|
||||||
{
|
{
|
||||||
load_pattern ();
|
load_pattern ();
|
||||||
|
|
||||||
if (filename == null)
|
if (filename == null)
|
||||||
set_loaded ();
|
set_loaded ();
|
||||||
else
|
else
|
||||||
load_file (filename);
|
load_file (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void settings_changed ()
|
void settings_changed ()
|
||||||
{
|
{
|
||||||
changed ();
|
changed ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,110 +17,110 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class BackgroundCache : Object
|
public class BackgroundCache : Object
|
||||||
{
|
{
|
||||||
static BackgroundCache? instance = null;
|
static BackgroundCache? instance = null;
|
||||||
|
|
||||||
public static unowned BackgroundCache get_default ()
|
public static unowned BackgroundCache get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new BackgroundCache ();
|
instance = new BackgroundCache ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public signal void file_changed (string filename);
|
public signal void file_changed (string filename);
|
||||||
|
|
||||||
Gee.HashMap<string,FileMonitor> file_monitors;
|
Gee.HashMap<string,FileMonitor> file_monitors;
|
||||||
Gee.HashMap<string,BackgroundSource> background_sources;
|
Gee.HashMap<string,BackgroundSource> background_sources;
|
||||||
|
|
||||||
Animation animation;
|
Animation animation;
|
||||||
string animation_filename;
|
string animation_filename;
|
||||||
|
|
||||||
public BackgroundCache ()
|
public BackgroundCache ()
|
||||||
{
|
{
|
||||||
Object ();
|
Object ();
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
file_monitors = new Gee.HashMap<string,FileMonitor> ();
|
file_monitors = new Gee.HashMap<string,FileMonitor> ();
|
||||||
background_sources = new Gee.HashMap<string,BackgroundSource> ();
|
background_sources = new Gee.HashMap<string,BackgroundSource> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void monitor_file (string filename)
|
public void monitor_file (string filename)
|
||||||
{
|
{
|
||||||
if (file_monitors.has_key (filename))
|
if (file_monitors.has_key (filename))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var file = File.new_for_path (filename);
|
var file = File.new_for_path (filename);
|
||||||
try {
|
try {
|
||||||
var monitor = file.monitor (FileMonitorFlags.NONE, null);
|
var monitor = file.monitor (FileMonitorFlags.NONE, null);
|
||||||
monitor.changed.connect(() => {
|
monitor.changed.connect(() => {
|
||||||
file_changed (filename);
|
file_changed (filename);
|
||||||
});
|
});
|
||||||
|
|
||||||
file_monitors[filename] = monitor;
|
file_monitors[filename] = monitor;
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
warning ("Failed to monitor %s: %s", filename, e.message);
|
warning ("Failed to monitor %s: %s", filename, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Animation get_animation (string filename)
|
public async Animation get_animation (string filename)
|
||||||
{
|
{
|
||||||
if (animation_filename == filename) {
|
if (animation_filename == filename) {
|
||||||
Idle.add (() => {
|
Idle.add (() => {
|
||||||
get_animation.callback ();
|
get_animation.callback ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
return animation;
|
return animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
var animation = new Animation (filename);
|
var animation = new Animation (filename);
|
||||||
|
|
||||||
yield animation.load ();
|
yield animation.load ();
|
||||||
|
|
||||||
Idle.add (() => {
|
Idle.add (() => {
|
||||||
get_animation.callback ();
|
get_animation.callback ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
return animation;
|
return animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public BackgroundSource get_background_source (Meta.Display display, string settings_schema)
|
public BackgroundSource get_background_source (Meta.Display display, string settings_schema)
|
||||||
#else
|
#else
|
||||||
public BackgroundSource get_background_source (Meta.Screen screen, string settings_schema)
|
public BackgroundSource get_background_source (Meta.Screen screen, string settings_schema)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
var background_source = background_sources[settings_schema];
|
var background_source = background_sources[settings_schema];
|
||||||
if (background_source == null) {
|
if (background_source == null) {
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
background_source = new BackgroundSource (display, settings_schema);
|
background_source = new BackgroundSource (display, settings_schema);
|
||||||
#else
|
#else
|
||||||
background_source = new BackgroundSource (screen, settings_schema);
|
background_source = new BackgroundSource (screen, settings_schema);
|
||||||
#endif
|
#endif
|
||||||
background_source.use_count = 1;
|
background_source.use_count = 1;
|
||||||
background_sources[settings_schema] = background_source;
|
background_sources[settings_schema] = background_source;
|
||||||
} else
|
} else
|
||||||
background_source.use_count++;
|
background_source.use_count++;
|
||||||
|
|
||||||
return background_source;
|
return background_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release_background_source (string settings_schema)
|
public void release_background_source (string settings_schema)
|
||||||
{
|
{
|
||||||
if (background_sources.has_key (settings_schema)) {
|
if (background_sources.has_key (settings_schema)) {
|
||||||
var source = background_sources[settings_schema];
|
var source = background_sources[settings_schema];
|
||||||
if (--source.use_count == 0) {
|
if (--source.use_count == 0) {
|
||||||
background_sources.unset (settings_schema);
|
background_sources.unset (settings_schema);
|
||||||
source.destroy ();
|
source.destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,78 +17,78 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class BackgroundContainer : Meta.BackgroundGroup
|
public class BackgroundContainer : Meta.BackgroundGroup
|
||||||
{
|
{
|
||||||
public signal void changed ();
|
public signal void changed ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
|
|
||||||
public BackgroundContainer (Meta.Display display)
|
public BackgroundContainer (Meta.Display display)
|
||||||
{
|
{
|
||||||
Object (display: display);
|
Object (display: display);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
Meta.MonitorManager.@get ().monitors_changed.connect (update);
|
Meta.MonitorManager.@get ().monitors_changed.connect (update);
|
||||||
|
|
||||||
update ();
|
update ();
|
||||||
}
|
}
|
||||||
|
|
||||||
~BackgroundContainer ()
|
~BackgroundContainer ()
|
||||||
{
|
{
|
||||||
Meta.MonitorManager.@get ().monitors_changed.disconnect (update);
|
Meta.MonitorManager.@get ().monitors_changed.disconnect (update);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public Meta.Screen screen { get; construct; }
|
public Meta.Screen screen { get; construct; }
|
||||||
|
|
||||||
public BackgroundContainer (Meta.Screen screen)
|
public BackgroundContainer (Meta.Screen screen)
|
||||||
{
|
{
|
||||||
Object (screen: screen);
|
Object (screen: screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
screen.monitors_changed.connect (update);
|
screen.monitors_changed.connect (update);
|
||||||
|
|
||||||
update ();
|
update ();
|
||||||
}
|
}
|
||||||
|
|
||||||
~BackgroundContainer ()
|
~BackgroundContainer ()
|
||||||
{
|
{
|
||||||
screen.monitors_changed.disconnect (update);
|
screen.monitors_changed.disconnect (update);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void update ()
|
void update ()
|
||||||
{
|
{
|
||||||
var reference_child = (get_child_at_index (0) as BackgroundManager);
|
var reference_child = (get_child_at_index (0) as BackgroundManager);
|
||||||
if (reference_child != null)
|
if (reference_child != null)
|
||||||
reference_child.changed.disconnect (background_changed);
|
reference_child.changed.disconnect (background_changed);
|
||||||
|
|
||||||
destroy_all_children ();
|
destroy_all_children ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
for (var i = 0; i < display.get_n_monitors (); i++) {
|
for (var i = 0; i < display.get_n_monitors (); i++) {
|
||||||
var background = new BackgroundManager (display, i);
|
var background = new BackgroundManager (display, i);
|
||||||
#else
|
#else
|
||||||
for (var i = 0; i < screen.get_n_monitors (); i++) {
|
for (var i = 0; i < screen.get_n_monitors (); i++) {
|
||||||
var background = new BackgroundManager (screen, i);
|
var background = new BackgroundManager (screen, i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_child (background);
|
add_child (background);
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
background.changed.connect (background_changed);
|
background.changed.connect (background_changed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void background_changed ()
|
void background_changed ()
|
||||||
{
|
{
|
||||||
changed ();
|
changed ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,173 +17,173 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class BackgroundManager : Meta.BackgroundGroup
|
public class BackgroundManager : Meta.BackgroundGroup
|
||||||
{
|
{
|
||||||
const string BACKGROUND_SCHEMA = "org.gnome.desktop.background";
|
const string BACKGROUND_SCHEMA = "org.gnome.desktop.background";
|
||||||
const int FADE_ANIMATION_TIME = 1000;
|
const int FADE_ANIMATION_TIME = 1000;
|
||||||
|
|
||||||
public signal void changed ();
|
public signal void changed ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
#else
|
#else
|
||||||
public Meta.Screen screen { get; construct; }
|
public Meta.Screen screen { get; construct; }
|
||||||
#endif
|
#endif
|
||||||
public int monitor_index { get; construct; }
|
public int monitor_index { get; construct; }
|
||||||
public bool control_position { get; construct; }
|
public bool control_position { get; construct; }
|
||||||
|
|
||||||
BackgroundSource background_source;
|
BackgroundSource background_source;
|
||||||
Meta.BackgroundActor background_actor;
|
Meta.BackgroundActor background_actor;
|
||||||
Meta.BackgroundActor? new_background_actor = null;
|
Meta.BackgroundActor? new_background_actor = null;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public BackgroundManager (Meta.Display display, int monitor_index, bool control_position = true)
|
public BackgroundManager (Meta.Display display, int monitor_index, bool control_position = true)
|
||||||
{
|
{
|
||||||
Object (display: display, monitor_index: monitor_index, control_position: control_position);
|
Object (display: display, monitor_index: monitor_index, control_position: control_position);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public BackgroundManager (Meta.Screen screen, int monitor_index, bool control_position = true)
|
public BackgroundManager (Meta.Screen screen, int monitor_index, bool control_position = true)
|
||||||
{
|
{
|
||||||
Object (screen: screen, monitor_index: monitor_index, control_position: control_position);
|
Object (screen: screen, monitor_index: monitor_index, control_position: control_position);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
background_source = BackgroundCache.get_default ().get_background_source (display, BACKGROUND_SCHEMA);
|
background_source = BackgroundCache.get_default ().get_background_source (display, BACKGROUND_SCHEMA);
|
||||||
#else
|
#else
|
||||||
background_source = BackgroundCache.get_default ().get_background_source (screen, BACKGROUND_SCHEMA);
|
background_source = BackgroundCache.get_default ().get_background_source (screen, BACKGROUND_SCHEMA);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
background_actor = create_background_actor ();
|
background_actor = create_background_actor ();
|
||||||
|
|
||||||
destroy.connect (on_destroy);
|
destroy.connect (on_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_destroy ()
|
void on_destroy ()
|
||||||
{
|
{
|
||||||
BackgroundCache.get_default ().release_background_source (BACKGROUND_SCHEMA);
|
BackgroundCache.get_default ().release_background_source (BACKGROUND_SCHEMA);
|
||||||
background_source = null;
|
background_source = null;
|
||||||
|
|
||||||
if (new_background_actor != null) {
|
if (new_background_actor != null) {
|
||||||
new_background_actor.destroy ();
|
new_background_actor.destroy ();
|
||||||
new_background_actor = null;
|
new_background_actor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (background_actor != null) {
|
if (background_actor != null) {
|
||||||
background_actor.destroy ();
|
background_actor.destroy ();
|
||||||
background_actor = null;
|
background_actor = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap_background_actor ()
|
void swap_background_actor ()
|
||||||
{
|
{
|
||||||
return_if_fail (new_background_actor != null);
|
return_if_fail (new_background_actor != null);
|
||||||
|
|
||||||
var old_background_actor = background_actor;
|
var old_background_actor = background_actor;
|
||||||
background_actor = new_background_actor;
|
background_actor = new_background_actor;
|
||||||
new_background_actor = null;
|
new_background_actor = null;
|
||||||
|
|
||||||
if (old_background_actor == null)
|
if (old_background_actor == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var transition = new Clutter.PropertyTransition ("opacity");
|
var transition = new Clutter.PropertyTransition ("opacity");
|
||||||
transition.set_from_value (255);
|
transition.set_from_value (255);
|
||||||
transition.set_to_value (0);
|
transition.set_to_value (0);
|
||||||
transition.duration = FADE_ANIMATION_TIME;
|
transition.duration = FADE_ANIMATION_TIME;
|
||||||
transition.progress_mode = Clutter.AnimationMode.EASE_OUT_QUAD;
|
transition.progress_mode = Clutter.AnimationMode.EASE_OUT_QUAD;
|
||||||
transition.remove_on_complete = true;
|
transition.remove_on_complete = true;
|
||||||
transition.completed.connect (() => {
|
transition.completed.connect (() => {
|
||||||
old_background_actor.destroy ();
|
old_background_actor.destroy ();
|
||||||
|
|
||||||
changed ();
|
changed ();
|
||||||
});
|
});
|
||||||
|
|
||||||
old_background_actor.add_transition ("fade-out", transition);
|
old_background_actor.add_transition ("fade-out", transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_background_actor ()
|
void update_background_actor ()
|
||||||
{
|
{
|
||||||
if (new_background_actor != null) {
|
if (new_background_actor != null) {
|
||||||
// Skip displaying existing background queued for load
|
// Skip displaying existing background queued for load
|
||||||
new_background_actor.destroy ();
|
new_background_actor.destroy ();
|
||||||
new_background_actor = null;
|
new_background_actor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_background_actor = create_background_actor ();
|
new_background_actor = create_background_actor ();
|
||||||
new_background_actor.vignette_sharpness = background_actor.vignette_sharpness;
|
new_background_actor.vignette_sharpness = background_actor.vignette_sharpness;
|
||||||
new_background_actor.brightness = background_actor.brightness;
|
new_background_actor.brightness = background_actor.brightness;
|
||||||
new_background_actor.visible = background_actor.visible;
|
new_background_actor.visible = background_actor.visible;
|
||||||
|
|
||||||
var background = new_background_actor.background.get_data<unowned Background> ("delegate");
|
var background = new_background_actor.background.get_data<unowned Background> ("delegate");
|
||||||
|
|
||||||
if (background.is_loaded) {
|
if (background.is_loaded) {
|
||||||
swap_background_actor ();
|
swap_background_actor ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong handler = 0;
|
ulong handler = 0;
|
||||||
handler = background.loaded.connect (() => {
|
handler = background.loaded.connect (() => {
|
||||||
SignalHandler.disconnect (background, handler);
|
SignalHandler.disconnect (background, handler);
|
||||||
background.set_data<ulong> ("background-loaded-handler", 0);
|
background.set_data<ulong> ("background-loaded-handler", 0);
|
||||||
|
|
||||||
swap_background_actor ();
|
swap_background_actor ();
|
||||||
});
|
});
|
||||||
background.set_data<ulong> ("background-loaded-handler", handler);
|
background.set_data<ulong> ("background-loaded-handler", handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_size (float width, float height) {
|
public void set_size (float width, float height) {
|
||||||
background_actor.set_size (width, height);
|
background_actor.set_size (width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Meta.BackgroundActor create_background_actor ()
|
Meta.BackgroundActor create_background_actor ()
|
||||||
{
|
{
|
||||||
var background = background_source.get_background (monitor_index);
|
var background = background_source.get_background (monitor_index);
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var background_actor = new Meta.BackgroundActor (display, monitor_index);
|
var background_actor = new Meta.BackgroundActor (display, monitor_index);
|
||||||
#else
|
#else
|
||||||
var background_actor = new Meta.BackgroundActor (screen, monitor_index);
|
var background_actor = new Meta.BackgroundActor (screen, monitor_index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
background_actor.background = background.background;
|
background_actor.background = background.background;
|
||||||
|
|
||||||
insert_child_below (background_actor, null);
|
insert_child_below (background_actor, null);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var monitor = display.get_monitor_geometry (monitor_index);
|
var monitor = display.get_monitor_geometry (monitor_index);
|
||||||
#else
|
#else
|
||||||
var monitor = screen.get_monitor_geometry (monitor_index);
|
var monitor = screen.get_monitor_geometry (monitor_index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
background_actor.set_size (monitor.width, monitor.height);
|
background_actor.set_size (monitor.width, monitor.height);
|
||||||
|
|
||||||
if (control_position) {
|
if (control_position) {
|
||||||
background_actor.set_position (monitor.x, monitor.y);
|
background_actor.set_position (monitor.x, monitor.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong changed_handler = 0;
|
ulong changed_handler = 0;
|
||||||
changed_handler = background.changed.connect (() => {
|
changed_handler = background.changed.connect (() => {
|
||||||
SignalHandler.disconnect (background, changed_handler);
|
SignalHandler.disconnect (background, changed_handler);
|
||||||
changed_handler = 0;
|
changed_handler = 0;
|
||||||
update_background_actor ();
|
update_background_actor ();
|
||||||
});
|
});
|
||||||
|
|
||||||
background_actor.destroy.connect (() => {
|
background_actor.destroy.connect (() => {
|
||||||
if (changed_handler != 0) {
|
if (changed_handler != 0) {
|
||||||
SignalHandler.disconnect (background, changed_handler);
|
SignalHandler.disconnect (background, changed_handler);
|
||||||
changed_handler = 0;
|
changed_handler = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var loaded_handler = background.get_data<ulong> ("background-loaded-handler");
|
var loaded_handler = background.get_data<ulong> ("background-loaded-handler");
|
||||||
if (loaded_handler != 0) {
|
if (loaded_handler != 0) {
|
||||||
SignalHandler.disconnect (background, loaded_handler);
|
SignalHandler.disconnect (background, loaded_handler);
|
||||||
background.set_data<ulong> ("background-loaded-handler", 0);
|
background.set_data<ulong> ("background-loaded-handler", 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return background_actor;
|
return background_actor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,171 +17,171 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class BackgroundSource : Object
|
public class BackgroundSource : Object
|
||||||
{
|
{
|
||||||
public signal void changed ();
|
public signal void changed ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
#else
|
#else
|
||||||
public Meta.Screen screen { get; construct; }
|
public Meta.Screen screen { get; construct; }
|
||||||
#endif
|
#endif
|
||||||
public Settings settings { get; construct; }
|
public Settings settings { get; construct; }
|
||||||
|
|
||||||
internal int use_count { get; set; default = 0; }
|
internal int use_count { get; set; default = 0; }
|
||||||
|
|
||||||
Gee.HashMap<int,Background> backgrounds;
|
Gee.HashMap<int,Background> backgrounds;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public BackgroundSource (Meta.Display display, string settings_schema)
|
public BackgroundSource (Meta.Display display, string settings_schema)
|
||||||
{
|
{
|
||||||
Object (display: display, settings: new Settings (settings_schema));
|
Object (display: display, settings: new Settings (settings_schema));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public BackgroundSource (Meta.Screen screen, string settings_schema)
|
public BackgroundSource (Meta.Screen screen, string settings_schema)
|
||||||
{
|
{
|
||||||
Object (screen: screen, settings: new Settings (settings_schema));
|
Object (screen: screen, settings: new Settings (settings_schema));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
backgrounds = new Gee.HashMap<int,Background> ();
|
backgrounds = new Gee.HashMap<int,Background> ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
Meta.MonitorManager.@get ().monitors_changed.connect (monitors_changed);
|
Meta.MonitorManager.@get ().monitors_changed.connect (monitors_changed);
|
||||||
#else
|
#else
|
||||||
screen.monitors_changed.connect (monitors_changed);
|
screen.monitors_changed.connect (monitors_changed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
settings_hash_cache = get_current_settings_hash_cache ();
|
settings_hash_cache = get_current_settings_hash_cache ();
|
||||||
settings.changed.connect (settings_changed);
|
settings.changed.connect (settings_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void monitors_changed ()
|
void monitors_changed ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var n = display.get_n_monitors ();
|
var n = display.get_n_monitors ();
|
||||||
#else
|
#else
|
||||||
var n = screen.get_n_monitors ();
|
var n = screen.get_n_monitors ();
|
||||||
#endif
|
#endif
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
|
||||||
foreach (var background in backgrounds.values) {
|
foreach (var background in backgrounds.values) {
|
||||||
if (i++ < n) {
|
if (i++ < n) {
|
||||||
background.update_resolution ();
|
background.update_resolution ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
background.changed.disconnect (background_changed);
|
background.changed.disconnect (background_changed);
|
||||||
background.destroy ();
|
background.destroy ();
|
||||||
// TODO can we remove from a list while iterating?
|
// TODO can we remove from a list while iterating?
|
||||||
backgrounds.unset (i);
|
backgrounds.unset (i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Background get_background (int monitor_index)
|
public Background get_background (int monitor_index)
|
||||||
{
|
{
|
||||||
string? filename = null;
|
string? filename = null;
|
||||||
|
|
||||||
var style = settings.get_enum ("picture-options");
|
var style = settings.get_enum ("picture-options");
|
||||||
if (style != GDesktop.BackgroundStyle.NONE) {
|
if (style != GDesktop.BackgroundStyle.NONE) {
|
||||||
var uri = settings.get_string ("picture-uri");
|
var uri = settings.get_string ("picture-uri");
|
||||||
if (Uri.parse_scheme (uri) != null)
|
if (Uri.parse_scheme (uri) != null)
|
||||||
filename = File.new_for_uri (uri).get_path ();
|
filename = File.new_for_uri (uri).get_path ();
|
||||||
else
|
else
|
||||||
filename = uri;
|
filename = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animated backgrounds are (potentially) per-monitor, since
|
// Animated backgrounds are (potentially) per-monitor, since
|
||||||
// they can have variants that depend on the aspect ratio and
|
// they can have variants that depend on the aspect ratio and
|
||||||
// size of the monitor; for other backgrounds we can use the
|
// size of the monitor; for other backgrounds we can use the
|
||||||
// same background object for all monitors.
|
// same background object for all monitors.
|
||||||
if (filename == null || !filename.has_suffix (".xml"))
|
if (filename == null || !filename.has_suffix (".xml"))
|
||||||
monitor_index = 0;
|
monitor_index = 0;
|
||||||
|
|
||||||
if (!backgrounds.has_key (monitor_index)) {
|
if (!backgrounds.has_key (monitor_index)) {
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var background = new Background (display, monitor_index, filename, this, (GDesktop.BackgroundStyle) style);
|
var background = new Background (display, monitor_index, filename, this, (GDesktop.BackgroundStyle) style);
|
||||||
#else
|
#else
|
||||||
var background = new Background (screen, monitor_index, filename, this, (GDesktop.BackgroundStyle) style);
|
var background = new Background (screen, monitor_index, filename, this, (GDesktop.BackgroundStyle) style);
|
||||||
#endif
|
#endif
|
||||||
background.changed.connect (background_changed);
|
background.changed.connect (background_changed);
|
||||||
backgrounds[monitor_index] = background;
|
backgrounds[monitor_index] = background;
|
||||||
}
|
}
|
||||||
|
|
||||||
return backgrounds[monitor_index];
|
return backgrounds[monitor_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void background_changed (Background background)
|
void background_changed (Background background)
|
||||||
{
|
{
|
||||||
background.changed.disconnect (background_changed);
|
background.changed.disconnect (background_changed);
|
||||||
background.destroy ();
|
background.destroy ();
|
||||||
backgrounds.unset (background.monitor_index);
|
backgrounds.unset (background.monitor_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy ()
|
public void destroy ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
Meta.MonitorManager.@get ().monitors_changed.disconnect (monitors_changed);
|
Meta.MonitorManager.@get ().monitors_changed.disconnect (monitors_changed);
|
||||||
#else
|
#else
|
||||||
screen.monitors_changed.disconnect (monitors_changed);
|
screen.monitors_changed.disconnect (monitors_changed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
foreach (var background in backgrounds) {
|
foreach (var background in backgrounds) {
|
||||||
background.changed.disconnect (background_changed);
|
background.changed.disconnect (background_changed);
|
||||||
background.destroy ();
|
background.destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unfortunately the settings sometimes tend to fire random changes even though
|
// unfortunately the settings sometimes tend to fire random changes even though
|
||||||
// nothing actually happend. The code below is used to prevent us from spamming
|
// nothing actually happend. The code below is used to prevent us from spamming
|
||||||
// new actors all the time, which lead to some problems in other areas of the code
|
// new actors all the time, which lead to some problems in other areas of the code
|
||||||
|
|
||||||
// helper struct which stores the hash values generated by g_variant_hash
|
// helper struct which stores the hash values generated by g_variant_hash
|
||||||
struct SettingsHashCache
|
struct SettingsHashCache
|
||||||
{
|
{
|
||||||
uint color_shading_type;
|
uint color_shading_type;
|
||||||
uint picture_opacity;
|
uint picture_opacity;
|
||||||
uint picture_options;
|
uint picture_options;
|
||||||
uint picture_uri;
|
uint picture_uri;
|
||||||
uint primar_color;
|
uint primar_color;
|
||||||
uint secondary_color;
|
uint secondary_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsHashCache settings_hash_cache;
|
SettingsHashCache settings_hash_cache;
|
||||||
|
|
||||||
// list of keys that are actually relevant for us
|
// list of keys that are actually relevant for us
|
||||||
const string[] options = { "color-shading-type", "picture-opacity",
|
const string[] options = { "color-shading-type", "picture-opacity",
|
||||||
"picture-options", "picture-uri", "primary-color", "secondary-color" };
|
"picture-options", "picture-uri", "primary-color", "secondary-color" };
|
||||||
|
|
||||||
void settings_changed (string key)
|
void settings_changed (string key)
|
||||||
{
|
{
|
||||||
if (!(key in options))
|
if (!(key in options))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var current = get_current_settings_hash_cache ();
|
var current = get_current_settings_hash_cache ();
|
||||||
|
|
||||||
if (Memory.cmp (&settings_hash_cache, ¤t, sizeof (SettingsHashCache)) == 0) {
|
if (Memory.cmp (&settings_hash_cache, ¤t, sizeof (SettingsHashCache)) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory.copy (&settings_hash_cache, ¤t, sizeof (SettingsHashCache));
|
Memory.copy (&settings_hash_cache, ¤t, sizeof (SettingsHashCache));
|
||||||
|
|
||||||
changed ();
|
changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsHashCache get_current_settings_hash_cache ()
|
SettingsHashCache get_current_settings_hash_cache ()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
settings.get_value ("color-shading-type").hash (),
|
settings.get_value ("color-shading-type").hash (),
|
||||||
settings.get_value ("picture-opacity").hash (),
|
settings.get_value ("picture-opacity").hash (),
|
||||||
settings.get_value ("picture-options").hash (),
|
settings.get_value ("picture-options").hash (),
|
||||||
settings.get_value ("picture-uri").hash (),
|
settings.get_value ("picture-uri").hash (),
|
||||||
settings.get_value ("primary-color").hash (),
|
settings.get_value ("primary-color").hash (),
|
||||||
settings.get_value ("secondary-color").hash ()
|
settings.get_value ("secondary-color").hash ()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,89 +18,89 @@
|
|||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER332
|
#if HAS_MUTTER332
|
||||||
public class SystemBackground : GLib.Object
|
public class SystemBackground : GLib.Object
|
||||||
#else
|
#else
|
||||||
public class SystemBackground : Meta.BackgroundActor
|
public class SystemBackground : Meta.BackgroundActor
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
const Clutter.Color DEFAULT_BACKGROUND_COLOR = { 0x2e, 0x34, 0x36, 0xff };
|
const Clutter.Color DEFAULT_BACKGROUND_COLOR = { 0x2e, 0x34, 0x36, 0xff };
|
||||||
|
|
||||||
static Meta.Background? system_background = null;
|
static Meta.Background? system_background = null;
|
||||||
#if HAS_MUTTER332
|
#if HAS_MUTTER332
|
||||||
public Meta.BackgroundActor background_actor { get; construct; }
|
public Meta.BackgroundActor background_actor { get; construct; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public signal void loaded ();
|
public signal void loaded ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public SystemBackground (Meta.Display display)
|
public SystemBackground (Meta.Display display)
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER332
|
#if HAS_MUTTER332
|
||||||
Object (background_actor: new Meta.BackgroundActor (display, 0));
|
Object (background_actor: new Meta.BackgroundActor (display, 0));
|
||||||
#else
|
#else
|
||||||
Object (meta_display: display, monitor: 0);
|
Object (meta_display: display, monitor: 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public SystemBackground (Meta.Screen screen)
|
public SystemBackground (Meta.Screen screen)
|
||||||
{
|
{
|
||||||
Object (meta_screen: screen, monitor: 0);
|
Object (meta_screen: screen, monitor: 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
var background_file = GLib.File.new_for_uri ("resource:///io/elementary/desktop/gala/texture.png");
|
var background_file = GLib.File.new_for_uri ("resource:///io/elementary/desktop/gala/texture.png");
|
||||||
unowned string custom_path = AppearanceSettings.get_default ().workspace_switcher_background;
|
unowned string custom_path = AppearanceSettings.get_default ().workspace_switcher_background;
|
||||||
if (custom_path != "" && FileUtils.test (custom_path, FileTest.IS_REGULAR)) {
|
if (custom_path != "" && FileUtils.test (custom_path, FileTest.IS_REGULAR)) {
|
||||||
background_file = GLib.File.new_for_path (custom_path);
|
background_file = GLib.File.new_for_path (custom_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system_background == null) {
|
if (system_background == null) {
|
||||||
#if HAS_MUTTER332
|
#if HAS_MUTTER332
|
||||||
system_background = new Meta.Background (background_actor.meta_display);
|
system_background = new Meta.Background (background_actor.meta_display);
|
||||||
#elif HAS_MUTTER330
|
#elif HAS_MUTTER330
|
||||||
system_background = new Meta.Background (meta_display);
|
system_background = new Meta.Background (meta_display);
|
||||||
#else
|
#else
|
||||||
system_background = new Meta.Background (meta_screen);
|
system_background = new Meta.Background (meta_screen);
|
||||||
#endif
|
#endif
|
||||||
system_background.set_color (DEFAULT_BACKGROUND_COLOR);
|
system_background.set_color (DEFAULT_BACKGROUND_COLOR);
|
||||||
system_background.set_file (background_file, GDesktop.BackgroundStyle.WALLPAPER);
|
system_background.set_file (background_file, GDesktop.BackgroundStyle.WALLPAPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER332
|
#if HAS_MUTTER332
|
||||||
background_actor.background = system_background;
|
background_actor.background = system_background;
|
||||||
#else
|
#else
|
||||||
background = system_background;
|
background = system_background;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var cache = Meta.BackgroundImageCache.get_default ();
|
var cache = Meta.BackgroundImageCache.get_default ();
|
||||||
var image = cache.load (background_file);
|
var image = cache.load (background_file);
|
||||||
if (image.is_loaded ()) {
|
if (image.is_loaded ()) {
|
||||||
image = null;
|
image = null;
|
||||||
Idle.add(() => {
|
Idle.add(() => {
|
||||||
loaded ();
|
loaded ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
ulong handler = 0;
|
ulong handler = 0;
|
||||||
handler = image.loaded.connect (() => {
|
handler = image.loaded.connect (() => {
|
||||||
loaded ();
|
loaded ();
|
||||||
SignalHandler.disconnect (image, handler);
|
SignalHandler.disconnect (image, handler);
|
||||||
image = null;
|
image = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void refresh ()
|
public static void refresh ()
|
||||||
{
|
{
|
||||||
// Meta.Background.refresh_all does not refresh backgrounds with the WALLPAPER style.
|
// Meta.Background.refresh_all does not refresh backgrounds with the WALLPAPER style.
|
||||||
// (Last tested with mutter 3.28)
|
// (Last tested with mutter 3.28)
|
||||||
// As a workaround, re-apply the current color again to force the wallpaper texture
|
// As a workaround, re-apply the current color again to force the wallpaper texture
|
||||||
// to be rendered from scratch.
|
// to be rendered from scratch.
|
||||||
if (system_background != null)
|
if (system_background != null)
|
||||||
system_background.set_color (DEFAULT_BACKGROUND_COLOR);
|
system_background.set_color (DEFAULT_BACKGROUND_COLOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
374
src/DBus.vala
374
src/DBus.vala
@ -17,233 +17,233 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
[DBus (name="org.pantheon.gala")]
|
[DBus (name="org.pantheon.gala")]
|
||||||
public class DBus
|
public class DBus
|
||||||
{
|
{
|
||||||
static DBus? instance;
|
static DBus? instance;
|
||||||
static WindowManager wm;
|
static WindowManager wm;
|
||||||
|
|
||||||
[DBus (visible = false)]
|
[DBus (visible = false)]
|
||||||
public static void init (WindowManager _wm)
|
public static void init (WindowManager _wm)
|
||||||
{
|
{
|
||||||
wm = _wm;
|
wm = _wm;
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.pantheon.gala", BusNameOwnerFlags.NONE,
|
Bus.own_name (BusType.SESSION, "org.pantheon.gala", BusNameOwnerFlags.NONE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new DBus ();
|
instance = new DBus ();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/pantheon/gala", instance);
|
connection.register_object ("/org/pantheon/gala", instance);
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
() => warning ("Could not acquire name\n") );
|
() => warning ("Could not acquire name\n") );
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.gnome.Shell", BusNameOwnerFlags.NONE,
|
Bus.own_name (BusType.SESSION, "org.gnome.Shell", BusNameOwnerFlags.NONE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/gnome/Shell", DBusAccelerator.init (wm));
|
connection.register_object ("/org/gnome/Shell", DBusAccelerator.init (wm));
|
||||||
connection.register_object ("/org/gnome/Shell/Screenshot", ScreenshotManager.init (wm));
|
connection.register_object ("/org/gnome/Shell/Screenshot", ScreenshotManager.init (wm));
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
() => critical ("Could not acquire name") );
|
() => critical ("Could not acquire name") );
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.gnome.Shell.Screenshot", BusNameOwnerFlags.REPLACE,
|
Bus.own_name (BusType.SESSION, "org.gnome.Shell.Screenshot", BusNameOwnerFlags.REPLACE,
|
||||||
() => {},
|
() => {},
|
||||||
() => {},
|
() => {},
|
||||||
() => critical ("Could not acquire name") );
|
() => critical ("Could not acquire name") );
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.gnome.SessionManager.EndSessionDialog", BusNameOwnerFlags.NONE,
|
Bus.own_name (BusType.SESSION, "org.gnome.SessionManager.EndSessionDialog", BusNameOwnerFlags.NONE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/gnome/SessionManager/EndSessionDialog", SessionManager.init ());
|
connection.register_object ("/org/gnome/SessionManager/EndSessionDialog", SessionManager.init ());
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
() => critical ("Could not acquire name") );
|
() => critical ("Could not acquire name") );
|
||||||
}
|
}
|
||||||
|
|
||||||
private DBus ()
|
private DBus ()
|
||||||
{
|
{
|
||||||
if (wm.background_group != null)
|
if (wm.background_group != null)
|
||||||
(wm.background_group as BackgroundContainer).changed.connect (() => background_changed ());
|
(wm.background_group as BackgroundContainer).changed.connect (() => background_changed ());
|
||||||
else
|
else
|
||||||
assert_not_reached ();
|
assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void perform_action (ActionType type) throws DBusError, IOError
|
public void perform_action (ActionType type) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
wm.perform_action (type);
|
wm.perform_action (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const double SATURATION_WEIGHT = 1.5;
|
const double SATURATION_WEIGHT = 1.5;
|
||||||
const double WEIGHT_THRESHOLD = 1.0;
|
const double WEIGHT_THRESHOLD = 1.0;
|
||||||
|
|
||||||
class DummyOffscreenEffect : Clutter.OffscreenEffect {
|
class DummyOffscreenEffect : Clutter.OffscreenEffect {
|
||||||
public signal void done_painting ();
|
public signal void done_painting ();
|
||||||
public override void post_paint ()
|
public override void post_paint ()
|
||||||
{
|
{
|
||||||
base.post_paint ();
|
base.post_paint ();
|
||||||
done_painting ();
|
done_painting ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ColorInformation
|
public struct ColorInformation
|
||||||
{
|
{
|
||||||
double average_red;
|
double average_red;
|
||||||
double average_green;
|
double average_green;
|
||||||
double average_blue;
|
double average_blue;
|
||||||
double mean;
|
double mean;
|
||||||
double variance;
|
double variance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted when the background change occured and the transition ended.
|
* Emitted when the background change occured and the transition ended.
|
||||||
* You can safely call get_optimal_panel_alpha then. It is not guaranteed
|
* You can safely call get_optimal_panel_alpha then. It is not guaranteed
|
||||||
* that this signal will be emitted only once per group of changes as often
|
* that this signal will be emitted only once per group of changes as often
|
||||||
* done by GUIs. The change may not be visible to the user.
|
* done by GUIs. The change may not be visible to the user.
|
||||||
*/
|
*/
|
||||||
public signal void background_changed ();
|
public signal void background_changed ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a dummy offscreen effect to the background at monitor to get its
|
* Attaches a dummy offscreen effect to the background at monitor to get its
|
||||||
* isolated color data. Then calculate the red, green and blue components of
|
* isolated color data. Then calculate the red, green and blue components of
|
||||||
* the average color in that area and the mean color value and variance. All
|
* the average color in that area and the mean color value and variance. All
|
||||||
* variables are returned as a tuple in that order.
|
* variables are returned as a tuple in that order.
|
||||||
*
|
*
|
||||||
* @param monitor The monitor where the panel will be placed
|
* @param monitor The monitor where the panel will be placed
|
||||||
* @param reference_x X coordinate of the rectangle used to gather color data
|
* @param reference_x X coordinate of the rectangle used to gather color data
|
||||||
* relative to the monitor you picked. Values will be clamped
|
* relative to the monitor you picked. Values will be clamped
|
||||||
* to its dimensions
|
* to its dimensions
|
||||||
* @param reference_y Y coordinate
|
* @param reference_y Y coordinate
|
||||||
* @param reference_width Width of the rectangle
|
* @param reference_width Width of the rectangle
|
||||||
* @param reference_height Height of the rectangle
|
* @param reference_height Height of the rectangle
|
||||||
*/
|
*/
|
||||||
public async ColorInformation get_background_color_information (int monitor,
|
public async ColorInformation get_background_color_information (int monitor,
|
||||||
int reference_x, int reference_y, int reference_width, int reference_height)
|
int reference_x, int reference_y, int reference_width, int reference_height)
|
||||||
throws DBusError, IOError
|
throws DBusError, IOError
|
||||||
{
|
{
|
||||||
var background = wm.background_group.get_child_at_index (monitor);
|
var background = wm.background_group.get_child_at_index (monitor);
|
||||||
if (background == null)
|
if (background == null)
|
||||||
throw new DBusError.INVALID_ARGS ("Invalid monitor requested");
|
throw new DBusError.INVALID_ARGS ("Invalid monitor requested");
|
||||||
|
|
||||||
var effect = new DummyOffscreenEffect ();
|
var effect = new DummyOffscreenEffect ();
|
||||||
background.add_effect (effect);
|
background.add_effect (effect);
|
||||||
|
|
||||||
var tex_width = (int)background.width;
|
var tex_width = (int)background.width;
|
||||||
var tex_height = (int)background.height;
|
var tex_height = (int)background.height;
|
||||||
|
|
||||||
int x_start = reference_x;
|
int x_start = reference_x;
|
||||||
int y_start = reference_y;
|
int y_start = reference_y;
|
||||||
int width = int.min (tex_width - reference_x, reference_width);
|
int width = int.min (tex_width - reference_x, reference_width);
|
||||||
int height = int.min (tex_height - reference_y, reference_height);
|
int height = int.min (tex_height - reference_y, reference_height);
|
||||||
|
|
||||||
if (x_start > tex_width || x_start > tex_height || width <= 0 || height <= 0)
|
if (x_start > tex_width || x_start > tex_height || width <= 0 || height <= 0)
|
||||||
throw new DBusError.INVALID_ARGS ("Invalid rectangle specified");
|
throw new DBusError.INVALID_ARGS ("Invalid rectangle specified");
|
||||||
|
|
||||||
double variance = 0, mean = 0,
|
double variance = 0, mean = 0,
|
||||||
rTotal = 0, gTotal = 0, bTotal = 0;
|
rTotal = 0, gTotal = 0, bTotal = 0;
|
||||||
|
|
||||||
ulong paint_signal_handler = 0;
|
ulong paint_signal_handler = 0;
|
||||||
paint_signal_handler = effect.done_painting.connect (() => {
|
paint_signal_handler = effect.done_painting.connect (() => {
|
||||||
SignalHandler.disconnect (effect, paint_signal_handler);
|
SignalHandler.disconnect (effect, paint_signal_handler);
|
||||||
background.remove_effect (effect);
|
background.remove_effect (effect);
|
||||||
|
|
||||||
var texture = (Cogl.Texture)effect.get_texture ();
|
var texture = (Cogl.Texture)effect.get_texture ();
|
||||||
var pixels = new uint8[texture.get_width () * texture.get_height () * 4];
|
var pixels = new uint8[texture.get_width () * texture.get_height () * 4];
|
||||||
CoglFixes.texture_get_data (texture, Cogl.PixelFormat.BGRA_8888_PRE, 0, pixels);
|
CoglFixes.texture_get_data (texture, Cogl.PixelFormat.BGRA_8888_PRE, 0, pixels);
|
||||||
|
|
||||||
int size = width * height;
|
int size = width * height;
|
||||||
|
|
||||||
double mean_squares = 0;
|
double mean_squares = 0;
|
||||||
double pixel = 0;
|
double pixel = 0;
|
||||||
|
|
||||||
double max, min, score, delta, scoreTotal = 0,
|
double max, min, score, delta, scoreTotal = 0,
|
||||||
rTotal2 = 0, gTotal2 = 0, bTotal2 = 0;
|
rTotal2 = 0, gTotal2 = 0, bTotal2 = 0;
|
||||||
|
|
||||||
// code to calculate weighted average color is copied from
|
// code to calculate weighted average color is copied from
|
||||||
// plank's lib/Drawing/DrawingService.vala average_color()
|
// plank's lib/Drawing/DrawingService.vala average_color()
|
||||||
// http://bazaar.launchpad.net/~docky-core/plank/trunk/view/head:/lib/Drawing/DrawingService.vala
|
// http://bazaar.launchpad.net/~docky-core/plank/trunk/view/head:/lib/Drawing/DrawingService.vala
|
||||||
for (int y = y_start; y < height; y++) {
|
for (int y = y_start; y < height; y++) {
|
||||||
for (int x = x_start; x < width; x++) {
|
for (int x = x_start; x < width; x++) {
|
||||||
int i = y * width * 4 + x * 4;
|
int i = y * width * 4 + x * 4;
|
||||||
|
|
||||||
uint8 r = pixels[i];
|
uint8 r = pixels[i];
|
||||||
uint8 g = pixels[i + 1];
|
uint8 g = pixels[i + 1];
|
||||||
uint8 b = pixels[i + 2];
|
uint8 b = pixels[i + 2];
|
||||||
|
|
||||||
pixel = (0.3 * r + 0.6 * g + 0.11 * b) - 128f;
|
pixel = (0.3 * r + 0.6 * g + 0.11 * b) - 128f;
|
||||||
|
|
||||||
min = uint8.min (r, uint8.min (g, b));
|
min = uint8.min (r, uint8.min (g, b));
|
||||||
max = uint8.max (r, uint8.max (g, b));
|
max = uint8.max (r, uint8.max (g, b));
|
||||||
delta = max - min;
|
delta = max - min;
|
||||||
|
|
||||||
// prefer colored pixels over shades of grey
|
// prefer colored pixels over shades of grey
|
||||||
score = SATURATION_WEIGHT * (delta == 0 ? 0.0 : delta / max);
|
score = SATURATION_WEIGHT * (delta == 0 ? 0.0 : delta / max);
|
||||||
|
|
||||||
rTotal += score * r;
|
rTotal += score * r;
|
||||||
gTotal += score * g;
|
gTotal += score * g;
|
||||||
bTotal += score * b;
|
bTotal += score * b;
|
||||||
scoreTotal += score;
|
scoreTotal += score;
|
||||||
|
|
||||||
rTotal += r;
|
rTotal += r;
|
||||||
gTotal += g;
|
gTotal += g;
|
||||||
bTotal += b;
|
bTotal += b;
|
||||||
|
|
||||||
mean += pixel;
|
mean += pixel;
|
||||||
mean_squares += pixel * pixel;
|
mean_squares += pixel * pixel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scoreTotal /= size;
|
scoreTotal /= size;
|
||||||
bTotal /= size;
|
bTotal /= size;
|
||||||
gTotal /= size;
|
gTotal /= size;
|
||||||
rTotal /= size;
|
rTotal /= size;
|
||||||
|
|
||||||
if (scoreTotal > 0.0) {
|
if (scoreTotal > 0.0) {
|
||||||
bTotal /= scoreTotal;
|
bTotal /= scoreTotal;
|
||||||
gTotal /= scoreTotal;
|
gTotal /= scoreTotal;
|
||||||
rTotal /= scoreTotal;
|
rTotal /= scoreTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bTotal2 /= size * uint8.MAX;
|
bTotal2 /= size * uint8.MAX;
|
||||||
gTotal2 /= size * uint8.MAX;
|
gTotal2 /= size * uint8.MAX;
|
||||||
rTotal2 /= size * uint8.MAX;
|
rTotal2 /= size * uint8.MAX;
|
||||||
|
|
||||||
// combine weighted and not weighted sum depending on the average "saturation"
|
// combine weighted and not weighted sum depending on the average "saturation"
|
||||||
// if saturation isn't reasonable enough
|
// if saturation isn't reasonable enough
|
||||||
// s = 0.0 -> f = 0.0 ; s = WEIGHT_THRESHOLD -> f = 1.0
|
// s = 0.0 -> f = 0.0 ; s = WEIGHT_THRESHOLD -> f = 1.0
|
||||||
if (scoreTotal <= WEIGHT_THRESHOLD) {
|
if (scoreTotal <= WEIGHT_THRESHOLD) {
|
||||||
var f = 1.0 / WEIGHT_THRESHOLD * scoreTotal;
|
var f = 1.0 / WEIGHT_THRESHOLD * scoreTotal;
|
||||||
var rf = 1.0 - f;
|
var rf = 1.0 - f;
|
||||||
bTotal = bTotal * f + bTotal2 * rf;
|
bTotal = bTotal * f + bTotal2 * rf;
|
||||||
gTotal = gTotal * f + gTotal2 * rf;
|
gTotal = gTotal * f + gTotal2 * rf;
|
||||||
rTotal = rTotal * f + rTotal2 * rf;
|
rTotal = rTotal * f + rTotal2 * rf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// there shouldn't be values larger then 1.0
|
// there shouldn't be values larger then 1.0
|
||||||
var max_val = double.max (rTotal, double.max (gTotal, bTotal));
|
var max_val = double.max (rTotal, double.max (gTotal, bTotal));
|
||||||
if (max_val > 1.0) {
|
if (max_val > 1.0) {
|
||||||
bTotal /= max_val;
|
bTotal /= max_val;
|
||||||
gTotal /= max_val;
|
gTotal /= max_val;
|
||||||
rTotal /= max_val;
|
rTotal /= max_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
mean /= size;
|
mean /= size;
|
||||||
mean_squares *= mean_squares / size;
|
mean_squares *= mean_squares / size;
|
||||||
|
|
||||||
variance = Math.sqrt (mean_squares - mean * mean) / (double) size;
|
variance = Math.sqrt (mean_squares - mean * mean) / (double) size;
|
||||||
|
|
||||||
get_background_color_information.callback ();
|
get_background_color_information.callback ();
|
||||||
});
|
});
|
||||||
|
|
||||||
background.queue_redraw ();
|
background.queue_redraw ();
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
return { rTotal, gTotal, bTotal, mean, variance };
|
return { rTotal, gTotal, bTotal, mean, variance };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,134 +17,134 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public struct Accelerator
|
public struct Accelerator
|
||||||
{
|
{
|
||||||
public string name;
|
public string name;
|
||||||
public Meta.KeyBindingFlags flags;
|
public Meta.KeyBindingFlags flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DBus (name="org.gnome.Shell")]
|
[DBus (name="org.gnome.Shell")]
|
||||||
public class DBusAccelerator
|
public class DBusAccelerator
|
||||||
{
|
{
|
||||||
static DBusAccelerator? instance;
|
static DBusAccelerator? instance;
|
||||||
|
|
||||||
[DBus (visible = false)]
|
[DBus (visible = false)]
|
||||||
public static unowned DBusAccelerator init (WindowManager wm)
|
public static unowned DBusAccelerator init (WindowManager wm)
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new DBusAccelerator (wm);
|
instance = new DBusAccelerator (wm);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public signal void accelerator_activated (uint action, GLib.HashTable<string, Variant> parameters);
|
public signal void accelerator_activated (uint action, GLib.HashTable<string, Variant> parameters);
|
||||||
|
|
||||||
WindowManager wm;
|
WindowManager wm;
|
||||||
HashTable<string, uint?> grabbed_accelerators;
|
HashTable<string, uint?> grabbed_accelerators;
|
||||||
|
|
||||||
DBusAccelerator (WindowManager _wm)
|
DBusAccelerator (WindowManager _wm)
|
||||||
{
|
{
|
||||||
wm = _wm;
|
wm = _wm;
|
||||||
grabbed_accelerators = new HashTable<string, uint?> (str_hash, str_equal);
|
grabbed_accelerators = new HashTable<string, uint?> (str_hash, str_equal);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
wm.get_display ().accelerator_activated.connect (on_accelerator_activated);
|
wm.get_display ().accelerator_activated.connect (on_accelerator_activated);
|
||||||
#else
|
#else
|
||||||
wm.get_screen ().get_display ().accelerator_activated.connect (on_accelerator_activated);
|
wm.get_screen ().get_display ().accelerator_activated.connect (on_accelerator_activated);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER334
|
#if HAS_MUTTER334
|
||||||
void on_accelerator_activated (uint action, Clutter.InputDevice device, uint timestamp)
|
void on_accelerator_activated (uint action, Clutter.InputDevice device, uint timestamp)
|
||||||
#else
|
#else
|
||||||
void on_accelerator_activated (uint action, uint device_id, uint timestamp)
|
void on_accelerator_activated (uint action, uint device_id, uint timestamp)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
foreach (string accelerator in grabbed_accelerators.get_keys ()) {
|
foreach (string accelerator in grabbed_accelerators.get_keys ()) {
|
||||||
if (grabbed_accelerators[accelerator] == action) {
|
if (grabbed_accelerators[accelerator] == action) {
|
||||||
var parameters = new GLib.HashTable<string, Variant> (null, null);
|
var parameters = new GLib.HashTable<string, Variant> (null, null);
|
||||||
#if HAS_MUTTER334
|
#if HAS_MUTTER334
|
||||||
parameters.set ("device-id", new Variant.uint32 (device.id));
|
parameters.set ("device-id", new Variant.uint32 (device.id));
|
||||||
#else
|
#else
|
||||||
parameters.set ("device-id", new Variant.uint32 (device_id));
|
parameters.set ("device-id", new Variant.uint32 (device_id));
|
||||||
#endif
|
#endif
|
||||||
parameters.set ("timestamp", new Variant.uint32 (timestamp));
|
parameters.set ("timestamp", new Variant.uint32 (timestamp));
|
||||||
|
|
||||||
accelerator_activated (action, parameters);
|
accelerator_activated (action, parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint grab_accelerator (string accelerator, uint flags) throws DBusError, IOError
|
public uint grab_accelerator (string accelerator, uint flags) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
uint? action = grabbed_accelerators[accelerator];
|
uint? action = grabbed_accelerators[accelerator];
|
||||||
|
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
#if HAS_MUTTER332
|
#if HAS_MUTTER332
|
||||||
action = wm.get_display ().grab_accelerator (accelerator, (Meta.KeyBindingFlags)flags);
|
action = wm.get_display ().grab_accelerator (accelerator, (Meta.KeyBindingFlags)flags);
|
||||||
#elif HAS_MUTTER330
|
#elif HAS_MUTTER330
|
||||||
action = wm.get_display ().grab_accelerator (accelerator);
|
action = wm.get_display ().grab_accelerator (accelerator);
|
||||||
#else
|
#else
|
||||||
action = wm.get_screen ().get_display ().grab_accelerator (accelerator);
|
action = wm.get_screen ().get_display ().grab_accelerator (accelerator);
|
||||||
#endif
|
#endif
|
||||||
if (action > 0) {
|
if (action > 0) {
|
||||||
grabbed_accelerators[accelerator] = action;
|
grabbed_accelerators[accelerator] = action;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint[] grab_accelerators (Accelerator[] accelerators) throws DBusError, IOError
|
public uint[] grab_accelerators (Accelerator[] accelerators) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
uint[] actions = {};
|
uint[] actions = {};
|
||||||
|
|
||||||
foreach (unowned Accelerator? accelerator in accelerators) {
|
foreach (unowned Accelerator? accelerator in accelerators) {
|
||||||
actions += grab_accelerator (accelerator.name, accelerator.flags);
|
actions += grab_accelerator (accelerator.name, accelerator.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ungrab_accelerator (uint action) throws DBusError, IOError
|
public bool ungrab_accelerator (uint action) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
foreach (unowned string accelerator in grabbed_accelerators.get_keys ()) {
|
foreach (unowned string accelerator in grabbed_accelerators.get_keys ()) {
|
||||||
if (grabbed_accelerators[accelerator] == action) {
|
if (grabbed_accelerators[accelerator] == action) {
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
ret = wm.get_display ().ungrab_accelerator (action);
|
ret = wm.get_display ().ungrab_accelerator (action);
|
||||||
#else
|
#else
|
||||||
ret = wm.get_screen ().get_display ().ungrab_accelerator (action);
|
ret = wm.get_screen ().get_display ().ungrab_accelerator (action);
|
||||||
#endif
|
#endif
|
||||||
grabbed_accelerators.remove (accelerator);
|
grabbed_accelerators.remove (accelerator);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DBus (name = "ShowOSD")]
|
[DBus (name = "ShowOSD")]
|
||||||
public void show_osd (GLib.HashTable<string, Variant> parameters) throws DBusError, IOError
|
public void show_osd (GLib.HashTable<string, Variant> parameters) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
int32 monitor_index = -1;
|
int32 monitor_index = -1;
|
||||||
if (parameters.contains ("monitor"))
|
if (parameters.contains ("monitor"))
|
||||||
monitor_index = parameters["monitor"].get_int32 ();
|
monitor_index = parameters["monitor"].get_int32 ();
|
||||||
string icon = "";
|
string icon = "";
|
||||||
if (parameters.contains ("icon"))
|
if (parameters.contains ("icon"))
|
||||||
icon = parameters["icon"].get_string ();
|
icon = parameters["icon"].get_string ();
|
||||||
string label = "";
|
string label = "";
|
||||||
if (parameters.contains ("label"))
|
if (parameters.contains ("label"))
|
||||||
label = parameters["label"].get_string ();
|
label = parameters["label"].get_string ();
|
||||||
int32 level = 0;
|
int32 level = 0;
|
||||||
if (parameters.contains ("level"))
|
if (parameters.contains ("level"))
|
||||||
level = parameters["level"].get_int32 ();
|
level = parameters["level"].get_int32 ();
|
||||||
|
|
||||||
//if (monitor_index > -1)
|
//if (monitor_index > -1)
|
||||||
// message ("MediaFeedback requested for specific monitor %i which is not supported", monitor_index);
|
// message ("MediaFeedback requested for specific monitor %i which is not supported", monitor_index);
|
||||||
|
|
||||||
MediaFeedback.send (icon, level);
|
MediaFeedback.send (icon, level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,52 +17,52 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Provides access to a PlankDrawingDockTheme and PlankDockPrefereces
|
* Provides access to a PlankDrawingDockTheme and PlankDockPrefereces
|
||||||
*/
|
*/
|
||||||
public class DockThemeManager : Object
|
public class DockThemeManager : Object
|
||||||
{
|
{
|
||||||
static DockThemeManager? instance = null;
|
static DockThemeManager? instance = null;
|
||||||
|
|
||||||
public static unowned DockThemeManager get_default ()
|
public static unowned DockThemeManager get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new DockThemeManager ();
|
instance = new DockThemeManager ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plank.DockPreferences? dock_settings = null;
|
Plank.DockPreferences? dock_settings = null;
|
||||||
Plank.DockTheme? dock_theme = null;
|
Plank.DockTheme? dock_theme = null;
|
||||||
|
|
||||||
public signal void dock_theme_changed (Plank.DockTheme? old_theme,
|
public signal void dock_theme_changed (Plank.DockTheme? old_theme,
|
||||||
Plank.DockTheme new_theme);
|
Plank.DockTheme new_theme);
|
||||||
|
|
||||||
DockThemeManager ()
|
DockThemeManager ()
|
||||||
{
|
{
|
||||||
dock_settings = new Plank.DockPreferences ("dock1");
|
dock_settings = new Plank.DockPreferences ("dock1");
|
||||||
dock_settings.notify["Theme"].connect (load_dock_theme);
|
dock_settings.notify["Theme"].connect (load_dock_theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plank.DockTheme get_dock_theme ()
|
public Plank.DockTheme get_dock_theme ()
|
||||||
{
|
{
|
||||||
if (dock_theme == null)
|
if (dock_theme == null)
|
||||||
load_dock_theme ();
|
load_dock_theme ();
|
||||||
|
|
||||||
return dock_theme;
|
return dock_theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plank.DockPreferences get_dock_settings ()
|
public Plank.DockPreferences get_dock_settings ()
|
||||||
{
|
{
|
||||||
return dock_settings;
|
return dock_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_dock_theme ()
|
void load_dock_theme ()
|
||||||
{
|
{
|
||||||
var new_theme = new Plank.DockTheme (dock_settings.Theme);
|
var new_theme = new Plank.DockTheme (dock_settings.Theme);
|
||||||
new_theme.load ("dock");
|
new_theme.load ("dock");
|
||||||
dock_theme_changed (dock_theme, new_theme);
|
dock_theme_changed (dock_theme, new_theme);
|
||||||
dock_theme = new_theme;
|
dock_theme = new_theme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,389 +19,389 @@ using Clutter;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum DragDropActionType
|
public enum DragDropActionType
|
||||||
{
|
{
|
||||||
SOURCE,
|
SOURCE,
|
||||||
DESTINATION
|
DESTINATION
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DragDropAction : Clutter.Action
|
public class DragDropAction : Clutter.Action
|
||||||
{
|
{
|
||||||
static Gee.HashMap<string,Gee.LinkedList<Actor>>? sources = null;
|
static Gee.HashMap<string,Gee.LinkedList<Actor>>? sources = null;
|
||||||
static Gee.HashMap<string,Gee.LinkedList<Actor>>? destinations = null;
|
static Gee.HashMap<string,Gee.LinkedList<Actor>>? destinations = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A drag has been started. You have to connect to this signal and
|
* A drag has been started. You have to connect to this signal and
|
||||||
* return an actor that is transformed during the drag operation.
|
* return an actor that is transformed during the drag operation.
|
||||||
*
|
*
|
||||||
* @param x The global x coordinate where the action was activated
|
* @param x The global x coordinate where the action was activated
|
||||||
* @param y The global y coordinate where the action was activated
|
* @param y The global y coordinate where the action was activated
|
||||||
* @return A ClutterActor that serves as handle
|
* @return A ClutterActor that serves as handle
|
||||||
*/
|
*/
|
||||||
public signal Actor drag_begin (float x, float y);
|
public signal Actor drag_begin (float x, float y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A drag has been canceled. You may want to consider cleaning up
|
* A drag has been canceled. You may want to consider cleaning up
|
||||||
* your handle.
|
* your handle.
|
||||||
*/
|
*/
|
||||||
public signal void drag_canceled ();
|
public signal void drag_canceled ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A drag action has successfully been finished.
|
* A drag action has successfully been finished.
|
||||||
*
|
*
|
||||||
* @param actor The actor on which the drag finished
|
* @param actor The actor on which the drag finished
|
||||||
*/
|
*/
|
||||||
public signal void drag_end (Actor actor);
|
public signal void drag_end (Actor actor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The destination has been crossed
|
* The destination has been crossed
|
||||||
*
|
*
|
||||||
* @param target the target actor that is crossing the destination
|
* @param target the target actor that is crossing the destination
|
||||||
* @param hovered indicates whether the actor is now hovered or not
|
* @param hovered indicates whether the actor is now hovered or not
|
||||||
*/
|
*/
|
||||||
public signal void crossed (Actor? target, bool hovered);
|
public signal void crossed (Actor? target, bool hovered);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted on the source when a destination is crossed.
|
* Emitted on the source when a destination is crossed.
|
||||||
*
|
*
|
||||||
* @param destination The destination actor that has been crossed
|
* @param destination The destination actor that has been crossed
|
||||||
* @param hovered Whether the actor is now hovered or has just been left
|
* @param hovered Whether the actor is now hovered or has just been left
|
||||||
*/
|
*/
|
||||||
public signal void destination_crossed (Actor destination, bool hovered);
|
public signal void destination_crossed (Actor destination, bool hovered);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source has been clicked, but the movement was not larger than
|
* The source has been clicked, but the movement was not larger than
|
||||||
* the drag threshold. Useful if the source is also activable.
|
* the drag threshold. Useful if the source is also activable.
|
||||||
*
|
*
|
||||||
* @param button The button which was pressed
|
* @param button The button which was pressed
|
||||||
*/
|
*/
|
||||||
public signal void actor_clicked (uint32 button);
|
public signal void actor_clicked (uint32 button);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the action
|
* The type of the action
|
||||||
*/
|
*/
|
||||||
public DragDropActionType drag_type { get; construct; }
|
public DragDropActionType drag_type { get; construct; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The unique id given to this drag-drop-group
|
* The unique id given to this drag-drop-group
|
||||||
*/
|
*/
|
||||||
public string drag_id { get; construct; }
|
public string drag_id { get; construct; }
|
||||||
|
|
||||||
public Actor handle { get; private set; }
|
public Actor handle { get; private set; }
|
||||||
/**
|
/**
|
||||||
* Indicates whether a drag action is currently active
|
* Indicates whether a drag action is currently active
|
||||||
*/
|
*/
|
||||||
public bool dragging { get; private set; default = false; }
|
public bool dragging { get; private set; default = false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow checking the parents of reactive children if they are valid destinations
|
* Allow checking the parents of reactive children if they are valid destinations
|
||||||
* if the child is none
|
* if the child is none
|
||||||
*/
|
*/
|
||||||
public bool allow_bubbling { get; set; default = true; }
|
public bool allow_bubbling { get; set; default = true; }
|
||||||
|
|
||||||
public Actor? hovered { private get; set; default = null; }
|
public Actor? hovered { private get; set; default = null; }
|
||||||
|
|
||||||
bool clicked = false;
|
bool clicked = false;
|
||||||
float last_x;
|
float last_x;
|
||||||
float last_y;
|
float last_y;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new DragDropAction
|
* Create a new DragDropAction
|
||||||
*
|
*
|
||||||
* @param type The type of this actor
|
* @param type The type of this actor
|
||||||
* @param id An ID that marks which sources can be dragged on
|
* @param id An ID that marks which sources can be dragged on
|
||||||
* which destinations. It has to be the same for all actors that
|
* which destinations. It has to be the same for all actors that
|
||||||
* should be compatible with each other.
|
* should be compatible with each other.
|
||||||
*/
|
*/
|
||||||
public DragDropAction (DragDropActionType type, string id)
|
public DragDropAction (DragDropActionType type, string id)
|
||||||
{
|
{
|
||||||
Object (drag_type : type, drag_id : id);
|
Object (drag_type : type, drag_id : id);
|
||||||
|
|
||||||
if (sources == null)
|
if (sources == null)
|
||||||
sources = new Gee.HashMap<string,Gee.LinkedList<Actor>> ();
|
sources = new Gee.HashMap<string,Gee.LinkedList<Actor>> ();
|
||||||
|
|
||||||
if (destinations == null)
|
if (destinations == null)
|
||||||
destinations = new Gee.HashMap<string,Gee.LinkedList<Actor>> ();
|
destinations = new Gee.HashMap<string,Gee.LinkedList<Actor>> ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~DragDropAction ()
|
~DragDropAction ()
|
||||||
{
|
{
|
||||||
if (actor != null)
|
if (actor != null)
|
||||||
release_actor (actor);
|
release_actor (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void set_actor (Actor? new_actor)
|
public override void set_actor (Actor? new_actor)
|
||||||
{
|
{
|
||||||
if (actor != null) {
|
if (actor != null) {
|
||||||
release_actor (actor);
|
release_actor (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_actor != null) {
|
if (new_actor != null) {
|
||||||
connect_actor (new_actor);
|
connect_actor (new_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
base.set_actor (new_actor);
|
base.set_actor (new_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_actor (Actor actor)
|
void release_actor (Actor actor)
|
||||||
{
|
{
|
||||||
if (DragDropActionType.SOURCE in drag_type) {
|
if (DragDropActionType.SOURCE in drag_type) {
|
||||||
actor.button_press_event.disconnect (source_clicked);
|
actor.button_press_event.disconnect (source_clicked);
|
||||||
|
|
||||||
var source_list = sources.@get (drag_id);
|
var source_list = sources.@get (drag_id);
|
||||||
source_list.remove (actor);
|
source_list.remove (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DragDropActionType.DESTINATION in drag_type) {
|
if (DragDropActionType.DESTINATION in drag_type) {
|
||||||
var dest_list = destinations[drag_id];
|
var dest_list = destinations[drag_id];
|
||||||
dest_list.remove (actor);
|
dest_list.remove (actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect_actor (Actor actor)
|
void connect_actor (Actor actor)
|
||||||
{
|
{
|
||||||
if (DragDropActionType.SOURCE in drag_type) {
|
if (DragDropActionType.SOURCE in drag_type) {
|
||||||
actor.button_press_event.connect (source_clicked);
|
actor.button_press_event.connect (source_clicked);
|
||||||
|
|
||||||
var source_list = sources.@get (drag_id);
|
var source_list = sources.@get (drag_id);
|
||||||
if (source_list == null) {
|
if (source_list == null) {
|
||||||
source_list = new Gee.LinkedList<Actor> ();
|
source_list = new Gee.LinkedList<Actor> ();
|
||||||
sources.@set (drag_id, source_list);
|
sources.@set (drag_id, source_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
source_list.add (actor);
|
source_list.add (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DragDropActionType.DESTINATION in drag_type) {
|
if (DragDropActionType.DESTINATION in drag_type) {
|
||||||
var dest_list = destinations[drag_id];
|
var dest_list = destinations[drag_id];
|
||||||
if (dest_list == null) {
|
if (dest_list == null) {
|
||||||
dest_list = new Gee.LinkedList<Actor> ();
|
dest_list = new Gee.LinkedList<Actor> ();
|
||||||
destinations[drag_id] = dest_list;
|
destinations[drag_id] = dest_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest_list.add (actor);
|
dest_list.add (actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_crossed (Actor destination, bool is_hovered)
|
void emit_crossed (Actor destination, bool is_hovered)
|
||||||
{
|
{
|
||||||
get_drag_drop_action (destination).crossed (actor, is_hovered);
|
get_drag_drop_action (destination).crossed (actor, is_hovered);
|
||||||
destination_crossed (destination, is_hovered);
|
destination_crossed (destination, is_hovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool source_clicked (ButtonEvent event)
|
bool source_clicked (ButtonEvent event)
|
||||||
{
|
{
|
||||||
if (event.button != 1) {
|
if (event.button != 1) {
|
||||||
actor_clicked (event.button);
|
actor_clicked (event.button);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.get_stage ().captured_event.connect (follow_move);
|
actor.get_stage ().captured_event.connect (follow_move);
|
||||||
clicked = true;
|
clicked = true;
|
||||||
last_x = event.x;
|
last_x = event.x;
|
||||||
last_y = event.y;
|
last_y = event.y;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool follow_move (Event event)
|
bool follow_move (Event event)
|
||||||
{
|
{
|
||||||
// still determining if we actually want to start a drag action
|
// still determining if we actually want to start a drag action
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
switch (event.get_type ()) {
|
switch (event.get_type ()) {
|
||||||
case EventType.MOTION:
|
case EventType.MOTION:
|
||||||
float x, y;
|
float x, y;
|
||||||
event.get_coords (out x, out y);
|
event.get_coords (out x, out y);
|
||||||
|
|
||||||
var drag_threshold = Clutter.Settings.get_default ().dnd_drag_threshold;
|
var drag_threshold = Clutter.Settings.get_default ().dnd_drag_threshold;
|
||||||
if (Math.fabsf (last_x - x) > drag_threshold || Math.fabsf (last_y - y) > drag_threshold) {
|
if (Math.fabsf (last_x - x) > drag_threshold || Math.fabsf (last_y - y) > drag_threshold) {
|
||||||
handle = drag_begin (x, y);
|
handle = drag_begin (x, y);
|
||||||
if (handle == null) {
|
if (handle == null) {
|
||||||
actor.get_stage ().captured_event.disconnect (follow_move);
|
actor.get_stage ().captured_event.disconnect (follow_move);
|
||||||
critical ("No handle has been returned by the started signal, aborting drag.");
|
critical ("No handle has been returned by the started signal, aborting drag.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle.reactive = false;
|
handle.reactive = false;
|
||||||
|
|
||||||
clicked = false;
|
clicked = false;
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
|
||||||
var source_list = sources.@get (drag_id);
|
var source_list = sources.@get (drag_id);
|
||||||
if (source_list != null) {
|
if (source_list != null) {
|
||||||
var dest_list = destinations[drag_id];
|
var dest_list = destinations[drag_id];
|
||||||
foreach (var actor in source_list) {
|
foreach (var actor in source_list) {
|
||||||
// Do not unset reactivity on destinations
|
// Do not unset reactivity on destinations
|
||||||
if (actor in dest_list) {
|
if (actor in dest_list) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.reactive = false;
|
actor.reactive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case EventType.BUTTON_RELEASE:
|
case EventType.BUTTON_RELEASE:
|
||||||
float x, y, ex, ey;
|
float x, y, ex, ey;
|
||||||
event.get_coords (out ex, out ey);
|
event.get_coords (out ex, out ey);
|
||||||
actor.get_transformed_position (out x, out y);
|
actor.get_transformed_position (out x, out y);
|
||||||
|
|
||||||
// release has happened within bounds of actor
|
// release has happened within bounds of actor
|
||||||
if (x < ex && x + actor.width > ex && y < ey && y + actor.height > ey) {
|
if (x < ex && x + actor.width > ex && y < ey && y + actor.height > ey) {
|
||||||
actor_clicked (event.get_button ());
|
actor_clicked (event.get_button ());
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.get_stage ().captured_event.disconnect (follow_move);
|
actor.get_stage ().captured_event.disconnect (follow_move);
|
||||||
clicked = false;
|
clicked = false;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event.get_type ()) {
|
switch (event.get_type ()) {
|
||||||
case EventType.KEY_PRESS:
|
case EventType.KEY_PRESS:
|
||||||
if (event.get_key_code () == Key.Escape) {
|
if (event.get_key_code () == Key.Escape) {
|
||||||
cancel ();
|
cancel ();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case EventType.MOTION:
|
case EventType.MOTION:
|
||||||
float x, y;
|
float x, y;
|
||||||
event.get_coords (out x, out y);
|
event.get_coords (out x, out y);
|
||||||
handle.x -= last_x - x;
|
handle.x -= last_x - x;
|
||||||
handle.y -= last_y - y;
|
handle.y -= last_y - y;
|
||||||
last_x = x;
|
last_x = x;
|
||||||
last_y = y;
|
last_y = y;
|
||||||
|
|
||||||
var stage = actor.get_stage ();
|
var stage = actor.get_stage ();
|
||||||
var actor = stage.get_actor_at_pos (PickMode.REACTIVE, (int) x, (int) y);
|
var actor = stage.get_actor_at_pos (PickMode.REACTIVE, (int) x, (int) y);
|
||||||
DragDropAction action = null;
|
DragDropAction action = null;
|
||||||
// if we're allowed to bubble and this actor is not a destination, check its parents
|
// if we're allowed to bubble and this actor is not a destination, check its parents
|
||||||
if (actor != null && (action = get_drag_drop_action (actor)) == null && allow_bubbling) {
|
if (actor != null && (action = get_drag_drop_action (actor)) == null && allow_bubbling) {
|
||||||
while ((actor = actor.get_parent ()) != stage) {
|
while ((actor = actor.get_parent ()) != stage) {
|
||||||
if ((action = get_drag_drop_action (actor)) != null)
|
if ((action = get_drag_drop_action (actor)) != null)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// didn't change, no need to do anything
|
// didn't change, no need to do anything
|
||||||
if (actor == hovered)
|
if (actor == hovered)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
// apparently we left ours if we had one before
|
// apparently we left ours if we had one before
|
||||||
if (hovered != null) {
|
if (hovered != null) {
|
||||||
emit_crossed (hovered, false);
|
emit_crossed (hovered, false);
|
||||||
hovered = null;
|
hovered = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// signal the previous one that we left it
|
// signal the previous one that we left it
|
||||||
if (hovered != null) {
|
if (hovered != null) {
|
||||||
emit_crossed (hovered, false);
|
emit_crossed (hovered, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell the new one that it is hovered
|
// tell the new one that it is hovered
|
||||||
hovered = actor;
|
hovered = actor;
|
||||||
emit_crossed (hovered, true);
|
emit_crossed (hovered, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case EventType.BUTTON_RELEASE:
|
case EventType.BUTTON_RELEASE:
|
||||||
if (hovered != null) {
|
if (hovered != null) {
|
||||||
finish ();
|
finish ();
|
||||||
} else {
|
} else {
|
||||||
cancel ();
|
cancel ();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case EventType.ENTER:
|
case EventType.ENTER:
|
||||||
case EventType.LEAVE:
|
case EventType.LEAVE:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks for a DragDropAction instance if this actor has one or NULL.
|
* Looks for a DragDropAction instance if this actor has one or NULL.
|
||||||
* It also checks if it is a DESTINATION and if the id matches
|
* It also checks if it is a DESTINATION and if the id matches
|
||||||
*
|
*
|
||||||
* @return the DragDropAction instance on this actor or NULL
|
* @return the DragDropAction instance on this actor or NULL
|
||||||
*/
|
*/
|
||||||
DragDropAction? get_drag_drop_action (Actor actor)
|
DragDropAction? get_drag_drop_action (Actor actor)
|
||||||
{
|
{
|
||||||
DragDropAction? drop_action = null;
|
DragDropAction? drop_action = null;
|
||||||
|
|
||||||
foreach (var action in actor.get_actions ()) {
|
foreach (var action in actor.get_actions ()) {
|
||||||
drop_action = action as DragDropAction;
|
drop_action = action as DragDropAction;
|
||||||
if (drop_action == null
|
if (drop_action == null
|
||||||
|| !(DragDropActionType.DESTINATION in drop_action.drag_type)
|
|| !(DragDropActionType.DESTINATION in drop_action.drag_type)
|
||||||
|| drop_action.drag_id != drag_id)
|
|| drop_action.drag_id != drag_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return drop_action;
|
return drop_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abort the drag
|
* Abort the drag
|
||||||
*/
|
*/
|
||||||
public void cancel ()
|
public void cancel ()
|
||||||
{
|
{
|
||||||
cleanup ();
|
cleanup ();
|
||||||
|
|
||||||
drag_canceled ();
|
drag_canceled ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows you to abort all drags currently running for a given drag-id
|
* Allows you to abort all drags currently running for a given drag-id
|
||||||
*/
|
*/
|
||||||
public static void cancel_all_by_id (string id)
|
public static void cancel_all_by_id (string id)
|
||||||
{
|
{
|
||||||
var actors = sources.@get (id);
|
var actors = sources.@get (id);
|
||||||
if (actors == null)
|
if (actors == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var actor in actors) {
|
foreach (var actor in actors) {
|
||||||
foreach (var action in actor.get_actions ()) {
|
foreach (var action in actor.get_actions ()) {
|
||||||
var drag_action = action as DragDropAction;
|
var drag_action = action as DragDropAction;
|
||||||
if (drag_action != null && drag_action.dragging) {
|
if (drag_action != null && drag_action.dragging) {
|
||||||
drag_action.cancel ();
|
drag_action.cancel ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish ()
|
void finish ()
|
||||||
{
|
{
|
||||||
// make sure they reset the style or whatever they changed when hovered
|
// make sure they reset the style or whatever they changed when hovered
|
||||||
emit_crossed (hovered, false);
|
emit_crossed (hovered, false);
|
||||||
|
|
||||||
cleanup ();
|
cleanup ();
|
||||||
|
|
||||||
drag_end (hovered);
|
drag_end (hovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup ()
|
void cleanup ()
|
||||||
{
|
{
|
||||||
var source_list = sources.@get (drag_id);
|
var source_list = sources.@get (drag_id);
|
||||||
if (source_list != null) {
|
if (source_list != null) {
|
||||||
foreach (var actor in source_list) {
|
foreach (var actor in source_list) {
|
||||||
actor.reactive = true;
|
actor.reactive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dragging)
|
if (dragging)
|
||||||
actor.get_stage ().captured_event.disconnect (follow_move);
|
actor.get_stage ().captured_event.disconnect (follow_move);
|
||||||
|
|
||||||
dragging = false;
|
dragging = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,368 +19,368 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public enum InputArea
|
public enum InputArea
|
||||||
{
|
{
|
||||||
NONE,
|
NONE,
|
||||||
FULLSCREEN,
|
FULLSCREEN,
|
||||||
DEFAULT
|
DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InternalUtils
|
public class InternalUtils
|
||||||
{
|
{
|
||||||
public static bool workspaces_only_on_primary ()
|
public static bool workspaces_only_on_primary ()
|
||||||
{
|
{
|
||||||
return Prefs.get_dynamic_workspaces ()
|
return Prefs.get_dynamic_workspaces ()
|
||||||
&& Prefs.get_workspaces_only_on_primary ();
|
&& Prefs.get_workspaces_only_on_primary ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reload shadow settings
|
* Reload shadow settings
|
||||||
*/
|
*/
|
||||||
public static void reload_shadow ()
|
public static void reload_shadow ()
|
||||||
{
|
{
|
||||||
var factory = ShadowFactory.get_default ();
|
var factory = ShadowFactory.get_default ();
|
||||||
var settings = ShadowSettings.get_default ();
|
var settings = ShadowSettings.get_default ();
|
||||||
Meta.ShadowParams shadow;
|
Meta.ShadowParams shadow;
|
||||||
|
|
||||||
//normal focused
|
//normal focused
|
||||||
shadow = settings.get_shadowparams ("normal_focused");
|
shadow = settings.get_shadowparams ("normal_focused");
|
||||||
factory.set_params ("normal", true, shadow);
|
factory.set_params ("normal", true, shadow);
|
||||||
|
|
||||||
//normal unfocused
|
//normal unfocused
|
||||||
shadow = settings.get_shadowparams ("normal_unfocused");
|
shadow = settings.get_shadowparams ("normal_unfocused");
|
||||||
factory.set_params ("normal", false, shadow);
|
factory.set_params ("normal", false, shadow);
|
||||||
|
|
||||||
//menus
|
//menus
|
||||||
shadow = settings.get_shadowparams ("menu");
|
shadow = settings.get_shadowparams ("menu");
|
||||||
factory.set_params ("menu", false, shadow);
|
factory.set_params ("menu", false, shadow);
|
||||||
factory.set_params ("dropdown-menu", false, shadow);
|
factory.set_params ("dropdown-menu", false, shadow);
|
||||||
factory.set_params ("popup-menu", false, shadow);
|
factory.set_params ("popup-menu", false, shadow);
|
||||||
|
|
||||||
//dialog focused
|
//dialog focused
|
||||||
shadow = settings.get_shadowparams ("dialog_focused");
|
shadow = settings.get_shadowparams ("dialog_focused");
|
||||||
factory.set_params ("dialog", true, shadow);
|
factory.set_params ("dialog", true, shadow);
|
||||||
factory.set_params ("modal_dialog", false, shadow);
|
factory.set_params ("modal_dialog", false, shadow);
|
||||||
|
|
||||||
//dialog unfocused
|
//dialog unfocused
|
||||||
shadow = settings.get_shadowparams ("dialog_unfocused");
|
shadow = settings.get_shadowparams ("dialog_unfocused");
|
||||||
factory.set_params ("dialog", false, shadow);
|
factory.set_params ("dialog", false, shadow);
|
||||||
factory.set_params ("modal_dialog", false, shadow);
|
factory.set_params ("modal_dialog", false, shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the area where clutter can receive events
|
* set the area where clutter can receive events
|
||||||
**/
|
**/
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public static void set_input_area (Display display, InputArea area)
|
public static void set_input_area (Display display, InputArea area)
|
||||||
{
|
{
|
||||||
X.Xrectangle[] rects = {};
|
X.Xrectangle[] rects = {};
|
||||||
int width, height;
|
int width, height;
|
||||||
display.get_size (out width, out height);
|
display.get_size (out width, out height);
|
||||||
var geometry = display.get_monitor_geometry (display.get_primary_monitor ());
|
var geometry = display.get_monitor_geometry (display.get_primary_monitor ());
|
||||||
|
|
||||||
switch (area) {
|
switch (area) {
|
||||||
case InputArea.FULLSCREEN:
|
case InputArea.FULLSCREEN:
|
||||||
X.Xrectangle rect = {0, 0, (ushort)width, (ushort)height};
|
X.Xrectangle rect = {0, 0, (ushort)width, (ushort)height};
|
||||||
rects = {rect};
|
rects = {rect};
|
||||||
break;
|
break;
|
||||||
case InputArea.DEFAULT:
|
case InputArea.DEFAULT:
|
||||||
var schema = BehaviorSettings.get_default ().schema;
|
var schema = BehaviorSettings.get_default ().schema;
|
||||||
|
|
||||||
// if ActionType is NONE make it 0 sized
|
// if ActionType is NONE make it 0 sized
|
||||||
ushort tl_size = (schema.get_enum ("hotcorner-topleft") != ActionType.NONE ? 1 : 0);
|
ushort tl_size = (schema.get_enum ("hotcorner-topleft") != ActionType.NONE ? 1 : 0);
|
||||||
ushort tr_size = (schema.get_enum ("hotcorner-topright") != ActionType.NONE ? 1 : 0);
|
ushort tr_size = (schema.get_enum ("hotcorner-topright") != ActionType.NONE ? 1 : 0);
|
||||||
ushort bl_size = (schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE ? 1 : 0);
|
ushort bl_size = (schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE ? 1 : 0);
|
||||||
ushort br_size = (schema.get_enum ("hotcorner-bottomright") != ActionType.NONE ? 1 : 0);
|
ushort br_size = (schema.get_enum ("hotcorner-bottomright") != ActionType.NONE ? 1 : 0);
|
||||||
|
|
||||||
X.Xrectangle topleft = {(short)geometry.x, (short)geometry.y, tl_size, tl_size};
|
X.Xrectangle topleft = {(short)geometry.x, (short)geometry.y, tl_size, tl_size};
|
||||||
X.Xrectangle topright = {(short)(geometry.x + geometry.width - 1), (short)geometry.y, tr_size, tr_size};
|
X.Xrectangle topright = {(short)(geometry.x + geometry.width - 1), (short)geometry.y, tr_size, tr_size};
|
||||||
X.Xrectangle bottomleft = {(short)geometry.x, (short)(geometry.y + geometry.height - 1), bl_size, bl_size};
|
X.Xrectangle bottomleft = {(short)geometry.x, (short)(geometry.y + geometry.height - 1), bl_size, bl_size};
|
||||||
X.Xrectangle bottomright = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), br_size, br_size};
|
X.Xrectangle bottomright = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), br_size, br_size};
|
||||||
|
|
||||||
rects = {topleft, topright, bottomleft, bottomright};
|
rects = {topleft, topright, bottomleft, bottomright};
|
||||||
|
|
||||||
// add plugin's requested areas
|
// add plugin's requested areas
|
||||||
if (area == InputArea.FULLSCREEN || area == InputArea.DEFAULT) {
|
if (area == InputArea.FULLSCREEN || area == InputArea.DEFAULT) {
|
||||||
foreach (var rect in PluginManager.get_default ().regions) {
|
foreach (var rect in PluginManager.get_default ().regions) {
|
||||||
rects += rect;
|
rects += rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InputArea.NONE:
|
case InputArea.NONE:
|
||||||
default:
|
default:
|
||||||
#if HAS_MUTTER334
|
#if HAS_MUTTER334
|
||||||
unowned Meta.X11Display x11display = display.get_x11_display ();
|
unowned Meta.X11Display x11display = display.get_x11_display ();
|
||||||
x11display.clear_stage_input_region ();
|
x11display.clear_stage_input_region ();
|
||||||
#else
|
#else
|
||||||
display.empty_stage_input_region ();
|
display.empty_stage_input_region ();
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER334
|
#if HAS_MUTTER334
|
||||||
unowned Meta.X11Display x11display = display.get_x11_display ();
|
unowned Meta.X11Display x11display = display.get_x11_display ();
|
||||||
var xregion = X.Fixes.create_region (x11display.get_xdisplay (), rects);
|
var xregion = X.Fixes.create_region (x11display.get_xdisplay (), rects);
|
||||||
x11display.set_stage_input_region (xregion);
|
x11display.set_stage_input_region (xregion);
|
||||||
#else
|
#else
|
||||||
var xregion = X.Fixes.create_region (display.get_x11_display ().get_xdisplay (), rects);
|
var xregion = X.Fixes.create_region (display.get_x11_display ().get_xdisplay (), rects);
|
||||||
Util.set_stage_input_region (display, xregion);
|
Util.set_stage_input_region (display, xregion);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public static void set_input_area (Screen screen, InputArea area)
|
public static void set_input_area (Screen screen, InputArea area)
|
||||||
{
|
{
|
||||||
var display = screen.get_display ();
|
var display = screen.get_display ();
|
||||||
|
|
||||||
X.Xrectangle[] rects = {};
|
X.Xrectangle[] rects = {};
|
||||||
int width, height;
|
int width, height;
|
||||||
screen.get_size (out width, out height);
|
screen.get_size (out width, out height);
|
||||||
var geometry = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
var geometry = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
||||||
|
|
||||||
switch (area) {
|
switch (area) {
|
||||||
case InputArea.FULLSCREEN:
|
case InputArea.FULLSCREEN:
|
||||||
X.Xrectangle rect = {0, 0, (ushort)width, (ushort)height};
|
X.Xrectangle rect = {0, 0, (ushort)width, (ushort)height};
|
||||||
rects = {rect};
|
rects = {rect};
|
||||||
break;
|
break;
|
||||||
case InputArea.DEFAULT:
|
case InputArea.DEFAULT:
|
||||||
var schema = BehaviorSettings.get_default ().schema;
|
var schema = BehaviorSettings.get_default ().schema;
|
||||||
|
|
||||||
// if ActionType is NONE make it 0 sized
|
// if ActionType is NONE make it 0 sized
|
||||||
ushort tl_size = (schema.get_enum ("hotcorner-topleft") != ActionType.NONE ? 1 : 0);
|
ushort tl_size = (schema.get_enum ("hotcorner-topleft") != ActionType.NONE ? 1 : 0);
|
||||||
ushort tr_size = (schema.get_enum ("hotcorner-topright") != ActionType.NONE ? 1 : 0);
|
ushort tr_size = (schema.get_enum ("hotcorner-topright") != ActionType.NONE ? 1 : 0);
|
||||||
ushort bl_size = (schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE ? 1 : 0);
|
ushort bl_size = (schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE ? 1 : 0);
|
||||||
ushort br_size = (schema.get_enum ("hotcorner-bottomright") != ActionType.NONE ? 1 : 0);
|
ushort br_size = (schema.get_enum ("hotcorner-bottomright") != ActionType.NONE ? 1 : 0);
|
||||||
|
|
||||||
X.Xrectangle topleft = {(short)geometry.x, (short)geometry.y, tl_size, tl_size};
|
X.Xrectangle topleft = {(short)geometry.x, (short)geometry.y, tl_size, tl_size};
|
||||||
X.Xrectangle topright = {(short)(geometry.x + geometry.width - 1), (short)geometry.y, tr_size, tr_size};
|
X.Xrectangle topright = {(short)(geometry.x + geometry.width - 1), (short)geometry.y, tr_size, tr_size};
|
||||||
X.Xrectangle bottomleft = {(short)geometry.x, (short)(geometry.y + geometry.height - 1), bl_size, bl_size};
|
X.Xrectangle bottomleft = {(short)geometry.x, (short)(geometry.y + geometry.height - 1), bl_size, bl_size};
|
||||||
X.Xrectangle bottomright = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), br_size, br_size};
|
X.Xrectangle bottomright = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), br_size, br_size};
|
||||||
|
|
||||||
rects = {topleft, topright, bottomleft, bottomright};
|
rects = {topleft, topright, bottomleft, bottomright};
|
||||||
|
|
||||||
// add plugin's requested areas
|
// add plugin's requested areas
|
||||||
if (area == InputArea.FULLSCREEN || area == InputArea.DEFAULT) {
|
if (area == InputArea.FULLSCREEN || area == InputArea.DEFAULT) {
|
||||||
foreach (var rect in PluginManager.get_default ().regions) {
|
foreach (var rect in PluginManager.get_default ().regions) {
|
||||||
rects += rect;
|
rects += rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InputArea.NONE:
|
case InputArea.NONE:
|
||||||
default:
|
default:
|
||||||
screen.empty_stage_input_region ();
|
screen.empty_stage_input_region ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xregion = X.Fixes.create_region (display.get_xdisplay (), rects);
|
var xregion = X.Fixes.create_region (display.get_xdisplay (), rects);
|
||||||
screen.set_stage_input_region (xregion);
|
screen.set_stage_input_region (xregion);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a workspace at the given index. To ensure the workspace is not immediately
|
* Inserts a workspace at the given index. To ensure the workspace is not immediately
|
||||||
* removed again when in dynamic workspaces, the window is first placed on it.
|
* removed again when in dynamic workspaces, the window is first placed on it.
|
||||||
*
|
*
|
||||||
* @param index The index at which to insert the workspace
|
* @param index The index at which to insert the workspace
|
||||||
* @param new_window A window that should be moved to the new workspace
|
* @param new_window A window that should be moved to the new workspace
|
||||||
*/
|
*/
|
||||||
public static void insert_workspace_with_window (int index, Window new_window)
|
public static void insert_workspace_with_window (int index, Window new_window)
|
||||||
{
|
{
|
||||||
unowned WorkspaceManager workspace_manager = WorkspaceManager.get_default ();
|
unowned WorkspaceManager workspace_manager = WorkspaceManager.get_default ();
|
||||||
workspace_manager.freeze_remove ();
|
workspace_manager.freeze_remove ();
|
||||||
|
|
||||||
new_window.change_workspace_by_index (index, false);
|
new_window.change_workspace_by_index (index, false);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned List<WindowActor> actors = new_window.get_display ().get_window_actors ();
|
unowned List<WindowActor> actors = new_window.get_display ().get_window_actors ();
|
||||||
#else
|
#else
|
||||||
unowned List<WindowActor> actors = new_window.get_screen ().get_window_actors ();
|
unowned List<WindowActor> actors = new_window.get_screen ().get_window_actors ();
|
||||||
#endif
|
#endif
|
||||||
foreach (unowned Meta.WindowActor actor in actors) {
|
foreach (unowned Meta.WindowActor actor in actors) {
|
||||||
if (actor.is_destroyed ())
|
if (actor.is_destroyed ())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
unowned Meta.Window window = actor.get_meta_window ();
|
unowned Meta.Window window = actor.get_meta_window ();
|
||||||
if (window == new_window)
|
if (window == new_window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var current_index = window.get_workspace ().index ();
|
var current_index = window.get_workspace ().index ();
|
||||||
if (current_index >= index
|
if (current_index >= index
|
||||||
&& !window.on_all_workspaces) {
|
&& !window.on_all_workspaces) {
|
||||||
window.change_workspace_by_index (current_index + 1, true);
|
window.change_workspace_by_index (current_index + 1, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
workspace_manager.thaw_remove ();
|
workspace_manager.thaw_remove ();
|
||||||
workspace_manager.cleanup ();
|
workspace_manager.cleanup ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code ported from KWin present windows effect
|
// Code ported from KWin present windows effect
|
||||||
// https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
|
// https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
|
||||||
|
|
||||||
// constants, mainly for natural expo
|
// constants, mainly for natural expo
|
||||||
const int GAPS = 10;
|
const int GAPS = 10;
|
||||||
const int MAX_TRANSLATIONS = 100000;
|
const int MAX_TRANSLATIONS = 100000;
|
||||||
const int ACCURACY = 20;
|
const int ACCURACY = 20;
|
||||||
|
|
||||||
// some math utilities
|
// some math utilities
|
||||||
static int squared_distance (Gdk.Point a, Gdk.Point b)
|
static int squared_distance (Gdk.Point a, Gdk.Point b)
|
||||||
{
|
{
|
||||||
var k1 = b.x - a.x;
|
var k1 = b.x - a.x;
|
||||||
var k2 = b.y - a.y;
|
var k2 = b.y - a.y;
|
||||||
|
|
||||||
return k1*k1 + k2*k2;
|
return k1*k1 + k2*k2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Meta.Rectangle rect_adjusted (Meta.Rectangle rect, int dx1, int dy1, int dx2, int dy2)
|
static Meta.Rectangle rect_adjusted (Meta.Rectangle rect, int dx1, int dy1, int dx2, int dy2)
|
||||||
{
|
{
|
||||||
return {rect.x + dx1, rect.y + dy1, rect.width + (-dx1 + dx2), rect.height + (-dy1 + dy2)};
|
return {rect.x + dx1, rect.y + dy1, rect.width + (-dx1 + dx2), rect.height + (-dy1 + dy2)};
|
||||||
}
|
}
|
||||||
|
|
||||||
static Gdk.Point rect_center (Meta.Rectangle rect)
|
static Gdk.Point rect_center (Meta.Rectangle rect)
|
||||||
{
|
{
|
||||||
return {rect.x + rect.width / 2, rect.y + rect.height / 2};
|
return {rect.x + rect.width / 2, rect.y + rect.height / 2};
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct TilableWindow
|
public struct TilableWindow
|
||||||
{
|
{
|
||||||
Meta.Rectangle rect;
|
Meta.Rectangle rect;
|
||||||
void *id;
|
void *id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<TilableWindow?> calculate_grid_placement (Meta.Rectangle area,
|
public static List<TilableWindow?> calculate_grid_placement (Meta.Rectangle area,
|
||||||
List<TilableWindow?> windows)
|
List<TilableWindow?> windows)
|
||||||
{
|
{
|
||||||
uint window_count = windows.length ();
|
uint window_count = windows.length ();
|
||||||
int columns = (int)Math.ceil (Math.sqrt (window_count));
|
int columns = (int)Math.ceil (Math.sqrt (window_count));
|
||||||
int rows = (int)Math.ceil (window_count / (double)columns);
|
int rows = (int)Math.ceil (window_count / (double)columns);
|
||||||
|
|
||||||
// Assign slots
|
// Assign slots
|
||||||
int slot_width = area.width / columns;
|
int slot_width = area.width / columns;
|
||||||
int slot_height = area.height / rows;
|
int slot_height = area.height / rows;
|
||||||
|
|
||||||
TilableWindow?[] taken_slots = {};
|
TilableWindow?[] taken_slots = {};
|
||||||
taken_slots.resize (rows * columns);
|
taken_slots.resize (rows * columns);
|
||||||
|
|
||||||
// precalculate all slot centers
|
// precalculate all slot centers
|
||||||
Gdk.Point[] slot_centers = {};
|
Gdk.Point[] slot_centers = {};
|
||||||
slot_centers.resize (rows * columns);
|
slot_centers.resize (rows * columns);
|
||||||
for (int x = 0; x < columns; x++) {
|
for (int x = 0; x < columns; x++) {
|
||||||
for (int y = 0; y < rows; y++) {
|
for (int y = 0; y < rows; y++) {
|
||||||
slot_centers[x + y * columns] = {area.x + slot_width * x + slot_width / 2,
|
slot_centers[x + y * columns] = {area.x + slot_width * x + slot_width / 2,
|
||||||
area.y + slot_height * y + slot_height / 2};
|
area.y + slot_height * y + slot_height / 2};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign each window to the closest available slot
|
// Assign each window to the closest available slot
|
||||||
var tmplist = windows.copy ();
|
var tmplist = windows.copy ();
|
||||||
while (tmplist.length () > 0) {
|
while (tmplist.length () > 0) {
|
||||||
unowned List<unowned TilableWindow?> link = tmplist.nth (0);
|
unowned List<unowned TilableWindow?> link = tmplist.nth (0);
|
||||||
var window = link.data;
|
var window = link.data;
|
||||||
var rect = window.rect;
|
var rect = window.rect;
|
||||||
|
|
||||||
var slot_candidate = -1;
|
var slot_candidate = -1;
|
||||||
var slot_candidate_distance = int.MAX;
|
var slot_candidate_distance = int.MAX;
|
||||||
var pos = rect_center (rect);
|
var pos = rect_center (rect);
|
||||||
|
|
||||||
// all slots
|
// all slots
|
||||||
for (int i = 0; i < columns * rows; i++) {
|
for (int i = 0; i < columns * rows; i++) {
|
||||||
if (i > window_count - 1)
|
if (i > window_count - 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var dist = squared_distance (pos, slot_centers[i]);
|
var dist = squared_distance (pos, slot_centers[i]);
|
||||||
|
|
||||||
if (dist < slot_candidate_distance) {
|
if (dist < slot_candidate_distance) {
|
||||||
// window is interested in this slot
|
// window is interested in this slot
|
||||||
var occupier = taken_slots[i];
|
var occupier = taken_slots[i];
|
||||||
if (occupier == window)
|
if (occupier == window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (occupier == null || dist < squared_distance (rect_center (occupier.rect), slot_centers[i])) {
|
if (occupier == null || dist < squared_distance (rect_center (occupier.rect), slot_centers[i])) {
|
||||||
// either nobody lives here, or we're better - takeover the slot if it's our best
|
// either nobody lives here, or we're better - takeover the slot if it's our best
|
||||||
slot_candidate = i;
|
slot_candidate = i;
|
||||||
slot_candidate_distance = dist;
|
slot_candidate_distance = dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot_candidate == -1)
|
if (slot_candidate == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (taken_slots[slot_candidate] != null)
|
if (taken_slots[slot_candidate] != null)
|
||||||
tmplist.prepend (taken_slots[slot_candidate]);
|
tmplist.prepend (taken_slots[slot_candidate]);
|
||||||
|
|
||||||
tmplist.remove_link (link);
|
tmplist.remove_link (link);
|
||||||
taken_slots[slot_candidate] = window;
|
taken_slots[slot_candidate] = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new List<TilableWindow?> ();
|
var result = new List<TilableWindow?> ();
|
||||||
|
|
||||||
// see how many windows we have on the last row
|
// see how many windows we have on the last row
|
||||||
int left_over = (int)window_count - columns * (rows - 1);
|
int left_over = (int)window_count - columns * (rows - 1);
|
||||||
|
|
||||||
for (int slot = 0; slot < columns * rows; slot++) {
|
for (int slot = 0; slot < columns * rows; slot++) {
|
||||||
var window = taken_slots[slot];
|
var window = taken_slots[slot];
|
||||||
// some slots might be empty
|
// some slots might be empty
|
||||||
if (window == null)
|
if (window == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var rect = window.rect;
|
var rect = window.rect;
|
||||||
|
|
||||||
// Work out where the slot is
|
// Work out where the slot is
|
||||||
Meta.Rectangle target = {area.x + (slot % columns) * slot_width,
|
Meta.Rectangle target = {area.x + (slot % columns) * slot_width,
|
||||||
area.y + (slot / columns) * slot_height,
|
area.y + (slot / columns) * slot_height,
|
||||||
slot_width,
|
slot_width,
|
||||||
slot_height};
|
slot_height};
|
||||||
target = rect_adjusted (target, 10, 10, -10, -10);
|
target = rect_adjusted (target, 10, 10, -10, -10);
|
||||||
|
|
||||||
float scale;
|
float scale;
|
||||||
if (target.width / (double)rect.width < target.height / (double)rect.height) {
|
if (target.width / (double)rect.width < target.height / (double)rect.height) {
|
||||||
// Center vertically
|
// Center vertically
|
||||||
scale = target.width / (float)rect.width;
|
scale = target.width / (float)rect.width;
|
||||||
target.y += (target.height - (int)(rect.height * scale)) / 2;
|
target.y += (target.height - (int)(rect.height * scale)) / 2;
|
||||||
target.height = (int)Math.floorf (rect.height * scale);
|
target.height = (int)Math.floorf (rect.height * scale);
|
||||||
} else {
|
} else {
|
||||||
// Center horizontally
|
// Center horizontally
|
||||||
scale = target.height / (float)rect.height;
|
scale = target.height / (float)rect.height;
|
||||||
target.x += (target.width - (int)(rect.width * scale)) / 2;
|
target.x += (target.width - (int)(rect.width * scale)) / 2;
|
||||||
target.width = (int)Math.floorf (rect.width * scale);
|
target.width = (int)Math.floorf (rect.width * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't scale the windows too much
|
// Don't scale the windows too much
|
||||||
if (scale > 1.0) {
|
if (scale > 1.0) {
|
||||||
scale = 1.0f;
|
scale = 1.0f;
|
||||||
target = {rect_center (target).x - (int)Math.floorf (rect.width * scale) / 2,
|
target = {rect_center (target).x - (int)Math.floorf (rect.width * scale) / 2,
|
||||||
rect_center (target).y - (int)Math.floorf (rect.height * scale) / 2,
|
rect_center (target).y - (int)Math.floorf (rect.height * scale) / 2,
|
||||||
(int)Math.floorf (scale * rect.width),
|
(int)Math.floorf (scale * rect.width),
|
||||||
(int)Math.floorf (scale * rect.height)};
|
(int)Math.floorf (scale * rect.height)};
|
||||||
}
|
}
|
||||||
|
|
||||||
// put the last row in the center, if necessary
|
// put the last row in the center, if necessary
|
||||||
if (left_over != columns && slot >= columns * (rows - 1))
|
if (left_over != columns && slot >= columns * (rows - 1))
|
||||||
target.x += (columns - left_over) * slot_width / 2;
|
target.x += (columns - left_over) * slot_width / 2;
|
||||||
|
|
||||||
result.prepend ({ target, window.id });
|
result.prepend ({ target, window.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
result.reverse ();
|
result.reverse ();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline bool get_window_is_normal (Meta.Window window)
|
public static inline bool get_window_is_normal (Meta.Window window)
|
||||||
{
|
{
|
||||||
switch (window.get_window_type ()) {
|
switch (window.get_window_type ()) {
|
||||||
case Meta.WindowType.NORMAL:
|
case Meta.WindowType.NORMAL:
|
||||||
case Meta.WindowType.DIALOG:
|
case Meta.WindowType.DIALOG:
|
||||||
case Meta.WindowType.MODAL_DIALOG:
|
case Meta.WindowType.MODAL_DIALOG:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int get_ui_scaling_factor ()
|
public static int get_ui_scaling_factor ()
|
||||||
{
|
{
|
||||||
return Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
|
return Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,97 +17,97 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class KeyboardManager : Object
|
public class KeyboardManager : Object
|
||||||
{
|
{
|
||||||
static KeyboardManager? instance;
|
static KeyboardManager? instance;
|
||||||
static VariantType sources_variant_type;
|
static VariantType sources_variant_type;
|
||||||
|
|
||||||
public static void init (Meta.Display display)
|
public static void init (Meta.Display display)
|
||||||
{
|
{
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
instance = new KeyboardManager ();
|
instance = new KeyboardManager ();
|
||||||
|
|
||||||
display.modifiers_accelerator_activated.connect (instance.handle_modifiers_accelerator_activated);
|
display.modifiers_accelerator_activated.connect (instance.handle_modifiers_accelerator_activated);
|
||||||
}
|
}
|
||||||
|
|
||||||
static construct
|
static construct
|
||||||
{
|
{
|
||||||
sources_variant_type = new VariantType ("a(ss)");
|
sources_variant_type = new VariantType ("a(ss)");
|
||||||
}
|
}
|
||||||
|
|
||||||
GLib.Settings settings;
|
GLib.Settings settings;
|
||||||
|
|
||||||
KeyboardManager ()
|
KeyboardManager ()
|
||||||
{
|
{
|
||||||
Object ();
|
Object ();
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
var schema = GLib.SettingsSchemaSource.get_default ().lookup ("org.gnome.desktop.input-sources", true);
|
var schema = GLib.SettingsSchemaSource.get_default ().lookup ("org.gnome.desktop.input-sources", true);
|
||||||
if (schema == null)
|
if (schema == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
settings = new GLib.Settings.full (schema, null, null);
|
settings = new GLib.Settings.full (schema, null, null);
|
||||||
Signal.connect (settings, "changed", (Callback) set_keyboard_layout, this);
|
Signal.connect (settings, "changed", (Callback) set_keyboard_layout, this);
|
||||||
|
|
||||||
set_keyboard_layout (settings, "current");
|
set_keyboard_layout (settings, "current");
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (instance_pos = -1)]
|
[CCode (instance_pos = -1)]
|
||||||
bool handle_modifiers_accelerator_activated (Meta.Display display)
|
bool handle_modifiers_accelerator_activated (Meta.Display display)
|
||||||
{
|
{
|
||||||
display.ungrab_keyboard (display.get_current_time ());
|
display.ungrab_keyboard (display.get_current_time ());
|
||||||
|
|
||||||
var sources = settings.get_value ("sources");
|
var sources = settings.get_value ("sources");
|
||||||
if (!sources.is_of_type (sources_variant_type))
|
if (!sources.is_of_type (sources_variant_type))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var n_sources = (uint) sources.n_children ();
|
var n_sources = (uint) sources.n_children ();
|
||||||
if (n_sources < 2)
|
if (n_sources < 2)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var current = settings.get_uint ("current");
|
var current = settings.get_uint ("current");
|
||||||
settings.set_uint ("current", (current + 1) % n_sources);
|
settings.set_uint ("current", (current + 1) % n_sources);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (instance_pos = -1)]
|
[CCode (instance_pos = -1)]
|
||||||
void set_keyboard_layout (GLib.Settings settings, string key)
|
void set_keyboard_layout (GLib.Settings settings, string key)
|
||||||
{
|
{
|
||||||
if (!(key == "current" || key == "source" || key == "xkb-options"))
|
if (!(key == "current" || key == "source" || key == "xkb-options"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string layout = "us", variant = "", options = "";
|
string layout = "us", variant = "", options = "";
|
||||||
|
|
||||||
var sources = settings.get_value ("sources");
|
var sources = settings.get_value ("sources");
|
||||||
if (!sources.is_of_type (sources_variant_type))
|
if (!sources.is_of_type (sources_variant_type))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var current = settings.get_uint ("current");
|
var current = settings.get_uint ("current");
|
||||||
unowned string? type = null, name = null;
|
unowned string? type = null, name = null;
|
||||||
if (sources.n_children () > current)
|
if (sources.n_children () > current)
|
||||||
sources.get_child (current, "(&s&s)", out type, out name);
|
sources.get_child (current, "(&s&s)", out type, out name);
|
||||||
if (type == "xkb") {
|
if (type == "xkb") {
|
||||||
string[] arr = name.split ("+", 2);
|
string[] arr = name.split ("+", 2);
|
||||||
layout = arr[0];
|
layout = arr[0];
|
||||||
variant = arr[1] ?? "";
|
variant = arr[1] ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
var xkb_options = settings.get_strv ("xkb-options");
|
var xkb_options = settings.get_strv ("xkb-options");
|
||||||
if (xkb_options.length > 0)
|
if (xkb_options.length > 0)
|
||||||
options = string.joinv (",", xkb_options);
|
options = string.joinv (",", xkb_options);
|
||||||
|
|
||||||
// Needed to make common keybindings work on non-latin layouts
|
// Needed to make common keybindings work on non-latin layouts
|
||||||
if (layout != "us" || variant != "") {
|
if (layout != "us" || variant != "") {
|
||||||
layout = layout + ",us";
|
layout = layout + ",us";
|
||||||
variant = variant + ",";
|
variant = variant + ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
Meta.Backend.get_backend ().set_keymap (layout, variant, options);
|
Meta.Backend.get_backend ().set_keymap (layout, variant, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,47 +17,47 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
const OptionEntry[] OPTIONS = {
|
const OptionEntry[] OPTIONS = {
|
||||||
{ "version", 0, OptionFlags.NO_ARG, OptionArg.CALLBACK, (void*) print_version, "Print version", null },
|
{ "version", 0, OptionFlags.NO_ARG, OptionArg.CALLBACK, (void*) print_version, "Print version", null },
|
||||||
{ null }
|
{ null }
|
||||||
};
|
};
|
||||||
|
|
||||||
void print_version () {
|
void print_version () {
|
||||||
stdout.printf ("Gala %s\n", Config.VERSION);
|
stdout.printf ("Gala %s\n", Config.VERSION);
|
||||||
Meta.exit (Meta.ExitCode.SUCCESS);
|
Meta.exit (Meta.ExitCode.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int main (string[] args)
|
public static int main (string[] args)
|
||||||
{
|
{
|
||||||
unowned OptionContext ctx = Meta.get_option_context ();
|
unowned OptionContext ctx = Meta.get_option_context ();
|
||||||
ctx.add_main_entries (Gala.OPTIONS, null);
|
ctx.add_main_entries (Gala.OPTIONS, null);
|
||||||
try {
|
try {
|
||||||
ctx.parse (ref args);
|
ctx.parse (ref args);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
stderr.printf ("Error initializing: %s\n", e.message);
|
stderr.printf ("Error initializing: %s\n", e.message);
|
||||||
Meta.exit (Meta.ExitCode.ERROR);
|
Meta.exit (Meta.ExitCode.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
Meta.Plugin.manager_set_plugin_type (typeof (WindowManagerGala));
|
Meta.Plugin.manager_set_plugin_type (typeof (WindowManagerGala));
|
||||||
|
|
||||||
Meta.Util.set_wm_name ("Mutter(Gala)");
|
Meta.Util.set_wm_name ("Mutter(Gala)");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevent Meta.init () from causing gtk to load gail and at-bridge
|
* Prevent Meta.init () from causing gtk to load gail and at-bridge
|
||||||
* Taken from Gnome-Shell main.c
|
* Taken from Gnome-Shell main.c
|
||||||
*/
|
*/
|
||||||
GLib.Environment.set_variable ("NO_GAIL", "1", true);
|
GLib.Environment.set_variable ("NO_GAIL", "1", true);
|
||||||
GLib.Environment.set_variable ("NO_AT_BRIDGE", "1", true);
|
GLib.Environment.set_variable ("NO_AT_BRIDGE", "1", true);
|
||||||
Meta.init ();
|
Meta.init ();
|
||||||
GLib.Environment.unset_variable ("NO_GAIL");
|
GLib.Environment.unset_variable ("NO_GAIL");
|
||||||
GLib.Environment.unset_variable ("NO_AT_BRIDGE");
|
GLib.Environment.unset_variable ("NO_AT_BRIDGE");
|
||||||
|
|
||||||
Plank.Paths.initialize ("plank", Config.DATADIR + "/plank");
|
Plank.Paths.initialize ("plank", Config.DATADIR + "/plank");
|
||||||
|
|
||||||
// Force initialization of static fields in Utils class
|
// Force initialization of static fields in Utils class
|
||||||
// https://bugzilla.gnome.org/show_bug.cgi?id=543189
|
// https://bugzilla.gnome.org/show_bug.cgi?id=543189
|
||||||
typeof (Gala.Utils).class_ref ();
|
typeof (Gala.Utils).class_ref ();
|
||||||
|
|
||||||
return Meta.run ();
|
return Meta.run ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,113 +17,113 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
[DBus (name = "org.freedesktop.Notifications")]
|
[DBus (name = "org.freedesktop.Notifications")]
|
||||||
interface DBusNotifications : GLib.Object
|
interface DBusNotifications : GLib.Object
|
||||||
{
|
{
|
||||||
public abstract uint32 notify (string app_name, uint32 replaces_id, string app_icon, string summary,
|
public abstract uint32 notify (string app_name, uint32 replaces_id, string app_icon, string summary,
|
||||||
string body, string[] actions, HashTable<string, Variant> hints, int32 expire_timeout) throws DBusError, IOError;
|
string body, string[] actions, HashTable<string, Variant> hints, int32 expire_timeout) throws DBusError, IOError;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MediaFeedback : GLib.Object
|
public class MediaFeedback : GLib.Object
|
||||||
{
|
{
|
||||||
[Compact]
|
[Compact]
|
||||||
class Feedback
|
class Feedback
|
||||||
{
|
{
|
||||||
public string icon;
|
public string icon;
|
||||||
public int32 level;
|
public int32 level;
|
||||||
|
|
||||||
public Feedback (string _icon, int32 _level)
|
public Feedback (string _icon, int32 _level)
|
||||||
{
|
{
|
||||||
icon = _icon;
|
icon = _icon;
|
||||||
level = _level;
|
level = _level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static MediaFeedback? instance = null;
|
static MediaFeedback? instance = null;
|
||||||
static ThreadPool<Feedback>? pool = null;
|
static ThreadPool<Feedback>? pool = null;
|
||||||
|
|
||||||
public static void init ()
|
public static void init ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new MediaFeedback ();
|
instance = new MediaFeedback ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void send (string icon, int val)
|
public static void send (string icon, int val)
|
||||||
requires (instance != null && pool != null)
|
requires (instance != null && pool != null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
pool.add (new Feedback (icon, val));
|
pool.add (new Feedback (icon, val));
|
||||||
} catch (ThreadError e) {
|
} catch (ThreadError e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBusConnection? connection = null;
|
DBusConnection? connection = null;
|
||||||
DBusNotifications? notifications = null;
|
DBusNotifications? notifications = null;
|
||||||
uint dbus_name_owner_changed_signal_id = 0;
|
uint dbus_name_owner_changed_signal_id = 0;
|
||||||
uint32 notification_id = 0;
|
uint32 notification_id = 0;
|
||||||
|
|
||||||
MediaFeedback ()
|
MediaFeedback ()
|
||||||
{
|
{
|
||||||
Object ();
|
Object ();
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
pool = new ThreadPool<Feedback>.with_owned_data ((ThreadPoolFunc<Feedback>) send_feedback, 1, false);
|
pool = new ThreadPool<Feedback>.with_owned_data ((ThreadPoolFunc<Feedback>) send_feedback, 1, false);
|
||||||
} catch (ThreadError e) {
|
} catch (ThreadError e) {
|
||||||
critical ("%s", e.message);
|
critical ("%s", e.message);
|
||||||
pool = null;
|
pool = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connection = Bus.get_sync (BusType.SESSION);
|
connection = Bus.get_sync (BusType.SESSION);
|
||||||
dbus_name_owner_changed_signal_id = connection.signal_subscribe ("org.freedesktop.DBus", "org.freedesktop.DBus",
|
dbus_name_owner_changed_signal_id = connection.signal_subscribe ("org.freedesktop.DBus", "org.freedesktop.DBus",
|
||||||
"NameOwnerChanged", "/org/freedesktop/DBus", null, DBusSignalFlags.NONE, (DBusSignalCallback) handle_name_owner_changed);
|
"NameOwnerChanged", "/org/freedesktop/DBus", null, DBusSignalFlags.NONE, (DBusSignalCallback) handle_name_owner_changed);
|
||||||
} catch (IOError e) {
|
} catch (IOError e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (instance_pos = -1)]
|
[CCode (instance_pos = -1)]
|
||||||
void handle_name_owner_changed (DBusConnection connection, string sender_name, string object_path,
|
void handle_name_owner_changed (DBusConnection connection, string sender_name, string object_path,
|
||||||
string interface_name, string signal_name, Variant parameters)
|
string interface_name, string signal_name, Variant parameters)
|
||||||
{
|
{
|
||||||
string name, before, after;
|
string name, before, after;
|
||||||
parameters.get ("(sss)", out name, out before, out after);
|
parameters.get ("(sss)", out name, out before, out after);
|
||||||
|
|
||||||
if (name != "org.freedesktop.Notifications")
|
if (name != "org.freedesktop.Notifications")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (after != "" && before == "")
|
if (after != "" && before == "")
|
||||||
new Thread<void*> (null, () => {
|
new Thread<void*> (null, () => {
|
||||||
lock (notifications) {
|
lock (notifications) {
|
||||||
try {
|
try {
|
||||||
notifications = connection.get_proxy_sync<DBusNotifications> ("org.freedesktop.Notifications",
|
notifications = connection.get_proxy_sync<DBusNotifications> ("org.freedesktop.Notifications",
|
||||||
"/org/freedesktop/Notifications", DBusProxyFlags.NONE);
|
"/org/freedesktop/Notifications", DBusProxyFlags.NONE);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
notifications = null;
|
notifications = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
else if (before != "" && after == "")
|
else if (before != "" && after == "")
|
||||||
lock (notifications) {
|
lock (notifications) {
|
||||||
notifications = null;
|
notifications = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (instance_pos = -1)]
|
[CCode (instance_pos = -1)]
|
||||||
void send_feedback (owned Feedback feedback)
|
void send_feedback (owned Feedback feedback)
|
||||||
{
|
{
|
||||||
var hints = new GLib.HashTable<string, Variant> (null, null);
|
var hints = new GLib.HashTable<string, Variant> (null, null);
|
||||||
hints.set ("x-canonical-private-synchronous", new Variant.string ("gala-feedback"));
|
hints.set ("x-canonical-private-synchronous", new Variant.string ("gala-feedback"));
|
||||||
hints.set ("value", new Variant.int32 (feedback.level));
|
hints.set ("value", new Variant.int32 (feedback.level));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
notification_id = notifications.notify ("gala-feedback", notification_id, feedback.icon, "", "", {}, hints, 2000);
|
notification_id = notifications.notify ("gala-feedback", notification_id, feedback.icon, "", "", {}, hints, 2000);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
critical ("%s", e.message);
|
critical ("%s", e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,217 +17,217 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
delegate PluginInfo RegisterPluginFunction ();
|
delegate PluginInfo RegisterPluginFunction ();
|
||||||
|
|
||||||
public class PluginManager : Object
|
public class PluginManager : Object
|
||||||
{
|
{
|
||||||
static PluginManager? instance = null;
|
static PluginManager? instance = null;
|
||||||
public static unowned PluginManager get_default ()
|
public static unowned PluginManager get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new PluginManager ();
|
instance = new PluginManager ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public signal void regions_changed ();
|
public signal void regions_changed ();
|
||||||
|
|
||||||
public bool initialized { get; private set; default = false; }
|
public bool initialized { get; private set; default = false; }
|
||||||
|
|
||||||
public X.Xrectangle[] regions { get; private set; }
|
public X.Xrectangle[] regions { get; private set; }
|
||||||
|
|
||||||
public string? window_switcher_provider { get; private set; default = null; }
|
public string? window_switcher_provider { get; private set; default = null; }
|
||||||
public string? desktop_provider { get; private set; default = null; }
|
public string? desktop_provider { get; private set; default = null; }
|
||||||
public string? window_overview_provider { get; private set; default = null; }
|
public string? window_overview_provider { get; private set; default = null; }
|
||||||
public string? workspace_view_provider { get; private set; default = null; }
|
public string? workspace_view_provider { get; private set; default = null; }
|
||||||
|
|
||||||
HashTable<string,Plugin> plugins;
|
HashTable<string,Plugin> plugins;
|
||||||
File plugin_dir;
|
File plugin_dir;
|
||||||
|
|
||||||
WindowManager? wm = null;
|
WindowManager? wm = null;
|
||||||
|
|
||||||
Gee.LinkedList<PluginInfo?> load_later_plugins;
|
Gee.LinkedList<PluginInfo?> load_later_plugins;
|
||||||
|
|
||||||
PluginManager ()
|
PluginManager ()
|
||||||
{
|
{
|
||||||
plugins = new HashTable<string,Plugin> (str_hash, str_equal);
|
plugins = new HashTable<string,Plugin> (str_hash, str_equal);
|
||||||
load_later_plugins = new Gee.LinkedList<PluginInfo?> ();
|
load_later_plugins = new Gee.LinkedList<PluginInfo?> ();
|
||||||
|
|
||||||
if (!Module.supported ()) {
|
if (!Module.supported ()) {
|
||||||
warning ("Modules are not supported on this platform");
|
warning ("Modules are not supported on this platform");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_dir = File.new_for_path (Config.PLUGINDIR);
|
plugin_dir = File.new_for_path (Config.PLUGINDIR);
|
||||||
if (!plugin_dir.query_exists ())
|
if (!plugin_dir.query_exists ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var enumerator = plugin_dir.enumerate_children (FileAttribute.STANDARD_NAME +
|
var enumerator = plugin_dir.enumerate_children (FileAttribute.STANDARD_NAME +
|
||||||
"," + FileAttribute.STANDARD_CONTENT_TYPE, 0);
|
"," + FileAttribute.STANDARD_CONTENT_TYPE, 0);
|
||||||
FileInfo info;
|
FileInfo info;
|
||||||
while ((info = enumerator.next_file ()) != null) {
|
while ((info = enumerator.next_file ()) != null) {
|
||||||
if (info.get_content_type () == "application/x-sharedlib")
|
if (info.get_content_type () == "application/x-sharedlib")
|
||||||
load_module (info.get_name ());
|
load_module (info.get_name ());
|
||||||
}
|
}
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
warning (e.message);
|
warning (e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
plugin_dir.monitor_directory (FileMonitorFlags.NONE, null).changed.connect ((file, other_file, type) => {
|
plugin_dir.monitor_directory (FileMonitorFlags.NONE, null).changed.connect ((file, other_file, type) => {
|
||||||
if (type == FileMonitorEvent.CREATED) {
|
if (type == FileMonitorEvent.CREATED) {
|
||||||
load_module (file.get_basename ());
|
load_module (file.get_basename ());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
warning (e.message);
|
warning (e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load_module (string plugin_name)
|
bool load_module (string plugin_name)
|
||||||
{
|
{
|
||||||
var path = Module.build_path (plugin_dir.get_path (), plugin_name);
|
var path = Module.build_path (plugin_dir.get_path (), plugin_name);
|
||||||
var module = Module.open (path, ModuleFlags.BIND_LOCAL);
|
var module = Module.open (path, ModuleFlags.BIND_LOCAL);
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
warning (Module.error ());
|
warning (Module.error ());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* function;
|
void* function;
|
||||||
module.symbol ("register_plugin", out function);
|
module.symbol ("register_plugin", out function);
|
||||||
if (function == null) {
|
if (function == null) {
|
||||||
warning ("%s failed to register: register_plugin() function not found", plugin_name);
|
warning ("%s failed to register: register_plugin() function not found", plugin_name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unowned RegisterPluginFunction register = (RegisterPluginFunction)function;
|
unowned RegisterPluginFunction register = (RegisterPluginFunction)function;
|
||||||
|
|
||||||
var info = register ();
|
var info = register ();
|
||||||
if (info.plugin_type.is_a (typeof (Plugin)) == false) {
|
if (info.plugin_type.is_a (typeof (Plugin)) == false) {
|
||||||
warning ("%s does not return a class of type Plugin", plugin_name);
|
warning ("%s does not return a class of type Plugin", plugin_name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_provides (info.name, info.provides)) {
|
if (!check_provides (info.name, info.provides)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.module_name = plugin_name;
|
info.module_name = plugin_name;
|
||||||
module.make_resident ();
|
module.make_resident ();
|
||||||
|
|
||||||
if (info.load_priority == LoadPriority.DEFERRED && !initialized) {
|
if (info.load_priority == LoadPriority.DEFERRED && !initialized) {
|
||||||
load_later_plugins.add (info);
|
load_later_plugins.add (info);
|
||||||
} else {
|
} else {
|
||||||
load_plugin_class (info);
|
load_plugin_class (info);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_plugin_class (PluginInfo info)
|
void load_plugin_class (PluginInfo info)
|
||||||
{
|
{
|
||||||
var plugin = (Plugin)Object.@new (info.plugin_type);
|
var plugin = (Plugin)Object.@new (info.plugin_type);
|
||||||
plugins.set (info.module_name, plugin);
|
plugins.set (info.module_name, plugin);
|
||||||
|
|
||||||
debug ("Loaded plugin %s (%s)", info.name, info.module_name);
|
debug ("Loaded plugin %s (%s)", info.name, info.module_name);
|
||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
initialize_plugin (info.module_name, plugin);
|
initialize_plugin (info.module_name, plugin);
|
||||||
recalculate_regions ();
|
recalculate_regions ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_plugin (string plugin_name, Plugin plugin)
|
void initialize_plugin (string plugin_name, Plugin plugin)
|
||||||
{
|
{
|
||||||
plugin.initialize (wm);
|
plugin.initialize (wm);
|
||||||
plugin.region_changed.connect (recalculate_regions);
|
plugin.region_changed.connect (recalculate_regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_provides (string name, PluginFunction provides)
|
bool check_provides (string name, PluginFunction provides)
|
||||||
{
|
{
|
||||||
var message = "Plugins %s and %s both provide %s functionality, using first one only";
|
var message = "Plugins %s and %s both provide %s functionality, using first one only";
|
||||||
switch (provides) {
|
switch (provides) {
|
||||||
case PluginFunction.WORKSPACE_VIEW:
|
case PluginFunction.WORKSPACE_VIEW:
|
||||||
if (workspace_view_provider != null) {
|
if (workspace_view_provider != null) {
|
||||||
warning (message, workspace_view_provider, name, "workspace view");
|
warning (message, workspace_view_provider, name, "workspace view");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
workspace_view_provider = name;
|
workspace_view_provider = name;
|
||||||
return true;
|
return true;
|
||||||
case PluginFunction.WINDOW_OVERVIEW:
|
case PluginFunction.WINDOW_OVERVIEW:
|
||||||
if (window_overview_provider != null) {
|
if (window_overview_provider != null) {
|
||||||
warning (message, window_overview_provider, name, "window overview");
|
warning (message, window_overview_provider, name, "window overview");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
window_overview_provider = name;
|
window_overview_provider = name;
|
||||||
return true;
|
return true;
|
||||||
case PluginFunction.DESKTOP:
|
case PluginFunction.DESKTOP:
|
||||||
if (desktop_provider != null) {
|
if (desktop_provider != null) {
|
||||||
warning (message, desktop_provider, name, "desktop");
|
warning (message, desktop_provider, name, "desktop");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
desktop_provider = name;
|
desktop_provider = name;
|
||||||
return true;
|
return true;
|
||||||
case PluginFunction.WINDOW_SWITCHER:
|
case PluginFunction.WINDOW_SWITCHER:
|
||||||
if (window_switcher_provider != null) {
|
if (window_switcher_provider != null) {
|
||||||
warning (message, window_switcher_provider, name, "window switcher");
|
warning (message, window_switcher_provider, name, "window switcher");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
window_switcher_provider = name;
|
window_switcher_provider = name;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize (WindowManager _wm)
|
public void initialize (WindowManager _wm)
|
||||||
{
|
{
|
||||||
wm = _wm;
|
wm = _wm;
|
||||||
|
|
||||||
plugins.@foreach (initialize_plugin);
|
plugins.@foreach (initialize_plugin);
|
||||||
recalculate_regions ();
|
recalculate_regions ();
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load_waiting_plugins ()
|
public void load_waiting_plugins ()
|
||||||
{
|
{
|
||||||
foreach (var info in load_later_plugins) {
|
foreach (var info in load_later_plugins) {
|
||||||
load_plugin_class (info);
|
load_plugin_class (info);
|
||||||
}
|
}
|
||||||
|
|
||||||
load_later_plugins.clear ();
|
load_later_plugins.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin? get_plugin (string id)
|
public Plugin? get_plugin (string id)
|
||||||
{
|
{
|
||||||
return plugins.lookup (id);
|
return plugins.lookup (id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over all plugins and grab their regions, update the regions
|
* Iterate over all plugins and grab their regions, update the regions
|
||||||
* array accordingly and emit the regions_changed signal.
|
* array accordingly and emit the regions_changed signal.
|
||||||
*/
|
*/
|
||||||
void recalculate_regions ()
|
void recalculate_regions ()
|
||||||
{
|
{
|
||||||
X.Xrectangle[] regions = {};
|
X.Xrectangle[] regions = {};
|
||||||
|
|
||||||
plugins.@foreach ((name, plugin) => {
|
plugins.@foreach ((name, plugin) => {
|
||||||
foreach (var region in plugin.region) {
|
foreach (var region in plugin.region) {
|
||||||
X.Xrectangle rect = {
|
X.Xrectangle rect = {
|
||||||
(short) region.x,
|
(short) region.x,
|
||||||
(short) region.y,
|
(short) region.y,
|
||||||
(ushort) region.width,
|
(ushort) region.width,
|
||||||
(ushort) region.height
|
(ushort) region.height
|
||||||
};
|
};
|
||||||
|
|
||||||
regions += rect;
|
regions += rect;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.regions = regions;
|
this.regions = regions;
|
||||||
regions_changed ();
|
regions_changed ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
[DBus (name = "org.gnome.ScreenSaver")]
|
[DBus (name = "org.gnome.ScreenSaver")]
|
||||||
public interface ScreenSaver : GLib.Object
|
public interface ScreenSaver : GLib.Object
|
||||||
{
|
{
|
||||||
public abstract bool get_active () throws DBusError, IOError;
|
public abstract bool get_active () throws DBusError, IOError;
|
||||||
public signal void active_changed (bool active);
|
public signal void active_changed (bool active);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,357 +17,357 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
const string EXTENSION = ".png";
|
const string EXTENSION = ".png";
|
||||||
const int UNCONCEAL_TEXT_TIMEOUT = 2000;
|
const int UNCONCEAL_TEXT_TIMEOUT = 2000;
|
||||||
|
|
||||||
[DBus (name="org.gnome.Shell.Screenshot")]
|
[DBus (name="org.gnome.Shell.Screenshot")]
|
||||||
public class ScreenshotManager : Object
|
public class ScreenshotManager : Object
|
||||||
{
|
{
|
||||||
static ScreenshotManager? instance;
|
static ScreenshotManager? instance;
|
||||||
|
|
||||||
[DBus (visible = false)]
|
[DBus (visible = false)]
|
||||||
public static unowned ScreenshotManager init (WindowManager wm)
|
public static unowned ScreenshotManager init (WindowManager wm)
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new ScreenshotManager (wm);
|
instance = new ScreenshotManager (wm);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowManager wm;
|
WindowManager wm;
|
||||||
Settings desktop_settings;
|
Settings desktop_settings;
|
||||||
|
|
||||||
string prev_font_regular;
|
string prev_font_regular;
|
||||||
string prev_font_document;
|
string prev_font_document;
|
||||||
string prev_font_mono;
|
string prev_font_mono;
|
||||||
uint conceal_timeout;
|
uint conceal_timeout;
|
||||||
|
|
||||||
construct {
|
construct {
|
||||||
desktop_settings = new Settings ("org.gnome.desktop.interface");
|
desktop_settings = new Settings ("org.gnome.desktop.interface");
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenshotManager (WindowManager _wm)
|
ScreenshotManager (WindowManager _wm)
|
||||||
{
|
{
|
||||||
wm = _wm;
|
wm = _wm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flash_area (int x, int y, int width, int height) throws DBusError, IOError
|
public void flash_area (int x, int y, int width, int height) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
debug ("Flashing area");
|
debug ("Flashing area");
|
||||||
|
|
||||||
double[] keyframes = { 0.3f, 0.8f };
|
double[] keyframes = { 0.3f, 0.8f };
|
||||||
GLib.Value[] values = { 180U, 0U };
|
GLib.Value[] values = { 180U, 0U };
|
||||||
|
|
||||||
var transition = new Clutter.KeyframeTransition ("opacity");
|
var transition = new Clutter.KeyframeTransition ("opacity");
|
||||||
transition.duration = 200;
|
transition.duration = 200;
|
||||||
transition.remove_on_complete = true;
|
transition.remove_on_complete = true;
|
||||||
transition.progress_mode = Clutter.AnimationMode.LINEAR;
|
transition.progress_mode = Clutter.AnimationMode.LINEAR;
|
||||||
transition.set_key_frames (keyframes);
|
transition.set_key_frames (keyframes);
|
||||||
transition.set_values (values);
|
transition.set_values (values);
|
||||||
transition.set_to_value (0.0f);
|
transition.set_to_value (0.0f);
|
||||||
|
|
||||||
var flash_actor = new Clutter.Actor ();
|
var flash_actor = new Clutter.Actor ();
|
||||||
flash_actor.set_size (width, height);
|
flash_actor.set_size (width, height);
|
||||||
flash_actor.set_position (x, y);
|
flash_actor.set_position (x, y);
|
||||||
flash_actor.set_background_color (Clutter.Color.get_static (Clutter.StaticColor.WHITE));
|
flash_actor.set_background_color (Clutter.Color.get_static (Clutter.StaticColor.WHITE));
|
||||||
flash_actor.set_opacity (0);
|
flash_actor.set_opacity (0);
|
||||||
flash_actor.transitions_completed.connect ((actor) => {
|
flash_actor.transitions_completed.connect ((actor) => {
|
||||||
wm.top_window_group.remove_child (actor);
|
wm.top_window_group.remove_child (actor);
|
||||||
actor.destroy ();
|
actor.destroy ();
|
||||||
});
|
});
|
||||||
|
|
||||||
wm.top_window_group.add_child (flash_actor);
|
wm.top_window_group.add_child (flash_actor);
|
||||||
flash_actor.add_transition ("flash", transition);
|
flash_actor.add_transition ("flash", transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void screenshot (bool include_cursor, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
public async void screenshot (bool include_cursor, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
debug ("Taking screenshot");
|
debug ("Taking screenshot");
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
wm.get_display ().get_size (out width, out height);
|
wm.get_display ().get_size (out width, out height);
|
||||||
#else
|
#else
|
||||||
wm.get_screen ().get_size (out width, out height);
|
wm.get_screen ().get_size (out width, out height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var image = take_screenshot (0, 0, width, height, include_cursor);
|
var image = take_screenshot (0, 0, width, height, include_cursor);
|
||||||
unconceal_text ();
|
unconceal_text ();
|
||||||
|
|
||||||
if (flash) {
|
if (flash) {
|
||||||
flash_area (0, 0, width, height);
|
flash_area (0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
success = yield save_image (image, filename, out filename_used);
|
success = yield save_image (image, filename, out filename_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void screenshot_area (int x, int y, int width, int height, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
public async void screenshot_area (int x, int y, int width, int height, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
yield screenshot_area_with_cursor (x, y, width, height, false, flash, filename, out success, out filename_used);
|
yield screenshot_area_with_cursor (x, y, width, height, false, flash, filename, out success, out filename_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void screenshot_area_with_cursor (int x, int y, int width, int height, bool include_cursor, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
public async void screenshot_area_with_cursor (int x, int y, int width, int height, bool include_cursor, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
debug ("Taking area screenshot");
|
debug ("Taking area screenshot");
|
||||||
|
|
||||||
yield wait_stage_repaint ();
|
yield wait_stage_repaint ();
|
||||||
|
|
||||||
var image = take_screenshot (x, y, width, height, include_cursor);
|
var image = take_screenshot (x, y, width, height, include_cursor);
|
||||||
unconceal_text ();
|
unconceal_text ();
|
||||||
|
|
||||||
if (flash) {
|
if (flash) {
|
||||||
flash_area (x, y, width, height);
|
flash_area (x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
success = yield save_image (image, filename, out filename_used);
|
success = yield save_image (image, filename, out filename_used);
|
||||||
if (!success)
|
if (!success)
|
||||||
throw new DBusError.FAILED ("Failed to save image");
|
throw new DBusError.FAILED ("Failed to save image");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void screenshot_window (bool include_frame, bool include_cursor, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
public async void screenshot_window (bool include_frame, bool include_cursor, bool flash, string filename, out bool success, out string filename_used) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
debug ("Taking window screenshot");
|
debug ("Taking window screenshot");
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var window = wm.get_display ().get_focus_window ();
|
var window = wm.get_display ().get_focus_window ();
|
||||||
#else
|
#else
|
||||||
var window = wm.get_screen ().get_display ().get_focus_window ();
|
var window = wm.get_screen ().get_display ().get_focus_window ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (window == null) {
|
if (window == null) {
|
||||||
unconceal_text ();
|
unconceal_text ();
|
||||||
throw new DBusError.FAILED ("Cannot find active window");
|
throw new DBusError.FAILED ("Cannot find active window");
|
||||||
}
|
}
|
||||||
|
|
||||||
var window_actor = (Meta.WindowActor) window.get_compositor_private ();
|
var window_actor = (Meta.WindowActor) window.get_compositor_private ();
|
||||||
unowned Meta.ShapedTexture window_texture = (Meta.ShapedTexture) window_actor.get_texture ();
|
unowned Meta.ShapedTexture window_texture = (Meta.ShapedTexture) window_actor.get_texture ();
|
||||||
|
|
||||||
float actor_x, actor_y;
|
float actor_x, actor_y;
|
||||||
window_actor.get_position (out actor_x, out actor_y);
|
window_actor.get_position (out actor_x, out actor_y);
|
||||||
|
|
||||||
var rect = window.get_frame_rect ();
|
var rect = window.get_frame_rect ();
|
||||||
if (include_frame) {
|
if (include_frame) {
|
||||||
rect = window.frame_rect_to_client_rect (rect);
|
rect = window.frame_rect_to_client_rect (rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cairo.RectangleInt clip = { rect.x - (int) actor_x, rect.y - (int) actor_y, rect.width, rect.height };
|
Cairo.RectangleInt clip = { rect.x - (int) actor_x, rect.y - (int) actor_y, rect.width, rect.height };
|
||||||
var image = (Cairo.ImageSurface) window_texture.get_image (clip);
|
var image = (Cairo.ImageSurface) window_texture.get_image (clip);
|
||||||
if (include_cursor) {
|
if (include_cursor) {
|
||||||
image = composite_stage_cursor (image, { rect.x, rect.y, rect.width, rect.height });
|
image = composite_stage_cursor (image, { rect.x, rect.y, rect.width, rect.height });
|
||||||
}
|
}
|
||||||
|
|
||||||
unconceal_text ();
|
unconceal_text ();
|
||||||
|
|
||||||
if (flash) {
|
if (flash) {
|
||||||
flash_area (rect.x, rect.y, rect.width, rect.height);
|
flash_area (rect.x, rect.y, rect.width, rect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
success = yield save_image (image, filename, out filename_used);
|
success = yield save_image (image, filename, out filename_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void select_area (out int x, out int y, out int width, out int height) throws DBusError, IOError
|
public async void select_area (out int x, out int y, out int width, out int height) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
var selection_area = new SelectionArea (wm);
|
var selection_area = new SelectionArea (wm);
|
||||||
selection_area.closed.connect (() => Idle.add (select_area.callback));
|
selection_area.closed.connect (() => Idle.add (select_area.callback));
|
||||||
wm.ui_group.add (selection_area);
|
wm.ui_group.add (selection_area);
|
||||||
selection_area.start_selection ();
|
selection_area.start_selection ();
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
selection_area.destroy ();
|
selection_area.destroy ();
|
||||||
|
|
||||||
if (selection_area.cancelled) {
|
if (selection_area.cancelled) {
|
||||||
throw new GLib.IOError.CANCELLED ("Operation was cancelled");
|
throw new GLib.IOError.CANCELLED ("Operation was cancelled");
|
||||||
}
|
}
|
||||||
|
|
||||||
yield wait_stage_repaint ();
|
yield wait_stage_repaint ();
|
||||||
selection_area.get_selection_rectangle (out x, out y, out width, out height);
|
selection_area.get_selection_rectangle (out x, out y, out width, out height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unconceal_text ()
|
private void unconceal_text ()
|
||||||
{
|
{
|
||||||
if (conceal_timeout == 0) {
|
if (conceal_timeout == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
desktop_settings.set_string ("font-name", prev_font_regular);
|
desktop_settings.set_string ("font-name", prev_font_regular);
|
||||||
desktop_settings.set_string ("monospace-font-name", prev_font_mono);
|
desktop_settings.set_string ("monospace-font-name", prev_font_mono);
|
||||||
desktop_settings.set_string ("document-font-name", prev_font_document);
|
desktop_settings.set_string ("document-font-name", prev_font_document);
|
||||||
|
|
||||||
Source.remove (conceal_timeout);
|
Source.remove (conceal_timeout);
|
||||||
conceal_timeout = 0;
|
conceal_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void conceal_text () throws DBusError, IOError
|
public async void conceal_text () throws DBusError, IOError
|
||||||
{
|
{
|
||||||
if (conceal_timeout > 0) {
|
if (conceal_timeout > 0) {
|
||||||
Source.remove (conceal_timeout);
|
Source.remove (conceal_timeout);
|
||||||
} else {
|
} else {
|
||||||
prev_font_regular = desktop_settings.get_string ("font-name");
|
prev_font_regular = desktop_settings.get_string ("font-name");
|
||||||
prev_font_mono = desktop_settings.get_string ("monospace-font-name");
|
prev_font_mono = desktop_settings.get_string ("monospace-font-name");
|
||||||
prev_font_document = desktop_settings.get_string ("document-font-name");
|
prev_font_document = desktop_settings.get_string ("document-font-name");
|
||||||
|
|
||||||
desktop_settings.set_string ("font-name", "Redacted Script Regular 9");
|
desktop_settings.set_string ("font-name", "Redacted Script Regular 9");
|
||||||
desktop_settings.set_string ("monospace-font-name", "Redacted Script Light 10");
|
desktop_settings.set_string ("monospace-font-name", "Redacted Script Light 10");
|
||||||
desktop_settings.set_string ("document-font-name", "Redacted Script Regular 10");
|
desktop_settings.set_string ("document-font-name", "Redacted Script Regular 10");
|
||||||
}
|
}
|
||||||
|
|
||||||
conceal_timeout = Timeout.add (UNCONCEAL_TEXT_TIMEOUT, () => {
|
conceal_timeout = Timeout.add (UNCONCEAL_TEXT_TIMEOUT, () => {
|
||||||
unconceal_text ();
|
unconceal_text ();
|
||||||
return Source.REMOVE;
|
return Source.REMOVE;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static string find_target_path ()
|
static string find_target_path ()
|
||||||
{
|
{
|
||||||
// Try to create dedicated "Screenshots" subfolder in PICTURES xdg-dir
|
// Try to create dedicated "Screenshots" subfolder in PICTURES xdg-dir
|
||||||
unowned string? base_path = Environment.get_user_special_dir (UserDirectory.PICTURES);
|
unowned string? base_path = Environment.get_user_special_dir (UserDirectory.PICTURES);
|
||||||
if (base_path != null && FileUtils.test (base_path, FileTest.EXISTS)) {
|
if (base_path != null && FileUtils.test (base_path, FileTest.EXISTS)) {
|
||||||
var path = Path.build_path (Path.DIR_SEPARATOR_S, base_path, _("Screenshots"));
|
var path = Path.build_path (Path.DIR_SEPARATOR_S, base_path, _("Screenshots"));
|
||||||
if (FileUtils.test (path, FileTest.EXISTS)) {
|
if (FileUtils.test (path, FileTest.EXISTS)) {
|
||||||
return path;
|
return path;
|
||||||
} else if (DirUtils.create (path, 0755) == 0) {
|
} else if (DirUtils.create (path, 0755) == 0) {
|
||||||
return path;
|
return path;
|
||||||
} else {
|
} else {
|
||||||
return base_path;
|
return base_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Environment.get_home_dir ();
|
return Environment.get_home_dir ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async bool save_image (Cairo.ImageSurface image, string filename, out string used_filename)
|
static async bool save_image (Cairo.ImageSurface image, string filename, out string used_filename)
|
||||||
{
|
{
|
||||||
used_filename = filename;
|
used_filename = filename;
|
||||||
|
|
||||||
// We only alter non absolute filename because absolute
|
// We only alter non absolute filename because absolute
|
||||||
// filename is used for temp clipboard file and shouldn't be changed
|
// filename is used for temp clipboard file and shouldn't be changed
|
||||||
if (!Path.is_absolute (used_filename)) {
|
if (!Path.is_absolute (used_filename)) {
|
||||||
if (!used_filename.has_suffix (EXTENSION)) {
|
if (!used_filename.has_suffix (EXTENSION)) {
|
||||||
used_filename = used_filename.concat (EXTENSION);
|
used_filename = used_filename.concat (EXTENSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
var scale_factor = InternalUtils.get_ui_scaling_factor ();
|
var scale_factor = InternalUtils.get_ui_scaling_factor ();
|
||||||
if (scale_factor > 1) {
|
if (scale_factor > 1) {
|
||||||
var scale_pos = -EXTENSION.length;
|
var scale_pos = -EXTENSION.length;
|
||||||
used_filename = used_filename.splice (scale_pos, scale_pos, "@%ix".printf (scale_factor));
|
used_filename = used_filename.splice (scale_pos, scale_pos, "@%ix".printf (scale_factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = find_target_path ();
|
var path = find_target_path ();
|
||||||
used_filename = Path.build_filename (path, used_filename, null);
|
used_filename = Path.build_filename (path, used_filename, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var screenshot = Gdk.pixbuf_get_from_surface (image, 0, 0, image.get_width (), image.get_height ());
|
var screenshot = Gdk.pixbuf_get_from_surface (image, 0, 0, image.get_width (), image.get_height ());
|
||||||
var file = File.new_for_path (used_filename);
|
var file = File.new_for_path (used_filename);
|
||||||
FileIOStream stream;
|
FileIOStream stream;
|
||||||
if (file.query_exists ()) {
|
if (file.query_exists ()) {
|
||||||
stream = yield file.open_readwrite_async (FileCreateFlags.NONE);
|
stream = yield file.open_readwrite_async (FileCreateFlags.NONE);
|
||||||
} else {
|
} else {
|
||||||
stream = yield file.create_readwrite_async (FileCreateFlags.NONE);
|
stream = yield file.create_readwrite_async (FileCreateFlags.NONE);
|
||||||
}
|
}
|
||||||
yield screenshot.save_to_stream_async (stream.output_stream, "png");
|
yield screenshot.save_to_stream_async (stream.output_stream, "png");
|
||||||
return true;
|
return true;
|
||||||
} catch (GLib.Error e) {
|
} catch (GLib.Error e) {
|
||||||
warning ("could not save file: %s", e.message);
|
warning ("could not save file: %s", e.message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cairo.ImageSurface take_screenshot (int x, int y, int width, int height, bool include_cursor)
|
Cairo.ImageSurface take_screenshot (int x, int y, int width, int height, bool include_cursor)
|
||||||
{
|
{
|
||||||
Cairo.ImageSurface image;
|
Cairo.ImageSurface image;
|
||||||
Clutter.Capture[] captures;
|
Clutter.Capture[] captures;
|
||||||
wm.stage.capture (false, {x, y, width, height}, out captures);
|
wm.stage.capture (false, {x, y, width, height}, out captures);
|
||||||
|
|
||||||
if (captures.length == 0)
|
if (captures.length == 0)
|
||||||
image = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
|
image = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
|
||||||
else if (captures.length == 1)
|
else if (captures.length == 1)
|
||||||
image = captures[0].image;
|
image = captures[0].image;
|
||||||
else
|
else
|
||||||
image = composite_capture_images (captures, x, y, width, height);
|
image = composite_capture_images (captures, x, y, width, height);
|
||||||
|
|
||||||
if (include_cursor) {
|
if (include_cursor) {
|
||||||
image = composite_stage_cursor (image, { x, y, width, height});
|
image = composite_stage_cursor (image, { x, y, width, height});
|
||||||
}
|
}
|
||||||
|
|
||||||
image.mark_dirty ();
|
image.mark_dirty ();
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cairo.ImageSurface composite_capture_images (Clutter.Capture[] captures, int x, int y, int width, int height)
|
Cairo.ImageSurface composite_capture_images (Clutter.Capture[] captures, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
var image = new Cairo.ImageSurface (captures[0].image.get_format (), width, height);
|
var image = new Cairo.ImageSurface (captures[0].image.get_format (), width, height);
|
||||||
var cr = new Cairo.Context (image);
|
var cr = new Cairo.Context (image);
|
||||||
|
|
||||||
foreach (unowned Clutter.Capture capture in captures) {
|
foreach (unowned Clutter.Capture capture in captures) {
|
||||||
// Ignore capture regions with scale other than 1 for now; mutter can't
|
// Ignore capture regions with scale other than 1 for now; mutter can't
|
||||||
// produce them yet, so there is no way to test them.
|
// produce them yet, so there is no way to test them.
|
||||||
double capture_scale = 1.0;
|
double capture_scale = 1.0;
|
||||||
capture.image.get_device_scale (out capture_scale, null);
|
capture.image.get_device_scale (out capture_scale, null);
|
||||||
if (capture_scale != 1.0)
|
if (capture_scale != 1.0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cr.save ();
|
cr.save ();
|
||||||
cr.translate (capture.rect.x - x, capture.rect.y - y);
|
cr.translate (capture.rect.x - x, capture.rect.y - y);
|
||||||
cr.set_source_surface (capture.image, 0, 0);
|
cr.set_source_surface (capture.image, 0, 0);
|
||||||
cr.restore ();
|
cr.restore ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cairo.ImageSurface composite_stage_cursor (Cairo.ImageSurface image, Cairo.RectangleInt image_rect)
|
Cairo.ImageSurface composite_stage_cursor (Cairo.ImageSurface image, Cairo.RectangleInt image_rect)
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.CursorTracker cursor_tracker = wm.get_display ().get_cursor_tracker ();
|
unowned Meta.CursorTracker cursor_tracker = wm.get_display ().get_cursor_tracker ();
|
||||||
#else
|
#else
|
||||||
unowned Meta.CursorTracker cursor_tracker = wm.get_screen ().get_cursor_tracker ();
|
unowned Meta.CursorTracker cursor_tracker = wm.get_screen ().get_cursor_tracker ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
cursor_tracker.get_pointer (out x, out y, null);
|
cursor_tracker.get_pointer (out x, out y, null);
|
||||||
|
|
||||||
var region = new Cairo.Region.rectangle (image_rect);
|
var region = new Cairo.Region.rectangle (image_rect);
|
||||||
if (!region.contains_point (x, y)) {
|
if (!region.contains_point (x, y)) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
unowned Cogl.Texture texture = cursor_tracker.get_sprite ();
|
unowned Cogl.Texture texture = cursor_tracker.get_sprite ();
|
||||||
if (texture == null) {
|
if (texture == null) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
int width = (int)texture.get_width ();
|
int width = (int)texture.get_width ();
|
||||||
int height = (int)texture.get_height ();
|
int height = (int)texture.get_height ();
|
||||||
|
|
||||||
uint8[] data = new uint8[width * height * 4];
|
uint8[] data = new uint8[width * height * 4];
|
||||||
CoglFixes.texture_get_data (texture, Cogl.PixelFormat.RGBA_8888, 0, data);
|
CoglFixes.texture_get_data (texture, Cogl.PixelFormat.RGBA_8888, 0, data);
|
||||||
|
|
||||||
var cursor_image = new Cairo.ImageSurface.for_data (data, Cairo.Format.ARGB32, width, height, width * 4);
|
var cursor_image = new Cairo.ImageSurface.for_data (data, Cairo.Format.ARGB32, width, height, width * 4);
|
||||||
var target = new Cairo.ImageSurface (Cairo.Format.ARGB32, image_rect.width, image_rect.height);
|
var target = new Cairo.ImageSurface (Cairo.Format.ARGB32, image_rect.width, image_rect.height);
|
||||||
|
|
||||||
var cr = new Cairo.Context (target);
|
var cr = new Cairo.Context (target);
|
||||||
cr.set_operator (Cairo.Operator.OVER);
|
cr.set_operator (Cairo.Operator.OVER);
|
||||||
cr.set_source_surface (image, 0, 0);
|
cr.set_source_surface (image, 0, 0);
|
||||||
cr.paint ();
|
cr.paint ();
|
||||||
|
|
||||||
cr.set_operator (Cairo.Operator.OVER);
|
cr.set_operator (Cairo.Operator.OVER);
|
||||||
cr.set_source_surface (cursor_image, x - image_rect.x, y - image_rect.y);
|
cr.set_source_surface (cursor_image, x - image_rect.x, y - image_rect.y);
|
||||||
cr.paint ();
|
cr.paint ();
|
||||||
|
|
||||||
return (Cairo.ImageSurface)cr.get_target ();
|
return (Cairo.ImageSurface)cr.get_target ();
|
||||||
}
|
}
|
||||||
|
|
||||||
async void wait_stage_repaint ()
|
async void wait_stage_repaint ()
|
||||||
{
|
{
|
||||||
ulong signal_id = 0UL;
|
ulong signal_id = 0UL;
|
||||||
signal_id = wm.stage.paint.connect_after (() => {
|
signal_id = wm.stage.paint.connect_after (() => {
|
||||||
wm.stage.disconnect (signal_id);
|
wm.stage.disconnect (signal_id);
|
||||||
Idle.add (wait_stage_repaint.callback);
|
Idle.add (wait_stage_repaint.callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
wm.stage.queue_redraw ();
|
wm.stage.queue_redraw ();
|
||||||
yield;
|
yield;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,82 +20,82 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
[DBus (name = "io.elementary.wingpanel.session.EndSessionDialog")]
|
[DBus (name = "io.elementary.wingpanel.session.EndSessionDialog")]
|
||||||
public interface WingpanelEndSessionDialog : Object
|
public interface WingpanelEndSessionDialog : Object
|
||||||
{
|
{
|
||||||
public signal void confirmed_logout ();
|
public signal void confirmed_logout ();
|
||||||
public signal void confirmed_reboot ();
|
public signal void confirmed_reboot ();
|
||||||
public signal void confirmed_shutdown ();
|
public signal void confirmed_shutdown ();
|
||||||
public signal void canceled ();
|
public signal void canceled ();
|
||||||
public signal void closed ();
|
public signal void closed ();
|
||||||
|
|
||||||
public abstract void open (uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError;
|
public abstract void open (uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DBus (name = "org.gnome.SessionManager.EndSessionDialog")]
|
[DBus (name = "org.gnome.SessionManager.EndSessionDialog")]
|
||||||
public class SessionManager : Object
|
public class SessionManager : Object
|
||||||
{
|
{
|
||||||
static SessionManager? instance;
|
static SessionManager? instance;
|
||||||
|
|
||||||
[DBus (visible = false)]
|
[DBus (visible = false)]
|
||||||
public static unowned SessionManager init ()
|
public static unowned SessionManager init ()
|
||||||
{
|
{
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new SessionManager ();
|
instance = new SessionManager ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public signal void confirmed_logout ();
|
public signal void confirmed_logout ();
|
||||||
public signal void confirmed_reboot ();
|
public signal void confirmed_reboot ();
|
||||||
public signal void confirmed_shutdown ();
|
public signal void confirmed_shutdown ();
|
||||||
public signal void canceled ();
|
public signal void canceled ();
|
||||||
public signal void closed ();
|
public signal void closed ();
|
||||||
|
|
||||||
WingpanelEndSessionDialog? proxy = null;
|
WingpanelEndSessionDialog? proxy = null;
|
||||||
|
|
||||||
SessionManager ()
|
SessionManager ()
|
||||||
{
|
{
|
||||||
Bus.watch_name (BusType.SESSION, "io.elementary.wingpanel.session.EndSessionDialog",
|
Bus.watch_name (BusType.SESSION, "io.elementary.wingpanel.session.EndSessionDialog",
|
||||||
BusNameWatcherFlags.NONE, proxy_appeared, proxy_vanished);
|
BusNameWatcherFlags.NONE, proxy_appeared, proxy_vanished);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_proxy_cb (Object? o, AsyncResult? res)
|
void get_proxy_cb (Object? o, AsyncResult? res)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
proxy = Bus.get_proxy.end (res);
|
proxy = Bus.get_proxy.end (res);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
warning ("Could not connect to io.elementary.wingpanel.session.EndSessionDialog proxy: %s", e.message);
|
warning ("Could not connect to io.elementary.wingpanel.session.EndSessionDialog proxy: %s", e.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.confirmed_logout.connect (() => confirmed_logout ());
|
proxy.confirmed_logout.connect (() => confirmed_logout ());
|
||||||
proxy.confirmed_reboot.connect (() => confirmed_reboot ());
|
proxy.confirmed_reboot.connect (() => confirmed_reboot ());
|
||||||
proxy.confirmed_shutdown.connect (() => confirmed_shutdown ());
|
proxy.confirmed_shutdown.connect (() => confirmed_shutdown ());
|
||||||
proxy.canceled.connect (() => canceled ());
|
proxy.canceled.connect (() => canceled ());
|
||||||
proxy.closed.connect (() => closed ());
|
proxy.closed.connect (() => closed ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void proxy_appeared ()
|
void proxy_appeared ()
|
||||||
{
|
{
|
||||||
Bus.get_proxy.begin<WingpanelEndSessionDialog> (BusType.SESSION,
|
Bus.get_proxy.begin<WingpanelEndSessionDialog> (BusType.SESSION,
|
||||||
"io.elementary.wingpanel.session.EndSessionDialog", "/io/elementary/wingpanel/session/EndSessionDialog",
|
"io.elementary.wingpanel.session.EndSessionDialog", "/io/elementary/wingpanel/session/EndSessionDialog",
|
||||||
0, null, get_proxy_cb);
|
0, null, get_proxy_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void proxy_vanished ()
|
void proxy_vanished ()
|
||||||
{
|
{
|
||||||
proxy = null;
|
proxy = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open (uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError
|
public void open (uint type, uint timestamp, uint open_length, ObjectPath[] inhibiters) throws DBusError, IOError
|
||||||
{
|
{
|
||||||
if (proxy == null) {
|
if (proxy == null) {
|
||||||
throw new DBusError.FAILED ("io.elementary.wingpanel.session.EndSessionDialog DBus interface is not registered.");
|
throw new DBusError.FAILED ("io.elementary.wingpanel.session.EndSessionDialog DBus interface is not registered.");
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.open (type, timestamp, open_length, inhibiters);
|
proxy.open (type, timestamp, open_length, inhibiters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,139 +17,139 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class BehaviorSettings : Granite.Services.Settings
|
public class BehaviorSettings : Granite.Services.Settings
|
||||||
{
|
{
|
||||||
public bool dynamic_workspaces { get; set; }
|
public bool dynamic_workspaces { get; set; }
|
||||||
public bool edge_tiling { get; set; }
|
public bool edge_tiling { get; set; }
|
||||||
public string panel_main_menu_action { get; set; }
|
public string panel_main_menu_action { get; set; }
|
||||||
public string toggle_recording_action { get; set; }
|
public string toggle_recording_action { get; set; }
|
||||||
public string overlay_action { get; set; }
|
public string overlay_action { get; set; }
|
||||||
public string hotcorner_custom_command { get; set; }
|
public string hotcorner_custom_command { get; set; }
|
||||||
public string[] dock_names { get; set; }
|
public string[] dock_names { get; set; }
|
||||||
public bool move_maximized_workspace { get; set; }
|
public bool move_maximized_workspace { get; set; }
|
||||||
|
|
||||||
public WindowOverviewType window_overview_type { get; set; }
|
public WindowOverviewType window_overview_type { get; set; }
|
||||||
|
|
||||||
public ActionType hotcorner_topleft { get; set; }
|
public ActionType hotcorner_topleft { get; set; }
|
||||||
public ActionType hotcorner_topright { get; set; }
|
public ActionType hotcorner_topright { get; set; }
|
||||||
public ActionType hotcorner_bottomleft { get; set; }
|
public ActionType hotcorner_bottomleft { get; set; }
|
||||||
public ActionType hotcorner_bottomright { get; set; }
|
public ActionType hotcorner_bottomright { get; set; }
|
||||||
|
|
||||||
static BehaviorSettings? instance = null;
|
static BehaviorSettings? instance = null;
|
||||||
|
|
||||||
private BehaviorSettings ()
|
private BehaviorSettings ()
|
||||||
{
|
{
|
||||||
base (Config.SCHEMA + ".behavior");
|
base (Config.SCHEMA + ".behavior");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unowned BehaviorSettings get_default ()
|
public static unowned BehaviorSettings get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new BehaviorSettings ();
|
instance = new BehaviorSettings ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KeybindingSettings : Granite.Services.Settings
|
public class KeybindingSettings : Granite.Services.Settings
|
||||||
{
|
{
|
||||||
static KeybindingSettings? instance = null;
|
static KeybindingSettings? instance = null;
|
||||||
|
|
||||||
private KeybindingSettings ()
|
private KeybindingSettings ()
|
||||||
{
|
{
|
||||||
base (Config.SCHEMA + ".keybindings");
|
base (Config.SCHEMA + ".keybindings");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unowned KeybindingSettings get_default ()
|
public static unowned KeybindingSettings get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new KeybindingSettings ();
|
instance = new KeybindingSettings ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AppearanceSettings : Granite.Services.Settings
|
public class AppearanceSettings : Granite.Services.Settings
|
||||||
{
|
{
|
||||||
public string button_layout { get; set; }
|
public string button_layout { get; set; }
|
||||||
public bool attach_modal_dialogs { get; set; }
|
public bool attach_modal_dialogs { get; set; }
|
||||||
public bool dim_parents { get; set; }
|
public bool dim_parents { get; set; }
|
||||||
public string workspace_switcher_background { get; set; }
|
public string workspace_switcher_background { get; set; }
|
||||||
|
|
||||||
static AppearanceSettings? instance = null;
|
static AppearanceSettings? instance = null;
|
||||||
|
|
||||||
private AppearanceSettings ()
|
private AppearanceSettings ()
|
||||||
{
|
{
|
||||||
base (Config.SCHEMA + ".appearance");
|
base (Config.SCHEMA + ".appearance");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unowned AppearanceSettings get_default ()
|
public static unowned AppearanceSettings get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new AppearanceSettings ();
|
instance = new AppearanceSettings ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ShadowSettings : Granite.Services.Settings
|
public class ShadowSettings : Granite.Services.Settings
|
||||||
{
|
{
|
||||||
public string[] menu { get; set; }
|
public string[] menu { get; set; }
|
||||||
public string[] normal_focused { get; set; }
|
public string[] normal_focused { get; set; }
|
||||||
public string[] normal_unfocused { get; set; }
|
public string[] normal_unfocused { get; set; }
|
||||||
public string[] dialog_focused { get; set; }
|
public string[] dialog_focused { get; set; }
|
||||||
public string[] dialog_unfocused { get; set; }
|
public string[] dialog_unfocused { get; set; }
|
||||||
|
|
||||||
static ShadowSettings? instance = null;
|
static ShadowSettings? instance = null;
|
||||||
|
|
||||||
private ShadowSettings ()
|
private ShadowSettings ()
|
||||||
{
|
{
|
||||||
base (Config.SCHEMA + ".shadows");
|
base (Config.SCHEMA + ".shadows");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unowned ShadowSettings get_default ()
|
public static unowned ShadowSettings get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new ShadowSettings ();
|
instance = new ShadowSettings ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Meta.ShadowParams get_shadowparams (string class_name)
|
public Meta.ShadowParams get_shadowparams (string class_name)
|
||||||
{
|
{
|
||||||
string[] val;
|
string[] val;
|
||||||
get (class_name, out val);
|
get (class_name, out val);
|
||||||
|
|
||||||
if (val == null || int.parse (val[0]) < 1)
|
if (val == null || int.parse (val[0]) < 1)
|
||||||
return Meta.ShadowParams () {radius = 1, top_fade = 0, x_offset = 0, y_offset = 0, opacity = 0};
|
return Meta.ShadowParams () {radius = 1, top_fade = 0, x_offset = 0, y_offset = 0, opacity = 0};
|
||||||
|
|
||||||
return Meta.ShadowParams () {radius = int.parse (val[0]), top_fade = int.parse (val[1]),
|
return Meta.ShadowParams () {radius = int.parse (val[0]), top_fade = int.parse (val[1]),
|
||||||
x_offset = int.parse (val[2]), y_offset = int.parse (val[3]), opacity = (uint8)int.parse (val[4])};
|
x_offset = int.parse (val[2]), y_offset = int.parse (val[3]), opacity = (uint8)int.parse (val[4])};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BackgroundSettings : Granite.Services.Settings
|
public class BackgroundSettings : Granite.Services.Settings
|
||||||
{
|
{
|
||||||
public string picture_options { get; set; }
|
public string picture_options { get; set; }
|
||||||
public string picture_uri { get; set; }
|
public string picture_uri { get; set; }
|
||||||
public int picture_opacity { get; set; }
|
public int picture_opacity { get; set; }
|
||||||
public string primary_color { get; set; }
|
public string primary_color { get; set; }
|
||||||
public string secondary_color { get; set; }
|
public string secondary_color { get; set; }
|
||||||
public string color_shading_type { get; set; }
|
public string color_shading_type { get; set; }
|
||||||
|
|
||||||
static BackgroundSettings? instance = null;
|
static BackgroundSettings? instance = null;
|
||||||
|
|
||||||
private BackgroundSettings ()
|
private BackgroundSettings ()
|
||||||
{
|
{
|
||||||
base ("org.gnome.desktop.background");
|
base ("org.gnome.desktop.background");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unowned BackgroundSettings get_default ()
|
public static unowned BackgroundSettings get_default ()
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new BackgroundSettings ();
|
instance = new BackgroundSettings ();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,150 +19,150 @@ using Clutter;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class ShadowEffect : Effect
|
public class ShadowEffect : Effect
|
||||||
{
|
{
|
||||||
private class Shadow
|
private class Shadow
|
||||||
{
|
{
|
||||||
public int users;
|
public int users;
|
||||||
public Cogl.Texture texture;
|
public Cogl.Texture texture;
|
||||||
|
|
||||||
public Shadow (Cogl.Texture _texture)
|
public Shadow (Cogl.Texture _texture)
|
||||||
{
|
{
|
||||||
texture = _texture;
|
texture = _texture;
|
||||||
users = 1;
|
users = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the sizes of the textures often repeat, especially for the background actor
|
// the sizes of the textures often repeat, especially for the background actor
|
||||||
// so we keep a cache to avoid creating the same texture all over again.
|
// so we keep a cache to avoid creating the same texture all over again.
|
||||||
static Gee.HashMap<string,Shadow> shadow_cache;
|
static Gee.HashMap<string,Shadow> shadow_cache;
|
||||||
static Gtk.StyleContext style_context;
|
static Gtk.StyleContext style_context;
|
||||||
|
|
||||||
class construct
|
class construct
|
||||||
{
|
{
|
||||||
shadow_cache = new Gee.HashMap<string,Shadow> ();
|
shadow_cache = new Gee.HashMap<string,Shadow> ();
|
||||||
|
|
||||||
var style_path = new Gtk.WidgetPath ();
|
var style_path = new Gtk.WidgetPath ();
|
||||||
var id = style_path.append_type (typeof (Gtk.Window));
|
var id = style_path.append_type (typeof (Gtk.Window));
|
||||||
|
|
||||||
style_context = new Gtk.StyleContext ();
|
style_context = new Gtk.StyleContext ();
|
||||||
style_context.add_provider (Gala.Utils.get_gala_css (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
|
style_context.add_provider (Gala.Utils.get_gala_css (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
|
||||||
style_context.add_class ("decoration");
|
style_context.add_class ("decoration");
|
||||||
style_context.set_path (style_path);
|
style_context.set_path (style_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int shadow_size { get; construct; }
|
public int shadow_size { get; construct; }
|
||||||
public int shadow_spread { get; construct; }
|
public int shadow_spread { get; construct; }
|
||||||
|
|
||||||
public float scale_factor { get; set; default = 1; }
|
public float scale_factor { get; set; default = 1; }
|
||||||
public uint8 shadow_opacity { get; set; default = 255; }
|
public uint8 shadow_opacity { get; set; default = 255; }
|
||||||
public string? css_class { get; set; default = null; }
|
public string? css_class { get; set; default = null; }
|
||||||
|
|
||||||
Cogl.Material material;
|
Cogl.Material material;
|
||||||
string? current_key = null;
|
string? current_key = null;
|
||||||
|
|
||||||
public ShadowEffect (int shadow_size, int shadow_spread)
|
public ShadowEffect (int shadow_size, int shadow_spread)
|
||||||
{
|
{
|
||||||
Object (shadow_size: shadow_size, shadow_spread: shadow_spread);
|
Object (shadow_size: shadow_size, shadow_spread: shadow_spread);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
material = new Cogl.Material ();
|
material = new Cogl.Material ();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ShadowEffect ()
|
~ShadowEffect ()
|
||||||
{
|
{
|
||||||
if (current_key != null)
|
if (current_key != null)
|
||||||
decrement_shadow_users (current_key);
|
decrement_shadow_users (current_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cogl.Texture? get_shadow (int width, int height, int shadow_size, int shadow_spread)
|
Cogl.Texture? get_shadow (int width, int height, int shadow_size, int shadow_spread)
|
||||||
{
|
{
|
||||||
var old_key = current_key;
|
var old_key = current_key;
|
||||||
current_key = "%ix%i:%i:%i".printf (width, height, shadow_size, shadow_spread);
|
current_key = "%ix%i:%i:%i".printf (width, height, shadow_size, shadow_spread);
|
||||||
if (old_key == current_key)
|
if (old_key == current_key)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (old_key != null)
|
if (old_key != null)
|
||||||
decrement_shadow_users (old_key);
|
decrement_shadow_users (old_key);
|
||||||
|
|
||||||
Shadow? shadow = null;
|
Shadow? shadow = null;
|
||||||
if ((shadow = shadow_cache.@get (current_key)) != null) {
|
if ((shadow = shadow_cache.@get (current_key)) != null) {
|
||||||
shadow.users++;
|
shadow.users++;
|
||||||
return shadow.texture;
|
return shadow.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
|
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
|
||||||
var cr = new Cairo.Context (surface);
|
var cr = new Cairo.Context (surface);
|
||||||
cr.set_source_rgba (0, 0, 0, 0);
|
cr.set_source_rgba (0, 0, 0, 0);
|
||||||
cr.fill ();
|
cr.fill ();
|
||||||
|
|
||||||
cr.set_operator (Cairo.Operator.OVER);
|
cr.set_operator (Cairo.Operator.OVER);
|
||||||
cr.save ();
|
cr.save ();
|
||||||
cr.scale (scale_factor, scale_factor);
|
cr.scale (scale_factor, scale_factor);
|
||||||
style_context.save ();
|
style_context.save ();
|
||||||
if (css_class != null) {
|
if (css_class != null) {
|
||||||
style_context.add_class (css_class);
|
style_context.add_class (css_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
style_context.set_scale ((int)scale_factor);
|
style_context.set_scale ((int)scale_factor);
|
||||||
style_context.render_background (cr, shadow_size, shadow_size, width - shadow_size * 2, height - shadow_size * 2);
|
style_context.render_background (cr, shadow_size, shadow_size, width - shadow_size * 2, height - shadow_size * 2);
|
||||||
style_context.restore ();
|
style_context.restore ();
|
||||||
cr.restore ();
|
cr.restore ();
|
||||||
|
|
||||||
cr.paint ();
|
cr.paint ();
|
||||||
|
|
||||||
var texture = new Cogl.Texture.from_data (width, height, 0, Cogl.PixelFormat.BGRA_8888_PRE,
|
var texture = new Cogl.Texture.from_data (width, height, 0, Cogl.PixelFormat.BGRA_8888_PRE,
|
||||||
Cogl.PixelFormat.ANY, surface.get_stride (), surface.get_data ());
|
Cogl.PixelFormat.ANY, surface.get_stride (), surface.get_data ());
|
||||||
|
|
||||||
shadow_cache.@set (current_key, new Shadow (texture));
|
shadow_cache.@set (current_key, new Shadow (texture));
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decrement_shadow_users (string key)
|
void decrement_shadow_users (string key)
|
||||||
{
|
{
|
||||||
var shadow = shadow_cache.@get (key);
|
var shadow = shadow_cache.@get (key);
|
||||||
|
|
||||||
if (shadow == null)
|
if (shadow == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (--shadow.users == 0)
|
if (--shadow.users == 0)
|
||||||
shadow_cache.unset (key);
|
shadow_cache.unset (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void paint (EffectPaintFlags flags)
|
public override void paint (EffectPaintFlags flags)
|
||||||
{
|
{
|
||||||
var bounding_box = get_bounding_box ();
|
var bounding_box = get_bounding_box ();
|
||||||
var width = (int) (bounding_box.x2 - bounding_box.x1);
|
var width = (int) (bounding_box.x2 - bounding_box.x1);
|
||||||
var height = (int) (bounding_box.y2 - bounding_box.y1);
|
var height = (int) (bounding_box.y2 - bounding_box.y1);
|
||||||
|
|
||||||
var shadow = get_shadow (width, height, shadow_size, shadow_spread);
|
var shadow = get_shadow (width, height, shadow_size, shadow_spread);
|
||||||
if (shadow != null)
|
if (shadow != null)
|
||||||
material.set_layer (0, shadow);
|
material.set_layer (0, shadow);
|
||||||
|
|
||||||
var opacity = actor.get_paint_opacity () * shadow_opacity / 255;
|
var opacity = actor.get_paint_opacity () * shadow_opacity / 255;
|
||||||
var alpha = Cogl.Color.from_4ub (255, 255, 255, opacity);
|
var alpha = Cogl.Color.from_4ub (255, 255, 255, opacity);
|
||||||
alpha.premultiply ();
|
alpha.premultiply ();
|
||||||
|
|
||||||
material.set_color (alpha);
|
material.set_color (alpha);
|
||||||
|
|
||||||
Cogl.set_source (material);
|
Cogl.set_source (material);
|
||||||
Cogl.rectangle (bounding_box.x1, bounding_box.y1, bounding_box.x2, bounding_box.y2);
|
Cogl.rectangle (bounding_box.x1, bounding_box.y1, bounding_box.x2, bounding_box.y2);
|
||||||
|
|
||||||
actor.continue_paint ();
|
actor.continue_paint ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ActorBox get_bounding_box ()
|
public virtual ActorBox get_bounding_box ()
|
||||||
{
|
{
|
||||||
var size = shadow_size * scale_factor;
|
var size = shadow_size * scale_factor;
|
||||||
var bounding_box = ActorBox ();
|
var bounding_box = ActorBox ();
|
||||||
|
|
||||||
bounding_box.set_origin (-size, -size);
|
bounding_box.set_origin (-size, -size);
|
||||||
bounding_box.set_size (actor.width + size * 2, actor.height + size * 2);
|
bounding_box.set_size (actor.width + size * 2, actor.height + size * 2);
|
||||||
|
|
||||||
return bounding_box;
|
return bounding_box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,46 +17,46 @@
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class TextShadowEffect : Clutter.Effect
|
public class TextShadowEffect : Clutter.Effect
|
||||||
{
|
{
|
||||||
int _offset_y;
|
int _offset_y;
|
||||||
public int offset_y {
|
public int offset_y {
|
||||||
get { return _offset_y; }
|
get { return _offset_y; }
|
||||||
set { _offset_y = value; update (); }
|
set { _offset_y = value; update (); }
|
||||||
}
|
}
|
||||||
|
|
||||||
int _offset_x;
|
int _offset_x;
|
||||||
public int offset_x {
|
public int offset_x {
|
||||||
get { return _offset_x; }
|
get { return _offset_x; }
|
||||||
set { _offset_x = value; update (); }
|
set { _offset_x = value; update (); }
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 _opacity;
|
uint8 _opacity;
|
||||||
public uint8 opacity {
|
public uint8 opacity {
|
||||||
get { return _opacity; }
|
get { return _opacity; }
|
||||||
set { _opacity = value; update (); }
|
set { _opacity = value; update (); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextShadowEffect (int offset_x, int offset_y, uint8 opacity)
|
public TextShadowEffect (int offset_x, int offset_y, uint8 opacity)
|
||||||
{
|
{
|
||||||
_offset_x = offset_x;
|
_offset_x = offset_x;
|
||||||
_offset_y = offset_y;
|
_offset_y = offset_y;
|
||||||
_opacity = opacity;
|
_opacity = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool pre_paint ()
|
public override bool pre_paint ()
|
||||||
{
|
{
|
||||||
var layout = ((Clutter.Text)get_actor ()).get_layout ();
|
var layout = ((Clutter.Text)get_actor ()).get_layout ();
|
||||||
Cogl.pango_render_layout (layout, offset_x, offset_y, Cogl.Color.from_4ub (0, 0, 0, opacity), 0);
|
Cogl.pango_render_layout (layout, offset_x, offset_y, Cogl.Color.from_4ub (0, 0, 0, opacity), 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update ()
|
public void update ()
|
||||||
{
|
{
|
||||||
if (get_actor () != null)
|
if (get_actor () != null)
|
||||||
get_actor ().queue_redraw ();
|
get_actor ().queue_redraw ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,146 +20,146 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* This class contains the icon groups at the bottom and will take
|
* This class contains the icon groups at the bottom and will take
|
||||||
* care of displaying actors for inserting windows between the groups
|
* care of displaying actors for inserting windows between the groups
|
||||||
* once implemented
|
* once implemented
|
||||||
*/
|
*/
|
||||||
public class IconGroupContainer : Actor
|
public class IconGroupContainer : Actor
|
||||||
{
|
{
|
||||||
public const int SPACING = 48;
|
public const int SPACING = 48;
|
||||||
public const int GROUP_WIDTH = 64;
|
public const int GROUP_WIDTH = 64;
|
||||||
|
|
||||||
public signal void request_reposition (bool animate);
|
public signal void request_reposition (bool animate);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
#else
|
#else
|
||||||
public Screen screen { get; construct; }
|
public Screen screen { get; construct; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public IconGroupContainer (Meta.Display display)
|
public IconGroupContainer (Meta.Display display)
|
||||||
{
|
{
|
||||||
Object (display: display);
|
Object (display: display);
|
||||||
|
|
||||||
layout_manager = new BoxLayout ();
|
layout_manager = new BoxLayout ();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public IconGroupContainer (Screen screen)
|
public IconGroupContainer (Screen screen)
|
||||||
{
|
{
|
||||||
Object (screen: screen);
|
Object (screen: screen);
|
||||||
|
|
||||||
layout_manager = new BoxLayout ();
|
layout_manager = new BoxLayout ();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public void add_group (IconGroup group)
|
public void add_group (IconGroup group)
|
||||||
{
|
{
|
||||||
var index = group.workspace.index ();
|
var index = group.workspace.index ();
|
||||||
|
|
||||||
insert_child_at_index (group, index * 2);
|
insert_child_at_index (group, index * 2);
|
||||||
|
|
||||||
var thumb = new WorkspaceInsertThumb (index);
|
var thumb = new WorkspaceInsertThumb (index);
|
||||||
thumb.notify["expanded"].connect_after (expanded_changed);
|
thumb.notify["expanded"].connect_after (expanded_changed);
|
||||||
insert_child_at_index (thumb, index * 2);
|
insert_child_at_index (thumb, index * 2);
|
||||||
|
|
||||||
update_inserter_indices ();
|
update_inserter_indices ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove_group (IconGroup group)
|
public void remove_group (IconGroup group)
|
||||||
{
|
{
|
||||||
var thumb = (WorkspaceInsertThumb) group.get_previous_sibling ();
|
var thumb = (WorkspaceInsertThumb) group.get_previous_sibling ();
|
||||||
thumb.notify["expanded"].disconnect (expanded_changed);
|
thumb.notify["expanded"].disconnect (expanded_changed);
|
||||||
remove_child (thumb);
|
remove_child (thumb);
|
||||||
|
|
||||||
remove_child (group);
|
remove_child (group);
|
||||||
|
|
||||||
update_inserter_indices ();
|
update_inserter_indices ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an icon group "in place".
|
* Removes an icon group "in place".
|
||||||
* When initially dragging an icon group we remove
|
* When initially dragging an icon group we remove
|
||||||
* it and it's previous WorkspaceInsertThumb. This would make
|
* it and it's previous WorkspaceInsertThumb. This would make
|
||||||
* the container immediately reallocate and fill the empty space
|
* the container immediately reallocate and fill the empty space
|
||||||
* with right-most IconGroups.
|
* with right-most IconGroups.
|
||||||
*
|
*
|
||||||
* We don't want that until the IconGroup
|
* We don't want that until the IconGroup
|
||||||
* leaves the expanded WorkspaceInsertThumb.
|
* leaves the expanded WorkspaceInsertThumb.
|
||||||
*/
|
*/
|
||||||
public void remove_group_in_place (IconGroup group)
|
public void remove_group_in_place (IconGroup group)
|
||||||
{
|
{
|
||||||
var deleted_thumb = (WorkspaceInsertThumb) group.get_previous_sibling ();
|
var deleted_thumb = (WorkspaceInsertThumb) group.get_previous_sibling ();
|
||||||
var deleted_placeholder_thumb = (WorkspaceInsertThumb) group.get_next_sibling ();
|
var deleted_placeholder_thumb = (WorkspaceInsertThumb) group.get_next_sibling ();
|
||||||
|
|
||||||
remove_group (group);
|
remove_group (group);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We will account for that empty space
|
* We will account for that empty space
|
||||||
* by manually expanding the next WorkspaceInsertThumb with the
|
* by manually expanding the next WorkspaceInsertThumb with the
|
||||||
* width we deleted. Because the IconGroup is still hovering over
|
* width we deleted. Because the IconGroup is still hovering over
|
||||||
* the expanded thumb, we will also update the drag & drop action
|
* the expanded thumb, we will also update the drag & drop action
|
||||||
* of IconGroup on that.
|
* of IconGroup on that.
|
||||||
*/
|
*/
|
||||||
float deleted_width = deleted_thumb.get_width () + group.get_width ();
|
float deleted_width = deleted_thumb.get_width () + group.get_width ();
|
||||||
deleted_placeholder_thumb.expanded = true;
|
deleted_placeholder_thumb.expanded = true;
|
||||||
deleted_placeholder_thumb.width += deleted_width;
|
deleted_placeholder_thumb.width += deleted_width;
|
||||||
group.set_hovered_actor (deleted_placeholder_thumb);
|
group.set_hovered_actor (deleted_placeholder_thumb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset_thumbs (int delay)
|
public void reset_thumbs (int delay)
|
||||||
{
|
{
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
unowned WorkspaceInsertThumb thumb = child as WorkspaceInsertThumb;
|
unowned WorkspaceInsertThumb thumb = child as WorkspaceInsertThumb;
|
||||||
if (thumb != null) {
|
if (thumb != null) {
|
||||||
thumb.delay = delay;
|
thumb.delay = delay;
|
||||||
thumb.destroy_all_children ();
|
thumb.destroy_all_children ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void expanded_changed (ParamSpec param)
|
void expanded_changed (ParamSpec param)
|
||||||
{
|
{
|
||||||
request_reposition (true);
|
request_reposition (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the width that will be occupied taking currently running animations
|
* Calculates the width that will be occupied taking currently running animations
|
||||||
* end states into account
|
* end states into account
|
||||||
*/
|
*/
|
||||||
public float calculate_total_width ()
|
public float calculate_total_width ()
|
||||||
{
|
{
|
||||||
var scale = InternalUtils.get_ui_scaling_factor ();
|
var scale = InternalUtils.get_ui_scaling_factor ();
|
||||||
var spacing = SPACING * scale;
|
var spacing = SPACING * scale;
|
||||||
var group_width = GROUP_WIDTH * scale;
|
var group_width = GROUP_WIDTH * scale;
|
||||||
|
|
||||||
var width = 0.0f;
|
var width = 0.0f;
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
if (child is WorkspaceInsertThumb) {
|
if (child is WorkspaceInsertThumb) {
|
||||||
if (((WorkspaceInsertThumb) child).expanded)
|
if (((WorkspaceInsertThumb) child).expanded)
|
||||||
width += group_width + spacing * 2;
|
width += group_width + spacing * 2;
|
||||||
else
|
else
|
||||||
width += spacing;
|
width += spacing;
|
||||||
} else
|
} else
|
||||||
width += group_width;
|
width += group_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
width += spacing;
|
width += spacing;
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_inserter_indices ()
|
void update_inserter_indices ()
|
||||||
{
|
{
|
||||||
var current_index = 0;
|
var current_index = 0;
|
||||||
|
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
unowned WorkspaceInsertThumb thumb = child as WorkspaceInsertThumb;
|
unowned WorkspaceInsertThumb thumb = child as WorkspaceInsertThumb;
|
||||||
if (thumb != null) {
|
if (thumb != null) {
|
||||||
thumb.workspace_index = current_index++;
|
thumb.workspace_index = current_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,150 +20,150 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* More or less utility class to contain a WindowCloneContainer for each
|
* More or less utility class to contain a WindowCloneContainer for each
|
||||||
* non-primary monitor. It's the pendant to the WorkspaceClone which is
|
* non-primary monitor. It's the pendant to the WorkspaceClone which is
|
||||||
* only placed on the primary monitor. It also draws a wallpaper behind itself
|
* only placed on the primary monitor. It also draws a wallpaper behind itself
|
||||||
* as the WindowGroup is hidden while the view is active. Only used when
|
* as the WindowGroup is hidden while the view is active. Only used when
|
||||||
* workspaces-only-on-primary is set to true.
|
* workspaces-only-on-primary is set to true.
|
||||||
*/
|
*/
|
||||||
public class MonitorClone : Actor
|
public class MonitorClone : Actor
|
||||||
{
|
{
|
||||||
public signal void window_selected (Window window);
|
public signal void window_selected (Window window);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public Meta.Display display { get; construct; }
|
public Meta.Display display { get; construct; }
|
||||||
#else
|
#else
|
||||||
public Screen screen { get; construct; }
|
public Screen screen { get; construct; }
|
||||||
#endif
|
#endif
|
||||||
public int monitor { get; construct; }
|
public int monitor { get; construct; }
|
||||||
|
|
||||||
WindowCloneContainer window_container;
|
WindowCloneContainer window_container;
|
||||||
BackgroundManager background;
|
BackgroundManager background;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public MonitorClone (Meta.Display display, int monitor)
|
public MonitorClone (Meta.Display display, int monitor)
|
||||||
{
|
{
|
||||||
Object (display: display, monitor: monitor);
|
Object (display: display, monitor: monitor);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public MonitorClone (Screen screen, int monitor)
|
public MonitorClone (Screen screen, int monitor)
|
||||||
{
|
{
|
||||||
Object (screen: screen, monitor: monitor);
|
Object (screen: screen, monitor: monitor);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
reactive = true;
|
reactive = true;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
background = new BackgroundManager (display, monitor, false);
|
background = new BackgroundManager (display, monitor, false);
|
||||||
#else
|
#else
|
||||||
background = new BackgroundManager (screen, monitor, false);
|
background = new BackgroundManager (screen, monitor, false);
|
||||||
#endif
|
#endif
|
||||||
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
||||||
|
|
||||||
window_container = new WindowCloneContainer ();
|
window_container = new WindowCloneContainer ();
|
||||||
window_container.window_selected.connect ((w) => { window_selected (w); });
|
window_container.window_selected.connect ((w) => { window_selected (w); });
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.restacked.connect (window_container.restack_windows);
|
display.restacked.connect (window_container.restack_windows);
|
||||||
|
|
||||||
display.window_entered_monitor.connect (window_entered);
|
display.window_entered_monitor.connect (window_entered);
|
||||||
display.window_left_monitor.connect (window_left);
|
display.window_left_monitor.connect (window_left);
|
||||||
#else
|
#else
|
||||||
screen.restacked.connect (window_container.restack_windows);
|
screen.restacked.connect (window_container.restack_windows);
|
||||||
|
|
||||||
screen.window_entered_monitor.connect (window_entered);
|
screen.window_entered_monitor.connect (window_entered);
|
||||||
screen.window_left_monitor.connect (window_left);
|
screen.window_left_monitor.connect (window_left);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned GLib.List<Meta.WindowActor> window_actors = display.get_window_actors ();
|
unowned GLib.List<Meta.WindowActor> window_actors = display.get_window_actors ();
|
||||||
#else
|
#else
|
||||||
unowned GLib.List<Meta.WindowActor> window_actors = screen.get_window_actors ();
|
unowned GLib.List<Meta.WindowActor> window_actors = screen.get_window_actors ();
|
||||||
#endif
|
#endif
|
||||||
foreach (unowned Meta.WindowActor window_actor in window_actors) {
|
foreach (unowned Meta.WindowActor window_actor in window_actors) {
|
||||||
if (window_actor.is_destroyed ())
|
if (window_actor.is_destroyed ())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
unowned Meta.Window window = window_actor.get_meta_window ();
|
unowned Meta.Window window = window_actor.get_meta_window ();
|
||||||
if (window.get_monitor () == monitor) {
|
if (window.get_monitor () == monitor) {
|
||||||
window_entered (monitor, window);
|
window_entered (monitor, window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_child (background);
|
add_child (background);
|
||||||
add_child (window_container);
|
add_child (window_container);
|
||||||
|
|
||||||
var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
||||||
add_action (drop);
|
add_action (drop);
|
||||||
|
|
||||||
update_allocation ();
|
update_allocation ();
|
||||||
}
|
}
|
||||||
|
|
||||||
~MonitorClone ()
|
~MonitorClone ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.window_entered_monitor.disconnect (window_entered);
|
display.window_entered_monitor.disconnect (window_entered);
|
||||||
display.window_left_monitor.disconnect (window_left);
|
display.window_left_monitor.disconnect (window_left);
|
||||||
display.restacked.disconnect (window_container.restack_windows);
|
display.restacked.disconnect (window_container.restack_windows);
|
||||||
#else
|
#else
|
||||||
screen.window_entered_monitor.disconnect (window_entered);
|
screen.window_entered_monitor.disconnect (window_entered);
|
||||||
screen.window_left_monitor.disconnect (window_left);
|
screen.window_left_monitor.disconnect (window_left);
|
||||||
screen.restacked.disconnect (window_container.restack_windows);
|
screen.restacked.disconnect (window_container.restack_windows);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make sure the MonitorClone is at the location of the monitor on the stage
|
* Make sure the MonitorClone is at the location of the monitor on the stage
|
||||||
*/
|
*/
|
||||||
public void update_allocation ()
|
public void update_allocation ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var monitor_geometry = display.get_monitor_geometry (monitor);
|
var monitor_geometry = display.get_monitor_geometry (monitor);
|
||||||
#else
|
#else
|
||||||
var monitor_geometry = screen.get_monitor_geometry (monitor);
|
var monitor_geometry = screen.get_monitor_geometry (monitor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
set_position (monitor_geometry.x, monitor_geometry.y);
|
set_position (monitor_geometry.x, monitor_geometry.y);
|
||||||
set_size (monitor_geometry.width, monitor_geometry.height);
|
set_size (monitor_geometry.width, monitor_geometry.height);
|
||||||
window_container.set_size (monitor_geometry.width, monitor_geometry.height);
|
window_container.set_size (monitor_geometry.width, monitor_geometry.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animate the windows from their old location to a tiled layout
|
* Animate the windows from their old location to a tiled layout
|
||||||
*/
|
*/
|
||||||
public void open ()
|
public void open ()
|
||||||
{
|
{
|
||||||
window_container.open ();
|
window_container.open ();
|
||||||
// background.opacity = 0; TODO consider this option
|
// background.opacity = 0; TODO consider this option
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animate the windows back to their old location
|
* Animate the windows back to their old location
|
||||||
*/
|
*/
|
||||||
public void close ()
|
public void close ()
|
||||||
{
|
{
|
||||||
window_container.close ();
|
window_container.close ();
|
||||||
background.opacity = 255;
|
background.opacity = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_left (int window_monitor, Window window)
|
void window_left (int window_monitor, Window window)
|
||||||
{
|
{
|
||||||
if (window_monitor != monitor)
|
if (window_monitor != monitor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window_container.remove_window (window);
|
window_container.remove_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_entered (int window_monitor, Window window)
|
void window_entered (int window_monitor, Window window)
|
||||||
{
|
{
|
||||||
if (window_monitor != monitor || window.window_type != WindowType.NORMAL)
|
if (window_monitor != monitor || window.window_type != WindowType.NORMAL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window_container.add_window (window);
|
window_container.add_window (window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -19,57 +19,57 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* A clone for a MetaWindowActor that will guard against the
|
* A clone for a MetaWindowActor that will guard against the
|
||||||
* meta_window_appears_focused crash by disabling painting the clone
|
* meta_window_appears_focused crash by disabling painting the clone
|
||||||
* as soon as it gets unavailable.
|
* as soon as it gets unavailable.
|
||||||
*/
|
*/
|
||||||
public class SafeWindowClone : Clutter.Clone
|
public class SafeWindowClone : Clutter.Clone
|
||||||
{
|
{
|
||||||
public Window window { get; construct; }
|
public Window window { get; construct; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to true, the SafeWindowClone will destroy itself when the connected
|
* If set to true, the SafeWindowClone will destroy itself when the connected
|
||||||
* window is unmanaged
|
* window is unmanaged
|
||||||
*/
|
*/
|
||||||
public bool destroy_on_unmanaged { get; construct set; default = false; }
|
public bool destroy_on_unmanaged { get; construct set; default = false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new SafeWindowClone
|
* Creates a new SafeWindowClone
|
||||||
*
|
*
|
||||||
* @param window The window to clone from
|
* @param window The window to clone from
|
||||||
* @param destroy_on_unmanaged see destroy_on_unmanaged property
|
* @param destroy_on_unmanaged see destroy_on_unmanaged property
|
||||||
*/
|
*/
|
||||||
public SafeWindowClone (Window window, bool destroy_on_unmanaged = false)
|
public SafeWindowClone (Window window, bool destroy_on_unmanaged = false)
|
||||||
{
|
{
|
||||||
var actor = (WindowActor) window.get_compositor_private ();
|
var actor = (WindowActor) window.get_compositor_private ();
|
||||||
|
|
||||||
Object (window: window,
|
Object (window: window,
|
||||||
source: actor,
|
source: actor,
|
||||||
destroy_on_unmanaged: destroy_on_unmanaged);
|
destroy_on_unmanaged: destroy_on_unmanaged);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
if (source != null)
|
if (source != null)
|
||||||
window.unmanaged.connect (reset_source);
|
window.unmanaged.connect (reset_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SafeWindowClone ()
|
~SafeWindowClone ()
|
||||||
{
|
{
|
||||||
window.unmanaged.disconnect (reset_source);
|
window.unmanaged.disconnect (reset_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_source ()
|
void reset_source ()
|
||||||
{
|
{
|
||||||
// actually destroying the clone will be handled somewhere else (unless we were
|
// actually destroying the clone will be handled somewhere else (unless we were
|
||||||
// requested to destroy it), we just need to make sure the clone doesn't attempt
|
// requested to destroy it), we just need to make sure the clone doesn't attempt
|
||||||
// to draw a clone of a window that has been destroyed
|
// to draw a clone of a window that has been destroyed
|
||||||
source = null;
|
source = null;
|
||||||
|
|
||||||
if (destroy_on_unmanaged)
|
if (destroy_on_unmanaged)
|
||||||
destroy ();
|
destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,381 +20,381 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Container which controls the layout of a set of WindowClones.
|
* Container which controls the layout of a set of WindowClones.
|
||||||
*/
|
*/
|
||||||
public class WindowCloneContainer : Actor
|
public class WindowCloneContainer : Actor
|
||||||
{
|
{
|
||||||
public signal void window_selected (Window window);
|
public signal void window_selected (Window window);
|
||||||
|
|
||||||
public int padding_top { get; set; default = 12; }
|
public int padding_top { get; set; default = 12; }
|
||||||
public int padding_left { get; set; default = 12; }
|
public int padding_left { get; set; default = 12; }
|
||||||
public int padding_right { get; set; default = 12; }
|
public int padding_right { get; set; default = 12; }
|
||||||
public int padding_bottom { get; set; default = 12; }
|
public int padding_bottom { get; set; default = 12; }
|
||||||
|
|
||||||
public bool overview_mode { get; construct; }
|
public bool overview_mode { get; construct; }
|
||||||
|
|
||||||
bool opened;
|
bool opened;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The window that is currently selected via keyboard shortcuts. It is not
|
* The window that is currently selected via keyboard shortcuts. It is not
|
||||||
* necessarily the same as the active window.
|
* necessarily the same as the active window.
|
||||||
*/
|
*/
|
||||||
WindowClone? current_window;
|
WindowClone? current_window;
|
||||||
|
|
||||||
public WindowCloneContainer (bool overview_mode = false)
|
public WindowCloneContainer (bool overview_mode = false)
|
||||||
{
|
{
|
||||||
Object (overview_mode: overview_mode);
|
Object (overview_mode: overview_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
opened = false;
|
opened = false;
|
||||||
current_window = null;
|
current_window = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a WindowClone for a MetaWindow and add it to the group
|
* Create a WindowClone for a MetaWindow and add it to the group
|
||||||
*
|
*
|
||||||
* @param window The window for which to create the WindowClone for
|
* @param window The window for which to create the WindowClone for
|
||||||
*/
|
*/
|
||||||
public void add_window (Window window)
|
public void add_window (Window window)
|
||||||
{
|
{
|
||||||
unowned Meta.Display display = window.get_display ();
|
unowned Meta.Display display = window.get_display ();
|
||||||
var children = get_children ();
|
var children = get_children ();
|
||||||
|
|
||||||
GLib.SList<Meta.Window> windows = new GLib.SList<Meta.Window> ();
|
GLib.SList<Meta.Window> windows = new GLib.SList<Meta.Window> ();
|
||||||
foreach (unowned Actor child in children) {
|
foreach (unowned Actor child in children) {
|
||||||
unowned WindowClone tw = (WindowClone) child;
|
unowned WindowClone tw = (WindowClone) child;
|
||||||
windows.prepend (tw.window);
|
windows.prepend (tw.window);
|
||||||
}
|
}
|
||||||
windows.prepend (window);
|
windows.prepend (window);
|
||||||
windows.reverse ();
|
windows.reverse ();
|
||||||
|
|
||||||
var windows_ordered = display.sort_windows_by_stacking (windows);
|
var windows_ordered = display.sort_windows_by_stacking (windows);
|
||||||
|
|
||||||
var new_window = new WindowClone (window, overview_mode);
|
var new_window = new WindowClone (window, overview_mode);
|
||||||
|
|
||||||
new_window.selected.connect (window_selected_cb);
|
new_window.selected.connect (window_selected_cb);
|
||||||
new_window.destroy.connect (window_destroyed);
|
new_window.destroy.connect (window_destroyed);
|
||||||
new_window.request_reposition.connect (reflow);
|
new_window.request_reposition.connect (reflow);
|
||||||
|
|
||||||
var added = false;
|
var added = false;
|
||||||
unowned Meta.Window? target = null;
|
unowned Meta.Window? target = null;
|
||||||
foreach (unowned Meta.Window w in windows_ordered) {
|
foreach (unowned Meta.Window w in windows_ordered) {
|
||||||
if (w != window) {
|
if (w != window) {
|
||||||
target = w;
|
target = w;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (unowned Actor child in children) {
|
foreach (unowned Actor child in children) {
|
||||||
unowned WindowClone tw = (WindowClone) child;
|
unowned WindowClone tw = (WindowClone) child;
|
||||||
if (target == tw.window) {
|
if (target == tw.window) {
|
||||||
insert_child_above (new_window, tw);
|
insert_child_above (new_window, tw);
|
||||||
added = true;
|
added = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// top most or no other children
|
// top most or no other children
|
||||||
if (!added)
|
if (!added)
|
||||||
add_child (new_window);
|
add_child (new_window);
|
||||||
|
|
||||||
reflow ();
|
reflow ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find and remove the WindowClone for a MetaWindow
|
* Find and remove the WindowClone for a MetaWindow
|
||||||
*/
|
*/
|
||||||
public void remove_window (Window window)
|
public void remove_window (Window window)
|
||||||
{
|
{
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
if (((WindowClone) child).window == window) {
|
if (((WindowClone) child).window == window) {
|
||||||
remove_child (child);
|
remove_child (child);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reflow ();
|
reflow ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_selected_cb (WindowClone tiled)
|
void window_selected_cb (WindowClone tiled)
|
||||||
{
|
{
|
||||||
window_selected (tiled.window);
|
window_selected (tiled.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_destroyed (Actor actor)
|
void window_destroyed (Actor actor)
|
||||||
{
|
{
|
||||||
var window = actor as WindowClone;
|
var window = actor as WindowClone;
|
||||||
if (window == null)
|
if (window == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window.destroy.disconnect (window_destroyed);
|
window.destroy.disconnect (window_destroyed);
|
||||||
window.selected.disconnect (window_selected_cb);
|
window.selected.disconnect (window_selected_cb);
|
||||||
|
|
||||||
Idle.add (() => {
|
Idle.add (() => {
|
||||||
reflow ();
|
reflow ();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort the windows z-order by their actual stacking to make intersections
|
* Sort the windows z-order by their actual stacking to make intersections
|
||||||
* during animations correct.
|
* during animations correct.
|
||||||
*/
|
*/
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public void restack_windows (Meta.Display display)
|
public void restack_windows (Meta.Display display)
|
||||||
{
|
{
|
||||||
var children = get_children ();
|
var children = get_children ();
|
||||||
|
|
||||||
GLib.SList<Meta.Window> windows = new GLib.SList<Meta.Window> ();
|
GLib.SList<Meta.Window> windows = new GLib.SList<Meta.Window> ();
|
||||||
foreach (unowned Actor child in children) {
|
foreach (unowned Actor child in children) {
|
||||||
unowned WindowClone tw = (WindowClone) child;
|
unowned WindowClone tw = (WindowClone) child;
|
||||||
windows.prepend (tw.window);
|
windows.prepend (tw.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
var windows_ordered = display.sort_windows_by_stacking (windows);
|
var windows_ordered = display.sort_windows_by_stacking (windows);
|
||||||
windows_ordered.reverse ();
|
windows_ordered.reverse ();
|
||||||
|
|
||||||
foreach (unowned Meta.Window window in windows_ordered) {
|
foreach (unowned Meta.Window window in windows_ordered) {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
foreach (unowned Actor child in children) {
|
foreach (unowned Actor child in children) {
|
||||||
if (((WindowClone) child).window == window) {
|
if (((WindowClone) child).window == window) {
|
||||||
set_child_at_index (child, i);
|
set_child_at_index (child, i);
|
||||||
children.remove (child);
|
children.remove (child);
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public void restack_windows (Screen screen)
|
public void restack_windows (Screen screen)
|
||||||
{
|
{
|
||||||
unowned Meta.Display display = screen.get_display ();
|
unowned Meta.Display display = screen.get_display ();
|
||||||
var children = get_children ();
|
var children = get_children ();
|
||||||
|
|
||||||
GLib.SList<Meta.Window> windows = new GLib.SList<Meta.Window> ();
|
GLib.SList<Meta.Window> windows = new GLib.SList<Meta.Window> ();
|
||||||
foreach (unowned Actor child in children) {
|
foreach (unowned Actor child in children) {
|
||||||
unowned WindowClone tw = (WindowClone) child;
|
unowned WindowClone tw = (WindowClone) child;
|
||||||
windows.prepend (tw.window);
|
windows.prepend (tw.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
var windows_ordered = display.sort_windows_by_stacking (windows);
|
var windows_ordered = display.sort_windows_by_stacking (windows);
|
||||||
windows_ordered.reverse ();
|
windows_ordered.reverse ();
|
||||||
|
|
||||||
foreach (unowned Meta.Window window in windows_ordered) {
|
foreach (unowned Meta.Window window in windows_ordered) {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
foreach (unowned Actor child in children) {
|
foreach (unowned Actor child in children) {
|
||||||
if (((WindowClone) child).window == window) {
|
if (((WindowClone) child).window == window) {
|
||||||
set_child_at_index (child, i);
|
set_child_at_index (child, i);
|
||||||
children.remove (child);
|
children.remove (child);
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recalculate the tiling positions of the windows and animate them to
|
* Recalculate the tiling positions of the windows and animate them to
|
||||||
* the resulting spots.
|
* the resulting spots.
|
||||||
*/
|
*/
|
||||||
public void reflow ()
|
public void reflow ()
|
||||||
{
|
{
|
||||||
if (!opened)
|
if (!opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var windows = new List<InternalUtils.TilableWindow?> ();
|
var windows = new List<InternalUtils.TilableWindow?> ();
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
unowned WindowClone window = (WindowClone) child;
|
unowned WindowClone window = (WindowClone) child;
|
||||||
windows.prepend ({ window.window.get_frame_rect (), window });
|
windows.prepend ({ window.window.get_frame_rect (), window });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windows.length () < 1)
|
if (windows.length () < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// make sure the windows are always in the same order so the algorithm
|
// make sure the windows are always in the same order so the algorithm
|
||||||
// doesn't give us different slots based on stacking order, which can lead
|
// doesn't give us different slots based on stacking order, which can lead
|
||||||
// to windows flying around weirdly
|
// to windows flying around weirdly
|
||||||
windows.sort ((a, b) => {
|
windows.sort ((a, b) => {
|
||||||
var seq_a = ((WindowClone) a.id).window.get_stable_sequence ();
|
var seq_a = ((WindowClone) a.id).window.get_stable_sequence ();
|
||||||
var seq_b = ((WindowClone) b.id).window.get_stable_sequence ();
|
var seq_b = ((WindowClone) b.id).window.get_stable_sequence ();
|
||||||
return (int) (seq_b - seq_a);
|
return (int) (seq_b - seq_a);
|
||||||
});
|
});
|
||||||
|
|
||||||
Meta.Rectangle area = {
|
Meta.Rectangle area = {
|
||||||
padding_left,
|
padding_left,
|
||||||
padding_top,
|
padding_top,
|
||||||
(int)width - padding_left - padding_right,
|
(int)width - padding_left - padding_right,
|
||||||
(int)height - padding_top - padding_bottom
|
(int)height - padding_top - padding_bottom
|
||||||
};
|
};
|
||||||
|
|
||||||
var window_positions = InternalUtils.calculate_grid_placement (area, windows);
|
var window_positions = InternalUtils.calculate_grid_placement (area, windows);
|
||||||
|
|
||||||
foreach (var tilable in window_positions) {
|
foreach (var tilable in window_positions) {
|
||||||
unowned WindowClone window = (WindowClone) tilable.id;
|
unowned WindowClone window = (WindowClone) tilable.id;
|
||||||
window.take_slot (tilable.rect);
|
window.take_slot (tilable.rect);
|
||||||
window.place_widgets (tilable.rect.width, tilable.rect.height);
|
window.place_widgets (tilable.rect.width, tilable.rect.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look for the next window in a direction and make this window the
|
* Look for the next window in a direction and make this window the
|
||||||
* new current_window. Used for keyboard navigation.
|
* new current_window. Used for keyboard navigation.
|
||||||
*
|
*
|
||||||
* @param direction The MetaMotionDirection in which to search for windows for.
|
* @param direction The MetaMotionDirection in which to search for windows for.
|
||||||
*/
|
*/
|
||||||
public void select_next_window (MotionDirection direction)
|
public void select_next_window (MotionDirection direction)
|
||||||
{
|
{
|
||||||
if (get_n_children () < 1)
|
if (get_n_children () < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (current_window == null) {
|
if (current_window == null) {
|
||||||
current_window = (WindowClone) get_child_at_index (0);
|
current_window = (WindowClone) get_child_at_index (0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var current_rect = current_window.slot;
|
var current_rect = current_window.slot;
|
||||||
|
|
||||||
WindowClone? closest = null;
|
WindowClone? closest = null;
|
||||||
foreach (var window in get_children ()) {
|
foreach (var window in get_children ()) {
|
||||||
if (window == current_window)
|
if (window == current_window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var window_rect = ((WindowClone) window).slot;
|
var window_rect = ((WindowClone) window).slot;
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case MotionDirection.LEFT:
|
case MotionDirection.LEFT:
|
||||||
if (window_rect.x > current_rect.x)
|
if (window_rect.x > current_rect.x)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// test for vertical intersection
|
// test for vertical intersection
|
||||||
if (window_rect.y + window_rect.height > current_rect.y
|
if (window_rect.y + window_rect.height > current_rect.y
|
||||||
&& window_rect.y < current_rect.y + current_rect.height) {
|
&& window_rect.y < current_rect.y + current_rect.height) {
|
||||||
|
|
||||||
if (closest == null
|
if (closest == null
|
||||||
|| closest.slot.x < window_rect.x)
|
|| closest.slot.x < window_rect.x)
|
||||||
closest = (WindowClone) window;
|
closest = (WindowClone) window;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MotionDirection.RIGHT:
|
case MotionDirection.RIGHT:
|
||||||
if (window_rect.x < current_rect.x)
|
if (window_rect.x < current_rect.x)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// test for vertical intersection
|
// test for vertical intersection
|
||||||
if (window_rect.y + window_rect.height > current_rect.y
|
if (window_rect.y + window_rect.height > current_rect.y
|
||||||
&& window_rect.y < current_rect.y + current_rect.height) {
|
&& window_rect.y < current_rect.y + current_rect.height) {
|
||||||
|
|
||||||
if (closest == null
|
if (closest == null
|
||||||
|| closest.slot.x > window_rect.x)
|
|| closest.slot.x > window_rect.x)
|
||||||
closest = (WindowClone) window;
|
closest = (WindowClone) window;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MotionDirection.UP:
|
case MotionDirection.UP:
|
||||||
if (window_rect.y > current_rect.y)
|
if (window_rect.y > current_rect.y)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// test for horizontal intersection
|
// test for horizontal intersection
|
||||||
if (window_rect.x + window_rect.width > current_rect.x
|
if (window_rect.x + window_rect.width > current_rect.x
|
||||||
&& window_rect.x < current_rect.x + current_rect.width) {
|
&& window_rect.x < current_rect.x + current_rect.width) {
|
||||||
|
|
||||||
if (closest == null
|
if (closest == null
|
||||||
|| closest.slot.y < window_rect.y)
|
|| closest.slot.y < window_rect.y)
|
||||||
closest = (WindowClone) window;
|
closest = (WindowClone) window;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MotionDirection.DOWN:
|
case MotionDirection.DOWN:
|
||||||
if (window_rect.y < current_rect.y)
|
if (window_rect.y < current_rect.y)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// test for horizontal intersection
|
// test for horizontal intersection
|
||||||
if (window_rect.x + window_rect.width > current_rect.x
|
if (window_rect.x + window_rect.width > current_rect.x
|
||||||
&& window_rect.x < current_rect.x + current_rect.width) {
|
&& window_rect.x < current_rect.x + current_rect.width) {
|
||||||
|
|
||||||
if (closest == null
|
if (closest == null
|
||||||
|| closest.slot.y > window_rect.y)
|
|| closest.slot.y > window_rect.y)
|
||||||
closest = (WindowClone) window;
|
closest = (WindowClone) window;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closest == null)
|
if (closest == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (current_window != null)
|
if (current_window != null)
|
||||||
current_window.active = false;
|
current_window.active = false;
|
||||||
|
|
||||||
closest.active = true;
|
closest.active = true;
|
||||||
current_window = closest;
|
current_window = closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit the selected signal for the current_window.
|
* Emit the selected signal for the current_window.
|
||||||
*/
|
*/
|
||||||
public bool activate_selected_window ()
|
public bool activate_selected_window ()
|
||||||
{
|
{
|
||||||
if (current_window != null) {
|
if (current_window != null) {
|
||||||
current_window.selected ();
|
current_window.selected ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When opened the WindowClones are animated to a tiled layout
|
* When opened the WindowClones are animated to a tiled layout
|
||||||
*/
|
*/
|
||||||
public void open (Window? selected_window = null)
|
public void open (Window? selected_window = null)
|
||||||
{
|
{
|
||||||
if (opened)
|
if (opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
opened = true;
|
opened = true;
|
||||||
|
|
||||||
// hide the highlight when opened
|
// hide the highlight when opened
|
||||||
if (selected_window != null) {
|
if (selected_window != null) {
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
unowned WindowClone tiled_window = (WindowClone) child;
|
unowned WindowClone tiled_window = (WindowClone) child;
|
||||||
if (tiled_window.window == selected_window) {
|
if (tiled_window.window == selected_window) {
|
||||||
current_window = tiled_window;
|
current_window = tiled_window;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_window != null) {
|
if (current_window != null) {
|
||||||
current_window.active = false;
|
current_window.active = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
current_window = null;
|
current_window = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure our windows are where they belong in case they were moved
|
// make sure our windows are where they belong in case they were moved
|
||||||
// while were closed.
|
// while were closed.
|
||||||
foreach (var window in get_children ())
|
foreach (var window in get_children ())
|
||||||
((WindowClone) window).transition_to_original_state (false);
|
((WindowClone) window).transition_to_original_state (false);
|
||||||
|
|
||||||
reflow ();
|
reflow ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls the transition_to_original_state() function on each child
|
* Calls the transition_to_original_state() function on each child
|
||||||
* to make them take their original locations again.
|
* to make them take their original locations again.
|
||||||
*/
|
*/
|
||||||
public void close ()
|
public void close ()
|
||||||
{
|
{
|
||||||
if (!opened)
|
if (!opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
opened = false;
|
opened = false;
|
||||||
|
|
||||||
foreach (var window in get_children ())
|
foreach (var window in get_children ())
|
||||||
((WindowClone) window).transition_to_original_state (true);
|
((WindowClone) window).transition_to_original_state (true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,176 +20,176 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Private class which is basically just a container for the actual
|
* Private class which is basically just a container for the actual
|
||||||
* icon and takes care of blending the same icon in different sizes
|
* icon and takes care of blending the same icon in different sizes
|
||||||
* over each other and various animations related to the icons
|
* over each other and various animations related to the icons
|
||||||
*/
|
*/
|
||||||
public class WindowIconActor : Actor
|
public class WindowIconActor : Actor
|
||||||
{
|
{
|
||||||
public Window window { get; construct; }
|
public Window window { get; construct; }
|
||||||
|
|
||||||
int _icon_size;
|
int _icon_size;
|
||||||
/**
|
/**
|
||||||
* The icon size of the WindowIcon. Once set the new icon will be
|
* 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.
|
* faded over the old one and the actor animates to the new size.
|
||||||
*/
|
*/
|
||||||
public int icon_size {
|
public int icon_size {
|
||||||
get {
|
get {
|
||||||
return _icon_size;
|
return _icon_size;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if (value == _icon_size)
|
if (value == _icon_size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var scale = InternalUtils.get_ui_scaling_factor ();
|
var scale = InternalUtils.get_ui_scaling_factor ();
|
||||||
_icon_size = value;
|
_icon_size = value;
|
||||||
|
|
||||||
set_size (_icon_size * scale, _icon_size * scale);
|
set_size (_icon_size * scale, _icon_size * scale);
|
||||||
|
|
||||||
fade_new_icon ();
|
fade_new_icon ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _temporary;
|
bool _temporary;
|
||||||
/**
|
/**
|
||||||
* Mark the WindowIcon as temporary. Only effect of this is that a pulse
|
* 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
|
* animation will be played on the actor. Used while DnDing window thumbs
|
||||||
* over the group.
|
* over the group.
|
||||||
*/
|
*/
|
||||||
public bool temporary {
|
public bool temporary {
|
||||||
get {
|
get {
|
||||||
return _temporary;
|
return _temporary;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if (_temporary && !value) {
|
if (_temporary && !value) {
|
||||||
remove_transition ("pulse");
|
remove_transition ("pulse");
|
||||||
} else if (!_temporary && value) {
|
} else if (!_temporary && value) {
|
||||||
var transition = new TransitionGroup ();
|
var transition = new TransitionGroup ();
|
||||||
transition.duration = 800;
|
transition.duration = 800;
|
||||||
transition.auto_reverse = true;
|
transition.auto_reverse = true;
|
||||||
transition.repeat_count = -1;
|
transition.repeat_count = -1;
|
||||||
transition.progress_mode = AnimationMode.LINEAR;
|
transition.progress_mode = AnimationMode.LINEAR;
|
||||||
|
|
||||||
var opacity_transition = new PropertyTransition ("opacity");
|
var opacity_transition = new PropertyTransition ("opacity");
|
||||||
opacity_transition.set_from_value (100);
|
opacity_transition.set_from_value (100);
|
||||||
opacity_transition.set_to_value (255);
|
opacity_transition.set_to_value (255);
|
||||||
opacity_transition.auto_reverse = true;
|
opacity_transition.auto_reverse = true;
|
||||||
|
|
||||||
var scale_x_transition = new PropertyTransition ("scale-x");
|
var scale_x_transition = new PropertyTransition ("scale-x");
|
||||||
scale_x_transition.set_from_value (0.8);
|
scale_x_transition.set_from_value (0.8);
|
||||||
scale_x_transition.set_to_value (1.1);
|
scale_x_transition.set_to_value (1.1);
|
||||||
scale_x_transition.auto_reverse = true;
|
scale_x_transition.auto_reverse = true;
|
||||||
|
|
||||||
var scale_y_transition = new PropertyTransition ("scale-y");
|
var scale_y_transition = new PropertyTransition ("scale-y");
|
||||||
scale_y_transition.set_from_value (0.8);
|
scale_y_transition.set_from_value (0.8);
|
||||||
scale_y_transition.set_to_value (1.1);
|
scale_y_transition.set_to_value (1.1);
|
||||||
scale_y_transition.auto_reverse = true;
|
scale_y_transition.auto_reverse = true;
|
||||||
|
|
||||||
transition.add_transition (opacity_transition);
|
transition.add_transition (opacity_transition);
|
||||||
transition.add_transition (scale_x_transition);
|
transition.add_transition (scale_x_transition);
|
||||||
transition.add_transition (scale_y_transition);
|
transition.add_transition (scale_y_transition);
|
||||||
|
|
||||||
add_transition ("pulse", transition);
|
add_transition ("pulse", transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
_temporary = value;
|
_temporary = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool initial = true;
|
bool initial = true;
|
||||||
|
|
||||||
WindowIcon? icon = null;
|
WindowIcon? icon = null;
|
||||||
WindowIcon? old_icon = null;
|
WindowIcon? old_icon = null;
|
||||||
|
|
||||||
public WindowIconActor (Window window)
|
public WindowIconActor (Window window)
|
||||||
{
|
{
|
||||||
Object (window: window);
|
Object (window: window);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
set_pivot_point (0.5f, 0.5f);
|
set_pivot_point (0.5f, 0.5f);
|
||||||
set_easing_mode (AnimationMode.EASE_OUT_ELASTIC);
|
set_easing_mode (AnimationMode.EASE_OUT_ELASTIC);
|
||||||
set_easing_duration (800);
|
set_easing_duration (800);
|
||||||
|
|
||||||
window.notify["on-all-workspaces"].connect (on_all_workspaces_changed);
|
window.notify["on-all-workspaces"].connect (on_all_workspaces_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
~WindowIconActor ()
|
~WindowIconActor ()
|
||||||
{
|
{
|
||||||
window.notify["on-all-workspaces"].disconnect (on_all_workspaces_changed);
|
window.notify["on-all-workspaces"].disconnect (on_all_workspaces_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_all_workspaces_changed ()
|
void on_all_workspaces_changed ()
|
||||||
{
|
{
|
||||||
// we don't display windows that are on all workspaces
|
// we don't display windows that are on all workspaces
|
||||||
if (window.on_all_workspaces)
|
if (window.on_all_workspaces)
|
||||||
destroy ();
|
destroy ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut to set both position and size of the icon
|
* Shortcut to set both position and size of the icon
|
||||||
*
|
*
|
||||||
* @param x The x coordinate to which to animate to
|
* @param x The x coordinate to which to animate to
|
||||||
* @param y The y 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
|
* @param size The size to which to animate to and display the icon in
|
||||||
*/
|
*/
|
||||||
public void place (float x, float y, int size)
|
public void place (float x, float y, int size)
|
||||||
{
|
{
|
||||||
if (initial) {
|
if (initial) {
|
||||||
save_easing_state ();
|
save_easing_state ();
|
||||||
set_easing_duration (10);
|
set_easing_duration (10);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_position (x, y);
|
set_position (x, y);
|
||||||
icon_size = size;
|
icon_size = size;
|
||||||
|
|
||||||
if (initial) {
|
if (initial) {
|
||||||
restore_easing_state ();
|
restore_easing_state ();
|
||||||
initial = false;
|
initial = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fades out the old icon and fades in the new icon
|
* Fades out the old icon and fades in the new icon
|
||||||
*/
|
*/
|
||||||
void fade_new_icon ()
|
void fade_new_icon ()
|
||||||
{
|
{
|
||||||
var scale = InternalUtils.get_ui_scaling_factor ();
|
var scale = InternalUtils.get_ui_scaling_factor ();
|
||||||
var new_icon = new WindowIcon (window, icon_size, scale);
|
var new_icon = new WindowIcon (window, icon_size, scale);
|
||||||
new_icon.add_constraint (new BindConstraint (this, BindCoordinate.SIZE, 0));
|
new_icon.add_constraint (new BindConstraint (this, BindCoordinate.SIZE, 0));
|
||||||
new_icon.opacity = 0;
|
new_icon.opacity = 0;
|
||||||
|
|
||||||
add_child (new_icon);
|
add_child (new_icon);
|
||||||
|
|
||||||
new_icon.set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
new_icon.set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||||
new_icon.set_easing_duration (500);
|
new_icon.set_easing_duration (500);
|
||||||
|
|
||||||
if (icon == null) {
|
if (icon == null) {
|
||||||
icon = new_icon;
|
icon = new_icon;
|
||||||
} else {
|
} else {
|
||||||
old_icon = icon;
|
old_icon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_icon.opacity = 255;
|
new_icon.opacity = 255;
|
||||||
|
|
||||||
if (old_icon != null) {
|
if (old_icon != null) {
|
||||||
old_icon.opacity = 0;
|
old_icon.opacity = 0;
|
||||||
var transition = old_icon.get_transition ("opacity");
|
var transition = old_icon.get_transition ("opacity");
|
||||||
if (transition != null) {
|
if (transition != null) {
|
||||||
transition.completed.connect (() => {
|
transition.completed.connect (() => {
|
||||||
old_icon.destroy ();
|
old_icon.destroy ();
|
||||||
old_icon = null;
|
old_icon = null;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
old_icon.destroy ();
|
old_icon.destroy ();
|
||||||
old_icon = null;
|
old_icon = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
icon = new_icon;
|
icon = new_icon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,368 +21,368 @@ using Clutter;
|
|||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
|
|
||||||
public enum WindowOverviewType
|
public enum WindowOverviewType
|
||||||
{
|
{
|
||||||
GRID = 0,
|
GRID = 0,
|
||||||
NATURAL
|
NATURAL
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate void WindowPlacer (Actor window, Meta.Rectangle rect);
|
public delegate void WindowPlacer (Actor window, Meta.Rectangle rect);
|
||||||
|
|
||||||
public class WindowOverview : Actor, ActivatableComponent
|
public class WindowOverview : Actor, ActivatableComponent
|
||||||
{
|
{
|
||||||
const int BORDER = 10;
|
const int BORDER = 10;
|
||||||
const int TOP_GAP = 30;
|
const int TOP_GAP = 30;
|
||||||
const int BOTTOM_GAP = 100;
|
const int BOTTOM_GAP = 100;
|
||||||
|
|
||||||
public WindowManager wm { get; construct; }
|
public WindowManager wm { get; construct; }
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
Meta.Display display;
|
Meta.Display display;
|
||||||
#else
|
#else
|
||||||
Meta.Screen screen;
|
Meta.Screen screen;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ModalProxy modal_proxy;
|
ModalProxy modal_proxy;
|
||||||
bool ready;
|
bool ready;
|
||||||
|
|
||||||
// the workspaces which we expose right now
|
// the workspaces which we expose right now
|
||||||
List<Workspace> workspaces;
|
List<Workspace> workspaces;
|
||||||
|
|
||||||
public WindowOverview (WindowManager wm)
|
public WindowOverview (WindowManager wm)
|
||||||
{
|
{
|
||||||
Object (wm : wm);
|
Object (wm : wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display = wm.get_display ();
|
display = wm.get_display ();
|
||||||
|
|
||||||
display.get_workspace_manager ().workspace_switched.connect (close);
|
display.get_workspace_manager ().workspace_switched.connect (close);
|
||||||
display.restacked.connect (restack_windows);
|
display.restacked.connect (restack_windows);
|
||||||
#else
|
#else
|
||||||
screen = wm.get_screen ();
|
screen = wm.get_screen ();
|
||||||
|
|
||||||
screen.workspace_switched.connect (close);
|
screen.workspace_switched.connect (close);
|
||||||
screen.restacked.connect (restack_windows);
|
screen.restacked.connect (restack_windows);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
visible = false;
|
visible = false;
|
||||||
ready = true;
|
ready = true;
|
||||||
reactive = true;
|
reactive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
~WindowOverview ()
|
~WindowOverview ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.restacked.disconnect (restack_windows);
|
display.restacked.disconnect (restack_windows);
|
||||||
#else
|
#else
|
||||||
screen.restacked.disconnect (restack_windows);
|
screen.restacked.disconnect (restack_windows);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool key_press_event (Clutter.KeyEvent event)
|
public override bool key_press_event (Clutter.KeyEvent event)
|
||||||
{
|
{
|
||||||
if (event.keyval == Clutter.Key.Escape) {
|
if (event.keyval == Clutter.Key.Escape) {
|
||||||
close ();
|
close ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void key_focus_out ()
|
public override void key_focus_out ()
|
||||||
{
|
{
|
||||||
if (!contains (get_stage ().key_focus))
|
if (!contains (get_stage ().key_focus))
|
||||||
close ();
|
close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool button_press_event (Clutter.ButtonEvent event)
|
public override bool button_press_event (Clutter.ButtonEvent event)
|
||||||
{
|
{
|
||||||
if (event.button == 1)
|
if (event.button == 1)
|
||||||
close ();
|
close ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public bool is_opened ()
|
public bool is_opened ()
|
||||||
{
|
{
|
||||||
return visible;
|
return visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* You may specify 'all-windows' in hints to expose all windows
|
* You may specify 'all-windows' in hints to expose all windows
|
||||||
*/
|
*/
|
||||||
public void open (HashTable<string,Variant>? hints = null)
|
public void open (HashTable<string,Variant>? hints = null)
|
||||||
{
|
{
|
||||||
if (!ready)
|
if (!ready)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
close ();
|
close ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var all_windows = hints != null && "all-windows" in hints;
|
var all_windows = hints != null && "all-windows" in hints;
|
||||||
|
|
||||||
var used_windows = new SList<Window> ();
|
var used_windows = new SList<Window> ();
|
||||||
|
|
||||||
workspaces = new List<Workspace> ();
|
workspaces = new List<Workspace> ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
||||||
if (all_windows) {
|
if (all_windows) {
|
||||||
for (int i = 0; i < manager.get_n_workspaces (); i++) {
|
for (int i = 0; i < manager.get_n_workspaces (); i++) {
|
||||||
workspaces.append (manager.get_workspace_by_index (i));
|
workspaces.append (manager.get_workspace_by_index (i));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
workspaces.append (manager.get_active_workspace ());
|
workspaces.append (manager.get_active_workspace ());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (all_windows) {
|
if (all_windows) {
|
||||||
foreach (var workspace in screen.get_workspaces ())
|
foreach (var workspace in screen.get_workspaces ())
|
||||||
workspaces.append (workspace);
|
workspaces.append (workspace);
|
||||||
} else {
|
} else {
|
||||||
workspaces.append (screen.get_active_workspace ());
|
workspaces.append (screen.get_active_workspace ());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
foreach (var workspace in workspaces) {
|
foreach (var workspace in workspaces) {
|
||||||
foreach (var window in workspace.list_windows ()) {
|
foreach (var window in workspace.list_windows ()) {
|
||||||
if (window.window_type != WindowType.NORMAL &&
|
if (window.window_type != WindowType.NORMAL &&
|
||||||
window.window_type != WindowType.DOCK &&
|
window.window_type != WindowType.DOCK &&
|
||||||
window.window_type != WindowType.DIALOG ||
|
window.window_type != WindowType.DIALOG ||
|
||||||
window.is_attached_dialog ()) {
|
window.is_attached_dialog ()) {
|
||||||
var actor = window.get_compositor_private () as WindowActor;
|
var actor = window.get_compositor_private () as WindowActor;
|
||||||
if (actor != null)
|
if (actor != null)
|
||||||
actor.hide ();
|
actor.hide ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (window.window_type == WindowType.DOCK)
|
if (window.window_type == WindowType.DOCK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// skip windows that are on all workspace except we're currently
|
// skip windows that are on all workspace except we're currently
|
||||||
// processing the workspace it actually belongs to
|
// processing the workspace it actually belongs to
|
||||||
if (window.is_on_all_workspaces () && window.get_workspace () != workspace)
|
if (window.is_on_all_workspaces () && window.get_workspace () != workspace)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
used_windows.append (window);
|
used_windows.append (window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var n_windows = used_windows.length ();
|
var n_windows = used_windows.length ();
|
||||||
if (n_windows == 0)
|
if (n_windows == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ready = false;
|
ready = false;
|
||||||
|
|
||||||
foreach (var workspace in workspaces) {
|
foreach (var workspace in workspaces) {
|
||||||
workspace.window_added.connect (add_window);
|
workspace.window_added.connect (add_window);
|
||||||
workspace.window_removed.connect (remove_window);
|
workspace.window_removed.connect (remove_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.window_left_monitor.connect (window_left_monitor);
|
display.window_left_monitor.connect (window_left_monitor);
|
||||||
|
|
||||||
// sort windows by stacking order
|
// sort windows by stacking order
|
||||||
var windows = display.sort_windows_by_stacking (used_windows);
|
var windows = display.sort_windows_by_stacking (used_windows);
|
||||||
#else
|
#else
|
||||||
screen.window_left_monitor.connect (window_left_monitor);
|
screen.window_left_monitor.connect (window_left_monitor);
|
||||||
|
|
||||||
// sort windows by stacking order
|
// sort windows by stacking order
|
||||||
var windows = screen.get_display ().sort_windows_by_stacking (used_windows);
|
var windows = screen.get_display ().sort_windows_by_stacking (used_windows);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
grab_key_focus ();
|
grab_key_focus ();
|
||||||
|
|
||||||
modal_proxy = wm.push_modal ();
|
modal_proxy = wm.push_modal ();
|
||||||
modal_proxy.keybinding_filter = keybinding_filter;
|
modal_proxy.keybinding_filter = keybinding_filter;
|
||||||
|
|
||||||
visible = true;
|
visible = true;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
for (var i = 0; i < display.get_n_monitors (); i++) {
|
for (var i = 0; i < display.get_n_monitors (); i++) {
|
||||||
var geometry = display.get_monitor_geometry (i);
|
var geometry = display.get_monitor_geometry (i);
|
||||||
#else
|
#else
|
||||||
for (var i = 0; i < screen.get_n_monitors (); i++) {
|
for (var i = 0; i < screen.get_n_monitors (); i++) {
|
||||||
var geometry = screen.get_monitor_geometry (i);
|
var geometry = screen.get_monitor_geometry (i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var container = new WindowCloneContainer (true);
|
var container = new WindowCloneContainer (true);
|
||||||
container.padding_top = TOP_GAP;
|
container.padding_top = TOP_GAP;
|
||||||
container.padding_left = container.padding_right = BORDER;
|
container.padding_left = container.padding_right = BORDER;
|
||||||
container.padding_bottom = BOTTOM_GAP;
|
container.padding_bottom = BOTTOM_GAP;
|
||||||
container.set_position (geometry.x, geometry.y);
|
container.set_position (geometry.x, geometry.y);
|
||||||
container.set_size (geometry.width, geometry.height);
|
container.set_size (geometry.width, geometry.height);
|
||||||
container.window_selected.connect (thumb_selected);
|
container.window_selected.connect (thumb_selected);
|
||||||
|
|
||||||
add_child (container);
|
add_child (container);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var window in windows) {
|
foreach (var window in windows) {
|
||||||
unowned WindowActor actor = window.get_compositor_private () as WindowActor;
|
unowned WindowActor actor = window.get_compositor_private () as WindowActor;
|
||||||
if (actor != null)
|
if (actor != null)
|
||||||
actor.hide ();
|
actor.hide ();
|
||||||
|
|
||||||
unowned WindowCloneContainer container = get_child_at_index (window.get_monitor ()) as WindowCloneContainer;
|
unowned WindowCloneContainer container = get_child_at_index (window.get_monitor ()) as WindowCloneContainer;
|
||||||
if (container == null)
|
if (container == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
container.add_window (window);
|
container.add_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var child in get_children ())
|
foreach (var child in get_children ())
|
||||||
((WindowCloneContainer) child).open ();
|
((WindowCloneContainer) child).open ();
|
||||||
|
|
||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keybinding_filter (KeyBinding binding)
|
bool keybinding_filter (KeyBinding binding)
|
||||||
{
|
{
|
||||||
var name = binding.get_name ();
|
var name = binding.get_name ();
|
||||||
return (name != "expose-windows" && name != "expose-all-windows");
|
return (name != "expose-windows" && name != "expose-all-windows");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
void restack_windows (Display display)
|
void restack_windows (Display display)
|
||||||
{
|
{
|
||||||
foreach (var child in get_children ())
|
foreach (var child in get_children ())
|
||||||
((WindowCloneContainer) child).restack_windows (display);
|
((WindowCloneContainer) child).restack_windows (display);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void restack_windows (Screen screen)
|
void restack_windows (Screen screen)
|
||||||
{
|
{
|
||||||
foreach (var child in get_children ())
|
foreach (var child in get_children ())
|
||||||
((WindowCloneContainer) child).restack_windows (screen);
|
((WindowCloneContainer) child).restack_windows (screen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void window_left_monitor (int num, Window window)
|
void window_left_monitor (int num, Window window)
|
||||||
{
|
{
|
||||||
unowned WindowCloneContainer container = get_child_at_index (num) as WindowCloneContainer;
|
unowned WindowCloneContainer container = get_child_at_index (num) as WindowCloneContainer;
|
||||||
if (container == null)
|
if (container == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// make sure the window belongs to one of our workspaces
|
// make sure the window belongs to one of our workspaces
|
||||||
foreach (var workspace in workspaces)
|
foreach (var workspace in workspaces)
|
||||||
if (window.located_on_workspace (workspace)) {
|
if (window.located_on_workspace (workspace)) {
|
||||||
container.remove_window (window);
|
container.remove_window (window);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_window (Window window)
|
void add_window (Window window)
|
||||||
{
|
{
|
||||||
if (!visible
|
if (!visible
|
||||||
|| (window.window_type != WindowType.NORMAL && window.window_type != WindowType.DIALOG))
|
|| (window.window_type != WindowType.NORMAL && window.window_type != WindowType.DIALOG))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unowned WindowCloneContainer container = get_child_at_index (window.get_monitor ()) as WindowCloneContainer;
|
unowned WindowCloneContainer container = get_child_at_index (window.get_monitor ()) as WindowCloneContainer;
|
||||||
if (container == null)
|
if (container == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// make sure the window belongs to one of our workspaces
|
// make sure the window belongs to one of our workspaces
|
||||||
foreach (var workspace in workspaces)
|
foreach (var workspace in workspaces)
|
||||||
if (window.located_on_workspace (workspace)) {
|
if (window.located_on_workspace (workspace)) {
|
||||||
container.add_window (window);
|
container.add_window (window);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_window (Window window)
|
void remove_window (Window window)
|
||||||
{
|
{
|
||||||
unowned WindowCloneContainer container = get_child_at_index (window.get_monitor ()) as WindowCloneContainer;
|
unowned WindowCloneContainer container = get_child_at_index (window.get_monitor ()) as WindowCloneContainer;
|
||||||
if (container == null)
|
if (container == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
container.remove_window (window);
|
container.remove_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
void thumb_selected (Window window)
|
void thumb_selected (Window window)
|
||||||
{
|
{
|
||||||
if (window.get_workspace () == display.get_workspace_manager ().get_active_workspace ()) {
|
if (window.get_workspace () == display.get_workspace_manager ().get_active_workspace ()) {
|
||||||
window.activate (display.get_current_time ());
|
window.activate (display.get_current_time ());
|
||||||
close ();
|
close ();
|
||||||
} else {
|
} else {
|
||||||
close ();
|
close ();
|
||||||
//wait for the animation to finish before switching
|
//wait for the animation to finish before switching
|
||||||
Timeout.add (400, () => {
|
Timeout.add (400, () => {
|
||||||
window.get_workspace ().activate_with_focus (window, display.get_current_time ());
|
window.get_workspace ().activate_with_focus (window, display.get_current_time ());
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void thumb_selected (Window window)
|
void thumb_selected (Window window)
|
||||||
{
|
{
|
||||||
if (window.get_workspace () == screen.get_active_workspace ()) {
|
if (window.get_workspace () == screen.get_active_workspace ()) {
|
||||||
window.activate (screen.get_display ().get_current_time ());
|
window.activate (screen.get_display ().get_current_time ());
|
||||||
close ();
|
close ();
|
||||||
} else {
|
} else {
|
||||||
close ();
|
close ();
|
||||||
//wait for the animation to finish before switching
|
//wait for the animation to finish before switching
|
||||||
Timeout.add (400, () => {
|
Timeout.add (400, () => {
|
||||||
window.get_workspace ().activate_with_focus (window, screen.get_display ().get_current_time ());
|
window.get_workspace ().activate_with_focus (window, screen.get_display ().get_current_time ());
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void close ()
|
public void close ()
|
||||||
{
|
{
|
||||||
if (!visible || !ready)
|
if (!visible || !ready)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var workspace in workspaces) {
|
foreach (var workspace in workspaces) {
|
||||||
workspace.window_added.disconnect (add_window);
|
workspace.window_added.disconnect (add_window);
|
||||||
workspace.window_removed.disconnect (remove_window);
|
workspace.window_removed.disconnect (remove_window);
|
||||||
}
|
}
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.window_left_monitor.disconnect (window_left_monitor);
|
display.window_left_monitor.disconnect (window_left_monitor);
|
||||||
#else
|
#else
|
||||||
screen.window_left_monitor.disconnect (window_left_monitor);
|
screen.window_left_monitor.disconnect (window_left_monitor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ready = false;
|
ready = false;
|
||||||
|
|
||||||
wm.pop_modal (modal_proxy);
|
wm.pop_modal (modal_proxy);
|
||||||
|
|
||||||
foreach (var child in get_children ()) {
|
foreach (var child in get_children ()) {
|
||||||
((WindowCloneContainer) child).close ();
|
((WindowCloneContainer) child).close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
Clutter.Threads.Timeout.add (300, () => {
|
Clutter.Threads.Timeout.add (300, () => {
|
||||||
cleanup ();
|
cleanup ();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup ()
|
void cleanup ()
|
||||||
{
|
{
|
||||||
ready = true;
|
ready = true;
|
||||||
visible = false;
|
visible = false;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
foreach (var window in display.get_workspace_manager ().get_active_workspace ().list_windows ())
|
foreach (var window in display.get_workspace_manager ().get_active_workspace ().list_windows ())
|
||||||
#else
|
#else
|
||||||
foreach (var window in screen.get_active_workspace ().list_windows ())
|
foreach (var window in screen.get_active_workspace ().list_windows ())
|
||||||
#endif
|
#endif
|
||||||
if (window.showing_on_its_workspace ())
|
if (window.showing_on_its_workspace ())
|
||||||
((Actor) window.get_compositor_private ()).show ();
|
((Actor) window.get_compositor_private ()).show ();
|
||||||
|
|
||||||
destroy_all_children ();
|
destroy_all_children ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,413 +20,413 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Utility class which adds a border and a shadow to a Background
|
* Utility class which adds a border and a shadow to a Background
|
||||||
*/
|
*/
|
||||||
class FramedBackground : BackgroundManager
|
class FramedBackground : BackgroundManager
|
||||||
{
|
{
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public FramedBackground (Display display)
|
public FramedBackground (Display display)
|
||||||
{
|
{
|
||||||
Object (display: display, monitor_index: display.get_primary_monitor (), control_position: false);
|
Object (display: display, monitor_index: display.get_primary_monitor (), control_position: false);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public FramedBackground (Screen screen)
|
public FramedBackground (Screen screen)
|
||||||
{
|
{
|
||||||
Object (screen: screen, monitor_index: screen.get_primary_monitor (), control_position: false);
|
Object (screen: screen, monitor_index: screen.get_primary_monitor (), control_position: false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var primary = display.get_primary_monitor ();
|
var primary = display.get_primary_monitor ();
|
||||||
var monitor_geom = display.get_monitor_geometry (primary);
|
var monitor_geom = display.get_monitor_geometry (primary);
|
||||||
#else
|
#else
|
||||||
var primary = screen.get_primary_monitor ();
|
var primary = screen.get_primary_monitor ();
|
||||||
var monitor_geom = screen.get_monitor_geometry (primary);
|
var monitor_geom = screen.get_monitor_geometry (primary);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var effect = new ShadowEffect (40, 5);
|
var effect = new ShadowEffect (40, 5);
|
||||||
effect.css_class = "workspace";
|
effect.css_class = "workspace";
|
||||||
add_effect (effect);
|
add_effect (effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void paint ()
|
public override void paint ()
|
||||||
{
|
{
|
||||||
base.paint ();
|
base.paint ();
|
||||||
|
|
||||||
Cogl.set_source_color4ub (0, 0, 0, 100);
|
Cogl.set_source_color4ub (0, 0, 0, 100);
|
||||||
var path = new Cogl.Path ();
|
var path = new Cogl.Path ();
|
||||||
path.rectangle (0, 0, width, height);
|
path.rectangle (0, 0, width, height);
|
||||||
path.stroke ();
|
path.stroke ();
|
||||||
|
|
||||||
Cogl.set_source_color4ub (255, 255, 255, 25);
|
Cogl.set_source_color4ub (255, 255, 255, 25);
|
||||||
path.rectangle (0.5f, 0.5f, width - 1, height - 1);
|
path.rectangle (0.5f, 0.5f, width - 1, height - 1);
|
||||||
path.stroke ();
|
path.stroke ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the container which manages a clone of the background which will
|
* This is the container which manages a clone of the background which will
|
||||||
* be scaled and animated inwards, a WindowCloneContainer for the windows on
|
* be scaled and animated inwards, a WindowCloneContainer for the windows on
|
||||||
* this workspace and also holds the instance for this workspace's IconGroup.
|
* this workspace and also holds the instance for this workspace's IconGroup.
|
||||||
* The latter is not added to the WorkspaceClone itself though but to a container
|
* The latter is not added to the WorkspaceClone itself though but to a container
|
||||||
* of the MultitaskingView.
|
* of the MultitaskingView.
|
||||||
*/
|
*/
|
||||||
public class WorkspaceClone : Actor
|
public class WorkspaceClone : Actor
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The offset of the scaled background to the bottom of the monitor bounds
|
* The offset of the scaled background to the bottom of the monitor bounds
|
||||||
*/
|
*/
|
||||||
public const int BOTTOM_OFFSET = 100;
|
public const int BOTTOM_OFFSET = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset of the scaled background to the top of the monitor bounds
|
* The offset of the scaled background to the top of the monitor bounds
|
||||||
*/
|
*/
|
||||||
const int TOP_OFFSET = 20;
|
const int TOP_OFFSET = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of time a window has to be over the WorkspaceClone while in drag
|
* The amount of time a window has to be over the WorkspaceClone while in drag
|
||||||
* before we activate the workspace.
|
* before we activate the workspace.
|
||||||
*/
|
*/
|
||||||
const int HOVER_ACTIVATE_DELAY = 400;
|
const int HOVER_ACTIVATE_DELAY = 400;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A window has been selected, the MultitaskingView should consider activating
|
* A window has been selected, the MultitaskingView should consider activating
|
||||||
* and closing the view.
|
* and closing the view.
|
||||||
*/
|
*/
|
||||||
public signal void window_selected (Window window);
|
public signal void window_selected (Window window);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The background has been selected. Switch to that workspace.
|
* The background has been selected. Switch to that workspace.
|
||||||
*
|
*
|
||||||
* @param close_view If the MultitaskingView should also consider closing itself
|
* @param close_view If the MultitaskingView should also consider closing itself
|
||||||
* after switching.
|
* after switching.
|
||||||
*/
|
*/
|
||||||
public signal void selected (bool close_view);
|
public signal void selected (bool close_view);
|
||||||
|
|
||||||
public Workspace workspace { get; construct; }
|
public Workspace workspace { get; construct; }
|
||||||
public IconGroup icon_group { get; private set; }
|
public IconGroup icon_group { get; private set; }
|
||||||
public WindowCloneContainer window_container { get; private set; }
|
public WindowCloneContainer window_container { get; private set; }
|
||||||
|
|
||||||
bool _active = false;
|
bool _active = false;
|
||||||
/**
|
/**
|
||||||
* If this WorkspaceClone is currently the active one. Also sets the active
|
* If this WorkspaceClone is currently the active one. Also sets the active
|
||||||
* state on its IconGroup.
|
* state on its IconGroup.
|
||||||
*/
|
*/
|
||||||
public bool active {
|
public bool active {
|
||||||
get {
|
get {
|
||||||
return _active;
|
return _active;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
_active = value;
|
_active = value;
|
||||||
icon_group.active = value;
|
icon_group.active = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BackgroundManager background;
|
BackgroundManager background;
|
||||||
bool opened;
|
bool opened;
|
||||||
|
|
||||||
uint hover_activate_timeout = 0;
|
uint hover_activate_timeout = 0;
|
||||||
|
|
||||||
public WorkspaceClone (Workspace workspace)
|
public WorkspaceClone (Workspace workspace)
|
||||||
{
|
{
|
||||||
Object (workspace: workspace);
|
Object (workspace: workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
opened = false;
|
opened = false;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Display display = workspace.get_display ();
|
unowned Display display = workspace.get_display ();
|
||||||
var monitor_geometry = display.get_monitor_geometry (display.get_primary_monitor ());
|
var monitor_geometry = display.get_monitor_geometry (display.get_primary_monitor ());
|
||||||
#else
|
#else
|
||||||
unowned Screen screen = workspace.get_screen ();
|
unowned Screen screen = workspace.get_screen ();
|
||||||
var monitor_geometry = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
var monitor_geometry = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
background = new FramedBackground (display);
|
background = new FramedBackground (display);
|
||||||
#else
|
#else
|
||||||
background = new FramedBackground (screen);
|
background = new FramedBackground (screen);
|
||||||
#endif
|
#endif
|
||||||
background.reactive = true;
|
background.reactive = true;
|
||||||
background.button_press_event.connect (() => {
|
background.button_press_event.connect (() => {
|
||||||
selected (true);
|
selected (true);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
window_container = new WindowCloneContainer ();
|
window_container = new WindowCloneContainer ();
|
||||||
window_container.window_selected.connect ((w) => { window_selected (w); });
|
window_container.window_selected.connect ((w) => { window_selected (w); });
|
||||||
window_container.set_size (monitor_geometry.width, monitor_geometry.height);
|
window_container.set_size (monitor_geometry.width, monitor_geometry.height);
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.restacked.connect (window_container.restack_windows);
|
display.restacked.connect (window_container.restack_windows);
|
||||||
#else
|
#else
|
||||||
screen.restacked.connect (window_container.restack_windows);
|
screen.restacked.connect (window_container.restack_windows);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
icon_group = new IconGroup (workspace);
|
icon_group = new IconGroup (workspace);
|
||||||
icon_group.selected.connect (() => {
|
icon_group.selected.connect (() => {
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
if (workspace == display.get_workspace_manager ().get_active_workspace ())
|
if (workspace == display.get_workspace_manager ().get_active_workspace ())
|
||||||
Utils.bell (display);
|
Utils.bell (display);
|
||||||
else
|
else
|
||||||
selected (false);
|
selected (false);
|
||||||
#else
|
#else
|
||||||
if (workspace == screen.get_active_workspace ())
|
if (workspace == screen.get_active_workspace ())
|
||||||
Utils.bell (screen);
|
Utils.bell (screen);
|
||||||
else
|
else
|
||||||
selected (false);
|
selected (false);
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
var icons_drop_action = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
var icons_drop_action = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
||||||
icon_group.add_action (icons_drop_action);
|
icon_group.add_action (icons_drop_action);
|
||||||
|
|
||||||
var background_drop_action = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
var background_drop_action = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
||||||
background.add_action (background_drop_action);
|
background.add_action (background_drop_action);
|
||||||
background_drop_action.crossed.connect ((target, hovered) => {
|
background_drop_action.crossed.connect ((target, hovered) => {
|
||||||
if (!hovered && hover_activate_timeout != 0) {
|
if (!hovered && hover_activate_timeout != 0) {
|
||||||
Source.remove (hover_activate_timeout);
|
Source.remove (hover_activate_timeout);
|
||||||
hover_activate_timeout = 0;
|
hover_activate_timeout = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hovered && hover_activate_timeout == 0) {
|
if (hovered && hover_activate_timeout == 0) {
|
||||||
hover_activate_timeout = Timeout.add (HOVER_ACTIVATE_DELAY, () => {
|
hover_activate_timeout = Timeout.add (HOVER_ACTIVATE_DELAY, () => {
|
||||||
selected (false);
|
selected (false);
|
||||||
hover_activate_timeout = 0;
|
hover_activate_timeout = 0;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
display.window_entered_monitor.connect (window_entered_monitor);
|
display.window_entered_monitor.connect (window_entered_monitor);
|
||||||
display.window_left_monitor.connect (window_left_monitor);
|
display.window_left_monitor.connect (window_left_monitor);
|
||||||
#else
|
#else
|
||||||
screen.window_entered_monitor.connect (window_entered_monitor);
|
screen.window_entered_monitor.connect (window_entered_monitor);
|
||||||
screen.window_left_monitor.connect (window_left_monitor);
|
screen.window_left_monitor.connect (window_left_monitor);
|
||||||
#endif
|
#endif
|
||||||
workspace.window_added.connect (add_window);
|
workspace.window_added.connect (add_window);
|
||||||
workspace.window_removed.connect (remove_window);
|
workspace.window_removed.connect (remove_window);
|
||||||
|
|
||||||
add_child (background);
|
add_child (background);
|
||||||
add_child (window_container);
|
add_child (window_container);
|
||||||
|
|
||||||
// add existing windows
|
// add existing windows
|
||||||
var windows = workspace.list_windows ();
|
var windows = workspace.list_windows ();
|
||||||
foreach (var window in windows) {
|
foreach (var window in windows) {
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
if (window.window_type == WindowType.NORMAL
|
if (window.window_type == WindowType.NORMAL
|
||||||
&& !window.on_all_workspaces
|
&& !window.on_all_workspaces
|
||||||
&& window.get_monitor () == display.get_primary_monitor ()) {
|
&& window.get_monitor () == display.get_primary_monitor ()) {
|
||||||
window_container.add_window (window);
|
window_container.add_window (window);
|
||||||
icon_group.add_window (window, true);
|
icon_group.add_window (window, true);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (window.window_type == WindowType.NORMAL
|
if (window.window_type == WindowType.NORMAL
|
||||||
&& !window.on_all_workspaces
|
&& !window.on_all_workspaces
|
||||||
&& window.get_monitor () == screen.get_primary_monitor ()) {
|
&& window.get_monitor () == screen.get_primary_monitor ()) {
|
||||||
window_container.add_window (window);
|
window_container.add_window (window);
|
||||||
icon_group.add_window (window, true);
|
icon_group.add_window (window, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
var listener = WindowListener.get_default ();
|
var listener = WindowListener.get_default ();
|
||||||
listener.window_no_longer_on_all_workspaces.connect (add_window);
|
listener.window_no_longer_on_all_workspaces.connect (add_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
~WorkspaceClone ()
|
~WorkspaceClone ()
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = workspace.get_display ();
|
unowned Meta.Display display = workspace.get_display ();
|
||||||
|
|
||||||
display.restacked.disconnect (window_container.restack_windows);
|
display.restacked.disconnect (window_container.restack_windows);
|
||||||
|
|
||||||
display.window_entered_monitor.disconnect (window_entered_monitor);
|
display.window_entered_monitor.disconnect (window_entered_monitor);
|
||||||
display.window_left_monitor.disconnect (window_left_monitor);
|
display.window_left_monitor.disconnect (window_left_monitor);
|
||||||
#else
|
#else
|
||||||
unowned Screen screen = workspace.get_screen ();
|
unowned Screen screen = workspace.get_screen ();
|
||||||
|
|
||||||
screen.restacked.disconnect (window_container.restack_windows);
|
screen.restacked.disconnect (window_container.restack_windows);
|
||||||
|
|
||||||
screen.window_entered_monitor.disconnect (window_entered_monitor);
|
screen.window_entered_monitor.disconnect (window_entered_monitor);
|
||||||
screen.window_left_monitor.disconnect (window_left_monitor);
|
screen.window_left_monitor.disconnect (window_left_monitor);
|
||||||
#endif
|
#endif
|
||||||
workspace.window_added.disconnect (add_window);
|
workspace.window_added.disconnect (add_window);
|
||||||
workspace.window_removed.disconnect (remove_window);
|
workspace.window_removed.disconnect (remove_window);
|
||||||
|
|
||||||
var listener = WindowListener.get_default ();
|
var listener = WindowListener.get_default ();
|
||||||
listener.window_no_longer_on_all_workspaces.disconnect (add_window);
|
listener.window_no_longer_on_all_workspaces.disconnect (add_window);
|
||||||
|
|
||||||
background.destroy ();
|
background.destroy ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a window to the WindowCloneContainer and the IconGroup if it really
|
* Add a window to the WindowCloneContainer and the IconGroup if it really
|
||||||
* belongs to this workspace and this monitor.
|
* belongs to this workspace and this monitor.
|
||||||
*/
|
*/
|
||||||
void add_window (Window window)
|
void add_window (Window window)
|
||||||
{
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
if (window.window_type != WindowType.NORMAL
|
if (window.window_type != WindowType.NORMAL
|
||||||
|| window.get_workspace () != workspace
|
|| window.get_workspace () != workspace
|
||||||
|| window.on_all_workspaces
|
|| window.on_all_workspaces
|
||||||
|| window.get_monitor () != window.get_display ().get_primary_monitor ())
|
|| window.get_monitor () != window.get_display ().get_primary_monitor ())
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
if (window.window_type != WindowType.NORMAL
|
if (window.window_type != WindowType.NORMAL
|
||||||
|| window.get_workspace () != workspace
|
|| window.get_workspace () != workspace
|
||||||
|| window.on_all_workspaces
|
|| window.on_all_workspaces
|
||||||
|| window.get_monitor () != window.get_screen ().get_primary_monitor ())
|
|| window.get_monitor () != window.get_screen ().get_primary_monitor ())
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
foreach (var child in window_container.get_children ())
|
foreach (var child in window_container.get_children ())
|
||||||
if (((WindowClone) child).window == window)
|
if (((WindowClone) child).window == window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window_container.add_window (window);
|
window_container.add_window (window);
|
||||||
icon_group.add_window (window);
|
icon_group.add_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a window from the WindowCloneContainer and the IconGroup
|
* Remove a window from the WindowCloneContainer and the IconGroup
|
||||||
*/
|
*/
|
||||||
void remove_window (Window window)
|
void remove_window (Window window)
|
||||||
{
|
{
|
||||||
window_container.remove_window (window);
|
window_container.remove_window (window);
|
||||||
icon_group.remove_window (window, opened);
|
icon_group.remove_window (window, opened);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
void window_entered_monitor (Display display, int monitor, Window window)
|
void window_entered_monitor (Display display, int monitor, Window window)
|
||||||
{
|
{
|
||||||
add_window (window);
|
add_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_left_monitor (Display display, int monitor, Window window)
|
void window_left_monitor (Display display, int monitor, Window window)
|
||||||
{
|
{
|
||||||
if (monitor == display.get_primary_monitor ())
|
if (monitor == display.get_primary_monitor ())
|
||||||
remove_window (window);
|
remove_window (window);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void window_entered_monitor (Screen screen, int monitor, Window window)
|
void window_entered_monitor (Screen screen, int monitor, Window window)
|
||||||
{
|
{
|
||||||
add_window (window);
|
add_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_left_monitor (Screen screen, int monitor, Window window)
|
void window_left_monitor (Screen screen, int monitor, Window window)
|
||||||
{
|
{
|
||||||
if (monitor == screen.get_primary_monitor ())
|
if (monitor == screen.get_primary_monitor ())
|
||||||
remove_window (window);
|
remove_window (window);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void update_size (Meta.Rectangle monitor_geometry)
|
void update_size (Meta.Rectangle monitor_geometry)
|
||||||
{
|
{
|
||||||
if (window_container.width != monitor_geometry.width || window_container.height != monitor_geometry.height) {
|
if (window_container.width != monitor_geometry.width || window_container.height != monitor_geometry.height) {
|
||||||
window_container.set_size (monitor_geometry.width, monitor_geometry.height);
|
window_container.set_size (monitor_geometry.width, monitor_geometry.height);
|
||||||
background.set_size (window_container.width, window_container.height);
|
background.set_size (window_container.width, window_container.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility function to shrink a MetaRectangle on all sides for the given amount.
|
* Utility function to shrink a MetaRectangle on all sides for the given amount.
|
||||||
* Negative amounts will scale it instead.
|
* Negative amounts will scale it instead.
|
||||||
*
|
*
|
||||||
* @param amount The amount in px to shrink.
|
* @param amount The amount in px to shrink.
|
||||||
*/
|
*/
|
||||||
static inline void shrink_rectangle (ref Meta.Rectangle rect, int amount)
|
static inline void shrink_rectangle (ref Meta.Rectangle rect, int amount)
|
||||||
{
|
{
|
||||||
rect.x += amount;
|
rect.x += amount;
|
||||||
rect.y += amount;
|
rect.y += amount;
|
||||||
rect.width -= amount * 2;
|
rect.width -= amount * 2;
|
||||||
rect.height -= amount * 2;
|
rect.height -= amount * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animates the background to its scale, causes a redraw on the IconGroup and
|
* Animates the background to its scale, causes a redraw on the IconGroup and
|
||||||
* makes sure the WindowCloneContainer animates its windows to their tiled layout.
|
* makes sure the WindowCloneContainer animates its windows to their tiled layout.
|
||||||
* Also sets the current_window of the WindowCloneContainer to the active window
|
* Also sets the current_window of the WindowCloneContainer to the active window
|
||||||
* if it belongs to this workspace.
|
* if it belongs to this workspace.
|
||||||
*/
|
*/
|
||||||
public void open ()
|
public void open ()
|
||||||
{
|
{
|
||||||
if (opened)
|
if (opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
opened = true;
|
opened = true;
|
||||||
|
|
||||||
var scale_factor = InternalUtils.get_ui_scaling_factor ();
|
var scale_factor = InternalUtils.get_ui_scaling_factor ();
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
var display = workspace.get_display ();
|
var display = workspace.get_display ();
|
||||||
|
|
||||||
var monitor = display.get_monitor_geometry (display.get_primary_monitor ());
|
var monitor = display.get_monitor_geometry (display.get_primary_monitor ());
|
||||||
#else
|
#else
|
||||||
var screen = workspace.get_screen ();
|
var screen = workspace.get_screen ();
|
||||||
var display = screen.get_display ();
|
var display = screen.get_display ();
|
||||||
|
|
||||||
var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
||||||
#endif
|
#endif
|
||||||
var scale = (float)(monitor.height - TOP_OFFSET * scale_factor - BOTTOM_OFFSET * scale_factor) / monitor.height;
|
var scale = (float)(monitor.height - TOP_OFFSET * scale_factor - BOTTOM_OFFSET * scale_factor) / monitor.height;
|
||||||
var pivotY = TOP_OFFSET * scale_factor / (monitor.height - monitor.height * scale);
|
var pivotY = TOP_OFFSET * scale_factor / (monitor.height - monitor.height * scale);
|
||||||
|
|
||||||
update_size (monitor);
|
update_size (monitor);
|
||||||
|
|
||||||
background.set_pivot_point (0.5f, pivotY);
|
background.set_pivot_point (0.5f, pivotY);
|
||||||
|
|
||||||
background.save_easing_state ();
|
background.save_easing_state ();
|
||||||
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
||||||
background.set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
background.set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
||||||
background.set_scale (scale, scale);
|
background.set_scale (scale, scale);
|
||||||
background.restore_easing_state ();
|
background.restore_easing_state ();
|
||||||
|
|
||||||
Meta.Rectangle area = {
|
Meta.Rectangle area = {
|
||||||
(int)Math.floorf (monitor.x + monitor.width - monitor.width * scale) / 2,
|
(int)Math.floorf (monitor.x + monitor.width - monitor.width * scale) / 2,
|
||||||
(int)Math.floorf (monitor.y + TOP_OFFSET * scale_factor),
|
(int)Math.floorf (monitor.y + TOP_OFFSET * scale_factor),
|
||||||
(int)Math.floorf (monitor.width * scale),
|
(int)Math.floorf (monitor.width * scale),
|
||||||
(int)Math.floorf (monitor.height * scale)
|
(int)Math.floorf (monitor.height * scale)
|
||||||
};
|
};
|
||||||
shrink_rectangle (ref area, 32);
|
shrink_rectangle (ref area, 32);
|
||||||
|
|
||||||
window_container.padding_top = TOP_OFFSET * scale_factor;
|
window_container.padding_top = TOP_OFFSET * scale_factor;
|
||||||
window_container.padding_left =
|
window_container.padding_left =
|
||||||
window_container.padding_right = (int)(monitor.width - monitor.width * scale) / 2;
|
window_container.padding_right = (int)(monitor.width - monitor.width * scale) / 2;
|
||||||
window_container.padding_bottom = BOTTOM_OFFSET * scale_factor;
|
window_container.padding_bottom = BOTTOM_OFFSET * scale_factor;
|
||||||
|
|
||||||
icon_group.redraw ();
|
icon_group.redraw ();
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
window_container.open (display.get_workspace_manager ().get_active_workspace () == workspace ? display.get_focus_window () : null);
|
window_container.open (display.get_workspace_manager ().get_active_workspace () == workspace ? display.get_focus_window () : null);
|
||||||
#else
|
#else
|
||||||
window_container.open (screen.get_active_workspace () == workspace ? display.get_focus_window () : null);
|
window_container.open (screen.get_active_workspace () == workspace ? display.get_focus_window () : null);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the view again by animating the background back to its scale and
|
* Close the view again by animating the background back to its scale and
|
||||||
* the windows back to their old locations.
|
* the windows back to their old locations.
|
||||||
*/
|
*/
|
||||||
public void close ()
|
public void close ()
|
||||||
{
|
{
|
||||||
if (!opened)
|
if (!opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
opened = false;
|
opened = false;
|
||||||
|
|
||||||
background.save_easing_state ();
|
background.save_easing_state ();
|
||||||
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
||||||
background.set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
background.set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
||||||
background.set_scale (1, 1);
|
background.set_scale (1, 1);
|
||||||
background.restore_easing_state ();
|
background.restore_easing_state ();
|
||||||
|
|
||||||
window_container.close ();
|
window_container.close ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,112 +20,112 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class WorkspaceInsertThumb : Actor
|
public class WorkspaceInsertThumb : Actor
|
||||||
{
|
{
|
||||||
public const int EXPAND_DELAY = 300;
|
public const int EXPAND_DELAY = 300;
|
||||||
|
|
||||||
public int workspace_index { get; construct set; }
|
public int workspace_index { get; construct set; }
|
||||||
public bool expanded { get; set; default = false; }
|
public bool expanded { get; set; default = false; }
|
||||||
public int delay { get; set; default = EXPAND_DELAY; }
|
public int delay { get; set; default = EXPAND_DELAY; }
|
||||||
|
|
||||||
uint expand_timeout = 0;
|
uint expand_timeout = 0;
|
||||||
|
|
||||||
public WorkspaceInsertThumb (int workspace_index)
|
public WorkspaceInsertThumb (int workspace_index)
|
||||||
{
|
{
|
||||||
Object (workspace_index: workspace_index);
|
Object (workspace_index: workspace_index);
|
||||||
|
|
||||||
var scale = InternalUtils.get_ui_scaling_factor ();
|
var scale = InternalUtils.get_ui_scaling_factor ();
|
||||||
width = IconGroupContainer.SPACING * scale;
|
width = IconGroupContainer.SPACING * scale;
|
||||||
height = IconGroupContainer.GROUP_WIDTH * scale;
|
height = IconGroupContainer.GROUP_WIDTH * scale;
|
||||||
y = (IconGroupContainer.GROUP_WIDTH * scale - IconGroupContainer.SPACING * scale) / 2;
|
y = (IconGroupContainer.GROUP_WIDTH * scale - IconGroupContainer.SPACING * scale) / 2;
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
set_pivot_point (0.5f, 0.5f);
|
set_pivot_point (0.5f, 0.5f);
|
||||||
reactive = true;
|
reactive = true;
|
||||||
x_align = Clutter.ActorAlign.CENTER;
|
x_align = Clutter.ActorAlign.CENTER;
|
||||||
|
|
||||||
var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
var drop = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
|
||||||
drop.crossed.connect ((target, hovered) => {
|
drop.crossed.connect ((target, hovered) => {
|
||||||
if (!Prefs.get_dynamic_workspaces () && (target != null && target is WindowClone))
|
if (!Prefs.get_dynamic_workspaces () && (target != null && target is WindowClone))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!hovered) {
|
if (!hovered) {
|
||||||
if (expand_timeout != 0) {
|
if (expand_timeout != 0) {
|
||||||
Source.remove (expand_timeout);
|
Source.remove (expand_timeout);
|
||||||
expand_timeout = 0;
|
expand_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
transform (false);
|
transform (false);
|
||||||
} else
|
} else
|
||||||
expand_timeout = Timeout.add (delay, expand);
|
expand_timeout = Timeout.add (delay, expand);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_action (drop);
|
add_action (drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_window_thumb (Window window)
|
public void set_window_thumb (Window window)
|
||||||
{
|
{
|
||||||
destroy_all_children ();
|
destroy_all_children ();
|
||||||
|
|
||||||
var scale = InternalUtils.get_ui_scaling_factor ();
|
var scale = InternalUtils.get_ui_scaling_factor ();
|
||||||
var icon = new WindowIcon (window, IconGroupContainer.GROUP_WIDTH, scale);
|
var icon = new WindowIcon (window, IconGroupContainer.GROUP_WIDTH, scale);
|
||||||
icon.x = IconGroupContainer.SPACING;
|
icon.x = IconGroupContainer.SPACING;
|
||||||
icon.x_align = ActorAlign.CENTER;
|
icon.x_align = ActorAlign.CENTER;
|
||||||
add_child (icon);
|
add_child (icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool expand ()
|
bool expand ()
|
||||||
{
|
{
|
||||||
expand_timeout = 0;
|
expand_timeout = 0;
|
||||||
|
|
||||||
transform (true);
|
transform (true);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void transform (bool expand)
|
void transform (bool expand)
|
||||||
{
|
{
|
||||||
save_easing_state ();
|
save_easing_state ();
|
||||||
set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||||
set_easing_duration (200);
|
set_easing_duration (200);
|
||||||
|
|
||||||
var scale = InternalUtils.get_ui_scaling_factor ();
|
var scale = InternalUtils.get_ui_scaling_factor ();
|
||||||
if (!expand) {
|
if (!expand) {
|
||||||
remove_transition ("pulse");
|
remove_transition ("pulse");
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
width = IconGroupContainer.SPACING * scale;
|
width = IconGroupContainer.SPACING * scale;
|
||||||
expanded = false;
|
expanded = false;
|
||||||
} else {
|
} else {
|
||||||
add_pulse_animation ();
|
add_pulse_animation ();
|
||||||
opacity = 200;
|
opacity = 200;
|
||||||
width = IconGroupContainer.GROUP_WIDTH * scale + IconGroupContainer.SPACING * 2;
|
width = IconGroupContainer.GROUP_WIDTH * scale + IconGroupContainer.SPACING * 2;
|
||||||
expanded = true;
|
expanded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_easing_state ();
|
restore_easing_state ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_pulse_animation ()
|
void add_pulse_animation ()
|
||||||
{
|
{
|
||||||
var transition = new TransitionGroup ();
|
var transition = new TransitionGroup ();
|
||||||
transition.duration = 800;
|
transition.duration = 800;
|
||||||
transition.auto_reverse = true;
|
transition.auto_reverse = true;
|
||||||
transition.repeat_count = -1;
|
transition.repeat_count = -1;
|
||||||
transition.progress_mode = AnimationMode.LINEAR;
|
transition.progress_mode = AnimationMode.LINEAR;
|
||||||
|
|
||||||
var scale_x_transition = new PropertyTransition ("scale-x");
|
var scale_x_transition = new PropertyTransition ("scale-x");
|
||||||
scale_x_transition.set_from_value (0.8);
|
scale_x_transition.set_from_value (0.8);
|
||||||
scale_x_transition.set_to_value (1.1);
|
scale_x_transition.set_to_value (1.1);
|
||||||
scale_x_transition.auto_reverse = true;
|
scale_x_transition.auto_reverse = true;
|
||||||
|
|
||||||
var scale_y_transition = new PropertyTransition ("scale-y");
|
var scale_y_transition = new PropertyTransition ("scale-y");
|
||||||
scale_y_transition.set_from_value (0.8);
|
scale_y_transition.set_from_value (0.8);
|
||||||
scale_y_transition.set_to_value (1.1);
|
scale_y_transition.set_to_value (1.1);
|
||||||
scale_y_transition.auto_reverse = true;
|
scale_y_transition.auto_reverse = true;
|
||||||
|
|
||||||
transition.add_transition (scale_x_transition);
|
transition.add_transition (scale_x_transition);
|
||||||
transition.add_transition (scale_y_transition);
|
transition.add_transition (scale_y_transition);
|
||||||
|
|
||||||
add_transition ("pulse", transition);
|
add_transition ("pulse", transition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,126 +20,126 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public struct WindowGeometry {
|
public struct WindowGeometry {
|
||||||
Meta.Rectangle inner;
|
Meta.Rectangle inner;
|
||||||
Meta.Rectangle outer;
|
Meta.Rectangle outer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WindowListener : Object
|
public class WindowListener : Object
|
||||||
{
|
{
|
||||||
static WindowListener? instance = null;
|
static WindowListener? instance = null;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
public static void init (Meta.Display display)
|
public static void init (Meta.Display display)
|
||||||
{
|
{
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
instance = new WindowListener ();
|
instance = new WindowListener ();
|
||||||
|
|
||||||
foreach (unowned Meta.WindowActor actor in display.get_window_actors ()) {
|
foreach (unowned Meta.WindowActor actor in display.get_window_actors ()) {
|
||||||
if (actor.is_destroyed ())
|
if (actor.is_destroyed ())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
unowned Meta.Window window = actor.get_meta_window ();
|
unowned Meta.Window window = actor.get_meta_window ();
|
||||||
if (window.window_type == WindowType.NORMAL)
|
if (window.window_type == WindowType.NORMAL)
|
||||||
instance.monitor_window (window);
|
instance.monitor_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
display.window_created.connect ((window) => {
|
display.window_created.connect ((window) => {
|
||||||
if (window.window_type == WindowType.NORMAL)
|
if (window.window_type == WindowType.NORMAL)
|
||||||
instance.monitor_window (window);
|
instance.monitor_window (window);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public static void init (Screen screen)
|
public static void init (Screen screen)
|
||||||
{
|
{
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
instance = new WindowListener ();
|
instance = new WindowListener ();
|
||||||
|
|
||||||
foreach (unowned Meta.WindowActor actor in screen.get_window_actors ()) {
|
foreach (unowned Meta.WindowActor actor in screen.get_window_actors ()) {
|
||||||
if (actor.is_destroyed ())
|
if (actor.is_destroyed ())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
unowned Meta.Window window = actor.get_meta_window ();
|
unowned Meta.Window window = actor.get_meta_window ();
|
||||||
if (window.window_type == WindowType.NORMAL)
|
if (window.window_type == WindowType.NORMAL)
|
||||||
instance.monitor_window (window);
|
instance.monitor_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
screen.get_display ().window_created.connect ((window) => {
|
screen.get_display ().window_created.connect ((window) => {
|
||||||
if (window.window_type == WindowType.NORMAL)
|
if (window.window_type == WindowType.NORMAL)
|
||||||
instance.monitor_window (window);
|
instance.monitor_window (window);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public static unowned WindowListener get_default ()
|
public static unowned WindowListener get_default ()
|
||||||
requires (instance != null)
|
requires (instance != null)
|
||||||
{
|
{
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public signal void window_no_longer_on_all_workspaces (Window window);
|
public signal void window_no_longer_on_all_workspaces (Window window);
|
||||||
|
|
||||||
Gee.HashMap<Meta.Window, WindowGeometry?> unmaximized_state_geometry;
|
Gee.HashMap<Meta.Window, WindowGeometry?> unmaximized_state_geometry;
|
||||||
|
|
||||||
WindowListener ()
|
WindowListener ()
|
||||||
{
|
{
|
||||||
unmaximized_state_geometry = new Gee.HashMap<Meta.Window, WindowGeometry?> ();
|
unmaximized_state_geometry = new Gee.HashMap<Meta.Window, WindowGeometry?> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void monitor_window (Window window)
|
void monitor_window (Window window)
|
||||||
{
|
{
|
||||||
window.notify.connect (window_notify);
|
window.notify.connect (window_notify);
|
||||||
window.unmanaged.connect (window_removed);
|
window.unmanaged.connect (window_removed);
|
||||||
|
|
||||||
window_maximized_changed (window);
|
window_maximized_changed (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_notify (Object object, ParamSpec pspec)
|
void window_notify (Object object, ParamSpec pspec)
|
||||||
{
|
{
|
||||||
var window = (Window) object;
|
var window = (Window) object;
|
||||||
|
|
||||||
switch (pspec.name) {
|
switch (pspec.name) {
|
||||||
case "maximized-horizontally":
|
case "maximized-horizontally":
|
||||||
case "maximized-vertically":
|
case "maximized-vertically":
|
||||||
window_maximized_changed (window);
|
window_maximized_changed (window);
|
||||||
break;
|
break;
|
||||||
case "on-all-workspaces":
|
case "on-all-workspaces":
|
||||||
window_on_all_workspaces_changed (window);
|
window_on_all_workspaces_changed (window);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_on_all_workspaces_changed (Window window)
|
void window_on_all_workspaces_changed (Window window)
|
||||||
{
|
{
|
||||||
if (window.on_all_workspaces)
|
if (window.on_all_workspaces)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window_no_longer_on_all_workspaces (window);
|
window_no_longer_on_all_workspaces (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_maximized_changed (Window window)
|
void window_maximized_changed (Window window)
|
||||||
{
|
{
|
||||||
WindowGeometry window_geometry = {};
|
WindowGeometry window_geometry = {};
|
||||||
window_geometry.inner = window.get_frame_rect ();
|
window_geometry.inner = window.get_frame_rect ();
|
||||||
window_geometry.outer = window.get_buffer_rect ();
|
window_geometry.outer = window.get_buffer_rect ();
|
||||||
|
|
||||||
unmaximized_state_geometry.@set (window, window_geometry);
|
unmaximized_state_geometry.@set (window, window_geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WindowGeometry? get_unmaximized_state_geometry (Window window)
|
public WindowGeometry? get_unmaximized_state_geometry (Window window)
|
||||||
{
|
{
|
||||||
return unmaximized_state_geometry.@get (window);
|
return unmaximized_state_geometry.@get (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_removed (Window window)
|
void window_removed (Window window)
|
||||||
{
|
{
|
||||||
window.notify.disconnect (window_notify);
|
window.notify.disconnect (window_notify);
|
||||||
window.unmanaged.disconnect (window_removed);
|
window.unmanaged.disconnect (window_removed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -19,407 +19,407 @@ using Meta;
|
|||||||
|
|
||||||
namespace Gala
|
namespace Gala
|
||||||
{
|
{
|
||||||
public class WorkspaceManager : Object
|
public class WorkspaceManager : Object
|
||||||
{
|
{
|
||||||
public static void init (WindowManager wm)
|
public static void init (WindowManager wm)
|
||||||
requires (instance == null)
|
requires (instance == null)
|
||||||
{
|
{
|
||||||
instance = new WorkspaceManager (wm);
|
instance = new WorkspaceManager (wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unowned WorkspaceManager get_default ()
|
public static unowned WorkspaceManager get_default ()
|
||||||
requires (instance != null)
|
requires (instance != null)
|
||||||
{
|
{
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WorkspaceManager? instance = null;
|
static WorkspaceManager? instance = null;
|
||||||
|
|
||||||
public WindowManager wm { get; construct; }
|
public WindowManager wm { get; construct; }
|
||||||
|
|
||||||
Gee.LinkedList<Workspace> workspaces_marked_removed;
|
Gee.LinkedList<Workspace> workspaces_marked_removed;
|
||||||
int remove_freeze_count = 0;
|
int remove_freeze_count = 0;
|
||||||
|
|
||||||
WorkspaceManager (WindowManager wm)
|
WorkspaceManager (WindowManager wm)
|
||||||
{
|
{
|
||||||
Object (wm: wm);
|
Object (wm: wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
construct
|
construct
|
||||||
{
|
{
|
||||||
workspaces_marked_removed = new Gee.LinkedList<Workspace> ();
|
workspaces_marked_removed = new Gee.LinkedList<Workspace> ();
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = wm.get_display ();
|
unowned Meta.Display display = wm.get_display ();
|
||||||
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
||||||
|
|
||||||
if (Prefs.get_dynamic_workspaces ())
|
if (Prefs.get_dynamic_workspaces ())
|
||||||
manager.override_workspace_layout (DisplayCorner.TOPLEFT, false, 1, -1);
|
manager.override_workspace_layout (DisplayCorner.TOPLEFT, false, 1, -1);
|
||||||
|
|
||||||
for (var i = 0; i < manager.get_n_workspaces (); i++)
|
for (var i = 0; i < manager.get_n_workspaces (); i++)
|
||||||
workspace_added (manager, i);
|
workspace_added (manager, i);
|
||||||
|
|
||||||
Prefs.add_listener (prefs_listener);
|
Prefs.add_listener (prefs_listener);
|
||||||
|
|
||||||
manager.workspace_switched.connect_after (workspace_switched);
|
manager.workspace_switched.connect_after (workspace_switched);
|
||||||
manager.workspace_added.connect (workspace_added);
|
manager.workspace_added.connect (workspace_added);
|
||||||
manager.workspace_removed.connect_after (workspace_removed);
|
manager.workspace_removed.connect_after (workspace_removed);
|
||||||
display.window_entered_monitor.connect (window_entered_monitor);
|
display.window_entered_monitor.connect (window_entered_monitor);
|
||||||
display.window_left_monitor.connect (window_left_monitor);
|
display.window_left_monitor.connect (window_left_monitor);
|
||||||
|
|
||||||
// make sure the last workspace has no windows on it
|
// make sure the last workspace has no windows on it
|
||||||
if (Prefs.get_dynamic_workspaces ()
|
if (Prefs.get_dynamic_workspaces ()
|
||||||
&& Utils.get_n_windows (manager.get_workspace_by_index (manager.get_n_workspaces () - 1)) > 0)
|
&& Utils.get_n_windows (manager.get_workspace_by_index (manager.get_n_workspaces () - 1)) > 0)
|
||||||
append_workspace ();
|
append_workspace ();
|
||||||
#else
|
#else
|
||||||
unowned Screen screen = wm.get_screen ();
|
unowned Screen screen = wm.get_screen ();
|
||||||
|
|
||||||
if (Prefs.get_dynamic_workspaces ())
|
if (Prefs.get_dynamic_workspaces ())
|
||||||
screen.override_workspace_layout (ScreenCorner.TOPLEFT, false, 1, -1);
|
screen.override_workspace_layout (ScreenCorner.TOPLEFT, false, 1, -1);
|
||||||
|
|
||||||
for (var i = 0; i < screen.get_n_workspaces (); i++)
|
for (var i = 0; i < screen.get_n_workspaces (); i++)
|
||||||
workspace_added (screen, i);
|
workspace_added (screen, i);
|
||||||
|
|
||||||
Prefs.add_listener (prefs_listener);
|
Prefs.add_listener (prefs_listener);
|
||||||
|
|
||||||
screen.workspace_switched.connect_after (workspace_switched);
|
screen.workspace_switched.connect_after (workspace_switched);
|
||||||
screen.workspace_added.connect (workspace_added);
|
screen.workspace_added.connect (workspace_added);
|
||||||
screen.workspace_removed.connect_after (workspace_removed);
|
screen.workspace_removed.connect_after (workspace_removed);
|
||||||
screen.window_entered_monitor.connect (window_entered_monitor);
|
screen.window_entered_monitor.connect (window_entered_monitor);
|
||||||
screen.window_left_monitor.connect (window_left_monitor);
|
screen.window_left_monitor.connect (window_left_monitor);
|
||||||
|
|
||||||
// make sure the last workspace has no windows on it
|
// make sure the last workspace has no windows on it
|
||||||
if (Prefs.get_dynamic_workspaces ()
|
if (Prefs.get_dynamic_workspaces ()
|
||||||
&& Utils.get_n_windows (screen.get_workspace_by_index (screen.get_n_workspaces () - 1)) > 0)
|
&& Utils.get_n_windows (screen.get_workspace_by_index (screen.get_n_workspaces () - 1)) > 0)
|
||||||
append_workspace ();
|
append_workspace ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// There are some empty workspace at startup
|
// There are some empty workspace at startup
|
||||||
cleanup ();
|
cleanup ();
|
||||||
}
|
}
|
||||||
|
|
||||||
~WorkspaceManager ()
|
~WorkspaceManager ()
|
||||||
{
|
{
|
||||||
Prefs.remove_listener (prefs_listener);
|
Prefs.remove_listener (prefs_listener);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
|
||||||
unowned Meta.Display display = wm.get_display ();
|
|
||||||
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
|
||||||
manager.workspace_added.disconnect (workspace_added);
|
|
||||||
manager.workspace_switched.disconnect (workspace_switched);
|
|
||||||
manager.workspace_removed.disconnect (workspace_removed);
|
|
||||||
display.window_entered_monitor.disconnect (window_entered_monitor);
|
|
||||||
display.window_left_monitor.disconnect (window_left_monitor);
|
|
||||||
#else
|
|
||||||
unowned Screen screen = wm.get_screen ();
|
|
||||||
screen.workspace_added.disconnect (workspace_added);
|
|
||||||
screen.workspace_switched.disconnect (workspace_switched);
|
|
||||||
screen.workspace_removed.disconnect (workspace_removed);
|
|
||||||
screen.window_entered_monitor.disconnect (window_entered_monitor);
|
|
||||||
screen.window_left_monitor.disconnect (window_left_monitor);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
|
||||||
void workspace_added (Meta.WorkspaceManager manager, int index)
|
|
||||||
{
|
|
||||||
var workspace = manager.get_workspace_by_index (index);
|
|
||||||
if (workspace == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
workspace.window_added.connect (window_added);
|
|
||||||
workspace.window_removed.connect (window_removed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void workspace_removed (Meta.WorkspaceManager manager, int index)
|
|
||||||
{
|
|
||||||
List<Workspace> existing_workspaces = null;
|
|
||||||
for (int i = 0; i < manager.get_n_workspaces (); i++) {
|
|
||||||
existing_workspaces.append (manager.get_workspace_by_index (i));
|
|
||||||
}
|
|
||||||
|
|
||||||
var it = workspaces_marked_removed.iterator ();
|
|
||||||
while (it.next ()) {
|
|
||||||
var workspace = it.@get ();
|
|
||||||
|
|
||||||
if (existing_workspaces.index (workspace) < 0)
|
|
||||||
it.remove ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void workspace_switched (Meta.WorkspaceManager manager, int from, int to, MotionDirection direction)
|
|
||||||
{
|
|
||||||
if (!Prefs.get_dynamic_workspaces ())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// remove empty workspaces after we switched away from them unless it's the last one
|
|
||||||
var prev_workspace = manager.get_workspace_by_index (from);
|
|
||||||
if (Utils.get_n_windows (prev_workspace) < 1
|
|
||||||
&& from != manager.get_n_workspaces () - 1) {
|
|
||||||
remove_workspace (prev_workspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void workspace_added (Screen screen, int index)
|
|
||||||
{
|
|
||||||
var workspace = screen.get_workspace_by_index (index);
|
|
||||||
if (workspace == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
workspace.window_added.connect (window_added);
|
|
||||||
workspace.window_removed.connect (window_removed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void workspace_removed (Screen screen, int index)
|
|
||||||
{
|
|
||||||
unowned List<Workspace> existing_workspaces = screen.get_workspaces ();
|
|
||||||
|
|
||||||
var it = workspaces_marked_removed.iterator ();
|
|
||||||
while (it.next ()) {
|
|
||||||
if (existing_workspaces.index (it.@get ()) < 0)
|
|
||||||
it.remove ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void workspace_switched (Screen screen, int from, int to, MotionDirection direction)
|
|
||||||
{
|
|
||||||
if (!Prefs.get_dynamic_workspaces ())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// remove empty workspaces after we switched away from them unless it's the last one
|
|
||||||
var prev_workspace = screen.get_workspace_by_index (from);
|
|
||||||
if (Utils.get_n_windows (prev_workspace) < 1
|
|
||||||
&& from != screen.get_n_workspaces () - 1) {
|
|
||||||
remove_workspace (prev_workspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void window_added (Workspace? workspace, Window window)
|
|
||||||
{
|
|
||||||
if (workspace == null || !Prefs.get_dynamic_workspaces ()
|
|
||||||
|| window.on_all_workspaces)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
|
||||||
unowned Meta.WorkspaceManager manager = workspace.get_display ().get_workspace_manager ();
|
|
||||||
int last_workspace = manager.get_n_workspaces () - 1;
|
|
||||||
#else
|
|
||||||
unowned Screen screen = workspace.get_screen ();
|
|
||||||
int last_workspace = screen.get_n_workspaces () - 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((window.window_type == WindowType.NORMAL
|
|
||||||
|| window.window_type == WindowType.DIALOG
|
|
||||||
|| window.window_type == WindowType.MODAL_DIALOG)
|
|
||||||
&& workspace.index () == last_workspace)
|
|
||||||
append_workspace ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_removed (Workspace? workspace, Window window)
|
|
||||||
{
|
|
||||||
if (workspace == null || !Prefs.get_dynamic_workspaces () || window.on_all_workspaces)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
|
||||||
unowned Meta.WorkspaceManager manager = workspace.get_display ().get_workspace_manager ();
|
|
||||||
var index = workspace.index ();
|
|
||||||
bool is_active_workspace = workspace == manager.get_active_workspace ();
|
|
||||||
int last_workspace = manager.get_n_workspaces () - 1;
|
|
||||||
#else
|
|
||||||
unowned Screen screen = workspace.get_screen ();
|
|
||||||
var index = screen.get_workspaces ().index (workspace);
|
|
||||||
bool is_active_workspace = workspace == screen.get_active_workspace ();
|
|
||||||
int last_workspace = screen.get_n_workspaces () - 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (window.window_type != WindowType.NORMAL
|
|
||||||
&& window.window_type != WindowType.DIALOG
|
|
||||||
&& window.window_type != WindowType.MODAL_DIALOG)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// has already been removed
|
|
||||||
if (index < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// remove it right away if it was the active workspace and it's not the very last
|
|
||||||
// or we are in modal-mode
|
|
||||||
if ((!is_active_workspace || wm.is_modal ())
|
|
||||||
&& remove_freeze_count < 1
|
|
||||||
&& Utils.get_n_windows (workspace) < 1
|
|
||||||
&& index != last_workspace) {
|
|
||||||
remove_workspace (workspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
|
||||||
void window_entered_monitor (Meta.Display display, int monitor, Window window)
|
|
||||||
{
|
|
||||||
if (InternalUtils.workspaces_only_on_primary ()
|
|
||||||
&& monitor == display.get_primary_monitor ())
|
|
||||||
window_added (window.get_workspace (), window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_left_monitor (Meta.Display display, int monitor, Window window)
|
|
||||||
{
|
|
||||||
if (InternalUtils.workspaces_only_on_primary ()
|
|
||||||
&& monitor == display.get_primary_monitor ())
|
|
||||||
window_removed (window.get_workspace (), window);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void window_entered_monitor (Screen screen, int monitor, Window window)
|
|
||||||
{
|
|
||||||
if (InternalUtils.workspaces_only_on_primary ()
|
|
||||||
&& monitor == screen.get_primary_monitor ())
|
|
||||||
window_added (window.get_workspace (), window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_left_monitor (Screen screen, int monitor, Window window)
|
|
||||||
{
|
|
||||||
if (InternalUtils.workspaces_only_on_primary ()
|
|
||||||
&& monitor == screen.get_primary_monitor ())
|
|
||||||
window_removed (window.get_workspace (), window);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void prefs_listener (Meta.Preference pref)
|
|
||||||
{
|
|
||||||
#if HAS_MUTTER330
|
|
||||||
unowned Meta.WorkspaceManager manager = wm.get_display ().get_workspace_manager ();
|
|
||||||
|
|
||||||
if (pref == Preference.DYNAMIC_WORKSPACES && Prefs.get_dynamic_workspaces ()) {
|
|
||||||
// if the last workspace has a window, we need to append a new workspace
|
|
||||||
if (Utils.get_n_windows (manager.get_workspace_by_index (manager.get_n_workspaces () - 1)) > 0)
|
|
||||||
append_workspace ();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
unowned Screen screen = wm.get_screen ();
|
|
||||||
|
|
||||||
if (pref == Preference.DYNAMIC_WORKSPACES && Prefs.get_dynamic_workspaces ()) {
|
|
||||||
// if the last workspace has a window, we need to append a new workspace
|
|
||||||
if (Utils.get_n_windows (screen.get_workspace_by_index (screen.get_n_workspaces () - 1)) > 0)
|
|
||||||
append_workspace ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void append_workspace ()
|
|
||||||
{
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = wm.get_display ();
|
unowned Meta.Display display = wm.get_display ();
|
||||||
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
||||||
|
manager.workspace_added.disconnect (workspace_added);
|
||||||
manager.append_new_workspace (false, display.get_current_time ());
|
manager.workspace_switched.disconnect (workspace_switched);
|
||||||
|
manager.workspace_removed.disconnect (workspace_removed);
|
||||||
|
display.window_entered_monitor.disconnect (window_entered_monitor);
|
||||||
|
display.window_left_monitor.disconnect (window_left_monitor);
|
||||||
#else
|
#else
|
||||||
unowned Screen screen = wm.get_screen ();
|
unowned Screen screen = wm.get_screen ();
|
||||||
|
screen.workspace_added.disconnect (workspace_added);
|
||||||
screen.append_new_workspace (false, screen.get_display ().get_current_time ());
|
screen.workspace_switched.disconnect (workspace_switched);
|
||||||
|
screen.workspace_removed.disconnect (workspace_removed);
|
||||||
|
screen.window_entered_monitor.disconnect (window_entered_monitor);
|
||||||
|
screen.window_left_monitor.disconnect (window_left_monitor);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#if HAS_MUTTER330
|
||||||
* Make sure we switch to a different workspace and remove the given one
|
void workspace_added (Meta.WorkspaceManager manager, int index)
|
||||||
*
|
{
|
||||||
* @param workspace The workspace to remove
|
var workspace = manager.get_workspace_by_index (index);
|
||||||
*/
|
if (workspace == null)
|
||||||
void remove_workspace (Workspace workspace)
|
return;
|
||||||
{
|
|
||||||
|
workspace.window_added.connect (window_added);
|
||||||
|
workspace.window_removed.connect (window_removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_removed (Meta.WorkspaceManager manager, int index)
|
||||||
|
{
|
||||||
|
List<Workspace> existing_workspaces = null;
|
||||||
|
for (int i = 0; i < manager.get_n_workspaces (); i++) {
|
||||||
|
existing_workspaces.append (manager.get_workspace_by_index (i));
|
||||||
|
}
|
||||||
|
|
||||||
|
var it = workspaces_marked_removed.iterator ();
|
||||||
|
while (it.next ()) {
|
||||||
|
var workspace = it.@get ();
|
||||||
|
|
||||||
|
if (existing_workspaces.index (workspace) < 0)
|
||||||
|
it.remove ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_switched (Meta.WorkspaceManager manager, int from, int to, MotionDirection direction)
|
||||||
|
{
|
||||||
|
if (!Prefs.get_dynamic_workspaces ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// remove empty workspaces after we switched away from them unless it's the last one
|
||||||
|
var prev_workspace = manager.get_workspace_by_index (from);
|
||||||
|
if (Utils.get_n_windows (prev_workspace) < 1
|
||||||
|
&& from != manager.get_n_workspaces () - 1) {
|
||||||
|
remove_workspace (prev_workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void workspace_added (Screen screen, int index)
|
||||||
|
{
|
||||||
|
var workspace = screen.get_workspace_by_index (index);
|
||||||
|
if (workspace == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
workspace.window_added.connect (window_added);
|
||||||
|
workspace.window_removed.connect (window_removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_removed (Screen screen, int index)
|
||||||
|
{
|
||||||
|
unowned List<Workspace> existing_workspaces = screen.get_workspaces ();
|
||||||
|
|
||||||
|
var it = workspaces_marked_removed.iterator ();
|
||||||
|
while (it.next ()) {
|
||||||
|
if (existing_workspaces.index (it.@get ()) < 0)
|
||||||
|
it.remove ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_switched (Screen screen, int from, int to, MotionDirection direction)
|
||||||
|
{
|
||||||
|
if (!Prefs.get_dynamic_workspaces ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// remove empty workspaces after we switched away from them unless it's the last one
|
||||||
|
var prev_workspace = screen.get_workspace_by_index (from);
|
||||||
|
if (Utils.get_n_windows (prev_workspace) < 1
|
||||||
|
&& from != screen.get_n_workspaces () - 1) {
|
||||||
|
remove_workspace (prev_workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void window_added (Workspace? workspace, Window window)
|
||||||
|
{
|
||||||
|
if (workspace == null || !Prefs.get_dynamic_workspaces ()
|
||||||
|
|| window.on_all_workspaces)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if HAS_MUTTER330
|
||||||
|
unowned Meta.WorkspaceManager manager = workspace.get_display ().get_workspace_manager ();
|
||||||
|
int last_workspace = manager.get_n_workspaces () - 1;
|
||||||
|
#else
|
||||||
|
unowned Screen screen = workspace.get_screen ();
|
||||||
|
int last_workspace = screen.get_n_workspaces () - 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((window.window_type == WindowType.NORMAL
|
||||||
|
|| window.window_type == WindowType.DIALOG
|
||||||
|
|| window.window_type == WindowType.MODAL_DIALOG)
|
||||||
|
&& workspace.index () == last_workspace)
|
||||||
|
append_workspace ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_removed (Workspace? workspace, Window window)
|
||||||
|
{
|
||||||
|
if (workspace == null || !Prefs.get_dynamic_workspaces () || window.on_all_workspaces)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if HAS_MUTTER330
|
||||||
|
unowned Meta.WorkspaceManager manager = workspace.get_display ().get_workspace_manager ();
|
||||||
|
var index = workspace.index ();
|
||||||
|
bool is_active_workspace = workspace == manager.get_active_workspace ();
|
||||||
|
int last_workspace = manager.get_n_workspaces () - 1;
|
||||||
|
#else
|
||||||
|
unowned Screen screen = workspace.get_screen ();
|
||||||
|
var index = screen.get_workspaces ().index (workspace);
|
||||||
|
bool is_active_workspace = workspace == screen.get_active_workspace ();
|
||||||
|
int last_workspace = screen.get_n_workspaces () - 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (window.window_type != WindowType.NORMAL
|
||||||
|
&& window.window_type != WindowType.DIALOG
|
||||||
|
&& window.window_type != WindowType.MODAL_DIALOG)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// has already been removed
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// remove it right away if it was the active workspace and it's not the very last
|
||||||
|
// or we are in modal-mode
|
||||||
|
if ((!is_active_workspace || wm.is_modal ())
|
||||||
|
&& remove_freeze_count < 1
|
||||||
|
&& Utils.get_n_windows (workspace) < 1
|
||||||
|
&& index != last_workspace) {
|
||||||
|
remove_workspace (workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAS_MUTTER330
|
||||||
|
void window_entered_monitor (Meta.Display display, int monitor, Window window)
|
||||||
|
{
|
||||||
|
if (InternalUtils.workspaces_only_on_primary ()
|
||||||
|
&& monitor == display.get_primary_monitor ())
|
||||||
|
window_added (window.get_workspace (), window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_left_monitor (Meta.Display display, int monitor, Window window)
|
||||||
|
{
|
||||||
|
if (InternalUtils.workspaces_only_on_primary ()
|
||||||
|
&& monitor == display.get_primary_monitor ())
|
||||||
|
window_removed (window.get_workspace (), window);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void window_entered_monitor (Screen screen, int monitor, Window window)
|
||||||
|
{
|
||||||
|
if (InternalUtils.workspaces_only_on_primary ()
|
||||||
|
&& monitor == screen.get_primary_monitor ())
|
||||||
|
window_added (window.get_workspace (), window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_left_monitor (Screen screen, int monitor, Window window)
|
||||||
|
{
|
||||||
|
if (InternalUtils.workspaces_only_on_primary ()
|
||||||
|
&& monitor == screen.get_primary_monitor ())
|
||||||
|
window_removed (window.get_workspace (), window);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void prefs_listener (Meta.Preference pref)
|
||||||
|
{
|
||||||
|
#if HAS_MUTTER330
|
||||||
|
unowned Meta.WorkspaceManager manager = wm.get_display ().get_workspace_manager ();
|
||||||
|
|
||||||
|
if (pref == Preference.DYNAMIC_WORKSPACES && Prefs.get_dynamic_workspaces ()) {
|
||||||
|
// if the last workspace has a window, we need to append a new workspace
|
||||||
|
if (Utils.get_n_windows (manager.get_workspace_by_index (manager.get_n_workspaces () - 1)) > 0)
|
||||||
|
append_workspace ();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
unowned Screen screen = wm.get_screen ();
|
||||||
|
|
||||||
|
if (pref == Preference.DYNAMIC_WORKSPACES && Prefs.get_dynamic_workspaces ()) {
|
||||||
|
// if the last workspace has a window, we need to append a new workspace
|
||||||
|
if (Utils.get_n_windows (screen.get_workspace_by_index (screen.get_n_workspaces () - 1)) > 0)
|
||||||
|
append_workspace ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_workspace ()
|
||||||
|
{
|
||||||
|
#if HAS_MUTTER330
|
||||||
|
unowned Meta.Display display = wm.get_display ();
|
||||||
|
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
||||||
|
|
||||||
|
manager.append_new_workspace (false, display.get_current_time ());
|
||||||
|
#else
|
||||||
|
unowned Screen screen = wm.get_screen ();
|
||||||
|
|
||||||
|
screen.append_new_workspace (false, screen.get_display ().get_current_time ());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure we switch to a different workspace and remove the given one
|
||||||
|
*
|
||||||
|
* @param workspace The workspace to remove
|
||||||
|
*/
|
||||||
|
void remove_workspace (Workspace workspace)
|
||||||
|
{
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = workspace.get_display ();
|
unowned Meta.Display display = workspace.get_display ();
|
||||||
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
||||||
var time = display.get_current_time ();
|
var time = display.get_current_time ();
|
||||||
unowned Meta.Workspace active_workspace = manager.get_active_workspace ();
|
unowned Meta.Workspace active_workspace = manager.get_active_workspace ();
|
||||||
#else
|
#else
|
||||||
unowned Screen screen = workspace.get_screen ();
|
unowned Screen screen = workspace.get_screen ();
|
||||||
|
|
||||||
var time = screen.get_display ().get_current_time ();
|
var time = screen.get_display ().get_current_time ();
|
||||||
unowned Meta.Workspace active_workspace = screen.get_active_workspace ();
|
unowned Meta.Workspace active_workspace = screen.get_active_workspace ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (workspace == active_workspace) {
|
if (workspace == active_workspace) {
|
||||||
Workspace? next = null;
|
Workspace? next = null;
|
||||||
|
|
||||||
next = workspace.get_neighbor (MotionDirection.LEFT);
|
next = workspace.get_neighbor (MotionDirection.LEFT);
|
||||||
// if it's the first one we may have another one to the right
|
// if it's the first one we may have another one to the right
|
||||||
if (next == workspace || next == null)
|
if (next == workspace || next == null)
|
||||||
next = workspace.get_neighbor (MotionDirection.RIGHT);
|
next = workspace.get_neighbor (MotionDirection.RIGHT);
|
||||||
|
|
||||||
if (next != null)
|
if (next != null)
|
||||||
next.activate (time);
|
next.activate (time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// workspace has already been removed
|
// workspace has already been removed
|
||||||
if (workspace in workspaces_marked_removed) {
|
if (workspace in workspaces_marked_removed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
workspace.window_added.disconnect (window_added);
|
workspace.window_added.disconnect (window_added);
|
||||||
workspace.window_removed.disconnect (window_removed);
|
workspace.window_removed.disconnect (window_removed);
|
||||||
|
|
||||||
workspaces_marked_removed.add (workspace);
|
workspaces_marked_removed.add (workspace);
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
manager.remove_workspace (workspace, time);
|
manager.remove_workspace (workspace, time);
|
||||||
#else
|
#else
|
||||||
screen.remove_workspace (workspace, time);
|
screen.remove_workspace (workspace, time);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporarily disables removing workspaces when they are empty
|
* Temporarily disables removing workspaces when they are empty
|
||||||
*/
|
*/
|
||||||
public void freeze_remove ()
|
public void freeze_remove ()
|
||||||
{
|
{
|
||||||
remove_freeze_count++;
|
remove_freeze_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo the effect of freeze_remove()
|
* Undo the effect of freeze_remove()
|
||||||
*/
|
*/
|
||||||
public void thaw_remove ()
|
public void thaw_remove ()
|
||||||
{
|
{
|
||||||
remove_freeze_count--;
|
remove_freeze_count--;
|
||||||
|
|
||||||
assert (remove_freeze_count >= 0);
|
assert (remove_freeze_count >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If workspaces are dynamic, checks if there are empty workspaces that should
|
* If workspaces are dynamic, checks if there are empty workspaces that should
|
||||||
* be removed. Particularily useful in conjunction with freeze/thaw_remove to
|
* be removed. Particularily useful in conjunction with freeze/thaw_remove to
|
||||||
* cleanup after an operation that required stable workspace/window indices
|
* cleanup after an operation that required stable workspace/window indices
|
||||||
*/
|
*/
|
||||||
public void cleanup ()
|
public void cleanup ()
|
||||||
{
|
{
|
||||||
if (!Prefs.get_dynamic_workspaces ())
|
if (!Prefs.get_dynamic_workspaces ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if HAS_MUTTER330
|
#if HAS_MUTTER330
|
||||||
unowned Meta.Display display = wm.get_display ();
|
unowned Meta.Display display = wm.get_display ();
|
||||||
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
|
||||||
List<Meta.Workspace> workspaces = null;
|
List<Meta.Workspace> workspaces = null;
|
||||||
for (int i = 0; i < manager.get_n_workspaces (); i++) {
|
for (int i = 0; i < manager.get_n_workspaces (); i++) {
|
||||||
workspaces.append (manager.get_workspace_by_index (i));
|
workspaces.append (manager.get_workspace_by_index (i));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var workspace in workspaces) {
|
foreach (var workspace in workspaces) {
|
||||||
var last_index = manager.get_n_workspaces () - 1;
|
var last_index = manager.get_n_workspaces () - 1;
|
||||||
if (Utils.get_n_windows (workspace) < 1
|
if (Utils.get_n_windows (workspace) < 1
|
||||||
&& workspace.index () != last_index) {
|
&& workspace.index () != last_index) {
|
||||||
remove_workspace (workspace);
|
remove_workspace (workspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
var screen = wm.get_screen ();
|
var screen = wm.get_screen ();
|
||||||
var last_index = screen.get_n_workspaces () - 1;
|
var last_index = screen.get_n_workspaces () - 1;
|
||||||
unowned GLib.List<Meta.Workspace> workspaces = screen.get_workspaces ();
|
unowned GLib.List<Meta.Workspace> workspaces = screen.get_workspaces ();
|
||||||
|
|
||||||
foreach (var workspace in workspaces) {
|
foreach (var workspace in workspaces) {
|
||||||
if (Utils.get_n_windows (workspace) < 1
|
if (Utils.get_n_windows (workspace) < 1
|
||||||
&& workspace.index () != last_index) {
|
&& workspace.index () != last_index) {
|
||||||
remove_workspace (workspace);
|
remove_workspace (workspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user