Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions libdiodon/image-clipboard-item.vala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace Diodon
private ClipboardType _clipboard_type;
private string _checksum; // checksum to identify pic content
private Gdk.Pixbuf _pixbuf;
private ByteArray? _raw_payload; // kept for lazy pixbuf loading
private string _label;
private string? _origin;
private DateTime _date_copied;
Expand Down Expand Up @@ -61,11 +62,17 @@ namespace Diodon
_origin = origin;
_date_copied = date_copied;

// Extract dimensions and checksum without keeping full pixbuf
// in memory. Store raw payload for lazy decoding when needed.
Gdk.PixbufLoader loader = new Gdk.PixbufLoader();
loader.write(payload.data);
loader.close();
Gdk.Pixbuf pixbuf = loader.get_pixbuf();
extract_pixbuf_info(pixbuf);

// Keep payload for lazy reload, release full pixbuf
_raw_payload = payload;
_pixbuf = null;
}

/**
Expand Down Expand Up @@ -123,7 +130,7 @@ namespace Diodon
public Icon get_icon()
{
try {
File file = save_tmp_pixbuf(_pixbuf);
File file = save_tmp_pixbuf(ensure_pixbuf());
FileIcon icon = new FileIcon(file);
return icon;
} catch(Error e) {
Expand All @@ -146,7 +153,7 @@ namespace Diodon
*/
public Gtk.Image? get_image()
{
Gdk.Pixbuf pixbuf_preview = create_scaled_pixbuf(_pixbuf);
Gdk.Pixbuf pixbuf_preview = create_scaled_pixbuf(ensure_pixbuf());
return new Gtk.Image.from_pixbuf(pixbuf_preview);
}

Expand All @@ -155,8 +162,11 @@ namespace Diodon
*/
public ByteArray? get_payload() throws GLib.Error
{
if (_raw_payload != null) {
return _raw_payload;
}
uint8[] buffer;
_pixbuf.save_to_buffer(out buffer, "png");
ensure_pixbuf().save_to_buffer(out buffer, "png");
return new ByteArray.take(buffer);
}

Expand All @@ -173,7 +183,7 @@ namespace Diodon
*/
public void to_clipboard(Gtk.Clipboard clipboard)
{
clipboard.set_image(_pixbuf);
clipboard.set_image(ensure_pixbuf());
clipboard.store();
}

Expand Down Expand Up @@ -219,6 +229,31 @@ namespace Diodon
_pixbuf = pixbuf;
}

/**
* Lazily loads the full pixbuf from raw payload when needed.
* Items loaded from Zeitgeist only keep the raw payload until
* the pixbuf is actually required (e.g. paste or icon display).
*
* @return decoded pixbuf
*/
private Gdk.Pixbuf ensure_pixbuf()
{
if (_pixbuf != null) {
return _pixbuf;
}

try {
Gdk.PixbufLoader loader = new Gdk.PixbufLoader();
loader.write(_raw_payload.data);
loader.close();
_pixbuf = loader.get_pixbuf();
} catch (Error e) {
warning("Failed to decode image payload: %s", e.message);
_pixbuf = new Gdk.Pixbuf(Gdk.Colorspace.RGB, false, 8, 1, 1);
}
return _pixbuf;
}

/**
* Create a menu icon size scaled pix buf
*
Expand Down
16 changes: 12 additions & 4 deletions libdiodon/text-clipboard-item.vala
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,20 @@ namespace Diodon
_date_copied = date_copied;
_checksum = Checksum.compute_for_string(ChecksumType.SHA1, _text);

// label should not be longer than 50 letters
_label = _text;
// Truncate early to avoid processing large strings.
// Vala's string.replace() uses g_regex_replace_literal() internally
// which runs the entire string through PCRE2. For large clipboard
// items (e.g. 74KB of text), this causes excessive CPU usage.
// 200 bytes is enough to contain 50 UTF-8 chars (max 4 bytes each).
string label_text = _text;
if (label_text.length > 200) {
label_text = label_text.substring(0, 200);
}
_label = string.joinv(" ", label_text.split("\n"));
if (_label.char_count() > 50) {
_label = _label.substring(0, 50) + "...";
long index_char = _label.index_of_nth_char(50);
_label = _label.substring(0, index_char) + "...";
}
_label = _label.replace("\n", " ");
}

/**
Expand Down