2
* Diodon - GTK+ clipboard manager.
3
* Copyright (C) 2012 Diodon Team <diodon-team@lists.launchpad.net>
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.
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.
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/>.
19
namespace Diodon.Plugins
22
* A Zeitgeist data provider for diodon
24
* @author Oliver Sauder <os@esite.ch>
26
public class ZeitgeistPlugin : Peas.ExtensionBase, Peas.Activatable
28
private Zeitgeist.Log log;
29
public Object object { get; construct; }
31
public ZeitgeistPlugin()
36
public void activate()
38
Controller controller = object as Controller;
41
log = new Zeitgeist.Log();
44
controller.on_add_item.connect(add_clipboard_item);
47
public void deactivate()
49
Controller controller = object as Controller;
51
controller.on_add_item.disconnect(add_clipboard_item);
54
public void update_state()
58
private void add_clipboard_item(IClipboardItem item)
60
string interpretation = Zeitgeist.NFO.PLAIN_TEXT_DOCUMENT;
61
if(item is FileClipboardItem) {
62
interpretation = Zeitgeist.NFO.FILE_DATA_OBJECT;
64
else if (item is ImageClipboardItem) {
65
interpretation = Zeitgeist.NFO.IMAGE;
68
string? origin = get_path_of_active_application();
70
Zeitgeist.Subject subject = new Zeitgeist.Subject();
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();
77
subject.origin = origin;
79
subject.text = item.get_label();
80
//subject.set_storage("");
82
Zeitgeist.Event event = new Zeitgeist.Event();
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();
92
TimeVal cur_time = TimeVal();
93
int64 timestamp = Zeitgeist.Timestamp.from_timeval(cur_time);
94
event.timestamp = timestamp;
96
GenericArray<Zeitgeist.Event> events = new GenericArray<Zeitgeist.Event>();
99
log.insert_events_no_reply(events);
102
private string? get_path_of_active_application()
104
X.Window window = get_active_window();
105
if(window != X.None) {
106
ulong pid = get_pid(window);
109
File file = File.new_for_path("/proc/" + pid.to_string() + "/exe");
111
FileInfo info = file.query_info(FileAttribute.STANDARD_SYMLINK_TARGET,
112
FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
114
string path = info.get_attribute_as_string(
115
FileAttribute.STANDARD_SYMLINK_TARGET);
116
debug("Path is %s", path);
120
catch(GLib.Error e) {
121
debug("Error occured while reading %s: %s",
122
file.get_path(), e.message);
130
private X.Window get_active_window()
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;
143
private ulong get_pid(X.Window window)
145
unowned X.Display display = Gdk.x11_get_default_xdisplay();
146
X.Atom wm_pid = display.intern_atom("_NET_WM_PID", false);
148
if(wm_pid != X.None) {
149
X.Atom actual_type_return;
150
int actual_format_return;
152
ulong bytes_after_return;
153
void* prop_return = null;
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);
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);
174
public void peas_register_types (GLib.TypeModule module)
176
Peas.ObjectModule objmodule = module as Peas.ObjectModule;
177
objmodule.register_extension_type (typeof (Peas.Activatable),
178
typeof (Diodon.Plugins.ZeitgeistPlugin));