pidgin/pidgin

Get transparency plugin working again

20 months ago, Elliott Sales de Andrade
eef0cabd6340
Parents c68748c1f42e
Children c6edf4d87185
Get transparency plugin working again

No need to restrict to Windows-only as it uses plain GTK APIs.

GTK4 doesn't support setting Always-on-Top programmatically, and that seems bad from the user point of view for programs to be able to do that anyway, so drop that option.

Instead of tracking a list of windows manually based on `PurpleConversation`s, just follow along the `GtkApplication` for windows added/removed.

Testing Done:
Configuration is completely untested because we have no way to open plugin prefs yet.

Enabled plugin and checked that Buddy List and Conversation Windows were made transparent. The latter also gained a slider to set the opacity, which also worked.

Opaque-during-focus also seemed to work, though there seems to be a bug with the window getting a focus `enter` event on hover even if the window isn't really focused.

We don't currently have a way to create a second Conversation Window, so I can't be entirely sure the window signals work, but at least `window-added` is checked because the plugin is loaded before the first window is created.

Reviewed at https://reviews.imfreedom.org/r/1731/
--- a/pidgin/plugins/meson.build Fri Sep 09 01:11:21 2022 -0500
+++ b/pidgin/plugins/meson.build Fri Sep 09 01:33:01 2022 -0500
@@ -28,14 +28,11 @@
build_by_default: false,
install : false, install_dir : PIDGIN_PLUGINDIR)
-if IS_WIN32
- transparency = library('transparency', 'transparency.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PidginPlugin-Transparency"'],
- dependencies : [libpurple_dep, libpidgin_dep, glib],
- name_prefix : '',
- build_by_default: false,
- install : true, install_dir : PIDGIN_PLUGINDIR)
-endif
+transparency = library('transparency', 'transparency.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PidginPlugin-Transparency"'],
+ dependencies : [libpurple_dep, libpidgin_dep, glib],
+ name_prefix : '',
+ install : true, install_dir : PIDGIN_PLUGINDIR)
if enable_unity
unity = library('unity', 'unity.c',
--- a/pidgin/plugins/transparency.c Fri Sep 09 01:11:21 2022 -0500
+++ b/pidgin/plugins/transparency.c Fri Sep 09 01:33:01 2022 -0500
@@ -39,13 +39,11 @@
* loading for users who were using it. */
#define WINTRANS_PLUGIN_ID "gtk-win-trans"
-/*
- * DATA STRUCTS
- */
-typedef struct {
- GtkWidget *win;
- GtkWidget *slider;
-} slider_win;
+/* Key used to save GtkEventControllerFocus for this plugin. */
+#define WINTRANS_CONTROLLER_KEY (WINTRANS_PLUGIN_ID "-focus-controller")
+
+/* Key used to save GtkSlider for this plugin. */
+#define WINTRANS_SLIDER_KEY (WINTRANS_PLUGIN_ID "-slider")
/*
* LOCALS
@@ -54,12 +52,9 @@
static const char *OPT_WINTRANS_IM_ALPHA = "/plugins/gtk/transparency/im_alpha";
static const char *OPT_WINTRANS_IM_SLIDER = "/plugins/gtk/transparency/im_slider";
static const char *OPT_WINTRANS_IM_ONFOCUS= "/plugins/gtk/transparency/im_solid_onfocus";
-static const char *OPT_WINTRANS_IM_ONTOP = "/plugins/gtk/transparency/im_always_on_top";
static const char *OPT_WINTRANS_BL_ENABLED= "/plugins/gtk/transparency/bl_enabled";
static const char *OPT_WINTRANS_BL_ALPHA = "/plugins/gtk/transparency/bl_alpha";
static const char *OPT_WINTRANS_BL_ONFOCUS= "/plugins/gtk/transparency/bl_solid_onfocus";
-static const char *OPT_WINTRANS_BL_ONTOP = "/plugins/gtk/transparency/bl_always_on_top";
-static GSList *window_list = NULL;
/*
* CODE
@@ -80,55 +75,81 @@
}
/* Set window transparency level */
-static void set_wintrans(GtkWidget *window, int alpha, gboolean enabled,
- gboolean always_on_top) {
- GdkWindow *gdk_window = gtk_widget_get_window(window);
-
+static void
+set_wintrans(GtkWidget *window, int alpha, gboolean enabled)
+{
if (enabled) {
- gdk_window_set_opacity(gdk_window, alpha / 255.0);
- gdk_window_set_keep_above(gdk_window, always_on_top);
+ gtk_widget_set_opacity(window, alpha / 255.0);
} else {
- gdk_window_set_opacity(gdk_window, 1);
- gdk_window_set_keep_above(gdk_window, 0);
+ gtk_widget_set_opacity(window, 1);
}
+
+ /* Changing from opaque to partially transparent seems to need some kind of
+ * structural refresh. Unfortunately, a simple `gtk_widget_queue_draw` is
+ * not sufficient, so we need to do this instead. */
+ gtk_widget_queue_resize(window);
}
/* When a conv window is focused, if we're only transparent when unfocused,
* deal with transparency */
-static gboolean focus_conv_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) {
- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)
- && purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) {
- GtkWidget *window = (GtkWidget *) d;
- if (e->in) { /* Focused */
- set_wintrans(window, 0, FALSE,
- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
- } else {
- set_wintrans(window,
- purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA),
- TRUE,
- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
- }
+static void
+focus_conv_win_cb(GtkEventControllerFocus *self, gpointer data) {
+ GtkWidget *window = NULL;
+ gboolean enter = GPOINTER_TO_INT(data);
+
+ if(!purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
+ return;
+ }
+ if(!purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) {
+ return;
}
- return FALSE;
+
+ window = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(self));
+ set_wintrans(window, purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA), !enter);
+}
+
+static void
+add_focus_controller_to_conv_win(GtkWidget *window) {
+ GtkEventController *focus = NULL;
+
+ focus = gtk_event_controller_focus_new();
+ g_signal_connect(focus, "enter", G_CALLBACK(focus_conv_win_cb),
+ GINT_TO_POINTER(TRUE));
+ g_signal_connect(focus, "leave", G_CALLBACK(focus_conv_win_cb),
+ GINT_TO_POINTER(FALSE));
+
+ gtk_widget_add_controller(window, focus);
+ g_object_set_data(G_OBJECT(window), WINTRANS_CONTROLLER_KEY, focus);
+}
+
+static void
+remove_focus_controller_from_conv_win(GtkWidget *window) {
+ GtkEventController *focus = NULL;
+
+ focus = g_object_get_data(G_OBJECT(window), WINTRANS_CONTROLLER_KEY);
+ if(GTK_IS_EVENT_CONTROLLER_FOCUS(focus)) {
+ gtk_widget_remove_controller(window, focus);
+ }
+ g_object_set_data(G_OBJECT(window), WINTRANS_CONTROLLER_KEY, NULL);
}
/* When buddy list window is focused,
* if we're only transparent when unfocused, deal with transparency */
-static gboolean focus_blist_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) {
- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)
- && purple_prefs_get_bool(OPT_WINTRANS_BL_ONFOCUS)) {
- GtkWidget *window = (GtkWidget *) d;
- if (e->in) { /* Focused */
- set_wintrans(window, 0, FALSE,
- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
- } else {
- set_wintrans(window,
- purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
- TRUE,
- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
- }
+static void
+focus_blist_win_cb(GtkEventControllerFocus *self, gpointer data)
+{
+ GtkWidget *window = NULL;
+ gboolean enter = GPOINTER_TO_INT(data);
+
+ if(!purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) {
+ return;
}
- return FALSE;
+ if(!purple_prefs_get_bool(OPT_WINTRANS_BL_ONFOCUS)) {
+ return;
+ }
+
+ window = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(self));
+ set_wintrans(window, purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA), !enter);
}
static void change_alpha(GtkWidget *w, gpointer data) {
@@ -137,84 +158,27 @@
/* If we're in no-transparency on focus mode,
* don't take effect immediately */
- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS))
- set_wintrans(GTK_WIDGET(data), alpha, TRUE,
- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
-}
-
-
-static GtkWidget *wintrans_slider(GtkWidget *win) {
- GtkWidget *hbox;
- GtkWidget *label, *slider;
- GtkWidget *frame;
-
- int imalpha = purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA);
-
- frame = gtk_frame_new(NULL);
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
- gtk_widget_show(frame);
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
- gtk_container_add(GTK_CONTAINER(frame), hbox);
-
- label = gtk_label_new(_("Opacity:"));
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
- gtk_widget_show(hbox);
-
- slider = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 50, 255, 1);
- gtk_range_set_value(GTK_RANGE(slider), imalpha);
-
- /* On slider val change, update window's transparency level */
- g_signal_connect(G_OBJECT(slider), "value-changed",
- G_CALLBACK(change_alpha), win);
-
- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
-
- /* Set the initial transparency level */
- set_wintrans(win, imalpha, TRUE,
- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
-
- gtk_widget_show_all(hbox);
-
- return frame;
-}
-
-static slider_win* find_slidwin(GtkWidget *win) {
- GSList *tmp = window_list;
-
- while (tmp) {
- if (((slider_win*) (tmp->data))->win == win)
- return (slider_win*) tmp->data;
- tmp = tmp->next;
+ if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) {
+ set_wintrans(GTK_WIDGET(data), alpha, TRUE);
}
- return NULL;
}
/* Clean up transparency stuff for the conv window */
-static void cleanup_conv_window(PidginConvWindow *win) {
- GtkWidget *window = win->window;
- slider_win *slidwin = NULL;
-
- /* Remove window from the window list */
- purple_debug_info(WINTRANS_PLUGIN_ID,
- "Conv window destroyed... removing from list\n");
-
- if ((slidwin = find_slidwin(window))) {
- window_list = g_slist_remove(window_list, slidwin);
- g_free(slidwin);
+static void
+conversation_delete_cb(G_GNUC_UNUSED GtkApplication *application,
+ GtkWindow *window, G_GNUC_UNUSED gpointer data)
+{
+ if(!PIDGIN_IS_CONVERSATION_WINDOW(window)) {
+ return;
}
- /* Remove the focus cbs */
- g_signal_handlers_disconnect_by_func(G_OBJECT(window),
- G_CALLBACK(focus_conv_win_cb), window);
-}
+ purple_debug_info(WINTRANS_PLUGIN_ID,
+ "Conv window destroyed... removing from list");
-static void
-conversation_delete_cb(PurpleConversation *conv) {
- PidginConvWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
- /* If it is the last conversation in the window, cleanup */
- if (win != NULL && pidgin_conv_window_get_gtkconv_count(win) == 1)
- cleanup_conv_window(win);
+ g_object_set_data(G_OBJECT(window), WINTRANS_SLIDER_KEY, NULL);
+
+ /* Remove the focus cbs */
+ remove_focus_controller_from_conv_win(GTK_WIDGET(window));
}
static void set_blist_trans(GtkWidget *w, const char *pref) {
@@ -223,110 +187,119 @@
purple_prefs_set_bool(pref, enabled);
if (window != NULL) {
set_wintrans(window, purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
- purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED),
- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+ purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED));
}
}
+static void
+remove_slider(GtkWidget *slider_frame) {
+ purple_prefs_disconnect_by_handle(slider_frame);
+ gtk_widget_unparent(slider_frame);
+}
+
+static void
+update_slider(G_GNUC_UNUSED const gchar *name,
+ G_GNUC_UNUSED PurplePrefType type,
+ gconstpointer val, gpointer data)
+{
+ GtkWidget *slider = data;
+ gint imalpha = GPOINTER_TO_INT(val);
+
+ gtk_range_set_value(GTK_RANGE(slider), imalpha);
+}
+
static void add_slider(GtkWidget *win) {
- GList *wl, *wl1;
GtkWidget *vbox = NULL;
+ GtkWidget *slider_frame;
+ GtkWidget *hbox;
+ GtkWidget *label, *slider;
+ gint imalpha = 255;
/* Look up this window to see if it already has a slider */
- if (!find_slidwin(win)) {
- GtkWidget *slider_box = NULL;
- slider_win *slidwin = NULL;
+ if (g_object_get_data(G_OBJECT(win), WINTRANS_SLIDER_KEY) != NULL) {
+ return;
+ }
+
+ vbox = gtk_widget_get_first_child(win);
+ while(vbox != NULL && !GTK_IS_BOX(vbox)) {
+ vbox = gtk_widget_get_next_sibling(vbox);
+ }
- /* Get top vbox */
- for (wl1 = wl = gtk_container_get_children(
- GTK_CONTAINER(win));
- wl != NULL;
- wl = wl->next) {
- if (GTK_IS_BOX(G_OBJECT(wl->data)))
- vbox = GTK_WIDGET(wl->data);
- else {
- purple_debug_error(WINTRANS_PLUGIN_ID,
- "no vbox found\n");
- return;
- }
- }
- g_list_free(wl1);
+ if(vbox == NULL) {
+ purple_debug_error(WINTRANS_PLUGIN_ID, "no vbox found");
+ return;
+ }
- slider_box = wintrans_slider(win);
- gtk_box_pack_start(GTK_BOX(vbox), slider_box, FALSE, FALSE, 0);
+ slider_frame = gtk_frame_new(NULL);
+ gtk_widget_set_margin_start(slider_frame, 6);
+ gtk_widget_set_margin_end(slider_frame, 6);
+ gtk_box_prepend(GTK_BOX(vbox), slider_frame);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_frame_set_child(GTK_FRAME(slider_frame), hbox);
- /* Add window to list, to track that it has a slider */
- slidwin = g_new0(slider_win, 1);
- slidwin->win = win;
- slidwin->slider = slider_box;
- window_list = g_slist_append(window_list, slidwin);
- }
-}
+ label = gtk_label_new(_("Opacity:"));
+ gtk_box_append(GTK_BOX(hbox), label);
+
+ slider = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 50, 255, 1);
+ gtk_widget_set_hexpand(slider, TRUE);
+ gtk_box_append(GTK_BOX(hbox), slider);
-static void remove_sliders() {
- if (window_list) {
- GSList *tmp = window_list;
- while (tmp) {
- slider_win *slidwin = (slider_win*) tmp->data;
- if (slidwin != NULL &&
- GTK_IS_WINDOW(slidwin->win)) {
- gtk_widget_destroy(slidwin->slider);
- }
- g_free(slidwin);
- tmp = tmp->next;
- }
- g_slist_free(window_list);
- window_list = NULL;
- }
+ imalpha = purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA);
+ gtk_range_set_value(GTK_RANGE(slider), imalpha);
+ /* On slider val change, update window's transparency level */
+ g_signal_connect(G_OBJECT(slider), "value-changed",
+ G_CALLBACK(change_alpha), win);
+
+ /* Set the initial transparency level */
+ set_wintrans(win, purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA), TRUE);
+
+ purple_prefs_connect_callback(slider_frame, OPT_WINTRANS_IM_ALPHA,
+ update_slider, slider);
+
+ /* Set window data, to track that it has a slider */
+ g_object_set_data_full(G_OBJECT(win), WINTRANS_SLIDER_KEY, slider_frame,
+ (GDestroyNotify)remove_slider);
}
/* Remove all transparency related aspects from conversation windows */
static void remove_convs_wintrans(gboolean remove_signal) {
+ GApplication *application = NULL;
GList *wins;
- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
- PidginConvWindow *win = wins->data;
- GtkWidget *window = win->window;
+ application = g_application_get_default();
+ wins = gtk_application_get_windows(GTK_APPLICATION(application));
+
+ for(; wins; wins = wins->next) {
+ GtkWidget *window = wins->data;
- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED))
- set_wintrans(window, 0, FALSE, FALSE);
+ if(!PIDGIN_IS_CONVERSATION_WINDOW(window)) {
+ continue;
+ }
+
+ if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
+ set_wintrans(window, 0, FALSE);
+ }
/* Remove the focus cbs */
- if (remove_signal)
- g_signal_handlers_disconnect_by_func(G_OBJECT(window),
- G_CALLBACK(focus_conv_win_cb), window);
+ if (remove_signal) {
+ remove_focus_controller_from_conv_win(window);
+ }
+
+ g_object_set_data(G_OBJECT(window), WINTRANS_SLIDER_KEY, NULL);
}
-
- remove_sliders();
}
-static void set_conv_window_trans(PidginConvWindow *oldwin, PidginConvWindow *newwin) {
- GtkWidget *win = newwin->window;
-
+static void
+set_conv_window_trans(GtkWidget *window) {
/* check prefs to see if we want trans */
if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
- set_wintrans(win, purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA),
- TRUE, purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+ set_wintrans(window, purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA), TRUE);
if (purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER)) {
- add_slider(win);
+ add_slider(window);
}
}
-
- /* If we're moving from one window to another,
- * add the focus listeners to the new window if not already there */
- if (oldwin != NULL && oldwin != newwin) {
- if (pidgin_conv_window_get_gtkconv_count(newwin) == 0) {
- g_signal_connect(G_OBJECT(win), "focus_in_event",
- G_CALLBACK(focus_conv_win_cb), win);
- g_signal_connect(G_OBJECT(win), "focus_out_event",
- G_CALLBACK(focus_conv_win_cb), win);
- }
-
- /* If we've moved the last conversation, cleanup the window */
- if (pidgin_conv_window_get_gtkconv_count(oldwin) == 1)
- cleanup_conv_window(oldwin);
- }
}
static void update_convs_wintrans(GtkWidget *toggle_btn, const char *pref) {
@@ -334,97 +307,94 @@
GTK_TOGGLE_BUTTON(toggle_btn)));
if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
+ GApplication *application = NULL;
GList *wins;
- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
- PidginConvWindow *win = wins->data;
- set_conv_window_trans(NULL, win);
- }
+ application = g_application_get_default();
+ wins = gtk_application_get_windows(GTK_APPLICATION(application));
- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER))
- remove_sliders();
- }
- else
- remove_convs_wintrans(FALSE);
-}
-
-static void
-conv_updated_cb(PurpleConversation *conv, PurpleConversationUpdateType type) {
- PidginConversation *pconv = PIDGIN_CONVERSATION(conv);
- PidginConvWindow *win = pidgin_conv_get_window(pconv);
+ for(; wins; wins = wins->next) {
+ GtkWidget *win = wins->data;
- if(type == PURPLE_CONVERSATION_UPDATE_UNSEEN
- && pconv->unseen_state == PIDGIN_UNSEEN_NONE
- && pidgin_conv_window_get_gtkconv_count(win) == 1) {
- GtkWidget *window = win->window;
- gboolean has_focus;
+ if(!PIDGIN_IS_CONVERSATION_WINDOW(win)) {
+ continue;
+ }
- g_object_get(G_OBJECT(window), "has-toplevel-focus", &has_focus, NULL);
+ set_conv_window_trans(win);
- if(!has_focus || !purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) {
- set_conv_window_trans(NULL, win);
+ if (!purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER)) {
+ g_object_set_data(G_OBJECT(win), WINTRANS_SLIDER_KEY, NULL);
+ }
}
-
- if(g_signal_handler_find(G_OBJECT(window), G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, G_CALLBACK(focus_conv_win_cb), NULL) == 0) {
- g_signal_connect(G_OBJECT(window), "focus_in_event",
- G_CALLBACK(focus_conv_win_cb), window);
- g_signal_connect(G_OBJECT(window), "focus_out_event",
- G_CALLBACK(focus_conv_win_cb), window);
- }
+ } else {
+ remove_convs_wintrans(FALSE);
}
}
static void
-new_conversation_cb(PurpleConversation *conv) {
- PidginConvWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
-
- /* If it is the first conversation in the window,
- * add the sliders, and set transparency */
- if(pidgin_conv_window_get_gtkconv_count(win) == 1) {
- GtkWidget *window = win->window;
+new_conversation_cb(G_GNUC_UNUSED GtkApplication *application,
+ GtkWindow *window, G_GNUC_UNUSED gpointer data)
+{
+ if(!PIDGIN_IS_CONVERSATION_WINDOW(window)) {
+ return;
+ }
- set_conv_window_trans(NULL, win);
-
- g_signal_connect(G_OBJECT(window), "focus_in_event",
- G_CALLBACK(focus_conv_win_cb), window);
- g_signal_connect(G_OBJECT(window), "focus_out_event",
- G_CALLBACK(focus_conv_win_cb), window);
- }
+ set_conv_window_trans(GTK_WIDGET(window));
+ add_focus_controller_to_conv_win(GTK_WIDGET(window));
}
static void
blist_created_cb(PurpleBuddyList *purple_blist, gpointer data) {
GtkWidget *window = get_buddy_list_window();
if (window != NULL) {
+ GtkEventController *focus = NULL;
+
if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) {
set_wintrans(window,
purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
- TRUE,
- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
+ TRUE);
}
- g_signal_connect(G_OBJECT(window), "focus_in_event",
- G_CALLBACK(focus_blist_win_cb), window);
- g_signal_connect(G_OBJECT(window), "focus_out_event",
- G_CALLBACK(focus_blist_win_cb), window);
+ focus = gtk_event_controller_focus_new();
+
+ g_signal_connect(focus, "enter", G_CALLBACK(focus_blist_win_cb),
+ GINT_TO_POINTER(TRUE));
+ g_signal_connect(focus, "leave", G_CALLBACK(focus_blist_win_cb),
+ GINT_TO_POINTER(FALSE));
+
+ gtk_widget_add_controller(window, focus);
+ g_object_set_data(G_OBJECT(window), WINTRANS_CONTROLLER_KEY, focus);
}
}
static void alpha_change(GtkWidget *w, gpointer data) {
+ GApplication *application = NULL;
GList *wins;
int imalpha = gtk_range_get_value(GTK_RANGE(w));
- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
- PidginConvWindow *win = wins->data;
- set_wintrans(win->window, imalpha, TRUE,
- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+ application = g_application_get_default();
+ wins = gtk_application_get_windows(GTK_APPLICATION(application));
+
+ for(; wins; wins = wins->next) {
+ GtkWidget *window = wins->data;
+
+ if(!PIDGIN_IS_CONVERSATION_WINDOW(window)) {
+ continue;
+ }
+
+ set_wintrans(window, imalpha, TRUE);
}
}
-static void alpha_pref_set_int (GtkWidget *w, GdkEventFocus *e, const char *pref)
-{
- int alpha = gtk_range_get_value(GTK_RANGE(w));
+static void
+alpha_pref_set_int(GtkEventControllerFocus *self, gpointer data) {
+ const char *pref = data;
+ GtkWidget *slider = NULL;
+ int alpha = 255;
+
+ slider = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(self));
+ alpha = gtk_range_get_value(GTK_RANGE(slider));
+
purple_prefs_set_int(pref, alpha);
}
@@ -435,19 +405,24 @@
}
}
-static void update_existing_convs() {
+static void
+update_existing_convs(void) {
+ GApplication *application = NULL;
GList *wins;
- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
- PidginConvWindow *win = wins->data;
- GtkWidget *window = win->window;
+ application = g_application_get_default();
+ wins = gtk_application_get_windows(GTK_APPLICATION(application));
+
+ for(; wins; wins = wins->next) {
+ GtkWidget *window = wins->data;
- set_conv_window_trans(NULL, win);
+ if(!PIDGIN_IS_CONVERSATION_WINDOW(window)) {
+ continue;
+ }
- g_signal_connect(G_OBJECT(window), "focus_in_event",
- G_CALLBACK(focus_conv_win_cb), window);
- g_signal_connect(G_OBJECT(window), "focus_out_event",
- G_CALLBACK(focus_conv_win_cb), window);
+ set_conv_window_trans(window);
+
+ add_focus_controller_to_conv_win(window);
}
}
@@ -459,9 +434,13 @@
GtkWidget *label, *slider;
GtkWidget *button;
GtkWidget *trans_box;
+ GtkEventController *focus = NULL;
ret = gtk_box_new(GTK_ORIENTATION_VERTICAL, 18);
- gtk_container_set_border_width(GTK_CONTAINER (ret), 12);
+ gtk_widget_set_margin_start(ret, 12);
+ gtk_widget_set_margin_end(ret, 12);
+ gtk_widget_set_margin_top(ret, 12);
+ gtk_widget_set_margin_bottom(ret, 12);
/* IM Convo trans options */
imtransbox = pidgin_make_frame(ret, _("IM Conversation Windows"));
@@ -472,7 +451,6 @@
(gpointer) OPT_WINTRANS_IM_ENABLED);
trans_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 18);
- gtk_widget_show(trans_box);
g_object_bind_property(button, "active", trans_box, "sensitive",
G_BINDING_SYNC_CREATE);
@@ -486,19 +464,13 @@
_("Remove IM window transparency on focus"),
OPT_WINTRANS_IM_ONFOCUS, trans_box);
- button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_IM_ONTOP,
- trans_box);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(update_convs_wintrans),
- (gpointer) OPT_WINTRANS_IM_ONTOP);
-
- gtk_box_pack_start(GTK_BOX(imtransbox), trans_box, FALSE, FALSE, 5);
+ gtk_box_append(GTK_BOX(imtransbox), trans_box);
/* IM transparency slider */
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
label = gtk_label_new(_("Opacity:"));
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+ gtk_box_append(GTK_BOX(hbox), label);
slider = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 50, 255, 1);
gtk_range_set_value(GTK_RANGE(slider),
@@ -506,15 +478,14 @@
g_signal_connect(G_OBJECT(slider), "value-changed",
G_CALLBACK(alpha_change), NULL);
- g_signal_connect(G_OBJECT(slider), "focus-out-event",
- G_CALLBACK(alpha_pref_set_int),
- (gpointer) OPT_WINTRANS_IM_ALPHA);
+ focus = gtk_event_controller_focus_new();
+ g_signal_connect(focus, "leave", G_CALLBACK(alpha_pref_set_int),
+ (gpointer)OPT_WINTRANS_IM_ALPHA);
+ gtk_widget_add_controller(slider, focus);
- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
+ gtk_box_append(GTK_BOX(hbox), slider);
- gtk_widget_show_all(hbox);
-
- gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5);
+ gtk_box_append(GTK_BOX(trans_box), hbox);
/* Buddy List trans options */
bltransbox = pidgin_make_frame (ret, _("Buddy List Window"));
@@ -525,24 +496,18 @@
(gpointer) OPT_WINTRANS_BL_ENABLED);
trans_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 18);
- gtk_widget_show(trans_box);
g_object_bind_property(button, "active", trans_box, "sensitive",
G_BINDING_SYNC_CREATE);
button = pidgin_prefs_checkbox(
_("Remove Buddy List window transparency on focus"),
OPT_WINTRANS_BL_ONFOCUS, trans_box);
- button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_BL_ONTOP,
- trans_box);
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(set_blist_trans),
- (gpointer) OPT_WINTRANS_BL_ONTOP);
- gtk_box_pack_start(GTK_BOX(bltransbox), trans_box, FALSE, FALSE, 5);
+ gtk_box_append(GTK_BOX(bltransbox), trans_box);
/* IM transparency slider */
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
label = gtk_label_new(_("Opacity:"));
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+ gtk_box_append(GTK_BOX(hbox), label);
slider = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 50, 255, 1);
gtk_range_set_value(GTK_RANGE(slider),
@@ -550,17 +515,15 @@
g_signal_connect(G_OBJECT(slider), "value-changed",
G_CALLBACK(bl_alpha_change), NULL);
- g_signal_connect(G_OBJECT(slider), "focus-out-event",
- G_CALLBACK(alpha_pref_set_int),
- (gpointer) OPT_WINTRANS_BL_ALPHA);
-
- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
+ focus = gtk_event_controller_focus_new();
+ g_signal_connect(focus, "leave", G_CALLBACK(alpha_pref_set_int),
+ (gpointer)OPT_WINTRANS_BL_ALPHA);
+ gtk_widget_add_controller(slider, focus);
- gtk_widget_show_all(hbox);
+ gtk_box_append(GTK_BOX(hbox), slider);
- gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5);
+ gtk_box_append(GTK_BOX(trans_box), hbox);
- gtk_widget_show_all(ret);
return ret;
}
@@ -588,8 +551,8 @@
static gboolean
transparency_load(GPluginPlugin *plugin, GError **error) {
+ GApplication *application = NULL;
GtkWidget *window = NULL;
- gpointer conv_handle = NULL;
purple_prefs_add_none("/plugins/gtk");
purple_prefs_add_none("/plugins/gtk/transparency");
@@ -597,23 +560,16 @@
purple_prefs_add_int(OPT_WINTRANS_IM_ALPHA, 255);
purple_prefs_add_bool(OPT_WINTRANS_IM_SLIDER, FALSE);
purple_prefs_add_bool(OPT_WINTRANS_IM_ONFOCUS, FALSE);
- purple_prefs_add_bool(OPT_WINTRANS_IM_ONTOP, FALSE);
purple_prefs_add_bool(OPT_WINTRANS_BL_ENABLED, FALSE);
purple_prefs_add_int(OPT_WINTRANS_BL_ALPHA, 255);
purple_prefs_add_bool(OPT_WINTRANS_BL_ONFOCUS, FALSE);
- purple_prefs_add_bool(OPT_WINTRANS_BL_ONTOP, FALSE);
purple_prefs_rename("/plugins/gtk/win32/wintrans", "/plugins/gtk/transparency");
- conv_handle = purple_conversations_get_handle();
- purple_signal_connect(conv_handle, "conversation-created", plugin,
- G_CALLBACK(new_conversation_cb), NULL);
-
- /* Set callback to remove window from the list, if the window is destroyed */
- purple_signal_connect(conv_handle, "deleting-conversation", plugin,
- G_CALLBACK(conversation_delete_cb), NULL);
-
- purple_signal_connect(conv_handle, "conversation-updated", plugin,
- G_CALLBACK(conv_updated_cb), NULL);
+ application = g_application_get_default();
+ g_signal_connect(application, "window-added",
+ G_CALLBACK(new_conversation_cb), NULL);
+ g_signal_connect(application, "window-removed",
+ G_CALLBACK(conversation_delete_cb), NULL);
update_existing_convs();
@@ -639,12 +595,17 @@
window = get_buddy_list_window();
if (window != NULL) {
- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED))
- set_wintrans(window, 0, FALSE, FALSE);
+ GtkEventController *focus = NULL;
+
+ if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) {
+ set_wintrans(window, 0, FALSE);
+ }
/* Remove the focus cbs */
- g_signal_handlers_disconnect_by_func(G_OBJECT(window),
- G_CALLBACK(focus_blist_win_cb), window);
+ focus = g_object_get_data(G_OBJECT(window), WINTRANS_CONTROLLER_KEY);
+ if(GTK_IS_EVENT_CONTROLLER_FOCUS(focus)) {
+ gtk_widget_remove_controller(window, focus);
+ }
}
return TRUE;