diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 96 |
1 files changed, 85 insertions, 11 deletions
@@ -29,6 +29,8 @@ #include <glib.h> #include <stdlib.h> #include <gtk/gtk.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> #include <X11/keysym.h> #ifdef HAVE_APPINDICATOR #include <libayatana-appindicator/app-indicator.h> @@ -45,6 +47,9 @@ #include <stdbool.h> #include <string.h> +#define ICON "clipit-trayicon" +#define ICON_OFFLINE "clipit-trayicon-offline" + static gchar* primary_text; static gchar* clipboard_text; static gchar* synchronized_text; @@ -61,6 +66,11 @@ static gboolean status_menu_lock = FALSE; static gboolean actions_lock = FALSE; +static Atom a_Primary = None; +static Atom a_Clipboard = None; +static Atom a_netWmName = None; +static Display *display = NULL; + /* Init preferences structure */ prefs_t prefs = {DEF_USE_COPY, DEF_USE_PRIMARY, @@ -88,7 +98,8 @@ prefs_t prefs = {DEF_USE_COPY, INIT_SEARCH_KEY, INIT_OFFLINE_KEY, DEF_NO_ICON, - DEF_OFFLINE_MODE}; + DEF_OFFLINE_MODE, + DEF_EXCLUDE_WINDOWS}; /* Variables for input buffer used for matching input to menu items */ #define MAX_INPUT_BUF_SIZE 100 @@ -103,7 +114,54 @@ gboolean selected_by_digit(const GtkWidget *history_menu, const GdkEventKey *eve * As the user types, attempt to match input with the values in the menu. * Only the first match will be activated. * */ -gboolean selected_by_input(const GtkWidget *history_menu, const GdkEventKey *event) ; +gboolean selected_by_input(const GtkWidget *history_menu, const GdkEventKey *event); + +/* Determine, if selection comes from excluded window. */ +static gboolean is_selection_from_excluded_window(Atom selection_type) { + gboolean excluded = FALSE; + Window window; + XTextProperty text_prop_return; + gchar* window_name = NULL; + int tmp; + + window = XGetSelectionOwner(display, selection_type); + + if (window != None) + { + // Using _NET_WM_NAME property instead of WM_NAME/XFetchName, because it is guaranted to be UTF-8 encoded. + if (XGetTextProperty(display, window, &text_prop_return, a_netWmName)) + { + window_name = (gchar*) text_prop_return.value; + } + } + + // XGetSelectionOwner doesn't work well for Qt apps. It returns unnamed window outside real app window hierarchy. + // Try focused window instead. + if (!window_name) + { + XGetInputFocus(display, &window, &tmp); + + if (XGetTextProperty(display, window, &text_prop_return, a_netWmName)) + { + window_name = (gchar*) text_prop_return.value; + } + } + + if (window_name) + { + GRegex *regexp = NULL; + if (prefs.exclude_windows && strlen(prefs.exclude_windows) > 0) + { + regexp = g_regex_new(prefs.exclude_windows, G_REGEX_CASELESS, 0, NULL); + if (regexp) { + excluded = g_regex_match(regexp, window_name, 0, NULL); + g_regex_unref(regexp); + } + } + } + + return excluded; +} /* Called every CHECK_INTERVAL seconds to check for new items */ static gboolean item_check(gpointer data) { @@ -157,7 +215,8 @@ static gboolean item_check(gpointer data) { } /* Proceed if mouse button not being held */ - if ((primary_temp != NULL) && !(button_state & GDK_BUTTON1_MASK)) + if ((primary_temp != NULL) && !(button_state & GDK_BUTTON1_MASK) && + !is_selection_from_excluded_window(a_Primary)) { /* Check if primary is the same as the last entry */ if (g_strcmp0(primary_temp, primary_text) != 0) @@ -192,7 +251,8 @@ static gboolean item_check(gpointer data) { else { /* Check if clipboard is the same as the last entry */ - if (g_strcmp0(clipboard_temp, clipboard_text) != 0) + if (g_strcmp0(clipboard_temp, clipboard_text) != 0 && + !is_selection_from_excluded_window(a_Clipboard)) { /* New clipboard entry */ g_free(clipboard_text); @@ -673,6 +733,13 @@ static void toggle_offline_mode() { } prefs.offline_mode = !prefs.offline_mode; + +#ifdef HAVE_APPINDICATOR + app_indicator_set_icon(indicator, prefs.offline_mode ? ICON_OFFLINE : ICON); +#else + gtk_status_icon_set_from_icon_name(status_icon, prefs.offline_mode ? ICON_OFFLINE : ICON); +#endif + /* Save the change */ save_preferences(); } @@ -889,9 +956,9 @@ void create_app_indicator(gint create) { indicator_menu = create_tray_menu(indicator_menu, 2); /* check if we need to create the indicator or just refresh the menu */ if(create == 1) { - indicator = app_indicator_new("clipit", "clipit-trayicon", APP_INDICATOR_CATEGORY_APPLICATION_STATUS); + indicator = app_indicator_new("clipit", ICON, APP_INDICATOR_CATEGORY_APPLICATION_STATUS); app_indicator_set_status (indicator, APP_INDICATOR_STATUS_ACTIVE); - app_indicator_set_attention_icon (indicator, "clipit-trayicon"); + app_indicator_set_attention_icon (indicator, ICON); } app_indicator_set_menu (indicator, GTK_MENU (indicator_menu)); } @@ -980,6 +1047,11 @@ static void clipit_init() { g_signal_connect(primary, "owner-change", G_CALLBACK(item_check), NULL); g_signal_connect(clipboard, "owner-change", G_CALLBACK(item_check), NULL); + display = XOpenDisplay(NULL); + a_Primary = XInternAtom(display, "PRIMARY", True); + a_Clipboard = XInternAtom(display, "CLIPBOARD", True); + a_netWmName = XInternAtom(display, "_NET_WM_NAME", True); + /* Read preferences */ read_preferences(); @@ -1001,7 +1073,7 @@ static void clipit_init() { #ifdef HAVE_APPINDICATOR create_app_indicator(1); #else - status_icon = gtk_status_icon_new_from_icon_name("clipit-trayicon"); + status_icon = gtk_status_icon_new_from_icon_name(ICON); gtk_status_icon_set_tooltip_text((GtkStatusIcon*)status_icon, _("Clipboard Manager")); g_signal_connect((GObject*)status_icon, "button_press_event", (GCallback)status_icon_clicked, NULL); #endif @@ -1014,8 +1086,8 @@ int main(int argc, char **argv) { bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); - input_buffer[0] = '\0'; - input_index = 0; + input_buffer[0] = '\0'; + input_index = 0; /* Initiate GTK+ */ gtk_init(&argc, &argv); @@ -1064,8 +1136,8 @@ int main(int argc, char **argv) { /* Init ClipIt */ clipit_init(); - /* Create the history_timeout_timer if applicable */ - init_history_timeout_timer(); + /* Create the history_timeout_timer if applicable */ + init_history_timeout_timer(); /* Run GTK+ loop */ gtk_main(); @@ -1088,6 +1160,8 @@ int main(int argc, char **argv) { g_free(clipboard_text); g_free(synchronized_text); + XCloseDisplay(display); + /* Exit */ return 0; } |