initial implementation of keyboard selection
This commit is contained in:
parent
5fe6721f2f
commit
f8c8c748f0
|
@ -22,6 +22,7 @@ KEYBINDINGS
|
||||||
* ``ctrl-shift-n``: jump to next search match
|
* ``ctrl-shift-n``: jump to next search match
|
||||||
* ``ctrl-shift-p``: jump to previous search match
|
* ``ctrl-shift-p``: jump to previous search match
|
||||||
* ``ctrl-tab``: start scrollback completion
|
* ``ctrl-tab``: start scrollback completion
|
||||||
|
* ``ctrl-shift-space``: start selection mode
|
||||||
|
|
||||||
During scrollback search, the current selection is changed to the search match
|
During scrollback search, the current selection is changed to the search match
|
||||||
and copied to the PRIMARY clipboard buffer.
|
and copied to the PRIMARY clipboard buffer.
|
||||||
|
@ -29,6 +30,11 @@ and copied to the PRIMARY clipboard buffer.
|
||||||
With the scrollback search/completion widget open, up/down cycle through
|
With the scrollback search/completion widget open, up/down cycle through
|
||||||
completions, escape closes the widget and enter accepts the input.
|
completions, escape closes the widget and enter accepts the input.
|
||||||
|
|
||||||
|
TEXT SELECTION MODE
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* ``escape``: deactivate selection mode
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
56
termite.c
56
termite.c
|
@ -1,11 +1,13 @@
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <vte/vte.h>
|
#include <vte/vte.h>
|
||||||
|
#include <vte/vteaccess.h>
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
# define __attribute__(x)
|
# define __attribute__(x)
|
||||||
|
@ -20,11 +22,19 @@ typedef enum overlay_mode {
|
||||||
OVERLAY_COMPLETION
|
OVERLAY_COMPLETION
|
||||||
} overlay_mode;
|
} overlay_mode;
|
||||||
|
|
||||||
|
typedef struct select_info {
|
||||||
|
AtkText *text;
|
||||||
|
bool mode;
|
||||||
|
int begin;
|
||||||
|
int end;
|
||||||
|
} select_info;
|
||||||
|
|
||||||
typedef struct search_panel_info {
|
typedef struct search_panel_info {
|
||||||
GtkWidget *vte;
|
GtkWidget *vte;
|
||||||
GtkWidget *entry;
|
GtkWidget *entry;
|
||||||
GtkWidget *panel;
|
GtkWidget *panel;
|
||||||
enum overlay_mode mode;
|
enum overlay_mode mode;
|
||||||
|
select_info select;
|
||||||
} search_panel_info;
|
} search_panel_info;
|
||||||
|
|
||||||
static char *browser_cmd[3] = {NULL};
|
static char *browser_cmd[3] = {NULL};
|
||||||
|
@ -60,11 +70,54 @@ void window_title_cb(VteTerminal *vte, GtkWindow *window) {
|
||||||
gtk_window_set_title(window, t ? t : "termite");
|
gtk_window_set_title(window, t ? t : "termite");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_selection(VteTerminal *vte, select_info *select) {
|
||||||
|
int n_selections = atk_text_get_n_selections(select->text);
|
||||||
|
|
||||||
|
if (n_selections) {
|
||||||
|
if (n_selections == 1) {
|
||||||
|
atk_text_remove_selection(select->text, 0);
|
||||||
|
} else {
|
||||||
|
g_printerr("more than one selection!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
atk_text_add_selection(select->text,
|
||||||
|
MIN(select->begin, select->end),
|
||||||
|
MAX(select->begin, select->end));
|
||||||
|
|
||||||
|
vte_terminal_copy_primary(vte);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start_selection(select_info *select) {
|
||||||
|
select->mode = true;
|
||||||
|
select->begin = select->end = atk_text_get_caret_offset(select->text);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info) {
|
gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info) {
|
||||||
const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask();
|
const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask();
|
||||||
gboolean dynamic_title = FALSE, urgent_on_bell = FALSE, clickable_url = FALSE;
|
gboolean dynamic_title = FALSE, urgent_on_bell = FALSE, clickable_url = FALSE;
|
||||||
|
if (info->select.mode) {
|
||||||
|
switch (event->keyval) {
|
||||||
|
case GDK_KEY_h:
|
||||||
|
info->select.end--;
|
||||||
|
update_selection(vte, &info->select);
|
||||||
|
break;
|
||||||
|
case GDK_KEY_l:
|
||||||
|
info->select.end++;
|
||||||
|
update_selection(vte, &info->select);
|
||||||
|
break;
|
||||||
|
case GDK_KEY_Escape:
|
||||||
|
info->select.mode = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
if (modifiers == (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) {
|
if (modifiers == (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) {
|
||||||
switch (gdk_keyval_to_lower(event->keyval)) {
|
switch (gdk_keyval_to_lower(event->keyval)) {
|
||||||
|
case GDK_KEY_space:
|
||||||
|
start_selection(&info->select);
|
||||||
|
return TRUE;
|
||||||
case GDK_KEY_c:
|
case GDK_KEY_c:
|
||||||
vte_terminal_copy_clipboard(vte);
|
vte_terminal_copy_clipboard(vte);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -559,7 +612,8 @@ int main(int argc, char **argv) {
|
||||||
gtk_container_add(GTK_CONTAINER(overlay), vte);
|
gtk_container_add(GTK_CONTAINER(overlay), vte);
|
||||||
gtk_container_add(GTK_CONTAINER(window), overlay);
|
gtk_container_add(GTK_CONTAINER(window), overlay);
|
||||||
|
|
||||||
search_panel_info info = {vte, entry, alignment, OVERLAY_HIDDEN};
|
select_info select = {ATK_TEXT(vte_terminal_accessible_new(VTE_TERMINAL(vte))), false, 0, 0};
|
||||||
|
search_panel_info info = {vte, entry, alignment, OVERLAY_HIDDEN, select};
|
||||||
|
|
||||||
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
||||||
g_signal_connect(vte, "child-exited", G_CALLBACK(gtk_main_quit), NULL);
|
g_signal_connect(vte, "child-exited", G_CALLBACK(gtk_main_quit), NULL);
|
||||||
|
|
Loading…
Reference in New Issue