mirror of
https://github.com/lbonn/rofi
synced 2024-11-26 05:40:23 +00:00
Merge remote-tracking branch 'upstream/next' into wayland
This commit is contained in:
commit
d44b81e778
30 changed files with 265 additions and 86 deletions
38
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
38
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -9,28 +9,52 @@ body:
|
|||
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.
|
||||
|
||||
If you feel like you “it is simple and requires no explanation”, please consider you’re 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 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 feel like you “it is simple and requires no explanation”, please
|
||||
consider you’re 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
|
||||
attributes:
|
||||
label: "Rofi version (rofi -v)"
|
||||
placeholder: "Version: 1.6.0"
|
||||
placeholder: "Version: 1.7.5"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
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"
|
||||
validations:
|
||||
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
|
||||
attributes:
|
||||
label: "Launch command"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# Please match the documentation and example scripts to the version of rofi used:
|
||||
|
||||
* [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.3](https://github.com/davatorium/rofi/tree/1.7.3)
|
||||
* [1.7.2](https://github.com/davatorium/rofi/tree/1.7.2)
|
||||
|
|
|
@ -154,8 +154,8 @@ Settings config = {
|
|||
.steal_focus = FALSE,
|
||||
/** fallback icon */
|
||||
.application_fallback_icon = NULL,
|
||||
/** refilter limit */
|
||||
.refilter_timeout_limit = 8192,
|
||||
/** refilter limit in ms*/
|
||||
.refilter_timeout_limit = 300,
|
||||
/** workaround for broken xserver (#300 on xserver, #611) */
|
||||
.xserver_i300_workaround = FALSE,
|
||||
};
|
||||
|
|
|
@ -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_HEADER([config.h])
|
||||
|
|
|
@ -96,6 +96,13 @@ Paste clipboard
|
|||
.PP
|
||||
\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
|
||||
.PP
|
||||
Clear input line
|
||||
|
|
|
@ -65,6 +65,12 @@ Paste clipboard
|
|||
|
||||
**Default**: Control+v,Insert
|
||||
|
||||
### **kb-secondary-copy**
|
||||
|
||||
Copy current selection to clipboard
|
||||
|
||||
**Default**: Control+c
|
||||
|
||||
### **kb-clear-line**
|
||||
Clear input line
|
||||
|
||||
|
|
|
@ -1501,6 +1501,8 @@ This option is only available on the \fB\fCelement-text\fR widget.
|
|||
.IP \(bu 2
|
||||
\fBplaceholder\fP: Set the displayed text (String) when nothing is entered.
|
||||
.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.
|
||||
.IP \(bu 2
|
||||
\fBblink\fP: Enable/Disable blinking on an input textbox (Boolean).
|
||||
|
|
|
@ -929,6 +929,7 @@ The following properties are currently supported:
|
|||
* **width**: override the desired width for the textbox.
|
||||
* **content**: Set the displayed text (String).
|
||||
* **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.
|
||||
* **blink**: Enable/Disable blinking on an input textbox (Boolean).
|
||||
* **markup**: Force markup on, beware that only valid pango markup strings are shown.
|
||||
|
|
13
doc/rofi.1
13
doc/rofi.1
|
@ -220,6 +220,13 @@ Dump the current active theme, in rasi format, to stdout and exit.
|
|||
.PP
|
||||
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
|
||||
\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
|
||||
|
||||
.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
|
||||
Default: 8192
|
||||
Default: 300
|
||||
|
||||
.PP
|
||||
A fallback icon can be specified for each mode:
|
||||
|
@ -959,7 +966,7 @@ Format what is being displayed for windows.
|
|||
.RE
|
||||
|
||||
.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
|
||||
If length is positive, the entry will be truncated or padded to fill that length.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
`-list-keybindings`
|
||||
|
||||
List all known keybindings without trying to parse them. This can be used to
|
||||
look for duplicate bindings.
|
||||
|
||||
`-threads` *num*
|
||||
|
||||
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`
|
||||
|
||||
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:
|
||||
|
||||
|
@ -574,7 +579,7 @@ Format what is being displayed for windows.
|
|||
* **r**: role
|
||||
* **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.
|
||||
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ typedef enum {
|
|||
PASTE_PRIMARY = 1,
|
||||
/** Paste from secondary clipboard */
|
||||
PASTE_SECONDARY,
|
||||
/** Copy to secondary clipboard */
|
||||
COPY_SECONDARY,
|
||||
/** Clear the entry box. */
|
||||
CLEAR_LINE,
|
||||
/** Move to front of text */
|
||||
|
@ -184,6 +186,7 @@ gboolean parse_keys_abe(NkBindings *bindings);
|
|||
*/
|
||||
void setup_abe(void);
|
||||
|
||||
void abe_list_all_bindings(gboolean is_term);
|
||||
/**
|
||||
* @param name Don't have the name.
|
||||
*
|
||||
|
|
|
@ -199,7 +199,10 @@ struct _rofi_view_cache_state {
|
|||
/** timeout for reloading */
|
||||
guint refilter_timeout;
|
||||
guint refilter_timeout_count;
|
||||
/** User timeout */
|
||||
|
||||
double max_refilter_time;
|
||||
gboolean delayed_mode;
|
||||
/** timeout handling */
|
||||
guint user_timeout;
|
||||
};
|
||||
extern struct _rofi_view_cache_state CacheState;
|
||||
|
|
|
@ -62,7 +62,7 @@ typedef struct {
|
|||
unsigned long flags;
|
||||
short cursor;
|
||||
char *text;
|
||||
const char *placeholder;
|
||||
char *placeholder;
|
||||
int show_placeholder;
|
||||
PangoLayout *layout;
|
||||
int tbft;
|
||||
|
|
|
@ -433,7 +433,7 @@ if ( queue == NULL ) {
|
|||
} else {
|
||||
char *str = g_markup_printf_escaped ( "Failed to open theme: <i>%s</i>\nError: <b>%s</b>",
|
||||
filename, strerror ( errno ) );
|
||||
rofi_add_error_message ( g_string_new ( str ) );
|
||||
rofi_add_warning_message ( g_string_new ( str ) );
|
||||
g_free ( str );
|
||||
g_free(filename);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
|
||||
DIR=$1
|
||||
FILE=$2
|
||||
GIT=$(which git)
|
||||
GIT=$(command -v git)
|
||||
SED=$(command -v sed)
|
||||
|
||||
if [ -d "${DIR}/.git/" ] && [ -n "${GIT}" ]
|
||||
then
|
||||
echo -n "#define GIT_VERSION \"" > "${FILE}.tmp"
|
||||
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')"
|
||||
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')"
|
||||
echo -n "${REV} (${BRTG})" >> "${FILE}.tmp"
|
||||
echo "\"" >> "${FILE}.tmp"
|
||||
else
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
# This code is released in public domain by Dave Davenport <qball@gmpclient.org>
|
||||
#
|
||||
|
||||
ROFI=$(which rofi)
|
||||
SED=$(which sed)
|
||||
MKTEMP=$(which mktemp)
|
||||
ROFI=$(command -v rofi)
|
||||
SED=$(command -v sed)
|
||||
MKTEMP=$(command -v mktemp)
|
||||
|
||||
if [ -z "${SED}" ]
|
||||
then
|
||||
|
@ -103,7 +103,7 @@ create_config_copy()
|
|||
{
|
||||
${ROFI} -dump-config > "${TMP_CONFIG_FILE}"
|
||||
# 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}"
|
||||
}
|
||||
|
||||
###
|
||||
|
|
|
@ -24,12 +24,11 @@
|
|||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include "nkutils-bindings.h"
|
||||
#include "rofi.h"
|
||||
#include "xrmoptions.h"
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include "nkutils-bindings.h"
|
||||
|
||||
typedef struct {
|
||||
guint id;
|
||||
|
@ -51,6 +50,10 @@ ActionBindingEntry rofi_bindings[] = {
|
|||
.name = "kb-secondary-paste",
|
||||
.binding = "Control+v,Insert",
|
||||
.comment = "Paste clipboard"},
|
||||
{.id = COPY_SECONDARY,
|
||||
.name = "kb-secondary-copy",
|
||||
.binding = "Control+c",
|
||||
.comment = "Copy to clipboard"},
|
||||
{.id = CLEAR_LINE,
|
||||
.name = "kb-clear-line",
|
||||
.binding = "Control+w",
|
||||
|
@ -369,6 +372,24 @@ static const gchar *mouse_default_bindings[] = {
|
|||
[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) {
|
||||
for (gsize i = 0; i < G_N_ELEMENTS(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,
|
||||
binding_check_action, binding_trigger_action,
|
||||
GUINT_TO_POINTER(b->id), NULL, &error)) {
|
||||
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);
|
||||
if ( error->code == NK_BINDINGS_ERROR_ALREADY_REGISTERED && error->domain == NK_BINDINGS_ERROR){
|
||||
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\">Binding `%s` is already bound.\n"
|
||||
"\tExecute <b>rofi -list-keybindings</b> to get the current list of configured bindings.</span>\n",
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,9 +167,17 @@ static ModeMode combi_mode_result(Mode *sw, int mretv, char **input,
|
|||
}
|
||||
if (switcher >= 0) {
|
||||
if (eob[0] == ' ') {
|
||||
char *n = eob + 1;
|
||||
return mode_result(pd->switchers[switcher].mode, mretv, &n,
|
||||
selected_line - pd->starts[switcher]);
|
||||
char *n = g_strdup(eob + 1);
|
||||
ModeMode retv = mode_result(pd->switchers[switcher].mode, mretv, &n,
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ static DmenuScriptEntry *execute_executor(Mode *sw, char *arg,
|
|||
*length = 0;
|
||||
// Reset these between runs.
|
||||
pd->new_selection = -1;
|
||||
pd->keep_selection = -1;
|
||||
pd->keep_selection = 0;
|
||||
// Environment
|
||||
char **env = g_get_environ();
|
||||
|
||||
|
@ -535,20 +535,15 @@ Mode *script_mode_parse_setup(const char *str) {
|
|||
return sw;
|
||||
}
|
||||
Mode *sw = g_malloc0(sizeof(*sw));
|
||||
char *endp = NULL;
|
||||
char *parse = g_strdup(str);
|
||||
unsigned int index = 0;
|
||||
const char *const sep = ":";
|
||||
for (char *token = strtok_r(parse, sep, &endp); token != NULL;
|
||||
token = strtok_r(NULL, sep, &endp)) {
|
||||
if (index == 0) {
|
||||
sw->name = g_strdup(token);
|
||||
} else if (index == 1) {
|
||||
sw->ed = (void *)rofi_expand_path(token);
|
||||
}
|
||||
index++;
|
||||
char **tokens = g_strsplit(str, sep, 2);
|
||||
if ( tokens ){
|
||||
index = g_strv_length(tokens);
|
||||
sw->name = g_strdup(tokens[0]);
|
||||
sw->ed = (void*)rofi_expand_path(tokens[1]);
|
||||
g_strfreev(tokens);
|
||||
}
|
||||
g_free(parse);
|
||||
if (index == 2) {
|
||||
sw->free = script_switcher_free;
|
||||
sw->_init = script_mode_init;
|
||||
|
|
|
@ -294,7 +294,7 @@ window_get_attributes(xcb_window_t w) {
|
|||
// _NET_WM_STATE_*
|
||||
static int client_has_state(client *c, xcb_atom_t state) {
|
||||
for (int i = 0; i < c->states; i++) {
|
||||
if (c->state[i] == state) {
|
||||
if ((c->state[i] & state) == state) {
|
||||
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 : "";
|
||||
// Both l and max_len are in characters, not bytes.
|
||||
int spaces = 0;
|
||||
if (l == 0) {
|
||||
spaces = MAX(0, max_len - nc);
|
||||
g_string_append(str, input_nn);
|
||||
} else {
|
||||
if (l > 0) {
|
||||
if (nc > l) {
|
||||
int bl = g_utf8_offset_to_pointer(input_nn, l) - input_nn;
|
||||
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_free(tmp);
|
||||
}
|
||||
} else {
|
||||
g_string_append(str, input_nn);
|
||||
if (l == 0) {
|
||||
spaces = MAX(0, max_len - nc);
|
||||
}
|
||||
}
|
||||
while (spaces--) {
|
||||
g_string_append_c(str, ' ');
|
||||
|
@ -890,9 +892,6 @@ static gboolean helper_eval_cb(const GMatchInfo *info, GString *str,
|
|||
int l = 0;
|
||||
if (match[2] == ':') {
|
||||
l = (int)g_ascii_strtoll(&match[3], NULL, 10);
|
||||
if (l < 0) {
|
||||
l = 0;
|
||||
}
|
||||
}
|
||||
if (match[1] == 'w') {
|
||||
helper_eval_add_str(str, d->c->wmdesktopstr, l, d->pd->wmdn_len,
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sysexits.h>
|
||||
#include <time.h>
|
||||
|
@ -323,6 +324,9 @@ static void print_main_application_options(int is_term) {
|
|||
print_help_msg("-dump-theme", "",
|
||||
"Dump the current theme in rasi format and exit.", NULL,
|
||||
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) {
|
||||
int is_term = isatty(fileno(stdout));
|
||||
|
@ -1045,6 +1049,11 @@ int main(int argc, char *argv[]) {
|
|||
// This might clear existing errors.
|
||||
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 ");
|
||||
|
||||
// Get the path to the cache dir.
|
||||
|
@ -1117,6 +1126,11 @@ int main(int argc, char *argv[]) {
|
|||
cleanup();
|
||||
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;
|
||||
if (find_arg_uint("-record-screenshots", &interval)) {
|
||||
|
|
|
@ -78,6 +78,8 @@ struct _rofi_view_cache_state CacheState = {
|
|||
.views = G_QUEUE_INIT,
|
||||
.refilter_timeout = 0,
|
||||
.refilter_timeout_count = 0,
|
||||
.max_refilter_time = 0.0,
|
||||
.delayed_mode = FALSE,
|
||||
.user_timeout = 0,
|
||||
};
|
||||
|
||||
|
@ -553,6 +555,7 @@ static gboolean rofi_view_refilter_real(RofiViewState *state) {
|
|||
if (state->sw == NULL) {
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
GTimer *timer = g_timer_new();
|
||||
TICK_N("Filter start");
|
||||
if (state->reload) {
|
||||
_rofi_view_reload_row(state);
|
||||
|
@ -631,6 +634,10 @@ static gboolean rofi_view_refilter_real(RofiViewState *state) {
|
|||
// Cleanup + bookkeeping.
|
||||
state->filtered_lines = j;
|
||||
g_free(pattern);
|
||||
|
||||
double elapsed = g_timer_elapsed(timer, NULL);
|
||||
|
||||
CacheState.max_refilter_time = elapsed;
|
||||
} else {
|
||||
listview_set_filtered(state->list_view, FALSE);
|
||||
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;
|
||||
TICK_N("Filter done");
|
||||
rofi_view_update(state, TRUE);
|
||||
|
||||
g_timer_destroy(timer);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
void rofi_view_refilter(RofiViewState *state) {
|
||||
|
@ -682,12 +691,26 @@ void rofi_view_refilter(RofiViewState *state) {
|
|||
g_source_remove(CacheState.refilter_timeout);
|
||||
CacheState.refilter_timeout = 0;
|
||||
}
|
||||
if (state->num_lines > config.refilter_timeout_limit &&
|
||||
CacheState.refilter_timeout_count < 25 && state->text &&
|
||||
strlen(state->text->text) > 0) {
|
||||
if (CacheState.max_refilter_time > (config.refilter_timeout_limit / 1000.0) &&
|
||||
state->text && 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 =
|
||||
g_timeout_add(200, (GSourceFunc)rofi_view_refilter_real, state);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
@ -758,6 +781,21 @@ static void rofi_view_trigger_global_action(KeyBindingAction action) {
|
|||
}
|
||||
#endif
|
||||
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:
|
||||
rofi_capture_screenshot();
|
||||
break;
|
||||
|
|
|
@ -583,13 +583,20 @@ unsigned int listview_get_selected(listview *lv) {
|
|||
}
|
||||
|
||||
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->barview.direction = LEFT_TO_RIGHT;
|
||||
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) {
|
||||
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->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));
|
||||
}
|
||||
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)
|
||||
: 0;
|
||||
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));
|
||||
}
|
||||
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) {
|
||||
if (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));
|
||||
}
|
||||
}
|
||||
static void listview_nav_column_right_int(listview *lv) {
|
||||
if ((lv->selected + lv->cur_columns) < lv->req_elements) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -890,7 +905,9 @@ void listview_nav_left(listview *lv) {
|
|||
}
|
||||
if (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));
|
||||
}
|
||||
}
|
||||
|
@ -911,7 +928,9 @@ void listview_nav_right(listview *lv) {
|
|||
}
|
||||
if ((lv->selected + lv->max_rows) < lv->req_elements) {
|
||||
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));
|
||||
} else if (lv->selected < (lv->req_elements - 1)) {
|
||||
// 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 (col != ncol) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -949,7 +970,9 @@ static void listview_nav_page_prev_int(listview *lv) {
|
|||
} else {
|
||||
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));
|
||||
}
|
||||
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->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));
|
||||
return;
|
||||
}
|
||||
|
@ -972,7 +997,9 @@ static void listview_nav_page_next_int(listview *lv) {
|
|||
if (lv->selected >= lv->req_elements) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -226,7 +226,11 @@ textbox *textbox_create(widget *parent, WidgetType type, const char *name,
|
|||
const char *placeholder =
|
||||
rofi_theme_get_string(WIDGET(tb), "placeholder", NULL);
|
||||
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_cursor_end(tb);
|
||||
|
@ -309,7 +313,7 @@ static void __textbox_update_pango_text(textbox *tb) {
|
|||
pango_layout_set_attributes(tb->layout, NULL);
|
||||
if (tb->placeholder && (tb->text == NULL || tb->text[0] == 0)) {
|
||||
tb->show_placeholder = TRUE;
|
||||
pango_layout_set_text(tb->layout, tb->placeholder, -1);
|
||||
pango_layout_set_markup(tb->layout, tb->placeholder, -1);
|
||||
return;
|
||||
}
|
||||
tb->show_placeholder = FALSE;
|
||||
|
@ -441,6 +445,7 @@ static void textbox_free(widget *wid) {
|
|||
}
|
||||
g_free(tb->text);
|
||||
|
||||
g_free(tb->placeholder);
|
||||
if (tb->layout != NULL) {
|
||||
g_object_unref(tb->layout);
|
||||
}
|
||||
|
|
|
@ -837,6 +837,8 @@ static void xcb_rofi_view_hide(void) {
|
|||
}
|
||||
|
||||
static void xcb_rofi_view_cleanup() {
|
||||
// Clear clipboard data.
|
||||
xcb_stuff_set_clipboard(NULL);
|
||||
g_debug("Cleanup.");
|
||||
if (XcbState.idle_timeout > 0) {
|
||||
g_source_remove(XcbState.idle_timeout);
|
||||
|
|
|
@ -426,8 +426,8 @@ static XrmOption xrmOptions[] = {
|
|||
"refilter-timeout-limit",
|
||||
{.num = &(config.refilter_timeout_limit)},
|
||||
NULL,
|
||||
"When there are more entries then this limit, only refilter after a "
|
||||
"timeout.",
|
||||
"When filtering takes more then this time (in ms) switch to delayed "
|
||||
"filter.",
|
||||
CONFIG_DEFAULT},
|
||||
{xrm_Boolean,
|
||||
"xserver-i300-workaround",
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 555fa6df92434c1c3c7548b5a583b1d8ec3fabb3
|
||||
Subproject commit 42a145150cff135be377754486c504836ddea836
|
|
@ -1 +1 @@
|
|||
Subproject commit d08fa898d71da4c11653284968ec14384dd70b6a
|
||||
Subproject commit b39df45e80fa6bcb40b1be8266d9d9b06854e19b
|
|
@ -126,7 +126,7 @@ END_TEST
|
|||
|
||||
START_TEST(test_mode_num_items) {
|
||||
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++) {
|
||||
int state = 0;
|
||||
GList *list = NULL;
|
||||
|
|
|
@ -1327,11 +1327,11 @@ START_TEST(test_import_error) {
|
|||
|
||||
const char *errstr = "Failed to open theme: <i>/non-existing-file.rasi</i>\n"
|
||||
"Error: <b>No such file or directory</b>";
|
||||
ck_assert_int_eq(error, 1);
|
||||
ck_assert_str_eq(error_msg->str, errstr);
|
||||
g_string_free(error_msg, TRUE);
|
||||
error_msg = NULL;
|
||||
error = 0;
|
||||
ck_assert_int_eq(warning, 1);
|
||||
ck_assert_str_eq(warning_msg->str, errstr);
|
||||
g_string_free(warning_msg, TRUE);
|
||||
warning_msg = NULL;
|
||||
warning = 0;
|
||||
}
|
||||
END_TEST
|
||||
START_TEST(test_prepare_array) {
|
||||
|
|
Loading…
Reference in a new issue