Some major code-style changes and clean up

* add copyright headers
* don't use "this."
* use tabs to indent
* some varible renames
* factor out some callbacks

There is probably more to come
This commit is contained in:
Rico Tzschichholz 2012-05-31 23:17:10 +02:00
parent 43cb1fa553
commit 50399b4ad5
11 changed files with 1160 additions and 999 deletions

View File

@ -41,10 +41,9 @@ ensure_vala_version("0.16.0" MINIMUM)
include(ValaPrecompile) include(ValaPrecompile)
vala_precompile(VALA_C vala_precompile(VALA_C
src/gala.vala src/Main.vala
src/gala-settings.vala src/Settings.vala
src/gala-plugin.vala src/TextShadowEffect.vala
src/main.vala
src/Widgets/WorkspaceSwitcher.vala src/Widgets/WorkspaceSwitcher.vala
src/Widgets/WindowSwitcher.vala src/Widgets/WindowSwitcher.vala
src/Widgets/CornerMenu.vala src/Widgets/CornerMenu.vala
@ -69,4 +68,4 @@ add_schema ("data/org.pantheon.desktop.gala.gschema.xml")
add_executable(gala ${VALA_C})#src/main.c) add_executable(gala ${VALA_C})#src/main.c)
install(TARGETS gala RUNTIME DESTINATION bin) install(TARGETS gala RUNTIME DESTINATION bin)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/gala.desktop DESTINATION share/applications) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/gala.desktop DESTINATION share/applications)

497
src/Main.vala Normal file
View File

@ -0,0 +1,497 @@
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
using Meta;
namespace Gala
{
public enum InputArea {
NONE,
FULLSCREEN,
HOT_CORNER
}
public class Plugin : Meta.Plugin
{
WorkspaceSwitcher wswitcher;
WindowSwitcher winswitcher;
CornerMenu corner_menu;
Clutter.Actor elements;
public Plugin ()
{
if (Settings.get_default().use_gnome_defaults)
return;
Prefs.override_preference_schema ("attach-modal-dialogs", SCHEMA);
Prefs.override_preference_schema ("button-layout", SCHEMA);
Prefs.override_preference_schema ("edge-tiling", SCHEMA);
Prefs.override_preference_schema ("enable-animations", SCHEMA);
Prefs.override_preference_schema ("theme", SCHEMA);
}
public override void start ()
{
elements = Compositor.get_stage_for_screen (screen);
Compositor.get_window_group_for_screen (screen).reparent (elements);
Compositor.get_overlay_group_for_screen (screen).reparent (elements);
Compositor.get_stage_for_screen (screen).add_child (elements);
screen.override_workspace_layout (ScreenCorner.TOPLEFT, false, -1, 4);
int width, height;
screen.get_size (out width, out height);
corner_menu = new CornerMenu (this);
elements.add_child (corner_menu);
corner_menu.visible = false;
wswitcher = new WorkspaceSwitcher (this, width, height);
wswitcher.workspaces = 4;
elements.add_child (wswitcher);
winswitcher = new WindowSwitcher (this);
elements.add_child (winswitcher);
KeyBinding.set_custom_handler ("panel-main-menu", () => {
try {
Process.spawn_command_line_async (
Settings.get_default().panel_main_menu_action);
} catch (Error e) { warning (e.message); }
});
KeyBinding.set_custom_handler ("switch-windows",
(display, screen, window, ev, binding) => {
window_switcher (display, screen, binding, false);
});
KeyBinding.set_custom_handler ("switch-windows-backward",
(display, screen, window, ev, binding) => {
window_switcher (display, screen, binding, true);
});
KeyBinding.set_custom_handler ("switch-to-workspace-left", () => {});
KeyBinding.set_custom_handler ("switch-to-workspace-right", () => {});
KeyBinding.set_custom_handler ("switch-to-workspace-up", (d, s) => workspace_switcher (s, true));
KeyBinding.set_custom_handler ("switch-to-workspace-down", (d, s) => workspace_switcher (s, false));
KeyBinding.set_custom_handler ("move-to-workspace-left", () => {});
KeyBinding.set_custom_handler ("move-to-workspace-right", () => {});
KeyBinding.set_custom_handler ("move-to-workspace-up", (d, s, w) => move_window (w, true) );
KeyBinding.set_custom_handler ("move-to-workspace-down", (d, s, w) => move_window (w, false) );
/*shadows*/
ShadowFactory.get_default ().set_params ("normal", true, {30, -1, 0, 35, 120});
/*hot corner*/
var hot_corner = new Clutter.Rectangle ();
hot_corner.x = width - 2;
hot_corner.y = height - 2;
hot_corner.width = 2;
hot_corner.height = 2;
hot_corner.reactive = true;
hot_corner.enter_event.connect (() => {
corner_menu.show ();
return false;
});
Compositor.get_overlay_group_for_screen (screen).add_child (hot_corner);
if (Settings.get_default ().enable_manager_corner)
set_input_area (InputArea.HOT_CORNER);
else
set_input_area (InputArea.NONE);
Settings.get_default ().notify["enable-manager-corner"].connect (() => {
if (Settings.get_default ().enable_manager_corner)
set_input_area (InputArea.HOT_CORNER);
else
set_input_area (InputArea.NONE);
});
}
/**
* set the area where clutter can receive events
**/
public void set_input_area (InputArea area)
{
X.Rectangle rect;
int width, height;
screen.get_size (out width, out height);
switch (area) {
case InputArea.FULLSCREEN:
rect = {0, 0, (short)width, (short)height};
break;
case InputArea.HOT_CORNER: //leave one pix in the bottom left
rect = {(short)(width - 1), (short)(height - 1), 1, 1};
break;
default:
Util.empty_stage_input_region (screen);
return;
}
var xregion = X.Fixes.create_region (screen.get_display ().get_xdisplay (), {rect});
Util.set_stage_input_region (screen, xregion);
}
public void move_window (Window? window, bool up)
{
if (window == null || window.is_on_all_workspaces ())
return;
var idx = screen.get_active_workspace ().index () + ((up)?-1:1);
window.change_workspace_by_index (idx, false,
screen.get_display ().get_current_time ());
screen.get_workspace_by_index (idx).activate_with_focus (window,
screen.get_display ().get_current_time ());
}
public new void begin_modal ()
{
base.begin_modal (x_get_stage_window (Compositor.get_stage_for_screen (screen)), {}, 0, screen.get_display ().get_current_time ());
}
public new void end_modal ()
{
base.end_modal (get_screen ().get_display ().get_current_time ());
}
public void window_switcher (Display display, Screen screen, KeyBinding binding, bool backward)
{
if (screen.get_display ().get_tab_list (TabList.NORMAL, screen, screen.get_active_workspace ()).length () == 0)
return;
begin_modal ();
int width, height;
screen.get_size (out width, out height);
winswitcher.list_windows (display, screen, binding, backward);
winswitcher.x = width / 2 - winswitcher.width / 2;
winswitcher.y = height / 2 - winswitcher.height / 2;
winswitcher.grab_key_focus ();
winswitcher.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, opacity : 255);
}
public void workspace_switcher (Screen screen, bool up)
{
int width, height;
screen.get_size (out width, out height);
wswitcher.x = width / 2 - wswitcher.width / 2;
wswitcher.y = height / 2 - wswitcher.height / 2;
wswitcher.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 100, opacity:255);
wswitcher.workspace = move_workspaces (up);;
begin_modal ();
wswitcher.grab_key_focus ();
}
public int move_workspaces (bool up)
{
var i = screen.get_active_workspace_index ();
if (up && i - 1 >= 0) //move up
i --;
else if (!up && i + 1 < screen.n_workspaces) //move down
i ++;
if (i != screen.get_active_workspace_index ()) {
screen.get_workspace_by_index (i).
activate (screen.get_display ().get_current_time ());
}
return i;
}
public override void minimize (WindowActor actor)
{
minimize_completed (actor);
}
//stolen from original mutter plugin
public override void maximize (WindowActor actor, int ex, int ey, int ew, int eh)
{
if (actor.meta_window.window_type == WindowType.NORMAL) {
float x, y, width, height;
actor.get_size (out width, out height);
actor.get_position (out x, out y);
float scale_x = (float)ew / width;
float scale_y = (float)eh / height;
float anchor_x = (float)(x - ex) * width / (ew - width);
float anchor_y = (float)(y - ey) * height / (eh - height);
actor.move_anchor_point (anchor_x, anchor_y);
actor.animate (Clutter.AnimationMode.EASE_IN_SINE, 150, scale_x:scale_x,
scale_y:scale_y).completed.connect ( () => {
actor.move_anchor_point_from_gravity (Clutter.Gravity.NORTH_WEST);
actor.animate (Clutter.AnimationMode.LINEAR, 1, scale_x:1.0f,
scale_y:1.0f);//just scaling didnt want to work..
maximize_completed (actor);
});
return;
}
maximize_completed (actor);
}
public override void map (WindowActor actor)
{
actor.show ();
switch (actor.meta_window.window_type) {
case WindowType.NORMAL:
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.rotation_center_x = {0, actor.height, 10};
actor.scale_x = 0.55f;
actor.scale_y = 0.55f;
actor.opacity = 0;
actor.rotation_angle_x = 40.0f;
actor.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 350,
scale_x:1.0f, scale_y:1.0f, rotation_angle_x:0.0f, opacity:255)
.completed.connect ( () => {
map_completed (actor);
});
break;
case WindowType.MENU:
case WindowType.DROPDOWN_MENU:
case WindowType.POPUP_MENU:
case WindowType.MODAL_DIALOG:
case WindowType.DIALOG:
actor.scale_gravity = Clutter.Gravity.NORTH;
actor.scale_x = 1.0f;
actor.scale_y = 0.0f;
actor.opacity = 0;
actor.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 150,
scale_y:1.0f, opacity:255).completed.connect ( () => {
map_completed (actor);
});
break;
default:
map_completed (actor);
break;
}
}
public override void destroy (WindowActor actor)
{
switch (actor.meta_window.window_type) {
case WindowType.NORMAL:
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.rotation_center_x = {0, actor.height, 10};
actor.show ();
actor.animate (Clutter.AnimationMode.EASE_IN_QUAD, 250,
scale_x:0.95f, scale_y:0.95f, opacity:0, rotation_angle_x:15.0f)
.completed.connect ( () => {
destroy_completed (actor);
});
break;
case WindowType.MENU:
case WindowType.DROPDOWN_MENU:
case WindowType.POPUP_MENU:
case WindowType.MODAL_DIALOG:
case WindowType.DIALOG:
actor.scale_gravity = Clutter.Gravity.NORTH;
actor.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200,
scale_y:0.0f, opacity:0).completed.connect ( () => {
destroy_completed (actor);
});
break;
default:
destroy_completed (actor);
break;
}
}
GLib.List<Clutter.Actor>? win;
GLib.List<Clutter.Actor>? par; //class space for kill func
Clutter.Group in_group;
Clutter.Group out_group;
public override void switch_workspace (int from, int to, MotionDirection direction)
{
unowned List<Clutter.Actor> windows = Compositor.get_window_actors (get_screen ());
//FIXME js/ui/windowManager.js line 430
int w, h;
get_screen ().get_size (out w, out h);
var x2 = 0.0f; var y2 = 0.0f;
if (direction == MotionDirection.UP ||
direction == MotionDirection.UP_LEFT ||
direction == MotionDirection.UP_RIGHT)
y2 = h;
else if (direction == MotionDirection.DOWN ||
direction == MotionDirection.DOWN_LEFT ||
direction == MotionDirection.DOWN_RIGHT)
y2 = -h;
if (direction == MotionDirection.LEFT ||
direction == MotionDirection.UP_LEFT ||
direction == MotionDirection.DOWN_LEFT)
y2 = h;
else if (direction == MotionDirection.RIGHT ||
direction == MotionDirection.UP_RIGHT ||
direction == MotionDirection.DOWN_RIGHT)
y2 = -h;
var in_group = new Clutter.Group ();
var out_group = new Clutter.Group ();
var group = Compositor.get_window_group_for_screen (get_screen ());
group.add_actor (in_group);
group.add_actor (out_group);
win = new List<Clutter.Actor> ();
par = new List<Clutter.Actor> ();
for (var i=0;i<windows.length ();i++) {
var window = windows.nth_data (i);
if (!(window as WindowActor).meta_window.showing_on_its_workspace ())
continue;
win.append (window);
par.append (window.get_parent ());
if ((window as WindowActor).get_workspace () == from) {
window.reparent (out_group);
} else if ((window as WindowActor).get_workspace () == to) {
window.reparent (in_group);
window.show_all ();
}
}
in_group.set_position (-x2, -y2);
in_group.raise_top ();
out_group.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 300,
x:x2, y:y2);
in_group.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 300,
x:0.0f, y:0.0f).completed.connect ( () => {
end_switch_workspace ();
});
}
public override void kill_window_effects (WindowActor actor)
{
/*FIXME should call the things in anim.completed
minimize_completed (actor);
maximize_completed (actor);
unmaximize_completed (actor);
map_completed (actor);
destroy_completed (actor);
*/
}
private void end_switch_workspace ()
{
if (win == null || par == null)
return;
for (var i=0;i<win.length ();i++) {
var window = win.nth_data (i);
if ((window as WindowActor).is_destroyed ())
continue;
if (window.get_parent () == out_group) {
window.reparent (par.nth_data (i));
window.hide ();
} else
window.reparent (par.nth_data (i));
}
win = null;
par = null;
if (in_group != null) {
in_group.detach_animation ();
in_group.destroy ();
}
if (out_group != null) {
out_group.detach_animation ();
out_group.destroy ();
}
switch_workspace_completed ();
}
public override void unmaximize (Meta.WindowActor actor, int x, int y, int w, int h)
{
unmaximize_completed (actor);
}
public override void kill_switch_workspace ()
{
end_switch_workspace ();
}
public override bool xevent_filter (X.Event event)
{
return x_handle_event (event) != 0;
}
public override PluginInfo plugin_info ()
{
return {"Gala", Gala.VERSION, "Tom Beckmann", "GPLv3", "A nice window manager"};
}
}
const string VERSION = "0.1";
const string SCHEMA = "org.pantheon.desktop.gala";
const OptionEntry[] OPTIONS = {
{ "version", 0, OptionFlags.NO_ARG, OptionArg.CALLBACK, (void*) print_version, "Print version", null },
{ null }
};
void print_version () {
stdout.printf ("Gala %s\n", Gala.VERSION);
Meta.exit (Meta.ExitCode.SUCCESS);
}
[CCode (cname="clutter_x11_handle_event")]
public extern int x_handle_event (X.Event xevent);
[CCode (cname="clutter_x11_get_stage_window")]
public extern X.Window x_get_stage_window (Clutter.Actor stage);
int main (string [] args) {
unowned OptionContext ctx = Meta.get_option_context ();
ctx.add_main_entries (Gala.OPTIONS, null);
try {
ctx.parse (ref args);
} catch (Error e) {
stderr.printf ("Error initializing: %s\n", e.message);
Meta.exit (Meta.ExitCode.ERROR);
}
Meta.Plugin.type_register (new Gala.Plugin ().get_type ());
/**
* Prevent Meta.init () from causing gtk to load gail and at-bridge
* Taken from Gnome-Shell main.c
*/
GLib.Environment.set_variable ("NO_GAIL", "1", true);
GLib.Environment.set_variable ("NO_AT_BRIDGE", "1", true);
Meta.init ();
GLib.Environment.unset_variable ("NO_GAIL");
GLib.Environment.unset_variable ("NO_AT_BRIDGE");
return Meta.run ();
}
}

46
src/Settings.vala Normal file
View File

@ -0,0 +1,46 @@
//
// Copyright (C) 2012 GardenGnome, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
namespace Gala
{
public class Settings : Granite.Services.Settings
{
public bool attach_modal_dialogs { get; set; }
public string[] button_layout { get; set; }
public bool edge_tiling { get; set; }
public bool enable_animations { get; set; }
public string panel_main_menu_action { get; set; }
public string theme { get; set; }
public bool use_gnome_defaults { get; set; }
public bool enable_manager_corner { get; set; }
static Settings? instance = null;
private Settings ()
{
base (SCHEMA);
}
public static Settings get_default ()
{
if (instance == null)
instance = new Settings ();
return instance;
}
}
}

62
src/TextShadowEffect.vala Normal file
View File

@ -0,0 +1,62 @@
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
namespace Gala
{
public class TextShadowEffect : Clutter.Effect
{
int _offset_y;
public int offset_y {
get { return _offset_y; }
set { _offset_y = value; update (); }
}
int _offset_x;
public int offset_x {
get { return _offset_x; }
set { _offset_x = value; update (); }
}
uint8 _opacity;
public uint8 opacity {
get { return _opacity; }
set { _opacity = value; update (); }
}
public TextShadowEffect (int offset_x, int offset_y, uint8 opacity)
{
_offset_x = offset_x;
_offset_y = offset_y;
_opacity = opacity;
}
public override bool pre_paint ()
{
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);
return true;
}
public void update ()
{
if (get_actor () != null)
get_actor ().queue_redraw ();
}
}
}

View File

@ -1,165 +1,174 @@
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
public class CornerMenu : Clutter.Group { namespace Gala
{
Clutter.Box workspaces; public class CornerMenu : Clutter.Group
{
unowned Gala.Plugin plugin; Gala.Plugin plugin;
bool animating; //prevent closing of the popup too fast Clutter.Box workspaces;
public CornerMenu (Gala.Plugin plugin) { bool animating; // delay closing the popup
this.plugin = plugin; public CornerMenu (Gala.Plugin _plugin)
{
this.width = 100; plugin = _plugin;
this.height = 100;
width = 100;
this.scale_gravity = Clutter.Gravity.SOUTH_EAST; height = 100;
this.opacity = 0; opacity = 0;
this.scale_x = this.scale_y = 0.0f; scale_gravity = Clutter.Gravity.SOUTH_EAST;
scale_x = scale_y = 0.0f;
this.workspaces = new Clutter.Box (new Clutter.BoxLayout ()); reactive = true;
(this.workspaces.layout_manager as Clutter.BoxLayout).spacing = 15;
(this.workspaces.layout_manager as Clutter.BoxLayout).vertical = true; workspaces = new Clutter.Box (new Clutter.BoxLayout ());
(workspaces.layout_manager as Clutter.BoxLayout).spacing = 15;
this.reactive = true; (workspaces.layout_manager as Clutter.BoxLayout).vertical = true;
this.leave_event.connect ( (e) => {
if (this.get_children ().index (e.related) == -1) leave_event.connect ((e) => {
this.hide (); if (get_children ().index (e.related) == -1)
return false; hide ();
});
return false;
var tile = new GtkClutter.Texture (); });
try {
tile.set_from_pixbuf (Gtk.IconTheme.get_default ().load_icon ("preferences-desktop-display", 64, 0)); var tile = new GtkClutter.Texture ();
} catch (Error e) { warning (e.message); } try {
tile.x = 5; tile.set_from_pixbuf (Gtk.IconTheme.get_default ().load_icon ("preferences-desktop-display", 64, 0));
tile.y = 5; } catch (Error e) {
tile.reactive = true; warning (e.message);
tile.button_release_event.connect ( () => { }
var windows = new GLib.List<Meta.Window> (); tile.x = 5;
plugin.screen.get_active_workspace ().list_windows ().foreach ( (w) => { tile.y = 5;
if (w.window_type != Meta.WindowType.NORMAL || w.minimized) tile.reactive = true;
return; tile.button_release_event.connect (() => {
windows.append (w); var windows = new GLib.List<Meta.Window> ();
}); plugin.screen.get_active_workspace ().list_windows ().foreach ( (w) => {
if (w.window_type != Meta.WindowType.NORMAL || w.minimized)
//make sure active window is biggest return;
var active_idx = windows.index (plugin.screen.get_display ().get_focus_window ());
if (active_idx != -1 && active_idx != 0) { windows.append (w);
windows.delete_link (windows.nth (active_idx)); });
windows.prepend (plugin.screen.get_display ().get_focus_window ());
} //make sure active window is biggest
var active_idx = windows.index (plugin.screen.get_display ().get_focus_window ());
unowned Meta.Rectangle area; if (active_idx != -1 && active_idx != 0) {
plugin.screen.get_active_workspace ().get_work_area_all_monitors (out area); windows.delete_link (windows.nth (active_idx));
windows.prepend (plugin.screen.get_display ().get_focus_window ());
var n_wins = windows.length (); }
var index = 0;
unowned Meta.Rectangle area;
windows.foreach ( (w) => { plugin.screen.get_active_workspace ().get_work_area_all_monitors (out area);
if (w.maximized_horizontally || w.maximized_vertically)
w.unmaximize (Meta.MaximizeFlags.VERTICAL | Meta.MaximizeFlags.HORIZONTAL); var n_wins = windows.length ();
switch (n_wins) { var index = 0;
case 1:
w.move_resize_frame (true, area.x, area.y, area.width, area.height); windows.foreach ( (w) => {
break; if (w.maximized_horizontally || w.maximized_vertically)
case 2: w.unmaximize (Meta.MaximizeFlags.VERTICAL | Meta.MaximizeFlags.HORIZONTAL);
w.move_resize_frame (true, area.x+area.width/2*index, area.y, area.width/2,
area.height); switch (n_wins) {
break; case 1:
case 3: w.move_resize_frame (true, area.x, area.y, area.width, area.height);
if (index == 0) break;
w.move_resize_frame (true, area.x, area.y, area.width/2, area.height); case 2:
else { w.move_resize_frame (true, area.x+area.width/2*index, area.y, area.width/2,
w.move_resize_frame (true, area.x+area.width/2, area.height);
area.y+(area.height/2*(index-1)), area.width/2, area.height/2); break;
} case 3:
break; if (index == 0)
case 4: w.move_resize_frame (true, area.x, area.y, area.width/2, area.height);
if (index < 2) else {
w.move_resize_frame (true, area.x+area.width/2*index, area.y, w.move_resize_frame (true, area.x+area.width/2,
area.width/2, area.height/2); area.y+(area.height/2*(index-1)), area.width/2, area.height/2);
else }
w.move_resize_frame (true, (index==3)?area.x+area.width/2:area.x, break;
area.y+area.height/2, area.width/2, area.height/2); case 4:
break; if (index < 2)
case 5: w.move_resize_frame (true, area.x+area.width/2*index, area.y,
if (index < 2) area.width/2, area.height/2);
w.move_resize_frame (true, area.x, area.y+(area.height/2*index), else
area.width/2, area.height/2); w.move_resize_frame (true, (index==3)?area.x+area.width/2:area.x,
else area.y+area.height/2, area.width/2, area.height/2);
w.move_resize_frame (true, area.x+area.width/2, break;
area.y+(area.height/3*(index-2)), area.width/2, area.height/3); case 5:
break; if (index < 2)
case 6: w.move_resize_frame (true, area.x, area.y+(area.height/2*index),
if (index < 3) area.width/2, area.height/2);
w.move_resize_frame (true, area.x, area.y+(area.height/3*index), else
area.width/2, area.height/3); w.move_resize_frame (true, area.x+area.width/2,
else area.y+(area.height/3*(index-2)), area.width/2, area.height/3);
w.move_resize_frame (true, area.x+area.width/2, break;
area.y+(area.height/3*(index-3)), area.width/2, area.height/3); case 6:
break; if (index < 3)
default: w.move_resize_frame (true, area.x, area.y+(area.height/3*index),
return; area.width/2, area.height/3);
} else
index ++; w.move_resize_frame (true, area.x+area.width/2,
}); area.y+(area.height/3*(index-3)), area.width/2, area.height/3);
return true; break;
}); default:
return;
this.add_child (tile); }
//this.add_child (this.workspaces); index ++;
} });
return true;
public new void show () { });
if (this.visible)
return; add_child (tile);
plugin.set_input_area (Gala.InputArea.FULLSCREEN); //add_child (workspaces);
plugin.begin_modal (); }
animating = true; public new void show ()
{
int width, height; if (visible)
plugin.get_screen ().get_size (out width, out height); return;
this.x = width - this.width;
this.y = height - this.height; plugin.set_input_area (Gala.InputArea.FULLSCREEN);
plugin.begin_modal ();
this.visible = true;
this.grab_key_focus (); animating = true;
this.animate (Clutter.AnimationMode.EASE_OUT_BOUNCE, 400, scale_x:1.0f, scale_y:1.0f, opacity:255).completed.connect ( () => {
animating = false; int width, height;
}); plugin.get_screen ().get_size (out width, out height);
x = width - width;
/*for (var i=0;i<plugin.get_screen ().n_workspaces;i++) { y = height - height;
plugin.get_screen ().get_workspace_by_index (i);
visible = true;
var g = new Clutter.Group (); grab_key_focus ();
animate (Clutter.AnimationMode.EASE_OUT_BOUNCE, 400, scale_x:1.0f, scale_y:1.0f, opacity:255).completed.connect (() => {
var s = new Clutter.Rectangle.with_color ({0, 0, 0, 255}); animating = false;
var b = new Clutter.Clone (background); });
}
b.width = s.width = WIDTH;
b.height = s.height = HEIGHT; public new void hide ()
{
g.add_child (s); if (!visible || animating)
g.add_child (b); return;
this.workspaces.add_child (g); plugin.end_modal ();
}*/ plugin.set_input_area (Gala.InputArea.HOT_CORNER);
}
animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, scale_x : 0.0f, scale_y : 0.0f, opacity : 0)
public new void hide () { .completed.connect ( () => {
if (!this.visible || animating) visible = false;
return; });
}
plugin.end_modal (); }
plugin.set_input_area (Gala.InputArea.HOT_CORNER);
this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, scale_x:0.0f, scale_y:0.0f, opacity:0)
.completed.connect ( () => {
this.visible = false;
});
}
} }

View File

@ -1,204 +1,237 @@
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
using Clutter;
using Granite.Drawing;
public class WindowSwitcher : Clutter.Group { namespace Gala
{
int ICON_SIZE = 128; public class WindowSwitcher : Clutter.Group
int spacing = 12; {
const int ICON_SIZE = 128;
public float len; const int spacing = 12;
Clutter.CairoTexture bg; Gala.Plugin plugin;
Clutter.CairoTexture cur;
Clutter.Text title; GLib.List<unowned Meta.Window> window_list;
int _windows = 1; CairoTexture background;
public int windows { CairoTexture current;
get { return _windows; } Text title;
set {
_windows = value; int _windows = 1;
this.width = spacing+_windows*(ICON_SIZE+spacing); int windows {
} get { return _windows; }
} set {
_windows = value;
GLib.List<weak Meta.Window> window_list; width = spacing + _windows * (ICON_SIZE + spacing);
}
Meta.Window? _current_window; }
Meta.Window? current_window {
get { return _current_window; } Meta.Window? _current_window;
set { Meta.Window? current_window {
_current_window = value; get { return _current_window; }
set {
this.title.text = this.current_window.title; _current_window = value;
this.title.x = (int)(this.width/2-this.title.width/2); title.text = current_window.title;
} title.x = (int)(width / 2 - title.width / 2);
} }
}
Gala.Plugin plugin;
public WindowSwitcher (Gala.Plugin _plugin)
public WindowSwitcher (Gala.Plugin plugin) { {
this.plugin = plugin; plugin = _plugin;
this.height = ICON_SIZE+spacing*2; height = ICON_SIZE + spacing * 2;
this.opacity = 0; opacity = 0;
this.scale_gravity = Clutter.Gravity.CENTER; scale_gravity = Gravity.CENTER;
this.bg = new Clutter.CairoTexture (100, 100); background = new CairoTexture (100, 100);
this.bg.auto_resize = true; background.auto_resize = true;
background.draw.connect (draw_background);
this.bg.draw.connect ( (ctx) => {
Granite.Drawing.Utilities.cairo_rounded_rectangle (ctx, 0.5, 0.5, width-1, current = new CairoTexture (ICON_SIZE, ICON_SIZE);
height-1, 10); current.y = spacing + 1;
ctx.set_line_width (1); current.x = spacing + 1;
ctx.set_source_rgba (0, 0, 0, 0.5); current.width = ICON_SIZE;
ctx.stroke_preserve (); current.height = ICON_SIZE;
ctx.set_source_rgba (1, 1, 1, 0.4); current.auto_resize = true;
ctx.fill (); current.draw.connect (draw_current);
return true; windows = 1;
});
title = new Text.with_text ("bold 16px", "");
this.cur = new Clutter.CairoTexture (ICON_SIZE, ICON_SIZE); title.y = ICON_SIZE + spacing * 2 + 6;
this.cur.width = ICON_SIZE; title.color = {255, 255, 255, 255};
this.cur.height = ICON_SIZE; title.add_effect (new TextShadowEffect (1, 1, 220));
this.cur.y = spacing+1;
this.cur.x = spacing+1; add_child (background);
this.cur.auto_resize = true; add_child (current);
this.cur.draw.connect ( (ctx) => { add_child (title);
Granite.Drawing.Utilities.cairo_rounded_rectangle (ctx, 0.5, 0.5, cur.width-2,
cur.height-1, 10); background.add_constraint (new BindConstraint (this, BindCoordinate.WIDTH, 0));
ctx.set_line_width (1); background.add_constraint (new BindConstraint (this, BindCoordinate.HEIGHT, 0));
ctx.set_source_rgba (0, 0, 0, 0.9); }
ctx.stroke_preserve ();
ctx.set_source_rgba (1, 1, 1, 0.9); public override bool key_release_event (Clutter.KeyEvent event)
ctx.fill (); {
if (((event.modifier_state & ModifierType.MOD1_MASK) == 0) ||
return true; event.keyval == Key.Alt_L) {
}); plugin.end_modal ();
this.windows = 1; current_window.activate (event.time);
this.title = new Clutter.Text.with_text ("bold 16px", ""); animate (AnimationMode.EASE_OUT_QUAD, 200, opacity:0);
this.title.y = ICON_SIZE + spacing*2 + 6; }
this.title.color = {255, 255, 255, 255};
this.title.add_effect (new TextShadowEffect (1, 1, 220)); return true;
}
this.add_child (bg);
this.add_child (cur); public override bool captured_event (Clutter.Event event)
this.add_child (title); {
bg.add_constraint (new Clutter.BindConstraint (this, Clutter.BindCoordinate.WIDTH, 0)); if (!(event.get_type () == EventType.KEY_PRESS))
bg.add_constraint (new Clutter.BindConstraint (this, Clutter.BindCoordinate.HEIGHT, 0)); return false;
this.key_release_event.connect_after ( (e) => { bool backward = (event.get_state () & X.KeyMask.ShiftMask) != 0;
if (((e.modifier_state & Clutter.ModifierType.MOD1_MASK) == 0) || var action = plugin.get_screen ().get_display ().get_keybinding_action (
e.keyval == Clutter.Key.Alt_L) { event.get_key_code (), event.get_state ());
plugin.end_modal ();
current_window.activate (e.time); switch (action) {
case Meta.KeyBindingAction.SWITCH_GROUP:
this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200, opacity:0); case Meta.KeyBindingAction.SWITCH_WINDOWS:
} current_window = plugin.get_screen ().get_display ().
return true; get_tab_next (Meta.TabList.NORMAL, plugin.get_screen (),
}); plugin.get_screen ().get_active_workspace (), current_window, backward);
this.captured_event.connect ( (e) => { break;
if (!(e.get_type () == Clutter.EventType.KEY_PRESS)) case Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD:
return false; case Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD:
current_window = plugin.get_screen ().get_display ().
bool backward = (((Clutter.Event)e).get_state () & X.KeyMask.ShiftMask) == 1; get_tab_next (Meta.TabList.NORMAL, plugin.get_screen (),
var action = plugin.get_screen ().get_display ().get_keybinding_action ( plugin.get_screen ().get_active_workspace (), current_window, true);
((Clutter.Event)e).get_key_code (), ((Clutter.Event)e).get_state ()); break;
default:
switch (action) { break;
case Meta.KeyBindingAction.SWITCH_GROUP: }
case Meta.KeyBindingAction.SWITCH_WINDOWS:
this.current_window = plugin.get_screen ().get_display (). current.animate (AnimationMode.EASE_OUT_QUAD, 200,
get_tab_next (Meta.TabList.NORMAL, plugin.get_screen (), x : 0.0f + spacing + window_list.index (current_window) * (spacing + ICON_SIZE));
plugin.get_screen ().get_active_workspace (), this.current_window, backward);
break; return true;
case Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD: }
case Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD:
this.current_window = plugin.get_screen ().get_display (). bool draw_background (Cairo.Context cr)
get_tab_next (Meta.TabList.NORMAL, plugin.get_screen (), {
plugin.get_screen ().get_active_workspace (), this.current_window, true); Utilities.cairo_rounded_rectangle (cr, 0.5, 0.5, width - 1, height - 1, 10);
break; cr.set_line_width (1);
default: cr.set_source_rgba (0, 0, 0, 0.5);
break; cr.stroke_preserve ();
} cr.set_source_rgba (1, 1, 1, 0.4);
cur.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200, cr.fill ();
x:0.0f+spacing+this.window_list.index (this.current_window)*(spacing+ICON_SIZE));
return true; return true;
}); }
}
bool draw_current (Cairo.Context cr)
public void list_windows (Meta.Display display, Meta.Screen screen, {
Meta.KeyBinding binding, bool backward) { Utilities.cairo_rounded_rectangle (cr, 0.5, 0.5, current.width - 2, current.height - 1, 10);
this.get_children ().foreach ( (c) => { //clear cr.set_line_width (1);
if (c != cur && c != bg && c != title) cr.set_source_rgba (0, 0, 0, 0.9);
this.remove_child (c); cr.stroke_preserve ();
}); cr.set_source_rgba (1, 1, 1, 0.9);
cr.fill ();
this.current_window = display.get_tab_next (Meta.TabList.NORMAL, screen,
screen.get_active_workspace (), null, backward); return true;
if (this.current_window == null) }
this.current_window = display.get_tab_current (Meta.TabList.NORMAL, screen,
screen.get_active_workspace ()); public void list_windows (Meta.Display display, Meta.Screen screen, Meta.KeyBinding binding, bool backward)
if (this.current_window == null) {
return; get_children ().foreach ((c) => { //clear
if (c != current && c != background && c != title)
if (binding.get_mask () == 0) { remove_child (c);
this.current_window.activate (display.get_current_time ()); });
return;
} current_window = display.get_tab_next (Meta.TabList.NORMAL, screen,
screen.get_active_workspace (), null, backward);
var matcher = Bamf.Matcher.get_default ();
if (current_window == null)
var i = 0; current_window = display.get_tab_current (Meta.TabList.NORMAL, screen, screen.get_active_workspace ());
this.window_list = screen.get_display ().get_tab_list (Meta.TabList.NORMAL, screen,
screen.get_active_workspace ()).copy (); if (current_window == null)
this.window_list.foreach ( (w) => { return;
if (w == null)
return; if (binding.get_mask () == 0) {
current_window.activate (display.get_current_time ());
Bamf.Window bamfwin = null; return;
matcher.get_windows ().foreach ( (bamfw) => { }
if ((bamfw as Bamf.Window).get_pid () == (uint32)w.get_pid ()) {
bamfwin = bamfw as Bamf.Window; var matcher = Bamf.Matcher.get_default ();
}
}); var i = 0;
window_list = display.get_tab_list (Meta.TabList.NORMAL, screen, screen.get_active_workspace ()).copy ();
Gdk.Pixbuf image = null;
if (bamfwin != null) { window_list.foreach ((w) => {
var app = matcher.get_application_for_window (bamfwin); if (w == null)
if (app != null) { return;
var desktop = new GLib.DesktopAppInfo.from_filename (app.get_desktop_file ());
try { Bamf.Window bamfwin = null;
image = Gtk.IconTheme.get_default ().lookup_by_gicon (desktop.get_icon (), matcher.get_windows ().foreach ( (bamfw) => {
ICON_SIZE, 0).load_icon (); if ((bamfw as Bamf.Window).get_pid () == (uint32)w.get_pid ()) {
} catch (Error e) { warning (e.message); } bamfwin = bamfw as Bamf.Window;
} }
} });
if (image == null) { Gdk.Pixbuf image = null;
try { if (bamfwin != null) {
image = Gtk.IconTheme.get_default ().load_icon ("application-default-icon", var app = matcher.get_application_for_window (bamfwin);
ICON_SIZE, 0); if (app != null) {
} catch (Error e) { warning (e.message); } var desktop = new GLib.DesktopAppInfo.from_filename (app.get_desktop_file ());
} try {
image = Gtk.IconTheme.get_default ().lookup_by_gicon (desktop.get_icon (), ICON_SIZE, 0).load_icon ();
var icon = new GtkClutter.Texture (); } catch (Error e) { warning (e.message); }
try { }
icon.set_from_pixbuf (image); }
} catch (Error e) { warning (e.message); }
if (image == null) {
icon.width = ICON_SIZE-10; try {
icon.height = ICON_SIZE-10; image = Gtk.IconTheme.get_default ().load_icon ("application-default-icon", ICON_SIZE, 0);
icon.x = spacing+i*(spacing+ICON_SIZE)+5; } catch (Error e) {
icon.y = spacing+5; warning (e.message);
this.add_child (icon); }
}
i ++;
}); var icon = new GtkClutter.Texture ();
this.windows = i; try {
icon.set_from_pixbuf (image);
var idx = this.window_list.index (this.current_window); } catch (Error e) {
cur.x = spacing+idx*(spacing+ICON_SIZE); warning (e.message);
} }
icon.x = spacing + 5 + i * (spacing + ICON_SIZE);
icon.y = spacing + 5;
icon.width = ICON_SIZE - 10;
icon.height = ICON_SIZE - 10;
add_child (icon);
i++;
});
windows = i;
var idx = window_list.index (current_window);
current.x = spacing + idx * (spacing + ICON_SIZE);
}
}
} }

View File

@ -1,108 +1,147 @@
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
public class WorkspaceSwitcher : Clutter.Group { using Clutter;
using Granite.Drawing;
public float len;
namespace Gala
Clutter.CairoTexture bg; {
Clutter.CairoTexture cur; public class WorkspaceSwitcher : Group
{
int _workspaces = 1; const float WIDTH = 200;
public int workspaces { const int spacing = 10;
get {return _workspaces;}
set {_workspaces = value; this.height = len*_workspaces+spacing;} float len;
}
int _workspace = 0; Gala.Plugin plugin;
public int workspace {
get {return _workspace;} CairoTexture background;
set { CairoTexture current;
_workspace = value;
cur.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 300, y:_workspace*len+1+spacing); int _workspaces = 1;
} public int workspaces {
} get { return _workspaces; }
set {
int spacing = 10; _workspaces = value;
float WIDTH = 200; height = len * _workspaces + spacing;
}
Gala.Plugin plugin; }
public WorkspaceSwitcher (Gala.Plugin plugin, int w, int h) { int _workspace = 0;
public int workspace {
this.plugin = plugin; get { return _workspace; }
set {
this.height = 100+spacing*2; _workspace = value;
this.width = WIDTH+spacing*2; current.animate (AnimationMode.EASE_OUT_QUAD, 300, y : _workspace * len + 1 + spacing);
this.opacity = 0; }
}
this.bg = new Clutter.CairoTexture (100, (int)WIDTH);
this.bg.auto_resize = true; public WorkspaceSwitcher (Gala.Plugin _plugin, int w, int h)
{
len = (float)(h)/w*WIDTH; plugin = _plugin;
this.bg.draw.connect ( (ctx) => {
Granite.Drawing.Utilities.cairo_rounded_rectangle (ctx, 0.5, 0.5, width-1, len = (float)h / w * WIDTH;
height-1, 10);
ctx.set_line_width (1); height = 100 + spacing * 2;
ctx.set_source_rgba (0, 0, 0, 0.5); width = WIDTH + spacing * 2;
ctx.stroke_preserve (); opacity = 0;
ctx.set_source_rgba (1, 1, 1, 0.4);
ctx.fill (); background = new CairoTexture (100, (int)WIDTH);
background.auto_resize = true;
for (var i=0;i<workspaces;i++) { background.draw.connect (draw_background);
Granite.Drawing.Utilities.cairo_rounded_rectangle (ctx, 0.5+spacing,
i*len+0.5+spacing, width-1-spacing*2, len-1-spacing, 10); current = new CairoTexture (100, 100);
ctx.set_line_width (1); current.x = spacing + 1;
ctx.set_source_rgba (0, 0, 0, 0.8); current.width = width - 1 - spacing * 2;
ctx.stroke_preserve (); current.height = len - 1 - spacing;
ctx.set_source_rgba (0, 0, 0, 0.4); current.auto_resize = true;
ctx.fill (); current.draw.connect (draw_current);
}
return true; workspace = 0;
});
add_child (background);
this.cur = new Clutter.CairoTexture (100, 100); add_child (current);
this.cur.width = width-1-spacing*2;
this.cur.height = len-1-spacing; background.add_constraint (new BindConstraint (this, BindCoordinate.WIDTH, 0));
this.cur.x = spacing+1; background.add_constraint (new BindConstraint (this, BindCoordinate.HEIGHT, 0));
this.cur.auto_resize = true; }
this.cur.draw.connect ( (ctx) => {
Granite.Drawing.Utilities.cairo_rounded_rectangle (ctx, 0.5, 0.5, cur.width-2, public override bool key_release_event (KeyEvent event)
cur.height-1, 10); {
ctx.set_line_width (1); if (((event.modifier_state & ModifierType.MOD1_MASK) == 0) ||
ctx.set_source_rgba (0, 0, 0, 0.9); event.keyval == Key.Alt_L) {
ctx.stroke_preserve (); plugin.end_modal ();
ctx.set_source_rgba (1, 1, 1, 0.9); animate (AnimationMode.EASE_OUT_QUAD, 200, opacity : 0);
ctx.fill ();
return true;
return true; }
});
this.workspace = 0; return false;
}
this.add_child (bg);
this.add_child (cur); public override bool key_press_event (KeyEvent event)
bg.add_constraint (new Clutter.BindConstraint (this, Clutter.BindCoordinate.WIDTH, 0)); {
bg.add_constraint (new Clutter.BindConstraint (this, Clutter.BindCoordinate.HEIGHT, 0)); switch (event.keyval) {
case Key.Up:
this.key_release_event.connect ( (e) => { workspace = plugin.move_workspaces (true);
if (((e.modifier_state & Clutter.ModifierType.MOD1_MASK) == 0) || return false;
e.keyval == Clutter.Key.Alt_L) { case Key.Down:
workspace = plugin.move_workspaces (false);
plugin.end_modal (); return false;
this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200, opacity:0); default:
break;
return true; }
}
return false; return true;
}); }
this.key_press_event.connect ( (e) => {
switch (e.keyval) {
case Clutter.Key.Up: bool draw_background (Cairo.Context cr)
this.workspace = plugin.move_workspaces (true); {
return false; Utilities.cairo_rounded_rectangle (cr, 0.5, 0.5, width - 1, height - 1, 10);
case Clutter.Key.Down: cr.set_line_width (1);
this.workspace = plugin.move_workspaces (false); cr.set_source_rgba (0, 0, 0, 0.5);
return false; cr.stroke_preserve ();
default: cr.set_source_rgba (1, 1, 1, 0.4);
return true; cr.fill ();
}
}); for (var i = 0; i < workspaces; i++) {
} Utilities.cairo_rounded_rectangle (cr, 0.5 + spacing, i * len + 0.5 + spacing,
width - 1 - spacing * 2, len - 1 - spacing, 10);
cr.set_line_width (1);
cr.set_source_rgba (0, 0, 0, 0.8);
cr.stroke_preserve ();
cr.set_source_rgba (0, 0, 0, 0.4);
cr.fill ();
}
return true;
}
bool draw_current (Cairo.Context cr)
{
Utilities.cairo_rounded_rectangle (cr, 0.5, 0.5, current.width - 2, current.height - 1, 10);
cr.set_line_width (1);
cr.set_source_rgba (0, 0, 0, 0.9);
cr.stroke_preserve ();
cr.set_source_rgba (1, 1, 1, 0.9);
cr.fill ();
return true;
}
}
} }

View File

@ -1,409 +0,0 @@
namespace Gala {
public enum InputArea {
FULLSCREEN,
HOT_CORNER,
NONE
}
public class Plugin : Meta.Plugin {
public WorkspaceSwitcher wswitcher;
public WindowSwitcher winswitcher;
public CornerMenu corner_menu;
public Clutter.Actor elements;
public Plugin () {
if (Settings.get_default().use_gnome_defaults)
return;
Meta.Prefs.override_preference_schema ("attach-modal-dialogs", SCHEMA);
Meta.Prefs.override_preference_schema ("button-layout", SCHEMA);
Meta.Prefs.override_preference_schema ("edge-tiling", SCHEMA);
Meta.Prefs.override_preference_schema ("enable-animations", SCHEMA);
Meta.Prefs.override_preference_schema ("theme", SCHEMA);
}
public override void start () {
this.elements = Meta.Compositor.get_stage_for_screen (screen);
Meta.Compositor.get_window_group_for_screen (screen).reparent (elements);
Meta.Compositor.get_overlay_group_for_screen (screen).reparent (elements);
Meta.Compositor.get_stage_for_screen (screen).add_child (elements);
screen.override_workspace_layout (Meta.ScreenCorner.TOPLEFT, false, -1, 4);
int w, h;
screen.get_size (out w, out h);
this.corner_menu = new CornerMenu (this);
this.elements.add_child (this.corner_menu);
this.corner_menu.visible = false;
this.wswitcher = new WorkspaceSwitcher (this, w, h);
this.wswitcher.workspaces = 4;
this.elements.add_child (this.wswitcher);
this.winswitcher = new WindowSwitcher (this);
this.elements.add_child (this.winswitcher);
Meta.KeyBinding.set_custom_handler ("panel-main-menu", () => {
try {
Process.spawn_command_line_async (
Settings.get_default().panel_main_menu_action);
} catch (Error e) { warning (e.message); }
});
Meta.KeyBinding.set_custom_handler ("switch-windows",
(display, screen, window, ev, binding) => {
window_switcher (display, screen, binding, false);
});
Meta.KeyBinding.set_custom_handler ("switch-windows-backward",
(display, screen, window, ev, binding) => {
window_switcher (display, screen, binding, true);
});
Meta.KeyBinding.set_custom_handler ("switch-to-workspace-left", ()=>{});
Meta.KeyBinding.set_custom_handler ("switch-to-workspace-right", ()=>{});
Meta.KeyBinding.set_custom_handler ("switch-to-workspace-up", (d,s) =>
workspace_switcher (s, true) );
Meta.KeyBinding.set_custom_handler ("switch-to-workspace-down", (d,s) =>
workspace_switcher (s, false) );
Meta.KeyBinding.set_custom_handler ("move-to-workspace-left", ()=>{});
Meta.KeyBinding.set_custom_handler ("move-to-workspace-right", ()=>{});
Meta.KeyBinding.set_custom_handler ("move-to-workspace-up", (d,s,w) =>
move_window (w, true) );
Meta.KeyBinding.set_custom_handler ("move-to-workspace-down", (d,s,w) =>
move_window (w, false) );
/*shadows*/
Meta.ShadowFactory.get_default ().set_params ("normal", true, {30, -1, 0, 35, 120});
/*hot corner*/
var hot_corner = new Clutter.Rectangle ();
hot_corner.x = w - 2;
hot_corner.y = h - 2;
hot_corner.width = 2;
hot_corner.height = 2;
hot_corner.reactive = true;
hot_corner.enter_event.connect ( () => {
corner_menu.show ();
return false;
});
Meta.Compositor.get_overlay_group_for_screen (screen).add_child (hot_corner);
if (Settings.get_default ().enable_manager_corner)
set_input_area (InputArea.HOT_CORNER);
else
set_input_area (InputArea.NONE);
Settings.get_default ().notify["enable-manager-corner"].connect ( () => {
if (Settings.get_default ().enable_manager_corner)
set_input_area (InputArea.HOT_CORNER);
else
set_input_area (InputArea.NONE);
});
}
/**
* set the area where clutter can receive events
**/
public void set_input_area (InputArea area) {
X.Rectangle rect;
int width, height;
screen.get_size (out width, out height);
switch (area) {
case InputArea.FULLSCREEN:
rect = {0, 0, (short)width, (short)height};
break;
case InputArea.HOT_CORNER: //leave one pix in the bottom left
rect = {(short)(width - 1), (short)(height - 1), 1, 1};
break;
default:
Meta.Util.empty_stage_input_region (screen);
return;
}
var xregion = X.Fixes.create_region (screen.get_display ().get_xdisplay (), {rect});
Meta.Util.set_stage_input_region (screen, xregion);
}
public void move_window (Meta.Window? window, bool up) {
if (window == null)
return;
if (window.is_on_all_workspaces ())
return;
var idx = screen.get_active_workspace ().index () + ((up)?-1:1);
window.change_workspace_by_index (idx, false,
screen.get_display ().get_current_time ());
screen.get_workspace_by_index (idx).activate_with_focus (window,
screen.get_display ().get_current_time ());
}
public new void begin_modal () {
base.begin_modal (x_get_stage_window (Meta.Compositor.get_stage_for_screen (
this.get_screen ())), {}, 0, this.get_screen ().get_display ().get_current_time ());
}
public new void end_modal () {
base.end_modal (this.get_screen ().get_display ().get_current_time ());
}
public void window_switcher (Meta.Display display, Meta.Screen screen,
Meta.KeyBinding binding, bool backward) {
if (screen.get_display ().get_tab_list (Meta.TabList.NORMAL, screen,
screen.get_active_workspace ()).length () == 0)
return;
this.begin_modal ();
int w, h;
this.get_screen ().get_size (out w, out h);
this.winswitcher.list_windows (display, screen, binding, backward);
this.winswitcher.x = w/2-winswitcher.width/2;
this.winswitcher.y = h/2-winswitcher.height/2;
this.winswitcher.grab_key_focus ();
this.winswitcher.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, opacity:255);
}
public void workspace_switcher (Meta.Screen screen, bool up) {
int w, h;
this.get_screen ().get_size (out w, out h);
wswitcher.x = w/2-wswitcher.width/2;
wswitcher.y = h/2-wswitcher.height/2;
wswitcher.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 100, opacity:255);
wswitcher.workspace = move_workspaces (up);;
this.begin_modal ();
wswitcher.grab_key_focus ();
}
public int move_workspaces (bool up) {
var i = screen.get_active_workspace_index ();
if (up && i-1 >= 0) //move up
i --;
else if (!up && i+1 < screen.n_workspaces) //move down
i ++;
if (i != screen.get_active_workspace_index ()) {
screen.get_workspace_by_index (i).
activate (screen.get_display ().get_current_time ());
}
return i;
}
public override void minimize (Meta.WindowActor actor) {
this.minimize_completed (actor);
}
//stolen from original mutter plugin
public override void maximize (Meta.WindowActor actor, int ex, int ey, int ew, int eh) {
if (actor.meta_window.window_type == Meta.WindowType.NORMAL) {
float x, y, width, height;
actor.get_size (out width, out height);
actor.get_position (out x, out y);
float scale_x = (float)ew / width;
float scale_y = (float)eh / height;
float anchor_x = (float)(x - ex) * width / (ew - width);
float anchor_y = (float)(y - ey) * height / (eh - height);
actor.move_anchor_point (anchor_x, anchor_y);
actor.animate (Clutter.AnimationMode.EASE_IN_SINE, 150, scale_x:scale_x,
scale_y:scale_y).completed.connect ( () => {
actor.move_anchor_point_from_gravity (Clutter.Gravity.NORTH_WEST);
actor.animate (Clutter.AnimationMode.LINEAR, 1, scale_x:1.0f,
scale_y:1.0f);//just scaling didnt want to work..
this.maximize_completed (actor);
});
return;
}
this.maximize_completed (actor);
}
public override void map (Meta.WindowActor actor) {
actor.show ();
switch (actor.meta_window.window_type) {
case Meta.WindowType.NORMAL:
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.rotation_center_x = {0, actor.height, 10};
actor.scale_x = 0.55f;
actor.scale_y = 0.55f;
actor.opacity = 0;
actor.rotation_angle_x = 40.0f;
actor.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 350,
scale_x:1.0f, scale_y:1.0f, rotation_angle_x:0.0f, opacity:255)
.completed.connect ( () => {
this.map_completed (actor);
});
break;
case Meta.WindowType.MENU:
case Meta.WindowType.DROPDOWN_MENU:
case Meta.WindowType.POPUP_MENU:
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
actor.scale_gravity = Clutter.Gravity.NORTH;
actor.scale_x = 1.0f;
actor.scale_y = 0.0f;
actor.opacity = 0;
actor.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 150,
scale_y:1.0f, opacity:255).completed.connect ( () => {
this.map_completed (actor);
});
break;
default:
this.map_completed (actor);
break;
}
}
public override void destroy (Meta.WindowActor actor) {
switch (actor.meta_window.window_type) {
case Meta.WindowType.NORMAL:
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.rotation_center_x = {0, actor.height, 10};
actor.show ();
actor.animate (Clutter.AnimationMode.EASE_IN_QUAD, 250,
scale_x:0.95f, scale_y:0.95f, opacity:0, rotation_angle_x:15.0f)
.completed.connect ( () => {
this.destroy_completed (actor);
});
break;
case Meta.WindowType.MENU:
case Meta.WindowType.DROPDOWN_MENU:
case Meta.WindowType.POPUP_MENU:
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
actor.scale_gravity = Clutter.Gravity.NORTH;
actor.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200,
scale_y:0.0f, opacity:0).completed.connect ( () => {
this.destroy_completed (actor);
});
break;
default:
this.destroy_completed (actor);
break;
}
}
private GLib.List<Clutter.Actor> win;
private GLib.List<Clutter.Actor> par; //class space for kill func
private Clutter.Group in_group;
private Clutter.Group out_group;
public override void switch_workspace (int from, int to, Meta.MotionDirection direction) {
unowned List<Clutter.Actor> windows =
Meta.Compositor.get_window_actors (this.get_screen ());
//FIXME js/ui/windowManager.js line 430
int w, h;
this.get_screen ().get_size (out w, out h);
var x2 = 0.0f; var y2 = 0.0f;
if (direction == Meta.MotionDirection.UP ||
direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.UP_RIGHT)
y2 = h;
else if (direction == Meta.MotionDirection.DOWN ||
direction == Meta.MotionDirection.DOWN_LEFT ||
direction == Meta.MotionDirection.DOWN_RIGHT)
y2 = -h;
if (direction == Meta.MotionDirection.LEFT ||
direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.DOWN_LEFT)
y2 = h;
else if (direction == Meta.MotionDirection.RIGHT ||
direction == Meta.MotionDirection.UP_RIGHT ||
direction == Meta.MotionDirection.DOWN_RIGHT)
y2 = -h;
var in_group = new Clutter.Group ();
var out_group = new Clutter.Group ();
var group = Meta.Compositor.get_window_group_for_screen (this.get_screen ());
group.add_actor (in_group);
group.add_actor (out_group);
win = new List<Clutter.Actor> ();
par = new List<Clutter.Actor> ();
for (var i=0;i<windows.length ();i++) {
var window = windows.nth_data (i);
if (!(window as Meta.WindowActor).meta_window.showing_on_its_workspace ())
continue;
win.append (window);
par.append (window.get_parent ());
if ((window as Meta.WindowActor).get_workspace () == from) {
window.reparent (out_group);
} else if ((window as Meta.WindowActor).get_workspace () == to) {
window.reparent (in_group);
window.show_all ();
}
}
in_group.set_position (-x2, -y2);
in_group.raise_top ();
out_group.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 300,
x:x2, y:y2);
in_group.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 300,
x:0.0f, y:0.0f).completed.connect ( () => {
end_switch_workspace ();
});
}
public override void kill_window_effects (Meta.WindowActor actor){
/*this.minimize_completed (actor);FIXME should call the things in anim.completed
this.maximize_completed (actor);
this.unmaximize_completed (actor);
this.map_completed (actor);
this.destroy_completed (actor);*/
}
private void end_switch_workspace () {
if (win == null || par == null)
return;
for (var i=0;i<win.length ();i++) {
var window = win.nth_data (i);
if ((window as Meta.WindowActor).is_destroyed ())
continue;
if (window.get_parent () == out_group) {
window.reparent (par.nth_data (i));
window.hide ();
} else
window.reparent (par.nth_data (i));
}
win = null;
par = null;
if (in_group != null) {
in_group.detach_animation ();
in_group.destroy ();
}
if (out_group != null) {
out_group.detach_animation ();
out_group.destroy ();
}
this.switch_workspace_completed ();
}
public override void unmaximize (Meta.WindowActor actor, int x, int y, int w, int h) {
this.unmaximize_completed (actor);
}
public override void kill_switch_workspace () {
end_switch_workspace ();
}
public override bool xevent_filter (X.Event event) {
return x_handle_event (event) != 0;
}
public override Meta.PluginInfo plugin_info () {
return {"Gala", Gala.VERSION, "Tom Beckmann", "GPLv3", "A nice window manager"};
}
}
}

View File

@ -1,29 +0,0 @@
namespace Gala
{
public class Settings : Granite.Services.Settings
{
public bool attach_modal_dialogs { get; set; }
public string[] button_layout { get; set; }
public bool edge_tiling { get; set; }
public bool enable_animations { get; set; }
public string panel_main_menu_action { get; set; }
public string theme { get; set; }
public bool use_gnome_defaults { get; set; }
public bool enable_manager_corner { get; set; }
static Settings? instance = null;
private Settings ()
{
base (SCHEMA);
}
public static Settings get_default()
{
if (instance == null)
instance = new Settings ();
return instance;
}
}
}

View File

@ -1,55 +0,0 @@
public class TextShadowEffect : Clutter.Effect {
int _offset_y;
public int offset_y {
get { return _offset_y; }
set { _offset_y = value; this.update (); }
}
int _offset_x;
public int offset_x {
get { return _offset_x; }
set { _offset_x = value; this.update (); }
}
uint8 _opacity;
public uint8 opacity {
get { return _opacity; }
set { _opacity = value; this.update (); }
}
public TextShadowEffect (int offset_x, int offset_y, uint8 opacity) {
this._offset_x = offset_x;
this._offset_y = offset_y;
this._opacity = opacity;
}
public override bool pre_paint () {
var layout = ((Clutter.Text)this.get_actor ()).get_layout ();
Cogl.pango_render_layout (layout, this.offset_x, this.offset_y,
Cogl.Color.from_4ub (0, 0, 0, opacity), 0);
return true;
}
public void update () {
if (this.get_actor () != null)
this.get_actor ().queue_redraw ();
}
}
namespace Gala {
const string VERSION = "0.1";
const string SCHEMA = "org.pantheon.desktop.gala";
const OptionEntry[] OPTIONS = {
{ "version", 0, OptionFlags.NO_ARG, OptionArg.CALLBACK, (void*) print_version, "Print version", null },
{ null }
};
void print_version () {
stdout.printf ("Gala %s\n", Gala.VERSION);
Meta.exit (Meta.ExitCode.SUCCESS);
}
}

View File

@ -1,31 +0,0 @@
[CCode (cname="clutter_x11_handle_event")]
public extern int x_handle_event (X.Event xevent);
[CCode (cname="clutter_x11_get_stage_window")]
public extern X.Window x_get_stage_window (Clutter.Actor stage);
int main (string [] args) {
unowned OptionContext ctx = Meta.get_option_context ();
ctx.add_main_entries (Gala.OPTIONS, null);
try {
ctx.parse (ref args);
} catch (Error e) {
stderr.printf ("Error initializing: %s\n", e.message);
Meta.exit (Meta.ExitCode.ERROR);
}
Meta.Plugin.type_register (new Gala.Plugin ().get_type ());
/**
* Prevent Meta.init () from causing gtk to load gail and at-bridge
* Taken from Gnome-Shell main.c
*/
GLib.Environment.set_variable ("NO_GAIL", "1", true);
GLib.Environment.set_variable ("NO_AT_BRIDGE", "1", true);
Meta.init ();
GLib.Environment.unset_variable ("NO_GAIL");
GLib.Environment.unset_variable ("NO_AT_BRIDGE");
return Meta.run ();
}