Skip to content

Commit

Permalink
Addons: Implement unselect with single click
Browse files Browse the repository at this point in the history
For this to work, we need to connect to the "button-press-event" for
each document and then differentiate between single and double
clicks, using a timeout handler which is triggered first after the GTK
double-click-time has passed, i.e. GTK won't recognise the event as part
of a double click.
Closes #445.
  • Loading branch information
eht16 committed Aug 28, 2016
1 parent 787c417 commit d18495a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 8 deletions.
3 changes: 2 additions & 1 deletion addons/src/addons.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ gboolean ao_editor_notify_cb(GObject *object, GeanyEditor *editor,
SCNotification *nt, gpointer data) SCNotification *nt, gpointer data)
{ {
ao_bookmark_list_update_marker(ao_info->bookmarklist, editor, nt); ao_bookmark_list_update_marker(ao_info->bookmarklist, editor, nt);
ao_mark_word_check(ao_info->markword, editor, nt);


return FALSE; return FALSE;
} }
Expand Down Expand Up @@ -204,6 +203,7 @@ static void ao_document_open_cb(GObject *obj, GeanyDocument *doc, gpointer data)
g_return_if_fail(doc != NULL && doc->is_valid); g_return_if_fail(doc != NULL && doc->is_valid);


ao_tasks_update(ao_info->tasks, doc); ao_tasks_update(ao_info->tasks, doc);
ao_mark_document_open(ao_info->markword, doc);
} }




Expand All @@ -212,6 +212,7 @@ static void ao_document_close_cb(GObject *obj, GeanyDocument *doc, gpointer data
g_return_if_fail(doc != NULL && doc->is_valid); g_return_if_fail(doc != NULL && doc->is_valid);


ao_tasks_remove(ao_info->tasks, doc); ao_tasks_remove(ao_info->tasks, doc);
ao_mark_document_close(ao_info->markword, doc);
} }




Expand Down
78 changes: 73 additions & 5 deletions addons/src/ao_markword.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct _AoMarkWordClass
struct _AoMarkWordPrivate struct _AoMarkWordPrivate
{ {
gboolean enable_markword; gboolean enable_markword;

gint double_click_time;
guint double_click_timer_id;
}; };


enum enum
Expand Down Expand Up @@ -108,24 +111,89 @@ static void ao_mark_word_finalize(GObject *object)
} }




void ao_mark_word_check(AoMarkWord *bm, GeanyEditor *editor, SCNotification *nt) static gboolean clear_marker(gpointer bm)
{ {
AoMarkWordPrivate *priv = AO_MARKWORD_GET_PRIVATE(bm); AoMarkWordPrivate *priv = AO_MARKWORD_GET_PRIVATE(bm);
/* There might be a small risk that the current document is not the one we want but for
* this the user has to manage to change the documents in "gtk-double-click-time". */
GeanyDocument *document = document_get_current();
/* clear current search indicators */
if (DOC_VALID(document))
editor_indicator_clear(document->editor, GEANY_INDICATOR_SEARCH);
/* unset and remove myself */
priv->double_click_timer_id = 0;
return FALSE;
}


if (priv->enable_markword)
static gboolean on_editor_button_press_event(GtkWidget *widget, GdkEventButton *event,
AoMarkWord *bm)
{
if (event->button == 1)
{ {
switch (nt->nmhdr.code) AoMarkWordPrivate *priv = AO_MARKWORD_GET_PRIVATE(bm);
/* Remove markers on single click, But do this asynchronously with a delay of the
* default double click time (GTK setting) to not act on double clicks as well.
* Simply checking for GDK_BUTTON_PRESS is not enough because it is also fired for
* double clicks (GDK_2BUTTON_PRESS) and so we need to differentiate between those.
*/
if (event->type == GDK_BUTTON_PRESS)
{ {
case SCN_DOUBLECLICK: if (priv->double_click_timer_id == 0)
{
/* Add a little buffer of 25ms in case the timer will be delayed a bit */
guint double_click_time = priv->double_click_time + 25;
priv->double_click_timer_id = g_timeout_add(double_click_time, clear_marker, bm);
}
}
else if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
{
/* remove previously set timeout handler */
if (priv->double_click_timer_id > 0)
{
g_source_remove(priv->double_click_timer_id);
priv->double_click_timer_id = 0;
}
/* mark (only on double click) */
if (event->type == GDK_2BUTTON_PRESS)
{
keybindings_send_command(GEANY_KEY_GROUP_SEARCH, GEANY_KEYS_SEARCH_MARKALL); keybindings_send_command(GEANY_KEY_GROUP_SEARCH, GEANY_KEYS_SEARCH_MARKALL);
break; }
} }
} }
return FALSE;
}


void ao_mark_document_open(AoMarkWord *mw, GeanyDocument *document)
{
g_return_if_fail(DOC_VALID(document));

plugin_signal_connect(
geany_plugin,
G_OBJECT(document->editor->sci),
"button-press-event",
FALSE,
G_CALLBACK(on_editor_button_press_event),
mw);
}


void ao_mark_document_close(AoMarkWord *mw, GeanyDocument *document)
{
g_return_if_fail(DOC_VALID(document));

g_signal_handlers_disconnect_by_func(document->editor->sci, on_editor_button_press_event, mw);
} }




static void ao_mark_word_init(AoMarkWord *self) static void ao_mark_word_init(AoMarkWord *self)
{ {
AoMarkWordPrivate *priv = AO_MARKWORD_GET_PRIVATE(self);
GtkSettings *settings = gtk_widget_get_settings(geany_data->main_widgets->window);

priv->double_click_timer_id = 0;
g_object_get(settings, "gtk-double-click-time", &priv->double_click_time, NULL);
} }




Expand Down
4 changes: 2 additions & 2 deletions addons/src/ao_markword.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ typedef struct _AoMarkWordClass AoMarkWordClass;


GType ao_mark_word_get_type (void); GType ao_mark_word_get_type (void);
AoMarkWord* ao_mark_word_new (gboolean enable); AoMarkWord* ao_mark_word_new (gboolean enable);
void ao_mark_word_check (AoMarkWord *bm, GeanyEditor *editor, void ao_mark_document_open (AoMarkWord *mw, GeanyDocument *document);
SCNotification *nt); void ao_mark_document_close (AoMarkWord *mw, GeanyDocument *document);


G_END_DECLS G_END_DECLS


Expand Down

0 comments on commit d18495a

Please sign in to comment.