-
Notifications
You must be signed in to change notification settings - Fork 0
Add basic gui tray app #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,7 +12,7 @@ mkdir -p $PKGDIR/usr/bin | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p $PKGDIR/etc/systemd/system | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Ensure build dependency is installed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| apt-get update && apt-get install -y libx11-dev | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| apt-get update && apt-get install -y libx11-dev libgtk-3-dev libappindicator3-dev | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Create control file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cat > $PKGDIR/DEBIAN/control <<EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -24,7 +24,7 @@ Architecture: amd64 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Maintainer: Prince Roshan <princekrroshan01@gmail.com> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description: HCP - Historical Clipboard Manager | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| A historical clipboard manager with LRU history and systemd integration. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Depends: libx11-6 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Depends: libx11-6, libgtk-3-0, libappindicator3-1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Create postinst script directly | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -60,13 +60,73 @@ echo "" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "To check if your environment is set up correctly, run:" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " hcp --diagnostic" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "To enable and start the GUI tray app (clipboard history in system tray), run:" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " sudo systemctl enable hcp-tray@${USERNAME}.service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " sudo systemctl start hcp-tray@${USERNAME}.service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| POSTINST | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chmod 755 $PKGDIR/DEBIAN/postinst | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build the binary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build the main binary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| make | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cp hcp $PKGDIR/usr/bin/hcp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build the GUI tray app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cd gui && make && cd .. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cp gui/hcp-tray $PKGDIR/usr/bin/hcp-tray | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Add systemd service for tray app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cat > $PKGDIR/etc/systemd/system/hcp-tray@.service <<EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Unit] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description=HCP Clipboard Tray App | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| After=graphical-session.target | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Service] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Type=simple | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| User=%i | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Environment=DISPLAY=:0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Environment=XAUTHORITY=/home/%i/.Xauthority | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ExecStart=/usr/bin/hcp-tray | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Restart=on-failure | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Install] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WantedBy=default.target | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+78
to
+93
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fix systemd service configuration inconsistency. The service uses [Unit]
Description=HCP Clipboard Tray App
-After=graphical-session.target
+After=graphical-session.target
[Service]
Type=simple
User=%i
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/%i/.Xauthority
ExecStart=/usr/bin/hcp-tray
Restart=on-failure
[Install]
-WantedBy=default.target
+WantedBy=graphical-session.target📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Create the man page BEFORE building the .deb | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p $PKGDIR/usr/share/man/man1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cat > $PKGDIR/usr/share/man/man1/hcp.1 <<'EOF' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .TH hcp 1 "$(date +%Y-%m-%d)" "$VERSION" "hcp manual" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .SH NAME | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hcp \- Historical Clipboard Manager for X11 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .SH SYNOPSIS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .B hcp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [service start | list | <index> | pop | --help | -h] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .SH DESCRIPTION | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .B hcp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| is a lightweight clipboard manager for X11 systems. It captures clipboard entries, maintains a history, and allows you to list, print, or remove entries. Designed for reliability and minimalism, it works directly with the X11 clipboard and is suitable for use as a background service or on-demand. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .SH COMMANDS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .TP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .B service start | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Start clipboard monitoring service in the background. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .TP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .B list | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List clipboard history. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .TP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .B <index> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Print clipboard entry at <index>. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .TP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .B pop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Remove most recent clipboard entry. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .TP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .B --help, -h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Show this help message. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .SH AUTHOR | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Written by the hcp project contributors. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .SH SEE ALSO | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clipboard(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gzip -f $PKGDIR/usr/share/man/man1/hcp.1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+97
to
+128
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix variable expansion in man page creation. The man page uses -cat > $PKGDIR/usr/share/man/man1/hcp.1 <<'EOF'
-.TH hcp 1 "$(date +%Y-%m-%d)" "$VERSION" "hcp manual"
+cat > $PKGDIR/usr/share/man/man1/hcp.1 <<EOF
+.TH hcp 1 "$(date +%Y-%m-%d)" "$VERSION" "hcp manual"Or use a different approach: +# Create the man page with proper variable expansion
+MANPAGE_DATE=$(date +%Y-%m-%d)
+cat > $PKGDIR/usr/share/man/man1/hcp.1 <<EOF
+.TH hcp 1 "$MANPAGE_DATE" "$VERSION" "hcp manual"🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build the .deb package | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dpkg-deb --build $PKGDIR | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -77,4 +137,8 @@ echo "After install, enable and start the service with:" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " sudo systemctl daemon-reload" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " sudo systemctl enable hcp@${USERNAME}.service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " sudo systemctl start hcp@${USERNAME}.service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "\nYou can override the version by running: VERSION=your_version ./build_deb.sh" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "To enable and start the GUI tray app (clipboard history in system tray), run:" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " sudo systemctl enable hcp-tray@${USERNAME}.service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " sudo systemctl start hcp-tray@${USERNAME}.service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "You can override the version by running: VERSION=your_version ./build_deb.sh" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,14 @@ | ||||||||||||||||||||||
| CXX = g++ | ||||||||||||||||||||||
| CXXFLAGS = -std=c++11 `pkg-config --cflags gtk+-3.0 appindicator3-0.1` -I../include | ||||||||||||||||||||||
| LDFLAGS = `pkg-config --libs gtk+-3.0 appindicator3-0.1` -lX11 | ||||||||||||||||||||||
|
Comment on lines
+2
to
+3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add dependency checking and error handling. The Makefile should verify that required packages are available before building. -CXXFLAGS = -std=c++11 `pkg-config --cflags gtk+-3.0 appindicator3-0.1` -I../include
-LDFLAGS = `pkg-config --libs gtk+-3.0 appindicator3-0.1` -lX11
+# Check for required packages
+PKG_CHECK := $(shell pkg-config --exists gtk+-3.0 appindicator3-0.1 && echo "ok")
+ifneq ($(PKG_CHECK),ok)
+$(error Required packages not found. Install libgtk-3-dev and libappindicator3-dev)
+endif
+
+CXXFLAGS = -std=c++11 -Wall -Wextra `pkg-config --cflags gtk+-3.0 appindicator3-0.1` -I../include
+LDFLAGS = `pkg-config --libs gtk+-3.0 appindicator3-0.1` -lX11📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| SRC = trey_app.cpp ../src/clipboard_mgmt.cpp ../src/db.cpp ../src/logging.cpp | ||||||||||||||||||||||
| TARGET = hcp-tray | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| all: $(TARGET) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| $(TARGET): $(SRC) | ||||||||||||||||||||||
| $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| clean: | ||||||||||||||||||||||
| rm -f $(TARGET) | ||||||||||||||||||||||
|
Comment on lines
+1
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add missing phony targets and improve Makefile robustness. The static analysis correctly identifies missing phony targets and other Makefile best practices. CXX = g++
CXXFLAGS = -std=c++11 `pkg-config --cflags gtk+-3.0 appindicator3-0.1` -I../include
LDFLAGS = `pkg-config --libs gtk+-3.0 appindicator3-0.1` -lX11
SRC = trey_app.cpp ../src/clipboard_mgmt.cpp ../src/db.cpp ../src/logging.cpp
TARGET = hcp-tray
+.PHONY: all clean test
+
all: $(TARGET)
$(TARGET): $(SRC)
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
+test:
+ @echo "No tests defined for GUI component"
+
clean:
rm -f $(TARGET)🧰 Tools🪛 checkmake (0.2.2)[warning] 1-1: Missing required phony target "all" (minphony) [warning] 1-1: Missing required phony target "clean" (minphony) [warning] 1-1: Missing required phony target "test" (minphony) [warning] 8-8: Target "all" should be declared PHONY. (phonydeclared) 🤖 Prompt for AI Agents |
||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,68 @@ | ||||||||||||||||||||||||||||||||||||||||
| #include <gtk/gtk.h> | ||||||||||||||||||||||||||||||||||||||||
| #include <libappindicator3-0.1/libappindicator/app-indicator.h> | ||||||||||||||||||||||||||||||||||||||||
| #include "../include/db.hpp" | ||||||||||||||||||||||||||||||||||||||||
| #include "../include/clipboard_mgmt.hpp" | ||||||||||||||||||||||||||||||||||||||||
| #include <X11/Xlib.h> | ||||||||||||||||||||||||||||||||||||||||
| #include <vector> | ||||||||||||||||||||||||||||||||||||||||
| #include <string> | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| static void on_copy_clicked(GtkButton *button, gpointer user_data) { | ||||||||||||||||||||||||||||||||||||||||
| const char *text = (const char *)user_data; | ||||||||||||||||||||||||||||||||||||||||
| Display *display = XOpenDisplay(nullptr); | ||||||||||||||||||||||||||||||||||||||||
| if (display) { | ||||||||||||||||||||||||||||||||||||||||
| set_clipboard(display, std::string(text)); | ||||||||||||||||||||||||||||||||||||||||
| XCloseDisplay(display); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for clipboard operations. The function should handle potential failures in clipboard operations and provide user feedback. static void on_copy_clicked(GtkButton *button, gpointer user_data) {
const char *text = (const char *)user_data;
Display *display = XOpenDisplay(nullptr);
if (display) {
- set_clipboard(display, std::string(text));
+ try {
+ set_clipboard(display, std::string(text));
+ } catch (const std::exception &e) {
+ g_warning("Failed to set clipboard: %s", e.what());
+ }
XCloseDisplay(display);
+ } else {
+ g_warning("Failed to open X11 display");
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical memory safety issue with dangling pointer. The Apply this diff to fix the memory safety issue by copying the string data: - g_signal_connect(button, "clicked", G_CALLBACK(on_copy_clicked), (gpointer)entry.c_str());
+ char *entry_copy = g_strdup(entry.c_str());
+ g_signal_connect(button, "clicked", G_CALLBACK(on_copy_clicked), entry_copy);
+ g_object_set_data_full(G_OBJECT(button), "entry_data", entry_copy, g_free);And update the static void on_copy_clicked(GtkButton *button, gpointer user_data) {
- const char *text = (const char *)user_data;
+ const char *text = (const char *)g_object_get_data(G_OBJECT(button), "entry_data");
Display *display = XOpenDisplay(nullptr);
if (display) {
set_clipboard(display, std::string(text));
XCloseDisplay(display);
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| static void show_history_window(GtkWidget *, gpointer) { | ||||||||||||||||||||||||||||||||||||||||
| GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||||||||||||||||||||||||||||||||||||||||
| gtk_window_set_title(GTK_WINDOW(window), "Clipboard History"); | ||||||||||||||||||||||||||||||||||||||||
| gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| GtkWidget *scrolled = gtk_scrolled_window_new(NULL, NULL); | ||||||||||||||||||||||||||||||||||||||||
| gtk_container_add(GTK_CONTAINER(window), scrolled); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); | ||||||||||||||||||||||||||||||||||||||||
| gtk_container_add(GTK_CONTAINER(scrolled), vbox); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| std::vector<std::string> history = load_clipboard_blocks(); | ||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for database operations. The - std::vector<std::string> history = load_clipboard_blocks();
+ std::vector<std::string> history;
+ try {
+ history = load_clipboard_blocks();
+ } catch (const std::exception &e) {
+ g_warning("Failed to load clipboard history: %s", e.what());
+ // Show error message to user
+ GtkWidget *error_label = gtk_label_new("Error loading clipboard history");
+ gtk_container_add(GTK_CONTAINER(vbox), error_label);
+ gtk_widget_show_all(window);
+ return;
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| for (const auto &entry : history) { | ||||||||||||||||||||||||||||||||||||||||
| GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); | ||||||||||||||||||||||||||||||||||||||||
| GtkWidget *label = gtk_label_new(entry.substr(0, 60).c_str()); | ||||||||||||||||||||||||||||||||||||||||
| gtk_label_set_xalign(GTK_LABEL(label), 0.0); | ||||||||||||||||||||||||||||||||||||||||
| GtkWidget *button = gtk_button_new_with_label("Copy"); | ||||||||||||||||||||||||||||||||||||||||
| g_signal_connect(button, "clicked", G_CALLBACK(on_copy_clicked), (gpointer)entry.c_str()); | ||||||||||||||||||||||||||||||||||||||||
| gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); | ||||||||||||||||||||||||||||||||||||||||
| gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | ||||||||||||||||||||||||||||||||||||||||
| gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| gtk_widget_show_all(window); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| int main(int argc, char **argv) { | ||||||||||||||||||||||||||||||||||||||||
| gtk_init(&argc, &argv); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| AppIndicator *indicator = app_indicator_new( | ||||||||||||||||||||||||||||||||||||||||
| "clipboard-manager", | ||||||||||||||||||||||||||||||||||||||||
| "system-run-symbolic", | ||||||||||||||||||||||||||||||||||||||||
| APP_INDICATOR_CATEGORY_APPLICATION_STATUS | ||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||
| app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| GtkWidget *menu = gtk_menu_new(); | ||||||||||||||||||||||||||||||||||||||||
| GtkWidget *item_show = gtk_menu_item_new_with_label("Show Clipboard History"); | ||||||||||||||||||||||||||||||||||||||||
| g_signal_connect(item_show, "activate", G_CALLBACK(show_history_window), NULL); | ||||||||||||||||||||||||||||||||||||||||
| gtk_menu_shell_append(GTK_MENU_SHELL(menu), item_show); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| GtkWidget *item_quit = gtk_menu_item_new_with_label("Quit"); | ||||||||||||||||||||||||||||||||||||||||
| g_signal_connect(item_quit, "activate", G_CALLBACK(gtk_main_quit), NULL); | ||||||||||||||||||||||||||||||||||||||||
| gtk_menu_shell_append(GTK_MENU_SHELL(menu), item_quit); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| gtk_widget_show_all(menu); | ||||||||||||||||||||||||||||||||||||||||
| app_indicator_set_menu(indicator, GTK_MENU(menu)); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| gtk_main(); | ||||||||||||||||||||||||||||||||||||||||
| return 0; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -196,4 +196,44 @@ std::string get_clipboard(Display *display) { | |
| } | ||
| XDestroyWindow(display, window); | ||
| return clipboard_content; | ||
| } | ||
|
|
||
| void set_clipboard(Display *display, const std::string &text) { | ||
| Atom clipboard = XInternAtom(display, "CLIPBOARD", False); | ||
| Atom utf8 = XInternAtom(display, "UTF8_STRING", False); | ||
| Atom targets[] = {utf8, XA_STRING}; | ||
|
|
||
| Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, | ||
| 1, 1, 0, 0, 0); | ||
| XSetSelectionOwner(display, clipboard, window, CurrentTime); | ||
|
|
||
| XEvent event; | ||
| bool running = true; | ||
| while (running) { | ||
| XNextEvent(display, &event); | ||
|
|
||
| if (event.type == SelectionRequest) { | ||
| XSelectionRequestEvent *req = &event.xselectionrequest; | ||
| XEvent respond; | ||
| memset(&respond, 0, sizeof(respond)); | ||
| respond.xselection.type = SelectionNotify; | ||
| respond.xselection.display = req->display; | ||
| respond.xselection.requestor = req->requestor; | ||
| respond.xselection.selection = req->selection; | ||
| respond.xselection.target = req->target; | ||
| respond.xselection.time = req->time; | ||
| respond.xselection.property = None; | ||
|
|
||
| if (req->target == utf8 || req->target == XA_STRING) { | ||
| XChangeProperty(display, req->requestor, req->property, req->target, 8, | ||
| PropModeReplace, (const unsigned char *)text.c_str(), | ||
| text.length()); | ||
| respond.xselection.property = req->property; | ||
| } | ||
| XSendEvent(display, req->requestor, 0, 0, &respond); | ||
| XFlush(display); | ||
| running = false; // Only serve one request | ||
| } | ||
| } | ||
| XDestroyWindow(display, window); | ||
| } | ||
|
Comment on lines
+201
to
239
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical issue: Clipboard ownership model is flawed. The current implementation has several serious problems:
For proper clipboard management, consider one of these approaches: Option 1: Persistent ownership (recommended for GUI tray app) -void set_clipboard(Display *display, const std::string &text) {
+void set_clipboard(Display *display, const std::string &text, bool persistent = true) {
// ... existing setup code ...
XEvent event;
- bool running = true;
+ bool running = persistent;
while (running) {
XNextEvent(display, &event);
if (event.type == SelectionRequest) {
// ... existing handling code ...
- running = false; // Only serve one request
+ if (!persistent) running = false; // Only serve one request for CLI usage
}
}
XDestroyWindow(display, window);
}Option 2: Add timeout for non-persistent usage + fd_set readfds;
+ struct timeval timeout;
+ int x11_fd = ConnectionNumber(display);
+
while (running) {
+ FD_ZERO(&readfds);
+ FD_SET(x11_fd, &readfds);
+ timeout.tv_sec = 30; // 30 second timeout
+ timeout.tv_usec = 0;
+
+ if (select(x11_fd + 1, &readfds, NULL, NULL, &timeout) <= 0) {
+ break; // Timeout or error
+ }
+
+ if (XPending(display)) {
XNextEvent(display, &event);
// ... rest of event handling
+ }
}
🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for GUI build process.
The build process assumes the
guidirectory exists and has a working Makefile without verification.📝 Committable suggestion
🤖 Prompt for AI Agents