Merge remote-tracking branch 'upstream/next' into wayland

This commit is contained in:
lbonn 2022-10-05 18:49:54 +02:00
commit d44b81e778
30 changed files with 265 additions and 86 deletions

View file

@ -9,28 +9,52 @@ body:
value: | value: |
First read the [guidelines](https://github.com/DaveDavenport/rofi/blob/next/.github/CONTRIBUTING.md)! This is not optional for any report. People must be able to understand the full context of the report when reading it, at any time. First read the [guidelines](https://github.com/DaveDavenport/rofi/blob/next/.github/CONTRIBUTING.md)! This is not optional for any report. People must be able to understand the full context of the report when reading it, at any time.
If you feel like you “it is simple and requires no explanation”, please consider youre wrong and still fill the full report. Any report missing these informations will be labeled as “Incomplete Report - Please follow the guidelines” and may not be answered in a timely fashion. If you feel like you “it is simple and requires no explanation”, please
If you ask a question, enter dummy information in required fields to get passed the checks or in general completely ignore the guidelines, the issue will be closed and locked as spam. consider youre wrong and still fill the full report. Any report
missing required informations will be labeled as “Incomplete Report -
Please follow the guidelines” and will be closed. If you ask a
question, enter dummy information in required fields to get passed the
checks or in general completely ignore the guidelines, the issue will
be closed and locked as spam.
If you are unsure, please use the [discussion](https://github.com/davatorium/rofi/discussions) forum first. It is easy to upgrade a question to an issue in github. If you are unsure, please use the
[discussion](https://github.com/davatorium/rofi/discussions) forum
first. It is easy to upgrade a question to an issue in github.
If you report problems with speed in rofi, please attach a [timing trace](https://github.com/davatorium/rofi/blob/next/doc/rofi-debugging.5.markdown#timing-traces). If you report problems with speed in rofi, attach a [timing
trace](https://github.com/davatorium/rofi/blob/next/doc/rofi-debugging.5.markdown#timing-traces).
**Please do not submit reports related to wayland, see [here](https://github.com/DaveDavenport/rofi/wiki/Wayland) for more information.** **Please do not submit reports related to wayland, see
[here](https://github.com/DaveDavenport/rofi/wiki/Wayland) for more
information.**
- type: input - type: input
attributes: attributes:
label: "Rofi version (rofi -v)" label: "Rofi version (rofi -v)"
placeholder: "Version: 1.6.0" placeholder: "Version: 1.7.5"
validations: validations:
required: true required: true
- type: input - type: input
attributes: attributes:
label: "Configuration" label: "Configuration"
description: "Please use https://gist.github.com and include output of `rofi -dump-config` and `rofi -dump-theme`." description: "Please use https://gist.github.com and include output of `rofi -dump-config`."
placeholder: "Gist URL" placeholder: "Gist URL"
validations: validations:
required: true required: true
- type: input
attributes:
label: "Theme"
description: "Please use https://gist.github.com and include output of `rofi -dump-theme`."
placeholder: "Gist URL"
validations:
required: true
- type: input
attributes:
label: "Timing report"
description: "Please use https://gist.github.com and include output of your command with G_MESSAGES_DEBUG=Timings set."
placeholder: "Gist URL"
validations:
required: false
- type: input - type: input
attributes: attributes:
label: "Launch command" label: "Launch command"

View file

@ -11,6 +11,7 @@
# Please match the documentation and example scripts to the version of rofi used: # Please match the documentation and example scripts to the version of rofi used:
* [next version](https://github.com/davatorium/rofi) * [next version](https://github.com/davatorium/rofi)
* [1.7.5](https://github.com/davatorium/rofi/tree/1.7.5)
* [1.7.4](https://github.com/davatorium/rofi/tree/1.7.4) * [1.7.4](https://github.com/davatorium/rofi/tree/1.7.4)
* [1.7.3](https://github.com/davatorium/rofi/tree/1.7.3) * [1.7.3](https://github.com/davatorium/rofi/tree/1.7.3)
* [1.7.2](https://github.com/davatorium/rofi/tree/1.7.2) * [1.7.2](https://github.com/davatorium/rofi/tree/1.7.2)

View file

@ -154,8 +154,8 @@ Settings config = {
.steal_focus = FALSE, .steal_focus = FALSE,
/** fallback icon */ /** fallback icon */
.application_fallback_icon = NULL, .application_fallback_icon = NULL,
/** refilter limit */ /** refilter limit in ms*/
.refilter_timeout_limit = 8192, .refilter_timeout_limit = 300,
/** workaround for broken xserver (#300 on xserver, #611) */ /** workaround for broken xserver (#300 on xserver, #611) */
.xserver_i300_workaround = FALSE, .xserver_i300_workaround = FALSE,
}; };

View file

@ -1,4 +1,4 @@
AC_INIT([rofi], [1.7.5], [https://github.com/davatorium/rofi/],[],[https://reddit.com/r/qtools/]) AC_INIT([rofi], [1.7.5-dev], [https://github.com/davatorium/rofi/],[],[https://reddit.com/r/qtools/])
AC_CONFIG_SRCDIR([source/rofi.c]) AC_CONFIG_SRCDIR([source/rofi.c])
AC_CONFIG_HEADER([config.h]) AC_CONFIG_HEADER([config.h])

View file

@ -96,6 +96,13 @@ Paste clipboard
.PP .PP
\fBDefault\fP: Control+v,Insert \fBDefault\fP: Control+v,Insert
.SS \fBkb-secondary-copy\fP
.PP
Copy current selection to clipboard
.PP
\fBDefault\fP: Control+c
.SS \fBkb-clear-line\fP .SS \fBkb-clear-line\fP
.PP .PP
Clear input line Clear input line

View file

@ -65,6 +65,12 @@ Paste clipboard
**Default**: Control+v,Insert **Default**: Control+v,Insert
### **kb-secondary-copy**
Copy current selection to clipboard
**Default**: Control+c
### **kb-clear-line** ### **kb-clear-line**
Clear input line Clear input line

View file

@ -1501,6 +1501,8 @@ This option is only available on the \fB\fCelement-text\fR widget.
.IP \(bu 2 .IP \(bu 2
\fBplaceholder\fP: Set the displayed text (String) when nothing is entered. \fBplaceholder\fP: Set the displayed text (String) when nothing is entered.
.IP \(bu 2 .IP \(bu 2
\fBplaceholder-markup\fP: If true, placeholder text supports pango markup for stylizing.
.IP \(bu 2
\fBplaceholder-color\fP: Color of the placeholder text. \fBplaceholder-color\fP: Color of the placeholder text.
.IP \(bu 2 .IP \(bu 2
\fBblink\fP: Enable/Disable blinking on an input textbox (Boolean). \fBblink\fP: Enable/Disable blinking on an input textbox (Boolean).

View file

@ -929,6 +929,7 @@ The following properties are currently supported:
* **width**: override the desired width for the textbox. * **width**: override the desired width for the textbox.
* **content**: Set the displayed text (String). * **content**: Set the displayed text (String).
* **placeholder**: Set the displayed text (String) when nothing is entered. * **placeholder**: Set the displayed text (String) when nothing is entered.
* **placeholder-markup**: If true, placeholder text supports pango markup for stylizing.
* **placeholder-color**: Color of the placeholder text. * **placeholder-color**: Color of the placeholder text.
* **blink**: Enable/Disable blinking on an input textbox (Boolean). * **blink**: Enable/Disable blinking on an input textbox (Boolean).
* **markup**: Force markup on, beware that only valid pango markup strings are shown. * **markup**: Force markup on, beware that only valid pango markup strings are shown.

View file

@ -220,6 +220,13 @@ Dump the current active theme, in rasi format, to stdout and exit.
.PP .PP
Try to parse the file and return 0 when successful, non-zero when failed. Try to parse the file and return 0 when successful, non-zero when failed.
.PP
\fB\fC-list-keybindings\fR
.PP
List all known keybindings without trying to parse them. This can be used to
look for duplicate bindings.
.PP .PP
\fB\fC-threads\fR \fInum\fP \fB\fC-threads\fR \fInum\fP
@ -456,10 +463,10 @@ Make rofi steal focus on launch and restore close to window that held it when la
\fB\fC-refilter-timeout-limit\fR \fB\fC-refilter-timeout-limit\fR
.PP .PP
The limit of elements that is used to switch from instant to delayed filter mode. The time (in ms) boundary filter may take before switch from instant to delayed filter mode.
.PP .PP
Default: 8192 Default: 300
.PP .PP
A fallback icon can be specified for each mode: A fallback icon can be specified for each mode:
@ -959,7 +966,7 @@ Format what is being displayed for windows.
.RE .RE
.PP .PP
\fIlen\fP: maximum field length (0 for auto-size). If length and window \fIwidth\fP are negative, field length is \fIwidth - len\fP\&. \fIlen\fP: maximum field length (0 for auto-size). If length is negative, the entry will be unchanged.
.br .br
If length is positive, the entry will be truncated or padded to fill that length. If length is positive, the entry will be truncated or padded to fill that length.

View file

@ -143,6 +143,11 @@ Dump the current active theme, in rasi format, to stdout and exit.
Try to parse the file and return 0 when successful, non-zero when failed. Try to parse the file and return 0 when successful, non-zero when failed.
`-list-keybindings`
List all known keybindings without trying to parse them. This can be used to
look for duplicate bindings.
`-threads` *num* `-threads` *num*
Specify the number of threads **rofi** should use: Specify the number of threads **rofi** should use:
@ -275,9 +280,9 @@ Make rofi steal focus on launch and restore close to window that held it when la
`-refilter-timeout-limit` `-refilter-timeout-limit`
The limit of elements that is used to switch from instant to delayed filter mode. The time (in ms) boundary filter may take before switch from instant to delayed filter mode.
Default: 8192 Default: 300
A fallback icon can be specified for each mode: A fallback icon can be specified for each mode:
@ -574,7 +579,7 @@ Format what is being displayed for windows.
* **r**: role * **r**: role
* **c**: class * **c**: class
*len*: maximum field length (0 for auto-size). If length and window *width* are negative, field length is *width - len*. *len*: maximum field length (0 for auto-size). If length is negative, the entry will be unchanged.
If length is positive, the entry will be truncated or padded to fill that length. If length is positive, the entry will be truncated or padded to fill that length.

View file

@ -60,6 +60,8 @@ typedef enum {
PASTE_PRIMARY = 1, PASTE_PRIMARY = 1,
/** Paste from secondary clipboard */ /** Paste from secondary clipboard */
PASTE_SECONDARY, PASTE_SECONDARY,
/** Copy to secondary clipboard */
COPY_SECONDARY,
/** Clear the entry box. */ /** Clear the entry box. */
CLEAR_LINE, CLEAR_LINE,
/** Move to front of text */ /** Move to front of text */
@ -184,6 +186,7 @@ gboolean parse_keys_abe(NkBindings *bindings);
*/ */
void setup_abe(void); void setup_abe(void);
void abe_list_all_bindings(gboolean is_term);
/** /**
* @param name Don't have the name. * @param name Don't have the name.
* *

View file

@ -199,7 +199,10 @@ struct _rofi_view_cache_state {
/** timeout for reloading */ /** timeout for reloading */
guint refilter_timeout; guint refilter_timeout;
guint refilter_timeout_count; guint refilter_timeout_count;
/** User timeout */
double max_refilter_time;
gboolean delayed_mode;
/** timeout handling */
guint user_timeout; guint user_timeout;
}; };
extern struct _rofi_view_cache_state CacheState; extern struct _rofi_view_cache_state CacheState;

View file

@ -62,7 +62,7 @@ typedef struct {
unsigned long flags; unsigned long flags;
short cursor; short cursor;
char *text; char *text;
const char *placeholder; char *placeholder;
int show_placeholder; int show_placeholder;
PangoLayout *layout; PangoLayout *layout;
int tbft; int tbft;

View file

@ -433,7 +433,7 @@ if ( queue == NULL ) {
} else { } else {
char *str = g_markup_printf_escaped ( "Failed to open theme: <i>%s</i>\nError: <b>%s</b>", char *str = g_markup_printf_escaped ( "Failed to open theme: <i>%s</i>\nError: <b>%s</b>",
filename, strerror ( errno ) ); filename, strerror ( errno ) );
rofi_add_error_message ( g_string_new ( str ) ); rofi_add_warning_message ( g_string_new ( str ) );
g_free ( str ); g_free ( str );
g_free(filename); g_free(filename);
} }

View file

@ -2,13 +2,14 @@
DIR=$1 DIR=$1
FILE=$2 FILE=$2
GIT=$(which git) GIT=$(command -v git)
SED=$(command -v sed)
if [ -d "${DIR}/.git/" ] && [ -n "${GIT}" ] if [ -d "${DIR}/.git/" ] && [ -n "${GIT}" ]
then then
echo -n "#define GIT_VERSION \"" > "${FILE}.tmp" echo -n "#define GIT_VERSION \"" > "${FILE}.tmp"
BRTG="$(${GIT} describe --tags --always --all | sed -e 's:heads/::')" BRTG="$(${GIT} describe --tags --always --all | ${SED} -e 's:heads/::')"
REV="$(${GIT} describe --tags --always --dirty| sed -e 's:-g\([a-f0-9]\{7\}\):-git-\1:g')" REV="$(${GIT} describe --tags --always --dirty| ${SED} -e 's:-g\([a-f0-9]\{7\}\):-git-\1:g')"
echo -n "${REV} (${BRTG})" >> "${FILE}.tmp" echo -n "${REV} (${BRTG})" >> "${FILE}.tmp"
echo "\"" >> "${FILE}.tmp" echo "\"" >> "${FILE}.tmp"
else else

View file

@ -3,9 +3,9 @@
# This code is released in public domain by Dave Davenport <qball@gmpclient.org> # This code is released in public domain by Dave Davenport <qball@gmpclient.org>
# #
ROFI=$(which rofi) ROFI=$(command -v rofi)
SED=$(which sed) SED=$(command -v sed)
MKTEMP=$(which mktemp) MKTEMP=$(command -v mktemp)
if [ -z "${SED}" ] if [ -z "${SED}" ]
then then
@ -103,7 +103,7 @@ create_config_copy()
{ {
${ROFI} -dump-config > "${TMP_CONFIG_FILE}" ${ROFI} -dump-config > "${TMP_CONFIG_FILE}"
# remove theme entry. # remove theme entry.
sed -i 's/^\s*theme:\s\+".*"\s*;//g' "${TMP_CONFIG_FILE}" ${SED} -i 's/^\s*theme:\s\+".*"\s*;//g' "${TMP_CONFIG_FILE}"
} }
### ###

View file

@ -24,12 +24,11 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
*/ */
#include <glib.h>
#include "nkutils-bindings.h"
#include "rofi.h" #include "rofi.h"
#include "xrmoptions.h" #include "xrmoptions.h"
#include <glib.h>
#include <string.h> #include <string.h>
#include "nkutils-bindings.h"
typedef struct { typedef struct {
guint id; guint id;
@ -51,6 +50,10 @@ ActionBindingEntry rofi_bindings[] = {
.name = "kb-secondary-paste", .name = "kb-secondary-paste",
.binding = "Control+v,Insert", .binding = "Control+v,Insert",
.comment = "Paste clipboard"}, .comment = "Paste clipboard"},
{.id = COPY_SECONDARY,
.name = "kb-secondary-copy",
.binding = "Control+c",
.comment = "Copy to clipboard"},
{.id = CLEAR_LINE, {.id = CLEAR_LINE,
.name = "kb-clear-line", .name = "kb-clear-line",
.binding = "Control+w", .binding = "Control+w",
@ -369,6 +372,24 @@ static const gchar *mouse_default_bindings[] = {
[MOUSE_DCLICK_UP] = "!MouseDPrimary", [MOUSE_DCLICK_UP] = "!MouseDPrimary",
}; };
void abe_list_all_bindings(gboolean is_term ) {
int length = 0;
for (gsize i = 0; i < G_N_ELEMENTS(rofi_bindings); ++i) {
ActionBindingEntry *b = &rofi_bindings[i];
int sl = strlen(b->name);
length = MAX(length, sl);
}
for (gsize i = 0; i < G_N_ELEMENTS(rofi_bindings); ++i) {
ActionBindingEntry *b = &rofi_bindings[i];
if (is_term) {
printf("%s%*s%s - %s\n", color_bold,length, b->name, color_reset,b->binding);
} else {
printf("%*s - %s\n", length, b->name, b->binding);
}
}
}
void setup_abe(void) { void setup_abe(void) {
for (gsize i = 0; i < G_N_ELEMENTS(rofi_bindings); ++i) { for (gsize i = 0; i < G_N_ELEMENTS(rofi_bindings); ++i) {
ActionBindingEntry *b = &rofi_bindings[i]; ActionBindingEntry *b = &rofi_bindings[i];
@ -418,12 +439,22 @@ gboolean parse_keys_abe(NkBindings *bindings) {
if (!nk_bindings_add_binding(bindings, b->scope, entry, if (!nk_bindings_add_binding(bindings, b->scope, entry,
binding_check_action, binding_trigger_action, binding_check_action, binding_trigger_action,
GUINT_TO_POINTER(b->id), NULL, &error)) { GUINT_TO_POINTER(b->id), NULL, &error)) {
char *str = g_markup_printf_escaped( if ( error->code == NK_BINDINGS_ERROR_ALREADY_REGISTERED && error->domain == NK_BINDINGS_ERROR){
"Failed to set binding <i>%s</i> for: <i>%s (%s)</i>:\n\t<span " char *str = g_markup_printf_escaped(
"size=\"smaller\" style=\"italic\">%s</span>\n", "Failed to set binding <i>%s</i> for: <i>%s (%s)</i>:\n\t<span "
b->binding, b->comment, b->name, error->message); "size=\"smaller\" style=\"italic\">Binding `%s` is already bound.\n"
g_string_append(error_msg, str); "\tExecute <b>rofi -list-keybindings</b> to get the current list of configured bindings.</span>\n",
g_free(str); b->binding, b->comment, b->name, entry);
g_string_append(error_msg, str);
g_free(str);
} else {
char *str = g_markup_printf_escaped(
"Failed to set binding <i>%s</i> for: <i>%s (%s)</i>:\n\t<span "
"size=\"smaller\" style=\"italic\">%s</span>\n",
b->binding, b->comment, b->name, error->message);
g_string_append(error_msg, str);
g_free(str);
}
g_clear_error(&error); g_clear_error(&error);
} }
} }

View file

@ -167,9 +167,17 @@ static ModeMode combi_mode_result(Mode *sw, int mretv, char **input,
} }
if (switcher >= 0) { if (switcher >= 0) {
if (eob[0] == ' ') { if (eob[0] == ' ') {
char *n = eob + 1; char *n = g_strdup(eob + 1);
return mode_result(pd->switchers[switcher].mode, mretv, &n, ModeMode retv = mode_result(pd->switchers[switcher].mode, mretv, &n,
selected_line - pd->starts[switcher]); selected_line - pd->starts[switcher]);
g_free(n);
return retv;
} else if (eob[0] == '\0') {
char *str = NULL;
ModeMode retv = mode_result(pd->switchers[switcher].mode, mretv, &str,
selected_line - pd->starts[switcher]);
g_free(str);
return retv;
} }
return MODE_EXIT; return MODE_EXIT;
} }

View file

@ -165,7 +165,7 @@ static DmenuScriptEntry *execute_executor(Mode *sw, char *arg,
*length = 0; *length = 0;
// Reset these between runs. // Reset these between runs.
pd->new_selection = -1; pd->new_selection = -1;
pd->keep_selection = -1; pd->keep_selection = 0;
// Environment // Environment
char **env = g_get_environ(); char **env = g_get_environ();
@ -535,20 +535,15 @@ Mode *script_mode_parse_setup(const char *str) {
return sw; return sw;
} }
Mode *sw = g_malloc0(sizeof(*sw)); Mode *sw = g_malloc0(sizeof(*sw));
char *endp = NULL;
char *parse = g_strdup(str);
unsigned int index = 0; unsigned int index = 0;
const char *const sep = ":"; const char *const sep = ":";
for (char *token = strtok_r(parse, sep, &endp); token != NULL; char **tokens = g_strsplit(str, sep, 2);
token = strtok_r(NULL, sep, &endp)) { if ( tokens ){
if (index == 0) { index = g_strv_length(tokens);
sw->name = g_strdup(token); sw->name = g_strdup(tokens[0]);
} else if (index == 1) { sw->ed = (void*)rofi_expand_path(tokens[1]);
sw->ed = (void *)rofi_expand_path(token); g_strfreev(tokens);
}
index++;
} }
g_free(parse);
if (index == 2) { if (index == 2) {
sw->free = script_switcher_free; sw->free = script_switcher_free;
sw->_init = script_mode_init; sw->_init = script_mode_init;

View file

@ -294,7 +294,7 @@ window_get_attributes(xcb_window_t w) {
// _NET_WM_STATE_* // _NET_WM_STATE_*
static int client_has_state(client *c, xcb_atom_t state) { static int client_has_state(client *c, xcb_atom_t state) {
for (int i = 0; i < c->states; i++) { for (int i = 0; i < c->states; i++) {
if (c->state[i] == state) { if ((c->state[i] & state) == state) {
return 1; return 1;
} }
} }
@ -860,10 +860,7 @@ static void helper_eval_add_str(GString *str, const char *input, int l,
const char *input_nn = input ? input : ""; const char *input_nn = input ? input : "";
// Both l and max_len are in characters, not bytes. // Both l and max_len are in characters, not bytes.
int spaces = 0; int spaces = 0;
if (l == 0) { if (l > 0) {
spaces = MAX(0, max_len - nc);
g_string_append(str, input_nn);
} else {
if (nc > l) { if (nc > l) {
int bl = g_utf8_offset_to_pointer(input_nn, l) - input_nn; int bl = g_utf8_offset_to_pointer(input_nn, l) - input_nn;
char *tmp = g_markup_escape_text(input_nn, bl); char *tmp = g_markup_escape_text(input_nn, bl);
@ -875,6 +872,11 @@ static void helper_eval_add_str(GString *str, const char *input, int l,
g_string_append(str, tmp); g_string_append(str, tmp);
g_free(tmp); g_free(tmp);
} }
} else {
g_string_append(str, input_nn);
if (l == 0) {
spaces = MAX(0, max_len - nc);
}
} }
while (spaces--) { while (spaces--) {
g_string_append_c(str, ' '); g_string_append_c(str, ' ');
@ -890,9 +892,6 @@ static gboolean helper_eval_cb(const GMatchInfo *info, GString *str,
int l = 0; int l = 0;
if (match[2] == ':') { if (match[2] == ':') {
l = (int)g_ascii_strtoll(&match[3], NULL, 10); l = (int)g_ascii_strtoll(&match[3], NULL, 10);
if (l < 0) {
l = 0;
}
} }
if (match[1] == 'w') { if (match[1] == 'w') {
helper_eval_add_str(str, d->c->wmdesktopstr, l, d->pd->wmdn_len, helper_eval_add_str(str, d->c->wmdesktopstr, l, d->pd->wmdn_len,

View file

@ -36,6 +36,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sysexits.h> #include <sysexits.h>
#include <time.h> #include <time.h>
@ -323,6 +324,9 @@ static void print_main_application_options(int is_term) {
print_help_msg("-dump-theme", "", print_help_msg("-dump-theme", "",
"Dump the current theme in rasi format and exit.", NULL, "Dump the current theme in rasi format and exit.", NULL,
is_term); is_term);
print_help_msg("-list-keybindings", "",
"Print a list of current keybindings and exit.", NULL,
is_term);
} }
static void help(G_GNUC_UNUSED int argc, char **argv) { static void help(G_GNUC_UNUSED int argc, char **argv) {
int is_term = isatty(fileno(stdout)); int is_term = isatty(fileno(stdout));
@ -1045,6 +1049,11 @@ int main(int argc, char *argv[]) {
// This might clear existing errors. // This might clear existing errors.
config_parse_cmd_options(); config_parse_cmd_options();
} }
if (rofi_theme == NULL || rofi_theme->num_widgets == 0) {
g_warning("Failed to load theme. Try to load default: ");
rofi_theme_parse_string("@theme \"default\"");
}
TICK_N("Load cmd config "); TICK_N("Load cmd config ");
// Get the path to the cache dir. // Get the path to the cache dir.
@ -1117,6 +1126,11 @@ int main(int argc, char *argv[]) {
cleanup(); cleanup();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
if (find_arg("-list-keybindings") >= 0) {
int is_term = isatty(fileno(stdout));
abe_list_all_bindings(is_term);
return EXIT_SUCCESS;
}
unsigned int interval = 1; unsigned int interval = 1;
if (find_arg_uint("-record-screenshots", &interval)) { if (find_arg_uint("-record-screenshots", &interval)) {

View file

@ -78,6 +78,8 @@ struct _rofi_view_cache_state CacheState = {
.views = G_QUEUE_INIT, .views = G_QUEUE_INIT,
.refilter_timeout = 0, .refilter_timeout = 0,
.refilter_timeout_count = 0, .refilter_timeout_count = 0,
.max_refilter_time = 0.0,
.delayed_mode = FALSE,
.user_timeout = 0, .user_timeout = 0,
}; };
@ -553,6 +555,7 @@ static gboolean rofi_view_refilter_real(RofiViewState *state) {
if (state->sw == NULL) { if (state->sw == NULL) {
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
GTimer *timer = g_timer_new();
TICK_N("Filter start"); TICK_N("Filter start");
if (state->reload) { if (state->reload) {
_rofi_view_reload_row(state); _rofi_view_reload_row(state);
@ -631,6 +634,10 @@ static gboolean rofi_view_refilter_real(RofiViewState *state) {
// Cleanup + bookkeeping. // Cleanup + bookkeeping.
state->filtered_lines = j; state->filtered_lines = j;
g_free(pattern); g_free(pattern);
double elapsed = g_timer_elapsed(timer, NULL);
CacheState.max_refilter_time = elapsed;
} else { } else {
listview_set_filtered(state->list_view, FALSE); listview_set_filtered(state->list_view, FALSE);
for (unsigned int i = 0; i < state->num_lines; i++) { for (unsigned int i = 0; i < state->num_lines; i++) {
@ -673,6 +680,8 @@ static gboolean rofi_view_refilter_real(RofiViewState *state) {
state->refilter = FALSE; state->refilter = FALSE;
TICK_N("Filter done"); TICK_N("Filter done");
rofi_view_update(state, TRUE); rofi_view_update(state, TRUE);
g_timer_destroy(timer);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
void rofi_view_refilter(RofiViewState *state) { void rofi_view_refilter(RofiViewState *state) {
@ -682,12 +691,26 @@ void rofi_view_refilter(RofiViewState *state) {
g_source_remove(CacheState.refilter_timeout); g_source_remove(CacheState.refilter_timeout);
CacheState.refilter_timeout = 0; CacheState.refilter_timeout = 0;
} }
if (state->num_lines > config.refilter_timeout_limit && if (CacheState.max_refilter_time > (config.refilter_timeout_limit / 1000.0) &&
CacheState.refilter_timeout_count < 25 && state->text && state->text && strlen(state->text->text) > 0 &&
strlen(state->text->text) > 0) { CacheState.refilter_timeout_count < 25) {
if (CacheState.delayed_mode == FALSE) {
g_warning(
"Filtering took %f seconds ( %f ), switching to delayed filter\n",
CacheState.max_refilter_time, config.refilter_timeout_limit / 1000.0);
CacheState.delayed_mode = TRUE;
}
CacheState.refilter_timeout = CacheState.refilter_timeout =
g_timeout_add(200, (GSourceFunc)rofi_view_refilter_real, state); g_timeout_add(200, (GSourceFunc)rofi_view_refilter_real, state);
} else { } else {
if (CacheState.delayed_mode == TRUE && state->text &&
strlen(state->text->text) > 0 &&
CacheState.refilter_timeout_count < 25) {
g_warning(
"Filtering took %f seconds , switching back to instant filter\n",
CacheState.max_refilter_time);
CacheState.delayed_mode = FALSE;
}
rofi_view_refilter_real(state); rofi_view_refilter_real(state);
} }
} }
@ -758,6 +781,21 @@ static void rofi_view_trigger_global_action(KeyBindingAction action) {
} }
#endif #endif
break; break;
case COPY_SECONDARY: {
char *data = NULL;
unsigned int selected = listview_get_selected(state->list_view);
if (selected < state->filtered_lines) {
data = mode_get_completion(state->sw, state->line_map[selected]);
} else if (state->text && state->text->text) {
data = g_strdup(state->text->text);
}
if (data) {
xcb_stuff_set_clipboard(data);
xcb_set_selection_owner(xcb->connection, CacheState.main_window,
netatoms[CLIPBOARD], XCB_CURRENT_TIME);
xcb_flush(xcb->connection);
}
} break;
case SCREENSHOT: case SCREENSHOT:
rofi_capture_screenshot(); rofi_capture_screenshot();
break; break;

View file

@ -583,13 +583,20 @@ unsigned int listview_get_selected(listview *lv) {
} }
void listview_set_selected(listview *lv, unsigned int selected) { void listview_set_selected(listview *lv, unsigned int selected) {
if (lv && lv->req_elements > 0) { if (lv == NULL) {
return;
}
if (lv->req_elements > 0) {
lv->selected = MIN(selected, lv->req_elements - 1); lv->selected = MIN(selected, lv->req_elements - 1);
lv->barview.direction = LEFT_TO_RIGHT; lv->barview.direction = LEFT_TO_RIGHT;
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
} else if (lv->req_elements == 0) { } else if (lv->req_elements == 0) {
lv->sc_callback(lv, UINT32_MAX, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, UINT32_MAX, lv->sc_udata);
}
} }
} }
@ -790,7 +797,9 @@ static void listview_nav_up_int(listview *lv) {
lv->selected--; lv->selected--;
lv->barview.direction = RIGHT_TO_LEFT; lv->barview.direction = RIGHT_TO_LEFT;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }
static void listview_nav_down_int(listview *lv) { static void listview_nav_down_int(listview *lv) {
@ -805,7 +814,9 @@ static void listview_nav_down_int(listview *lv) {
? MIN(lv->req_elements - 1, lv->selected + 1) ? MIN(lv->req_elements - 1, lv->selected + 1)
: 0; : 0;
lv->barview.direction = LEFT_TO_RIGHT; lv->barview.direction = LEFT_TO_RIGHT;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }
void listview_nav_next(listview *lv) { void listview_nav_next(listview *lv) {
@ -824,14 +835,18 @@ void listview_nav_prev(listview *lv) {
static void listview_nav_column_left_int(listview *lv) { static void listview_nav_column_left_int(listview *lv) {
if (lv->selected >= lv->cur_columns) { if (lv->selected >= lv->cur_columns) {
lv->selected -= lv->cur_columns; lv->selected -= lv->cur_columns;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }
} }
static void listview_nav_column_right_int(listview *lv) { static void listview_nav_column_right_int(listview *lv) {
if ((lv->selected + lv->cur_columns) < lv->req_elements) { if ((lv->selected + lv->cur_columns) < lv->req_elements) {
lv->selected += lv->cur_columns; lv->selected += lv->cur_columns;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }
} }
@ -890,7 +905,9 @@ void listview_nav_left(listview *lv) {
} }
if (lv->selected >= lv->max_rows) { if (lv->selected >= lv->max_rows) {
lv->selected -= lv->max_rows; lv->selected -= lv->max_rows;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }
} }
@ -911,7 +928,9 @@ void listview_nav_right(listview *lv) {
} }
if ((lv->selected + lv->max_rows) < lv->req_elements) { if ((lv->selected + lv->max_rows) < lv->req_elements) {
lv->selected += lv->max_rows; lv->selected += lv->max_rows;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} else if (lv->selected < (lv->req_elements - 1)) { } else if (lv->selected < (lv->req_elements - 1)) {
// We do not want to move to last item, UNLESS the last column is only // We do not want to move to last item, UNLESS the last column is only
@ -923,7 +942,9 @@ void listview_nav_right(listview *lv) {
// If there is an extra column, move. // If there is an extra column, move.
if (col != ncol) { if (col != ncol) {
lv->selected = lv->req_elements - 1; lv->selected = lv->req_elements - 1;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }
} }
@ -949,7 +970,9 @@ static void listview_nav_page_prev_int(listview *lv) {
} else { } else {
lv->selected -= (lv->max_elements); lv->selected -= (lv->max_elements);
} }
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }
static void listview_nav_page_next_int(listview *lv) { static void listview_nav_page_next_int(listview *lv) {
@ -964,7 +987,9 @@ static void listview_nav_page_next_int(listview *lv) {
lv->selected = MIN(new, lv->req_elements - 1); lv->selected = MIN(new, lv->req_elements - 1);
lv->barview.direction = LEFT_TO_RIGHT; lv->barview.direction = LEFT_TO_RIGHT;
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
return; return;
} }
@ -972,7 +997,9 @@ static void listview_nav_page_next_int(listview *lv) {
if (lv->selected >= lv->req_elements) { if (lv->selected >= lv->req_elements) {
lv->selected = lv->req_elements - 1; lv->selected = lv->req_elements - 1;
} }
lv->sc_callback(lv, lv->selected, lv->sc_udata); if (lv->sc_callback) {
lv->sc_callback(lv, lv->selected, lv->sc_udata);
}
widget_queue_redraw(WIDGET(lv)); widget_queue_redraw(WIDGET(lv));
} }

View file

@ -226,7 +226,11 @@ textbox *textbox_create(widget *parent, WidgetType type, const char *name,
const char *placeholder = const char *placeholder =
rofi_theme_get_string(WIDGET(tb), "placeholder", NULL); rofi_theme_get_string(WIDGET(tb), "placeholder", NULL);
if (placeholder) { if (placeholder) {
tb->placeholder = placeholder; if (rofi_theme_get_boolean(WIDGET(tb), "placeholder-markup", FALSE)) {
tb->placeholder = g_strdup(placeholder);
} else {
tb->placeholder = g_markup_escape_text(placeholder, -1);
}
} }
textbox_text(tb, txt ? txt : ""); textbox_text(tb, txt ? txt : "");
textbox_cursor_end(tb); textbox_cursor_end(tb);
@ -309,7 +313,7 @@ static void __textbox_update_pango_text(textbox *tb) {
pango_layout_set_attributes(tb->layout, NULL); pango_layout_set_attributes(tb->layout, NULL);
if (tb->placeholder && (tb->text == NULL || tb->text[0] == 0)) { if (tb->placeholder && (tb->text == NULL || tb->text[0] == 0)) {
tb->show_placeholder = TRUE; tb->show_placeholder = TRUE;
pango_layout_set_text(tb->layout, tb->placeholder, -1); pango_layout_set_markup(tb->layout, tb->placeholder, -1);
return; return;
} }
tb->show_placeholder = FALSE; tb->show_placeholder = FALSE;
@ -441,6 +445,7 @@ static void textbox_free(widget *wid) {
} }
g_free(tb->text); g_free(tb->text);
g_free(tb->placeholder);
if (tb->layout != NULL) { if (tb->layout != NULL) {
g_object_unref(tb->layout); g_object_unref(tb->layout);
} }

View file

@ -837,6 +837,8 @@ static void xcb_rofi_view_hide(void) {
} }
static void xcb_rofi_view_cleanup() { static void xcb_rofi_view_cleanup() {
// Clear clipboard data.
xcb_stuff_set_clipboard(NULL);
g_debug("Cleanup."); g_debug("Cleanup.");
if (XcbState.idle_timeout > 0) { if (XcbState.idle_timeout > 0) {
g_source_remove(XcbState.idle_timeout); g_source_remove(XcbState.idle_timeout);

View file

@ -426,8 +426,8 @@ static XrmOption xrmOptions[] = {
"refilter-timeout-limit", "refilter-timeout-limit",
{.num = &(config.refilter_timeout_limit)}, {.num = &(config.refilter_timeout_limit)},
NULL, NULL,
"When there are more entries then this limit, only refilter after a " "When filtering takes more then this time (in ms) switch to delayed "
"timeout.", "filter.",
CONFIG_DEFAULT}, CONFIG_DEFAULT},
{xrm_Boolean, {xrm_Boolean,
"xserver-i300-workaround", "xserver-i300-workaround",

@ -1 +1 @@
Subproject commit 555fa6df92434c1c3c7548b5a583b1d8ec3fabb3 Subproject commit 42a145150cff135be377754486c504836ddea836

@ -1 +1 @@
Subproject commit d08fa898d71da4c11653284968ec14384dd70b6a Subproject commit b39df45e80fa6bcb40b1be8266d9d9b06854e19b

View file

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

View file

@ -1327,11 +1327,11 @@ START_TEST(test_import_error) {
const char *errstr = "Failed to open theme: <i>/non-existing-file.rasi</i>\n" const char *errstr = "Failed to open theme: <i>/non-existing-file.rasi</i>\n"
"Error: <b>No such file or directory</b>"; "Error: <b>No such file or directory</b>";
ck_assert_int_eq(error, 1); ck_assert_int_eq(warning, 1);
ck_assert_str_eq(error_msg->str, errstr); ck_assert_str_eq(warning_msg->str, errstr);
g_string_free(error_msg, TRUE); g_string_free(warning_msg, TRUE);
error_msg = NULL; warning_msg = NULL;
error = 0; warning = 0;
} }
END_TEST END_TEST
START_TEST(test_prepare_array) { START_TEST(test_prepare_array) {