[gtksourceview/wip/chergert/vim: 334/363] try to keep cursor over a char when not processing
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/vim: 334/363] try to keep cursor over a char when not processing
- Date: Mon, 8 Nov 2021 19:53:55 +0000 (UTC)
commit 0e05adedd78b51ee0f08b53c5923794b59dc1814
Author: Christian Hergert <chergert redhat com>
Date: Sat Nov 6 11:41:11 2021 -0700
try to keep cursor over a char when not processing
gtksourceview/vim/gtk-source-vim.c | 128 ++++++++++++++++++++++++++++++++++---
1 file changed, 119 insertions(+), 9 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim.c b/gtksourceview/vim/gtk-source-vim.c
index 0e794834..2b90a91c 100644
--- a/gtksourceview/vim/gtk-source-vim.c
+++ b/gtksourceview/vim/gtk-source-vim.c
@@ -21,17 +21,23 @@
#include "config.h"
+#include "gtksourcebuffer.h"
#include "gtksourceview.h"
#include "gtk-source-vim.h"
#include "gtk-source-vim-command.h"
#include "gtk-source-vim-command-bar.h"
+#include "gtk-source-vim-insert.h"
#include "gtk-source-vim-normal.h"
+#include "gtk-source-vim-replace.h"
struct _GtkSourceVim
{
- GtkSourceVimState parent_instance;
- GString *command_text;
+ GtkSourceVimState parent_instance;
+ GString *command_text;
+ GtkSourceBuffer *buffer;
+ guint constrain_insert_source;
+ guint in_handle_event : 1;
};
G_DEFINE_TYPE (GtkSourceVim, gtk_source_vim, GTK_SOURCE_TYPE_VIM_STATE)
@@ -93,23 +99,25 @@ gtk_source_vim_handle_event (GtkSourceVimState *state,
{
GtkSourceVim *self = (GtkSourceVim *)state;
GtkSourceVimState *current;
- gboolean ret;
+ gboolean ret = FALSE;
g_assert (GTK_SOURCE_IS_VIM (self));
g_assert (event != NULL);
+ self->in_handle_event = TRUE;
+
+ g_clear_handle_id (&self->constrain_insert_source, g_source_remove);
+
/* Allow parent states to capture input before current state */
if (gtk_source_vim_state_capture (state, event))
{
- return TRUE;
+ ret = TRUE;
+ goto finish;
}
current = gtk_source_vim_state_get_current (state);
-
if (current == state)
- {
- return FALSE;
- }
+ goto finish;
ret = gtk_source_vim_state_handle_event (current, event);
@@ -118,15 +126,115 @@ gtk_source_vim_handle_event (GtkSourceVimState *state,
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COMMAND_TEXT]);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COMMAND_BAR_TEXT]);
+finish:
+ self->in_handle_event = FALSE;
+
return ret;
}
+static gboolean
+constrain_insert_source (gpointer data)
+{
+ GtkSourceVim *self = data;
+ GtkSourceVimState *current;
+ GtkSourceBuffer *buffer;
+ GtkTextIter iter, selection;
+
+ self->constrain_insert_source = 0;
+
+ buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), &iter, &selection);
+ current = gtk_source_vim_state_get_current (GTK_SOURCE_VIM_STATE (self));
+
+ if (!GTK_SOURCE_IS_VIM_INSERT (current) &&
+ !GTK_SOURCE_IS_VIM_REPLACE (current) &&
+ !gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (buffer)))
+ {
+ if (gtk_text_iter_ends_line (&iter) &&
+ !gtk_text_iter_starts_line (&iter))
+ {
+ gtk_text_iter_backward_char (&iter);
+ gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &iter, &iter);
+ }
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+on_cursor_moved_cb (GtkSourceVim *self,
+ GtkSourceBuffer *buffer)
+{
+ g_assert (GTK_SOURCE_IS_VIM (self));
+ g_assert (GTK_SOURCE_IS_BUFFER (buffer));
+
+ if (self->in_handle_event)
+ return;
+
+ /* Make sure we are placed on a character instead of on a \n
+ * which is possible when the user clicks with a button or other
+ * external tools. Don't do it until an idle callback though so
+ * that we don't affect anything currently processing.
+ */
+ if (self->constrain_insert_source == 0)
+ {
+ self->constrain_insert_source = g_idle_add (constrain_insert_source, self);
+ }
+}
+
+static void
+on_notify_buffer_cb (GtkSourceVim *self,
+ GParamSpec *pspec,
+ GtkSourceView *view)
+{
+ GtkSourceBuffer *buffer;
+
+ g_assert (GTK_SOURCE_IS_VIM (self));
+ g_assert (GTK_SOURCE_IS_VIEW (view));
+
+ buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+
+ if (self->buffer == buffer)
+ return;
+
+ if (self->buffer != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (self->buffer,
+ G_CALLBACK (on_cursor_moved_cb),
+ self);
+ g_clear_object (&self->buffer);
+ }
+
+ g_set_object (&self->buffer, buffer);
+
+ if (buffer != NULL)
+ {
+ g_signal_connect_object (buffer,
+ "cursor-moved",
+ G_CALLBACK (on_cursor_moved_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ on_cursor_moved_cb (self, buffer);
+ }
+}
+
static void
gtk_source_vim_view_set (GtkSourceVimState *state)
{
- g_assert (GTK_SOURCE_IS_VIM (state));
+ GtkSourceVim *self = (GtkSourceVim *)state;
+ GtkSourceView *view;
+
+ g_assert (GTK_SOURCE_IS_VIM (self));
g_assert (gtk_source_vim_state_get_child (state) == NULL);
+ view = gtk_source_vim_state_get_view (state);
+
+ g_signal_connect_object (view,
+ "notify::buffer",
+ G_CALLBACK (on_notify_buffer_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ on_notify_buffer_cb (self, NULL, view);
+
gtk_source_vim_state_push (state, gtk_source_vim_normal_new ());
}
@@ -135,6 +243,8 @@ gtk_source_vim_finalize (GObject *object)
{
GtkSourceVim *self = (GtkSourceVim *)object;
+ g_clear_handle_id (&self->constrain_insert_source, g_source_remove);
+ g_clear_object (&self->buffer);
g_string_free (self->command_text, TRUE);
self->command_text = 0;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]