29#define G_LOG_DOMAIN "View"
41#include <xcb-imdkit/encoding.h>
43#include <xcb/xcb_ewmh.h>
44#include <xcb/xcb_icccm.h>
46#include <xkbcommon/xkbcommon-x11.h>
53#define SN_API_NOT_YET_FROZEN
85static void xim_commit_string(xcb_xim_t *im, G_GNUC_UNUSED xcb_xic_t ic,
86 G_GNUC_UNUSED uint32_t flag,
char *str,
87 uint32_t length, G_GNUC_UNUSED uint32_t *keysym,
88 G_GNUC_UNUSED
size_t nKeySym,
89 G_GNUC_UNUSED
void *user_data);
90static void xim_disconnected(G_GNUC_UNUSED xcb_xim_t *im,
91 G_GNUC_UNUSED
void *user_data);
92xcb_xim_im_callback xim_callback = {.forward_event =
93 x11_event_handler_fowarding,
94 .commit_string = xim_commit_string,
95 .disconnected = xim_disconnected};
162}
CacheState = {.main_window = XCB_WINDOW_NONE,
168 .views = G_QUEUE_INIT,
170 .refilter_timeout = 0,
171 .refilter_timeout_count = 0,
172 .max_refilter_time = 0.0,
173 .delayed_mode = FALSE,
178 .entry_history_enable = TRUE,
179 .entry_history = NULL,
180 .entry_history_length = 0,
181 .entry_history_index = 0};
192 if (
config.case_sensitive) {
207static int lev_sort(
const void *p1,
const void *p2,
void *arg) {
210 int *distances = arg;
212 return distances[*a] - distances[*b];
221 g_warning(
"Nothing to screenshot.");
224 const char *outp = g_getenv(
"ROFI_PNG_OUTPUT");
225 const char *xdg_pict_dir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
226 if (outp == NULL && xdg_pict_dir == NULL) {
227 g_warning(
"XDG user picture directory or ROFI_PNG_OUTPUT is not set. "
228 "Cannot store screenshot.");
232 GDateTime *now = g_date_time_new_now_local();
234 char *timestmp = g_date_time_format(now,
"rofi-%Y-%m-%d-%H%M");
235 char *filename = g_strdup_printf(
"%s-%05d.png", timestmp, 0);
240 fpath = g_build_filename(xdg_pict_dir, filename, NULL);
241 while (g_file_test(fpath, G_FILE_TEST_EXISTS) && index < 99999) {
247 filename = g_strdup_printf(
"%s-%05d.png", timestmp, index);
249 fpath = g_build_filename(xdg_pict_dir, filename, NULL);
252 fpath = g_strdup(outp);
255 cairo_surface_t *surf = cairo_image_surface_create(
257 cairo_status_t status = cairo_surface_status(surf);
258 if (status != CAIRO_STATUS_SUCCESS) {
259 g_warning(
"Failed to produce screenshot '%s', got error: '%s'", fpath,
260 cairo_status_to_string(status));
262 cairo_t *draw = cairo_create(surf);
263 status = cairo_status(draw);
264 if (status != CAIRO_STATUS_SUCCESS) {
265 g_warning(
"Failed to produce screenshot '%s', got error: '%s'", fpath,
266 cairo_status_to_string(status));
269 status = cairo_surface_write_to_png(surf, fpath);
270 if (status != CAIRO_STATUS_SUCCESS) {
271 g_warning(
"Failed to produce screenshot '%s', got error: '%s'", fpath,
272 cairo_status_to_string(status));
278 cairo_surface_destroy(surf);
282 g_date_time_unref(now);
297}
BenchMark = {.time = NULL, .draws = 0, .last_ts = 0.0, .min = G_MAXDOUBLE};
300 if (!
config.benchmark_ui) {
309 double ts = g_timer_elapsed(
BenchMark.time, NULL);
310 double fps = 1024 / (ts -
BenchMark.last_ts);
315 printf(
"current: %.2f fps, avg: %.2f fps, min: %.2f fps, %lu draws\r\n",
331 g_debug(
"expose event");
336 xcb_flush(
xcb->connection);
340 return (
bench_update() == TRUE) ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE;
415 state->
x -= state->
width / 2;
428 state->
x -= state->
width / 2;
439 state->
x -= state->
width / 2;
446 "x-offset",
config.x_offset);
448 "y-offset",
config.y_offset);
457 uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
458 XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
459 uint32_t vals[] = {state->
x, state->
y, state->
width, state->
height};
462 xcb_configure_window(
xcb->connection,
CacheState.main_window, mask, vals);
476 g_debug(
"Re-size window based internal request: %dx%d.", state->
width,
491 GString *emesg = g_string_new(msg);
494 g_string_append_c(emesg,
'\n');
497 emesg,
"The following warnings were detected when starting rofi:\n");
500 for (; iter != NULL && index < 2; iter = g_list_next(iter)) {
501 GString *in_msg = (GString *)(iter->data);
502 g_string_append(emesg,
"\n\n");
503 g_string_append(emesg, in_msg->str);
506 if (g_list_length(iter) > 1) {
507 g_string_append_printf(emesg,
"\nThere are <b>%u</b> more errors.",
508 g_list_length(iter) - 1);
513 g_string_free(emesg, TRUE);
534 return G_SOURCE_REMOVE;
543 const char *action = p->
value.
s;
545 if (
id != UINT32_MAX) {
548 g_warning(
"Failed to parse keybinding: %s\r\n", action);
556 return G_SOURCE_REMOVE;
577 double delay = prop->
value.
f;
621 g_debug(
"stack view.");
626 if (state == NULL && !g_queue_is_empty(&(
CacheState.views))) {
627 g_debug(
"pop view.");
640 unsigned int selected_line) {
643 unsigned int selected = 0;
644 for (
unsigned int i = 0; ((state->
selected_line)) < UINT32_MAX && !selected &&
653 xcb_clear_area(
xcb->connection,
CacheState.main_window, 1, 0, 0, 1, 1);
654 xcb_flush(
xcb->connection);
670 g_free(state->
modes);
687 (next_pos) = state->
line_map[selected + 1];
752 G_GNUC_UNUSED gpointer user_data) {
754 for (
unsigned int i = t->
start; i < t->stop; i++) {
762 glong slen = g_utf8_strlen(str, -1);
763 switch (
config.sorting_method_enum) {
779 g_mutex_lock(t->
mutex);
781 g_cond_signal(t->
cond);
782 g_mutex_unlock(t->
mutex);
788 const char *
const fake_background) {
790 cairo_surface_t *s = NULL;
796 if (g_strcmp0(fake_background,
"real") == 0) {
799 if (g_strcmp0(fake_background,
"screenshot") == 0) {
801 }
else if (g_strcmp0(fake_background,
"background") == 0) {
805 g_debug(
"Opening %s to use as background.", fpath);
806 s = cairo_image_surface_create_from_png(fpath);
812 if (cairo_surface_status(s) != CAIRO_STATUS_SUCCESS) {
813 g_debug(
"Failed to open surface fake background: %s",
814 cairo_status_to_string(cairo_surface_status(s)));
815 cairo_surface_destroy(s);
818 CacheState.fake_bg = cairo_image_surface_create(
822 cairo_t *dr = cairo_create(
CacheState.fake_bg);
824 cairo_set_source_surface(dr, s, 0, 0);
830 cairo_surface_destroy(s);
837 TICK_N(
"Fake transparency");
842static void xim_commit_string(xcb_xim_t *im, G_GNUC_UNUSED xcb_xic_t ic,
843 G_GNUC_UNUSED uint32_t flag,
char *str,
844 uint32_t length, G_GNUC_UNUSED uint32_t *keysym,
845 G_GNUC_UNUSED
size_t nKeySym,
846 G_GNUC_UNUSED
void *user_data) {
852#ifndef XCB_IMDKIT_1_0_3_LOWER
853 if (xcb_xim_get_encoding(im) == XCB_XIM_UTF8_STRING) {
855 }
else if (xcb_xim_get_encoding(im) == XCB_XIM_COMPOUND_TEXT) {
856 size_t newLength = 0;
857 char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
863 size_t newLength = 0;
864 char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
871static void xim_disconnected(G_GNUC_UNUSED xcb_xim_t *im,
872 G_GNUC_UNUSED
void *user_data) {
876static void create_ic_callback(xcb_xim_t *im, xcb_xic_t new_ic,
877 G_GNUC_UNUSED
void *user_data) {
880 xcb_xim_set_ic_focus(im,
xcb->ic);
888 static xcb_point_t spot = {.x = 0, .y = 0};
889 if (spot.x != new_x || spot.y != new_y) {
892 xcb_xim_nested_list nested = xcb_xim_create_nested_list(
893 xcb->im, XCB_XIM_XNSpotLocation, &spot, NULL);
894 xcb_xim_set_ic_values(
xcb->im,
xcb->ic, NULL, NULL, XCB_XIM_XNClientWindow,
895 &
CacheState.main_window, XCB_XIM_XNFocusWindow,
896 &
CacheState.main_window, XCB_XIM_XNPreeditAttributes,
902static void open_xim_callback(xcb_xim_t *im, G_GNUC_UNUSED
void *user_data) {
904 uint32_t input_style = XCB_IM_PreeditPosition | XCB_IM_StatusArea;
910 xcb_xim_nested_list nested =
911 xcb_xim_create_nested_list(im, XCB_XIM_XNSpotLocation, &spot, NULL);
913 im, create_ic_callback, NULL, XCB_XIM_XNInputStyle, &input_style,
914 XCB_XIM_XNClientWindow, &
CacheState.main_window, XCB_XIM_XNFocusWindow,
915 &
CacheState.main_window, XCB_XIM_XNPreeditAttributes, &nested, NULL);
921 if (
CacheState.entry_history_enable == FALSE) {
928 gchar *path = g_build_filename(
cache_dir,
"rofi-entry-history.txt", NULL);
929 if (g_file_test(path, G_FILE_TEST_EXISTS)) {
930 FILE *fp = fopen(path,
"r");
935 while ((nread = getline(&line, &len, fp)) != -1) {
939 if (line[nread - 1] ==
'\n') {
940 line[nread - 1] =
'\0';
964 if (
CacheState.entry_history_enable == FALSE) {
969 int max_history = 20;
978 gchar *path = g_build_filename(
cache_dir,
"rofi-entry-history.txt", NULL);
979 g_debug(
"Entry filename output: '%s'", path);
980 FILE *fp = fopen(path,
"w");
982 gssize start = MAX(0, (
CacheState.entry_history_length - max_history));
983 for (gssize i = start; i <
CacheState.entry_history_length; i++) {
984 if (strlen(
CacheState.entry_history[i].string) > 0) {
985 fprintf(fp,
"%s\n",
CacheState.entry_history[i].string);
994 for (ssize_t i = 0; i <
CacheState.entry_history_length; i++) {
1007 uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
1008 XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE |
1009 XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
1010 uint32_t xcb_event_masks =
1011 XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
1012 XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_KEY_PRESS |
1013 XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE |
1014 XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE |
1015 XCB_EVENT_MASK_BUTTON_1_MOTION | XCB_EVENT_MASK_POINTER_MOTION;
1017 uint32_t selval[] = {XCB_BACK_PIXMAP_NONE, 0,
1018 XCB_GRAVITY_STATIC, XCB_BACKING_STORE_NOT_USEFUL,
1019 xcb_event_masks,
map};
1022 xcb_xim_set_im_callback(
xcb->im, &xim_callback, NULL);
1027 xcb_xim_open(
xcb->im, open_xim_callback,
true, NULL);
1030 xcb_window_t box_window = xcb_generate_id(
xcb->connection);
1031 xcb_void_cookie_t cc = xcb_create_window_checked(
1033 0, 200, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
visual->visual_id, selmask,
1035 xcb_generic_error_t *error;
1036 error = xcb_request_check(
xcb->connection, cc);
1038 g_error(
"xcb_create_window() failed error=0x%x\n", error->error_code);
1042 TICK_N(
"xcb create window");
1044 xcb_create_gc(
xcb->connection,
CacheState.gc, box_window, 0, 0);
1052 CacheState.edit_surf = cairo_xcb_surface_create(
1056 TICK_N(
"create cairo surface");
1058 cairo_font_options_t *fo = cairo_font_options_create();
1060 cairo_surface_get_font_options(
CacheState.edit_surf, fo);
1062 PangoContext *p = pango_cairo_create_context(
CacheState.edit_draw);
1064 pango_cairo_context_set_font_options(p, fo);
1065 TICK_N(
"pango cairo font setup");
1072 PangoFontMap *font_map = pango_cairo_font_map_get_default();
1073 pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map,
1081 dpi = (
xcb->screen->height_in_pixels * 25.4) /
1082 (
double)(
xcb->screen->height_in_millimeters);
1085 g_debug(
"Auto-detected DPI: %.2lf", dpi);
1086 PangoFontMap *font_map = pango_cairo_font_map_get_default();
1087 pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map, dpi);
1091 PangoFontMap *font_map = pango_cairo_font_map_get_default();
1093 pango_cairo_font_map_get_resolution((PangoCairoFontMap *)font_map);
1101 PangoFontDescription *pfd = pango_font_description_from_string(font);
1103 pango_context_set_font_description(p, pfd);
1105 pango_font_description_free(pfd);
1107 PangoLanguage *l = pango_language_get_default();
1108 pango_context_set_language(p, l);
1109 TICK_N(
"configure font");
1115 cairo_font_options_destroy(fo);
1120 xcb_atom_t atoms[] = {
xcb->ewmh._NET_WM_STATE_MODAL};
1123 sizeof(atoms) /
sizeof(xcb_atom_t));
1125 &(
xcb->ewmh._NET_WM_WINDOW_TYPE_UTILITY), 1);
1128 xcb_window_t active_window;
1129 xcb_get_property_cookie_t awc;
1130 awc = xcb_ewmh_get_active_window(&
xcb->ewmh,
xcb->screen_nbr);
1132 if (xcb_ewmh_get_active_window_reply(&
xcb->ewmh, awc, &active_window,
1134 xcb_change_property(
xcb->connection, XCB_PROP_MODE_REPLACE, box_window,
1135 XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, 1,
1140 &(
xcb->ewmh._NET_WM_STATE_ABOVE), 1);
1141 uint32_t values[] = {1};
1142 xcb_change_window_attributes(
xcb->connection, box_window,
1143 XCB_CW_OVERRIDE_REDIRECT, values);
1146 &(
xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL), 1);
1150 TICK_N(
"setup window attributes");
1154 xcb_atom_t atoms[] = {
xcb->ewmh._NET_WM_STATE_FULLSCREEN,
1155 xcb->ewmh._NET_WM_STATE_ABOVE};
1157 sizeof(atoms) /
sizeof(xcb_atom_t));
1160 xcb_atom_t protocols[] = {
netatoms[WM_TAKE_FOCUS]};
1161 xcb_icccm_set_wm_protocols(
xcb->connection, box_window,
1162 xcb->ewmh.WM_PROTOCOLS, G_N_ELEMENTS(protocols),
1165 TICK_N(
"setup window fullscreen");
1168 const char wm_class_name[] =
"rofi\0Rofi";
1169 xcb_icccm_set_wm_class(
xcb->connection, box_window,
sizeof(wm_class_name),
1172 TICK_N(
"setup window name and class");
1173 const char *transparency =
1178 if (
xcb->sncontext != NULL) {
1179 sn_launchee_context_setup_window(
xcb->sncontext,
CacheState.main_window);
1181 TICK_N(
"setup startup notification");
1186 pid_t pid = getpid();
1187 xcb_ewmh_set_wm_pid(&(
xcb->ewmh),
CacheState.main_window, pid);
1190 const char *hostname = g_get_host_name();
1191 char *ahost = g_hostname_to_ascii(hostname);
1192 if (ahost != NULL) {
1193 xcb_icccm_set_wm_client_machine(
xcb->connection,
CacheState.main_window,
1194 XCB_ATOM_STRING, 8, strlen(ahost), ahost);
1213 "width", state->
width);
1256 if (selected < state->filtered_lines) {
1289 unsigned int index,
void *udata) {
1292 if (index < state->filtered_lines) {
1295 &fstate, NULL, TRUE);
1304 if (index < state->filtered_lines) {
1308 cairo_surface_t *surf_icon =
1320 GList *add_list = NULL;
1323 &fstate, &add_list, TRUE);
1328 cairo_surface_t *surf_icon =
1339 pango_attr_list_ref(list);
1341 list = pango_attr_list_new();
1346 {0.0, 0.0, 0.0, 0.0}};
1351 for (GList *iter = g_list_first(add_list); iter != NULL;
1352 iter = g_list_next(iter)) {
1353 pango_attr_list_insert(list, (PangoAttribute *)(iter->data));
1356 pango_attr_list_unref(list);
1359 g_list_free(add_list);
1380 g_debug(
"Redraw view");
1383 cairo_set_operator(d, CAIRO_OPERATOR_SOURCE);
1386 cairo_set_source_surface(d,
CacheState.fake_bg, 0.0, 0.0);
1388 cairo_set_source_surface(d,
CacheState.fake_bg,
1394 cairo_set_source_rgba(d, 0, 0, 0, 0.0);
1398 cairo_set_operator(d, CAIRO_OPERATOR_OVER);
1431 if (state->
sw == NULL) {
1432 return G_SOURCE_REMOVE;
1434 GTimer *timer = g_timer_new();
1440 TICK_N(
"Filter reload rows");
1445 TICK_N(
"Filter tokenize");
1451 glong plen = pattern ? g_utf8_strlen(pattern, -1) : 0;
1460 unsigned int nt = MAX(1, state->
num_lines / 500);
1463 nt = MIN(nt,
config.threads * 4);
1467 g_mutex_init(&mutex);
1469 unsigned int count = nt;
1470 unsigned int steps = (state->
num_lines + nt) / nt;
1471 for (
unsigned int i = 0; i < nt; i++) {
1472 states[i].
state = state;
1473 states[i].
start = i * steps;
1475 states[i].
count = 0;
1476 states[i].
cond = &cond;
1477 states[i].
mutex = &mutex;
1479 states[i].
plen = plen;
1482 states[i].
st.
free = NULL;
1485 g_thread_pool_push(
tpool, &states[i], NULL);
1492 g_mutex_lock(&mutex);
1494 g_cond_wait(&cond, &mutex);
1496 g_mutex_unlock(&mutex);
1498 g_cond_clear(&cond);
1499 g_mutex_clear(&mutex);
1500 for (
unsigned int i = 0; i < nt; i++) {
1501 if (j != states[i].start) {
1503 sizeof(
unsigned int) * (states[i].
count));
1505 j += states[i].
count;
1516 double elapsed = g_timer_elapsed(timer, NULL);
1521 for (
unsigned int i = 0; i < state->
num_lines; i++) {
1526 TICK_N(
"Filter matching done");
1535 char *r = g_strdup_printf(
"%u", state->
num_lines);
1539 TICK_N(
"Update filter lines");
1551 if (height != state->
height) {
1555 g_debug(
"Resize based on re-filter");
1557 TICK_N(
"Filter resize window based on window ");
1562 g_timer_destroy(timer);
1563 return G_SOURCE_REMOVE;
1569 g_source_remove(
CacheState.refilter_timeout);
1572 if (
CacheState.max_refilter_time > (
config.refilter_timeout_limit / 1000.0) &&
1577 "Filtering took %f seconds ( %f ), switching to delayed filter\n",
1588 "Filtering took %f seconds , switching back to instant filter\n",
1597 g_source_remove(
CacheState.refilter_timeout);
1611 if (state && state->
finalize != NULL) {
1624 if (
CacheState.entry_history_enable && state) {
1641 xcb_convert_selection(
xcb->connection,
CacheState.main_window,
1642 XCB_ATOM_PRIMARY,
xcb->ewmh.UTF8_STRING,
1643 xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1644 xcb_flush(
xcb->connection);
1647 xcb_convert_selection(
xcb->connection,
CacheState.main_window,
1649 xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1650 xcb_flush(
xcb->connection);
1655 if (selected < state->filtered_lines) {
1658 data = g_strdup(state->
text->
text);
1662 xcb_set_selection_owner(
xcb->connection,
CacheState.main_window,
1663 netatoms[CLIPBOARD], XCB_CURRENT_TIME);
1664 xcb_flush(
xcb->connection);
1696 if (selected < state->filtered_lines) {
1715 if (selected < state->filtered_lines) {
1733 if (index < state->filtered_lines) {
1761 if (selected < state->filtered_lines) {
1839 }
else if (rc == 2) {
1848 if (selected < state->filtered_lines) {
1878 if (selected < state->filtered_lines) {
1960 if (target == NULL) {
1994 if (target == NULL) {
1998 if (target == NULL) {
2062 gboolean find_mouse_target) {
2070 if (find_mouse_target) {
2074 if (target != NULL) {
2083 if (find_mouse_target) {
2097 if (state == NULL) {
2117 xcb_configure_notify_event_t *xce) {
2119 if (state->
x != xce->x || state->
y != xce->y) {
2124 if (state->
width != xce->width || state->
height != xce->height) {
2125 state->
width = xce->width;
2126 state->
height = xce->height;
2137 cairo_xcb_surface_create(
xcb->connection,
CacheState.edit_pixmap,
2140 g_debug(
"Re-size window based external request: %d %d", state->
width,
2187 G_GNUC_UNUSED gint y, G_GNUC_UNUSED
void *user_data) {
2200 if (
id != UINT32_MAX) {
2216 G_GNUC_UNUSED gint y, G_GNUC_UNUSED
void *user_data) {
2219 for (i = 0; i < state->
num_modes; i++) {
2258 char *defaults = NULL;
2264 if (strcmp(name,
"mainbox") == 0) {
2267 if (
config.sidebar_mode) {
2268 defaults =
"inputbar,message,listview,mode-switcher";
2270 defaults =
"inputbar,message,listview";
2276 else if (strcmp(name,
"inputbar") == 0) {
2279 defaults =
"prompt,entry,overlay,case-indicator";
2285 else if (strcmp(name,
"prompt") == 0) {
2286 if (state->
prompt != NULL) {
2287 g_error(
"Prompt widget can only be added once to the layout.");
2297 }
else if (strcmp(name,
"num-rows") == 0) {
2303 }
else if (strcmp(name,
"num-filtered-rows") == 0) {
2309 }
else if (strcmp(name,
"textbox-current-entry") == 0) {
2315 }
else if (strcmp(name,
"icon-current-entry") == 0) {
2323 else if (strcmp(name,
"case-indicator") == 0) {
2325 g_error(
"Case indicator widget can only be added once to the layout.");
2338 else if (strcmp(name,
"entry") == 0) {
2339 if (state->
text != NULL) {
2340 g_error(
"Entry textbox widget can only be added once to the layout.");
2354 else if (strcmp(name,
"message") == 0) {
2356 g_error(
"Message widget can only be added once to the layout.");
2370 else if (strcmp(name,
"listview") == 0) {
2372 g_error(
"Listview widget can only be added once to the layout.");
2390 else if (strcmp(name,
"mode-switcher") == 0 || strcmp(name,
"sidebar") == 0) {
2392 g_error(
"Mode-switcher can only be added once to the layout.");
2400 for (
unsigned int j = 0; j < state->
num_modes; j++) {
2410 }
else if (g_ascii_strcasecmp(name,
"overlay") == 0) {
2416 }
else if (g_ascii_strncasecmp(name,
"textbox", 7) == 0) {
2420 }
else if (g_ascii_strncasecmp(name,
"button", 6) == 0) {
2426 }
else if (g_ascii_strncasecmp(name,
"icon", 4) == 0) {
2445 char **a = g_strsplit(defaults,
",", 0);
2446 for (
int i = 0; a && a[i]; i++) {
2452 for (
const GList *iter = g_list_first(list); iter != NULL;
2453 iter = g_list_next(iter)) {
2456 g_list_free_full(list, g_free);
2462 xcb_query_pointer_cookie_t pointer_cookie =
2464 xcb_query_pointer_reply_t *pointer_reply =
2465 xcb_query_pointer_reply(
xcb->connection, pointer_cookie, NULL);
2467 if (pointer_reply == NULL) {
2472 pointer_reply->win_y,
config.hover_select);
2474 free(pointer_reply);
2487 state->
quit = FALSE;
2497 g_debug(
"Disable entry history, because password setup.");
2499 if (
config.disable_history) {
2501 g_debug(
"Disable entry history, because history disable flag.");
2514 TICK_N(
"Startup notification");
2517 TICK_N(
"Get active monitor");
2526 for (
const GList *iter = list; iter != NULL; iter = g_list_next(iter)) {
2528 (
const char *)iter->data);
2530 g_list_free_full(list, g_free);
2533 if (state->
text && input) {
2553 state->
quit = FALSE;
2559 xcb_flush(
xcb->connection);
2568 if (
xcb->sncontext != NULL) {
2569 sn_launchee_context_complete(
xcb->sncontext);
2587 NORMAL, (msg != NULL) ? msg :
"", 0, 0);
2607 if (
xcb->sncontext != NULL) {
2608 sn_launchee_context_complete(
xcb->sncontext);
2617 if (
CacheState.main_window != XCB_WINDOW_NONE) {
2627 g_debug(
"Cleanup.");
2633 g_source_remove(
CacheState.refilter_timeout);
2656 if (
CacheState.main_window != XCB_WINDOW_NONE) {
2657 g_debug(
"Unmapping and free'ing window");
2662 xcb_destroy_window(
xcb->connection,
CacheState.main_window);
2665 if (
map != XCB_COLORMAP_NONE) {
2666 xcb_free_colormap(
xcb->connection,
map);
2667 map = XCB_COLORMAP_NONE;
2669 xcb_flush(
xcb->connection);
2670 g_assert(g_queue_is_empty(&(
CacheState.views)));
2676 gpointer data G_GNUC_UNUSED) {
2689 if (GPOINTER_TO_UINT(data) == 1) {
2691 g_debug(
"Glib thread-pool bug, received pointer with value 1.");
2702 TICK_N(
"Setup Threadpool, start");
2703 if (
config.threads == 0) {
2705 long procs = sysconf(_SC_NPROCESSORS_CONF);
2707 config.threads = MIN(procs, 128l);
2711 GError *error = NULL;
2715 if (error == NULL) {
2717 g_thread_pool_set_max_idle_time(60000);
2719 g_thread_pool_set_max_threads(
tpool,
config.threads, &error);
2722 if (error != NULL) {
2723 g_warning(
"Failed to setup thread pool: '%s'", error->message);
2724 g_error_free(error);
2728 TICK_N(
"Setup Threadpool, done");
2733 g_thread_pool_free(
tpool, TRUE, FALSE);
2761 PangoEllipsizeMode mode) {
2780 for (
unsigned int j = 0; j < state->
num_modes; j++) {
2796 ssize_t len = strlen(title);
2797 xcb_change_property(
xcb->connection, XCB_PROP_MODE_REPLACE,
2799 xcb->ewmh.UTF8_STRING, 8, len, title);
2800 xcb_change_property(
xcb->connection, XCB_PROP_MODE_REPLACE,
2801 CacheState.main_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
PangoAttrList * helper_token_match_get_pango_attr(RofiHighlightColorStyle th, rofi_int_matcher **tokens, const char *input, PangoAttrList *retv)
gboolean helper_validate_font(PangoFontDescription *pfd, const char *font)
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Property * rofi_theme_find_property(ThemeWidget *wid, PropertyType type, const char *property, gboolean exact)
void helper_tokenize_free(rofi_int_matcher **tokens)
unsigned int levenshtein(const char *needle, const glong needlelen, const char *haystack, const glong haystacklen)
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
char * rofi_expand_path(const char *input)
int rofi_scorer_fuzzy_evaluate(const char *pattern, glong plen, const char *str, glong slen)
guint key_binding_get_action_from_name(const char *name)
MouseBindingMouseDefaultAction
@ SCOPE_MOUSE_LISTVIEW_ELEMENT
@ SCOPE_MOUSE_MODE_SWITCHER
@ TOGGLE_CASE_SENSITIVITY
char * mode_preprocess_input(Mode *mode, const char *input)
cairo_surface_t * mode_get_icon(Mode *mode, unsigned int selected_line, unsigned int height)
const char * mode_get_display_name(const Mode *mode)
unsigned int mode_get_num_entries(const Mode *mode)
char * mode_get_message(const Mode *mode)
int mode_token_match(const Mode *mode, rofi_int_matcher **tokens, unsigned int selected_line)
char * mode_get_display_value(const Mode *mode, unsigned int selected_line, int *state, GList **attribute_list, int get_entry)
char * mode_get_completion(const Mode *mode, unsigned int selected_line)
const Mode * rofi_get_mode(unsigned int index)
void rofi_quit_main_loop(void)
unsigned int rofi_get_num_enabled_modes(void)
void textbox_font(textbox *tb, TextBoxFontType tbft)
int textbox_keybinding(textbox *tb, KeyBindingAction action)
void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list)
const char * textbox_get_visible_text(const textbox *tb)
int textbox_get_cursor(const textbox *tb)
void textbox_cursor(textbox *tb, int pos)
void textbox_set_pango_context(const char *font, PangoContext *p)
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
void textbox_cursor_end(textbox *tb)
gboolean textbox_append_text(textbox *tb, const char *pad, const int pad_len)
PangoAttrList * textbox_get_pango_attributes(textbox *tb)
void textbox_text(textbox *tb, const char *text)
int textbox_get_cursor_x_pos(const textbox *tb)
char * textbox_get_text(const textbox *tb)
void rofi_view_cleanup(void)
void rofi_view_set_overlay(RofiViewState *state, const char *text)
void __create_window(MenuFlags menu_flags)
void rofi_view_clear_input(RofiViewState *state)
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Mode * rofi_view_get_mode(RofiViewState *state)
void rofi_view_hide(void)
void rofi_view_reload(void)
xcb_window_t rofi_view_get_window(void)
void rofi_view_remove_active(RofiViewState *state)
int rofi_view_error_dialog(const char *msg, int markup)
void rofi_view_set_active(RofiViewState *state)
void rofi_view_queue_redraw(void)
RofiViewState * rofi_view_get_active(void)
void rofi_view_restart(RofiViewState *state)
void rofi_view_handle_text(RofiViewState *state, char *text)
void rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
unsigned int rofi_view_get_completed(const RofiViewState *state)
gboolean rofi_view_check_action(RofiViewState *state, BindingsScope scope, guint action)
const char * rofi_view_get_user_input(const RofiViewState *state)
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target)
void rofi_view_finalize(RofiViewState *state)
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
void rofi_view_temp_configure_notify(RofiViewState *state, xcb_configure_notify_event_t *xce)
void rofi_view_frame_callback(void)
void rofi_view_free(RofiViewState *state)
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
unsigned int rofi_view_get_next_position(const RofiViewState *state)
void rofi_view_maybe_update(RofiViewState *state)
gboolean rofi_set_im_window_pos(int new_x, int new_y)
void rofi_capture_screenshot(void)
void rofi_view_workers_initialize(void)
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)
void rofi_view_set_window_title(const char *title)
void rofi_view_ellipsize_listview(RofiViewState *state, PangoEllipsizeMode mode)
void rofi_view_get_current_monitor(int *width, int *height)
void rofi_view_workers_finalize(void)
void box_add(box *wid, widget *child, gboolean expand)
box * box_create(widget *parent, const char *name, RofiOrientation type)
void container_add(container *cont, widget *child)
container * container_create(widget *parent, const char *name)
void icon_set_surface(icon *icon_widget, cairo_surface_t *surf)
icon * icon_create(widget *parent, const char *name)
void listview_nav_page_next(listview *lv)
void listview_set_fixed_num_lines(listview *lv)
struct _listview listview
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)
void listview_set_num_elements(listview *lv, unsigned int rows)
void listview_nav_right(listview *lv)
void listview_set_mouse_activated_cb(listview *lv, listview_mouse_activated_cb cb, void *udata)
void listview_toggle_ellipsizing(listview *lv)
void listview_set_ellipsize(listview *lv, PangoEllipsizeMode mode)
void listview_set_selected(listview *lv, unsigned int selected)
void listview_set_max_lines(listview *lv, unsigned int max_lines)
void listview_nav_left(listview *lv)
void listview_set_scroll_type(listview *lv, ScrollType type)
void listview_nav_prev(listview *lv)
unsigned int listview_get_selected(listview *lv)
void listview_set_filtered(listview *lv, gboolean filtered)
void listview_nav_up(listview *lv)
void listview_nav_next(listview *lv)
void listview_nav_page_prev(listview *lv)
void listview_set_selection_changed_callback(listview *lv, listview_selection_changed_callback cb, void *udata)
void listview_nav_down(listview *lv)
@ ROFI_ORIENTATION_HORIZONTAL
@ ROFI_ORIENTATION_VERTICAL
struct _thread_state thread_state
GList * list_of_warning_msgs
void process_result(RofiViewState *state)
#define DEFAULT_MENU_WIDTH
unsigned int filtered_lines
struct RofiViewState::@120340234043206106057143171013161143075155346345 mouse
icon * icon_current_entry
void(* finalize)(struct RofiViewState *state)
textbox * tb_filtered_rows
rofi_int_matcher ** tokens
textbox * tb_current_entry
unsigned int selected_line
KeyBindingAction prev_action
void(* callback)(struct _thread_state *t, gpointer data)
int rofi_theme_get_integer(const widget *wid, const char *property, int def)
RofiHighlightColorStyle rofi_theme_get_highlight(widget *wid, const char *property, RofiHighlightColorStyle th)
int rofi_theme_get_position(const widget *wid, const char *property, int def)
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
int rofi_theme_get_boolean(const widget *wid, const char *property, int def)
RofiDistance rofi_theme_get_distance(const widget *wid, const char *property, int def)
GList * rofi_theme_get_list_strings(const widget *wid, const char *property)
const char * rofi_theme_get_string(const widget *wid, const char *property, const char *def)
static void rofi_view_call_thread(gpointer data, gpointer user_data)
cairo_surface_t * fake_bg
static void rofi_view_nav_last(RofiViewState *state)
static gboolean rofi_view_repaint(G_GNUC_UNUSED void *data)
static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data)
static gboolean rofi_view_reload_idle(G_GNUC_UNUSED gpointer data)
static gboolean bench_update(void)
struct _thread_state_view thread_state_view
guint refilter_timeout_count
static void rofi_view_nav_row_select(RofiViewState *state)
static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom, void *udata)
EntryHistoryIndex * entry_history
cairo_surface_t * edit_surf
static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget, const char *name)
static char * get_matching_state(void)
static void update_callback(textbox *t, icon *ico, unsigned int index, void *udata, TextBoxFontType *type, gboolean full)
static void rofi_view_nav_row_tab(RofiViewState *state)
static void rofi_view_setup_fake_transparency(widget *win, const char *const fake_background)
static void input_history_save(void)
gboolean entry_history_enable
static void rofi_view_reload_message_bar(RofiViewState *state)
static void rofi_view_nav_first(RofiViewState *state)
static gboolean rofi_view_refilter_real(RofiViewState *state)
static void page_changed_callback(void)
void rofi_view_update(RofiViewState *state, gboolean qr)
static const int loc_transtable[9]
static RofiViewState * __rofi_view_state_create(void)
static void rofi_view_trigger_global_action(KeyBindingAction action)
static void rofi_view_input_changed(void)
gssize entry_history_index
static void filter_elements(thread_state *ts, G_GNUC_UNUSED gpointer user_data)
void process_result(RofiViewState *state)
static void rofi_view_update_prompt(RofiViewState *state)
static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data)
static void rofi_view_refilter(RofiViewState *state)
X11CursorType cursor_type
static int rofi_view_calculate_height(RofiViewState *state)
RofiViewState * current_active_menu
static void rofi_thread_pool_state_free(gpointer data)
gssize entry_history_length
struct @021235355132206303136272140252157034367147165236 CacheState
static int rofi_thread_workers_sort(gconstpointer a, gconstpointer b, gpointer data G_GNUC_UNUSED)
static void rofi_view_calculate_window_position(RofiViewState *state)
static void rofi_view_set_cursor(RofiCursorType type)
static void rofi_view_take_action(const char *name)
static void selection_changed_callback(G_GNUC_UNUSED listview *lv, unsigned int index, void *udata)
static void rofi_view_ping_mouse(RofiViewState *state)
static void rofi_view_window_update_size(RofiViewState *state)
static void rofi_view_calculate_window_width(RofiViewState *state)
static struct @044075143323171165330343223070305341364056057360 BenchMark
static X11CursorType rofi_cursor_type_to_x11_cursor_type(RofiCursorType type)
static RofiCursorType rofi_view_resolve_cursor(RofiViewState *state, gint x, gint y)
static int lev_sort(const void *p1, const void *p2, void *arg)
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)
static void _rofi_view_reload_row(RofiViewState *state)
static void input_history_initialize(void)
static void rofi_view_refilter_force(RofiViewState *state)
int monitor_active(workarea *mon)
void display_early_cleanup(void)
cairo_surface_t * x11_helper_get_screenshot_surface(void)
void rofi_xcb_revert_input_focus(void)
cairo_surface_t * x11_helper_get_bg_surface(void)
void rofi_xcb_set_input_focus(xcb_window_t w)
void x11_set_cursor(xcb_window_t window, X11CursorType type)
xcb_window_t xcb_stuff_get_root_window(void)
void window_set_atom_prop(xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count)
void cairo_image_surface_blur(cairo_surface_t *surface, double radius, double deviation)
void xcb_stuff_set_clipboard(char *data)
void x11_disable_decoration(xcb_window_t window)
xcb_atom_t netatoms[NUM_NETATOMS]
xcb_visualtype_t * visual
struct _workarea workarea