File Browser Arrow Keys Navigation

Adds support for selecting/deselecting files in File Browser using the
arrow keys. All directions (up, down, left, right) are possible.

When to Select, When to Deselect?
Standard behaviour is selecting, however if we move into a block of
already selected files (meaning 2+ files are selected) we start
deselecting

Possible Selection Methods
Simple selection (arrow-key): All other files are deselected
Expand selection (Shift+arrow key): Add to/remove from existing
selection
ill-Expand selection (Ctrl+Shift+arrow key): Add to/remove from existing
selection and fill everything in-between

From which file do we start navigating?
From each available selection method (Mouse-, Walk-, All-, Border
Select), we use the last selected file. If there's no selection at all
we use the first (down/right arrow) or last (up/left arrow) file.
(Ideally, the view would automatically be set to the new selection, but
this behaviour overlaps with an other patch I've been working on, so
prefer to do that separately)

(Also tweaks color for highlighted file for better feedback)

D1297, Review done by @campbellbarton, thx a lot :)
This commit is contained in:
Julian Eisel 2015-06-11 17:20:29 +02:00
parent 356afe0085
commit 939948c233
Notes: blender-bot 2024-03-22 15:57:27 +01:00
Referenced by issue #45153, OpenGL, Dupli-Objects draw without shading.
10 changed files with 427 additions and 34 deletions

View File

@ -78,6 +78,10 @@ bool BLI_rctf_isect_x(const rctf *rect, const float x);
bool BLI_rctf_isect_y(const rctf *rect, const float y);
bool BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y);
bool BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]);
int BLI_rcti_length_x(const rcti *rect, const int x);
int BLI_rcti_length_y(const rcti *rect, const int y);
float BLI_rctf_length_x(const rctf *rect, const float x);
float BLI_rctf_length_y(const rctf *rect, const float y);
bool BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]);
bool BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2]);
bool BLI_rcti_isect_circle(const struct rcti *rect, const float xy[2], const float radius);

View File

@ -122,6 +122,38 @@ bool BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2])
return true;
}
/**
* \returns shortest distance from \a rect to x/y (0 if inside)
*/
int BLI_rcti_length_x(const rcti *rect, const int x)
{
if (x < rect->xmin) return rect->xmin - x;
if (x > rect->xmax) return x - rect->xmax;
return 0;
}
int BLI_rcti_length_y(const rcti *rect, const int y)
{
if (y < rect->ymin) return rect->ymin - y;
if (y > rect->ymax) return y - rect->ymax;
return 0;
}
float BLI_rctf_length_x(const rctf *rect, const float x)
{
if (x < rect->xmin) return rect->xmin - x;
if (x > rect->xmax) return x - rect->xmax;
return 0.0f;
}
float BLI_rctf_length_y(const rctf *rect, const float y)
{
if (y < rect->ymin) return rect->ymin - y;
if (y > rect->ymax) return y - rect->ymax;
return 0.0f;
}
/**
* is \a rct_b inside \a rct_a
*/

View File

@ -42,6 +42,7 @@ set(SRC
file_draw.c
file_ops.c
file_panels.c
file_utils.c
filelist.c
filesel.c
fsmenu.c

View File

@ -543,9 +543,9 @@ void file_draw_list(const bContext *C, ARegion *ar)
if (!(file->selflag & FILE_SEL_EDITING)) {
if ((params->active_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) || (file->selflag & FILE_SEL_SELECTED)) {
if ((params->highlight_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) || (file->selflag & FILE_SEL_SELECTED)) {
int colorid = (file->selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
int shade = (params->active_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) ? 20 : 0;
int shade = (params->highlight_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) ? 35 : 0;
/* readonly files (".." and ".") must not be drawn as selected - set color back to normal */
if (FILENAME_IS_CURRPAR(file->relname)) {

View File

@ -59,8 +59,17 @@ bool file_draw_check_exists(SpaceFile *sfile);
/* file_ops.h */
struct wmOperatorType;
struct wmOperator;
typedef enum WalkSelectDirection {
FILE_SELECT_WALK_UP,
FILE_SELECT_WALK_DOWN,
FILE_SELECT_WALK_LEFT,
FILE_SELECT_WALK_RIGHT,
} WalkSelectDirections;
void FILE_OT_highlight(struct wmOperatorType *ot);
void FILE_OT_select(struct wmOperatorType *ot);
void FILE_OT_select_walk(struct wmOperatorType *ot);
void FILE_OT_select_all_toggle(struct wmOperatorType *ot);
void FILE_OT_select_border(struct wmOperatorType *ot);
void FILE_OT_select_bookmark(struct wmOperatorType *ot);
@ -111,5 +120,8 @@ int autocomplete_file(struct bContext *C, char *str, void *arg_v);
/* file_panels.c */
void file_panels_register(struct ARegionType *art);
/* file_utils.c */
void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds);
#endif /* __FILE_INTERN_H__ */

View File

@ -176,7 +176,8 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
(selected_idx < numfiles) &&
(file = filelist_file(sfile->files, selected_idx)))
{
params->active_file = selected_idx;
params->highlight_file = selected_idx;
sfile->params->active_file = selected_idx;
if (S_ISDIR(file->type)) {
const bool is_parent_dir = FILENAME_IS_PARENT(file->relname);
@ -242,6 +243,53 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select,
return retval;
}
/**
* \warning: loops over all files so better use cautiously
*/
static bool file_is_any_selected(struct FileList *files)
{
const int numfiles = filelist_numfiles(files);
int i;
for (i = 0; i < numfiles; ++i) {
if (filelist_is_selected(files, i, CHECK_ALL)) {
return true;
}
}
return false;
}
static int file_border_select_find_last_selected(
SpaceFile *sfile, ARegion *ar, const FileSelection *sel,
const int mouse_xy[2])
{
FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
rcti bounds_first, bounds_last;
int dist_first, dist_last;
file_tile_boundbox(ar, layout, sel->first, &bounds_first);
file_tile_boundbox(ar, layout, sel->last, &bounds_last);
/* are first and last in the same column (horizontal layout)/row (vertical layout)? */
if ((layout->flag & FILE_LAYOUT_HOR && bounds_first.xmin == bounds_last.xmin) ||
(layout->flag & FILE_LAYOUT_VER && bounds_first.ymin != bounds_last.ymin))
{
/* use vertical distance */
const int my_loc = mouse_xy[1] - ar->winrct.ymin;
dist_first = BLI_rcti_length_y(&bounds_first, my_loc);
dist_last = BLI_rcti_length_y(&bounds_last, my_loc);
}
else {
/* use horizontal distance */
const int mx_loc = mouse_xy[0] - ar->winrct.xmin;
dist_first = BLI_rcti_length_x(&bounds_first, mx_loc);
dist_last = BLI_rcti_length_x(&bounds_last, mx_loc);
}
return dist_first < dist_last ? sel->first : sel->last;
}
static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
@ -276,17 +324,17 @@ static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *
file->selflag &= ~FILE_SEL_HIGHLIGHTED;
}
/* active_file gets highlighted as well - make sure it is no readonly file */
/* make sure highlight_file is no readonly file */
if (sel.last == idx) {
params->active_file = idx;
params->highlight_file = idx;
}
}
}
params->sel_first = sel.first; params->sel_last = sel.last;
params->active_file = file_border_select_find_last_selected(sfile, ar, &sel, &event->x);
}
else {
params->active_file = -1;
params->highlight_file = -1;
params->sel_first = params->sel_last = -1;
file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
@ -361,7 +409,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
if (sfile && sfile->params) {
int idx = sfile->params->active_file;
int idx = sfile->params->highlight_file;
if (idx >= 0) {
struct direntry *file = filelist_file(sfile->files, idx);
@ -409,35 +457,240 @@ void FILE_OT_select(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/**
* \returns true if selection has changed
*/
static bool file_walk_select_selection_set(
bContext *C, SpaceFile *sfile,
const int direction, const int numfiles,
const int active_old, const int active_new, const int other_site,
const bool has_selection, const bool extend, const bool fill)
{
FileSelectParams *params = sfile->params;
struct FileList *files = sfile->files;
const int last_sel = params->active_file; /* store old value */
int active = active_old; /* could use active_old instead, just for readability */
bool deselect = false;
if (has_selection) {
if (extend &&
filelist_is_selected(files, active_old, FILE_SEL_SELECTED) &&
filelist_is_selected(files, active_new, FILE_SEL_SELECTED))
{
/* conditions for deselecting: initial file is selected, new file is
* selected and either other_side isn't selected/found or we use fill */
deselect = (fill || other_site == -1 || !filelist_is_selected(files, other_site, FILE_SEL_SELECTED));
/* don't change active here since we either want to deselect active or we want to
* walk through a block of selected files without selecting/deselecting anything */
params->active_file = active_new;
/* but we want to change active if we use fill (needed to get correct selection bounds) */
if (deselect && fill) active = active_new;
}
else {
/* regular selection change */
params->active_file = active = active_new;
}
}
else {
/* select last file */
if (ELEM(direction, FILE_SELECT_WALK_UP, FILE_SELECT_WALK_LEFT)) {
params->active_file = active = numfiles - 1;
}
/* select first file */
else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) {
params->active_file = active = 1;
}
else {
BLI_assert(0);
}
}
if (!params || active < 0) return false;
/* highlight the active walker file for extended selection for better visual feedback */
if (extend) {
params->highlight_file = params->active_file;
}
else {
/* deselect all first */
file_deselect_all(sfile, FILE_SEL_SELECTED);
/* highlight file under mouse pos */
params->highlight_file = -1;
WM_event_add_mousemove(C);
}
/* do the actual selection */
if (fill) {
FileSelection sel = { MIN2(active, last_sel), MAX2(active, last_sel) };
/* fill selection between last and first selected file */
filelist_select(sfile->files, &sel, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD,
FILE_SEL_SELECTED, CHECK_ALL);
/* entire sel is cleared here, so select active again */
if (deselect) {
filelist_select_file(sfile->files, active, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
}
}
else {
filelist_select_file(sfile->files, active, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD,
FILE_SEL_SELECTED, CHECK_ALL);
}
BLI_assert(IN_RANGE(active, 0, numfiles));
/* selection changed */
return true;
}
/**
* \returns true if selection has changed
*/
static bool file_walk_select_do(
bContext *C, SpaceFile *sfile,
FileSelectParams *params, const int direction,
const bool extend, const bool fill)
{
const int numfiles = filelist_numfiles(sfile->files);
const bool has_selection = file_is_any_selected(sfile->files);
const int active_old = params->active_file;
int active_new = -1;
int other_site = -1; /* file on the other site of active_old */
/* *** get all needed files for handling selection *** */
if (has_selection) {
ARegion *ar = CTX_wm_region(C);
FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns;
if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) ||
(layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_LEFT))
{
active_new = active_old - 1;
other_site = active_old + 1;
}
else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_DOWN) ||
(layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_RIGHT))
{
active_new = active_old + 1;
other_site = active_old - 1;
}
else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_LEFT) ||
(layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_UP))
{
active_new = active_old - idx_shift;
other_site = active_old + idx_shift;
}
else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_RIGHT) ||
(layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_DOWN))
{
active_new = active_old + idx_shift;
other_site = active_old - idx_shift;
}
else {
BLI_assert(0);
}
if (!IN_RANGE(active_new, 0, numfiles)) {
/* extend to invalid file -> abort */
if (extend) return false;
/* select initial file */
else active_new = active_old;
}
if (!IN_RANGE(other_site, 0, numfiles)) {
other_site = -1;
}
}
return file_walk_select_selection_set(C, sfile, direction, numfiles, active_old, active_new, other_site,
has_selection, extend, fill);
}
static int file_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
FileSelectParams *params = sfile->params;
const int direction = RNA_enum_get(op->ptr, "direction");
const bool extend = RNA_boolean_get(op->ptr, "extend");
const bool fill = RNA_boolean_get(op->ptr, "fill");
if (file_walk_select_do(C, sfile, params, direction, extend, fill)) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
void FILE_OT_select_walk(wmOperatorType *ot)
{
static EnumPropertyItem direction_items[] = {
{FILE_SELECT_WALK_UP, "UP", 0, "Prev", ""},
{FILE_SELECT_WALK_DOWN, "DOWN", 0, "Next", ""},
{FILE_SELECT_WALK_LEFT, "LEFT", 0, "Left", ""},
{FILE_SELECT_WALK_RIGHT, "RIGHT", 0, "Right", ""},
{0, NULL, 0, NULL, NULL}
};
PropertyRNA *prop;
/* identifiers */
ot->name = "Walk Select/Deselect File";
ot->description = "Select/Deselect files by walking through them";
ot->idname = "FILE_OT_select_walk";
/* api callbacks */
ot->invoke = file_walk_select_invoke;
ot->poll = ED_operator_file_active;
/* properties */
prop = RNA_def_enum(ot->srna, "direction", direction_items, 0, "Walk Direction",
"Select/Deselect file in this direction");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "extend", false, "Extend",
"Extend selection instead of deselecting everything first");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "fill", false, "Fill", "Select everything beginning with the last selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelection sel;
int numfiles = filelist_numfiles(sfile->files);
int i;
bool is_selected = false;
const int numfiles = filelist_numfiles(sfile->files);
const bool has_selection = file_is_any_selected(sfile->files);
sel.first = 0;
sel.last = numfiles - 1;
/* Is any file selected ? */
for (i = 0; i < numfiles; ++i) {
if (filelist_is_selected(sfile->files, i, CHECK_ALL)) {
is_selected = true;
break;
}
}
/* select all only if previously no file was selected */
if (is_selected) {
if (has_selection) {
filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
}
else {
const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES;
int i;
filelist_select(sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_SELECTED, check_type);
/* set active_file to first selected */
for (i = 0; i < numfiles; i++) {
if (filelist_is_selected(sfile->files, i, check_type)) {
sfile->params->active_file = i;
break;
}
}
}
file_draw_check(C);
WM_event_add_mousemove(C);
ED_area_tag_redraw(sa);
return OPERATOR_FINISHED;
}
@ -748,28 +1001,28 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
numfiles = filelist_numfiles(sfile->files);
params = ED_fileselect_get_params(sfile);
origfile = params->active_file;
origfile = params->highlight_file;
mx -= ar->winrct.xmin;
my -= ar->winrct.ymin;
if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) {
float fx, fy;
int active_file;
int highlight_file;
UI_view2d_region_to_view(v2d, mx, my, &fx, &fy);
active_file = ED_fileselect_layout_offset(sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy));
highlight_file = ED_fileselect_layout_offset(sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy));
if ((active_file >= 0) && (active_file < numfiles))
params->active_file = active_file;
if ((highlight_file >= 0) && (highlight_file < numfiles))
params->highlight_file = highlight_file;
else
params->active_file = -1;
params->highlight_file = -1;
}
else
params->active_file = -1;
params->highlight_file = -1;
return (params->active_file != origfile);
return (params->highlight_file != origfile);
}
static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
@ -1669,7 +1922,7 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
if (sfile->params) {
int idx = sfile->params->active_file;
int idx = sfile->params->highlight_file;
int numfiles = filelist_numfiles(sfile->files);
if ( (0 <= idx) && (idx < numfiles) ) {
struct direntry *file = filelist_file(sfile->files, idx);
@ -1690,7 +1943,7 @@ static int file_rename_poll(bContext *C)
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile && sfile->params) {
int idx = sfile->params->active_file;
int idx = sfile->params->highlight_file;
if (idx >= 0) {
struct direntry *file = filelist_file(sfile->files, idx);
@ -1699,7 +1952,7 @@ static int file_rename_poll(bContext *C)
}
}
if (sfile->params->active_file < 0) {
if (sfile->params->highlight_file < 0) {
poll = 0;
}
else {

View File

@ -0,0 +1,46 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/space_file/file_utils.c
* \ingroup spfile
*/
#include "BLI_rect.h"
#include "BKE_context.h"
#include "ED_screen.h"
#include "ED_fileselect.h"
#include "WM_types.h"
#include "file_intern.h"
void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds)
{
int xmin, ymax;
ED_fileselect_layout_tilepos(layout, file, &xmin, &ymax);
BLI_rcti_init(r_bounds, xmin, xmin + layout->tile_w + layout->tile_border_x,
ar->winy - ymax - layout->tile_h - layout->tile_border_y, ar->winy - ymax);
}

View File

@ -697,7 +697,7 @@ void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile)
filelist_free(sfile->files);
}
sfile->params->active_file = -1;
sfile->params->highlight_file = -1;
WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}

View File

@ -212,7 +212,7 @@ static void file_refresh(const bContext *C, ScrArea *sa)
if (!sfile->files) {
sfile->files = filelist_new(params->type);
filelist_setdir(sfile->files, params->dir);
params->active_file = -1; /* added this so it opens nicer (ton) */
params->highlight_file = -1; /* added this so it opens nicer (ton) */
}
filelist_setsorting(sfile->files, params->sort);
filelist_setfilter_options(sfile->files, params->flag & FILE_HIDE_DOT,
@ -377,7 +377,7 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(v2d);
/* on first read, find active file */
if (params->active_file == -1) {
if (params->highlight_file == -1) {
wmEvent *event = CTX_wm_window(C)->eventstate;
file_highlight_set(sfile, ar, event->x, event->y);
}
@ -397,6 +397,7 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
static void file_operatortypes(void)
{
WM_operatortype_append(FILE_OT_select);
WM_operatortype_append(FILE_OT_select_walk);
WM_operatortype_append(FILE_OT_select_all_toggle);
WM_operatortype_append(FILE_OT_select_border);
WM_operatortype_append(FILE_OT_select_bookmark);
@ -462,6 +463,49 @@ static void file_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "fill", true);
RNA_boolean_set(kmi->ptr, "open", false);
/* arrow keys navigation (walk selecting) */
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", UPARROWKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_UP);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", UPARROWKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_UP);
RNA_boolean_set(kmi->ptr, "extend", true);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", UPARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_UP);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "fill", true);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", DOWNARROWKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_DOWN);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_DOWN);
RNA_boolean_set(kmi->ptr, "extend", true);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", DOWNARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_DOWN);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "fill", true);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", LEFTARROWKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_LEFT);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_LEFT);
RNA_boolean_set(kmi->ptr, "extend", true);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", LEFTARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_LEFT);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "fill", true);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", RIGHTARROWKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_RIGHT);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_RIGHT);
RNA_boolean_set(kmi->ptr, "extend", true);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select_walk", RIGHTARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "direction", FILE_SELECT_WALK_RIGHT);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "fill", true);
/* front and back mouse folder navigation */
WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_CLICK, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_CLICK, 0, 0);

View File

@ -591,7 +591,8 @@ typedef struct FileSelectParams {
char filter_search[64]; /* text items' name must match to be shown. */
int active_file;
int active_file; /* active file used for keyboard navigation */
int highlight_file; /* file under cursor */
int sel_first;
int sel_last;
unsigned short thumbnail_size;