~gala-dev/gala/trunk

« back to all changes in this revision

Viewing changes to src/Widgets/WindowThumb.vala

  • Committer: Rico Tzschichholz
  • Date: 2012-08-27 21:04:25 UTC
  • mfrom: (182.1.29 gala-expose-natural)
  • Revision ID: ricotz@ubuntu.com-20120827210425-jvvwsdxlv1ruscpf
Add window-overview feature to expose windows of the current workspace

There are two placements algorithms available (grid, natural) to choose
from.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  
 
2
//  Copyright (C) 2012 Tom Beckmann
 
3
// 
 
4
//  This program is free software: you can redistribute it and/or modify
 
5
//  it under the terms of the GNU General Public License as published by
 
6
//  the Free Software Foundation, either version 3 of the License, or
 
7
//  (at your option) any later version.
 
8
// 
 
9
//  This program is distributed in the hope that it will be useful,
 
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
//  GNU General Public License for more details.
 
13
// 
 
14
//  You should have received a copy of the GNU General Public License
 
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
// 
 
17
 
 
18
using Meta;
 
19
using Clutter;
 
20
 
 
21
namespace Gala
 
22
{
 
23
        public class WindowThumb : Actor
 
24
        {
 
25
                public weak Window window;
 
26
                Clone clone;
 
27
                public GtkClutter.Texture icon;
 
28
                public GtkClutter.Texture close_button;
 
29
                
 
30
                public signal void selected (Window window);
 
31
                public signal void reposition ();
 
32
                
 
33
                public WindowThumb (Window _window)
 
34
                {
 
35
                        window = _window;
 
36
                        
 
37
                        reactive = true;
 
38
                        
 
39
                        var actor = window.get_compositor_private () as WindowActor;
 
40
                        clone = new Clone (actor.get_texture ());
 
41
                        
 
42
                        icon = new GtkClutter.Texture ();
 
43
                        icon.scale_x = 0.0f;
 
44
                        icon.scale_y = 0.0f;
 
45
                        icon.scale_gravity = Gravity.CENTER;
 
46
                        
 
47
                        try {
 
48
                                icon.set_from_pixbuf (Utils.get_icon_for_window (window, 64));
 
49
                        } catch (Error e) { warning (e.message); }
 
50
                        
 
51
                        close_button = new GtkClutter.Texture ();
 
52
                        close_button.reactive = true;
 
53
                        close_button.visible = false;
 
54
                        close_button.scale_x = 0.0f;
 
55
                        close_button.scale_y = 0.0f;
 
56
                        close_button.scale_gravity = Gravity.CENTER;
 
57
                        close_button.button_press_event.connect (close_clicked);
 
58
                        close_button.leave_event.connect ((e) => leave_event (e));
 
59
                        
 
60
                        try {
 
61
                                close_button.set_from_pixbuf (Granite.Widgets.Utils.get_close_pixbuf ());
 
62
                        } catch (Error e) { warning (e.message); }
 
63
                        
 
64
                        add_child (clone);
 
65
                        
 
66
                        var stage = Compositor.get_stage_for_screen (window.get_screen ());
 
67
                        stage.add_child (icon);
 
68
                        stage.add_child (close_button);
 
69
                }
 
70
                
 
71
                bool close_clicked (ButtonEvent event)
 
72
                {
 
73
                        if (event.button != 1)
 
74
                                return false;
 
75
                        
 
76
                        //make sure we dont see a window closing animation in the background
 
77
                        (window.get_compositor_private () as Actor).opacity = 0;
 
78
                        get_parent ().set_child_below_sibling (this, null);
 
79
                        animate (AnimationMode.EASE_IN_CUBIC, 200, depth : -50.0f, opacity : 0).completed.connect (() => {
 
80
                                destroy ();
 
81
                                window.delete (window.get_screen ().get_display ().get_current_time ());
 
82
                        });
 
83
                        
 
84
                        close_button.destroy ();
 
85
                        icon.destroy ();
 
86
                        
 
87
                        reposition ();
 
88
                        
 
89
                        return true;
 
90
                }
 
91
                
 
92
                public override bool enter_event (CrossingEvent event)
 
93
                {
 
94
                        //if we're still animating don't show the close button
 
95
                        if (get_animation () != null)
 
96
                                return false;
 
97
                        
 
98
                        close_button.visible = true;
 
99
                        close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f);
 
100
                        
 
101
                        return true;
 
102
                }
 
103
                
 
104
                public override bool motion_event (MotionEvent event)
 
105
                {
 
106
                        if (get_animation () != null)
 
107
                                return false;
 
108
                        
 
109
                        close_button.visible = true;
 
110
                        close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f);
 
111
                        
 
112
                        return true;
 
113
                }
 
114
                
 
115
                public override bool leave_event (CrossingEvent event)
 
116
                {
 
117
                        if (event.related == close_button)
 
118
                                return false;
 
119
                        
 
120
                        close_button.animate (AnimationMode.EASE_IN_QUAD, 200, scale_x : 0.0f, scale_y : 0.0f)
 
121
                                .completed.connect (() => close_button.visible = false );
 
122
                        
 
123
                        return true;
 
124
                }
 
125
                
 
126
                public override bool button_press_event (ButtonEvent event)
 
127
                {
 
128
                        get_parent ().set_child_above_sibling (this, null);
 
129
                        selected (window);
 
130
                        
 
131
                        return true;
 
132
                }
 
133
                
 
134
                public void close (bool do_animate=true)
 
135
                {
 
136
                        unowned Meta.Rectangle rect = window.get_outer_rect ();
 
137
                        
 
138
                        //FIXME need to subtract 10 here to remove jump for most windows, but adds jump for maximized ones
 
139
                        float delta = window.maximized_horizontally || window.maximized_vertically ? 0 : 10;
 
140
                        
 
141
                        float dest_x = rect.x - delta;
 
142
                        float dest_y = rect.y - delta;
 
143
                        
 
144
                        //stop all running animations
 
145
                        detach_animation ();
 
146
                        icon.detach_animation ();
 
147
                        
 
148
                        if (do_animate) {
 
149
                                icon.animate (AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f).completed.connect ( () => {
 
150
                                        icon.destroy ();
 
151
                                });
 
152
                                
 
153
                                animate (AnimationMode.EASE_IN_OUT_CUBIC, 300, scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => {
 
154
                                        (window.get_compositor_private () as Actor).show ();
 
155
                                        destroy ();
 
156
                                });
 
157
                        } else {
 
158
                                (window.get_compositor_private () as Actor).show ();
 
159
                                
 
160
                                destroy ();
 
161
                                icon.destroy ();
 
162
                        }
 
163
                        
 
164
                        close_button.destroy ();
 
165
                }
 
166
        }
 
167
}