diff options
-rw-r--r-- | meson.build | 6 | ||||
-rw-r--r-- | meson_options.txt | 3 | ||||
-rw-r--r-- | pidgin/plugins/gestures/gestures.c | 33 | ||||
-rw-r--r-- | pidgin/plugins/gestures/gstroke.h | 7 | ||||
-rw-r--r-- | pidgin/plugins/gestures/meson.build | 5 | ||||
-rw-r--r-- | pidgin/plugins/gestures/stroke-draw.c | 308 | ||||
-rw-r--r-- | pidgin/plugins/gestures/stroke.c | 8 | ||||
-rw-r--r-- | pidgin/plugins/meson.build | 5 |
8 files changed, 163 insertions, 212 deletions
diff --git a/meson.build b/meson.build index 781467cd3d..534fdd5b2d 100644 --- a/meson.build +++ b/meson.build @@ -331,11 +331,6 @@ else endif conf.set('HAVE_X11', x11.found()) -enable_gestures = get_option('gestures') -if not get_option('gtkui') or not x11.found() - enable_gestures = false -endif - ####################################################################### # Check for LibXML2 (required) ####################################################################### @@ -793,7 +788,6 @@ message('Build GTK+ UI................. : ' + get_option('gtkui').to_string()) message('Build console UI.............. : ' + enable_consoleui.to_string()) message('Build for X11................. : ' + x11.found().to_string()) message('') -message('Enable Gestures............... : ' + enable_gestures.to_string()) message('Protocols to build dynamically : @0@'.format(DYNAMIC_PRPLS)) message('') message('Build with GStreamer support.. : ' + gstreamer.found().to_string()) diff --git a/meson_options.txt b/meson_options.txt index 5ecc1c6970..59b49d6e94 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -79,9 +79,6 @@ option('zephyr', type : 'feature', option('console-logging', type : 'boolean', value : false, description : 'compile with console logging support') -option('gestures', type : 'boolean', value : true, - description : 'compile with the gestures plugin') - option('gevolution', type : 'feature', value : 'disabled', description : 'compile with the Evolution plugin') diff --git a/pidgin/plugins/gestures/gestures.c b/pidgin/plugins/gestures/gestures.c index b6f896b324..432f5adf98 100644 --- a/pidgin/plugins/gestures/gestures.c +++ b/pidgin/plugins/gestures/gestures.c @@ -18,13 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02111-1301, USA. */ -#include "internal.h" -#include "pidgin.h" + +#include <glib/gi18n-lib.h> #include <purple.h> #include "gtkconv.h" -#include "gtkplugin.h" #include "gtkutils.h" #include "gstroke.h" @@ -45,7 +44,7 @@ stroke_close(GtkWidget *widget, void *data) gtkconv = PIDGIN_CONVERSATION(conv); - gstroke_cleanup(gtkconv->webview); + gstroke_cleanup(gtkconv->history); g_object_unref(conv); } @@ -123,15 +122,15 @@ attach_signals(PurpleConversation *conv) gtkconv = PIDGIN_CONVERSATION(conv); - gstroke_enable(gtkconv->webview); - gstroke_signal_connect(gtkconv->webview, "14789", stroke_close, conv); - gstroke_signal_connect(gtkconv->webview, "1456", stroke_close, conv); - gstroke_signal_connect(gtkconv->webview, "1489", stroke_close, conv); - gstroke_signal_connect(gtkconv->webview, "74123", stroke_next_tab, conv); - gstroke_signal_connect(gtkconv->webview, "7456", stroke_next_tab, conv); - gstroke_signal_connect(gtkconv->webview, "96321", stroke_prev_tab, conv); - gstroke_signal_connect(gtkconv->webview, "9654", stroke_prev_tab, conv); - gstroke_signal_connect(gtkconv->webview, "25852", stroke_new_win, conv); + gstroke_enable(gtkconv->history); + gstroke_signal_connect(gtkconv->history, "14789", stroke_close, conv); + gstroke_signal_connect(gtkconv->history, "1456", stroke_close, conv); + gstroke_signal_connect(gtkconv->history, "1489", stroke_close, conv); + gstroke_signal_connect(gtkconv->history, "74123", stroke_next_tab, conv); + gstroke_signal_connect(gtkconv->history, "7456", stroke_next_tab, conv); + gstroke_signal_connect(gtkconv->history, "96321", stroke_prev_tab, conv); + gstroke_signal_connect(gtkconv->history, "9654", stroke_prev_tab, conv); + gstroke_signal_connect(gtkconv->history, "25852", stroke_new_win, conv); } static void @@ -209,7 +208,7 @@ get_config_frame(PurplePlugin *plugin) return ret; } -static PidginPluginInfo * +static GPluginPluginInfo * plugin_query(GError **error) { const gchar * const authors[] = { @@ -217,7 +216,7 @@ plugin_query(GError **error) NULL }; - return pidgin_plugin_info_new( + return gplugin_plugin_info_new( "id", GESTURES_PLUGIN_ID, "name", N_("Mouse Gestures"), "version", DISPLAY_VERSION, @@ -288,8 +287,8 @@ plugin_unload(PurplePlugin *plugin, GError **error) gtkconv = PIDGIN_CONVERSATION(conv); - gstroke_cleanup(gtkconv->webview); - gstroke_disable(gtkconv->webview); + gstroke_cleanup(gtkconv->history); + gstroke_disable(gtkconv->history); } return TRUE; diff --git a/pidgin/plugins/gestures/gstroke.h b/pidgin/plugins/gestures/gstroke.h index 76a45ea9f8..146baf1731 100644 --- a/pidgin/plugins/gestures/gstroke.h +++ b/pidgin/plugins/gestures/gstroke.h @@ -36,10 +36,9 @@ void gstroke_enable (GtkWidget *widget); /* disable strokes for the widget */ void gstroke_disable(GtkWidget *widget); -guint gstroke_signal_connect (GtkWidget *widget, - const gchar *name, - void (*func)(GtkWidget *widget, void *data), - gpointer data); +void gstroke_signal_connect(GtkWidget *widget, const gchar *name, + void (*func)(GtkWidget *widget, void *data), + gpointer data); /* frees all the memory allocated for stroke, should be called when the widget is destroyed*/ diff --git a/pidgin/plugins/gestures/meson.build b/pidgin/plugins/gestures/meson.build index 3eea24162e..9b43a58c4f 100644 --- a/pidgin/plugins/gestures/meson.build +++ b/pidgin/plugins/gestures/meson.build @@ -8,8 +8,7 @@ gestures_SOURCES = [ if PLUGINS gestures = library('gestures', gestures_SOURCES, - build_by_default: false, - dependencies : [x11, libpurple_dep, libpidgin_dep, glib], + dependencies : [libpurple_dep, libpidgin_dep, glib], name_prefix : '', - install : false, install_dir : PIDGIN_PLUGINDIR) + install : true, install_dir : PIDGIN_PLUGINDIR) endif diff --git a/pidgin/plugins/gestures/stroke-draw.c b/pidgin/plugins/gestures/stroke-draw.c index 6ef136fe23..c098a11d58 100644 --- a/pidgin/plugins/gestures/stroke-draw.c +++ b/pidgin/plugins/gestures/stroke-draw.c @@ -11,19 +11,14 @@ #include <stdio.h> #include <glib.h> #include <gtk/gtk.h> -#include <gdk/gdkx.h> +#include <gdk/gdk.h> #include "gstroke.h" #include "gstroke-internal.h" -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -static void gstroke_invisible_window_init (GtkWidget *widget); +static gboolean gstroke_draw_cb(GtkWidget *widget, cairo_t *cr, + gpointer user_data); /*FIXME: Maybe these should be put in a structure, and not static...*/ -static Display * gstroke_disp = NULL; -static Window gstroke_window; -static GC gstroke_gc; static int mouse_button = 2; static gboolean draw_strokes = FALSE; @@ -65,24 +60,7 @@ record_stroke_segment(GtkWidget *widget) gdk_window_get_device_position(gtk_widget_get_window(widget), dev, &x, &y, NULL); - if (last_mouse_position.invalid) - last_mouse_position.invalid = FALSE; - else if (gstroke_draw_strokes()) { -#if 1 - XDrawLine(gstroke_disp, gstroke_window, gstroke_gc, - last_mouse_position.last_point.x, - last_mouse_position.last_point.y, x, y); - /* XFlush (gstroke_disp); */ -#else - /* FIXME: this does not work. It will only work if we create - * a corresponding GDK window for stroke_window and draw on - * that... */ - gdk_draw_line(gtk_widget_get_window(widget), - widget->style->fg_gc[GTK_STATE_NORMAL], - last_mouse_position.last_point.x, - last_mouse_position.last_point.y, x, y); -#endif - } + last_mouse_position.invalid = FALSE; if (last_mouse_position.last_point.x != x || last_mouse_position.last_point.y != y) @@ -92,6 +70,10 @@ record_stroke_segment(GtkWidget *widget) metrics = g_object_get_data(G_OBJECT(widget), GSTROKE_METRICS); _gstroke_record (x, y, metrics); } + + if (gstroke_draw_strokes()) { + gtk_widget_queue_draw(widget); + } } static gint @@ -107,7 +89,8 @@ gstroke_timeout (gpointer data) return TRUE; } -static void gstroke_cancel(GdkEvent *event) +static void +gstroke_cancel(GtkWidget *widget, GdkEvent *event) { last_mouse_position.invalid = TRUE; @@ -120,16 +103,13 @@ static void gstroke_cancel(GdkEvent *event) gdk_seat_ungrab(gdk_event_get_seat(event)); } - if (gstroke_draw_strokes() && gstroke_disp != NULL) { - /* get rid of the invisible stroke window */ - XUnmapWindow (gstroke_disp, gstroke_window); - XFlush (gstroke_disp); + if (gstroke_draw_strokes()) { + gtk_widget_queue_draw(widget); } - } static gint -process_event (GtkWidget *widget, GdkEvent *event, gpointer data G_GNUC_UNUSED) +process_event(GtkWidget *widget, GdkEvent *event, gpointer data) { static GtkWidget *original_widget = NULL; static GdkCursor *cursor = NULL; @@ -141,7 +121,7 @@ process_event (GtkWidget *widget, GdkEvent *event, gpointer data G_GNUC_UNUSED) * clicked after the middle button is clicked (but possibly * not released) */ - gstroke_cancel(event); + gstroke_cancel(widget, event); original_widget = NULL; break; } @@ -149,8 +129,6 @@ process_event (GtkWidget *widget, GdkEvent *event, gpointer data G_GNUC_UNUSED) original_widget = widget; /* remeber the widget where the stroke started */ - gstroke_invisible_window_init (widget); - record_stroke_segment (widget); if (cursor == NULL) { @@ -171,7 +149,7 @@ process_event (GtkWidget *widget, GdkEvent *event, gpointer data G_GNUC_UNUSED) /* Nice bug when you hold down one button and press another. */ /* We'll just cancel the gesture instead. */ - gstroke_cancel(event); + gstroke_cancel(widget, event); original_widget = NULL; break; } @@ -182,21 +160,20 @@ process_event (GtkWidget *widget, GdkEvent *event, gpointer data G_GNUC_UNUSED) gdk_seat_ungrab(gdk_event_get_seat(event)); timer_id = 0; - { + { + GtkWidget *history = data; char result[GSTROKE_MAX_SEQUENCE]; struct gstroke_metrics *metrics; metrics = (struct gstroke_metrics *)g_object_get_data(G_OBJECT (widget), GSTROKE_METRICS); if (gstroke_draw_strokes()) { - /* get rid of the invisible stroke window */ - XUnmapWindow (gstroke_disp, gstroke_window); - XFlush (gstroke_disp); + gtk_widget_queue_draw(widget); } - _gstroke_canonical (result, metrics); - gstroke_execute (widget, result); - } + _gstroke_canonical(result, metrics); + gstroke_execute(history, result); + } return FALSE; default: @@ -233,58 +210,85 @@ gstroke_get_mouse_button(void) void gstroke_enable (GtkWidget *widget) { - struct gstroke_metrics* - metrics = (struct gstroke_metrics *)g_object_get_data(G_OBJECT(widget), - GSTROKE_METRICS); - if (metrics == NULL) - { - metrics = (struct gstroke_metrics *)g_malloc (sizeof - (struct gstroke_metrics)); - metrics->pointList = NULL; - metrics->min_x = 10000; - metrics->min_y = 10000; - metrics->max_x = 0; - metrics->max_y = 0; - metrics->point_count = 0; - - g_object_set_data(G_OBJECT(widget), GSTROKE_METRICS, metrics); - - g_signal_connect(G_OBJECT(widget), "event", - G_CALLBACK(process_event), NULL); - } - else - _gstroke_init (metrics); + GtkWidget *event = gtk_widget_get_parent(widget); + struct gstroke_metrics *metrics = NULL; - last_mouse_position.invalid = TRUE; + if (GTK_IS_EVENT_BOX(event)) { + metrics = (struct gstroke_metrics *)g_object_get_data(G_OBJECT(event), + GSTROKE_METRICS); + } + + if (metrics == NULL) { + GtkWidget *parent; + + metrics = g_new0(struct gstroke_metrics, 1); + metrics->pointList = NULL; + metrics->min_x = 10000; + metrics->min_y = 10000; + metrics->max_x = 0; + metrics->max_y = 0; + metrics->point_count = 0; + + event = gtk_event_box_new(); + gtk_event_box_set_above_child(GTK_EVENT_BOX(event), TRUE); + gtk_widget_set_events(event, GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_BUTTON2_MOTION_MASK); + gtk_widget_set_app_paintable(event, TRUE); + gtk_widget_show(event); + + parent = gtk_widget_get_parent(widget); + g_object_ref(widget); + gtk_container_remove(GTK_CONTAINER(parent), widget); + gtk_container_add(GTK_CONTAINER(event), widget); + g_object_unref(widget); + gtk_container_add(GTK_CONTAINER(parent), event); + + g_object_set_data(G_OBJECT(event), GSTROKE_METRICS, metrics); + + g_signal_connect(G_OBJECT(event), "event", G_CALLBACK(process_event), + widget); + g_signal_connect_after(G_OBJECT(event), "draw", + G_CALLBACK(gstroke_draw_cb), NULL); + } else { + _gstroke_init(metrics); + } + + last_mouse_position.invalid = TRUE; } void gstroke_disable(GtkWidget *widget) { - g_signal_handlers_disconnect_by_func(G_OBJECT(widget), G_CALLBACK(process_event), NULL); + GtkWidget *event = gtk_widget_get_parent(widget); + + g_return_if_fail(GTK_IS_EVENT_BOX(event)); + + g_signal_handlers_disconnect_by_func(G_OBJECT(event), + G_CALLBACK(process_event), widget); + g_signal_handlers_disconnect_by_func(G_OBJECT(event), + G_CALLBACK(gstroke_draw_cb), NULL); } -guint -gstroke_signal_connect (GtkWidget *widget, - const gchar *name, - void (*func)(GtkWidget *widget, void *data), - gpointer data) +void +gstroke_signal_connect(GtkWidget *widget, const gchar *name, + void (*func)(GtkWidget *widget, void *data), + gpointer data) { - struct gstroke_func_and_data *func_and_data; - GHashTable *hash_table = - (GHashTable*)g_object_get_data(G_OBJECT(widget), GSTROKE_SIGNALS); + struct gstroke_func_and_data *func_and_data; + GHashTable *hash_table = + (GHashTable *)g_object_get_data(G_OBJECT(widget), GSTROKE_SIGNALS); + + if (!hash_table) { + hash_table = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + g_object_set_data(G_OBJECT(widget), GSTROKE_SIGNALS, hash_table); + } - if (!hash_table) - { - hash_table = g_hash_table_new (g_str_hash, g_str_equal); - g_object_set_data(G_OBJECT(widget), GSTROKE_SIGNALS, - (gpointer)hash_table); - } - func_and_data = g_new (struct gstroke_func_and_data, 1); - func_and_data->func = func; - func_and_data->data = data; - g_hash_table_insert (hash_table, (gpointer)name, (gpointer)func_and_data); - return TRUE; + func_and_data = g_new0(struct gstroke_func_and_data, 1); + func_and_data->func = func; + func_and_data->data = data; + g_hash_table_insert(hash_table, g_strdup(name), func_and_data); } static void @@ -310,100 +314,62 @@ gstroke_execute (GtkWidget *widget, const gchar *name) void gstroke_cleanup (GtkWidget *widget) { - struct gstroke_metrics *metrics; - GHashTable *hash_table = - (GHashTable*)g_object_get_data(G_OBJECT(widget), GSTROKE_SIGNALS); - if (hash_table) - /* FIXME: does this delete the elements too? */ - g_hash_table_destroy (hash_table); - - g_object_steal_data(G_OBJECT(widget), GSTROKE_SIGNALS); + struct gstroke_metrics *metrics; + GHashTable *hash_table = (GHashTable *)g_object_steal_data(G_OBJECT(widget), + GSTROKE_SIGNALS); + if (hash_table) { + g_hash_table_destroy(hash_table); + } - metrics = (struct gstroke_metrics*)g_object_get_data(G_OBJECT(widget), - GSTROKE_METRICS); - g_free(metrics); - g_object_steal_data(G_OBJECT(widget), GSTROKE_METRICS); + metrics = (struct gstroke_metrics *)g_object_steal_data(G_OBJECT(widget), + GSTROKE_METRICS); + g_free(metrics); } - -/* This function should be written using GTK+ primitives*/ -static void -gstroke_invisible_window_init (GtkWidget *widget) +static gboolean +gstroke_draw_cb(GtkWidget *widget, cairo_t *cr, + G_GNUC_UNUSED gpointer user_data) { - XSetWindowAttributes w_attr; - XWindowAttributes orig_w_attr; - unsigned long mask, col_border, col_background; - unsigned int border_width; - XSizeHints hints; - Display *disp = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(widget)); - Window wind = gdk_x11_window_get_xid(gtk_widget_get_window(widget)); - int screen = DefaultScreen (disp); - - if (!gstroke_draw_strokes()) - return; - - gstroke_disp = disp; - - /* X server should save what's underneath */ - XGetWindowAttributes (gstroke_disp, wind, &orig_w_attr); - hints.x = orig_w_attr.x; - hints.y = orig_w_attr.y; - hints.width = orig_w_attr.width; - hints.height = orig_w_attr.height; - mask = CWSaveUnder; - w_attr.save_under = True; - - /* inhibit all the decorations */ - mask |= CWOverrideRedirect; - w_attr.override_redirect = True; - - /* Don't set a background, transparent window */ - mask |= CWBackPixmap; - w_attr.background_pixmap = None; - - /* Default input window look */ - col_background = WhitePixel (gstroke_disp, screen); - - /* no border for the window */ -#if 0 - border_width = 5; -#endif - border_width = 0; + struct gstroke_metrics *metrics = + (struct gstroke_metrics *)g_object_get_data(G_OBJECT(widget), + GSTROKE_METRICS); + GSList *iter = NULL; + p_point point; + + if (last_mouse_position.invalid) { + return FALSE; + } - col_border = BlackPixel (gstroke_disp, screen); + if (!metrics) { + return FALSE; + } - gstroke_window = XCreateSimpleWindow (gstroke_disp, wind, - 0, 0, - hints.width - 2 * border_width, - hints.height - 2 * border_width, - border_width, - col_border, col_background); + iter = metrics->pointList; + if (!iter) { + return FALSE; + } - gstroke_gc = XCreateGC (gstroke_disp, gstroke_window, 0, NULL); + cairo_save(cr); - XSetFunction (gstroke_disp, gstroke_gc, GXinvert); + cairo_set_line_width(cr, 2.0); + cairo_set_dash(cr, NULL, 0, 0.0); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); + cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); - XChangeWindowAttributes (gstroke_disp, gstroke_window, mask, &w_attr); + point = (p_point)iter->data; + iter = iter->next; + cairo_move_to(cr, point->x, point->y); - XSetLineAttributes (gstroke_disp, gstroke_gc, 2, LineSolid, - CapButt, JoinMiter); - XMapRaised (gstroke_disp, gstroke_window); + while (iter) { + point = (p_point)iter->data; + iter = iter->next; -#if 0 - /*FIXME: is this call really needed? If yes, does it need the real - argc and argv? */ - hints.flags = PPosition | PSize; - XSetStandardProperties (gstroke_disp, gstroke_window, "gstroke_test", NULL, - (Pixmap)NULL, NULL, 0, &hints); - - - /* Receive the close window client message */ - { - /* FIXME: is this really needed? If yes, something should be done - with wmdelete...*/ - Atom wmdelete = XInternAtom (gstroke_disp, "WM_DELETE_WINDOW", - False); - XSetWMProtocols (gstroke_disp, gstroke_window, &wmdelete, True); - } -#endif + cairo_line_to(cr, point->x, point->y); + } + + cairo_stroke(cr); + + cairo_restore(cr); + + return FALSE; } diff --git a/pidgin/plugins/gestures/stroke.c b/pidgin/plugins/gestures/stroke.c index 642bb20c1e..13bd414cf4 100644 --- a/pidgin/plugins/gestures/stroke.c +++ b/pidgin/plugins/gestures/stroke.c @@ -147,11 +147,11 @@ _gstroke_trans (gchar *sequence, struct gstroke_metrics *metrics) prev_bin = current_bin; } - /* move to next point, freeing current point from list */ - - free (crt_elem->data); - crt_elem = g_slist_next (crt_elem); + /* move to next point, freeing current point from list */ + g_free(crt_elem->data); + crt_elem = g_slist_next(crt_elem); } + metrics->pointList = NULL; /* add the last run of points to the sequence */ sequence[sequence_count++] = '0' + current_bin; /* printf ("DEBUG:: adding final sequence: %d\n", current_bin); */ diff --git a/pidgin/plugins/meson.build b/pidgin/plugins/meson.build index cda73b47f3..5c18fdd1d2 100644 --- a/pidgin/plugins/meson.build +++ b/pidgin/plugins/meson.build @@ -4,11 +4,8 @@ if false subdir('musicmessaging') endif -if enable_gestures - subdir('gestures') -endif - subdir('disco') +subdir('gestures') subdir('ticker') subdir('xmppconsole') |