Merge #6432 from justinmk/guicursor

This commit is contained in:
Justin M. Keyes 2017-04-04 15:26:32 +02:00 committed by GitHub
commit 4566f7c7cd
16 changed files with 82 additions and 118 deletions

View File

@ -83,28 +83,6 @@ Recommended place for your personal GUI initializations:
The personal initialization files are searched in the order specified above
and only the first one that is found is read.
There are a number of options which only have meaning in the GUI version of
Vim. These are 'guicursor', 'guifont', and 'guioptions'. They are
documented in |options.txt| with all the other options.
Another way to set the colors for different occasions is with highlight
groups. The "Normal" group is used to set the background and foreground
colors. Example (which looks nice): >
:highlight Normal guibg=grey90
The "guibg" and "guifg" settings override the normal background and
foreground settings. The other settings for the Normal highlight group are
not used. Use the 'guifont' option to set the font.
Also check out the 'guicursor' option, to set the colors for the cursor in
various modes.
Vim tries to make the window fit on the screen when it starts up. This avoids
that you can't see part of it. On the X Window System this requires a bit of
guesswork. You can change the height that is used for the window title and a
task bar with the 'guiheadroom' option.
*:winp* *:winpos* *E188*
:winp[os]
Display current position of the top left corner of the GUI vim
@ -124,21 +102,6 @@ task bar with the 'guiheadroom' option.
:win[size] {width} {height}
Set the window height to {width} by {height} characters.
Obsolete, use ":set lines=11 columns=22".
If you get less lines than expected, check the 'guiheadroom'
option.
If you are running the X Window System, you can get information about the
window Vim is running in with these commands: >
:!xwininfo -id $WINDOWID
:!xprop -id $WINDOWID
:execute '!xwininfo -id ' . v:windowid
:execute '!xprop -id ' . v:windowid
<
*gui-IME* *iBus*
Input methods for international characters in X that rely on the XIM
framework, most notably iBus, have been known to produce undesirable results
in gVim. These may include an inability to enter spaces, or long delays
between typing a character and it being recognized by the application.
==============================================================================
2. Scrollbars *gui-scrollbars*

View File

@ -2796,7 +2796,7 @@ A jump table for the options with a short description can be found at |Q_op|.
-blinkwait175-blinkoff150-blinkon175")
global
Configures the cursor style for each mode. Works in the GUI and some
terminals. Empty means "non-blinking block cursor in all modes": >
terminals. Unset to disable: >
:set guicursor=
<
With tmux you might need this in ~/.tmux.conf (see terminal-overrides
@ -2976,18 +2976,6 @@ A jump table for the options with a short description can be found at |Q_op|.
If set and valid, 'guifontwide' is used for IME instead of 'guifont'.
*'guiheadroom'* *'ghr'*
'guiheadroom' 'ghr' number (default 50)
global
{only for X11 GUI}
The number of pixels subtracted from the screen height when fitting
the GUI window on the screen. Set this before the GUI is started,
e.g., in your |gvimrc| file. When zero, the whole screen height will
be used by the window. When positive, the specified number of pixel
lines will be left for window decorations and other items on the
screen. Set it to a negative value to allow windows taller than the
screen.
*'guioptions'* *'go'*
'guioptions' 'go' string (default "egmrLT" (MS-Windows))
global
@ -3812,9 +3800,6 @@ A jump table for the options with a short description can be found at |Q_op|.
use this command to get the tallest window possible: >
:set lines=999
< Minimum value is 2, maximum value is 1000.
If you get less lines than expected, check the 'guiheadroom' option.
When you set this option and Vim is unable to change the physical
number of lines of the display, the display may be messed up.
*'linespace'* *'lsp'*
'linespace' 'lsp' number (default 0, 1 for Win32 GUI)

View File

@ -715,7 +715,6 @@ Short explanation of each option: *option-list*
'guifont' 'gfn' GUI: Name(s) of font(s) to be used
'guifontset' 'gfs' GUI: Names of multi-byte fonts to be used
'guifontwide' 'gfw' list of font names for double-wide characters
'guiheadroom' 'ghr' GUI: pixels room for window decorations
'guioptions' 'go' GUI: Which components and options are used
'guitablabel' 'gtl' GUI: custom label for a tab page
'guitabtooltip' 'gtt' GUI: custom tooltip for a tab page

View File

@ -589,8 +589,6 @@ if has("gui")
call append("$", "toolbariconsize\tsize of toolbar icons")
call <SID>OptionG("tbis", &tbis)
endif
call append("$", "guiheadroom\troom (in pixels) left above/below the window")
call append("$", " \tset ghr=" . &ghr)
endif
if has("browse")
call append("$", "browsedir\t\"last\", \"buffer\" or \"current\": which directory used for the file browser")

View File

@ -300,11 +300,11 @@ static void remote_ui_scroll(UI *ui, int count)
push_call(ui, "scroll", args);
}
static void remote_ui_cursor_style_set(UI *ui, Dictionary styles)
static void remote_ui_cursor_style_set(UI *ui, bool enabled, Dictionary data)
{
Array args = ARRAY_DICT_INIT;
Object copy = copy_object(DICTIONARY_OBJ(styles));
ADD(args, copy);
ADD(args, BOOLEAN_OBJ(enabled));
ADD(args, copy_object(DICTIONARY_OBJ(data)));
push_call(ui, "cursor_style_set", args);
}

View File

@ -89,10 +89,8 @@ char_u *parse_shape_opt(int what)
int found_ve = false; /* found "ve" flag */
int round;
/*
* First round: check for errors; second round: do it for real.
*/
for (round = 1; round <= 2; ++round) {
// First round: check for errors; second round: do it for real.
for (round = 1; round <= 2; round++) {
// Repeat for all comma separated parts.
modep = p_guicursor;
if (*p_guicursor == NUL) {

View File

@ -283,7 +283,7 @@ int main(int argc, char **argv)
cmdline_row = (int)(Rows - p_ch);
msg_row = cmdline_row;
screenalloc(false); /* allocate screen buffers */
set_init_2();
set_init_2(params.headless);
TIME_MSG("inits 2");
msg_scroll = TRUE;

View File

@ -939,11 +939,8 @@ void free_all_options(void)
#endif
/*
* Initialize the options, part two: After getting Rows and Columns and
* setting 'term'.
*/
void set_init_2(void)
/// Initialize the options, part two: After getting Rows and Columns.
void set_init_2(bool headless)
{
int idx;
@ -966,8 +963,12 @@ void set_init_2(void)
p_window = Rows - 1;
}
set_number_default("window", Rows - 1);
parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */
(void)parse_printoptions(); /* parse 'printoptions' default value */
if (!headless && !os_term_is_nice()) {
set_string_option_direct((char_u *)"guicursor", -1, (char_u *)"",
OPT_GLOBAL, SID_NONE);
}
parse_shape_opt(SHAPE_CURSOR); // set cursor shapes from 'guicursor'
(void)parse_printoptions(); // parse 'printoptions' default value
}
/*
@ -2842,9 +2843,10 @@ did_set_string_option (
}
}
/* 'guicursor' */
else if (varp == &p_guicursor)
// 'guicursor'
else if (varp == &p_guicursor) {
errmsg = parse_shape_opt(SHAPE_CURSOR);
}
else if (varp == &p_popt)
errmsg = parse_printoptions();

View File

@ -1025,13 +1025,6 @@ return {
redraw={'everything'},
enable_if=false,
},
{
full_name='guiheadroom', abbreviation='ghr',
type='number', scope={'global'},
vi_def=true,
enable_if=false,
defaults={if_true={vi=50}}
},
{
full_name='guioptions', abbreviation='go',
type='string', list='flags', scope={'global'},

View File

@ -889,3 +889,17 @@ bool os_setenv_append_path(const char *fname)
}
return false;
}
/// Returns true if the terminal can be assumed to silently ignore unknown
/// control codes.
bool os_term_is_nice(void)
{
#if defined(__APPLE__) || defined(WIN32)
return true;
#else
const char *vte_version = os_getenv("VTE_VERSION");
return (vte_version && atoi(vte_version) >= 3900)
|| NULL != os_getenv("KONSOLE_PROFILE_NAME")
|| NULL != os_getenv("KONSOLE_DBUS_SESSION");
#endif
}

View File

@ -84,6 +84,7 @@ typedef struct {
} TUIData;
static bool volatile got_winch = false;
static bool cursor_style_enabled = false;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/tui.c.generated.h"
@ -151,6 +152,7 @@ static void terminfo_start(UI *ui)
// Set 't_Co' from the result of unibilium & fix_terminfo.
t_colors = unibi_get_num(data->ut, unibi_max_colors);
// Enter alternate screen and clear
// NOTE: Do this *before* changing terminal settings. #6433
unibi_out(ui, unibi_enter_ca_mode);
unibi_out(ui, unibi_clear_screen);
// Enable bracketed paste
@ -437,11 +439,11 @@ static void tui_cursor_goto(UI *ui, int row, int col)
CursorShape tui_cursor_decode_shape(const char *shape_str)
{
CursorShape shape = 0;
if (strcmp(shape_str, "block") == 0) {
if (strequal(shape_str, "block")) {
shape = SHAPE_BLOCK;
} else if (strcmp(shape_str, "vertical") == 0) {
} else if (strequal(shape_str, "vertical")) {
shape = SHAPE_VER;
} else if (strcmp(shape_str, "horizontal") == 0) {
} else if (strequal(shape_str, "horizontal")) {
shape = SHAPE_HOR;
} else {
EMSG2(_(e_invarg2), shape_str);
@ -454,40 +456,41 @@ static cursorentry_T decode_cursor_entry(Dictionary args)
cursorentry_T r;
for (size_t i = 0; i < args.size; i++) {
char *keyStr = args.items[i].key.data;
char *key = args.items[i].key.data;
Object value = args.items[i].value;
if (strcmp(keyStr, "cursor_shape") == 0) {
if (strequal(key, "cursor_shape")) {
r.shape = tui_cursor_decode_shape(args.items[i].value.data.string.data);
} else if (strcmp(keyStr, "blinkon") == 0) {
} else if (strequal(key, "blinkon")) {
r.blinkon = (int)value.data.integer;
} else if (strcmp(keyStr, "blinkoff") == 0) {
} else if (strequal(key, "blinkoff")) {
r.blinkoff = (int)value.data.integer;
} else if (strcmp(keyStr, "hl_id") == 0) {
} else if (strequal(key, "hl_id")) {
r.id = (int)value.data.integer;
}
}
return r;
}
static void tui_cursor_style_set(UI *ui, Dictionary args)
static void tui_cursor_style_set(UI *ui, bool enabled, Dictionary args)
{
cursor_style_enabled = enabled;
if (!enabled) {
return; // Do not send cursor style control codes.
}
TUIData *data = ui->data;
assert(args.size);
// Keys: as defined by `shape_table`.
for (size_t i = 0; i < args.size; i++) {
char *mode_name = args.items[i].key.data;
const int mode_id = cursor_mode_str2int(mode_name);
if (mode_id < 0) {
WLOG("Unknown mode '%s'", mode_name);
continue;
}
assert(mode_id >= 0);
cursorentry_T r = decode_cursor_entry(args.items[i].value.data.dictionary);
r.full_name = mode_name;
data->cursor_shapes[mode_id] = r;
}
// force redraw
MouseMode cursor_mode = tui_mode2cursor(data->showing_mode);
tui_set_cursor(ui, cursor_mode);
}
@ -528,6 +531,9 @@ static void tui_mouse_off(UI *ui)
/// @param mode one of SHAPE_XXX
static void tui_set_cursor(UI *ui, MouseMode mode)
{
if (!cursor_style_enabled) {
return;
}
TUIData *data = ui->data;
cursorentry_T c = data->cursor_shapes[mode];
int shape = c.shape;
@ -536,17 +542,15 @@ static void tui_set_cursor(UI *ui, MouseMode mode)
# define TMUX_WRAP(seq) (inside_tmux ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq)
// Support changing cursor shape on some popular terminals.
const char *term_prog = os_getenv("TERM_PROGRAM");
const char *vte_version = os_getenv("VTE_VERSION");
if ((term_prog && !strcmp(term_prog, "Konsole"))
|| os_getenv("KONSOLE_DBUS_SESSION") != NULL) {
if (os_getenv("KONSOLE_PROFILE_NAME") || os_getenv("KONSOLE_DBUS_SESSION")) {
// Konsole uses a proprietary escape code to set the cursor shape
// and does not support DECSCUSR.
switch (shape) {
case SHAPE_BLOCK: shape = 0; break;
case SHAPE_VER: shape = 1; break;
case SHAPE_HOR: shape = 3; break;
case SHAPE_HOR: shape = 2; break;
default: WLOG("Unknown shape value %d", shape); break;
}
data->params[0].i = shape;
@ -1102,15 +1106,15 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value,
stty_erase = tui_get_stty_erase();
}
if (strcmp(name, "key_backspace") == 0) {
if (strequal(name, "key_backspace")) {
ILOG("libtermkey:kbs=%s", value);
if (stty_erase != NULL && stty_erase[0] != 0) {
return stty_erase;
}
} else if (strcmp(name, "key_dc") == 0) {
} else if (strequal(name, "key_dc")) {
ILOG("libtermkey:kdch1=%s", value);
// Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
if (stty_erase != NULL && value != NULL && strcmp(stty_erase, value) == 0) {
if (stty_erase != NULL && value != NULL && strequal(stty_erase, value)) {
return stty_erase[0] == DEL ? CTRL_H_STR : DEL_STR;
}
}

View File

@ -381,7 +381,8 @@ void ui_cursor_goto(int new_row, int new_col)
void ui_cursor_style_set(void)
{
Dictionary style = cursor_shape_dict();
UI_CALL(cursor_style_set, style);
bool enabled = (*p_guicursor != NUL);
UI_CALL(cursor_style_set, enabled, style);
api_free_dictionary(style);
}

View File

@ -22,7 +22,7 @@ struct ui_t {
void (*clear)(UI *ui);
void (*eol_clear)(UI *ui);
void (*cursor_goto)(UI *ui, int row, int col);
void (*cursor_style_set)(UI *ui, Dictionary cursor_shapes);
void (*cursor_style_set)(UI *ui, bool enabled, Dictionary cursor_styles);
void (*update_menu)(UI *ui);
void (*busy_start)(UI *ui);
void (*busy_stop)(UI *ui);

View File

@ -60,7 +60,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
rv->bridge.clear = ui_bridge_clear;
rv->bridge.eol_clear = ui_bridge_eol_clear;
rv->bridge.cursor_goto = ui_bridge_cursor_goto;
rv->bridge.cursor_style_set = ui_bridge_cursor_styleset;
rv->bridge.cursor_style_set = ui_bridge_cursor_style_set;
rv->bridge.update_menu = ui_bridge_update_menu;
rv->bridge.busy_start = ui_bridge_busy_start;
rv->bridge.busy_stop = ui_bridge_busy_stop;
@ -180,19 +180,21 @@ static void ui_bridge_cursor_goto_event(void **argv)
ui->cursor_goto(ui, PTR2INT(argv[1]), PTR2INT(argv[2]));
}
static void ui_bridge_cursor_styleset(UI *b, Dictionary style)
static void ui_bridge_cursor_style_set(UI *b, bool enabled, Dictionary styles)
{
Object copy = copy_object(DICTIONARY_OBJ(style));
Object *pobj = xmalloc(sizeof(copy));
*pobj = copy;
UI_CALL(b, cursor_styleset, 2, b, pobj);
bool *enabledp = xmalloc(sizeof(*enabledp));
Object *stylesp = xmalloc(sizeof(*stylesp));
*enabledp = enabled;
*stylesp = copy_object(DICTIONARY_OBJ(styles));
UI_CALL(b, cursor_style_set, 3, b, enabledp, stylesp);
}
static void ui_bridge_cursor_styleset_event(void **argv)
static void ui_bridge_cursor_style_set_event(void **argv)
{
UI *ui = UI(argv[0]);
Object *styles = (Object *)argv[1];
ui->cursor_style_set(ui, styles->data.dictionary);
bool *enabled = argv[1];
Object *styles = argv[2];
ui->cursor_style_set(ui, *enabled, styles->data.dictionary);
xfree(enabled);
api_free_object(*styles);
xfree(styles);
}

View File

@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, meths = helpers.clear, helpers.meths
local eq = helpers.eq
local command = helpers.command
local wait = helpers.wait
describe('ui/cursor', function()
local screen
@ -18,7 +19,7 @@ describe('ui/cursor', function()
end)
it("'guicursor' is published as a UI event", function()
command('redraw')
wait()
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
local expected_cursor_style = {
cmdline_hover = {
@ -144,17 +145,18 @@ describe('ui/cursor', function()
}
-- Default 'guicursor' published on startup.
eq(expected_cursor_style, screen._cursor_style)
eq(true, screen._cursor_style_enabled)
eq('normal', screen.mode)
-- Event is published ONLY if the cursor style changed.
screen._cursor_style = nil
command('redraw')
wait()
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
eq(nil, screen._cursor_style)
-- Change the cursor style.
meths.set_option('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173,ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42')
command('redraw')
wait()
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
eq('vertical', screen._cursor_style.normal.cursor_shape)
eq('horizontal', screen._cursor_style.visual_select.cursor_shape)
@ -170,6 +172,8 @@ describe('ui/cursor', function()
meths.set_option('guicursor', '')
command('redraw')
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
-- Empty 'guicursor' sets enabled=false.
eq(false, screen._cursor_style_enabled)
for _, m in ipairs({ 'cmdline_insert', 'cmdline_normal', 'cmdline_replace', 'insert',
'showmatch', 'normal', 'replace', 'visual',
'visual_select', }) do

View File

@ -345,7 +345,8 @@ function Screen:_handle_resize(width, height)
}
end
function Screen:_handle_cursor_style_set(style)
function Screen:_handle_cursor_style_set(enabled, style)
self._cursor_style_enabled = enabled
self._cursor_style = style
end