pidgin/pidgin

Fix transparency plugin for display list/pref changes

13 months ago, Elliott Sales de Andrade
04c0398f1046
Fix transparency plugin for display list/pref changes

There is no longer a buddy list/conversation split, so remove the duplicate settings (half of which were not used any more), and rename them without the differentiating prefix. Also, now that there's only one thing, there's no need for a second "enabled" setting in the plugin that just duplicates the plugin's enabled setting itself, so I removed it.

Instead of adding and removing a slider when the setting changes, I instead opted to always add it, and bind its visibility to the setting instead.

We no longer need a `gtk-config-frame` now that Pidgin uses GPlugin's plugin settings, so remove that and correctly wire up the settings schema so that GPlugin automatically displays settings.

Finally, the scale UI and alpha setting had different ranges. If the setting was moved below the scale's minimum, it would clamp it but not resend that value back to the setting, so things would appear inconsistent. To rectify this, I changed the setting's range up to match the scale.

Testing Done:
* Enabled Transparency plugin, changed around the transparency level and confirmed the main window became transparent.
* Toggled the solid-on-focus setting and confirmed the window lost transparency when focused.
* Toggled the slider setting and confirmed it was added/removed from the window.
* When slider was enabled, changed the setting and confirmed the slider changed and vice versa.

Reviewed at https://reviews.imfreedom.org/r/2394/
/* purple
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "debug.h"
#include "signals.h"
/* must include this to use G_VA_COPY */
#include <string.h>
typedef struct
{
void *instance;
GHashTable *signals;
size_t signal_count;
gulong next_signal_id;
} PurpleInstanceData;
typedef struct
{
gulong id;
PurpleSignalMarshalFunc marshal;
int num_values;
GType *value_types;
GType ret_type;
GList *handlers;
size_t handler_count;
gulong next_handler_id;
} PurpleSignalData;
typedef struct
{
gulong id;
GCallback cb;
void *handle;
void *data;
gboolean use_vargs;
int priority;
} PurpleSignalHandlerData;
static GHashTable *instance_table = NULL;
static void
destroy_instance_data(PurpleInstanceData *instance_data)
{
g_hash_table_destroy(instance_data->signals);
g_free(instance_data);
}
static void
destroy_signal_data(PurpleSignalData *signal_data)
{
g_list_free_full(signal_data->handlers, g_free);
g_free(signal_data->value_types);
g_free(signal_data);
}
gulong
purple_signal_register(void *instance, const char *signal,
PurpleSignalMarshalFunc marshal,
GType ret_type, int num_values, ...)
{
PurpleInstanceData *instance_data;
PurpleSignalData *signal_data;
va_list args;
g_return_val_if_fail(instance != NULL, 0);
g_return_val_if_fail(signal != NULL, 0);
g_return_val_if_fail(marshal != NULL, 0);
instance_data =
(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
if (instance_data == NULL)
{
instance_data = g_new0(PurpleInstanceData, 1);
instance_data->instance = instance;
instance_data->next_signal_id = 1;
instance_data->signals =
g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify)destroy_signal_data);
g_hash_table_insert(instance_table, instance, instance_data);
}
signal_data = g_new0(PurpleSignalData, 1);
signal_data->id = instance_data->next_signal_id;
signal_data->marshal = marshal;
signal_data->next_handler_id = 1;
signal_data->ret_type = ret_type;
signal_data->num_values = num_values;
if (num_values > 0)
{
int i;
signal_data->value_types = g_new0(GType, num_values);
va_start(args, num_values);
for (i = 0; i < num_values; i++)
signal_data->value_types[i] = va_arg(args, GType);
va_end(args);
}
g_hash_table_insert(instance_data->signals,
g_strdup(signal), signal_data);
instance_data->next_signal_id++;
instance_data->signal_count++;
return signal_data->id;
}
void
purple_signal_unregister(void *instance, const char *signal)
{
PurpleInstanceData *instance_data;
g_return_if_fail(instance != NULL);
g_return_if_fail(signal != NULL);
instance_data =
(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
g_return_if_fail(instance_data != NULL);
g_hash_table_remove(instance_data->signals, signal);
instance_data->signal_count--;
if (instance_data->signal_count == 0)
{
/* Unregister the instance. */
g_hash_table_remove(instance_table, instance);
}
}
void
purple_signals_unregister_by_instance(void *instance)
{
g_return_if_fail(instance != NULL);
g_hash_table_remove(instance_table, instance);
/*
* Makes things easier (more annoying?) for developers who don't have
* things registering and unregistering in the right order :)
*/
/* g_return_if_fail(found); */
}
static gint handler_priority(void * a, void * b) {
PurpleSignalHandlerData *ah = (PurpleSignalHandlerData*)a;
PurpleSignalHandlerData *bh = (PurpleSignalHandlerData*)b;
if (ah->priority > bh->priority) return 1;
if (ah->priority < bh->priority) return -1;
return 0;
}
static gulong
signal_connect_common(void *instance, const char *signal, void *handle,
GCallback func, void *data, int priority, gboolean use_vargs)
{
PurpleInstanceData *instance_data;
PurpleSignalData *signal_data;
PurpleSignalHandlerData *handler_data;
g_return_val_if_fail(instance != NULL, 0);
g_return_val_if_fail(signal != NULL, 0);
g_return_val_if_fail(handle != NULL, 0);
g_return_val_if_fail(func != NULL, 0);
/* Get the instance data */
instance_data =
(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
if (instance_data == NULL)
{
purple_debug_warning("signals", "Something tried to register a callback "
"for the '%s' signal, but we do not have any signals "
"registered with the given handle\n", signal);
g_return_val_if_reached(0);
}
/* Get the signal data */
signal_data =
(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
if (signal_data == NULL) {
purple_debug_error("signals", "Signal data for %s not found!", signal);
return 0;
}
/* Create the signal handler data */
handler_data = g_new0(PurpleSignalHandlerData, 1);
handler_data->id = signal_data->next_handler_id;
handler_data->cb = func;
handler_data->handle = handle;
handler_data->data = data;
handler_data->use_vargs = use_vargs;
handler_data->priority = priority;
signal_data->handlers = g_list_insert_sorted(signal_data->handlers, handler_data, (GCompareFunc)handler_priority);
signal_data->handler_count++;
signal_data->next_handler_id++;
return handler_data->id;
}
gulong
purple_signal_connect_priority(void *instance, const char *signal, void *handle,
GCallback func, void *data, int priority)
{
return signal_connect_common(instance, signal, handle, func, data, priority, FALSE);
}
gulong
purple_signal_connect(void *instance, const char *signal, void *handle,
GCallback func, void *data)
{
return signal_connect_common(instance, signal, handle, func, data, PURPLE_SIGNAL_PRIORITY_DEFAULT, FALSE);
}
void
purple_signal_disconnect(void *instance, const char *signal,
void *handle, GCallback func)
{
PurpleInstanceData *instance_data;
PurpleSignalData *signal_data;
PurpleSignalHandlerData *handler_data;
GList *l;
gboolean found = FALSE;
g_return_if_fail(instance != NULL);
g_return_if_fail(signal != NULL);
g_return_if_fail(handle != NULL);
g_return_if_fail(func != NULL);
/* Get the instance data */
instance_data =
(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
g_return_if_fail(instance_data != NULL);
/* Get the signal data */
signal_data =
(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
if (signal_data == NULL) {
purple_debug_error("signals", "Signal data for %s not found!", signal);
return;
}
/* Find the handler data. */
for (l = signal_data->handlers; l != NULL; l = l->next)
{
handler_data = (PurpleSignalHandlerData *)l->data;
if (handler_data->handle == handle && handler_data->cb == func)
{
g_free(handler_data);
signal_data->handlers = g_list_delete_link(signal_data->handlers,
l);
signal_data->handler_count--;
found = TRUE;
break;
}
}
/* See note somewhere about this actually helping developers.. */
g_return_if_fail(found);
}
/*
* TODO: Make this all more efficient by storing a list of handlers, keyed
* to a handle.
*/
static void
disconnect_handle_from_signals(G_GNUC_UNUSED const char *signal,
PurpleSignalData *signal_data, void *handle)
{
GList *l, *l_next;
PurpleSignalHandlerData *handler_data;
for (l = signal_data->handlers; l != NULL; l = l_next)
{
handler_data = (PurpleSignalHandlerData *)l->data;
l_next = l->next;
if (handler_data->handle == handle)
{
g_free(handler_data);
signal_data->handler_count--;
signal_data->handlers = g_list_delete_link(signal_data->handlers,
l);
}
}
}
static void
disconnect_handle_from_instance(G_GNUC_UNUSED gpointer instance,
PurpleInstanceData *instance_data,
void *handle)
{
g_hash_table_foreach(instance_data->signals,
(GHFunc)disconnect_handle_from_signals, handle);
}
void
purple_signals_disconnect_by_handle(void *handle)
{
g_return_if_fail(handle != NULL);
g_hash_table_foreach(instance_table,
(GHFunc)disconnect_handle_from_instance, handle);
}
void
purple_signal_emit(void *instance, const char *signal, ...)
{
PurpleInstanceData *instance_data;
PurpleSignalData *signal_data;
PurpleSignalHandlerData *handler_data;
GList *l, *l_next;
va_list args;
va_list tmp;
g_return_if_fail(instance != NULL);
g_return_if_fail(signal != NULL);
instance_data =
(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
g_return_if_fail(instance_data != NULL);
signal_data =
(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
if (signal_data == NULL) {
purple_debug_error("signals", "Signal data for %s not found!", signal);
return;
}
va_start(args, signal);
for (l = signal_data->handlers; l != NULL; l = l_next)
{
l_next = l->next;
handler_data = (PurpleSignalHandlerData *)l->data;
/* This is necessary because a va_list may only be
* evaluated once */
G_VA_COPY(tmp, args);
if (handler_data->use_vargs)
{
((void (*)(va_list, void *))handler_data->cb)(tmp,
handler_data->data);
}
else
{
signal_data->marshal(handler_data->cb, tmp,
handler_data->data, NULL);
}
va_end(tmp);
}
va_end(args);
}
void *
purple_signal_emit_return_1(void *instance, const char *signal, ...) {
PurpleInstanceData *instance_data;
PurpleSignalData *signal_data;
PurpleSignalHandlerData *handler_data;
GList *l, *l_next;
va_list args;
va_list tmp;
void *ret_val = NULL;
g_return_val_if_fail(instance != NULL, NULL);
g_return_val_if_fail(signal != NULL, NULL);
instance_data =
(PurpleInstanceData *)g_hash_table_lookup(instance_table, instance);
g_return_val_if_fail(instance_data != NULL, NULL);
signal_data =
(PurpleSignalData *)g_hash_table_lookup(instance_data->signals, signal);
if (signal_data == NULL) {
purple_debug_error("signals", "Signal data for %s not found!", signal);
return 0;
}
va_start(args, signal);
for (l = signal_data->handlers; l != NULL; l = l_next)
{
l_next = l->next;
handler_data = (PurpleSignalHandlerData *)l->data;
G_VA_COPY(tmp, args);
if (handler_data->use_vargs)
{
ret_val = ((void *(*)(va_list, void *))handler_data->cb)(
tmp, handler_data->data);
}
else
{
signal_data->marshal(handler_data->cb, tmp,
handler_data->data, &ret_val);
}
va_end(tmp);
if(ret_val != NULL) {
break;
}
}
va_end(args);
return ret_val;
}
void
purple_signals_init(void)
{
g_return_if_fail(instance_table == NULL);
instance_table =
g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify)destroy_instance_data);
}
void
purple_signals_uninit(void)
{
g_return_if_fail(instance_table != NULL);
g_clear_pointer(&instance_table, g_hash_table_destroy);
}
/**************************************************************************
* Marshallers
**************************************************************************/
void
purple_marshal_VOID(GCallback cb, G_GNUC_UNUSED va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
((void (*)(void *))cb)(data);
}
void
purple_marshal_VOID__POINTER(GCallback cb, va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
((void (*)(void *, void *))cb)(arg1, data);
}
void
purple_marshal_VOID__POINTER_UINT(GCallback cb, va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
guint arg2 = va_arg(args, guint);
((void (*)(void *, guint, void *))cb)(arg1, arg2, data);
}
void
purple_marshal_VOID__POINTER_INT_INT(GCallback cb, va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
gint arg2 = va_arg(args, gint);
gint arg3 = va_arg(args, gint);
((void (*)(void *, gint, gint, void *))cb)(arg1, arg2, arg3, data);
}
void
purple_marshal_VOID__POINTER_INT_POINTER(GCallback cb, va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
gint arg2 = va_arg(args, gint);
void *arg3 = va_arg(args, void *);
((void (*)(void *, gint, void *, void *))cb)(arg1, arg2, arg3, data);
}
void
purple_marshal_VOID__POINTER_POINTER(GCallback cb, va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
((void (*)(void *, void *, void *))cb)(arg1, arg2, data);
}
void
purple_marshal_VOID__POINTER_POINTER_UINT(GCallback cb, va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
guint arg3 = va_arg(args, guint);
((void (*)(void *, void *, guint, void *))cb)(arg1, arg2, arg3, data);
}
void
purple_marshal_VOID__POINTER_POINTER_UINT_UINT(GCallback cb, va_list args,
void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
guint arg3 = va_arg(args, guint);
guint arg4 = va_arg(args, guint);
((void (*)(void *, void *, guint, guint, void *))cb)(arg1, arg2, arg3, arg4, data);
}
void
purple_marshal_VOID__POINTER_UINT_UINT(GCallback cb, va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
guint arg2 = va_arg(args, guint);
guint arg3 = va_arg(args, guint);
((void (*)(void *, guint, guint, void *))cb)(arg1, arg2, arg3, data);
}
void
purple_marshal_VOID__POINTER_POINTER_POINTER(GCallback cb, va_list args,
void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
((void (*)(void *, void *, void *, void *))cb)(arg1, arg2, arg3, data);
}
void
purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER(GCallback cb,
va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
void *arg4 = va_arg(args, void *);
((void (*)(void *, void *, void *, void *, void *))cb)(arg1, arg2, arg3, arg4, data);
}
void
purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER(GCallback cb,
va_list args,
void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
void *arg4 = va_arg(args, void *);
void *arg5 = va_arg(args, void *);
((void (*)(void *, void *, void *, void *, void *, void *))cb)(arg1, arg2, arg3, arg4, arg5, data);
}
void
purple_marshal_VOID__POINTER_POINTER_POINTER_UINT(GCallback cb,
va_list args, void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
guint arg4 = va_arg(args, guint);
((void (*)(void *, void *, void *, guint, void *))cb)(arg1, arg2, arg3, arg4, data);
}
void
purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT(GCallback cb,
va_list args,
void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
void *arg4 = va_arg(args, void *);
guint arg5 = va_arg(args, guint);
((void (*)(void *, void *, void *, void *, guint, void *))cb)(arg1, arg2, arg3, arg4, arg5, data);
}
void
purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT(GCallback cb,
va_list args,
void *data,
G_GNUC_UNUSED void **return_val)
{
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
guint arg4 = va_arg(args, guint);
guint arg5 = va_arg(args, guint);
((void (*)(void *, void *, void *, guint, guint, void *))cb)(
arg1, arg2, arg3, arg4, arg5, data);
}
void
purple_marshal_INT__POINTER_POINTER_POINTER(
GCallback cb, va_list args, void *data, void **return_val)
{
gint ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
ret_val = ((gint (*)(void *, void *, void *, void *))cb)(arg1, arg2, arg3, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER(
GCallback cb, va_list args, void *data, void **return_val)
{
gint ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
void *arg4 = va_arg(args, void *);
void *arg5 = va_arg(args, void *);
ret_val =
((gint (*)(void *, void *, void *, void *, void *, void *))cb)(
arg1, arg2, arg3, arg4, arg5, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER(GCallback cb, va_list args, void *data,
void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
ret_val = ((gboolean (*)(void *, void *))cb)(arg1, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER_POINTER(GCallback cb, va_list args,
void *data, void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
ret_val = ((gboolean (*)(void *, void *, void *))cb)(arg1, arg2, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER_BOOLEAN(GCallback cb, va_list args,
void *data, void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
gboolean arg2 = va_arg(args, gboolean);
ret_val = ((gboolean (*)(void *, gboolean, void *))cb)(arg1, arg2, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER(GCallback cb, va_list args,
void *data, void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
ret_val = ((gboolean (*)(void *, void *, void *, void *))cb)(arg1, arg2,
arg3, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER_POINTER_UINT(GCallback cb,
va_list args,
void *data,
void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
guint arg3 = va_arg(args, guint);
ret_val = ((gboolean (*)(void *, void *, guint, void *))cb)(
arg1, arg2, arg3, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER(GCallback cb,
va_list args,
void *data,
void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
void *arg4 = va_arg(args, void *);
ret_val = ((gboolean (*)(void *, void *, void *, void *, void *))cb)(
arg1, arg2, arg3, arg4, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER(
GCallback cb, va_list args, void *data, void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
void *arg4 = va_arg(args, void *);
void *arg5 = va_arg(args, void *);
ret_val =
((gboolean (*)(void *, void *, void *, void *, void *, void *))cb)(
arg1, arg2, arg3, arg4, arg5, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}
void
purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER(
GCallback cb, va_list args, void *data, void **return_val)
{
gboolean ret_val;
void *arg1 = va_arg(args, void *);
void *arg2 = va_arg(args, void *);
void *arg3 = va_arg(args, void *);
void *arg4 = va_arg(args, void *);
void *arg5 = va_arg(args, void *);
void *arg6 = va_arg(args, void *);
ret_val =
((gboolean (*)(void *, void *, void *, void *, void *, void *, void *))cb)(
arg1, arg2, arg3, arg4, arg5, arg6, data);
if (return_val != NULL)
*return_val = GINT_TO_POINTER(ret_val);
}