# HG changeset patch # User Bram Moolenaar # Date 1624474803 -7200 # Node ID 4962219168853797599000b0fb0ccff78b57bdf4 # Parent 791ae2f86aa427a2e7287af2c05f2d362cf47457 patch 8.2.3040: GUI: dropping files not tested Commit: https://github.com/vim/vim/commit/18d46587b985923ef4b90b19a0cf37a094607fec Author: Yegappan Lakshmanan Date: Wed Jun 23 20:46:52 2021 +0200 patch 8.2.3040: GUI: dropping files not tested Problem: GUI: dropping files not tested. Solution: Add test_gui_drop_files() and tests. (Yegappan Lakshmanan, closes #8434) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -3022,6 +3022,8 @@ test_feedinput({string}) none add key se test_garbagecollect_now() none free memory right now for testing test_garbagecollect_soon() none free memory soon for testing test_getvalue({string}) any get value of an internal variable +test_gui_drop_files({list}, {row}, {col}, {mods}) + none drop a list of files in a window test_gui_mouse_event({button}, {row}, {col}, {repeated}, {mods}) none add a mouse event to the input buffer test_ignore_error({expr}) none ignore a specific error diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -79,10 +79,23 @@ test_getvalue({name}) *test_getvalue Can also be used as a |method|: > GetName()->test_getvalue() < + *test_gui_drop_files()* +test_gui_drop_files({list}, {row}, {col}, {mods}) + Drop one or more files in {list} in the window at {row}, {col}. + This function only works when the GUI is running. + + The supported values for {mods} are: + 0x4 Shift + 0x8 Alt + 0x10 Ctrl + The files are added to the argument list and the first file in + {list} is edited in the window. See |drag-n-drop| for more + information. + *test_gui_mouse_event()* test_gui_mouse_event({button}, {row}, {col}, {multiclick}, {modifiers}) - Inject a mouse button click event. This function works only - when GUI is running. + Inject a mouse button click event. This function only works + when the GUI is running. The supported values for {button} are: 0 right mouse button 1 middle mouse button @@ -92,7 +105,9 @@ test_gui_mouse_event({button}, {row}, {c 5 scroll wheel up 6 scroll wheel left 7 scroll wheel right - {row} and {col} specify the location of the mouse click. + {row} and {col} specify the location of the mouse click. The + first row of the Vim window is 1 and the last row is 'lines'. + The maximum value of {col} is 'columns'. To inject a multiclick event, set {multiclick} to 1. The supported values for {modifiers} are: 4 shift is pressed diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1021,6 +1021,7 @@ Testing: *test-functions* test_garbagecollect_now() free memory right now test_garbagecollect_soon() set a flag to free memory soon test_getvalue() get value of an internal variable + test_gui_drop_files() drop file(s) in a window test_gui_mouse_event() add a GUI mouse event to the input buffer test_ignore_error() ignore a specific error message test_null_blob() return a null Blob diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1700,6 +1700,8 @@ static funcentry_T global_functions[] = ret_void, f_test_garbagecollect_soon}, {"test_getvalue", 1, 1, FEARG_1, NULL, ret_number, f_test_getvalue}, + {"test_gui_drop_files", 4, 4, 0, NULL, + ret_void, f_test_gui_drop_files}, {"test_gui_mouse_event", 5, 5, 0, NULL, ret_void, f_test_gui_mouse_event}, {"test_ignore_error", 1, 1, FEARG_1, NULL, diff --git a/src/gui.c b/src/gui.c --- a/src/gui.c +++ b/src/gui.c @@ -5567,6 +5567,7 @@ gui_handle_drop( { vim_free(fnames[0]); vim_free(fnames); + vim_free(p); } else handle_drop(count, fnames, (modifiers & MOUSE_CTRL) != 0, diff --git a/src/proto/testing.pro b/src/proto/testing.pro --- a/src/proto/testing.pro +++ b/src/proto/testing.pro @@ -36,4 +36,5 @@ void f_test_scrollbar(typval_T *argvars, void f_test_setmouse(typval_T *argvars, typval_T *rettv); void f_test_gui_mouse_event(typval_T *argvars, typval_T *rettv); void f_test_settime(typval_T *argvars, typval_T *rettv); +void f_test_gui_drop_files(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim --- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -1158,4 +1158,93 @@ func Test_gui_tablabel_tooltip() let &lines = save_lines endfunc +" Test for dropping files into a window in GUI +func DropFilesInCmdLine() + call feedkeys(":\"", 'L') + call test_gui_drop_files(['a.c', 'b.c'], &lines, 1, 0) + call feedkeys("\", 'L') +endfunc + +func Test_gui_drop_files() + call assert_fails('call test_gui_drop_files(1, 1, 1, 0)', 'E474:') + call assert_fails('call test_gui_drop_files(["x"], "", 1, 0)', 'E474:') + call assert_fails('call test_gui_drop_files(["x"], 1, "", 0)', 'E474:') + call assert_fails('call test_gui_drop_files(["x"], 1, 1, "")', 'E474:') + + %bw! + %argdelete + call test_gui_drop_files([], 1, 1, 0) + call assert_equal([], argv()) + call test_gui_drop_files([1, 2], 1, 1, 0) + call assert_equal([], argv()) + + call test_gui_drop_files(['a.c', 'b.c'], 1, 1, 0) + call assert_equal(['a.c', 'b.c'], argv()) + %bw! + %argdelete + call test_gui_drop_files([], 1, 1, 0) + call assert_equal([], argv()) + %bw! + " if the buffer in the window is modified, then the file should be opened in + " a new window + set modified + call test_gui_drop_files(['x.c', 'y.c'], 1, 1, 0) + call assert_equal(['x.c', 'y.c'], argv()) + call assert_equal(2, winnr('$')) + call assert_equal('x.c', bufname(winbufnr(1))) + %bw! + %argdelete + " if Ctrl is pressed, then the file should be opened in a new window + call test_gui_drop_files(['s.py', 't.py'], 1, 1, 0x10) + call assert_equal(['s.py', 't.py'], argv()) + call assert_equal(2, winnr('$')) + call assert_equal('s.py', bufname(winbufnr(1))) + %bw! + %argdelete + " drop the files in a non-current window + belowright new + call test_gui_drop_files(['a.py', 'b.py'], 1, 1, 0) + call assert_equal(['a.py', 'b.py'], argv()) + call assert_equal(2, winnr('$')) + call assert_equal(1, winnr()) + call assert_equal('a.py', bufname(winbufnr(1))) + %bw! + %argdelete + " pressing shift when dropping files should change directory + let save_cwd = getcwd() + call mkdir('Xdir1') + call writefile([], 'Xdir1/Xfile1') + call writefile([], 'Xdir1/Xfile2') + call test_gui_drop_files(['Xdir1/Xfile1', 'Xdir1/Xfile2'], 1, 1, 0x4) + call assert_equal('Xdir1', fnamemodify(getcwd(), ':t')) + call assert_equal('Xfile1', @%) + call chdir(save_cwd) + " pressing shift when dropping directory and files should change directory + call test_gui_drop_files(['Xdir1', 'Xdir1/Xfile2'], 1, 1, 0x4) + call assert_equal('Xdir1', fnamemodify(getcwd(), ':t')) + call assert_equal('Xdir1', fnamemodify(@%, ':t')) + call chdir(save_cwd) + %bw! + %argdelete + " dropping a directory should edit it + call test_gui_drop_files(['Xdir1'], 1, 1, 0) + call assert_equal('Xdir1', @%) + %bw! + %argdelete + " dropping only a directory name with Shift should ignore it + call test_gui_drop_files(['Xdir1'], 1, 1, 0x4) + call assert_equal('', @%) + %bw! + %argdelete + call delete('Xdir1', 'rf') + " drop files in the command line. The GUI drop files adds the file names to + " the low level input buffer. So need to use a cmdline map and feedkeys() + " with 'Lx!' to process it in this function itself. + cnoremap DropFilesInCmdLine() + call feedkeys(":\"\\", 'xt') + call feedkeys('k', 'Lx!') + call assert_equal('"a.c b.c', @:) + cunmap +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testing.c b/src/testing.c --- a/src/testing.c +++ b/src/testing.c @@ -1224,7 +1224,7 @@ f_test_setmouse(typval_T *argvars, typva void f_test_gui_mouse_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { -#ifdef FEAT_GUI +# ifdef FEAT_GUI int button; int row; int col; @@ -1248,7 +1248,7 @@ f_test_gui_mouse_event(typval_T *argvars mods = tv_get_number(&argvars[4]); gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1), repeated_click, mods); -#endif +# endif } void @@ -1257,5 +1257,61 @@ f_test_settime(typval_T *argvars, typval time_for_testing = (time_t)tv_get_number(&argvars[0]); } + void +f_test_gui_drop_files(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +# ifdef FEAT_GUI + int row; + int col; + int_u mods; + char_u **fnames; + int count = 0; + list_T *l; + listitem_T *li; + + if (argvars[0].v_type != VAR_LIST + || (argvars[1].v_type) != VAR_NUMBER + || (argvars[2].v_type) != VAR_NUMBER + || (argvars[3].v_type) != VAR_NUMBER) + { + emsg(_(e_invarg)); + return; + } + + row = tv_get_number(&argvars[1]); + col = tv_get_number(&argvars[2]); + mods = tv_get_number(&argvars[3]); + + l = argvars[0].vval.v_list; + if (list_len(l) == 0) + return; + + fnames = ALLOC_MULT(char_u *, list_len(l)); + if (fnames == NULL) + return; + + FOR_ALL_LIST_ITEMS(l, li) + { + // ignore non-string items + if (li->li_tv.v_type != VAR_STRING) + continue; + + fnames[count] = vim_strsave(li->li_tv.vval.v_string); + if (fnames[count] == NULL) + { + while (--count >= 0) + vim_free(fnames[count]); + vim_free(fnames); + return; + } + count++; + } + + if (count > 0) + gui_handle_drop(TEXT_X(col - 1), TEXT_Y(row - 1), mods, fnames, count); + else + vim_free(fnames); +# endif +} #endif // defined(FEAT_EVAL) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3040, +/**/ 3039, /**/ 3038,