rofi 1.7.5
view.c
Go to the documentation of this file.
1/*
2 * rofi
3 *
4 * MIT/X11 License
5 * Copyright © 2013-2022 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 <errno.h>
33#include <locale.h>
34#include <signal.h>
35#include <stdint.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <time.h>
40#include <unistd.h>
41#include <xcb/xcb_ewmh.h>
42#include <xcb/xcb_icccm.h>
43#include <xcb/xkb.h>
44#include <xkbcommon/xkbcommon-x11.h>
45
46#include <cairo-xcb.h>
47#include <cairo.h>
48
50#define SN_API_NOT_YET_FROZEN
51#include "rofi.h"
52#include <libsn/sn.h>
53
54#include "settings.h"
55#include "timings.h"
56
57#include "display.h"
58#include "helper-theme.h"
59#include "helper.h"
60#include "mode.h"
61#include "modes/modes.h"
62#include "xcb-internal.h"
63#include "xrmoptions.h"
64
65#include "view-internal.h"
66#include "view.h"
67
68#include "theme.h"
69
70#include "xcb.h"
71
78void rofi_view_update(RofiViewState *state, gboolean qr);
79
81
83GThreadPool *tpool = NULL;
84
87
91struct {
93 xcb_window_t main_window;
95 cairo_surface_t *fake_bg;
97 xcb_gcontext_t gc;
99 xcb_pixmap_t edit_pixmap;
101 cairo_surface_t *edit_surf;
103 cairo_t *edit_draw;
109 GQueue views;
120 unsigned long long count;
124 gboolean fullscreen;
127} CacheState = {
128 .main_window = XCB_WINDOW_NONE,
129 .fake_bg = NULL,
130 .edit_surf = NULL,
131 .edit_draw = NULL,
132 .fake_bgrel = FALSE,
133 .flags = MENU_NORMAL,
134 .views = G_QUEUE_INIT,
135 .idle_timeout = 0,
136 .refilter_timeout = 0,
137 .refilter_timeout_count = 0,
138 .user_timeout = 0,
139 .count = 0L,
140 .repaint_source = 0,
141 .fullscreen = FALSE,
143
144void rofi_view_get_current_monitor(int *width, int *height) {
145 if (width) {
146 *width = CacheState.mon.w;
147 }
148 if (height) {
149 *height = CacheState.mon.h;
150 }
151}
152static char *get_matching_state(void) {
154 if (config.sort) {
155 return "±";
156 }
157 return "-";
158 }
159 if (config.sort) {
160 return "+";
161 }
162 return " ";
163}
164
168static int lev_sort(const void *p1, const void *p2, void *arg) {
169 const int *a = p1;
170 const int *b = p2;
171 int *distances = arg;
172
173 return distances[*a] - distances[*b];
174}
175
180 const char *outp = g_getenv("ROFI_PNG_OUTPUT");
181 if (CacheState.edit_surf == NULL) {
182 // Nothing to store.
183 g_warning("There is no rofi surface to store");
184 return;
185 }
186 const char *xdg_pict_dir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
187 if (outp == NULL && xdg_pict_dir == NULL) {
188 g_warning("XDG user picture directory or ROFI_PNG_OUTPUT is not set. "
189 "Cannot store screenshot.");
190 return;
191 }
192 // Get current time.
193 GDateTime *now = g_date_time_new_now_local();
194 // Format filename.
195 char *timestmp = g_date_time_format(now, "rofi-%Y-%m-%d-%H%M");
196 char *filename = g_strdup_printf("%s-%05d.png", timestmp, 0);
197 // Build full path
198 char *fpath = NULL;
199 if (outp == NULL) {
200 int index = 0;
201 fpath = g_build_filename(xdg_pict_dir, filename, NULL);
202 while (g_file_test(fpath, G_FILE_TEST_EXISTS) && index < 99999) {
203 g_free(fpath);
204 g_free(filename);
205 // Try the next index.
206 index++;
207 // Format filename.
208 filename = g_strdup_printf("%s-%05d.png", timestmp, index);
209 // Build full path
210 fpath = g_build_filename(xdg_pict_dir, filename, NULL);
211 }
212 } else {
213 fpath = g_strdup(outp);
214 }
215 fprintf(stderr, color_green "Storing screenshot %s\n" color_reset, fpath);
216 cairo_status_t status =
217 cairo_surface_write_to_png(CacheState.edit_surf, fpath);
218 if (status != CAIRO_STATUS_SUCCESS) {
219 g_warning("Failed to produce screenshot '%s', got error: '%s'", fpath,
220 cairo_status_to_string(status));
221 }
222 g_free(fpath);
223 g_free(filename);
224 g_free(timestmp);
225 g_date_time_unref(now);
226}
227
232gboolean do_bench = TRUE;
233
237static struct {
239 GTimer *time;
241 uint64_t draws;
243 double last_ts;
245 double min;
246} BenchMark = {.time = NULL, .draws = 0, .last_ts = 0.0, .min = G_MAXDOUBLE};
247
248static gboolean bench_update(void) {
249 if (!config.benchmark_ui) {
250 return FALSE;
251 }
252 BenchMark.draws++;
253 if (BenchMark.time == NULL) {
254 BenchMark.time = g_timer_new();
255 }
256
257 if ((BenchMark.draws & 1023) == 0) {
258 double ts = g_timer_elapsed(BenchMark.time, NULL);
259 double fps = 1024 / (ts - BenchMark.last_ts);
260
261 if (fps < BenchMark.min) {
262 BenchMark.min = fps;
263 }
264 printf("current: %.2f fps, avg: %.2f fps, min: %.2f fps, %lu draws\r\n",
265 fps, BenchMark.draws / ts, BenchMark.min, BenchMark.draws);
266
267 BenchMark.last_ts = ts;
268 }
269 return TRUE;
270}
271
272static gboolean rofi_view_repaint(G_GNUC_UNUSED void *data) {
274 // Repaint the view (if needed).
275 // After a resize the edit_pixmap surface might not contain anything
276 // anymore. If we already re-painted, this does nothing.
277
278 TICK_N("Update start");
280 g_debug("expose event");
281 TICK_N("Expose");
282 xcb_copy_area(xcb->connection, CacheState.edit_pixmap,
283 CacheState.main_window, CacheState.gc, 0, 0, 0, 0,
285 xcb_flush(xcb->connection);
286 TICK_N("flush");
287 CacheState.repaint_source = 0;
288 }
289 return (bench_update() == TRUE) ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE;
290}
291
293 if (state->prompt) {
294 const char *str = mode_get_display_name(state->sw);
295 textbox_text(state->prompt, str);
296 }
297}
298
316 int location = rofi_theme_get_position(WIDGET(state->main_window), "location",
318 int anchor =
319 rofi_theme_get_position(WIDGET(state->main_window), "anchor", location);
320
321 if (CacheState.fullscreen) {
322 state->x = CacheState.mon.x;
323 state->y = CacheState.mon.y;
324 return;
325 }
326 state->y = CacheState.mon.y + (CacheState.mon.h) / 2;
327 state->x = CacheState.mon.x + (CacheState.mon.w) / 2;
328 // Determine window location
329 switch (location) {
330 case WL_NORTH_WEST:
331 state->x = CacheState.mon.x;
332 /* FALLTHRU */
333 case WL_NORTH:
334 state->y = CacheState.mon.y;
335 break;
336 case WL_NORTH_EAST:
337 state->y = CacheState.mon.y;
338 /* FALLTHRU */
339 case WL_EAST:
340 state->x = CacheState.mon.x + CacheState.mon.w;
341 break;
342 case WL_SOUTH_EAST:
343 state->x = CacheState.mon.x + CacheState.mon.w;
344 /* FALLTHRU */
345 case WL_SOUTH:
346 state->y = CacheState.mon.y + CacheState.mon.h;
347 break;
348 case WL_SOUTH_WEST:
349 state->y = CacheState.mon.y + CacheState.mon.h;
350 /* FALLTHRU */
351 case WL_WEST:
352 state->x = CacheState.mon.x;
353 break;
354 case WL_CENTER:;
355 /* FALLTHRU */
356 default:
357 break;
358 }
359 switch (anchor) {
360 case WL_SOUTH_WEST:
361 state->y -= state->height;
362 break;
363 case WL_SOUTH:
364 state->x -= state->width / 2;
365 state->y -= state->height;
366 break;
367 case WL_SOUTH_EAST:
368 state->x -= state->width;
369 state->y -= state->height;
370 break;
371 case WL_NORTH_EAST:
372 state->x -= state->width;
373 break;
374 case WL_NORTH_WEST:
375 break;
376 case WL_NORTH:
377 state->x -= state->width / 2;
378 break;
379 case WL_EAST:
380 state->x -= state->width;
381 state->y -= state->height / 2;
382 break;
383 case WL_WEST:
384 state->y -= state->height / 2;
385 break;
386 case WL_CENTER:
387 state->y -= state->height / 2;
388 state->x -= state->width / 2;
389 break;
390 default:
391 break;
392 }
393 // Apply offset.
395 "x-offset", config.x_offset);
397 "y-offset", config.y_offset);
400}
401
403 if (state == NULL) {
404 return;
405 }
406 uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
407 XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
408 uint32_t vals[] = {state->x, state->y, state->width, state->height};
409
410 // Display it.
411 xcb_configure_window(xcb->connection, CacheState.main_window, mask, vals);
412 cairo_destroy(CacheState.edit_draw);
413 cairo_surface_destroy(CacheState.edit_surf);
414
415 xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
416 CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
417 xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
418 CacheState.main_window, state->width, state->height);
419
420 CacheState.edit_surf =
421 cairo_xcb_surface_create(xcb->connection, CacheState.edit_pixmap, visual,
422 state->width, state->height);
423 CacheState.edit_draw = cairo_create(CacheState.edit_surf);
424
425 g_debug("Re-size window based internal request: %dx%d.", state->width,
426 state->height);
427 // Should wrap main window in a widget.
428 widget_resize(WIDGET(state->main_window), state->width, state->height);
429}
430
431extern GList *list_of_warning_msgs;
433 if (state->mesg_box == NULL) {
434 return;
435 }
436 char *msg = mode_get_message(state->sw);
437 if (msg || list_of_warning_msgs) {
440 GString *emesg = g_string_new(msg);
442 if (msg) {
443 g_string_append_c(emesg, '\n');
444 }
445 g_string_append(
446 emesg, "The following warnings were detected when starting rofi:\n");
447 GList *iter = g_list_first(list_of_warning_msgs);
448 int index = 0;
449 for (; iter != NULL && index < 2; iter = g_list_next(iter)) {
450 GString *msg = (GString *)(iter->data);
451 g_string_append(emesg, "\n\n");
452 g_string_append(emesg, msg->str);
453 index++;
454 }
455 if (g_list_length(iter) > 1) {
456 g_string_append_printf(emesg, "\nThere are <b>%u</b> more errors.",
457 g_list_length(iter) - 1);
458 }
459 }
460 textbox_text(state->mesg_tb, emesg->str);
462 g_string_free(emesg, TRUE);
463 g_free(msg);
464 } else {
466 }
467}
468
469static gboolean rofi_view_reload_idle(G_GNUC_UNUSED gpointer data) {
471 // For UI update on this.
473 char *r =
474 g_strdup_printf("%u", mode_get_num_entries(current_active_menu->sw));
476 g_free(r);
477 }
481 }
482 CacheState.idle_timeout = 0;
483 return G_SOURCE_REMOVE;
484}
485
486static void rofi_view_take_action(const char *name) {
487 ThemeWidget *wid = rofi_config_find_widget(name, NULL, TRUE);
488 if (wid) {
490 Property *p = rofi_theme_find_property(wid, P_STRING, "action", TRUE);
491 if (p != NULL && p->type == P_STRING) {
492 const char *action = p->value.s;
493 guint id = key_binding_get_action_from_name(action);
494 if (id != UINT32_MAX) {
496 } else {
497 g_warning("Failed to parse keybinding: %s\r\n", action);
498 }
499 }
500 }
501}
502static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data) {
503 CacheState.user_timeout = 0;
504 rofi_view_take_action("timeout");
505 return G_SOURCE_REMOVE;
506}
507
508static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data) {
509 if (CacheState.user_timeout > 0) {
510 g_source_remove(CacheState.user_timeout);
511 CacheState.user_timeout = 0;
512 }
513 {
515 ThemeWidget *wid = rofi_config_find_widget("timeout", NULL, TRUE);
516 if (wid) {
518 Property *p = rofi_theme_find_property(wid, P_INTEGER, "delay", TRUE);
519 if (p != NULL && p->type == P_INTEGER && p->value.i > 0) {
520 int delay = p->value.i;
521 CacheState.user_timeout =
522 g_timeout_add(delay * 1000, rofi_view_user_timeout, NULL);
523 }
524 }
525 }
526}
527
529 // @TODO add check if current view is equal to the callee
530 if (CacheState.idle_timeout == 0) {
531 CacheState.idle_timeout =
532 g_timeout_add(1000 / 100, rofi_view_reload_idle, NULL);
533 }
534}
536 if (current_active_menu && CacheState.repaint_source == 0) {
537 CacheState.count++;
538 g_debug("redraw %llu", CacheState.count);
539 CacheState.repaint_source =
540 g_idle_add_full(G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL);
541 }
542}
543
545 state->quit = FALSE;
546 state->retv = MENU_CANCEL;
547}
548
550
552 if (state == current_active_menu) {
554 } else if (state) {
555 g_queue_remove(&(CacheState.views), state);
556 }
557}
559 if (current_active_menu != NULL && state != NULL) {
560 g_queue_push_head(&(CacheState.views), current_active_menu);
561 // TODO check.
562 current_active_menu = state;
563 g_debug("stack view.");
566 return;
567 }
568 if (state == NULL && !g_queue_is_empty(&(CacheState.views))) {
569 g_debug("pop view.");
570 current_active_menu = g_queue_pop_head(&(CacheState.views));
573 return;
574 }
575 g_assert((current_active_menu == NULL && state != NULL) ||
576 (current_active_menu != NULL && state == NULL));
577 current_active_menu = state;
579}
580
582 unsigned int selected_line) {
583 state->selected_line = selected_line;
584 // Find the line.
585 unsigned int selected = 0;
586 for (unsigned int i = 0; ((state->selected_line)) < UINT32_MAX && !selected &&
587 i < state->filtered_lines;
588 i++) {
589 if (state->line_map[i] == (state->selected_line)) {
590 selected = i;
591 break;
592 }
593 }
594 listview_set_selected(state->list_view, selected);
595 xcb_clear_area(xcb->connection, CacheState.main_window, 1, 0, 0, 1, 1);
596 xcb_flush(xcb->connection);
597}
598
600 if (state->tokens) {
602 state->tokens = NULL;
603 }
604 // Do this here?
605 // Wait for final release?
607
608 g_free(state->line_map);
609 g_free(state->distance);
610 // Free the switcher boxes.
611 // When state is free'ed we should no longer need these.
612 g_free(state->modes);
613 state->num_modes = 0;
614 g_free(state);
615}
616
618 return state->retv;
619}
620
621unsigned int rofi_view_get_selected_line(const RofiViewState *state) {
622 return state->selected_line;
623}
624
625unsigned int rofi_view_get_next_position(const RofiViewState *state) {
626 unsigned int next_pos = state->selected_line;
627 unsigned int selected = listview_get_selected(state->list_view);
628 if ((selected + 1) < state->num_lines) {
629 (next_pos) = state->line_map[selected + 1];
630 }
631 return next_pos;
632}
633
634unsigned int rofi_view_get_completed(const RofiViewState *state) {
635 return state->quit;
636}
637
638const char *rofi_view_get_user_input(const RofiViewState *state) {
639 if (state->text) {
640 return state->text->text;
641 }
642 return NULL;
643}
644
651 return g_malloc0(sizeof(RofiViewState));
652}
653
657typedef struct _thread_state_view {
660
662 GCond *cond;
664 GMutex *mutex;
666 unsigned int *acount;
667
671 unsigned int start;
673 unsigned int stop;
675 unsigned int count;
676
678 const char *pattern;
680 glong plen;
688static void rofi_view_call_thread(gpointer data, gpointer user_data) {
689 thread_state *t = (thread_state *)data;
690 t->callback(t, user_data);
691}
692
694 G_GNUC_UNUSED gpointer user_data) {
696 for (unsigned int i = t->start; i < t->stop; i++) {
697 int match = mode_token_match(t->state->sw, t->state->tokens, i);
698 // If each token was matched, add it to list.
699 if (match) {
700 t->state->line_map[t->start + t->count] = i;
701 if (config.sort) {
702 // This is inefficient, need to fix it.
703 char *str = mode_get_completion(t->state->sw, i);
704 glong slen = g_utf8_strlen(str, -1);
705 switch (config.sorting_method_enum) {
706 case SORT_FZF:
707 t->state->distance[i] =
708 rofi_scorer_fuzzy_evaluate(t->pattern, t->plen, str, slen);
709 break;
710 case SORT_NORMAL:
711 default:
712 t->state->distance[i] = levenshtein(t->pattern, t->plen, str, slen);
713 break;
714 }
715 g_free(str);
716 }
717 t->count++;
718 }
719 }
720 if (t->acount != NULL) {
721 g_mutex_lock(t->mutex);
722 (*(t->acount))--;
723 g_cond_signal(t->cond);
724 g_mutex_unlock(t->mutex);
725 }
726}
727
728static void
730 const char *const fake_background) {
731 if (CacheState.fake_bg == NULL) {
732 cairo_surface_t *s = NULL;
737 TICK_N("Fake start");
738 if (g_strcmp0(fake_background, "real") == 0) {
739 return;
740 }
741 if (g_strcmp0(fake_background, "screenshot") == 0) {
743 } else if (g_strcmp0(fake_background, "background") == 0) {
745 } else {
746 char *fpath = rofi_expand_path(fake_background);
747 g_debug("Opening %s to use as background.", fpath);
748 s = cairo_image_surface_create_from_png(fpath);
749 CacheState.fake_bgrel = TRUE;
750 g_free(fpath);
751 }
752 TICK_N("Get surface.");
753 if (s != NULL) {
754 if (cairo_surface_status(s) != CAIRO_STATUS_SUCCESS) {
755 g_debug("Failed to open surface fake background: %s",
756 cairo_status_to_string(cairo_surface_status(s)));
757 cairo_surface_destroy(s);
758 s = NULL;
759 } else {
760 CacheState.fake_bg = cairo_image_surface_create(
761 CAIRO_FORMAT_ARGB32, CacheState.mon.w, CacheState.mon.h);
762
763 int blur = rofi_theme_get_integer(WIDGET(win), "blur", 0);
764 cairo_t *dr = cairo_create(CacheState.fake_bg);
765 if (CacheState.fake_bgrel) {
766 cairo_set_source_surface(dr, s, 0, 0);
767 } else {
768 cairo_set_source_surface(dr, s, -CacheState.mon.x, -CacheState.mon.y);
769 }
770 cairo_paint(dr);
771 cairo_destroy(dr);
772 cairo_surface_destroy(s);
773 if (blur > 0) {
774 cairo_image_surface_blur(CacheState.fake_bg, (double)blur, 0);
775 TICK_N("BLUR");
776 }
777 }
778 }
779 TICK_N("Fake transparency");
780 }
781}
782void __create_window(MenuFlags menu_flags) {
783 uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
784 XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE |
785 XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
786 uint32_t xcb_event_masks =
787 XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
788 XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_KEY_PRESS |
789 XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE |
790 XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE |
791 XCB_EVENT_MASK_BUTTON_1_MOTION | XCB_EVENT_MASK_POINTER_MOTION;
792
793 uint32_t selval[] = {XCB_BACK_PIXMAP_NONE, 0,
794 XCB_GRAVITY_STATIC, XCB_BACKING_STORE_NOT_USEFUL,
795 xcb_event_masks, map};
796
797 xcb_window_t box_window = xcb_generate_id(xcb->connection);
798 xcb_void_cookie_t cc = xcb_create_window_checked(
799 xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window(), 0,
800 0, 200, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visual_id, selmask,
801 selval);
802 xcb_generic_error_t *error;
803 error = xcb_request_check(xcb->connection, cc);
804 if (error) {
805 g_error("xcb_create_window() failed error=0x%x\n", error->error_code);
806 exit(EXIT_FAILURE);
807 }
808 TICK_N("xcb create window");
809 CacheState.gc = xcb_generate_id(xcb->connection);
810 xcb_create_gc(xcb->connection, CacheState.gc, box_window, 0, 0);
811
812 TICK_N("xcb create gc");
813 // Create a drawable.
814 CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
815 xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
816 CacheState.main_window, 200, 100);
817
818 CacheState.edit_surf = cairo_xcb_surface_create(
819 xcb->connection, CacheState.edit_pixmap, visual, 200, 100);
820 CacheState.edit_draw = cairo_create(CacheState.edit_surf);
821
822 TICK_N("create cairo surface");
823 // Set up pango context.
824 cairo_font_options_t *fo = cairo_font_options_create();
825 // Take font description from xlib surface
826 cairo_surface_get_font_options(CacheState.edit_surf, fo);
827 // TODO should we update the drawable each time?
828 PangoContext *p = pango_cairo_create_context(CacheState.edit_draw);
829 // Set the font options from the xlib surface
830 pango_cairo_context_set_font_options(p, fo);
831 TICK_N("pango cairo font setup");
832
833 CacheState.main_window = box_window;
834 CacheState.flags = menu_flags;
836 // Setup dpi
837 if (config.dpi > 1) {
838 PangoFontMap *font_map = pango_cairo_font_map_get_default();
839 pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map,
840 (double)config.dpi);
841 } else if (config.dpi == 0 || config.dpi == 1) {
842 // Auto-detect mode.
843 double dpi = 96;
844 if (CacheState.mon.mh > 0 && config.dpi == 1) {
845 dpi = (CacheState.mon.h * 25.4) / (double)(CacheState.mon.mh);
846 } else {
847 dpi = (xcb->screen->height_in_pixels * 25.4) /
848 (double)(xcb->screen->height_in_millimeters);
849 }
850
851 g_debug("Auto-detected DPI: %.2lf", dpi);
852 PangoFontMap *font_map = pango_cairo_font_map_get_default();
853 pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map, dpi);
854 config.dpi = dpi;
855 } else {
856 // default pango is 96.
857 PangoFontMap *font_map = pango_cairo_font_map_get_default();
858 config.dpi =
859 pango_cairo_font_map_get_resolution((PangoCairoFontMap *)font_map);
860 }
861 // Setup font.
862 // Dummy widget.
863 box *win = box_create(NULL, "window", ROFI_ORIENTATION_HORIZONTAL);
864 const char *font =
866 if (font) {
867 PangoFontDescription *pfd = pango_font_description_from_string(font);
868 if (helper_validate_font(pfd, font)) {
869 pango_context_set_font_description(p, pfd);
870 }
871 pango_font_description_free(pfd);
872 }
873 PangoLanguage *l = pango_language_get_default();
874 pango_context_set_language(p, l);
875 TICK_N("configure font");
876
877 // Tell textbox to use this context.
879 // cleanup
880 g_object_unref(p);
881 cairo_font_options_destroy(fo);
882
883 TICK_N("textbox setup");
884 // // make it an unmanaged window
885 if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) {
886 window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE,
887 &(xcb->ewmh._NET_WM_STATE_ABOVE), 1);
888 uint32_t values[] = {1};
889 xcb_change_window_attributes(xcb->connection, box_window,
890 XCB_CW_OVERRIDE_REDIRECT, values);
891 } else {
892 window_set_atom_prop(box_window, xcb->ewmh._NET_WM_WINDOW_TYPE,
893 &(xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL), 1);
894 x11_disable_decoration(box_window);
895 }
896
897 TICK_N("setup window attributes");
898 CacheState.fullscreen =
899 rofi_theme_get_boolean(WIDGET(win), "fullscreen", FALSE);
900 if (CacheState.fullscreen) {
901 xcb_atom_t atoms[] = {xcb->ewmh._NET_WM_STATE_FULLSCREEN,
902 xcb->ewmh._NET_WM_STATE_ABOVE};
903 window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE, atoms,
904 sizeof(atoms) / sizeof(xcb_atom_t));
905 }
906
907 xcb_atom_t protocols[] = {netatoms[WM_TAKE_FOCUS]};
908 xcb_icccm_set_wm_protocols(xcb->connection, box_window,
909 xcb->ewmh.WM_PROTOCOLS, G_N_ELEMENTS(protocols),
910 protocols);
911
912 TICK_N("setup window fullscreen");
913 // Set the WM_NAME
915 const char wm_class_name[] = "rofi\0Rofi";
916 xcb_icccm_set_wm_class(xcb->connection, box_window, sizeof(wm_class_name),
917 wm_class_name);
918
919 TICK_N("setup window name and class");
920 const char *transparency =
921 rofi_theme_get_string(WIDGET(win), "transparency", NULL);
922 if (transparency) {
923 rofi_view_setup_fake_transparency(WIDGET(win), transparency);
924 }
925 if (xcb->sncontext != NULL) {
926 sn_launchee_context_setup_window(xcb->sncontext, CacheState.main_window);
927 }
928 TICK_N("setup startup notification");
929 widget_free(WIDGET(win));
930 TICK_N("done");
931
932 // Set the PID.
933 pid_t pid = getpid();
934 xcb_ewmh_set_wm_pid(&(xcb->ewmh), CacheState.main_window, pid);
935
936 // Get hostname
937 const char *hostname = g_get_host_name();
938 char *ahost = g_hostname_to_ascii(hostname);
939 if (ahost != NULL) {
940 xcb_icccm_set_wm_client_machine(xcb->connection, CacheState.main_window,
941 XCB_ATOM_STRING, 8, strlen(ahost), ahost);
942 g_free(ahost);
943 }
944}
945
952 if (CacheState.fullscreen) {
953 state->width = CacheState.mon.w;
954 return;
955 }
956 // Calculate as float to stop silly, big rounding down errors.
957 state->width = (CacheState.mon.w / 100.0f) * DEFAULT_MENU_WIDTH;
958 // Use theme configured width, if set.
960 "width", state->width);
962}
963
974 if (state->filtered_lines == 1) {
975 state->retv = MENU_OK;
976 (state->selected_line) =
978 state->quit = 1;
979 return;
980 }
981
982 // Double tab!
983 if (state->filtered_lines == 0 && ROW_TAB == state->prev_action) {
984 state->retv = MENU_NEXT;
985 (state->selected_line) = 0;
986 state->quit = TRUE;
987 } else {
989 }
990 state->prev_action = ROW_TAB;
991}
997inline static void rofi_view_nav_row_select(RofiViewState *state) {
998 if (state->list_view == NULL) {
999 return;
1000 }
1001 unsigned int selected = listview_get_selected(state->list_view);
1002 // If a valid item is selected, return that..
1003 if (selected < state->filtered_lines) {
1004 char *str = mode_get_completion(state->sw, state->line_map[selected]);
1005 textbox_text(state->text, str);
1006 g_free(str);
1008 state->refilter = TRUE;
1009 }
1010}
1011
1017inline static void rofi_view_nav_first(RofiViewState *state) {
1018 // state->selected = 0;
1020}
1021
1027inline static void rofi_view_nav_last(RofiViewState *state) {
1028 // If no lines, do nothing.
1029 if (state->filtered_lines == 0) {
1030 return;
1031 }
1032 // state->selected = state->filtered_lines - 1;
1033 listview_set_selected(state->list_view, -1);
1034}
1035static void selection_changed_callback(G_GNUC_UNUSED listview *lv,
1036 unsigned int index, void *udata) {
1037 RofiViewState *state = (RofiViewState *)udata;
1038 if (state->tb_current_entry) {
1039 if (index < state->filtered_lines) {
1040 int fstate = 0;
1041 char *text = mode_get_display_value(state->sw, state->line_map[index],
1042 &fstate, NULL, TRUE);
1043 textbox_text(state->tb_current_entry, text);
1044 g_free(text);
1045
1046 } else {
1047 textbox_text(state->tb_current_entry, "");
1048 }
1049 }
1050 if (state->icon_current_entry) {
1051 if (index < state->filtered_lines) {
1052 int icon_height =
1054 WIDGET(state->icon_current_entry)->w);
1055 cairo_surface_t *icon =
1056 mode_get_icon(state->sw, state->line_map[index], icon_height);
1058 } else {
1060 }
1061 }
1062}
1063static void update_callback(textbox *t, icon *ico, unsigned int index,
1064 void *udata, TextBoxFontType *type, gboolean full) {
1065 RofiViewState *state = (RofiViewState *)udata;
1066 if (full) {
1067 GList *add_list = NULL;
1068 int fstate = 0;
1069 char *text = mode_get_display_value(state->sw, state->line_map[index],
1070 &fstate, &add_list, TRUE);
1071 (*type) |= fstate;
1072
1073 if (ico) {
1074 int icon_height = widget_get_desired_height(WIDGET(ico), WIDGET(ico)->w);
1075 cairo_surface_t *icon =
1076 mode_get_icon(state->sw, state->line_map[index], icon_height);
1077 icon_set_surface(ico, icon);
1078 }
1079 if (t) {
1080 // TODO needed for markup.
1081 textbox_font(t, *type);
1082 // Move into list view.
1083 textbox_text(t, text);
1084 PangoAttrList *list = textbox_get_pango_attributes(t);
1085 if (list != NULL) {
1086 pango_attr_list_ref(list);
1087 } else {
1088 list = pango_attr_list_new();
1089 }
1090
1091 if (state->tokens) {
1093 {0.0, 0.0, 0.0, 0.0}};
1094 th = rofi_theme_get_highlight(WIDGET(t), "highlight", th);
1096 textbox_get_visible_text(t), list);
1097 }
1098 for (GList *iter = g_list_first(add_list); iter != NULL;
1099 iter = g_list_next(iter)) {
1100 pango_attr_list_insert(list, (PangoAttribute *)(iter->data));
1101 }
1103 pango_attr_list_unref(list);
1104 }
1105 g_list_free(add_list);
1106 g_free(text);
1107 } else {
1108 // Never called.
1109 int fstate = 0;
1110 mode_get_display_value(state->sw, state->line_map[index], &fstate, NULL,
1111 FALSE);
1112 (*type) |= fstate;
1113 // TODO needed for markup.
1114 textbox_font(t, *type);
1115 }
1116}
1117
1118void rofi_view_update(RofiViewState *state, gboolean qr) {
1119 if (!widget_need_redraw(WIDGET(state->main_window))) {
1120 return;
1121 }
1122 g_debug("Redraw view");
1123 TICK();
1124 cairo_t *d = CacheState.edit_draw;
1125 cairo_set_operator(d, CAIRO_OPERATOR_SOURCE);
1126 if (CacheState.fake_bg != NULL) {
1127 if (CacheState.fake_bgrel) {
1128 cairo_set_source_surface(d, CacheState.fake_bg, 0.0, 0.0);
1129 } else {
1130 cairo_set_source_surface(d, CacheState.fake_bg,
1131 -(double)(state->x - CacheState.mon.x),
1132 -(double)(state->y - CacheState.mon.y));
1133 }
1134 cairo_paint(d);
1135 cairo_set_operator(d, CAIRO_OPERATOR_OVER);
1136 } else {
1137 // Paint the background transparent.
1138 cairo_set_source_rgba(d, 0, 0, 0, 0.0);
1139 cairo_paint(d);
1140 }
1141 TICK_N("Background");
1142
1143 // Always paint as overlay over the background.
1144 cairo_set_operator(d, CAIRO_OPERATOR_OVER);
1145 widget_draw(WIDGET(state->main_window), d);
1146
1147 TICK_N("widgets");
1148 cairo_surface_flush(CacheState.edit_surf);
1149 if (qr) {
1151 }
1152}
1153
1155 g_free(state->line_map);
1156 g_free(state->distance);
1157 state->num_lines = mode_get_num_entries(state->sw);
1158 state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
1159 state->distance = g_malloc0_n(state->num_lines, sizeof(int));
1162}
1163
1165 CacheState.refilter_timeout = 0;
1166 CacheState.refilter_timeout_count = 0;
1167 if (state->sw == NULL) {
1168 return G_SOURCE_REMOVE;
1169 }
1170 TICK_N("Filter start");
1171 if (state->reload) {
1172 _rofi_view_reload_row(state);
1173 state->reload = FALSE;
1174 }
1175 TICK_N("Filter reload rows");
1176 if (state->tokens) {
1178 state->tokens = NULL;
1179 }
1180 TICK_N("Filter tokenize");
1181 if (state->text && strlen(state->text->text) > 0) {
1182
1183 listview_set_filtered(state->list_view, TRUE);
1184 unsigned int j = 0;
1185 gchar *pattern = mode_preprocess_input(state->sw, state->text->text);
1186 glong plen = pattern ? g_utf8_strlen(pattern, -1) : 0;
1187 state->tokens = helper_tokenize(pattern, config.case_sensitive);
1195 unsigned int nt = MAX(1, state->num_lines / 500);
1196 // Limit the number of jobs, it could cause stack overflow if we don´t
1197 // limit.
1198 nt = MIN(nt, config.threads * 4);
1199 thread_state_view states[nt];
1200 GCond cond;
1201 GMutex mutex;
1202 g_mutex_init(&mutex);
1203 g_cond_init(&cond);
1204 unsigned int count = nt;
1205 unsigned int steps = (state->num_lines + nt) / nt;
1206 for (unsigned int i = 0; i < nt; i++) {
1207 states[i].state = state;
1208 states[i].start = i * steps;
1209 states[i].stop = MIN(state->num_lines, (i + 1) * steps);
1210 states[i].count = 0;
1211 states[i].cond = &cond;
1212 states[i].mutex = &mutex;
1213 states[i].acount = &count;
1214 states[i].plen = plen;
1215 states[i].pattern = pattern;
1216 states[i].st.callback = filter_elements;
1217 if (i > 0) {
1218 g_thread_pool_push(tpool, &states[i], NULL);
1219 }
1220 }
1221 // Run one in this thread.
1222 rofi_view_call_thread(&states[0], NULL);
1223 // No need to do this with only one thread.
1224 if (nt > 1) {
1225 g_mutex_lock(&mutex);
1226 while (count > 0) {
1227 g_cond_wait(&cond, &mutex);
1228 }
1229 g_mutex_unlock(&mutex);
1230 }
1231 g_cond_clear(&cond);
1232 g_mutex_clear(&mutex);
1233 for (unsigned int i = 0; i < nt; i++) {
1234 if (j != states[i].start) {
1235 memmove(&(state->line_map[j]), &(state->line_map[states[i].start]),
1236 sizeof(unsigned int) * (states[i].count));
1237 }
1238 j += states[i].count;
1239 }
1240 if (config.sort) {
1241 g_qsort_with_data(state->line_map, j, sizeof(int), lev_sort,
1242 state->distance);
1243 }
1244
1245 // Cleanup + bookkeeping.
1246 state->filtered_lines = j;
1247 g_free(pattern);
1248 } else {
1249 listview_set_filtered(state->list_view, FALSE);
1250 for (unsigned int i = 0; i < state->num_lines; i++) {
1251 state->line_map[i] = i;
1252 }
1253 state->filtered_lines = state->num_lines;
1254 }
1255 TICK_N("Filter matching done");
1257
1258 if (state->tb_filtered_rows) {
1259 char *r = g_strdup_printf("%u", state->filtered_lines);
1260 textbox_text(state->tb_filtered_rows, r);
1261 g_free(r);
1262 }
1263 if (state->tb_total_rows) {
1264 char *r = g_strdup_printf("%u", state->num_lines);
1265 textbox_text(state->tb_total_rows, r);
1266 g_free(r);
1267 }
1268 TICK_N("Update filter lines");
1269
1270 if (config.auto_select == TRUE && state->filtered_lines == 1 &&
1271 state->num_lines > 1) {
1272 (state->selected_line) =
1274 state->retv = MENU_OK;
1275 state->quit = TRUE;
1276 }
1277
1278 // Size the window.
1279 int height = rofi_view_calculate_height(state);
1280 if (height != state->height) {
1281 state->height = height;
1284 g_debug("Resize based on re-filter");
1285 }
1286 TICK_N("Filter resize window based on window ");
1287 state->refilter = FALSE;
1288 TICK_N("Filter done");
1289 rofi_view_update(state, TRUE);
1290 return G_SOURCE_REMOVE;
1291}
1293 CacheState.refilter_timeout_count++;
1294 if (CacheState.refilter_timeout != 0) {
1295
1296 g_source_remove(CacheState.refilter_timeout);
1297 CacheState.refilter_timeout = 0;
1298 }
1300 CacheState.refilter_timeout_count < 25 && state->text &&
1301 strlen(state->text->text) > 0) {
1302 CacheState.refilter_timeout =
1303 g_timeout_add(200, (GSourceFunc)rofi_view_refilter_real, state);
1304 } else {
1306 }
1307}
1309 if (CacheState.refilter_timeout != 0) {
1310 g_source_remove(CacheState.refilter_timeout);
1311 CacheState.refilter_timeout = 0;
1312 }
1313 if (state->refilter) {
1315 }
1316}
1322void process_result(RofiViewState *state);
1324 if (state && state->finalize != NULL) {
1325 state->finalize(state);
1326 }
1327}
1328
1333static void rofi_view_input_changed() { rofi_view_take_action("inputchange"); }
1334
1337 switch (action) {
1338 // Handling of paste
1339 case PASTE_PRIMARY:
1340 xcb_convert_selection(xcb->connection, CacheState.main_window,
1341 XCB_ATOM_PRIMARY, xcb->ewmh.UTF8_STRING,
1342 xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1343 xcb_flush(xcb->connection);
1344 break;
1345 case PASTE_SECONDARY:
1346 xcb_convert_selection(xcb->connection, CacheState.main_window,
1347 netatoms[CLIPBOARD], xcb->ewmh.UTF8_STRING,
1348 xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1349 xcb_flush(xcb->connection);
1350 break;
1351 case SCREENSHOT:
1353 break;
1354 case CHANGE_ELLIPSIZE:
1355 if (state->list_view) {
1357 }
1358 break;
1359 case TOGGLE_SORT:
1360 if (state->case_indicator != NULL) {
1362 state->refilter = TRUE;
1364 }
1365 break;
1366 case MODE_PREVIOUS:
1367 state->retv = MENU_PREVIOUS;
1368 (state->selected_line) = 0;
1369 state->quit = TRUE;
1370 break;
1371 // Menu navigation.
1372 case MODE_NEXT:
1373 state->retv = MENU_NEXT;
1374 (state->selected_line) = 0;
1375 state->quit = TRUE;
1376 break;
1377 case MODE_COMPLETE: {
1378 unsigned int selected = listview_get_selected(state->list_view);
1379 state->selected_line = UINT32_MAX;
1380 if (selected < state->filtered_lines) {
1381 state->selected_line = state->line_map[selected];
1382 }
1383 state->retv = MENU_COMPLETE;
1384 state->quit = TRUE;
1385 break;
1386 }
1387 // Toggle case sensitivity.
1389 if (state->case_indicator != NULL) {
1391 (state->selected_line) = 0;
1392 state->refilter = TRUE;
1394 }
1395 break;
1396 // Special delete entry command.
1397 case DELETE_ENTRY: {
1398 unsigned int selected = listview_get_selected(state->list_view);
1399 if (selected < state->filtered_lines) {
1400 (state->selected_line) = state->line_map[selected];
1401 state->retv = MENU_ENTRY_DELETE;
1402 state->quit = TRUE;
1403 }
1404 break;
1405 }
1406 case SELECT_ELEMENT_1:
1407 case SELECT_ELEMENT_2:
1408 case SELECT_ELEMENT_3:
1409 case SELECT_ELEMENT_4:
1410 case SELECT_ELEMENT_5:
1411 case SELECT_ELEMENT_6:
1412 case SELECT_ELEMENT_7:
1413 case SELECT_ELEMENT_8:
1414 case SELECT_ELEMENT_9:
1415 case SELECT_ELEMENT_10: {
1416 unsigned int index = action - SELECT_ELEMENT_1;
1417 if (index < state->filtered_lines) {
1418 state->selected_line = state->line_map[index];
1419 state->retv = MENU_OK;
1420 state->quit = TRUE;
1421 }
1422 break;
1423 }
1424 case CUSTOM_1:
1425 case CUSTOM_2:
1426 case CUSTOM_3:
1427 case CUSTOM_4:
1428 case CUSTOM_5:
1429 case CUSTOM_6:
1430 case CUSTOM_7:
1431 case CUSTOM_8:
1432 case CUSTOM_9:
1433 case CUSTOM_10:
1434 case CUSTOM_11:
1435 case CUSTOM_12:
1436 case CUSTOM_13:
1437 case CUSTOM_14:
1438 case CUSTOM_15:
1439 case CUSTOM_16:
1440 case CUSTOM_17:
1441 case CUSTOM_18:
1442 case CUSTOM_19: {
1443 state->selected_line = UINT32_MAX;
1444 unsigned int selected = listview_get_selected(state->list_view);
1445 if (selected < state->filtered_lines) {
1446 (state->selected_line) = state->line_map[selected];
1447 }
1448 state->retv = MENU_CUSTOM_COMMAND | ((action - CUSTOM_1) & MENU_LOWER_MASK);
1449 state->quit = TRUE;
1450 break;
1451 }
1452 // If you add a binding here, make sure to add it to
1453 // rofi_view_keyboard_navigation too
1454 case CANCEL:
1455 state->retv = MENU_CANCEL;
1456 state->quit = TRUE;
1457 break;
1458 case ELEMENT_NEXT:
1460 break;
1461 case ELEMENT_PREV:
1463 break;
1464 case ROW_UP:
1465 listview_nav_up(state->list_view);
1466 break;
1467 case ROW_TAB:
1468 rofi_view_nav_row_tab(state);
1469 break;
1470 case ROW_DOWN:
1472 break;
1473 case ROW_LEFT:
1475 break;
1476 case ROW_RIGHT:
1478 break;
1479 case PAGE_PREV:
1481 break;
1482 case PAGE_NEXT:
1484 break;
1485 case ROW_FIRST:
1486 rofi_view_nav_first(state);
1487 break;
1488 case ROW_LAST:
1489 rofi_view_nav_last(state);
1490 break;
1491 case ROW_SELECT:
1493 break;
1494 // If you add a binding here, make sure to add it to textbox_keybinding too
1495 case MOVE_CHAR_BACK: {
1496 if (textbox_keybinding(state->text, action) == 0) {
1498 }
1499 break;
1500 }
1501 case MOVE_CHAR_FORWARD: {
1502 if (textbox_keybinding(state->text, action) == 0) {
1504 }
1505 break;
1506 }
1507 case CLEAR_LINE:
1508 case MOVE_FRONT:
1509 case MOVE_END:
1510 case REMOVE_TO_EOL:
1511 case REMOVE_TO_SOL:
1512 case REMOVE_WORD_BACK:
1515 case MOVE_WORD_BACK:
1516 case MOVE_WORD_FORWARD:
1517 case REMOVE_CHAR_BACK: {
1518 int rc = textbox_keybinding(state->text, action);
1519 if (rc == 1) {
1520 // Entry changed.
1521 state->refilter = TRUE;
1523 } else if (rc == 2) {
1524 // Movement.
1525 }
1526 break;
1527 }
1528 case ACCEPT_ALT: {
1530 unsigned int selected = listview_get_selected(state->list_view);
1531 state->selected_line = UINT32_MAX;
1532 if (selected < state->filtered_lines) {
1533 (state->selected_line) = state->line_map[selected];
1534 state->retv = MENU_OK;
1535 } else {
1536 // Nothing entered and nothing selected.
1537 state->retv = MENU_CUSTOM_INPUT;
1538 }
1539 state->retv |= MENU_CUSTOM_ACTION;
1540 state->quit = TRUE;
1541 break;
1542 }
1543 case ACCEPT_CUSTOM: {
1545 state->selected_line = UINT32_MAX;
1546 state->retv = MENU_CUSTOM_INPUT;
1547 state->quit = TRUE;
1548 break;
1549 }
1550 case ACCEPT_CUSTOM_ALT: {
1552 state->selected_line = UINT32_MAX;
1554 state->quit = TRUE;
1555 break;
1556 }
1557 case ACCEPT_ENTRY: {
1559 // If a valid item is selected, return that..
1560 unsigned int selected = listview_get_selected(state->list_view);
1561 state->selected_line = UINT32_MAX;
1562 if (selected < state->filtered_lines) {
1563 (state->selected_line) = state->line_map[selected];
1564 state->retv = MENU_OK;
1565 } else {
1566 // Nothing entered and nothing selected.
1567 state->retv = MENU_CUSTOM_INPUT;
1568 }
1569
1570 state->quit = TRUE;
1571 break;
1572 }
1573 }
1574}
1575
1577 guint action) {
1578 switch (scope) {
1579 case SCOPE_GLOBAL:
1580 return TRUE;
1586 gint x = state->mouse.x, y = state->mouse.y;
1588 (WidgetType)scope, x, y);
1589 if (target == NULL) {
1590 return FALSE;
1591 }
1592 widget_xy_to_relative(target, &x, &y);
1593 switch (widget_check_action(target, action, x, y)) {
1595 return FALSE;
1599 return TRUE;
1600 }
1601 break;
1602 }
1603 }
1604 return FALSE;
1605}
1606
1608 guint action) {
1610 switch (scope) {
1611 case SCOPE_GLOBAL:
1613 return;
1619 gint x = state->mouse.x, y = state->mouse.y;
1621 (WidgetType)scope, x, y);
1622 if (target == NULL) {
1623 return;
1624 }
1625 widget_xy_to_relative(target, &x, &y);
1626 switch (widget_trigger_action(target, action, x, y)) {
1628 return;
1630 target = NULL;
1631 /* FALLTHRU */
1633 state->mouse.motion_target = target;
1634 /* FALLTHRU */
1636 return;
1637 }
1638 break;
1639 }
1640 }
1641}
1642
1643void rofi_view_handle_text(RofiViewState *state, char *text) {
1644 if (textbox_append_text(state->text, text, strlen(text))) {
1645 state->refilter = TRUE;
1647 }
1648}
1649
1651 switch (type) {
1653 return CURSOR_DEFAULT;
1654
1656 return CURSOR_POINTER;
1657
1658 case ROFI_CURSOR_TEXT:
1659 return CURSOR_TEXT;
1660 }
1661
1662 return CURSOR_DEFAULT;
1663}
1664
1666 gint y) {
1668 WIDGET_TYPE_UNKNOWN, x, y);
1669
1670 return target != NULL ? target->cursor_type : ROFI_CURSOR_DEFAULT;
1671}
1672
1675
1676 if (x11_type == CacheState.cursor_type) {
1677 return;
1678 }
1679
1680 CacheState.cursor_type = x11_type;
1681
1682 x11_set_cursor(CacheState.main_window, x11_type);
1683}
1684
1686 gboolean find_mouse_target) {
1687 state->mouse.x = x;
1688 state->mouse.y = y;
1689
1691
1693
1694 if (find_mouse_target) {
1697
1698 if (target != NULL) {
1699 state->mouse.motion_target = target;
1700 }
1701 }
1702
1703 if (state->mouse.motion_target != NULL) {
1706
1707 if (find_mouse_target) {
1708 state->mouse.motion_target = NULL;
1709 }
1710 }
1711}
1712
1714 if (rofi_view_get_completed(state)) {
1715 // This menu is done.
1716 rofi_view_finalize(state);
1717 // If there a state. (for example error) reload it.
1718 state = rofi_view_get_active();
1719
1720 // cleanup, if no more state to display.
1721 if (state == NULL) {
1722 // Quit main-loop.
1724 return;
1725 }
1726 }
1727
1728 // Update if requested.
1729 if (state->refilter) {
1730 rofi_view_refilter(state);
1731 }
1732 rofi_view_update(state, TRUE);
1733 return;
1734}
1735
1741 xcb_configure_notify_event_t *xce) {
1742 if (xce->window == CacheState.main_window) {
1743 if (state->x != xce->x || state->y != xce->y) {
1744 state->x = xce->x;
1745 state->y = xce->y;
1747 }
1748 if (state->width != xce->width || state->height != xce->height) {
1749 state->width = xce->width;
1750 state->height = xce->height;
1751
1752 cairo_destroy(CacheState.edit_draw);
1753 cairo_surface_destroy(CacheState.edit_surf);
1754
1755 xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
1756 CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
1757 xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
1758 CacheState.main_window, state->width, state->height);
1759
1760 CacheState.edit_surf =
1761 cairo_xcb_surface_create(xcb->connection, CacheState.edit_pixmap,
1762 visual, state->width, state->height);
1763 CacheState.edit_draw = cairo_create(CacheState.edit_surf);
1764 g_debug("Re-size window based external request: %d %d", state->width,
1765 state->height);
1766 widget_resize(WIDGET(state->main_window), state->width, state->height);
1767 }
1768 }
1769}
1770
1774void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target) {
1775 if ((CacheState.flags & MENU_NORMAL_WINDOW) == 0) {
1776 if (target != CacheState.main_window) {
1777 state->quit = TRUE;
1778 state->retv = MENU_CANCEL;
1779 }
1780 }
1781}
1782
1784 if (CacheState.repaint_source == 0) {
1785 CacheState.count++;
1786 g_debug("redraw %llu", CacheState.count);
1787 CacheState.repaint_source =
1788 g_idle_add_full(G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL);
1789 }
1790}
1791
1793 if (CacheState.fullscreen == TRUE) {
1794 return CacheState.mon.h;
1795 }
1796
1797 RofiDistance h =
1798 rofi_theme_get_distance(WIDGET(state->main_window), "height", 0);
1799 unsigned int height = distance_get_pixel(h, ROFI_ORIENTATION_VERTICAL);
1800 // If height is set, return it.
1801 if (height > 0) {
1802 return height;
1803 }
1804 // Autosize based on widgets.
1807}
1808
1810 widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1811 G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1812 RofiViewState *state = (RofiViewState *)user_data;
1813 switch (action) {
1814 case MOUSE_CLICK_DOWN: {
1815 const char *type = rofi_theme_get_string(wid, "action", NULL);
1816 if (type) {
1817 if (state->list_view) {
1818 (state->selected_line) =
1820 } else {
1821 (state->selected_line) = UINT32_MAX;
1822 }
1823 guint id = key_binding_get_action_from_name(type);
1824 if (id != UINT32_MAX) {
1826 }
1827 state->skip_absorb = TRUE;
1829 }
1830 }
1831 case MOUSE_CLICK_UP:
1832 case MOUSE_DCLICK_DOWN:
1833 case MOUSE_DCLICK_UP:
1834 break;
1835 }
1837}
1839 widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1840 G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1841 RofiViewState *state = (RofiViewState *)user_data;
1842 unsigned int i;
1843 for (i = 0; i < state->num_modes; i++) {
1844 if (WIDGET(state->modes[i]) == wid) {
1845 break;
1846 }
1847 }
1848 if (i == state->num_modes) {
1850 }
1851
1852 switch (action) {
1853 case MOUSE_CLICK_DOWN:
1854 state->retv = MENU_QUICK_SWITCH | (i & MENU_LOWER_MASK);
1855 state->quit = TRUE;
1856 state->skip_absorb = TRUE;
1858 case MOUSE_CLICK_UP:
1859 case MOUSE_DCLICK_DOWN:
1860 case MOUSE_DCLICK_UP:
1861 break;
1862 }
1864}
1865
1866// @TODO don't like this construction.
1867static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom,
1868 void *udata) {
1869 RofiViewState *state = (RofiViewState *)udata;
1870 state->retv = MENU_OK;
1871 if (custom) {
1872 state->retv |= MENU_CUSTOM_ACTION;
1873 }
1874 (state->selected_line) = state->line_map[listview_get_selected(lv)];
1875 // Quit
1876 state->quit = TRUE;
1877 state->skip_absorb = TRUE;
1878}
1879
1880static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget,
1881 const char *name) {
1882 char *defaults = NULL;
1883 widget *wid = NULL;
1884
1888 if (strcmp(name, "mainbox") == 0) {
1889 wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
1890 box_add((box *)parent_widget, WIDGET(wid), TRUE);
1891 if (config.sidebar_mode) {
1892 defaults = "inputbar,message,listview,mode-switcher";
1893 } else {
1894 defaults = "inputbar,message,listview";
1895 }
1896 }
1900 else if (strcmp(name, "inputbar") == 0) {
1901 wid =
1902 (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
1903 defaults = "prompt,entry,overlay,case-indicator";
1904 box_add((box *)parent_widget, WIDGET(wid), FALSE);
1905 }
1909 else if (strcmp(name, "prompt") == 0) {
1910 if (state->prompt != NULL) {
1911 g_error("Prompt widget can only be added once to the layout.");
1912 return;
1913 }
1914 // Prompt box.
1915 state->prompt =
1916 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1917 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1919 box_add((box *)parent_widget, WIDGET(state->prompt), FALSE);
1920 defaults = NULL;
1921 } else if (strcmp(name, "num-rows") == 0) {
1922 state->tb_total_rows =
1923 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1924 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1925 box_add((box *)parent_widget, WIDGET(state->tb_total_rows), FALSE);
1926 defaults = NULL;
1927 } else if (strcmp(name, "num-filtered-rows") == 0) {
1928 state->tb_filtered_rows =
1929 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1930 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1931 box_add((box *)parent_widget, WIDGET(state->tb_filtered_rows), FALSE);
1932 defaults = NULL;
1933 } else if (strcmp(name, "textbox-current-entry") == 0) {
1934 state->tb_current_entry =
1935 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1936 TB_MARKUP | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1937 box_add((box *)parent_widget, WIDGET(state->tb_current_entry), FALSE);
1938 defaults = NULL;
1939 } else if (strcmp(name, "icon-current-entry") == 0) {
1940 state->icon_current_entry = icon_create(parent_widget, name);
1941 box_add((box *)parent_widget, WIDGET(state->icon_current_entry), FALSE);
1942 defaults = NULL;
1943 }
1947 else if (strcmp(name, "case-indicator") == 0) {
1948 if (state->case_indicator != NULL) {
1949 g_error("Case indicator widget can only be added once to the layout.");
1950 return;
1951 }
1952 state->case_indicator =
1953 textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1954 TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*", 0, 0);
1955 // Add small separator between case indicator and text box.
1956 box_add((box *)parent_widget, WIDGET(state->case_indicator), FALSE);
1958 }
1962 else if (strcmp(name, "entry") == 0) {
1963 if (state->text != NULL) {
1964 g_error("Entry textbox widget can only be added once to the layout.");
1965 return;
1966 }
1967 // Entry box
1969 tfl |= ((state->menu_flags & MENU_PASSWORD) == MENU_PASSWORD) ? TB_PASSWORD
1970 : 0;
1971 state->text = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
1972 tfl | TB_AUTOHEIGHT, NORMAL, NULL, 0, 0);
1973 box_add((box *)parent_widget, WIDGET(state->text), TRUE);
1974 }
1978 else if (strcmp(name, "message") == 0) {
1979 if (state->mesg_box != NULL) {
1980 g_error("Message widget can only be added once to the layout.");
1981 return;
1982 }
1983 state->mesg_box = container_create(parent_widget, name);
1984 state->mesg_tb = textbox_create(
1985 WIDGET(state->mesg_box), WIDGET_TYPE_TEXTBOX_TEXT, "textbox",
1986 TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL, 0, 0);
1987 container_add(state->mesg_box, WIDGET(state->mesg_tb));
1989 box_add((box *)parent_widget, WIDGET(state->mesg_box), FALSE);
1990 }
1994 else if (strcmp(name, "listview") == 0) {
1995 if (state->list_view != NULL) {
1996 g_error("Listview widget can only be added once to the layout.");
1997 return;
1998 }
1999 state->list_view = listview_create(parent_widget, name, update_callback,
2000 state, config.element_height, 0);
2002 state->list_view, selection_changed_callback, (void *)state);
2003 box_add((box *)parent_widget, WIDGET(state->list_view), TRUE);
2006 state->list_view, rofi_view_listview_mouse_activated_cb, state);
2007
2008 int lines = rofi_theme_get_integer(WIDGET(state->list_view), "lines",
2010 listview_set_num_lines(state->list_view, lines);
2011 listview_set_max_lines(state->list_view, state->num_lines);
2012 }
2016 else if (strcmp(name, "mode-switcher") == 0 || strcmp(name, "sidebar") == 0) {
2017 if (state->sidebar_bar != NULL) {
2018 g_error("Mode-switcher can only be added once to the layout.");
2019 return;
2020 }
2021 state->sidebar_bar =
2022 box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
2023 box_add((box *)parent_widget, WIDGET(state->sidebar_bar), FALSE);
2025 state->modes = g_malloc0(state->num_modes * sizeof(textbox *));
2026 for (unsigned int j = 0; j < state->num_modes; j++) {
2027 const Mode *mode = rofi_get_mode(j);
2028 state->modes[j] = textbox_create(
2029 WIDGET(state->sidebar_bar), WIDGET_TYPE_MODE_SWITCHER, "button",
2030 TB_AUTOHEIGHT, (mode == state->sw) ? HIGHLIGHT : NORMAL,
2031 mode_get_display_name(mode), 0.5, 0.5);
2032 box_add(state->sidebar_bar, WIDGET(state->modes[j]), TRUE);
2035 }
2036 } else if (g_ascii_strcasecmp(name, "overlay") == 0) {
2037 state->overlay = textbox_create(
2038 WIDGET(parent_widget), WIDGET_TYPE_TEXTBOX_TEXT, "overlay",
2039 TB_AUTOWIDTH | TB_AUTOHEIGHT, URGENT, "blaat", 0.5, 0);
2040 box_add((box *)parent_widget, WIDGET(state->overlay), FALSE);
2041 widget_disable(WIDGET(state->overlay));
2042 } else if (g_ascii_strncasecmp(name, "textbox", 7) == 0) {
2043 textbox *t = textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
2044 TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
2045 box_add((box *)parent_widget, WIDGET(t), TRUE);
2046 } else if (g_ascii_strncasecmp(name, "button", 6) == 0) {
2047 textbox *t = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
2048 TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
2049 box_add((box *)parent_widget, WIDGET(t), TRUE);
2051 state);
2052 } else if (g_ascii_strncasecmp(name, "icon", 4) == 0) {
2053 icon *t = icon_create(parent_widget, name);
2054 /* small hack to make it clickable */
2055 const char *type = rofi_theme_get_string(WIDGET(t), "action", NULL);
2056 if (type) {
2057 WIDGET(t)->type = WIDGET_TYPE_EDITBOX;
2058 }
2059 box_add((box *)parent_widget, WIDGET(t), TRUE);
2061 state);
2062 } else {
2063 wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
2064 box_add((box *)parent_widget, WIDGET(wid), TRUE);
2065 // g_error("The widget %s does not exists. Invalid layout.", name);
2066 }
2067 if (wid) {
2068 GList *list = rofi_theme_get_list_strings(wid, "children");
2069 if (list == NULL) {
2070 if (defaults) {
2071 char **a = g_strsplit(defaults, ",", 0);
2072 for (int i = 0; a && a[i]; i++) {
2073 rofi_view_add_widget(state, wid, a[i]);
2074 }
2075 g_strfreev(a);
2076 }
2077 } else {
2078 for (const GList *iter = g_list_first(list); iter != NULL;
2079 iter = g_list_next(iter)) {
2080 rofi_view_add_widget(state, wid, (const char *)iter->data);
2081 }
2082 g_list_free_full(list, g_free);
2083 }
2084 }
2085}
2086
2088 xcb_query_pointer_cookie_t pointer_cookie =
2089 xcb_query_pointer(xcb->connection, CacheState.main_window);
2090 xcb_query_pointer_reply_t *pointer_reply =
2091 xcb_query_pointer_reply(xcb->connection, pointer_cookie, NULL);
2092
2093 if (pointer_reply == NULL) {
2094 return;
2095 }
2096
2097 rofi_view_handle_mouse_motion(state, pointer_reply->win_x,
2098 pointer_reply->win_y, config.hover_select);
2099
2100 free(pointer_reply);
2101}
2102
2103RofiViewState *rofi_view_create(Mode *sw, const char *input,
2104 MenuFlags menu_flags,
2105 void (*finalize)(RofiViewState *)) {
2106 TICK();
2108 state->menu_flags = menu_flags;
2109 state->sw = sw;
2110 state->selected_line = UINT32_MAX;
2111 state->retv = MENU_CANCEL;
2112 state->distance = NULL;
2113 state->quit = FALSE;
2114 state->skip_absorb = FALSE;
2115 // We want to filter on the first run.
2116 state->refilter = TRUE;
2117 state->finalize = finalize;
2118 state->mouse_seen = FALSE;
2119
2120 // Request the lines to show.
2121 state->num_lines = mode_get_num_entries(sw);
2122
2123 if (state->sw) {
2124 char *title =
2125 g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
2127 g_free(title);
2128 } else {
2130 }
2131 TICK_N("Startup notification");
2132
2133 // Get active monitor size.
2134 TICK_N("Get active monitor");
2135
2136 state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
2137 // Get children.
2138 GList *list =
2139 rofi_theme_get_list_strings(WIDGET(state->main_window), "children");
2140 if (list == NULL) {
2141 rofi_view_add_widget(state, WIDGET(state->main_window), "mainbox");
2142 } else {
2143 for (const GList *iter = list; iter != NULL; iter = g_list_next(iter)) {
2145 (const char *)iter->data);
2146 }
2147 g_list_free_full(list, g_free);
2148 }
2149
2150 if (state->text && input) {
2151 textbox_text(state->text, input);
2152 textbox_cursor_end(state->text);
2153 }
2154
2155 // filtered list
2156 state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
2157 state->distance = (int *)g_malloc0_n(state->num_lines, sizeof(int));
2158
2160 // Only needed when window is fixed size.
2163 }
2164
2165 state->height = rofi_view_calculate_height(state);
2166 // Move the window to the correct x,y position.
2169
2170 state->quit = FALSE;
2171 rofi_view_refilter(state);
2172 rofi_view_update(state, TRUE);
2173 xcb_map_window(xcb->connection, CacheState.main_window);
2175 rofi_view_ping_mouse(state);
2176 xcb_flush(xcb->connection);
2177
2179 /* When Override Redirect, the WM will not let us know we can take focus, so
2180 * just steal it */
2181 if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) {
2183 }
2184
2185 if (xcb->sncontext != NULL) {
2186 sn_launchee_context_complete(xcb->sncontext);
2187 }
2188 return state;
2189}
2190
2191int rofi_view_error_dialog(const char *msg, int markup) {
2193 state->retv = MENU_CANCEL;
2195 state->finalize = process_result;
2196
2197 state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
2198 box *box = box_create(WIDGET(state->main_window), "error-message",
2200 box_add(state->main_window, WIDGET(box), TRUE);
2201 state->text =
2203 (TB_AUTOHEIGHT | TB_WRAP) + ((markup) ? TB_MARKUP : 0),
2204 NORMAL, (msg != NULL) ? msg : "", 0, 0);
2205 box_add(box, WIDGET(state->text), TRUE);
2206
2207 // Make sure we enable fixed num lines when in normal window mode.
2210 }
2212 state->height = rofi_view_calculate_height(state);
2213
2214 // Calculate window position.
2216
2217 // Move the window to the correct x,y position.
2219
2220 // Display it.
2221 xcb_map_window(xcb->connection, CacheState.main_window);
2223
2224 if (xcb->sncontext != NULL) {
2225 sn_launchee_context_complete(xcb->sncontext);
2226 }
2227
2228 // Set it as current window.
2229 rofi_view_set_active(state);
2230 return TRUE;
2231}
2232
2233void rofi_view_hide(void) {
2234 if (CacheState.main_window != XCB_WINDOW_NONE) {
2236 xcb_unmap_window(xcb->connection, CacheState.main_window);
2238 }
2239}
2240
2242 g_debug("Cleanup.");
2243 if (CacheState.idle_timeout > 0) {
2244 g_source_remove(CacheState.idle_timeout);
2245 CacheState.idle_timeout = 0;
2246 }
2247 if (CacheState.refilter_timeout > 0) {
2248 g_source_remove(CacheState.refilter_timeout);
2249 CacheState.refilter_timeout = 0;
2250 }
2251 if (CacheState.user_timeout > 0) {
2252 g_source_remove(CacheState.user_timeout);
2253 CacheState.user_timeout = 0;
2254 }
2255 if (CacheState.repaint_source > 0) {
2256 g_source_remove(CacheState.repaint_source);
2257 CacheState.repaint_source = 0;
2258 }
2259 if (CacheState.fake_bg) {
2260 cairo_surface_destroy(CacheState.fake_bg);
2261 CacheState.fake_bg = NULL;
2262 }
2263 if (CacheState.edit_draw) {
2264 cairo_destroy(CacheState.edit_draw);
2265 CacheState.edit_draw = NULL;
2266 }
2267 if (CacheState.edit_surf) {
2268 cairo_surface_destroy(CacheState.edit_surf);
2269 CacheState.edit_surf = NULL;
2270 }
2271 if (CacheState.main_window != XCB_WINDOW_NONE) {
2272 g_debug("Unmapping and free'ing window");
2273 xcb_unmap_window(xcb->connection, CacheState.main_window);
2275 xcb_free_gc(xcb->connection, CacheState.gc);
2276 xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
2277 xcb_destroy_window(xcb->connection, CacheState.main_window);
2278 CacheState.main_window = XCB_WINDOW_NONE;
2279 }
2280 if (map != XCB_COLORMAP_NONE) {
2281 xcb_free_colormap(xcb->connection, map);
2282 map = XCB_COLORMAP_NONE;
2283 }
2284 xcb_flush(xcb->connection);
2285 g_assert(g_queue_is_empty(&(CacheState.views)));
2286}
2288 TICK_N("Setup Threadpool, start");
2289 if (config.threads == 0) {
2290 config.threads = 1;
2291 long procs = sysconf(_SC_NPROCESSORS_CONF);
2292 if (procs > 0) {
2293 config.threads = MIN(procs, 128l);
2294 }
2295 }
2296 // Create thread pool
2297 GError *error = NULL;
2298 tpool = g_thread_pool_new(rofi_view_call_thread, NULL, config.threads, FALSE,
2299 &error);
2300 if (error == NULL) {
2301 // Idle threads should stick around for a max of 60 seconds.
2302 g_thread_pool_set_max_idle_time(60000);
2303 // We are allowed to have
2304 g_thread_pool_set_max_threads(tpool, config.threads, &error);
2305 }
2306 // If error occurred during setup of pool, tell user and exit.
2307 if (error != NULL) {
2308 g_warning("Failed to setup thread pool: '%s'", error->message);
2309 g_error_free(error);
2310 exit(EXIT_FAILURE);
2311 }
2312 TICK_N("Setup Threadpool, done");
2313}
2315 if (tpool) {
2316 g_thread_pool_free(tpool, TRUE, TRUE);
2317 tpool = NULL;
2318 }
2319}
2320Mode *rofi_view_get_mode(RofiViewState *state) { return state->sw; }
2321
2322void rofi_view_set_overlay(RofiViewState *state, const char *text) {
2323 if (state->overlay == NULL || state->list_view == NULL) {
2324 return;
2325 }
2326 if (text == NULL) {
2327 widget_disable(WIDGET(state->overlay));
2328 return;
2329 }
2330 widget_enable(WIDGET(state->overlay));
2331 textbox_text(state->overlay, text);
2332 // We want to queue a repaint.
2334}
2335
2337 if (state->text) {
2338 textbox_text(state->text, "");
2340 }
2341}
2342
2346
2348 state->sw = mode;
2349 // Update prompt;
2350 if (state->prompt) {
2352 }
2353 if (state->sw) {
2354 char *title =
2355 g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
2357 g_free(title);
2358 } else {
2360 }
2361 if (state->sidebar_bar) {
2362 for (unsigned int j = 0; j < state->num_modes; j++) {
2363 const Mode *tb_mode = rofi_get_mode(j);
2364 textbox_font(state->modes[j],
2365 (tb_mode == state->sw) ? HIGHLIGHT : NORMAL);
2366 }
2367 }
2368 rofi_view_restart(state);
2369 state->reload = TRUE;
2370 state->refilter = TRUE;
2371 rofi_view_refilter(state);
2372 rofi_view_update(state, TRUE);
2373}
2374
2375xcb_window_t rofi_view_get_window(void) { return CacheState.main_window; }
2376
2377void rofi_view_set_window_title(const char *title) {
2378 ssize_t len = strlen(title);
2379 xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
2380 CacheState.main_window, xcb->ewmh._NET_WM_NAME,
2381 xcb->ewmh.UTF8_STRING, 8, len, title);
2382 xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
2383 CacheState.main_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
2384 8, len, title);
2385}
@ WL_SOUTH_EAST
Definition rofi-types.h:251
@ WL_CENTER
Definition rofi-types.h:237
@ WL_NORTH_WEST
Definition rofi-types.h:247
@ WL_SOUTH
Definition rofi-types.h:243
@ WL_NORTH_EAST
Definition rofi-types.h:249
@ WL_WEST
Definition rofi-types.h:245
@ WL_NORTH
Definition rofi-types.h:239
@ WL_EAST
Definition rofi-types.h:241
@ WL_SOUTH_WEST
Definition rofi-types.h:253
PangoAttrList * helper_token_match_get_pango_attr(RofiHighlightColorStyle th, rofi_int_matcher **tokens, const char *input, PangoAttrList *retv)
Definition helper.c:487
gboolean helper_validate_font(PangoFontDescription *pfd, const char *font)
Definition helper.c:628
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Definition helper.c:263
void helper_tokenize_free(rofi_int_matcher **tokens)
Definition helper.c:119
unsigned int levenshtein(const char *needle, const glong needlelen, const char *haystack, const glong haystacklen)
Definition helper.c:772
char * rofi_expand_path(const char *input)
Definition helper.c:740
int rofi_scorer_fuzzy_evaluate(const char *pattern, glong plen, const char *str, glong slen)
Definition helper.c:920
guint key_binding_get_action_from_name(const char *name)
Definition keyb.c:396
BindingsScope
Definition keyb.h:43
KeyBindingAction
Definition keyb.h:58
MouseBindingMouseDefaultAction
Definition keyb.h:168
@ 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:109
@ CUSTOM_4
Definition keyb.h:115
@ CUSTOM_17
Definition keyb.h:128
@ CUSTOM_12
Definition keyb.h:123
@ CUSTOM_9
Definition keyb.h:120
@ REMOVE_TO_SOL
Definition keyb.h:88
@ ROW_RIGHT
Definition keyb.h:100
@ ROW_UP
Definition keyb.h:101
@ CUSTOM_8
Definition keyb.h:119
@ SELECT_ELEMENT_9
Definition keyb.h:142
@ MOVE_FRONT
Definition keyb.h:66
@ REMOVE_WORD_FORWARD
Definition keyb.h:80
@ CHANGE_ELLIPSIZE
Definition keyb.h:132
@ ACCEPT_CUSTOM_ALT
Definition keyb.h:93
@ REMOVE_WORD_BACK
Definition keyb.h:78
@ TOGGLE_SORT
Definition keyb.h:133
@ ACCEPT_ENTRY
Definition keyb.h:90
@ ROW_TAB
Definition keyb.h:103
@ PAGE_NEXT
Definition keyb.h:107
@ TOGGLE_CASE_SENSITIVITY
Definition keyb.h:97
@ ELEMENT_NEXT
Definition keyb.h:104
@ MOVE_CHAR_FORWARD
Definition keyb.h:76
@ MOVE_WORD_FORWARD
Definition keyb.h:72
@ MODE_COMPLETE
Definition keyb.h:95
@ CUSTOM_1
Definition keyb.h:112
@ SELECT_ELEMENT_6
Definition keyb.h:139
@ CUSTOM_18
Definition keyb.h:129
@ CUSTOM_15
Definition keyb.h:126
@ CUSTOM_11
Definition keyb.h:122
@ ACCEPT_CUSTOM
Definition keyb.h:92
@ CUSTOM_5
Definition keyb.h:116
@ CUSTOM_19
Definition keyb.h:130
@ REMOVE_TO_EOL
Definition keyb.h:86
@ SELECT_ELEMENT_3
Definition keyb.h:136
@ ROW_SELECT
Definition keyb.h:110
@ PASTE_PRIMARY
Definition keyb.h:60
@ ROW_DOWN
Definition keyb.h:102
@ CUSTOM_13
Definition keyb.h:124
@ PASTE_SECONDARY
Definition keyb.h:62
@ SELECT_ELEMENT_10
Definition keyb.h:143
@ PAGE_PREV
Definition keyb.h:106
@ CUSTOM_3
Definition keyb.h:114
@ CUSTOM_7
Definition keyb.h:118
@ SELECT_ELEMENT_5
Definition keyb.h:138
@ ROW_FIRST
Definition keyb.h:108
@ CUSTOM_6
Definition keyb.h:117
@ ROW_LEFT
Definition keyb.h:99
@ CUSTOM_14
Definition keyb.h:125
@ SELECT_ELEMENT_4
Definition keyb.h:137
@ MOVE_WORD_BACK
Definition keyb.h:70
@ MOVE_END
Definition keyb.h:68
@ CUSTOM_10
Definition keyb.h:121
@ MODE_NEXT
Definition keyb.h:94
@ REMOVE_CHAR_BACK
Definition keyb.h:84
@ DELETE_ENTRY
Definition keyb.h:98
@ SELECT_ELEMENT_1
Definition keyb.h:134
@ CLEAR_LINE
Definition keyb.h:64
@ CUSTOM_2
Definition keyb.h:113
@ SELECT_ELEMENT_2
Definition keyb.h:135
@ SCREENSHOT
Definition keyb.h:131
@ CANCEL
Definition keyb.h:111
@ ELEMENT_PREV
Definition keyb.h:105
@ MODE_PREVIOUS
Definition keyb.h:96
@ ACCEPT_ALT
Definition keyb.h:91
@ SELECT_ELEMENT_7
Definition keyb.h:140
@ MOVE_CHAR_BACK
Definition keyb.h:74
@ SELECT_ELEMENT_8
Definition keyb.h:141
@ REMOVE_CHAR_FORWARD
Definition keyb.h:82
@ CUSTOM_16
Definition keyb.h:127
@ MOUSE_CLICK_DOWN
Definition keyb.h:169
@ MOUSE_DCLICK_UP
Definition keyb.h:172
@ MOUSE_CLICK_UP
Definition keyb.h:170
@ MOUSE_DCLICK_DOWN
Definition keyb.h:171
char * mode_preprocess_input(Mode *mode, const char *input)
Definition mode.c:195
cairo_surface_t * mode_get_icon(Mode *mode, unsigned int selected_line, unsigned int height)
Definition mode.c:75
const char * mode_get_display_name(const Mode *mode)
Definition mode.c:172
unsigned int mode_get_num_entries(const Mode *mode)
Definition mode.c:58
MenuReturn
Definition mode.h:65
char * mode_get_message(const Mode *mode)
Definition mode.c:201
int mode_token_match(const Mode *mode, rofi_int_matcher **tokens, unsigned int selected_line)
Definition mode.c:138
char * mode_get_display_value(const Mode *mode, unsigned int selected_line, int *state, GList **attribute_list, int get_entry)
Definition mode.c:64
char * mode_get_completion(const Mode *mode, unsigned int selected_line)
Definition mode.c:109
@ MENU_CUSTOM_COMMAND
Definition mode.h:79
@ MENU_COMPLETE
Definition mode.h:83
@ MENU_LOWER_MASK
Definition mode.h:87
@ MENU_PREVIOUS
Definition mode.h:81
@ MENU_CANCEL
Definition mode.h:69
@ MENU_QUICK_SWITCH
Definition mode.h:77
@ MENU_ENTRY_DELETE
Definition mode.h:75
@ MENU_NEXT
Definition mode.h:71
@ MENU_CUSTOM_ACTION
Definition mode.h:85
@ MENU_OK
Definition mode.h:67
@ MENU_CUSTOM_INPUT
Definition mode.h:73
const Mode * rofi_get_mode(unsigned int index)
Definition rofi.c:149
void rofi_quit_main_loop(void)
Definition rofi.c:691
#define color_reset
Definition rofi.h:107
unsigned int rofi_get_num_enabled_modes(void)
Definition rofi.c:147
#define color_green
Definition rofi.h:113
#define TICK()
Definition timings.h:64
#define TICK_N(a)
Definition timings.h:69
void textbox_font(textbox *tb, TextBoxFontType tbft)
Definition textbox.c:277
TextboxFlags
Definition textbox.h:89
int textbox_keybinding(textbox *tb, KeyBindingAction action)
Definition textbox.c:771
TextBoxFontType
Definition textbox.h:100
void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list)
Definition textbox.c:350
const char * textbox_get_visible_text(const textbox *tb)
Definition textbox.c:338
void textbox_set_pango_context(const char *font, PangoContext *p)
Definition textbox.c:871
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
Definition textbox.c:186
void textbox_cursor_end(textbox *tb)
Definition textbox.c:645
gboolean textbox_append_text(textbox *tb, const char *pad, const int pad_len)
Definition textbox.c:833
PangoAttrList * textbox_get_pango_attributes(textbox *tb)
Definition textbox.c:344
void textbox_text(textbox *tb, const char *text)
Definition textbox.c:358
@ TB_AUTOHEIGHT
Definition textbox.h:90
@ TB_PASSWORD
Definition textbox.h:95
@ TB_MARKUP
Definition textbox.h:93
@ TB_WRAP
Definition textbox.h:94
@ TB_EDITABLE
Definition textbox.h:92
@ TB_AUTOWIDTH
Definition textbox.h:91
@ URGENT
Definition textbox.h:104
@ HIGHLIGHT
Definition textbox.h:115
@ NORMAL
Definition textbox.h:102
void rofi_view_cleanup()
Definition view.c:2241
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Definition view.c:2322
void __create_window(MenuFlags menu_flags)
Definition view.c:782
void rofi_view_clear_input(RofiViewState *state)
Definition view.c:2336
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Definition view.c:2347
Mode * rofi_view_get_mode(RofiViewState *state)
Definition view.c:2320
void rofi_view_hide(void)
Definition view.c:2233
void rofi_view_reload(void)
Definition view.c:528
xcb_window_t rofi_view_get_window(void)
Definition view.c:2375
void rofi_view_remove_active(RofiViewState *state)
Definition view.c:551
int rofi_view_error_dialog(const char *msg, int markup)
Definition view.c:2191
void rofi_view_set_active(RofiViewState *state)
Definition view.c:558
void rofi_view_queue_redraw(void)
Definition view.c:535
RofiViewState * rofi_view_get_active(void)
Definition view.c:549
void rofi_view_restart(RofiViewState *state)
Definition view.c:544
MenuFlags
Definition view.h:48
void rofi_view_handle_text(RofiViewState *state, char *text)
Definition view.c:1643
void rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
Definition view.c:1607
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition view.c:617
unsigned int rofi_view_get_completed(const RofiViewState *state)
Definition view.c:634
gboolean rofi_view_check_action(RofiViewState *state, BindingsScope scope, guint action)
Definition view.c:1576
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition view.c:638
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
Definition view.c:1685
void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target)
Definition view.c:1774
void rofi_view_finalize(RofiViewState *state)
Definition view.c:1323
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition view.c:581
void rofi_view_temp_configure_notify(RofiViewState *state, xcb_configure_notify_event_t *xce)
Definition view.c:1740
void rofi_view_frame_callback(void)
Definition view.c:1783
void rofi_view_free(RofiViewState *state)
Definition view.c:599
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition view.c:2103
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition view.c:621
unsigned int rofi_view_get_next_position(const RofiViewState *state)
Definition view.c:625
void rofi_view_maybe_update(RofiViewState *state)
Definition view.c:1713
@ MENU_PASSWORD
Definition view.h:52
@ MENU_NORMAL_WINDOW
Definition view.h:54
@ MENU_ERROR_DIALOG
Definition view.h:56
@ MENU_NORMAL
Definition view.h:50
void rofi_view_ellipsize_start(RofiViewState *state)
Definition view.c:2343
void rofi_capture_screenshot(void)
Definition view.c:179
void rofi_view_workers_initialize(void)
Definition view.c:2287
void rofi_view_set_window_title(const char *title)
Definition view.c:2377
void rofi_view_get_current_monitor(int *width, int *height)
Definition view.c:144
void rofi_view_workers_finalize(void)
Definition view.c:2314
void box_add(box *box, widget *child, gboolean expand)
Definition box.c:286
box * box_create(widget *parent, const char *name, RofiOrientation type)
Definition box.c:346
void container_add(container *container, widget *child)
Definition container.c:67
container * container_create(widget *parent, const char *name)
Definition container.c:102
void icon_set_surface(icon *icon, cairo_surface_t *surf)
Definition icon.c:140
icon * icon_create(widget *parent, const char *name)
Definition icon.c:153
void listview_nav_page_next(listview *lv)
Definition listview.c:989
void listview_set_fixed_num_lines(listview *lv)
Definition listview.c:1073
void listview_set_num_lines(listview *lv, unsigned int num_lines)
Definition listview.c:1055
void listview_set_num_elements(listview *lv, unsigned int rows)
Definition listview.c:561
void listview_nav_right(listview *lv)
Definition listview.c:897
void listview_set_mouse_activated_cb(listview *lv, listview_mouse_activated_cb cb, void *udata)
Definition listview.c:1047
void listview_toggle_ellipsizing(listview *lv)
Definition listview.c:1088
void listview_set_selected(listview *lv, unsigned int selected)
Definition listview.c:585
void listview_set_max_lines(listview *lv, unsigned int max_lines)
Definition listview.c:1061
listview * listview_create(widget *parent, const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse)
Definition listview.c:711
void listview_nav_left(listview *lv)
Definition listview.c:876
void listview_set_scroll_type(listview *lv, ScrollType type)
Definition listview.c:1041
void listview_set_ellipsize_start(listview *lv)
Definition listview.c:1079
void listview_nav_prev(listview *lv)
Definition listview.c:817
unsigned int listview_get_selected(listview *lv)
Definition listview.c:578
void listview_set_filtered(listview *lv, gboolean filtered)
Definition listview.c:1105
void listview_nav_up(listview *lv)
Definition listview.c:839
void listview_nav_next(listview *lv)
Definition listview.c:811
void listview_nav_page_prev(listview *lv)
Definition listview.c:979
void listview_set_selection_changed_callback(listview *lv, listview_selection_changed_callback cb, void *udata)
Definition listview.c:1111
void listview_nav_down(listview *lv)
Definition listview.c:857
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
void widget_free(widget *wid)
Definition widget.c:425
static void widget_disable(widget *widget)
Definition widget.h:170
void widget_resize(widget *widget, short w, short h)
Definition widget.c:87
WidgetType
Definition widget.h:56
static void widget_enable(widget *widget)
Definition widget.h:178
void widget_draw(widget *widget, cairo_t *d)
Definition widget.c:135
void widget_xy_to_relative(widget *widget, gint *x, gint *y)
Definition widget.c:468
#define WIDGET(a)
Definition widget.h:119
WidgetTriggerActionResult
Definition widget.h:76
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
gboolean widget_need_redraw(widget *wid)
Definition widget.c:500
widget * widget_find_mouse_target(widget *wid, WidgetType type, gint x, gint y)
Definition widget.c:510
@ WIDGET_TYPE_UNKNOWN
Definition widget.h:58
@ WIDGET_TYPE_LISTVIEW_ELEMENT
Definition widget.h:62
@ WIDGET_TYPE_TEXTBOX_TEXT
Definition widget.h:70
@ WIDGET_TYPE_MODE_SWITCHER
Definition widget.h:68
@ WIDGET_TYPE_EDITBOX
Definition widget.h:64
@ WIDGET_TRIGGER_ACTION_RESULT_HANDLED
Definition widget.h:80
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_END
Definition widget.h:84
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_BEGIN
Definition widget.h:82
@ WIDGET_TRIGGER_ACTION_RESULT_IGNORED
Definition widget.h:78
@ P_INTEGER
Definition rofi-types.h:12
@ P_STRING
Definition rofi-types.h:16
@ ROFI_ORIENTATION_HORIZONTAL
Definition rofi-types.h:143
@ ROFI_ORIENTATION_VERTICAL
Definition rofi-types.h:142
RofiCursorType
Definition rofi-types.h:149
@ ROFI_CURSOR_POINTER
Definition rofi-types.h:151
@ ROFI_CURSOR_TEXT
Definition rofi-types.h:152
@ ROFI_CURSOR_DEFAULT
Definition rofi-types.h:150
@ ROFI_HL_UNDERLINE
Definition rofi-types.h:58
@ ROFI_HL_BOLD
Definition rofi-types.h:56
Settings config
#define DEFAULT_MENU_LINES
Definition settings.h:190
#define DEFAULT_MENU_WIDTH
Definition settings.h:194
@ SORT_FZF
Definition settings.h:49
@ SORT_NORMAL
Definition settings.h:49
PropertyValue value
Definition rofi-types.h:297
PropertyType type
Definition rofi-types.h:295
unsigned int filtered_lines
container * mesg_box
textbox * text
widget * motion_target
textbox * mesg_tb
textbox * overlay
struct RofiViewState::@7 mouse
icon * icon_current_entry
textbox ** modes
listview * list_view
unsigned int num_lines
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
textbox * tb_current_entry
textbox * tb_total_rows
unsigned int selected_line
KeyBindingAction prev_action
textbox * case_indicator
MenuFlags menu_flags
WindowLocation location
Definition settings.h:84
unsigned int threads
Definition settings.h:143
int x_offset
Definition settings.h:88
unsigned int scroll_method
Definition settings.h:144
int y_offset
Definition settings.h:86
unsigned int auto_select
Definition settings.h:126
unsigned int case_sensitive
Definition settings.h:114
unsigned int sort
Definition settings.h:96
char * menu_font
Definition settings.h:59
unsigned int sidebar_mode
Definition settings.h:120
gboolean benchmark_ui
Definition settings.h:173
int dpi
Definition settings.h:141
unsigned int refilter_timeout_limit
Definition settings.h:183
SortingMethod sorting_method_enum
Definition settings.h:98
gboolean hover_select
Definition settings.h:122
int element_height
Definition settings.h:118
Definition box.c:40
Definition icon.c:39
const char * pattern
Definition view.c:678
unsigned int count
Definition view.c:675
GMutex * mutex
Definition view.c:664
unsigned int stop
Definition view.c:673
thread_state st
Definition view.c:659
RofiViewState * state
Definition view.c:669
unsigned int * acount
Definition view.c:666
unsigned int start
Definition view.c:671
GCond * cond
Definition view.c:662
void(* callback)(struct _thread_state *t, gpointer data)
Definition rofi-types.h:321
RofiCursorType cursor_type
int w
Definition xcb.h:104
xcb_connection_t * connection
SnLauncheeContext * sncontext
xcb_ewmh_connection_t ewmh
xcb_screen_t * screen
char * text
Definition textbox.h:65
GList * rofi_theme_get_list_strings(const widget *widget, const char *property)
Definition theme.c:1267
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
Definition theme.c:990
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition theme.c:877
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition theme.c:903
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition theme.c:1415
Property * rofi_theme_find_property(ThemeWidget *widget, PropertyType type, const char *property, gboolean exact)
Definition theme.c:740
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
Definition theme.c:778
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
Definition theme.c:1320
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition theme.c:840
int rofi_theme_get_position(const widget *widget, const char *property, int def)
Definition theme.c:815
static void rofi_view_call_thread(gpointer data, gpointer user_data)
Definition view.c:688
cairo_surface_t * fake_bg
Definition view.c:95
static void rofi_view_nav_last(RofiViewState *state)
Definition view.c:1027
static gboolean rofi_view_repaint(G_GNUC_UNUSED void *data)
Definition view.c:272
static 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:1809
static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data)
Definition view.c:508
GList * list_of_warning_msgs
Definition rofi.c:87
static gboolean rofi_view_reload_idle(G_GNUC_UNUSED gpointer data)
Definition view.c:469
static gboolean bench_update(void)
Definition view.c:248
struct _thread_state_view thread_state_view
guint idle_timeout
Definition view.c:113
guint refilter_timeout_count
Definition view.c:116
static void rofi_view_nav_row_select(RofiViewState *state)
Definition view.c:997
GQueue views
Definition view.c:109
static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom, void *udata)
Definition view.c:1867
static void rofi_view_input_changed()
Definition view.c:1333
GTimer * time
Definition view.c:239
cairo_surface_t * edit_surf
Definition view.c:101
static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget, const char *name)
Definition view.c:1880
static char * get_matching_state(void)
Definition view.c:152
static void update_callback(textbox *t, icon *ico, unsigned int index, void *udata, TextBoxFontType *type, gboolean full)
Definition view.c:1063
static void rofi_view_nav_row_tab(RofiViewState *state)
Definition view.c:973
static void rofi_view_setup_fake_transparency(widget *win, const char *const fake_background)
Definition view.c:729
static struct @2 BenchMark
static void rofi_view_reload_message_bar(RofiViewState *state)
Definition view.c:432
static void rofi_view_nav_first(RofiViewState *state)
Definition view.c:1017
gboolean do_bench
Definition view.c:232
xcb_window_t main_window
Definition view.c:93
static gboolean rofi_view_refilter_real(RofiViewState *state)
Definition view.c:1164
xcb_gcontext_t gc
Definition view.c:97
guint user_timeout
Definition view.c:118
cairo_t * edit_draw
Definition view.c:103
void rofi_view_update(RofiViewState *state, gboolean qr)
Definition view.c:1118
guint refilter_timeout
Definition view.c:115
static const int loc_transtable[9]
Definition view.c:311
xcb_pixmap_t edit_pixmap
Definition view.c:99
static RofiViewState * __rofi_view_state_create(void)
Definition view.c:650
static void rofi_view_trigger_global_action(KeyBindingAction action)
Definition view.c:1335
workarea mon
Definition view.c:111
int fake_bgrel
Definition view.c:105
static void filter_elements(thread_state *ts, G_GNUC_UNUSED gpointer user_data)
Definition view.c:693
void process_result(RofiViewState *state)
Definition rofi.c:217
static void rofi_view_update_prompt(RofiViewState *state)
Definition view.c:292
static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data)
Definition view.c:502
static void rofi_view_refilter(RofiViewState *state)
Definition view.c:1292
X11CursorType cursor_type
Definition view.c:126
static int rofi_view_calculate_height(RofiViewState *state)
Definition view.c:1792
GThreadPool * tpool
Definition view.c:83
double min
Definition view.c:245
RofiViewState * current_active_menu
Definition view.c:86
MenuFlags flags
Definition view.c:107
unsigned long long count
Definition view.c:120
static void rofi_view_calculate_window_position(RofiViewState *state)
Definition view.c:315
uint64_t draws
Definition view.c:241
double last_ts
Definition view.c:243
static void rofi_view_set_cursor(RofiCursorType type)
Definition view.c:1673
static void rofi_view_take_action(const char *name)
Definition view.c:486
static void selection_changed_callback(G_GNUC_UNUSED listview *lv, unsigned int index, void *udata)
Definition view.c:1035
static void rofi_view_ping_mouse(RofiViewState *state)
Definition view.c:2087
static void rofi_view_window_update_size(RofiViewState *state)
Definition view.c:402
gboolean fullscreen
Definition view.c:124
static void rofi_view_calculate_window_width(RofiViewState *state)
Definition view.c:951
static X11CursorType rofi_cursor_type_to_x11_cursor_type(RofiCursorType type)
Definition view.c:1650
static RofiCursorType rofi_view_resolve_cursor(RofiViewState *state, gint x, gint y)
Definition view.c:1665
static int lev_sort(const void *p1, const void *p2, void *arg)
Definition view.c:168
struct @1 CacheState
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:1838
static void _rofi_view_reload_row(RofiViewState *state)
Definition view.c:1154
guint repaint_source
Definition view.c:122
static void rofi_view_refilter_force(RofiViewState *state)
Definition view.c:1308
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
xcb_colormap_t map
Definition xcb.c:98
int monitor_active(workarea *mon)
Definition xcb.c:992
void display_early_cleanup(void)
Definition xcb.c:1749
cairo_surface_t * x11_helper_get_screenshot_surface(void)
Definition xcb.c:337
xcb_stuff * xcb
Definition xcb.c:91
xcb_depth_t * depth
Definition xcb.c:96
void rofi_xcb_revert_input_focus(void)
Definition xcb.c:1358
cairo_surface_t * x11_helper_get_bg_surface(void)
Definition xcb.c:363
void rofi_xcb_set_input_focus(xcb_window_t w)
Definition xcb.c:1335
void x11_set_cursor(xcb_window_t window, X11CursorType type)
Definition xcb.c:1806
xcb_window_t xcb_stuff_get_root_window(void)
Definition xcb.c:1747
void window_set_atom_prop(xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count)
Definition xcb.c:403
void cairo_image_surface_blur(cairo_surface_t *surface, double radius, double deviation)
Definition xcb.c:167
void x11_disable_decoration(xcb_window_t window)
Definition xcb.c:1782
xcb_atom_t netatoms[NUM_NETATOMS]
Definition xcb.c:103
xcb_visualtype_t * visual
Definition xcb.c:97
X11CursorType
Definition xcb.h:174
@ CURSOR_POINTER
Definition xcb.h:178
@ CURSOR_DEFAULT
Definition xcb.h:176
@ CURSOR_TEXT
Definition xcb.h:180