~diodon-team/diodon/new-upstream-release-1.2.0

« back to all changes in this revision

Viewing changes to plugins/zeitgeist/zeitgeist-plugin.vala

Fixed merge conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Diodon - GTK+ clipboard manager.
3
 
 * Copyright (C) 2012 Diodon Team <diodon-team@lists.launchpad.net>
4
 
 *
5
 
 * This program is free software: you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published
7
 
 * by the Free Software Foundation, either version 2 of the License, or (at
8
 
 * your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful, but
11
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12
 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
13
 
 * License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
namespace Diodon.Plugins
20
 
{
21
 
    /**
22
 
     * A Zeitgeist data provider for diodon
23
 
     *
24
 
     * @author Oliver Sauder <os@esite.ch>
25
 
     */
26
 
    public class ZeitgeistPlugin : Peas.ExtensionBase, Peas.Activatable
27
 
    {
28
 
        private Zeitgeist.Log log;
29
 
        public Object object { get; construct; }
30
 
 
31
 
        public ZeitgeistPlugin()
32
 
        {
33
 
            Object();
34
 
        }
35
 
 
36
 
        public void activate()
37
 
        {
38
 
            Controller controller = object as Controller;
39
 
           
40
 
            if(log == null) {
41
 
                log = new Zeitgeist.Log();
42
 
            }
43
 
            
44
 
            controller.on_add_item.connect(add_clipboard_item);
45
 
        }
46
 
 
47
 
        public void deactivate()
48
 
        {
49
 
            Controller controller = object as Controller;
50
 
            
51
 
            controller.on_add_item.disconnect(add_clipboard_item);
52
 
        }
53
 
 
54
 
        public void update_state()
55
 
        {
56
 
        }
57
 
        
58
 
        private void add_clipboard_item(IClipboardItem item)
59
 
        {
60
 
            string interpretation = Zeitgeist.NFO.PLAIN_TEXT_DOCUMENT;
61
 
            if(item is FileClipboardItem) {
62
 
                interpretation = Zeitgeist.NFO.FILE_DATA_OBJECT;
63
 
            }
64
 
            else if (item is ImageClipboardItem) {
65
 
                interpretation = Zeitgeist.NFO.IMAGE;
66
 
            }
67
 
        
68
 
            string? origin = get_path_of_active_application();
69
 
            
70
 
            Zeitgeist.Subject subject = new Zeitgeist.Subject();
71
 
            
72
 
            subject.uri = "clipboard://" + item.get_checksum();
73
 
            subject.interpretation = interpretation;
74
 
            subject.manifestation = Zeitgeist.NFO.DATA_CONTAINER;
75
 
            subject.mimetype = item.get_mime_type();
76
 
            if(origin != null) {
77
 
                subject.origin = origin;
78
 
            }
79
 
            subject.text = item.get_label();
80
 
            //subject.set_storage("");
81
 
            
82
 
            Zeitgeist.Event event = new Zeitgeist.Event();
83
 
            //event.set_id(
84
 
            event.interpretation = Zeitgeist.ZG.CREATE_EVENT;
85
 
            event.manifestation = Zeitgeist.ZG.USER_ACTIVITY;
86
 
            event.actor = "application://diodon.desktop";
87
 
            event.add_subject(subject);
88
 
            // content should be added, however ignored as currently
89
 
            // data is not being read
90
 
            //event.set_payload();
91
 
            
92
 
            TimeVal cur_time = TimeVal();
93
 
            int64 timestamp = Zeitgeist.Timestamp.from_timeval(cur_time);
94
 
            event.timestamp = timestamp;
95
 
            
96
 
            GenericArray<Zeitgeist.Event> events = new GenericArray<Zeitgeist.Event>();
97
 
            events.add(event);
98
 
 
99
 
            log.insert_events_no_reply(events);
100
 
        }
101
 
        
102
 
        private string? get_path_of_active_application()
103
 
        {
104
 
            X.Window window = get_active_window();
105
 
            if(window != X.None) {
106
 
                ulong pid = get_pid(window);
107
 
                
108
 
                if(pid != 0) {
109
 
                    File file = File.new_for_path("/proc/" + pid.to_string() + "/exe");
110
 
                    try {
111
 
                        FileInfo info = file.query_info(FileAttribute.STANDARD_SYMLINK_TARGET, 
112
 
                            FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
113
 
                        if(info != null) {
114
 
                            string path = info.get_attribute_as_string(
115
 
                                FileAttribute.STANDARD_SYMLINK_TARGET);
116
 
                            debug("Path is %s", path);
117
 
                            return path;
118
 
                        }
119
 
                    }
120
 
                    catch(GLib.Error e) {
121
 
                        debug("Error occured while reading %s: %s",
122
 
                            file.get_path(), e.message);
123
 
                    }
124
 
                }
125
 
            }
126
 
            
127
 
            return null;
128
 
        }
129
 
        
130
 
        private X.Window get_active_window()
131
 
        {
132
 
            unowned Gdk.Screen screen = Gdk.Screen.get_default();
133
 
            Gdk.Window active_window = screen.get_active_window();
134
 
            if(active_window != null) {
135
 
                X.Window xactive_window = Gdk.X11Window.get_xid(active_window);
136
 
                debug("Active window %#x", (int)xactive_window);
137
 
                return xactive_window;
138
 
            }
139
 
            
140
 
            return X.None;
141
 
        }
142
 
        
143
 
        private ulong get_pid(X.Window window)
144
 
        {
145
 
            unowned X.Display display = Gdk.x11_get_default_xdisplay();
146
 
            X.Atom wm_pid = display.intern_atom("_NET_WM_PID", false);
147
 
            
148
 
            if(wm_pid != X.None) {
149
 
                X.Atom actual_type_return;
150
 
                int actual_format_return;
151
 
                ulong nitems_return;
152
 
                ulong bytes_after_return;
153
 
                void* prop_return = null;
154
 
 
155
 
                int status = display.get_window_property(window, wm_pid, 0,
156
 
                    long.MAX, false, 0, out actual_type_return, out actual_format_return,
157
 
                    out nitems_return, out bytes_after_return, out prop_return);
158
 
                
159
 
                if(status == X.Success) {
160
 
                    if(prop_return != null) {
161
 
                        ulong pid = *((ulong*)prop_return);
162
 
                        debug("Copied by process with pid %lu", pid);
163
 
                        return pid;
164
 
                    }
165
 
                }
166
 
            }
167
 
            
168
 
            return 0;
169
 
        }
170
 
    }
171
 
}
172
 
 
173
 
[ModuleInit]
174
 
public void peas_register_types (GLib.TypeModule module)
175
 
{
176
 
  Peas.ObjectModule objmodule = module as Peas.ObjectModule;
177
 
  objmodule.register_extension_type (typeof (Peas.Activatable),
178
 
                                     typeof (Diodon.Plugins.ZeitgeistPlugin));
179
 
}
180