1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2025-07-31 21:59:25 -04:00

Merge remote-tracking branch 'github/next' into next

This commit is contained in:
Dave Davenport 2023-01-22 17:25:36 +01:00
commit c84f7f3bad
13 changed files with 246 additions and 12 deletions

View file

@ -587,6 +587,20 @@ Select row 10
.PP
\fBDefault\fP: Super+0
.SS \fBkb-entry-history-up\fP
.PP
Go up in the entry history.
.PP
\fBDefault\fP: Control+Up
.SS \fBkb-entry-history-down\fP
.PP
Go down in the entry history.
.PP
\fBDefault\fP: Control+Down
.SH Mouse Bindings
.SS \fBml-row-left\fP
.PP

View file

@ -415,6 +415,16 @@ Select row 10
**Default**: Super+0
### **kb-entry-history-up**
Go up in the entry history.
**Default**: Control+Up
### **kb-entry-history-down**
Go down in the entry history.
**Default**: Control+Down
## Mouse Bindings
### **ml-row-left**

View file

@ -1180,6 +1180,28 @@ rofi -filebrowser-cancel-returns-1 true -show filebrowser
.PP
The \fB\fCshow-hidden\fR can also be triggered with the \fB\fCkb-delete-entry\fR keybinding.
.SS Entry history
.PP
The number of previous inputs for the entry box can be modified by setting
max-history on the entry box.
.PP
.RS
.nf
configuration {
entry {
max-history: 30;
}
}
.fi
.RE
.PP
By default the file is stored in the systems cache directory, in a file called
\fB\fCrofi-entry-history.txt\fR\&.
.SS Other
.PP
\fB\fC-drun-use-desktop-cache\fR

View file

@ -726,6 +726,22 @@ rofi -filebrowser-cancel-returns-1 true -show filebrowser
The `show-hidden` can also be triggered with the `kb-delete-entry` keybinding.
### Entry history
The number of previous inputs for the entry box can be modified by setting
max-history on the entry box.
```css
configuration {
entry {
max-history: 30;
}
}
```
By default the file is stored in the systems cache directory, in a file called
`rofi-entry-history.txt`.
### Other
`-drun-use-desktop-cache`

View file

@ -397,7 +397,7 @@ char *helper_string_replace_if_exists(char *string, ...);
*
* @returns path to theme or copy of filename if not found.
*/
char *helper_get_theme_path(const char *file, const char **ext);
char *helper_get_theme_path(const char *file, const char **ext) __attribute__((nonnull));
/**
* @param name The name of the element to find.

View file

@ -143,6 +143,8 @@ typedef enum {
SELECT_ELEMENT_8,
SELECT_ELEMENT_9,
SELECT_ELEMENT_10,
ENTRY_HISTORY_UP,
ENTRY_HISTORY_DOWN,
} KeyBindingAction;
/**

View file

@ -345,5 +345,19 @@ void textbox_set_ellipsize(textbox *tb, PangoEllipsizeMode mode);
* @returns the position of the cursor (0 if no cursor).
*/
int textbox_get_cursor_x_pos(const textbox *tb);
/**
* @param tb Handle to the textbox
*
* @returns gets a newly allocated copy of the content of the entrybox.
*/
char *textbox_get_text ( const textbox *tb );
/**
* @param tb Handle to the textbox
*
* @returns the position of the cursor.
*/
int textbox_get_cursor ( const textbox *tb );
/**@}*/
#endif // ROFI_TEXTBOX_H

View file

@ -1076,17 +1076,16 @@ char *helper_get_theme_path(const char *file, const char **ext) {
g_free(filename);
gboolean ext_found = FALSE;
if (ext) {
for (const char **i = ext; *i != NULL; i++) {
if (g_str_has_suffix(file, *i)) {
ext_found = TRUE;
break;
}
for (const char **i = ext; *i != NULL; i++) {
if (g_str_has_suffix(file, *i)) {
ext_found = TRUE;
break;
}
}
if (ext_found) {
filename = g_strdup(file);
} else {
g_assert_nonnull(ext[0]);
// TODO: Pick the first extension. needs fixing.
filename = g_strconcat(file, ext[0], NULL);
}

View file

@ -324,6 +324,14 @@ ActionBindingEntry rofi_bindings[] = {
.name = "kb-select-10",
.binding = "Super+0",
.comment = "Select row 10"},
{.id = ENTRY_HISTORY_UP,
.name = "kb-entry-history-up",
.binding = "Control+Up",
.comment = "Go up in the history of the entry box"},
{.id = ENTRY_HISTORY_DOWN,
.name = "kb-entry-history-down",
.binding = "Control+Down",
.comment = "Go down in the history of the entry box"},
/* Mouse-aware bindings */

View file

@ -83,10 +83,13 @@ void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw,
DmenuScriptEntry *entry, char *buffer,
G_GNUC_UNUSED size_t length) {
gchar **extras = g_strsplit(buffer, "\x1f", -1);
gchar **extra;
for (extra = extras; *extra != NULL && *(extra + 1) != NULL; extra += 2) {
gchar **extra = extras;
for (; *extra != NULL && *(extra + 1) != NULL; extra += 2) {
gchar *key = *extra;
gchar *value = *(extra + 1);
// Mark NULL
*(extra) = NULL;
*(extra+1) = NULL;
if (strcasecmp(key, "icon") == 0) {
entry->icon_name = value;
} else if (strcasecmp(key, "meta") == 0) {
@ -107,6 +110,10 @@ void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw,
}
g_free(key);
}
// Got an extra entry.. lets free it.
if ( *extras != NULL ) {
g_free(*extras);
}
g_free(extras);
}
@ -247,7 +254,7 @@ static DmenuScriptEntry *execute_executor(Mode *sw, char *arg,
buffer + buf_length,
read_length - buf_length);
}
retv[(*length) + 1].entry = NULL;
memset(&(retv[(*length)+1]), 0, sizeof(DmenuScriptEntry));
(*length)++;
}
}
@ -350,6 +357,7 @@ static ModeMode script_mode_result(Mode *sw, int mretv, char **input,
g_free(rmpd->cmd_list[i].entry);
g_free(rmpd->cmd_list[i].icon_name);
g_free(rmpd->cmd_list[i].meta);
g_free(rmpd->cmd_list[i].info);
}
g_free(rmpd->cmd_list);
@ -522,6 +530,7 @@ void script_mode_gather_user_scripts(void) {
}
num_scripts++;
}
g_dir_close(sd);
}
g_free(script_dir);

View file

@ -48,6 +48,7 @@
#include <cairo-xcb.h>
#include <cairo.h>
#include <gio/gio.h>
/** Indicated we understand the startup notification api is not yet stable.*/
#define SN_API_NOT_YET_FROZEN
@ -102,6 +103,11 @@ GThreadPool *tpool = NULL;
/** Global pointer to the currently active RofiViewState */
RofiViewState *current_active_menu = NULL;
typedef struct {
char *string;
int index;
} EntryHistoryIndex;
/**
* Structure holding cached state.
*/
@ -148,6 +154,10 @@ struct {
gboolean fullscreen;
/** Cursor type */
X11CursorType cursor_type;
/** Entry box */
EntryHistoryIndex *entry_history;
gssize entry_history_length;
gssize entry_history_index;
} CacheState = {
.main_window = XCB_WINDOW_NONE,
.fake_bg = NULL,
@ -165,6 +175,9 @@ struct {
.count = 0L,
.repaint_source = 0,
.fullscreen = FALSE,
.entry_history = NULL,
.entry_history_length = 0,
.entry_history_index = 0
};
void rofi_view_get_current_monitor(int *width, int *height) {
@ -885,7 +898,74 @@ static void open_xim_callback(xcb_xim_t *im, G_GNUC_UNUSED void *user_data) {
}
#endif
static void input_history_initialize ( void )
{
CacheState.entry_history = NULL;
CacheState.entry_history_index = 0;
CacheState.entry_history_length = 0;
gchar *path = g_build_filename(cache_dir, "rofi-entry-history.txt", NULL);
if ( g_file_test(path, G_FILE_TEST_EXISTS ) ) {
FILE *fp = fopen(path, "r");
if ( fp ) {
char *line = NULL;
size_t len = 0;
ssize_t nread;
while ((nread = getline(&line, &len, fp)) != -1) {
CacheState.entry_history = g_realloc(CacheState.entry_history,
sizeof(EntryHistoryIndex)*(CacheState.entry_history_length+1));
if ( line[nread-1] == '\n' ) {
line[nread-1] = '\0';
nread--;
}
CacheState.entry_history[CacheState.entry_history_length].string = g_strdup(line);
CacheState.entry_history[CacheState.entry_history_length].index = strlen(line);
CacheState.entry_history_length++;
CacheState.entry_history_index++;
}
free(line);
fclose(fp);
}
}
g_free(path);
CacheState.entry_history = g_realloc(CacheState.entry_history,
sizeof(EntryHistoryIndex)*(CacheState.entry_history_length+1));
CacheState.entry_history[CacheState.entry_history_length].string = g_strdup("");
CacheState.entry_history[CacheState.entry_history_length].index = 0;
CacheState.entry_history_length++;
}
static void input_history_save ( void )
{
if ( CacheState.entry_history_length > 0 ){
// History max.
int max_history = 20;
ThemeWidget *wid = rofi_config_find_widget("entry", NULL, TRUE);
if ( wid ) {
Property *p = rofi_theme_find_property(wid, P_INTEGER, "max-history", TRUE);
if ( p != NULL && p->type == P_INTEGER ){
max_history = p->value.i;
}
}
gchar *path = g_build_filename(cache_dir, "rofi-entry-history.txt", NULL);
g_debug("Entry filename output: '%s'", path);
FILE *fp = fopen(path, "w");
if ( fp ) {
gssize start = MAX(0, (CacheState.entry_history_length-max_history));
for ( gssize i = start; i < CacheState.entry_history_length; i++){
if ( strlen(CacheState.entry_history[i].string) > 0 ){
fprintf(fp, "%s\n", CacheState.entry_history[i].string);
}
}
fclose(fp);
}
g_free(path);
}
}
void __create_window(MenuFlags menu_flags) {
input_history_initialize();
uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE |
XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
@ -1476,7 +1556,18 @@ void rofi_view_finalize(RofiViewState *state) {
* This function should be called when the input of the entry is changed.
* TODO: Evaluate if this needs to be a 'signal' on textbox?
*/
static void rofi_view_input_changed() { rofi_view_take_action("inputchange"); }
static void rofi_view_input_changed() {
rofi_view_take_action("inputchange");
RofiViewState * state = current_active_menu;
if ( state ) {
if ( CacheState.entry_history[CacheState.entry_history_index].string != NULL) {
g_free(CacheState.entry_history[CacheState.entry_history_index].string);
}
CacheState.entry_history[CacheState.entry_history_index].string = textbox_get_text(state->text);
CacheState.entry_history[CacheState.entry_history_index].index = textbox_get_cursor(state->text);
}
}
static void rofi_view_trigger_global_action(KeyBindingAction action) {
RofiViewState *state = rofi_view_get_active();
@ -1731,6 +1822,44 @@ static void rofi_view_trigger_global_action(KeyBindingAction action) {
state->quit = TRUE;
break;
}
case ENTRY_HISTORY_DOWN: {
if ( state->text ) {
CacheState.entry_history[CacheState.entry_history_index].index = textbox_get_cursor(state->text);
if ( CacheState.entry_history_index > 0 ) {
CacheState.entry_history_index--;
}
if ( state->text ) {
textbox_text(state->text, CacheState.entry_history[CacheState.entry_history_index].string);
textbox_cursor(state->text,CacheState.entry_history[CacheState.entry_history_index].index );
state->refilter = TRUE;
}
}
break;
}
case ENTRY_HISTORY_UP: {
if ( state->text ) {
if ( CacheState.entry_history[CacheState.entry_history_index].string != NULL) {
g_free(CacheState.entry_history[CacheState.entry_history_index].string);
}
CacheState.entry_history[CacheState.entry_history_index].string = textbox_get_text(state->text);
CacheState.entry_history[CacheState.entry_history_index].index = textbox_get_cursor(state->text);
// Don't create up if current is empty.
if ( strlen(CacheState.entry_history[CacheState.entry_history_index].string) > 0 ) {
CacheState.entry_history_index++;
if ( CacheState.entry_history_index >= CacheState.entry_history_length ) {
CacheState.entry_history = g_realloc(CacheState.entry_history,
sizeof(EntryHistoryIndex)*(CacheState.entry_history_length+1));
CacheState.entry_history[CacheState.entry_history_length].string = g_strdup("");
CacheState.entry_history[CacheState.entry_history_length].index = 0;
CacheState.entry_history_length++;
}
}
textbox_text(state->text, CacheState.entry_history[CacheState.entry_history_index].string);
textbox_cursor(state->text,CacheState.entry_history[CacheState.entry_history_index].index );
state->refilter = TRUE;
}
break;
}
}
}
@ -2443,6 +2572,8 @@ void rofi_view_cleanup() {
}
xcb_flush(xcb->connection);
g_assert(g_queue_is_empty(&(CacheState.views)));
input_history_save();
}
void rofi_view_workers_initialize(void) {
TICK_N("Setup Threadpool, start");

View file

@ -359,6 +359,15 @@ void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list) {
pango_layout_set_attributes(tb->layout, list);
}
char *textbox_get_text ( const textbox *tb ) {
if ( tb->text == NULL ) {
return g_strdup("");
}
return g_strdup( tb->text );
}
int textbox_get_cursor ( const textbox *tb ) {
return tb->cursor;
}
// set the default text to display
void textbox_text(textbox *tb, const char *text) {
if (tb == NULL) {

View file

@ -127,7 +127,7 @@ END_TEST
START_TEST(test_mode_num_items) {
unsigned int rows = mode_get_num_entries(&help_keys_mode);
ck_assert_int_eq(rows, 77);
ck_assert_int_eq(rows, 79);
for (unsigned int i = 0; i < rows; i++) {
int state = 0;
GList *list = NULL;