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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user