rofi 2.1.0
view.c
Go to the documentation of this file.
1/*
2 * rofi
3 *
4 * MIT/X11 License
5 * Copyright © 2013-2023 Qball Cow <qball@gmpclient.org>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
29#define G_LOG_DOMAIN "View"
30
31#include <config.h>
32#include <locale.h>
33#include <signal.h>
34#include <stdint.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <time.h>
39#include <unistd.h>
40
41#include <glib.h>
42
43#include "rofi.h"
44
45#include "settings.h"
46#include "timings.h"
47
48#include "display.h"
49#include "helper-theme.h"
50#include "helper.h"
51#include "mode.h"
52
53#include "view-internal.h"
54#include "view.h"
55
56#include "theme.h"
57
58#ifdef ENABLE_XCB
59#include "xcb-internal.h"
60#include "xcb.h"
61#else
62#include "xcb-dummy.h"
63#endif
64
65static const view_proxy *proxy;
66
67void view_init(const view_proxy *view_in) { proxy = view_in; }
68
70GThreadPool *tpool = NULL;
71
74
76 .main_window = XCB_WINDOW_NONE,
77 .flags = MENU_NORMAL,
78 .views = G_QUEUE_INIT,
79 .refilter_timeout = 0,
80 .refilter_timeout_count = 0,
81 .max_refilter_time = 0.0,
82 .delayed_mode = FALSE,
83 .user_timeout = 0,
84 .overlay_timeout = 0,
85 .entry_history_enable = TRUE,
86 .entry_history = NULL,
87 .entry_history_length = 0,
88 .entry_history_index = 0,
89};
90
91static char *get_matching_state(RofiViewState *state) {
92 if (state->case_sensitive) {
93 if (config.sort) {
94 return "±";
95 } else {
96 return "-";
97 }
98 } else {
99 if (config.sort) {
100 return "+";
101 }
102 }
103 return " ";
104}
105
109static int lev_sort(const void *p1, const void *p2, void *arg) {
110 const int *a = p1;
111 const int *b = p2;
112 int *distances = arg;
113
114 return distances[*a] - distances[*b];
115}
116
124static int fzf_v2_sort(const void *p1, const void *p2, void *arg) {
125 const unsigned int *a = p1;
126 const unsigned int *b = p2;
127 int *distances = arg;
128 int d = distances[*a] - distances[*b];
129
130 if (d != 0) {
131 return d;
132 }
133 if (*a != *b) {
134 return *a < *b ? -1 : 1;
135 }
136 return 0;
137}
138
139static void screenshot_taken_user_callback(const char *path) {
140 if (config.on_screenshot_taken == NULL)
141 return;
142
143 char **args = NULL;
144 int argv = 0;
145 helper_parse_setup(config.on_screenshot_taken, &args, &argv, "{path}", path,
146 (char *)0);
147 if (args != NULL)
148 helper_execute(NULL, args, "", config.on_screenshot_taken, NULL);
149}
150
156 if (state == NULL || state->main_window == NULL) {
157 g_warning("Nothing to screenshot.");
158 return;
159 }
160 const char *outp = g_getenv("ROFI_PNG_OUTPUT");
161 const char *xdg_pict_dir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
162 if (outp == NULL && xdg_pict_dir == NULL) {
163 g_warning("XDG user picture directory or ROFI_PNG_OUTPUT is not set. "
164 "Cannot store screenshot.");
165 return;
166 }
167 // Get current time.
168 GDateTime *now = g_date_time_new_now_local();
169 // Format filename.
170 char *timestmp = g_date_time_format(now, "rofi-%Y-%m-%d-%H%M");
171 char *filename = g_strdup_printf("%s-%05d.png", timestmp, 0);
172 // Build full path
173 char *fpath = NULL;
174 if (outp == NULL) {
175 int index = 0;
176 fpath = g_build_filename(xdg_pict_dir, filename, NULL);
177 while (g_file_test(fpath, G_FILE_TEST_EXISTS) && index < 99999) {
178 g_free(fpath);
179 g_free(filename);
180 // Try the next index.
181 index++;
182 // Format filename.
183 filename = g_strdup_printf("%s-%05d.png", timestmp, index);
184 // Build full path
185 fpath = g_build_filename(xdg_pict_dir, filename, NULL);
186 }
187 } else {
188 fpath = g_strdup(outp);
189 }
190 fprintf(stderr, color_green "Storing screenshot %s\n" color_reset, fpath);
191 cairo_surface_t *surf = cairo_image_surface_create(
192 CAIRO_FORMAT_ARGB32, state->width, state->height);
193 cairo_status_t status = cairo_surface_status(surf);
194 if (status != CAIRO_STATUS_SUCCESS) {
195 g_warning("Failed to produce screenshot '%s', got error: '%s'", fpath,
196 cairo_status_to_string(status));
197 } else {
198 cairo_t *draw = cairo_create(surf);
199 status = cairo_status(draw);
200 if (status != CAIRO_STATUS_SUCCESS) {
201 g_warning("Failed to produce screenshot '%s', got error: '%s'", fpath,
202 cairo_status_to_string(status));
203 } else {
204 widget_draw(WIDGET(state->main_window), draw);
205 status = cairo_surface_write_to_png(surf, fpath);
206 if (status != CAIRO_STATUS_SUCCESS) {
207 g_warning("Failed to produce screenshot '%s', got error: '%s'", fpath,
208 cairo_status_to_string(status));
209 }
211 }
212 cairo_destroy(draw);
213 }
214 // Cleanup
215 cairo_surface_destroy(surf);
216 g_free(fpath);
217 g_free(filename);
218 g_free(timestmp);
219 g_date_time_unref(now);
220}
221
223 if (state->prompt) {
224 const char *str = mode_get_display_name(state->sw);
225 textbox_text(state->prompt, str);
226 }
227}
228
229extern GList *list_of_warning_msgs;
231 if (state->mesg_box == NULL) {
232 return;
233 }
234 char *msg = mode_get_message(state->sw);
235 if (msg || list_of_warning_msgs) {
237
238 GString *emesg = g_string_new(msg);
240 if (msg) {
241 g_string_append_c(emesg, '\n');
242 }
243 g_string_append(
244 emesg, "The following warnings were detected when starting rofi:\n");
245 GList *iter = g_list_first(list_of_warning_msgs);
246 int index = 0;
247 for (; iter != NULL && index < 2; iter = g_list_next(iter)) {
248 GString *in_msg = (GString *)(iter->data);
249 g_string_append(emesg, "\n\n");
250 g_string_append(emesg, in_msg->str);
251 index++;
252 }
253 if (g_list_length(iter) > 1) {
254 g_string_append_printf(emesg, "\nThere are <b>%u</b> more errors.",
255 g_list_length(iter) - 1);
256 }
257 }
258 textbox_text(state->mesg_tb, emesg->str);
260 g_string_free(emesg, TRUE);
261 g_free(msg);
262 } else {
264 }
265}
266
267static void rofi_view_take_action(const char *name) {
268 ThemeWidget *wid = rofi_config_find_widget(name, NULL, TRUE);
269 if (wid) {
271 Property *p = rofi_theme_find_property(wid, P_STRING, "action", TRUE);
272 if (p != NULL && p->type == P_STRING) {
273 const char *action = p->value.s;
274 guint id = key_binding_get_action_from_name(action);
275 if (id != UINT32_MAX) {
277 } else {
278 g_warning("Failed to parse keybinding: %s\r\n", action);
279 }
280 }
281 }
282}
283static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data) {
284 CacheState.user_timeout = 0;
285 rofi_view_take_action("timeout");
286 return G_SOURCE_REMOVE;
287}
288
289static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data) {
290 if (CacheState.user_timeout > 0) {
291 g_source_remove(CacheState.user_timeout);
292 CacheState.user_timeout = 0;
293 }
294 {
296 ThemeWidget *wid = rofi_config_find_widget("timeout", NULL, TRUE);
297 if (wid) {
299 Property *p = rofi_theme_find_property(wid, P_INTEGER, "delay", TRUE);
300 if (p != NULL && p->type == P_INTEGER && p->value.i > 0) {
301 int delay = p->value.i;
302 CacheState.user_timeout =
303 g_timeout_add(delay * 1000, rofi_view_user_timeout, NULL);
304 } else {
305 Property *prop = rofi_theme_find_property(wid, P_DOUBLE, "delay", TRUE);
306 if (prop != NULL && prop->type == P_DOUBLE && prop->value.f > 0.01) {
307 double delay = prop->value.f;
308 CacheState.user_timeout =
309 g_timeout_add(delay * 1000, rofi_view_user_timeout, NULL);
310 }
311 }
312 }
313 }
314}
315
317 state->quit = FALSE;
318 state->retv = MENU_CANCEL;
319}
320
322
325 if (state) {
326 return state->text;
327 }
328 return NULL;
329}
330
332 if (state == NULL) {
333 return;
334 }
335
336 state->retv = MENU_CANCEL;
337 state->quit = TRUE;
338}
339
341 if (state == current_active_menu) {
343 } else if (state) {
344 g_queue_remove(&(CacheState.views), state);
345 }
346}
348 if (current_active_menu != NULL && state != NULL) {
349 g_queue_push_head(&(CacheState.views), current_active_menu);
350 // TODO check.
351 current_active_menu = state;
352 g_debug("stack view.");
355 return;
356 } else if (state == NULL && !g_queue_is_empty(&(CacheState.views))) {
357 g_debug("pop view.");
358 current_active_menu = g_queue_pop_head(&(CacheState.views));
361 return;
362 }
363 g_assert((current_active_menu == NULL && state != NULL) ||
364 (current_active_menu != NULL && state == NULL));
365 current_active_menu = state;
367}
368
370 unsigned int selected_line) {
371 state->selected_line = selected_line;
372 // Find the line.
373 unsigned int selected = 0;
374 for (unsigned int i = 0; ((state->selected_line)) < UINT32_MAX && !selected &&
375 i < state->filtered_lines;
376 i++) {
377 if (state->line_map[i] == (state->selected_line)) {
378 selected = i;
379 break;
380 }
381 }
382 listview_set_selected(state->list_view, selected);
383#ifdef ENABLE_XCB
384 if (config.backend == DISPLAY_XCB) {
385 // Clear the window and force an expose event resulting in a redraw.
386 xcb_clear_area(xcb->connection, 1, CacheState.main_window, 0, 0, 1, 1);
387 xcb_flush(xcb->connection);
388 }
389#endif
390}
391
393 if (state->tokens) {
395 state->tokens = NULL;
396 }
397 // Do this here?
398 // Wait for final release?
400
401 g_free(state->line_map);
402 g_free(state->distance);
403 // Free the switcher boxes.
404 // When state is free'ed we should no longer need these.
405 g_free(state->modes);
406 state->num_modes = 0;
407 g_free(state);
408}
409
411 return state->retv;
412}
413
414unsigned int rofi_view_get_selected_line(const RofiViewState *state) {
415 return state->selected_line;
416}
417
419 RofiOrientation orientation) {
420 if (state == NULL) {
421 return 0;
422 }
423 return listview_get_element_pitch(state->list_view, orientation);
424}
425
426unsigned int rofi_view_get_next_position(const RofiViewState *state) {
427 unsigned int next_pos = state->selected_line;
428 unsigned int selected = listview_get_selected(state->list_view);
429 if ((selected + 1) < state->num_lines) {
430 (next_pos) = state->line_map[selected + 1];
431 }
432 return next_pos;
433}
434
435unsigned int rofi_view_get_completed(const RofiViewState *state) {
436 return state->quit;
437}
438
439const char *rofi_view_get_user_input(const RofiViewState *state) {
440 if (state->text) {
441 return state->text->text;
442 }
443 return NULL;
444}
445
452 return g_malloc0(sizeof(RofiViewState));
453}
454
458typedef struct _thread_state_view {
461
463 GCond *cond;
465 GMutex *mutex;
467 unsigned int *acount;
468
472 unsigned int start;
474 unsigned int stop;
476 unsigned int count;
477
479 const char *pattern;
481 glong plen;
489static void rofi_view_call_thread(gpointer data, gpointer user_data) {
490 thread_state *t = (thread_state *)data;
491 t->callback(t, user_data);
492}
493
495 G_GNUC_UNUSED gpointer user_data) {
497 for (unsigned int i = t->start; i < t->stop; i++) {
498 int match = mode_token_match(t->state->sw, t->state->tokens, i);
499 // If each token was matched, add it to list.
500 if (match) {
501 t->state->line_map[t->start + t->count] = i;
502 if (config.sort) {
503 char *str = mode_get_completion(t->state->sw, i);
504 glong slen = g_utf8_strlen(str, -1);
505 switch (config.sorting_method_enum) {
506 case SORT_FZF:
508 t->pattern, t->plen, str, slen, t->state->case_sensitive);
509 break;
510 case SORT_FZF_V2: {
511 /* Scores tie constantly, so sort on fzf's key (inverted score plus
512 * a length tiebreak) rather than on the score alone. */
513 int score = rofi_scorer_fzf_v2_evaluate(
514 t->pattern, t->plen, str, slen, t->state->case_sensitive);
515 t->state->distance[i] = rofi_scorer_fzf_v2_sort_key(score, str);
516 break;
517 }
518 case SORT_NORMAL:
519 default:
520 t->state->distance[i] = levenshtein(t->pattern, t->plen, str, slen,
522 break;
523 }
524 g_free(str);
525 }
526 t->count++;
527 }
528 }
529 if (t->acount != NULL) {
530 g_mutex_lock(t->mutex);
531 (*(t->acount))--;
532 g_cond_signal(t->cond);
533 g_mutex_unlock(t->mutex);
534 }
535}
536
538 if (CacheState.entry_history_enable == FALSE) {
539 return;
540 }
541 CacheState.entry_history = NULL;
542 CacheState.entry_history_index = 0;
543 CacheState.entry_history_length = 0;
544
545 gchar *path = g_build_filename(cache_dir, "rofi-entry-history.txt", NULL);
546 if (g_file_test(path, G_FILE_TEST_EXISTS)) {
547 FILE *fp = fopen(path, "r");
548 if (fp) {
549 char *line = NULL;
550 size_t len = 0;
551 ssize_t nread;
552 while ((nread = getline(&line, &len, fp)) != -1) {
553 CacheState.entry_history = g_realloc(
554 CacheState.entry_history,
555 sizeof(EntryHistoryIndex) * (CacheState.entry_history_length + 1));
556 if (line[nread - 1] == '\n') {
557 line[nread - 1] = '\0';
558 nread--;
559 }
560 CacheState.entry_history[CacheState.entry_history_length].string =
561 g_strdup(line);
562 CacheState.entry_history[CacheState.entry_history_length].index =
563 strlen(line);
564 CacheState.entry_history_length++;
565 CacheState.entry_history_index++;
566 }
567 free(line);
568 fclose(fp);
569 }
570 }
571 g_free(path);
572 CacheState.entry_history = g_realloc(
573 CacheState.entry_history,
574 sizeof(EntryHistoryIndex) * (CacheState.entry_history_length + 1));
575 CacheState.entry_history[CacheState.entry_history_length].string =
576 g_strdup("");
577 CacheState.entry_history[CacheState.entry_history_length].index = 0;
578 CacheState.entry_history_length++;
579}
581 if (CacheState.entry_history_enable == FALSE) {
582 return;
583 }
584 if (CacheState.entry_history_length > 0) {
585 // History max.
586 int max_history = 20;
587 ThemeWidget *wid = rofi_config_find_widget("entry", NULL, TRUE);
588 if (wid) {
589 Property *p =
590 rofi_theme_find_property(wid, P_INTEGER, "max-history", TRUE);
591 if (p != NULL && p->type == P_INTEGER) {
592 max_history = p->value.i;
593 }
594 }
595 gchar *path = g_build_filename(cache_dir, "rofi-entry-history.txt", NULL);
596 g_debug("Entry filename output: '%s'", path);
597 FILE *fp = fopen(path, "w");
598 if (fp) {
599 gssize start = MAX(0, (CacheState.entry_history_length - max_history));
600 for (gssize i = start; i < CacheState.entry_history_length; i++) {
601 if (strlen(CacheState.entry_history[i].string) > 0) {
602 fprintf(fp, "%s\n", CacheState.entry_history[i].string);
603 }
604 }
605 fclose(fp);
606 }
607 g_free(path);
608 }
609 // Cleanups.
610 if (CacheState.entry_history != NULL) {
611 for (ssize_t i = 0; i < CacheState.entry_history_length; i++) {
612 g_free(CacheState.entry_history[i].string);
613 }
614 g_free(CacheState.entry_history);
615 CacheState.entry_history = NULL;
616 CacheState.entry_history_length = 0;
617 CacheState.entry_history_index = 0;
618 }
619}
620
624
631 if (state->filtered_lines == 1) {
632 state->retv = MENU_OK;
633 (state->selected_line) =
635 state->quit = 1;
636 return;
637 }
638
639 // Double tab!
640 if (state->filtered_lines == 0 && ROW_TAB == state->prev_action) {
641 state->retv = MENU_NEXT;
642 (state->selected_line) = 0;
643 state->quit = TRUE;
644 } else {
646 }
647 state->prev_action = ROW_TAB;
648}
649
654inline static void rofi_view_nav_row_select(RofiViewState *state) {
655 if (state->list_view == NULL) {
656 return;
657 }
658 unsigned int selected = listview_get_selected(state->list_view);
659 // If a valid item is selected, return that..
660 if (selected < state->filtered_lines) {
661 char *str = mode_get_completion(state->sw, state->line_map[selected]);
662 textbox_text(state->text, str);
663 g_free(str);
665 state->refilter = TRUE;
666 }
667}
668
674inline static void rofi_view_nav_first(RofiViewState *state) {
675 // state->selected = 0;
677}
678
684inline static void rofi_view_nav_last(RofiViewState *state) {
685 // If no lines, do nothing.
686 if (state->filtered_lines == 0) {
687 return;
688 }
689 // state->selected = state->filtered_lines - 1;
691}
692static void selection_changed_user_callback(unsigned int index,
693 RofiViewState *state) {
694 if (config.on_selection_changed == NULL)
695 return;
696
697 int fstate = 0;
698 char *text = mode_get_display_value(state->sw, state->line_map[index],
699 &fstate, NULL, TRUE);
700 char **args = NULL;
701 int argv = 0;
702 helper_parse_setup(config.on_selection_changed, &args, &argv, "{entry}", text,
703 (char *)0);
704 if (args != NULL)
705 helper_execute(NULL, args, "", config.on_selection_changed, NULL);
706 g_free(text);
707}
708static void selection_changed_callback(G_GNUC_UNUSED listview *lv,
709 unsigned int index, void *udata) {
710 RofiViewState *state = (RofiViewState *)udata;
711 if (index < state->filtered_lines) {
712 if (state->previous_line != state->line_map[index]) {
714 state->previous_line = state->line_map[index];
715 }
716 }
717 if (state->tb_current_entry) {
718 if (index < state->filtered_lines) {
719 int fstate = 0;
720 char *text = mode_get_display_value(state->sw, state->line_map[index],
721 &fstate, NULL, TRUE);
722 textbox_text(state->tb_current_entry, text);
723 g_free(text);
724 } else {
725 textbox_text(state->tb_current_entry, "");
726 }
727 }
728 if (state->icon_current_entry) {
729 if (index < state->filtered_lines) {
730 int icon_height =
732 WIDGET(state->icon_current_entry)->w);
733 cairo_surface_t *surf_icon =
734 mode_get_icon(state->sw, state->line_map[index], icon_height);
735 icon_set_surface(state->icon_current_entry, surf_icon);
736 } else {
738 }
739 }
740}
741static void update_callback(textbox *t, icon *ico, unsigned int index,
742 void *udata, TextBoxFontType *type, gboolean full) {
743 RofiViewState *state = (RofiViewState *)udata;
744 if (full) {
745 GList *add_list = NULL;
746 int fstate = 0;
747 char *text = mode_get_display_value(state->sw, state->line_map[index],
748 &fstate, &add_list, TRUE);
749 (*type) |= fstate;
750
751 if (ico) {
752 int icon_height = widget_get_desired_height(WIDGET(ico), WIDGET(ico)->w);
753 cairo_surface_t *surf_icon =
754 mode_get_icon(state->sw, state->line_map[index], icon_height);
755 icon_set_surface(ico, surf_icon);
756 }
757 if (t) {
758 // TODO needed for markup.
759 textbox_font(t, *type);
760 // Move into list view.
761 textbox_text(t, text);
762 PangoAttrList *list = textbox_get_pango_attributes(t);
763 if (list != NULL) {
764 pango_attr_list_ref(list);
765 } else {
766 list = pango_attr_list_new();
767 }
768
769 if (state->tokens) {
771 {0.0, 0.0, 0.0, 0.0}};
772 th = rofi_theme_get_highlight(WIDGET(t), "highlight", th);
774 textbox_get_visible_text(t), list);
775 }
776 for (GList *iter = g_list_first(add_list); iter != NULL;
777 iter = g_list_next(iter)) {
778 pango_attr_list_insert(list, (PangoAttribute *)(iter->data));
779 }
781 pango_attr_list_unref(list);
782 }
783
784 g_list_free(add_list);
785 g_free(text);
786 } else {
787 // Never called.
788 int fstate = 0;
789 mode_get_display_value(state->sw, state->line_map[index], &fstate, NULL,
790 FALSE);
791 (*type) |= fstate;
792 // TODO needed for markup.
793 textbox_font(t, *type);
794 }
795}
800
802 g_free(state->line_map);
803 g_free(state->distance);
804 state->num_lines = mode_get_num_entries(state->sw);
805 state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
806 state->distance = g_malloc0_n(state->num_lines, sizeof(int));
809}
810
811static gboolean rofi_view_refilter_real(RofiViewState *state) {
812 CacheState.refilter_timeout = 0;
813 CacheState.refilter_timeout_count = 0;
814 if (state->sw == NULL) {
815 return G_SOURCE_REMOVE;
816 }
817 GTimer *timer = g_timer_new();
818 TICK_N("Filter start");
819 if (state->reload) {
821 state->reload = FALSE;
822 }
823 TICK_N("Filter reload rows");
824 if (state->tokens) {
826 state->tokens = NULL;
827 }
828 TICK_N("Filter tokenize");
829 if (state->text && strlen(state->text->text) > 0) {
830
831 listview_set_filtered(state->list_view, TRUE);
832 unsigned int j = 0;
833 gchar *pattern = mode_preprocess_input(state->sw, state->text->text);
834 glong plen = pattern ? g_utf8_strlen(pattern, -1) : 0;
836 state->tokens = helper_tokenize(pattern, state->case_sensitive);
837
838 if (config.case_smart && state->case_indicator) {
840 }
848 unsigned int nt = MAX(1, state->num_lines / 500);
849 // Limit the number of jobs, it could cause stack overflow if we don´t
850 // limit.
851 nt = MIN(nt, config.threads * 4);
852 thread_state_view states[nt];
853 GCond cond;
854 GMutex mutex;
855 g_mutex_init(&mutex);
856 g_cond_init(&cond);
857 unsigned int count = nt;
858 unsigned int steps = (state->num_lines + nt) / nt;
859 for (unsigned int i = 0; i < nt; i++) {
860 states[i].state = state;
861 states[i].start = i * steps;
862 states[i].stop = MIN(state->num_lines, (i + 1) * steps);
863 states[i].count = 0;
864 states[i].cond = &cond;
865 states[i].mutex = &mutex;
866 states[i].acount = &count;
867 states[i].plen = plen;
868 states[i].pattern = pattern;
869 states[i].st.callback = filter_elements;
870 states[i].st.free = NULL;
871 states[i].st.priority = G_PRIORITY_HIGH;
872 if (i > 0) {
873 g_thread_pool_push(tpool, &states[i], NULL);
874 }
875 }
876 // Run one in this thread.
877 rofi_view_call_thread(&states[0], NULL);
878 // No need to do this with only one thread.
879 if (nt > 1) {
880 g_mutex_lock(&mutex);
881 while (count > 0) {
882 g_cond_wait(&cond, &mutex);
883 }
884 g_mutex_unlock(&mutex);
885 }
886 g_cond_clear(&cond);
887 g_mutex_clear(&mutex);
888 for (unsigned int i = 0; i < nt; i++) {
889 if (j != states[i].start) {
890 memmove(&(state->line_map[j]), &(state->line_map[states[i].start]),
891 sizeof(unsigned int) * (states[i].count));
892 }
893 j += states[i].count;
894 }
895 if (config.sort) {
896 if (config.sorting_method_enum == SORT_FZF_V2) {
897 g_qsort_with_data(state->line_map, j, sizeof(int), fzf_v2_sort,
898 state->distance);
899 } else {
900 g_qsort_with_data(state->line_map, j, sizeof(int), lev_sort,
901 state->distance);
902 }
903 }
904
905 // Cleanup + bookkeeping.
906 state->filtered_lines = j;
907 g_free(pattern);
908
909 double elapsed = g_timer_elapsed(timer, NULL);
910
911 CacheState.max_refilter_time = elapsed;
912 } else {
913 listview_set_filtered(state->list_view, FALSE);
914 for (unsigned int i = 0; i < state->num_lines; i++) {
915 state->line_map[i] = i;
916 }
917 state->filtered_lines = state->num_lines;
918 }
919 TICK_N("Filter matching done");
921
922 if (state->tb_filtered_rows) {
923 char *r = g_strdup_printf("%u", state->filtered_lines);
925 g_free(r);
926 }
927 if (state->tb_total_rows) {
928 char *r = g_strdup_printf("%u", state->num_lines);
929 textbox_text(state->tb_total_rows, r);
930 g_free(r);
931 }
932 TICK_N("Update filter lines");
933
934 if (config.auto_select == TRUE && state->filtered_lines == 1 &&
935 state->num_lines > 1) {
936 (state->selected_line) =
938 state->retv = MENU_OK;
939 state->quit = TRUE;
940 }
941
942 // Size the window.
943 int height = rofi_view_calculate_window_height(state);
944 if (height != state->height) {
945 state->height = height;
948 g_debug("Resize based on re-filter");
949 }
950 TICK_N("Filter resize window based on window ");
951 state->refilter = FALSE;
952 TICK_N("Filter done");
953 rofi_view_update(state, TRUE);
954
955 g_timer_destroy(timer);
956 return G_SOURCE_REMOVE;
957}
959 CacheState.refilter_timeout_count++;
960 if (CacheState.refilter_timeout != 0) {
961
962 g_source_remove(CacheState.refilter_timeout);
963 CacheState.refilter_timeout = 0;
964 }
965 if (CacheState.max_refilter_time > (config.refilter_timeout_limit / 1000.0) &&
966 state->text && strlen(state->text->text) > 0 &&
967 CacheState.refilter_timeout_count < 25) {
968 if (CacheState.delayed_mode == FALSE) {
969 g_warning(
970 "Filtering took %f seconds ( %f ), switching to delayed filter\n",
971 CacheState.max_refilter_time, config.refilter_timeout_limit / 1000.0);
972 CacheState.delayed_mode = TRUE;
973 }
974 CacheState.refilter_timeout =
975 g_timeout_add(200, (GSourceFunc)rofi_view_refilter_real, state);
976 } else {
977 if (CacheState.delayed_mode == TRUE && state->text &&
978 strlen(state->text->text) > 0 &&
979 CacheState.refilter_timeout_count < 25) {
980 g_warning(
981 "Filtering took %f seconds , switching back to instant filter\n",
982 CacheState.max_refilter_time);
983 CacheState.delayed_mode = FALSE;
984 }
986 }
987}
989 if (CacheState.refilter_timeout != 0) {
990 g_source_remove(CacheState.refilter_timeout);
991 CacheState.refilter_timeout = 0;
992 }
993 if (state->refilter) {
995 }
996}
997
1002void process_result(RofiViewState *state);
1004 if (state && state->finalize != NULL) {
1005 state->finalize(state);
1006 }
1007}
1008
1013static void rofi_view_input_changed(void) {
1014 rofi_view_take_action("inputchange");
1015
1017 if (CacheState.entry_history_enable && state) {
1018 if (CacheState.entry_history[CacheState.entry_history_index].string !=
1019 NULL) {
1020 g_free(CacheState.entry_history[CacheState.entry_history_index].string);
1021 }
1022 CacheState.entry_history[CacheState.entry_history_index].string =
1023 textbox_get_text(state->text);
1024 CacheState.entry_history[CacheState.entry_history_index].index =
1025 textbox_get_cursor(state->text);
1026 }
1027}
1028
1029#ifdef ENABLE_WAYLAND
1030static void rofi_view_clipboard_callback(const char *clipboard_data,
1031 G_GNUC_UNUSED void *user_data) {
1033 if (clipboard_data != NULL) {
1034 if (state != NULL) {
1036 }
1037 }
1038}
1039#endif
1040
1043 switch (action) {
1044 // Handling of paste
1045 case PASTE_PRIMARY:
1046#ifdef ENABLE_XCB
1047 if (config.backend == DISPLAY_XCB) {
1048 xcb_convert_selection(xcb->connection, CacheState.main_window,
1049 XCB_ATOM_PRIMARY, xcb->ewmh.UTF8_STRING,
1050 xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1051 xcb_flush(xcb->connection);
1052 }
1053#endif
1054#ifdef ENABLE_WAYLAND
1055 if (config.backend == DISPLAY_WAYLAND) {
1057 rofi_view_clipboard_callback, NULL);
1058 }
1059#endif
1060 break;
1061 case PASTE_SECONDARY:
1062#ifdef ENABLE_XCB
1063 if (config.backend == DISPLAY_XCB) {
1064 xcb_convert_selection(xcb->connection, CacheState.main_window,
1065 netatoms[CLIPBOARD], xcb->ewmh.UTF8_STRING,
1066 xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1067 xcb_flush(xcb->connection);
1068 }
1069#endif
1070#ifdef ENABLE_WAYLAND
1071 if (config.backend == DISPLAY_WAYLAND) {
1073 rofi_view_clipboard_callback, NULL);
1074 }
1075#endif
1076 break;
1077 case COPY_SECONDARY: {
1078 char *data = NULL;
1079 unsigned int selected = listview_get_selected(state->list_view);
1080 if (selected < state->filtered_lines) {
1081 data = mode_get_completion(state->sw, state->line_map[selected]);
1082 } else if (state->text && state->text->text) {
1083 data = g_strdup(state->text->text);
1084 }
1085 if (data) {
1086#ifdef ENABLE_XCB
1087 if (config.backend == DISPLAY_XCB) {
1089 xcb_set_selection_owner(xcb->connection, CacheState.main_window,
1090 netatoms[CLIPBOARD], XCB_CURRENT_TIME);
1091 xcb_flush(xcb->connection);
1092 }
1093#endif
1094#ifdef ENABLE_WAYLAND
1095 if (config.backend == DISPLAY_WAYLAND) {
1096 // TODO
1097 }
1098#endif
1099 }
1100 } break;
1101 case SCREENSHOT:
1103 break;
1104 case CHANGE_ELLIPSIZE:
1105 if (state->list_view) {
1107 }
1108 break;
1109 case TOGGLE_SORT:
1110 if (state->case_indicator != NULL) {
1111 config.sort = !config.sort;
1112 state->refilter = TRUE;
1114 }
1115 break;
1116 case MODE_PREVIOUS:
1117 state->retv = MENU_PREVIOUS;
1118 (state->selected_line) = 0;
1119 state->quit = TRUE;
1120 break;
1121 // Menu navigation.
1122 case MODE_NEXT:
1123 state->retv = MENU_NEXT;
1124 (state->selected_line) = 0;
1125 state->quit = TRUE;
1126 break;
1127 case MODE_COMPLETE: {
1128 unsigned int selected = listview_get_selected(state->list_view);
1129 state->selected_line = UINT32_MAX;
1130 if (selected < state->filtered_lines) {
1131 state->selected_line = state->line_map[selected];
1132 }
1133 state->retv = MENU_COMPLETE;
1134 state->quit = TRUE;
1135 break;
1136 }
1137 // Toggle case sensitivity.
1139 if (state->case_indicator != NULL) {
1140 config.case_sensitive = !config.case_sensitive;
1141 (state->selected_line) = 0;
1142 state->refilter = TRUE;
1144 }
1145 break;
1146 // Special delete entry command.
1147 case DELETE_ENTRY: {
1148 unsigned int selected = listview_get_selected(state->list_view);
1149 if (selected < state->filtered_lines) {
1150 (state->selected_line) = state->line_map[selected];
1151 state->retv = MENU_ENTRY_DELETE;
1152 state->quit = TRUE;
1153 }
1154 break;
1155 }
1156 case SELECT_ELEMENT_1:
1157 case SELECT_ELEMENT_2:
1158 case SELECT_ELEMENT_3:
1159 case SELECT_ELEMENT_4:
1160 case SELECT_ELEMENT_5:
1161 case SELECT_ELEMENT_6:
1162 case SELECT_ELEMENT_7:
1163 case SELECT_ELEMENT_8:
1164 case SELECT_ELEMENT_9:
1165 case SELECT_ELEMENT_10: {
1166 unsigned int index = action - SELECT_ELEMENT_1;
1167 if (index < state->filtered_lines) {
1168 state->selected_line = state->line_map[index];
1169 state->retv = MENU_OK;
1170 state->quit = TRUE;
1171 }
1172 break;
1173 }
1174 case CUSTOM_1:
1175 case CUSTOM_2:
1176 case CUSTOM_3:
1177 case CUSTOM_4:
1178 case CUSTOM_5:
1179 case CUSTOM_6:
1180 case CUSTOM_7:
1181 case CUSTOM_8:
1182 case CUSTOM_9:
1183 case CUSTOM_10:
1184 case CUSTOM_11:
1185 case CUSTOM_12:
1186 case CUSTOM_13:
1187 case CUSTOM_14:
1188 case CUSTOM_15:
1189 case CUSTOM_16:
1190 case CUSTOM_17:
1191 case CUSTOM_18:
1192 case CUSTOM_19: {
1193 state->selected_line = UINT32_MAX;
1194 unsigned int selected = listview_get_selected(state->list_view);
1195 if (selected < state->filtered_lines) {
1196 (state->selected_line) = state->line_map[selected];
1197 }
1198 state->retv = MENU_CUSTOM_COMMAND | ((action - CUSTOM_1) & MENU_LOWER_MASK);
1199 state->quit = TRUE;
1200 break;
1201 }
1202 // If you add a binding here, make sure to add it to
1203 // rofi_view_keyboard_navigation too
1204 case CANCEL:
1205 state->retv = MENU_CANCEL;
1206 state->quit = TRUE;
1207 break;
1208 case ELEMENT_NEXT:
1210 break;
1211 case ELEMENT_PREV:
1213 break;
1214 case ROW_UP:
1215 listview_nav_up(state->list_view);
1216 break;
1217 case ROW_TAB:
1218 rofi_view_nav_row_tab(state);
1219 break;
1220 case ROW_DOWN:
1222 break;
1223 case ROW_LEFT:
1225 break;
1226 case ROW_RIGHT:
1228 break;
1229 case PAGE_PREV:
1231 break;
1232 case PAGE_NEXT:
1234 break;
1235 case ROW_FIRST:
1236 rofi_view_nav_first(state);
1237 break;
1238 case ROW_LAST:
1239 rofi_view_nav_last(state);
1240 break;
1241 case ROW_SELECT:
1243 break;
1244 // If you add a binding here, make sure to add it to textbox_keybinding too
1245 case MOVE_CHAR_BACK: {
1246 if (textbox_keybinding(state->text, action) == 0) {
1248 }
1249 break;
1250 }
1251 case MOVE_CHAR_FORWARD: {
1252 if (textbox_keybinding(state->text, action) == 0) {
1254 }
1255 break;
1256 }
1257 case CLEAR_LINE:
1258 case MOVE_FRONT:
1259 case MOVE_END:
1260 case REMOVE_TO_EOL:
1261 case REMOVE_TO_SOL:
1262 case TRANSPOSE_CHARS:
1263 case REMOVE_WORD_BACK:
1266 case MOVE_WORD_BACK:
1267 case MOVE_WORD_FORWARD:
1268 case REMOVE_CHAR_BACK: {
1269 int rc = textbox_keybinding(state->text, action);
1270 if (rc == 1) {
1271 // Entry changed.
1272 state->refilter = TRUE;
1274 } else if (rc == 2) {
1275 // Movement.
1276 }
1277 break;
1278 }
1279 case ACCEPT_ALT: {
1281 unsigned int selected = listview_get_selected(state->list_view);
1282 state->selected_line = UINT32_MAX;
1283 if (selected < state->filtered_lines) {
1284 (state->selected_line) = state->line_map[selected];
1285 state->retv = MENU_OK;
1286 } else {
1287 // Nothing entered and nothing selected.
1288 state->retv = MENU_CUSTOM_INPUT;
1289 }
1290 state->retv |= MENU_CUSTOM_ACTION;
1291 state->quit = TRUE;
1292 break;
1293 }
1294 case ACCEPT_CUSTOM: {
1296 state->selected_line = UINT32_MAX;
1297 state->retv = MENU_CUSTOM_INPUT;
1298 state->quit = TRUE;
1299 break;
1300 }
1301 case ACCEPT_CUSTOM_ALT: {
1303 state->selected_line = UINT32_MAX;
1305 state->quit = TRUE;
1306 break;
1307 }
1308 case ACCEPT_ENTRY: {
1310 // If a valid item is selected, return that..
1311 unsigned int selected = listview_get_selected(state->list_view);
1312 state->selected_line = UINT32_MAX;
1313 if (selected < state->filtered_lines) {
1314 (state->selected_line) = state->line_map[selected];
1315 state->retv = MENU_OK;
1316 } else {
1317 // Nothing entered and nothing selected.
1318 state->retv = MENU_CUSTOM_INPUT;
1319 }
1320 state->quit = TRUE;
1321 break;
1322 }
1323 case ENTRY_HISTORY_DOWN: {
1324 if (CacheState.entry_history_enable && state->text) {
1325 CacheState.entry_history[CacheState.entry_history_index].index =
1326 textbox_get_cursor(state->text);
1327 if (CacheState.entry_history_index > 0) {
1328 CacheState.entry_history_index--;
1329 }
1330 if (state->text) {
1332 state->text,
1333 CacheState.entry_history[CacheState.entry_history_index].string);
1335 state->text,
1336 CacheState.entry_history[CacheState.entry_history_index].index);
1337 state->refilter = TRUE;
1338 }
1339 }
1340 break;
1341 }
1342 case ENTRY_HISTORY_UP: {
1343 if (CacheState.entry_history_enable && state->text) {
1344 if (CacheState.entry_history[CacheState.entry_history_index].string !=
1345 NULL) {
1346 g_free(CacheState.entry_history[CacheState.entry_history_index].string);
1347 }
1348 CacheState.entry_history[CacheState.entry_history_index].string =
1349 textbox_get_text(state->text);
1350 CacheState.entry_history[CacheState.entry_history_index].index =
1351 textbox_get_cursor(state->text);
1352 // Don't create up if current is empty.
1353 if (strlen(
1354 CacheState.entry_history[CacheState.entry_history_index].string) >
1355 0) {
1356 CacheState.entry_history_index++;
1357 if (CacheState.entry_history_index >= CacheState.entry_history_length) {
1358 CacheState.entry_history =
1359 g_realloc(CacheState.entry_history,
1360 sizeof(EntryHistoryIndex) *
1361 (CacheState.entry_history_length + 1));
1362 CacheState.entry_history[CacheState.entry_history_length].string =
1363 g_strdup("");
1364 CacheState.entry_history[CacheState.entry_history_length].index = 0;
1365 CacheState.entry_history_length++;
1366 }
1367 }
1369 state->text,
1370 CacheState.entry_history[CacheState.entry_history_index].string);
1372 state->text,
1373 CacheState.entry_history[CacheState.entry_history_index].index);
1374 state->refilter = TRUE;
1375 }
1376 break;
1377 }
1378 case MATCHER_UP:
1380 rofi_view_refilter(state);
1382 break;
1383 case MATCHER_DOWN:
1385 rofi_view_refilter(state);
1387 break;
1388 }
1389}
1390
1392 guint action) {
1393 switch (scope) {
1394 case SCOPE_GLOBAL:
1395 return TRUE;
1401 gint x = state->mouse.x, y = state->mouse.y;
1403 (WidgetType)scope, x, y);
1404 if (target == NULL) {
1405 return FALSE;
1406 }
1407 widget_xy_to_relative(target, &x, &y);
1408 switch (widget_check_action(target, action, x, y)) {
1410 return FALSE;
1414 return TRUE;
1415 }
1416 break;
1417 }
1418 }
1419 return FALSE;
1420}
1421
1423 guint action) {
1425 switch (scope) {
1426 case SCOPE_GLOBAL:
1428 return;
1434 gint x = state->mouse.x, y = state->mouse.y;
1435 // If we already captured a motion, always forward action to this widget.
1436 widget *target = state->mouse.motion_target;
1437 // If we have not a previous captured motion, lookup widget.
1438 if (target == NULL) {
1440 (WidgetType)scope, x, y);
1441 }
1442 if (target == NULL) {
1443 return;
1444 }
1445 widget_xy_to_relative(target, &x, &y);
1446 switch (widget_trigger_action(target, action, x, y)) {
1448 return;
1450 target = NULL;
1453 state->mouse.motion_target = target;
1456 return;
1457 }
1458 break;
1459 }
1460 }
1461}
1462
1463void rofi_view_handle_text(RofiViewState *state, const char *text) {
1464 if (state == NULL || state->text == NULL) {
1465 return;
1466 }
1467 if (textbox_append_text(state->text, text, strlen(text))) {
1468 state->refilter = TRUE;
1470 }
1471}
1472
1473#if 0
1475{
1476 switch ( type )
1477 {
1479 return CURSOR_DEFAULT;
1480
1482 return CURSOR_POINTER;
1483
1484 case ROFI_CURSOR_TEXT:
1485 return CURSOR_TEXT;
1486 }
1487
1488 return CURSOR_DEFAULT;
1489}
1490#endif
1491
1493 gint y) {
1495 WIDGET_TYPE_UNKNOWN, x, y);
1496
1497 return target != NULL ? target->cursor_type : ROFI_CURSOR_DEFAULT;
1498}
1499
1501 gboolean find_mouse_target) {
1502 state->mouse.x = x;
1503 state->mouse.y = y;
1504
1506
1508
1509 if (find_mouse_target) {
1512
1513 if (target != NULL) {
1514 state->mouse.motion_target = target;
1515 }
1516 }
1517
1518 if (state->mouse.motion_target != NULL) {
1521
1522 if (find_mouse_target) {
1523 state->mouse.motion_target = NULL;
1524 }
1525 }
1526}
1527
1529 if (state->retv & MENU_OK) {
1530 if (config.on_entry_accepted == NULL)
1531 return;
1532 int fstate = 0;
1533 unsigned int selected = listview_get_selected(state->list_view);
1534 // TODO: handle custom text
1535 if (selected >= state->filtered_lines)
1536 return;
1537 // Pass selected text to custom command
1538 char *text = mode_get_display_value(state->sw, state->line_map[selected],
1539 &fstate, NULL, TRUE);
1540 char **args = NULL;
1541 int argv = 0;
1542 helper_parse_setup(config.on_entry_accepted, &args, &argv, "{entry}", text,
1543 (char *)0);
1544 if (args != NULL)
1545 helper_execute(NULL, args, "", config.on_entry_accepted, NULL);
1546 g_free(text);
1547 } else if (state->retv & MENU_CANCEL) {
1548 if (config.on_menu_canceled == NULL)
1549 return;
1550 helper_execute_command(NULL, config.on_menu_canceled, FALSE, NULL);
1551 } else if (state->retv & MENU_NEXT || state->retv & MENU_PREVIOUS ||
1552 state->retv & MENU_QUICK_SWITCH || state->retv & MENU_COMPLETE) {
1553 if (config.on_mode_changed == NULL)
1554 return;
1555 // TODO: pass mode name to custom command
1556 helper_execute_command(NULL, config.on_mode_changed, FALSE, NULL);
1557 }
1558}
1559
1561 if (rofi_view_get_completed(state)) {
1562 // Exec custom user commands
1564 // This menu is done.
1565 rofi_view_finalize(state);
1566 // If there a state. (for example error) reload it.
1567 state = rofi_view_get_active();
1568
1569 // cleanup, if no more state to display.
1570 if (state == NULL) {
1571 // Quit main-loop.
1573 return;
1574 }
1575 }
1576
1577 // Update if requested.
1578 if (state->refilter) {
1579 rofi_view_refilter(state);
1580 }
1581 rofi_view_update(state, TRUE);
1582 return;
1583}
1585 widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1586 G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1587 RofiViewState *state = (RofiViewState *)user_data;
1588 switch (action) {
1589 case MOUSE_CLICK_DOWN: {
1590 const char *type = rofi_theme_get_string(wid, "action", NULL);
1591 if (type) {
1592 if (state->list_view) {
1593 (state->selected_line) =
1595 } else {
1596 (state->selected_line) = UINT32_MAX;
1597 }
1598 guint id = key_binding_get_action_from_name(type);
1599 if (id != UINT32_MAX) {
1601 }
1602 state->skip_absorb = TRUE;
1604 }
1605 }
1606 case MOUSE_CLICK_UP:
1607 case MOUSE_DCLICK_DOWN:
1608 case MOUSE_DCLICK_UP:
1609 break;
1610 }
1612}
1614 widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1615 G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1616 RofiViewState *state = (RofiViewState *)user_data;
1617 unsigned int i;
1618 for (i = 0; i < state->num_modes; i++) {
1619 if (WIDGET(state->modes[i]) == wid) {
1620 break;
1621 }
1622 }
1623 if (i == state->num_modes) {
1625 }
1626
1627 switch (action) {
1628 case MOUSE_CLICK_DOWN:
1629 state->retv = MENU_QUICK_SWITCH | (i & MENU_LOWER_MASK);
1630 state->quit = TRUE;
1631 state->skip_absorb = TRUE;
1633 case MOUSE_CLICK_UP:
1634 case MOUSE_DCLICK_DOWN:
1635 case MOUSE_DCLICK_UP:
1636 break;
1637 }
1639}
1640
1641// @TODO don't like this construction.
1642static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom,
1643 void *udata) {
1644 RofiViewState *state = (RofiViewState *)udata;
1645 state->retv = MENU_OK;
1646 if (custom) {
1647 state->retv |= MENU_CUSTOM_ACTION;
1648 }
1649 (state->selected_line) = state->line_map[listview_get_selected(lv)];
1650 // Quit
1651 state->quit = TRUE;
1652 state->skip_absorb = TRUE;
1653}
1654
1655static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget,
1656 const char *name) {
1657 char *defaults = NULL;
1658 widget *wid = NULL;
1659
1663 if (strcmp(name, "mainbox") == 0) {
1664 wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
1665 box_add((box *)parent_widget, WIDGET(wid), TRUE);
1666 if (config.sidebar_mode) {
1667 defaults = "inputbar,message,listview,mode-switcher";
1668 } else {
1669 defaults = "inputbar,message,listview";
1670 }
1671 }
1675 else if (strcmp(name, "inputbar") == 0) {
1676 wid =
1677 (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
1678 defaults = "prompt,entry,overlay,case-indicator";
1679 box_add((box *)parent_widget, WIDGET(wid), FALSE);
1680 }
1684 else if (strcmp(name, "prompt") == 0) {
1685 if (state->prompt != NULL) {
1686 g_error("Prompt widget can only be added once to the layout.");
1687 return;
1688 }
1689 // Prompt box.
1690 state->prompt =
1691 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1692 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1694 box_add((box *)parent_widget, WIDGET(state->prompt), FALSE);
1695 defaults = NULL;
1696 } else if (strcmp(name, "num-rows") == 0) {
1697 state->tb_total_rows =
1698 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1699 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1700 box_add((box *)parent_widget, WIDGET(state->tb_total_rows), FALSE);
1701 defaults = NULL;
1702 } else if (strcmp(name, "num-filtered-rows") == 0) {
1703 state->tb_filtered_rows =
1704 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1705 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1706 box_add((box *)parent_widget, WIDGET(state->tb_filtered_rows), FALSE);
1707 defaults = NULL;
1708 } else if (strcmp(name, "textbox-current-entry") == 0) {
1709 state->tb_current_entry =
1710 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1711 TB_MARKUP | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1712 box_add((box *)parent_widget, WIDGET(state->tb_current_entry), FALSE);
1713 defaults = NULL;
1714 } else if (strcmp(name, "icon-current-entry") == 0) {
1715 state->icon_current_entry = icon_create(parent_widget, name);
1716 box_add((box *)parent_widget, WIDGET(state->icon_current_entry), FALSE);
1717 defaults = NULL;
1718 }
1722 else if (strcmp(name, "case-indicator") == 0) {
1723 if (state->case_indicator != NULL) {
1724 g_error("Case indicator widget can only be added once to the layout.");
1725 return;
1726 }
1727 state->case_indicator =
1728 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1729 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*", 0, 0);
1730 // Add small separator between case indicator and text box.
1731 box_add((box *)parent_widget, WIDGET(state->case_indicator), FALSE);
1733 }
1737 else if (strcmp(name, "entry") == 0) {
1738 if (state->text != NULL) {
1739 g_error("Entry textbox widget can only be added once to the layout.");
1740 return;
1741 }
1742 // Entry box
1744 tfl |= ((state->menu_flags & MENU_PASSWORD) == MENU_PASSWORD) ? TB_PASSWORD
1745 : 0;
1746 state->text = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
1747 tfl | TB_AUTOHEIGHT, NORMAL, NULL, 0, 0);
1748 box_add((box *)parent_widget, WIDGET(state->text), TRUE);
1749 }
1753 else if (strcmp(name, "message") == 0) {
1754 if (state->mesg_box != NULL) {
1755 g_error("Message widget can only be added once to the layout.");
1756 return;
1757 }
1758 state->mesg_box = container_create(parent_widget, name);
1759 state->mesg_tb = textbox_create(
1760 WIDGET(state->mesg_box), WIDGET_TYPE_TEXTBOX_TEXT, "textbox",
1761 TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL, 0, 0);
1762 container_add(state->mesg_box, WIDGET(state->mesg_tb));
1764 box_add((box *)parent_widget, WIDGET(state->mesg_box), FALSE);
1765 }
1769 else if (strcmp(name, "listview") == 0) {
1770 if (state->list_view != NULL) {
1771 g_error("Listview widget can only be added once to the layout.");
1772 return;
1773 }
1774 state->list_view =
1775 listview_create(parent_widget, name, update_callback,
1776 page_changed_callback, state, config.element_height, 0);
1778 state->list_view, selection_changed_callback, (void *)state);
1779 box_add((box *)parent_widget, WIDGET(state->list_view), TRUE);
1780 listview_set_scroll_type(state->list_view, config.scroll_method);
1782 state->list_view, rofi_view_listview_mouse_activated_cb, state);
1783
1784 listview_set_max_lines(state->list_view, state->num_lines);
1785 }
1789 else if (strcmp(name, "mode-switcher") == 0 || strcmp(name, "sidebar") == 0) {
1790 if (state->sidebar_bar != NULL) {
1791 g_error("Mode-switcher can only be added once to the layout.");
1792 return;
1793 }
1794 state->sidebar_bar =
1795 box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
1796 box_add((box *)parent_widget, WIDGET(state->sidebar_bar), FALSE);
1798 state->modes = g_malloc0(state->num_modes * sizeof(textbox *));
1799 for (unsigned int j = 0; j < state->num_modes; j++) {
1800 const Mode *mode = rofi_get_mode(j);
1801 state->modes[j] = textbox_create(
1802 WIDGET(state->sidebar_bar), WIDGET_TYPE_MODE_SWITCHER, "button",
1803 TB_AUTOHEIGHT, (mode == state->sw) ? HIGHLIGHT : NORMAL,
1804 mode_get_display_name(mode), 0.5, 0.5);
1805 box_add(state->sidebar_bar, WIDGET(state->modes[j]), TRUE);
1808 }
1809 } else if (g_ascii_strcasecmp(name, "overlay") == 0) {
1810 state->overlay = textbox_create(
1811 WIDGET(parent_widget), WIDGET_TYPE_TEXTBOX_TEXT, "overlay",
1812 TB_AUTOWIDTH | TB_AUTOHEIGHT, URGENT, "blaat", 0.5, 0);
1813 box_add((box *)parent_widget, WIDGET(state->overlay), FALSE);
1814 widget_disable(WIDGET(state->overlay));
1815 } else if (g_ascii_strncasecmp(name, "textbox", 7) == 0) {
1816 textbox *t = textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1817 TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
1818 box_add((box *)parent_widget, WIDGET(t), TRUE);
1819 } else if (g_ascii_strncasecmp(name, "button", 6) == 0) {
1820 textbox *t = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
1821 TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
1822 box_add((box *)parent_widget, WIDGET(t), TRUE);
1824 state);
1825 } else if (g_ascii_strncasecmp(name, "icon", 4) == 0) {
1826 icon *t = icon_create(parent_widget, name);
1827 /* small hack to make it clickable */
1828 const char *type = rofi_theme_get_string(WIDGET(t), "action", NULL);
1829 if (type) {
1830 WIDGET(t)->type = WIDGET_TYPE_EDITBOX;
1831 }
1832 box_add((box *)parent_widget, WIDGET(t), TRUE);
1834 state);
1835 } else {
1836 wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
1837 box_add((box *)parent_widget, WIDGET(wid), TRUE);
1838 // g_error("The widget %s does not exists. Invalid layout.", name);
1839 }
1840 if (wid) {
1841 GList *list = rofi_theme_get_list_strings(wid, "children");
1842 if (list == NULL) {
1843 if (defaults) {
1844 char **a = g_strsplit(defaults, ",", 0);
1845 for (int i = 0; a && a[i]; i++) {
1846 rofi_view_add_widget(state, wid, a[i]);
1847 }
1848 g_strfreev(a);
1849 }
1850 } else {
1851 for (const GList *iter = g_list_first(list); iter != NULL;
1852 iter = g_list_next(iter)) {
1853 rofi_view_add_widget(state, wid, (const char *)iter->data);
1854 }
1855 g_list_free_full(list, g_free);
1856 }
1857 }
1858}
1859
1860RofiViewState *rofi_view_create(Mode *sw, const char *input,
1861 MenuFlags menu_flags,
1862 void (*finalize)(RofiViewState *)) {
1863 TICK();
1865 state->menu_flags = menu_flags;
1866 state->sw = sw;
1867 state->selected_line = UINT32_MAX;
1868 state->previous_line = UINT32_MAX;
1869 state->retv = MENU_CANCEL;
1870 state->distance = NULL;
1871 state->quit = FALSE;
1872 state->skip_absorb = FALSE;
1873 // We want to filter on the first run.
1874 state->refilter = TRUE;
1875 state->finalize = finalize;
1876 state->mouse_seen = FALSE;
1877
1878 // In password mode, disable the entry history.
1879 if ((menu_flags & MENU_PASSWORD) == MENU_PASSWORD) {
1880 CacheState.entry_history_enable = FALSE;
1881 g_debug("Disable entry history, because password setup.");
1882 }
1883 if (config.disable_history) {
1884 CacheState.entry_history_enable = FALSE;
1885 g_debug("Disable entry history, because history disable flag.");
1886 }
1887 // Request the lines to show.
1888 state->num_lines = mode_get_num_entries(sw);
1889
1890 if (state->sw) {
1891 char *title =
1892 g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
1894 g_free(title);
1895 } else {
1897 }
1898 TICK_N("Startup notification");
1899
1900 // Get active monitor size.
1901 TICK_N("Get active monitor");
1902
1903 state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
1904 // Get children.
1905 GList *list =
1906 rofi_theme_get_list_strings(WIDGET(state->main_window), "children");
1907 if (list == NULL) {
1908 rofi_view_add_widget(state, WIDGET(state->main_window), "mainbox");
1909 } else {
1910 for (const GList *iter = list; iter != NULL; iter = g_list_next(iter)) {
1912 (const char *)iter->data);
1913 }
1914 g_list_free_full(list, g_free);
1915 }
1916
1917 if (state->text && input) {
1918 textbox_text(state->text, input);
1919 textbox_cursor_end(state->text);
1920 }
1921
1922 // filtered list
1923 state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
1924 state->distance = (int *)g_malloc0_n(state->num_lines, sizeof(int));
1925
1927 // Only needed when window is fixed size.
1930 }
1931
1933 // Move the window to the correct x,y position.
1936
1937 state->quit = FALSE;
1938 rofi_view_refilter(state);
1939 rofi_view_update(state, TRUE);
1940#ifdef ENABLE_XCB
1941 if (xcb->connection) {
1942 xcb_map_window(xcb->connection, CacheState.main_window);
1943 }
1944#endif
1946 rofi_view_ping_mouse(state);
1947#ifdef ENABLE_XCB
1948 if (xcb->connection) {
1949 xcb_flush(xcb->connection);
1950 }
1951#endif
1952
1954 /* When Override Redirect, the WM will not let us know we can take focus, so
1955 * just steal it */
1956 if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) {
1958 }
1959
1960#ifdef ENABLE_XCB
1961 if (xcb->sncontext != NULL) {
1962 sn_launchee_context_complete(xcb->sncontext);
1963 }
1964#endif
1965 return state;
1966}
1967
1968static void rofi_error_user_callback(const char *msg) {
1969 if (config.on_menu_error == NULL)
1970 return;
1971
1972 char **args = NULL;
1973 int argv = 0;
1974 helper_parse_setup(config.on_menu_error, &args, &argv, "{error}", msg,
1975 (char *)0);
1976 if (args != NULL)
1977 helper_execute(NULL, args, "", config.on_menu_error, NULL);
1978}
1979
1980int rofi_view_error_dialog(const char *msg, int markup) {
1982 state->retv = MENU_CANCEL;
1984 state->finalize = process_result;
1985
1986 state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
1987 box *new_box = box_create(WIDGET(state->main_window), "error-message",
1989 box_add(state->main_window, WIDGET(new_box), TRUE);
1990 state->text =
1991 textbox_create(WIDGET(new_box), WIDGET_TYPE_TEXTBOX_TEXT, "textbox",
1992 (TB_AUTOHEIGHT | TB_WRAP) + ((markup) ? TB_MARKUP : 0),
1993 NORMAL, (msg != NULL) ? msg : "", 0, 0);
1994 box_add(new_box, WIDGET(state->text), TRUE);
1995
1996 // Make sure we enable fixed num lines when in normal window mode.
1999 }
2002
2003 // Calculate window position.
2005
2006 // Move the window to the correct x,y position.
2008
2009#ifdef ENABLE_XCB
2010 // Display it.
2011 if (config.backend == DISPLAY_XCB) {
2012 xcb_map_window(xcb->connection, CacheState.main_window);
2013 }
2014#endif
2016
2017#ifdef ENABLE_XCB
2018 if (xcb->sncontext != NULL) {
2019 sn_launchee_context_complete(xcb->sncontext);
2020 }
2021#endif
2022
2023 // Exec custom command
2025
2026 // Set it as current window.
2027 rofi_view_set_active(state);
2028 return TRUE;
2029}
2030
2031static int rofi_thread_workers_sort(gconstpointer a, gconstpointer b,
2032 gpointer data G_GNUC_UNUSED) {
2033 thread_state *tsa = (thread_state *)a;
2034 thread_state *tsb = (thread_state *)b;
2035 // lower number is lower priority.. a is sorted above is a > b.
2036 return tsa->priority - tsb->priority;
2037}
2038
2039static void rofi_thread_pool_state_free(gpointer data) {
2040 if (data) {
2041 // This is a weirdness from glib that should not happen.
2042 // It pushes in a 1 to msg sleeping threads to wake up.
2043 // This should be removed from queue to avoid hitting this method.
2044 // In practice, we still hit it (and crash)
2045 if (GPOINTER_TO_UINT(data) == 1) {
2046 // Ignore this entry.
2047 g_debug("Glib thread-pool bug, received pointer with value 1.");
2048 return;
2049 }
2050 thread_state *ts = (thread_state *)data;
2051 if (ts->free) {
2052 ts->free(data);
2053 }
2054 }
2055}
2056
2058 TICK_N("Setup Threadpool, start");
2059 if (config.threads == 0) {
2060 config.threads = 1;
2061 long procs = sysconf(_SC_NPROCESSORS_CONF);
2062 config.threads = procs;
2063 }
2064 config.threads = MIN(config.threads, 128l);
2065 // Create thread pool
2066 GError *error = NULL;
2067 tpool = g_thread_pool_new_full(rofi_view_call_thread, NULL,
2069 FALSE, &error);
2070 if (error == NULL) {
2071 // Idle threads should stick around for a max of 60 seconds.
2072 g_thread_pool_set_max_idle_time(60000);
2073 // We are allowed to have
2074 g_thread_pool_set_max_threads(tpool, config.threads, &error);
2075 }
2076 // If error occurred during setup of pool, tell user and exit.
2077 if (error != NULL) {
2078 g_warning("Failed to setup thread pool: '%s'", error->message);
2079 g_error_free(error);
2080 exit(EXIT_FAILURE);
2081 }
2082 g_thread_pool_set_sort_function(tpool, rofi_thread_workers_sort, NULL);
2083 TICK_N("Setup Threadpool, done");
2084}
2086 if (tpool) {
2087 // Discard all unprocessed jobs and don't wait for current jobs in execution
2088 g_thread_pool_free(tpool, TRUE, FALSE);
2089 tpool = NULL;
2090 }
2091}
2092Mode *rofi_view_get_mode(RofiViewState *state) { return state->sw; }
2093
2094static gboolean rofi_view_overlay_timeout(G_GNUC_UNUSED gpointer user_data) {
2096 if (state) {
2097 widget_disable(WIDGET(state->overlay));
2098 }
2099 CacheState.overlay_timeout = 0;
2101 return G_SOURCE_REMOVE;
2102}
2103
2104void rofi_view_set_overlay_timeout(RofiViewState *state, const char *text) {
2105 if (state->overlay == NULL || state->list_view == NULL) {
2106 return;
2107 }
2108 if (text == NULL) {
2109 widget_disable(WIDGET(state->overlay));
2110 return;
2111 }
2112 rofi_view_set_overlay(state, text);
2113 int timeout = rofi_theme_get_integer(WIDGET(state->overlay), "timeout", 3);
2114 CacheState.overlay_timeout =
2115 g_timeout_add_seconds(timeout, rofi_view_overlay_timeout, state);
2116}
2117
2118void rofi_view_set_overlay(RofiViewState *state, const char *text) {
2119 if (state->overlay == NULL || state->list_view == NULL) {
2120 return;
2121 }
2122 if (CacheState.overlay_timeout > 0) {
2123 g_source_remove(CacheState.overlay_timeout);
2124 CacheState.overlay_timeout = 0;
2125 }
2126 if (text == NULL) {
2127 widget_disable(WIDGET(state->overlay));
2128 return;
2129 }
2130 widget_enable(WIDGET(state->overlay));
2131 textbox_text(state->overlay, text);
2132 // We want to queue a repaint.
2134}
2135
2137 if (state->text) {
2138 textbox_text(state->text, "");
2140 }
2141}
2142
2144 PangoEllipsizeMode mode) {
2145 listview_set_ellipsize(state->list_view, mode);
2146}
2147
2149 state->sw = mode;
2150 // Update prompt;
2151 if (state->prompt) {
2153 }
2154 if (state->sw) {
2155 char *title =
2156 g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
2158 g_free(title);
2159 } else {
2161 }
2162 if (state->sidebar_bar) {
2163 for (unsigned int j = 0; j < state->num_modes; j++) {
2164 const Mode *tb_mode = rofi_get_mode(j);
2165 textbox_font(state->modes[j],
2166 (tb_mode == state->sw) ? HIGHLIGHT : NORMAL);
2167 }
2168 }
2169 rofi_view_restart(state);
2170 state->reload = TRUE;
2171 state->refilter = TRUE;
2173 rofi_view_update(state, TRUE);
2174}
2175
2177
2178void rofi_view_update(RofiViewState *state, gboolean qr) {
2179 proxy->update(state, qr);
2180}
2181
2184 proxy->temp_configure_notify(state, xce);
2185}
2186
2188 proxy->temp_click_to_exit(state, target);
2189}
2190
2191void rofi_view_frame_callback(void) { proxy->frame_callback(); }
2192
2193void rofi_view_queue_redraw(void) { proxy->queue_redraw(); }
2194
2195void rofi_view_set_window_title(const char *title) {
2196 proxy->set_window_title(title);
2197}
2198
2200 proxy->calculate_window_position(state);
2201}
2202
2204 proxy->calculate_window_width(state);
2205}
2206
2208 return proxy->calculate_window_height(state);
2209}
2210
2212 proxy->window_update_size(state);
2213}
2214
2215void rofi_view_set_cursor(RofiCursorType type) { proxy->set_cursor(type); }
2216
2217void rofi_view_cleanup(void) { proxy->cleanup(); }
2218
2219void rofi_view_hide(void) { proxy->hide(); }
2220
2221void rofi_view_reload(void) { proxy->reload(); }
2222
2223void __create_window(MenuFlags menu_flags) {
2224 proxy->__create_window(menu_flags);
2225}
2226
2227xcb_window_t rofi_view_get_window(void) { return proxy->get_window(); }
2228
2229void rofi_view_get_current_monitor(int *width, int *height) {
2230 proxy->get_current_monitor(width, height);
2231}
2232
2233void rofi_view_set_size(RofiViewState *state, gint width, gint height) {
2234 proxy->set_size(state, width, height);
2235}
2236
2237void rofi_view_get_size(RofiViewState *state, gint *width, gint *height) {
2238 proxy->get_size(state, width, height);
2239}
2240
2241void rofi_view_ping_mouse(RofiViewState *state) { proxy->ping_mouse(state); }
2242
2243void rofi_view_pool_refresh(void) { proxy->pool_refresh(); }
2244
2245void rofi_view_get_menu_rect(int *x, int *y, int *w, int *h) {
2246 proxy->get_menu_rect(x, y, w, h);
2247}
void display_get_clipboard_data(enum clipboard_type type, ClipboardCb callback, void *user_data)
Definition display.c:85
static const display_proxy * proxy
Definition display.c:11
void display_set_input_focus(guint w)
Definition display.c:26
@ CLIPBOARD_DEFAULT
Definition display.h:126
@ CLIPBOARD_PRIMARY
Definition display.h:127
PangoAttrList * helper_token_match_get_pango_attr(RofiHighlightColorStyle th, rofi_int_matcher **tokens, const char *input, PangoAttrList *retv)
Definition helper.c:510
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Definition helper.c:286
unsigned int levenshtein(const char *needle, const glong needlelen, const char *haystack, const glong haystacklen, int case_sensitive)
Definition helper.c:819
Property * rofi_theme_find_property(ThemeWidget *wid, PropertyType type, const char *property, gboolean exact)
Definition theme.c:745
gboolean helper_execute_command(const char *wd, const char *cmd, gboolean run_in_term, RofiHelperExecuteContext *context)
Definition helper.c:1457
void helper_select_next_matching_mode(void)
Definition helper.c:83
void helper_tokenize_free(rofi_int_matcher **tokens)
Definition helper.c:146
const char * helper_get_matching_mode_str(void)
Definition helper.c:80
gboolean helper_execute(const char *wd, char **args, const char *error_precmd, const char *error_cmd, RofiHelperExecuteContext *context)
Definition helper.c:1424
int rofi_scorer_fzf_v2_evaluate(const char *pattern, glong plen, const char *str, glong slen, int case_sensitive)
Definition helper.c:1274
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
Definition theme.c:782
int helper_parse_setup(char *string, char ***output, int *length,...)
Definition helper.c:102
#define rofi_fallthrough
Definition helper.h:540
void helper_select_previous_matching_mode(void)
Definition helper.c:89
int rofi_scorer_fzf_v2_sort_key(int score, const char *str)
Definition helper.c:1374
int parse_case_sensitivity(const char *input)
Definition helper.c:1687
int rofi_scorer_fuzzy_evaluate(const char *pattern, glong plen, const char *str, glong slen, int case_sensitive)
Definition helper.c:971
guint key_binding_get_action_from_name(const char *name)
Definition keyb.c:440
BindingsScope
Definition keyb.h:43
KeyBindingAction
Definition keyb.h:58
MouseBindingMouseDefaultAction
Definition keyb.h:176
@ SCOPE_MOUSE_LISTVIEW_ELEMENT
Definition keyb.h:46
@ SCOPE_MOUSE_EDITBOX
Definition keyb.h:49
@ SCOPE_MOUSE_LISTVIEW
Definition keyb.h:45
@ SCOPE_MOUSE_SCROLLBAR
Definition keyb.h:50
@ SCOPE_GLOBAL
Definition keyb.h:44
@ SCOPE_MOUSE_MODE_SWITCHER
Definition keyb.h:51
@ ROW_LAST
Definition keyb.h:113
@ CUSTOM_4
Definition keyb.h:119
@ CUSTOM_17
Definition keyb.h:132
@ CUSTOM_12
Definition keyb.h:127
@ CUSTOM_9
Definition keyb.h:124
@ REMOVE_TO_SOL
Definition keyb.h:90
@ ROW_RIGHT
Definition keyb.h:104
@ ROW_UP
Definition keyb.h:105
@ CUSTOM_8
Definition keyb.h:123
@ ENTRY_HISTORY_DOWN
Definition keyb.h:149
@ SELECT_ELEMENT_9
Definition keyb.h:146
@ MATCHER_DOWN
Definition keyb.h:151
@ MOVE_FRONT
Definition keyb.h:68
@ REMOVE_WORD_FORWARD
Definition keyb.h:82
@ CHANGE_ELLIPSIZE
Definition keyb.h:136
@ ACCEPT_CUSTOM_ALT
Definition keyb.h:97
@ REMOVE_WORD_BACK
Definition keyb.h:80
@ TOGGLE_SORT
Definition keyb.h:137
@ ACCEPT_ENTRY
Definition keyb.h:94
@ ROW_TAB
Definition keyb.h:107
@ PAGE_NEXT
Definition keyb.h:111
@ TOGGLE_CASE_SENSITIVITY
Definition keyb.h:101
@ ELEMENT_NEXT
Definition keyb.h:108
@ MOVE_CHAR_FORWARD
Definition keyb.h:78
@ MOVE_WORD_FORWARD
Definition keyb.h:74
@ MODE_COMPLETE
Definition keyb.h:99
@ CUSTOM_1
Definition keyb.h:116
@ SELECT_ELEMENT_6
Definition keyb.h:143
@ CUSTOM_18
Definition keyb.h:133
@ ENTRY_HISTORY_UP
Definition keyb.h:148
@ CUSTOM_15
Definition keyb.h:130
@ CUSTOM_11
Definition keyb.h:126
@ ACCEPT_CUSTOM
Definition keyb.h:96
@ CUSTOM_5
Definition keyb.h:120
@ CUSTOM_19
Definition keyb.h:134
@ REMOVE_TO_EOL
Definition keyb.h:88
@ SELECT_ELEMENT_3
Definition keyb.h:140
@ ROW_SELECT
Definition keyb.h:114
@ PASTE_PRIMARY
Definition keyb.h:60
@ ROW_DOWN
Definition keyb.h:106
@ CUSTOM_13
Definition keyb.h:128
@ PASTE_SECONDARY
Definition keyb.h:62
@ SELECT_ELEMENT_10
Definition keyb.h:147
@ PAGE_PREV
Definition keyb.h:110
@ CUSTOM_3
Definition keyb.h:118
@ CUSTOM_7
Definition keyb.h:122
@ SELECT_ELEMENT_5
Definition keyb.h:142
@ TRANSPOSE_CHARS
Definition keyb.h:92
@ ROW_FIRST
Definition keyb.h:112
@ CUSTOM_6
Definition keyb.h:121
@ ROW_LEFT
Definition keyb.h:103
@ CUSTOM_14
Definition keyb.h:129
@ SELECT_ELEMENT_4
Definition keyb.h:141
@ MOVE_WORD_BACK
Definition keyb.h:72
@ MOVE_END
Definition keyb.h:70
@ CUSTOM_10
Definition keyb.h:125
@ MODE_NEXT
Definition keyb.h:98
@ COPY_SECONDARY
Definition keyb.h:64
@ REMOVE_CHAR_BACK
Definition keyb.h:86
@ DELETE_ENTRY
Definition keyb.h:102
@ SELECT_ELEMENT_1
Definition keyb.h:138
@ CLEAR_LINE
Definition keyb.h:66
@ MATCHER_UP
Definition keyb.h:150
@ CUSTOM_2
Definition keyb.h:117
@ SELECT_ELEMENT_2
Definition keyb.h:139
@ SCREENSHOT
Definition keyb.h:135
@ CANCEL
Definition keyb.h:115
@ ELEMENT_PREV
Definition keyb.h:109
@ MODE_PREVIOUS
Definition keyb.h:100
@ ACCEPT_ALT
Definition keyb.h:95
@ SELECT_ELEMENT_7
Definition keyb.h:144
@ MOVE_CHAR_BACK
Definition keyb.h:76
@ SELECT_ELEMENT_8
Definition keyb.h:145
@ REMOVE_CHAR_FORWARD
Definition keyb.h:84
@ CUSTOM_16
Definition keyb.h:131
@ MOUSE_CLICK_DOWN
Definition keyb.h:177
@ MOUSE_DCLICK_UP
Definition keyb.h:180
@ MOUSE_CLICK_UP
Definition keyb.h:178
@ MOUSE_DCLICK_DOWN
Definition keyb.h:179
char * mode_preprocess_input(Mode *mode, const char *input)
Definition mode.c:212
cairo_surface_t * mode_get_icon(Mode *mode, unsigned int selected_line, unsigned int height)
Definition mode.c:87
const char * mode_get_display_name(const Mode *mode)
Definition mode.c:189
struct rofi_mode Mode
Definition mode.h:49
unsigned int mode_get_num_entries(const Mode *mode)
Definition mode.c:70
MenuReturn
Definition mode.h:70
char * mode_get_message(const Mode *mode)
Definition mode.c:218
int mode_token_match(const Mode *mode, rofi_int_matcher **tokens, unsigned int selected_line)
Definition mode.c:150
char * mode_get_display_value(const Mode *mode, unsigned int selected_line, int *state, GList **attribute_list, int get_entry)
Definition mode.c:76
char * mode_get_completion(const Mode *mode, unsigned int selected_line)
Definition mode.c:121
@ MENU_CUSTOM_COMMAND
Definition mode.h:84
@ MENU_COMPLETE
Definition mode.h:88
@ MENU_LOWER_MASK
Definition mode.h:92
@ MENU_PREVIOUS
Definition mode.h:86
@ MENU_CANCEL
Definition mode.h:74
@ MENU_QUICK_SWITCH
Definition mode.h:82
@ MENU_ENTRY_DELETE
Definition mode.h:80
@ MENU_NEXT
Definition mode.h:76
@ MENU_CUSTOM_ACTION
Definition mode.h:90
@ MENU_OK
Definition mode.h:72
@ MENU_CUSTOM_INPUT
Definition mode.h:78
const Mode * rofi_get_mode(unsigned int index)
Definition rofi.c:159
void rofi_quit_main_loop(void)
Definition rofi.c:833
#define color_reset
Definition rofi.h:123
unsigned int rofi_get_num_enabled_modes(void)
Definition rofi.c:157
const char * cache_dir
Definition rofi.c:86
#define color_green
Definition rofi.h:129
#define TICK()
Definition timings.h:64
#define TICK_N(a)
Definition timings.h:69
void textbox_font(textbox *tb, TextBoxFontType tbft)
Definition textbox.c:308
TextboxFlags
Definition textbox.h:92
int textbox_keybinding(textbox *tb, KeyBindingAction action)
Definition textbox.c:922
TextBoxFontType
Definition textbox.h:103
void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list)
Definition textbox.c:392
const char * textbox_get_visible_text(const textbox *tb)
Definition textbox.c:380
int textbox_get_cursor(const textbox *tb)
Definition textbox.c:405
void textbox_cursor(textbox *tb, int pos)
Definition textbox.c:648
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
Definition textbox.c:204
void textbox_cursor_end(textbox *tb)
Definition textbox.c:750
gboolean textbox_append_text(textbox *tb, const char *pad, const int pad_len)
Definition textbox.c:987
PangoAttrList * textbox_get_pango_attributes(textbox *tb)
Definition textbox.c:386
void textbox_text(textbox *tb, const char *text)
Definition textbox.c:412
char * textbox_get_text(const textbox *tb)
Definition textbox.c:399
@ TB_AUTOHEIGHT
Definition textbox.h:93
@ TB_PASSWORD
Definition textbox.h:98
@ TB_MARKUP
Definition textbox.h:96
@ TB_WRAP
Definition textbox.h:97
@ TB_EDITABLE
Definition textbox.h:95
@ TB_AUTOWIDTH
Definition textbox.h:94
@ URGENT
Definition textbox.h:107
@ HIGHLIGHT
Definition textbox.h:118
@ NORMAL
Definition textbox.h:105
textbox * rofi_view_get_active_text(void)
Definition view.c:323
void rofi_view_cleanup(void)
Definition view.c:2217
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Definition view.c:2118
void __create_window(MenuFlags menu_flags)
Definition view.c:2223
void rofi_view_clear_input(RofiViewState *state)
Definition view.c:2136
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Definition view.c:2148
Mode * rofi_view_get_mode(RofiViewState *state)
Definition view.c:2092
void rofi_view_hide(void)
Definition view.c:2219
void rofi_view_calculate_window_position(RofiViewState *state)
Definition view.c:2199
void rofi_view_reload(void)
Definition view.c:2221
xcb_window_t rofi_view_get_window(void)
Definition view.c:2227
void rofi_view_remove_active(RofiViewState *state)
Definition view.c:340
void rofi_view_set_overlay_timeout(RofiViewState *state, const char *text)
Definition view.c:2104
int rofi_view_error_dialog(const char *msg, int markup)
Definition view.c:1980
void rofi_view_set_active(RofiViewState *state)
Definition view.c:347
void rofi_view_queue_redraw(void)
Definition view.c:2193
RofiViewState * rofi_view_get_active(void)
Definition view.c:321
void rofi_view_restart(RofiViewState *state)
Definition view.c:316
MenuFlags
Definition view.h:55
void rofi_view_handle_text(RofiViewState *state, const char *text)
Definition view.c:1463
void rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
Definition view.c:1422
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition view.c:410
unsigned int rofi_view_get_completed(const RofiViewState *state)
Definition view.c:435
gboolean rofi_view_check_action(RofiViewState *state, BindingsScope scope, guint action)
Definition view.c:1391
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition view.c:439
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
Definition view.c:1500
unsigned int rofi_view_get_element_pitch(const RofiViewState *state, RofiOrientation orientation)
Definition view.c:418
void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target)
Definition view.c:2187
void rofi_view_finalize(RofiViewState *state)
Definition view.c:1003
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition view.c:369
void rofi_view_temp_configure_notify(RofiViewState *state, xcb_configure_notify_event_t *xce)
Definition view.c:2182
void rofi_view_frame_callback(void)
Definition view.c:2191
void rofi_view_free(RofiViewState *state)
Definition view.c:392
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition view.c:1860
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition view.c:414
unsigned int rofi_view_get_next_position(const RofiViewState *state)
Definition view.c:426
void rofi_view_maybe_update(RofiViewState *state)
Definition view.c:1560
@ MENU_PASSWORD
Definition view.h:59
@ MENU_NORMAL_WINDOW
Definition view.h:61
@ MENU_ERROR_DIALOG
Definition view.h:63
@ MENU_NORMAL
Definition view.h:57
void rofi_view_ping_mouse(RofiViewState *state)
Definition view.c:2241
void rofi_capture_screenshot(void)
Definition view.c:154
void rofi_view_workers_initialize(void)
Definition view.c:2057
WidgetTriggerActionResult textbox_button_trigger_action(widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data)
Definition view.c:1584
void rofi_view_set_size(RofiViewState *state, gint width, gint height)
Definition view.c:2233
void rofi_view_get_menu_rect(int *x, int *y, int *w, int *h)
Definition view.c:2245
void rofi_view_set_window_title(const char *title)
Definition view.c:2195
void input_history_save(void)
Definition view.c:580
void input_history_initialize(void)
Definition view.c:537
void rofi_view_ellipsize_listview(RofiViewState *state, PangoEllipsizeMode mode)
Definition view.c:2143
void rofi_view_cancel(RofiViewState *state)
Definition view.c:331
void rofi_view_set_cursor(RofiCursorType type)
Definition view.c:2215
void rofi_view_get_current_monitor(int *width, int *height)
Definition view.c:2229
void rofi_view_workers_finalize(void)
Definition view.c:2085
void rofi_view_pool_refresh(void)
Definition view.c:2243
void rofi_view_get_size(RofiViewState *state, gint *width, gint *height)
Definition view.c:2237
void box_add(box *wid, widget *child, gboolean expand)
Definition box.c:287
box * box_create(widget *parent, const char *name, RofiOrientation type)
Definition box.c:347
struct _box box
Definition box.h:49
void container_add(container *cont, widget *child)
Definition container.c:68
container * container_create(widget *parent, const char *name)
Definition container.c:103
void icon_set_surface(icon *icon_widget, cairo_surface_t *surf)
Definition icon.c:148
icon * icon_create(widget *parent, const char *name)
Definition icon.c:161
struct _icon icon
Definition icon.h:44
void listview_nav_page_next(listview *lv)
Definition listview.c:1094
void listview_set_fixed_num_lines(listview *lv)
Definition listview.c:1173
struct _listview listview
Definition listview.h:45
listview * listview_create(widget *parent, const char *name, listview_update_callback cb, listview_page_changed_cb page_cb, void *udata, unsigned int eh, gboolean reverse)
Definition listview.c:789
void listview_set_num_elements(listview *lv, unsigned int rows)
Definition listview.c:614
void listview_nav_right(listview *lv)
Definition listview.c:992
void listview_set_mouse_activated_cb(listview *lv, listview_mouse_activated_cb cb, void *udata)
Definition listview.c:1152
void listview_toggle_ellipsizing(listview *lv)
Definition listview.c:1188
void listview_set_ellipsize(listview *lv, PangoEllipsizeMode mode)
Definition listview.c:1179
void listview_set_selected(listview *lv, unsigned int selected)
Definition listview.c:651
void listview_set_max_lines(listview *lv, unsigned int max_lines)
Definition listview.c:1161
void listview_nav_left(listview *lv)
Definition listview.c:969
void listview_set_scroll_type(listview *lv, ScrollType type)
Definition listview.c:1146
void listview_nav_prev(listview *lv)
Definition listview.c:906
unsigned int listview_get_selected(listview *lv)
Definition listview.c:631
void listview_set_filtered(listview *lv, gboolean filtered)
Definition listview.c:1205
void listview_nav_up(listview *lv)
Definition listview.c:932
void listview_nav_next(listview *lv)
Definition listview.c:900
void listview_nav_page_prev(listview *lv)
Definition listview.c:1084
unsigned int listview_get_element_pitch(listview *lv, RofiOrientation orientation)
Definition listview.c:638
void listview_set_selection_changed_callback(listview *lv, listview_selection_changed_callback cb, void *udata)
Definition listview.c:1211
void listview_nav_down(listview *lv)
Definition listview.c:950
WidgetTriggerActionResult widget_trigger_action(widget *wid, guint action, gint x, gint y)
Definition widget.c:546
void widget_queue_redraw(widget *wid)
Definition widget.c:487
static void widget_enable(widget *wid)
Definition widget.h:176
void widget_free(widget *wid)
Definition widget.c:425
void widget_draw(widget *wid, cairo_t *d)
Definition widget.c:140
struct _widget widget
Definition widget.h:49
WidgetType
Definition widget.h:54
#define WIDGET(a)
Definition widget.h:117
static void widget_disable(widget *wid)
Definition widget.h:168
WidgetTriggerActionResult
Definition widget.h:74
WidgetTriggerActionResult widget_check_action(widget *wid, G_GNUC_UNUSED guint action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y)
Definition widget.c:529
void widget_set_trigger_action_handler(widget *wid, widget_trigger_action_cb cb, void *cb_data)
Definition widget.c:557
int widget_get_desired_height(widget *wid, const int width)
Definition widget.c:644
gboolean widget_motion_notify(widget *wid, gint x, gint y)
Definition widget.c:566
void widget_xy_to_relative(widget *wid, gint *x, gint *y)
Definition widget.c:468
widget * widget_find_mouse_target(widget *wid, WidgetType type, gint x, gint y)
Definition widget.c:510
@ WIDGET_TYPE_UNKNOWN
Definition widget.h:56
@ WIDGET_TYPE_LISTVIEW_ELEMENT
Definition widget.h:60
@ WIDGET_TYPE_TEXTBOX_TEXT
Definition widget.h:68
@ WIDGET_TYPE_MODE_SWITCHER
Definition widget.h:66
@ WIDGET_TYPE_EDITBOX
Definition widget.h:62
@ WIDGET_TRIGGER_ACTION_RESULT_HANDLED
Definition widget.h:78
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_END
Definition widget.h:82
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_BEGIN
Definition widget.h:80
@ WIDGET_TRIGGER_ACTION_RESULT_IGNORED
Definition widget.h:76
@ P_INTEGER
Definition rofi-types.h:12
@ P_DOUBLE
Definition rofi-types.h:14
@ P_STRING
Definition rofi-types.h:16
RofiOrientation
Definition rofi-types.h:139
@ ROFI_ORIENTATION_HORIZONTAL
Definition rofi-types.h:141
@ ROFI_ORIENTATION_VERTICAL
Definition rofi-types.h:140
RofiCursorType
Definition rofi-types.h:147
@ ROFI_CURSOR_POINTER
Definition rofi-types.h:149
@ ROFI_CURSOR_TEXT
Definition rofi-types.h:150
@ ROFI_CURSOR_DEFAULT
Definition rofi-types.h:148
struct _thread_state thread_state
@ ROFI_HL_UNDERLINE
Definition rofi-types.h:56
@ ROFI_HL_BOLD
Definition rofi-types.h:54
GList * list_of_warning_msgs
Definition rofi.c:94
void process_result(RofiViewState *state)
Definition rofi.c:235
Settings config
@ DISPLAY_WAYLAND
Definition settings.h:54
@ DISPLAY_XCB
Definition settings.h:53
@ SORT_FZF_V2
Definition settings.h:50
@ SORT_FZF
Definition settings.h:50
@ SORT_NORMAL
Definition settings.h:50
PropertyValue value
Definition rofi-types.h:293
PropertyType type
Definition rofi-types.h:291
unsigned int filtered_lines
container * mesg_box
textbox * text
widget * motion_target
textbox * mesg_tb
textbox * overlay
icon * icon_current_entry
gboolean case_sensitive
textbox ** modes
listview * list_view
unsigned int num_lines
unsigned int previous_line
unsigned int num_modes
MenuReturn retv
void(* finalize)(struct RofiViewState *state)
textbox * prompt
unsigned int * line_map
textbox * tb_filtered_rows
rofi_int_matcher ** tokens
struct RofiViewState::@230320132007330210247211320260105015173207364214 mouse
textbox * tb_current_entry
textbox * tb_total_rows
unsigned int selected_line
KeyBindingAction prev_action
textbox * case_indicator
MenuFlags menu_flags
const char * pattern
Definition view.c:479
unsigned int count
Definition view.c:476
GMutex * mutex
Definition view.c:465
unsigned int stop
Definition view.c:474
thread_state st
Definition view.c:460
RofiViewState * state
Definition view.c:470
unsigned int * acount
Definition view.c:467
unsigned int start
Definition view.c:472
GCond * cond
Definition view.c:463
void(* callback)(struct _thread_state *t, gpointer data)
Definition rofi-types.h:368
void(* free)(void *)
Definition rofi-types.h:369
RofiCursorType cursor_type
char * text
Definition textbox.h:64
int rofi_theme_get_integer(const widget *wid, const char *property, int def)
Definition theme.c:842
RofiHighlightColorStyle rofi_theme_get_highlight(widget *wid, const char *property, RofiHighlightColorStyle th)
Definition theme.c:1308
GList * rofi_theme_get_list_strings(const widget *wid, const char *property)
Definition theme.c:1260
const char * rofi_theme_get_string(const widget *wid, const char *property, const char *def)
Definition theme.c:989
struct _view_proxy view_proxy
static void rofi_view_call_thread(gpointer data, gpointer user_data)
Definition view.c:489
static void rofi_view_nav_last(RofiViewState *state)
Definition view.c:684
void view_init(const view_proxy *view_in)
Definition view.c:67
static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data)
Definition view.c:289
static int fzf_v2_sort(const void *p1, const void *p2, void *arg)
Definition view.c:124
void rofi_view_refilter(RofiViewState *state)
Definition view.c:958
static void rofi_error_user_callback(const char *msg)
Definition view.c:1968
static char * get_matching_state(RofiViewState *state)
Definition view.c:91
struct _thread_state_view thread_state_view
static void rofi_view_nav_row_select(RofiViewState *state)
Definition view.c:654
static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom, void *udata)
Definition view.c:1642
static gboolean rofi_view_overlay_timeout(G_GNUC_UNUSED gpointer user_data)
Definition view.c:2094
static void screenshot_taken_user_callback(const char *path)
Definition view.c:139
static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget, const char *name)
Definition view.c:1655
static void update_callback(textbox *t, icon *ico, unsigned int index, void *udata, TextBoxFontType *type, gboolean full)
Definition view.c:741
static void rofi_view_nav_row_tab(RofiViewState *state)
Definition view.c:630
void rofi_view_window_update_size(RofiViewState *state)
Definition view.c:2211
static void rofi_view_reload_message_bar(RofiViewState *state)
Definition view.c:230
static void rofi_view_nav_first(RofiViewState *state)
Definition view.c:674
static gboolean rofi_view_refilter_real(RofiViewState *state)
Definition view.c:811
static void page_changed_callback(void)
Definition view.c:796
void rofi_view_update(RofiViewState *state, gboolean qr)
Definition view.c:2178
static RofiViewState * __rofi_view_state_create(void)
Definition view.c:451
static void rofi_view_trigger_global_action(KeyBindingAction action)
Definition view.c:1041
static void rofi_view_input_changed(void)
Definition view.c:1013
void rofi_view_calculate_window_width(struct RofiViewState *state)
Definition view.c:2203
static void filter_elements(thread_state *ts, G_GNUC_UNUSED gpointer user_data)
Definition view.c:494
void process_result(RofiViewState *state)
Definition rofi.c:235
static void rofi_view_update_prompt(RofiViewState *state)
Definition view.c:222
static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data)
Definition view.c:283
GThreadPool * tpool
Definition view.c:70
RofiViewState * current_active_menu
Definition view.c:73
static void rofi_thread_pool_state_free(gpointer data)
Definition view.c:2039
static int rofi_thread_workers_sort(gconstpointer a, gconstpointer b, gpointer data G_GNUC_UNUSED)
Definition view.c:2031
int rofi_view_calculate_window_height(RofiViewState *state)
Definition view.c:2207
static void selection_changed_user_callback(unsigned int index, RofiViewState *state)
Definition view.c:692
static void rofi_view_take_action(const char *name)
Definition view.c:267
static void selection_changed_callback(G_GNUC_UNUSED listview *lv, unsigned int index, void *udata)
Definition view.c:708
static void rofi_quit_user_callback(RofiViewState *state)
Definition view.c:1528
struct _rofi_view_cache_state CacheState
Definition view.c:75
static RofiCursorType rofi_view_resolve_cursor(RofiViewState *state, gint x, gint y)
Definition view.c:1492
static int lev_sort(const void *p1, const void *p2, void *arg)
Definition view.c:109
static WidgetTriggerActionResult textbox_sidebar_modes_trigger_action(widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data)
Definition view.c:1613
static void _rofi_view_reload_row(RofiViewState *state)
Definition view.c:801
static void rofi_view_refilter_force(RofiViewState *state)
Definition view.c:988
unsigned long long count
Definition view.c:77
int xcb_window_t
Definition xcb-dummy.h:9
#define XCB_WINDOW_NONE
Definition xcb-dummy.h:12
int xcb_configure_notify_event_t
Definition xcb-dummy.h:8
xcb_stuff * xcb
Definition display.c:103
void xcb_stuff_set_clipboard(char *data)
Definition display.c:2001
xcb_atom_t netatoms[NUM_NETATOMS]
Definition display.c:115
X11CursorType cursor_type
Definition view.c:127
static X11CursorType rofi_cursor_type_to_x11_cursor_type(RofiCursorType type)
Definition view.c:395
X11CursorType
Definition xcb.h:140
@ CURSOR_POINTER
Definition xcb.h:144
@ CURSOR_DEFAULT
Definition xcb.h:142
@ CURSOR_TEXT
Definition xcb.h:146