~cjgomes-it/+junk/pantheon-notify

« back to all changes in this revision

Viewing changes to src/pantheon-notify.vala

  • Committer: Carlos Gomes
  • Date: 2014-01-05 00:16:55 UTC
  • Revision ID: cjgomes.it@gmail.com-20140105001655-jxnlrqrw79l6sbrs
first release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
// FIXME: Width and Height should automatically take shadow into account
 
3
public const int WIDTH = 320; //300 + (2 * 10)px shadow
 
4
public const int HEIGHT = 76; //56 + (2 * 10)px shadow
 
5
public const int SHADOW = 10;
 
6
public const int EXPIRE = 7000; //in ms
 
7
 
 
8
 
 
9
[DBus (name="org.freedesktop.Notifications")]
 
10
public class NotifyServer : Object {
 
11
    
 
12
    internal int id_counter = 0;
 
13
    
 
14
    public Gtk.Window main_window;
 
15
    public Clutter.Box box;
 
16
    
 
17
    public NotifyServer () {
 
18
        var clutter = new GtkClutter.Embed ();
 
19
        
 
20
        this.main_window = new Gtk.Window (Gtk.WindowType.POPUP);
 
21
        this.main_window.set_visual (Gdk.Screen.get_default ().get_rgba_visual ());
 
22
        this.main_window.type_hint = Gdk.WindowTypeHint.NOTIFICATION;
 
23
        this.main_window.stick ();
 
24
        this.main_window.set_keep_above (true);
 
25
        this.main_window.focus_on_map = false;
 
26
        this.main_window.accept_focus = false;
 
27
        this.main_window.skip_pager_hint = true;
 
28
        this.main_window.skip_taskbar_hint = true;
 
29
        this.main_window.focus_visible = false;
 
30
        this.box = new Clutter.Box (new Clutter.BoxLayout ());
 
31
        
 
32
        ((Clutter.BoxLayout)this.box.layout_manager).vertical = true;
 
33
        this.box.add_constraint (new Clutter.BindConstraint (clutter.get_stage (), Clutter.BindCoordinate.WIDTH, 0));
 
34
        this.box.add_constraint (new Clutter.BindConstraint (clutter.get_stage (), Clutter.BindCoordinate.HEIGHT, 0));
 
35
        
 
36
        ((Clutter.Stage)clutter.get_stage ()).color = {0, 0, 0, 0};
 
37
        ((Clutter.Stage)clutter.get_stage ()).use_alpha = true;
 
38
        clutter.get_stage ().add_child (box);
 
39
        
 
40
        this.main_window.add (clutter);
 
41
        this.main_window.set_size_request (WIDTH, Gdk.Screen.get_default ().height ());
 
42
        this.main_window.show_all ();
 
43
        
 
44
        this.update_input_shape ();
 
45
        
 
46
                reposition ();
 
47
 
 
48
        Gdk.Screen.get_default ().monitors_changed.connect ( () => {
 
49
                        reposition ();
 
50
        });
 
51
    }
 
52
    
 
53
        public void reposition () {
 
54
                Gdk.Rectangle rect;
 
55
                Gdk.Screen.get_default ().get_monitor_geometry (Gdk.Screen.get_default ().get_primary_monitor (), out rect);
 
56
                main_window.move (rect.x + rect.width - WIDTH, rect.y + 30);
 
57
        }
 
58
 
 
59
    [DBus (visibility=false)]
 
60
    public void update_input_shape () {
 
61
        this.main_window.get_window ().input_shape_combine_region (new Cairo.Region.rectangle 
 
62
            ({0, 0, WIDTH, this.box.get_n_children () * HEIGHT}), 0, 0);
 
63
    }
 
64
    
 
65
    public void close_notification (uint32 id) {
 
66
        
 
67
    }
 
68
    public string [] get_capabilities () {
 
69
        return {"body", "body-markup"};
 
70
    }
 
71
    public void get_server_information (out string name, out string vendor, out string version, out string spec_version) {
 
72
        name = "pantheon-notify";
 
73
        vendor = "ElementaryOS";
 
74
        version = "0.1";
 
75
        spec_version = "1.1";
 
76
    }
 
77
    public new uint32 notify (string app_name, uint32 replaces_id, string app_icon, string summary, 
 
78
        string body, string [] actions, HashTable<string, Variant> hints, int32 expire_timeout, BusName name) {
 
79
        
 
80
        debug ("Bus Name: %s", name);
 
81
        
 
82
        int urgency = 1;
 
83
        if (hints.contains ("urgency"))
 
84
            urgency = hints.lookup ("urgency").get_byte ();
 
85
        message ("New notification, ID: %i, app: %s, icon: %s, priority: %i\n", id_counter + 1, 
 
86
                app_name, app_icon, urgency);
 
87
        
 
88
        
 
89
        if (replaces_id != 0) { //replace the notification
 
90
            
 
91
            bool found_one = false;
 
92
            for (var i=0;i<this.box.get_children ().length ();i++) {
 
93
                if (((Notification)this.box.get_children ().nth_data (i)).id == replaces_id) {
 
94
                    
 
95
                    ((Notification)this.box.get_children ().nth_data (i)).set_text (summary, body);
 
96
                    ((Notification)this.box.get_children ().nth_data (i)).set_pix  (hints, app_name, app_icon);
 
97
                    ((Notification)this.box.get_children ().nth_data (i)).updated ();
 
98
                    
 
99
                    found_one = true;
 
100
                    break;
 
101
                }
 
102
            }
 
103
            
 
104
            if (!found_one) //just add a normal one
 
105
                this.box.insert_child_at_index (new Notification (summary, body, app_icon, 
 
106
                    expire_timeout, app_name, this, hints, replaces_id, actions), 0);
 
107
            
 
108
            this.update_input_shape ();
 
109
            
 
110
            return replaces_id;
 
111
        } else {
 
112
            
 
113
            var notification = new Notification (summary, body, app_icon, 
 
114
                expire_timeout, app_name, this, hints, id_counter+1, actions);
 
115
            this.box.insert_child_at_index (notification, 0);
 
116
            
 
117
            this.update_input_shape ();
 
118
            return id_counter ++;
 
119
        }
 
120
    }
 
121
}
 
122
 
 
123
public static void main (string [] args) {
 
124
    var cl = GtkClutter.init (ref args);
 
125
    if (cl != Clutter.InitError.SUCCESS)
 
126
        error ("Clutter failed to initialize");
 
127
    
 
128
    Granite.Services.Logger.initialize ("pantheon-notifications");
 
129
    Granite.Services.Logger.DisplayLevel = Granite.Services.LogLevel.DEBUG;
 
130
    
 
131
    var n = new NotifyServer ();
 
132
    Bus.own_name (
 
133
        BusType.SESSION, 
 
134
        "org.freedesktop.Notifications", 
 
135
        BusNameOwnerFlags.NONE, 
 
136
        (con) => {
 
137
            try {
 
138
                con.register_object ("/org/freedesktop/Notifications", n);
 
139
            } catch (Error e) { warning (e.message); }
 
140
        }, 
 
141
        () => {}, 
 
142
        (con, name)=> warning ("Could not aquire bus %s", name));
 
143
    
 
144
    Gtk.main ();
 
145
}
 
146