rofi 1.7.9
rofi.c
Go to the documentation of this file.
1/*
2 * rofi
3 *
4 * MIT/X11 License
5 * Copyright © 2012 Sean Pringle <sean.pringle@gmail.com>
6 * Copyright © 2013-2023 Qball Cow <qball@gmpclient.org>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 */
28
30#define G_LOG_DOMAIN "Rofi"
31
32#include "config.h"
33#include <errno.h>
34#include <gmodule.h>
35#include <locale.h>
36#include <stdint.h>
37#include <stdlib.h>
38#include <string.h>
39#include <sys/stat.h>
40#include <sys/types.h>
41#include <sysexits.h>
42#include <time.h>
43#include <unistd.h>
44#include <xcb/xcb.h>
45
46#include <glib-unix.h>
47
48#include <libgwater-xcb.h>
49
50#ifdef USE_NK_GIT_VERSION
51#include "nkutils-git-version.h"
52#ifdef NK_GIT_VERSION
53#define GIT_VERSION NK_GIT_VERSION
54#endif
55#endif
56
57#include "resources.h"
58
59#include "display.h"
60#include "rofi.h"
61#include "settings.h"
62
63#include "helper.h"
64#include "mode.h"
65#include "modes/modes.h"
66#include "widgets/textbox.h"
67#include "xrmoptions.h"
68
69#include "view-internal.h"
70#include "view.h"
71
72#include "rofi-icon-fetcher.h"
73#include "theme.h"
74
75#include "timings.h"
76
78char *pidfile = NULL;
80const char *cache_dir = NULL;
83char *cache_dir_alloc = NULL;
84
86GList *list_of_error_msgs = NULL;
89
90static void rofi_collectmodes_destroy(void);
91void rofi_add_error_message(GString *str) {
92 list_of_error_msgs = g_list_append(list_of_error_msgs, str);
93}
96 for (GList *iter = g_list_first(list_of_error_msgs); iter != NULL;
97 iter = g_list_next(iter)) {
98 g_string_free((GString *)iter->data, TRUE);
99 }
100 g_list_free(list_of_error_msgs);
101 list_of_error_msgs = NULL;
102 }
103}
104void rofi_add_warning_message(GString *str) {
105 list_of_warning_msgs = g_list_append(list_of_warning_msgs, str);
106}
109 for (GList *iter = g_list_first(list_of_warning_msgs); iter != NULL;
110 iter = g_list_next(iter)) {
111 g_string_free((GString *)iter->data, TRUE);
112 }
113 g_list_free(list_of_warning_msgs);
115 }
116}
117
119G_MODULE_EXPORT char *config_path = NULL;
122Mode **modes = NULL;
123
127unsigned int num_available_modes = 0;
129unsigned int num_modes = 0;
131unsigned int curr_mode = 0;
132
134NkBindings *bindings = NULL;
135
137GMainLoop *main_loop = NULL;
138
142int return_code = EXIT_SUCCESS;
143
144void process_result(RofiViewState *state);
145
146void rofi_set_return_code(int code) { return_code = code; }
147
148unsigned int rofi_get_num_enabled_modes(void) { return num_modes; }
149
150const Mode *rofi_get_mode(unsigned int index) { return modes[index]; }
151
159static int mode_lookup(const char *name) {
160 for (unsigned int i = 0; i < num_modes; i++) {
161 if (strcmp(mode_get_name(modes[i]), name) == 0) {
162 return i;
163 }
164 }
165 return -1;
166}
167
174static const Mode *mode_available_lookup(const char *name) {
175 for (unsigned int i = 0; i < num_available_modes; i++) {
176 if (strcmp(mode_get_name(available_modes[i]), name) == 0) {
177 return available_modes[i];
178 }
179 }
180 return NULL;
181}
182
186static void teardown(int pfd) {
187 g_debug("Teardown");
188 // Cleanup font setup.
190
192
193 // Cleanup view
195
196 // Cleanup pid file.
197 remove_pid_file(pfd);
198}
199static void run_mode_index(ModeMode mode) {
200 // Otherwise check if requested mode is enabled.
201 for (unsigned int i = 0; i < num_modes; i++) {
202 if (!mode_init(modes[i])) {
203 GString *str = g_string_new("Failed to initialize the mode: ");
204 g_string_append(str, mode_get_name(modes[i]));
205 g_string_append(str, "\n");
206
208 g_string_free(str, FALSE);
209 break;
210 }
211 }
212 // Error dialog must have been created.
213 if (rofi_view_get_active() != NULL) {
214 return;
215 }
216 curr_mode = mode;
217 RofiViewState *state =
218 rofi_view_create(modes[mode], config.filter, 0, process_result);
219
220 // User can pre-select a row.
221 if (find_arg("-selected-row") >= 0) {
222 unsigned int sr = 0;
223 find_arg_uint("-selected-row", &(sr));
225 }
226 if (state) {
228 }
229 if (rofi_view_get_active() == NULL) {
230 g_main_loop_quit(main_loop);
231 }
232}
234 Mode *sw = state->sw;
235 // rofi_view_set_active ( NULL );
236 if (sw != NULL) {
237 unsigned int selected_line = rofi_view_get_selected_line(state);
238 ;
240 char *input = g_strdup(rofi_view_get_user_input(state));
241 ModeMode retv = mode_result(sw, mretv, &input, selected_line);
242 {
243 if (state->text) {
244 if (input == NULL) {
245 textbox_text(state->text, "");
246 } else if (strcmp(rofi_view_get_user_input(state), input) != 0) {
247 textbox_text(state->text, input);
248 textbox_cursor_end(state->text);
249 }
250 }
251 }
252 g_free(input);
253
254 ModeMode mode = curr_mode;
255 // Find next enabled
256 if (retv == NEXT_DIALOG) {
257 mode = (mode + 1) % num_modes;
258 } else if (retv == PREVIOUS_DIALOG) {
259 if (mode == 0) {
260 mode = num_modes - 1;
261 } else {
262 mode = (mode - 1) % num_modes;
263 }
264 } else if (retv == RELOAD_DIALOG) {
265 // do nothing.
266 } else if (retv == RESET_DIALOG) {
268 } else if (retv < MODE_EXIT) {
269 mode = (retv) % num_modes;
270 } else {
271 mode = retv;
272 }
273 if (mode != MODE_EXIT) {
277 rofi_view_switch_mode(state, modes[mode]);
278 curr_mode = mode;
279 return;
280 }
281 // On exit, free current view, and pop to one above.
283 rofi_view_free(state);
284 return;
285 }
286 // rofi_view_set_active ( NULL );
288 rofi_view_free(state);
289}
290
294static void print_list_of_modes(int is_term) {
295 for (unsigned int i = 0; i < num_available_modes; i++) {
296 gboolean active = FALSE;
297 for (unsigned int j = 0; j < num_modes; j++) {
298 if (modes[j] == available_modes[i]) {
299 active = TRUE;
300 break;
301 }
302 }
303 printf(" • %s%s%s%s\n", active ? "+" : "",
304 is_term ? (active ? color_green : color_red) : "",
305 mode_get_name(available_modes[i]), is_term ? color_reset : "");
306 }
307}
308static void print_main_application_options(int is_term) {
309 print_help_msg("-config", "[file]", "Load an alternative configuration.",
310 NULL, is_term);
311 print_help_msg("-no-config", "",
312 "Do not load configuration, use default values.", NULL,
313 is_term);
314 print_help_msg("-v,-version", "", "Print the version number and exit.", NULL,
315 is_term);
316 print_help_msg("-dmenu", "", "Start in dmenu mode.", NULL, is_term);
317 print_help_msg("-display", "[string]", "X server to contact.", "${DISPLAY}",
318 is_term);
319 print_help_msg("-h,-help", "", "This help message.", NULL, is_term);
320 print_help_msg("-e", "[string]",
321 "Show a dialog displaying the passed message and exit.", NULL,
322 is_term);
323 print_help_msg("-markup", "", "Enable pango markup where possible.", NULL,
324 is_term);
325 print_help_msg("-normal-window", "",
326 "Behave as a normal window. (experimental)", NULL, is_term);
327 print_help_msg("-transient-window", "",
328 "Behave as a modal dialog that is transient to the currently "
329 "focused window. (experimental)",
330 NULL, is_term);
331 print_help_msg("-show", "[mode]",
332 "Show the mode 'mode' and exit. The mode has to be enabled.",
333 NULL, is_term);
334 print_help_msg("-no-lazy-grab", "",
335 "Disable lazy grab that, when fail to grab keyboard, does not "
336 "block but retry later.",
337 NULL, is_term);
338 print_help_msg("-no-plugins", "", "Disable loading of external plugins.",
339 NULL, is_term);
340 print_help_msg("-plugin-path", "",
341 "Directory used to search for rofi plugins. *DEPRECATED*",
342 NULL, is_term);
343 print_help_msg("-dump-config", "",
344 "Dump the current configuration in rasi format and exit.",
345 NULL, is_term);
346 print_help_msg("-dump-theme", "",
347 "Dump the current theme in rasi format and exit.", NULL,
348 is_term);
349 print_help_msg("-list-keybindings", "",
350 "Print a list of current keybindings and exit.", NULL,
351 is_term);
352}
353static void help(G_GNUC_UNUSED int argc, char **argv) {
354 int is_term = isatty(fileno(stdout));
355 printf("%s usage:\n", argv[0]);
356 printf("\t%s [-options ...]\n\n", argv[0]);
357 printf("Command line only options:\n");
359 printf("DMENU command line options:\n");
361 printf("Global options:\n");
363 printf("\n");
364 printf("Detected Window manager:\n");
366 if (wm) {
367 printf("\t• %s\n", wm);
368 g_free(wm);
369 } else {
370 printf("\t• No window manager detected.\n");
371 }
372 printf("\n");
374 printf("\n");
375 printf("Detected modes:\n");
376 print_list_of_modes(is_term);
377 printf("\n");
378 printf("Detected user scripts:\n");
379 script_user_list(is_term);
380 printf("\n");
381 printf("Compile time options:\n");
382 printf("\t• Pango version %s\n", pango_version_string());
383#ifdef WINDOW_MODE
384 printf("\t• window %senabled%s\n", is_term ? color_green : "",
385 is_term ? color_reset : "");
386#else
387 printf("\t• window %sdisabled%s\n", is_term ? color_red : "",
388 is_term ? color_reset : "");
389#endif
390#ifdef ENABLE_DRUN
391 printf("\t• drun %senabled%s\n", is_term ? color_green : "",
392 is_term ? color_reset : "");
393#else
394 printf("\t• drun %sdisabled%s\n", is_term ? color_red : "",
395 is_term ? color_reset : "");
396#endif
397#ifdef ENABLE_GCOV
398 printf("\t• gcov %senabled%s\n", is_term ? color_green : "",
399 is_term ? color_reset : "");
400#else
401 printf("\t• gcov %sdisabled%s\n", is_term ? color_red : "",
402 is_term ? color_reset : "");
403#endif
404#ifdef ENABLE_ASAN
405 printf("\t• asan %senabled%s\n", is_term ? color_green : "",
406 is_term ? color_reset : "");
407#else
408 printf("\t• asan %sdisabled%s\n", is_term ? color_red : "",
409 is_term ? color_reset : "");
410#endif
411#ifdef XCB_IMDKIT
412 printf("\t• imdkit %senabled%s\n", is_term ? color_green : "",
413 is_term ? color_reset : "");
414#else
415 printf("\t• imdkit %sdisabled%s\n", is_term ? color_red : "",
416 is_term ? color_reset : "");
417#endif
418 printf("\n");
419 printf("For more information see: %sman rofi%s\n", is_term ? color_bold : "",
420 is_term ? color_reset : "");
421#ifdef GIT_VERSION
422 printf(" Version: %s" GIT_VERSION "%s\n",
423 is_term ? color_bold : "", is_term ? color_reset : "");
424#else
425 printf(" Version: %s" VERSION "%s\n",
426 is_term ? color_bold : "", is_term ? color_reset : "");
427#endif
428 printf(" Bugreports: %s" PACKAGE_BUGREPORT "%s\n",
429 is_term ? color_bold : "", is_term ? color_reset : "");
430 printf(" Support: %s" PACKAGE_URL "%s\n",
431 is_term ? color_bold : "", is_term ? color_reset : "");
432 printf(" %s#rofi @ libera.chat%s\n",
433 is_term ? color_bold : "", is_term ? color_reset : "");
434 if (find_arg("-no-config") < 0) {
435 if (config_path) {
436 printf(" Configuration file: %s%s%s\n", is_term ? color_bold : "",
437 config_path, is_term ? color_reset : "");
438 }
439 } else {
440 printf(" Configuration file: %sDisabled%s\n",
441 is_term ? color_bold : "", is_term ? color_reset : "");
442 }
444}
445
446static void help_print_disabled_mode(const char *mode) {
447 int is_term = isatty(fileno(stdout));
448 // Only output to terminal
449 if (is_term) {
450 fprintf(stderr, "Mode %s%s%s is not enabled. I have enabled it for now.\n",
451 color_red, mode, color_reset);
452 fprintf(stderr,
453 "Please consider adding %s%s%s to the list of enabled modes: "
454 "%smodes: [%s%s%s,%s]%s.\n",
457 }
458}
459static void help_print_mode_not_found(const char *mode) {
460 GString *str = g_string_new("");
461 g_string_printf(
462 str, "Mode %s is not found.\nThe following modes are known:\n", mode);
463 for (unsigned int i = 0; i < num_available_modes; i++) {
464 gboolean active = FALSE;
465 for (unsigned int j = 0; j < num_modes; j++) {
466 if (modes[j] == available_modes[i]) {
467 active = TRUE;
468 break;
469 }
470 }
471 g_string_append_printf(str, " * %s%s\n", active ? "+" : "",
473 }
475}
476static void help_print_no_arguments(void) {
477
478 GString *emesg = g_string_new(
479 "<span size=\"x-large\">Rofi is unsure what to show.</span>\n\n");
480 g_string_append(emesg, "Please specify the mode you want to show.\n\n");
481 g_string_append(
482 emesg, " <b>rofi</b> -show <span color=\"green\">{mode}</span>\n\n");
483 g_string_append(emesg, "The following modes are enabled:\n");
484 for (unsigned int j = 0; j < num_modes; j++) {
485 g_string_append_printf(emesg, " • <span color=\"green\">%s</span>\n",
486 mode_get_name(modes[j]));
487 }
488 g_string_append(emesg, "\nThe following modes can be enabled:\n");
489 for (unsigned int i = 0; i < num_available_modes; i++) {
490 gboolean active = FALSE;
491 for (unsigned int j = 0; j < num_modes; j++) {
492 if (modes[j] == available_modes[i]) {
493 active = TRUE;
494 break;
495 }
496 }
497 if (!active) {
498 g_string_append_printf(emesg, " • <span color=\"red\">%s</span>\n",
500 }
501 }
502 g_string_append(emesg, "\nTo activate a mode, add it to the list in "
503 "the <span color=\"green\">modes</span> "
504 "setting.\n");
506 rofi_set_return_code(EXIT_SUCCESS);
507}
508
512static void cleanup(void) {
513 for (unsigned int i = 0; i < num_modes; i++) {
515 }
517 if (main_loop != NULL) {
518 g_main_loop_unref(main_loop);
519 main_loop = NULL;
520 }
521 // Cleanup
523
524 nk_bindings_free(bindings);
525
526 // Cleaning up memory allocated by the Xresources file.
528 g_free(modes);
529
530 g_free(config_path);
531
534
535 if (rofi_theme) {
537 rofi_theme = NULL;
538 }
539 TIMINGS_STOP();
543
545 if (rofi_configuration) {
547 rofi_configuration = NULL;
548 }
549 // Cleanup memory allocated by rofi_expand_path
550 if (cache_dir_alloc) {
551 g_free(cache_dir_alloc);
552 cache_dir_alloc = NULL;
553 }
554}
555
559
560Mode *rofi_collect_modes_search(const char *name) {
561 for (unsigned int i = 0; i < num_available_modes; i++) {
562 if (g_strcmp0(name, mode_get_name(available_modes[i])) == 0) {
563 return available_modes[i];
564 }
565 }
566 return NULL;
567}
568
573static gboolean rofi_collectmodes_add(Mode *mode) {
575 if (m == NULL) {
577 g_realloc(available_modes, sizeof(Mode *) * (num_available_modes + 1));
578 // Set mode.
581 return TRUE;
582 }
583 return FALSE;
584}
585
586static void rofi_collectmodes_dir(const char *base_dir) {
587 g_debug("Looking into: %s for plugins", base_dir);
588 GDir *dir = g_dir_open(base_dir, 0, NULL);
589 if (dir) {
590 const char *dn = NULL;
591 while ((dn = g_dir_read_name(dir))) {
592 if (!g_str_has_suffix(dn, G_MODULE_SUFFIX)) {
593 continue;
594 }
595 char *fn = g_build_filename(base_dir, dn, NULL);
596 g_debug("Trying to open: %s plugin", fn);
597 GModule *mod =
598 g_module_open(fn, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
599 if (mod) {
600 Mode *m = NULL;
601 if (g_module_symbol(mod, "mode", (gpointer *)&m)) {
603 g_warning("ABI version of plugin: '%s' does not match: %08X "
604 "expecting: %08X",
606 g_module_close(mod);
607 } else {
609 if (!rofi_collectmodes_add(m)) {
610 g_module_close(mod);
611 }
612 }
613 } else {
614 g_warning("Symbol 'mode' not found in module: %s", dn);
615 g_module_close(mod);
616 }
617 } else {
618 g_warning("Failed to open 'mode' plugin: '%s', error: %s", dn,
619 g_module_error());
620 }
621 g_free(fn);
622 }
623 g_dir_close(dir);
624 }
625}
626
630static void rofi_collect_modes(void) {
631#ifdef WINDOW_MODE
632 rofi_collectmodes_add(&window_mode);
633 rofi_collectmodes_add(&window_mode_cd);
634#endif
637#ifdef ENABLE_DRUN
638 rofi_collectmodes_add(&drun_mode);
639#endif
644
645 if (find_arg("-no-plugins") < 0) {
646 find_arg_str("-plugin-path", &(config.plugin_path));
647 g_debug("Parse plugin path: %s", config.plugin_path);
648 rofi_collectmodes_dir(config.plugin_path);
649 /* ROFI_PLUGIN_PATH */
650 const char *path = g_getenv("ROFI_PLUGIN_PATH");
651 if (path != NULL) {
652 gchar **paths = g_strsplit(path, ":", -1);
653 for (unsigned int i = 0; paths[i]; i++) {
654 rofi_collectmodes_dir(paths[i]);
655 }
656 g_strfreev(paths);
657 }
658 }
660}
661
665static void rofi_collectmodes_setup(void) {
666 for (unsigned int i = 0; i < num_available_modes; i++) {
668 }
669}
670static void rofi_collectmodes_destroy(void) {
671 for (unsigned int i = 0; i < num_available_modes; i++) {
673 GModule *mod = mode_plugin_get_module(available_modes[i]);
674 available_modes[i] = NULL;
675 g_module_close(mod);
676 }
677 if (available_modes[i]) {
679 }
680 }
681 g_free(available_modes);
682 available_modes = NULL;
684}
685
693static int add_mode(const char *token) {
694 unsigned int index = num_modes;
695 // Resize and add entry.
696 modes = (Mode **)g_realloc(modes, sizeof(Mode *) * (num_modes + 1));
697
698 Mode *mode = rofi_collect_modes_search(token);
699 if (mode) {
700 modes[num_modes] = mode;
701 num_modes++;
702 } else if (script_mode_is_valid(token)) {
703 // If not build in, use custom mode.
704 Mode *sw = script_mode_parse_setup(token);
705 if (sw != NULL) {
706 // Add to available list, so combi can find it.
708 mode_set_config(sw);
709 modes[num_modes] = sw;
710 num_modes++;
711 }
712 }
713 return (index == num_modes) ? -1 : (int)index;
714}
715static gboolean setup_modes(void) {
716 const char *const sep = ",#";
717 char *savept = NULL;
718 // Make a copy, as strtok will modify it.
719 char *mode_str = g_strdup(config.modes);
720 // Split token on ','. This modifies mode_str.
721 for (char *token = strtok_r(mode_str, sep, &savept); token != NULL;
722 token = strtok_r(NULL, sep, &savept)) {
723 if (add_mode(token) == -1) {
725 }
726 }
727 // Free string that was modified by strtok_r
728 g_free(mode_str);
729 return FALSE;
730}
731
736void rofi_quit_main_loop(void) { g_main_loop_quit(main_loop); }
737
738static gboolean main_loop_signal_handler_int(G_GNUC_UNUSED gpointer data) {
739 // Break out of loop.
740 g_main_loop_quit(main_loop);
741 return G_SOURCE_CONTINUE;
742}
743static void show_error_dialog(void) {
744 GString *emesg =
745 g_string_new("The following errors were detected when starting rofi:\n");
746 GList *iter = g_list_first(list_of_error_msgs);
747 int index = 0;
748 for (; iter != NULL && index < 2; iter = g_list_next(iter)) {
749 GString *msg = (GString *)(iter->data);
750 g_string_append(emesg, "\n\n");
751 g_string_append(emesg, msg->str);
752 index++;
753 }
754 if (g_list_length(iter) > 1) {
755 g_string_append_printf(emesg, "\nThere are <b>%u</b> more errors.",
756 g_list_length(iter) - 1);
757 }
759 g_string_free(emesg, TRUE);
760 rofi_set_return_code(EX_DATAERR);
761}
762
763static gboolean startup(G_GNUC_UNUSED gpointer data) {
764 TICK_N("Startup");
765 // flags to run immediately and exit
766 char *sname = NULL;
767 char *msg = NULL;
768 MenuFlags window_flags = MENU_NORMAL;
769
770 if (find_arg("-normal-window") >= 0) {
771 window_flags |= MENU_NORMAL_WINDOW;
772 }
773 if (find_arg("-transient-window") >= 0) {
774 window_flags |= MENU_TRANSIENT_WINDOW;
775 }
776 TICK_N("Grab keyboard");
777 __create_window(window_flags);
778 TICK_N("Create Window");
779 // Parse the keybindings.
780 TICK_N("Parse ABE");
781 // Sanity check
783 TICK_N("Config sanity check");
784
785 if (list_of_error_msgs != NULL) {
787 return G_SOURCE_REMOVE;
788 }
789 if (list_of_warning_msgs != NULL) {
790 for (GList *iter = g_list_first(list_of_warning_msgs); iter != NULL;
791 iter = g_list_next(iter)) {
792 fputs(((GString *)iter->data)->str, stderr);
793 fputs("\n", stderr);
794 }
795 }
796 // Dmenu mode.
797 if (rofi_is_in_dmenu_mode == TRUE) {
798 // force off sidebar mode:
799 config.sidebar_mode = FALSE;
800 int retv = dmenu_mode_dialog();
801 if (retv) {
802 rofi_set_return_code(EXIT_SUCCESS);
803 // Directly exit.
804 g_main_loop_quit(main_loop);
805 }
806 } else if (find_arg_str("-e", &(msg))) {
807 int markup = FALSE;
808 if (find_arg("-markup") >= 0) {
809 markup = TRUE;
810 }
811 // When we pass -, we read from stdin.
812 if (g_strcmp0(msg, "-") == 0) {
813 size_t index = 0, i = 0;
814 size_t length = 1024;
815 msg = malloc(length * sizeof(char));
816 while ((i = fread(&msg[index], 1, 1024, stdin)) > 0) {
817 index += i;
818 length += i;
819 msg = realloc(msg, length * sizeof(char));
820 }
821
822 msg[index] = 0;
823
824 if (!rofi_view_error_dialog(msg, markup)) {
825 g_main_loop_quit(main_loop);
826 }
827 g_free(msg);
828 } else {
829 // Normal version
830 if (!rofi_view_error_dialog(msg, markup)) {
831 g_main_loop_quit(main_loop);
832 }
833 }
834 } else if (find_arg_str("-show", &sname) == TRUE) {
835 int index = mode_lookup(sname);
836 if (index < 0) {
837 // Add it to the list
838 index = add_mode(sname);
839 // Complain
840 if (index >= 0) {
842 }
843 // Run it anyway if found.
844 }
845 if (index >= 0) {
846 run_mode_index(index);
847 } else {
850 return G_SOURCE_REMOVE;
851 }
852 } else if (find_arg("-show") >= 0 && num_modes > 0) {
854 } else {
856
857 // g_main_loop_quit(main_loop);
858 }
859
860 return G_SOURCE_REMOVE;
861}
862
863static gboolean take_screenshot_quit(G_GNUC_UNUSED void *data) {
866 return G_SOURCE_REMOVE;
867}
868static gboolean record(G_GNUC_UNUSED void *data) {
870 return G_SOURCE_CONTINUE;
871}
872static void rofi_custom_log_function(const char *log_domain,
873 G_GNUC_UNUSED GLogLevelFlags log_level,
874 const gchar *message, gpointer user_data) {
875 int fp = GPOINTER_TO_INT(user_data);
876 dprintf(fp, "[%s]: %s\n", log_domain == NULL ? "default" : log_domain,
877 message);
878}
879
887int main(int argc, char *argv[]) {
888 cmd_set_arguments(argc, argv);
889 if (find_arg("-log") >= 0) {
890 char *logfile = NULL;
891 find_arg_str("-log", &logfile);
892 if (logfile != NULL) {
893 int fp = open(logfile, O_CLOEXEC | O_APPEND | O_CREAT | O_WRONLY,
894 S_IRUSR | S_IWUSR);
895 if (fp != -1) {
896 g_log_set_default_handler(rofi_custom_log_function,
897 GINT_TO_POINTER(fp));
898
899 } else {
900 g_error("Failed to open logfile '%s': %s.", logfile, strerror(errno));
901 }
902
903 } else {
904 g_warning("Option '-log' should pass in a filename.");
905 }
906 }
908
909 // Version
910 if (find_arg("-v") >= 0 || find_arg("-version") >= 0) {
911#ifdef GIT_VERSION
912 g_print("Version: " GIT_VERSION "\n");
913#else
914 g_print("Version: " VERSION "\n");
915#endif
916 return EXIT_SUCCESS;
917 }
918
919 if (find_arg("-rasi-validate") >= 0) {
920 char *str = NULL;
921 find_arg_str("-rasi-validate", &str);
922 if (str != NULL) {
923 int retv = rofi_theme_rasi_validate(str);
924 cleanup();
925 return retv;
926 }
927 fprintf(stderr, "Usage: %s -rasi-validate my-theme.rasi", argv[0]);
928 return EXIT_FAILURE;
929 }
930
931 {
932 const char *ro_pid = g_getenv("ROFI_OUTSIDE");
933 if (ro_pid != NULL) {
934 pid_t ro_pidi = (pid_t)g_ascii_strtoll(ro_pid, NULL, 0);
935 if (kill(ro_pidi, 0) == 0) {
936 printf("Do not launch rofi from inside rofi.\r\n");
937 return EXIT_FAILURE;
938 }
939 }
940 }
941
942 // Detect if we are in dmenu mode.
943 // This has two possible causes.
944 // 1 the user specifies it on the command-line.
945 if (find_arg("-dmenu") >= 0) {
947 }
948 // 2 the binary that executed is called dmenu (e.g. symlink to rofi)
949 else {
950 // Get the base name of the executable called.
951 char *base_name = g_path_get_basename(argv[0]);
952 const char *const dmenu_str = "dmenu";
953 rofi_is_in_dmenu_mode = (strcmp(base_name, dmenu_str) == 0);
954 // Free the basename for dmenu detection.
955 g_free(base_name);
956 }
957 TICK();
958
959 // Create pid file path.
960 const char *path = g_get_user_runtime_dir();
961 if (path) {
962 if (g_mkdir_with_parents(path, 0700) < 0) {
963 g_warning("Failed to create user runtime directory: %s with error: %s",
964 path, g_strerror(errno));
965 pidfile = g_build_filename(g_get_home_dir(), ".rofi.pid", NULL);
966 } else {
967 pidfile = g_build_filename(path, "rofi.pid", NULL);
968 }
969 }
971 "Pidfile location");
972
974 if (find_arg("-no-default-config") < 0) {
975 GBytes *theme_data = g_resource_lookup_data(
976 resources_get_resource(), "/org/qtools/rofi/default_configuration.rasi",
977 G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
978 if (theme_data) {
979 const char *theme = g_bytes_get_data(theme_data, NULL);
980 if (rofi_theme_parse_string((const char *)theme)) {
981 g_warning("Failed to parse default configuration. Giving up..");
982 if (list_of_error_msgs) {
983 for (GList *iter = g_list_first(list_of_error_msgs); iter != NULL;
984 iter = g_list_next(iter)) {
985 g_warning("Error: %s%s%s", color_bold, ((GString *)iter->data)->str,
987 }
988 }
989 rofi_configuration = NULL;
990 cleanup();
991 return EXIT_FAILURE;
992 }
993 g_bytes_unref(theme_data);
994 }
995 }
996
997 if (find_arg("-config") < 0) {
998 const char *cpath = g_get_user_config_dir();
999 if (cpath) {
1000 config_path = g_build_filename(cpath, "rofi", "config.rasi", NULL);
1001 }
1002 } else {
1003 char *c = NULL;
1004 find_arg_str("-config", &c);
1006 }
1007
1008 TICK();
1009 if (setlocale(LC_ALL, "") == NULL) {
1010 g_warning("Failed to set locale.");
1011 cleanup();
1012 return EXIT_FAILURE;
1013 }
1014
1015 TICK_N("Setup Locale");
1017 TICK_N("Collect MODES");
1019 TICK_N("Setup MODES");
1020
1021 main_loop = g_main_loop_new(NULL, FALSE);
1022
1023 TICK_N("Setup mainloop");
1024
1025 bindings = nk_bindings_new(0lu);
1026 TICK_N("NK Bindings");
1027
1029 g_warning("Connection has error");
1030 cleanup();
1031 return EXIT_FAILURE;
1032 }
1033 TICK_N("Setup Display");
1034
1035 // Setup keybinding
1036 setup_abe();
1037 TICK_N("Setup abe");
1038
1039 if (find_arg("-no-config") < 0) {
1040 // Load distro default settings
1041 gboolean found_system = FALSE;
1042 const char *const *dirs = g_get_system_config_dirs();
1043 if (dirs) {
1044 for (unsigned int i = 0; !found_system && dirs[i]; i++) {
1046 gchar *etc = g_build_filename(dirs[i], "rofi.rasi", NULL);
1047 g_debug("Look for default config file: %s", etc);
1048 if (g_file_test(etc, G_FILE_TEST_IS_REGULAR)) {
1049 g_debug("Parsing: %s", etc);
1051 found_system = TRUE;
1052 }
1053 g_free(etc);
1054 }
1055 }
1056 if (!found_system) {
1058 gchar *etc = g_build_filename(SYSCONFDIR, "rofi.rasi", NULL);
1059 g_debug("Look for default config file: %s", etc);
1060 if (g_file_test(etc, G_FILE_TEST_IS_REGULAR)) {
1061 g_debug("Look for default config file: %s", etc);
1063 }
1064 g_free(etc);
1065 }
1066
1067 if (config_path) {
1068 // Try to resolve the path.
1069 extern const char *rasi_theme_file_extensions[];
1070 char *file2 =
1071 helper_get_theme_path(config_path, rasi_theme_file_extensions, NULL);
1072 GFile *gf = g_file_new_for_path(file2);
1073 char *filename = g_file_get_path(gf);
1074 g_object_unref(gf);
1075 g_free(file2);
1076 if (filename && g_file_test(filename, G_FILE_TEST_EXISTS)) {
1077 if (rofi_theme_parse_file(filename)) {
1079 rofi_theme = NULL;
1080 }
1081 }
1082 g_free(filename);
1083 }
1084 }
1085 find_arg_str("-theme", &(config.theme));
1086 if (config.theme) {
1087 TICK_N("Parse theme");
1089 if (rofi_theme_parse_file(config.theme)) {
1090 g_warning("Failed to parse theme: \"%s\"", config.theme);
1091 // TODO: instantiate fallback theme.?
1093 rofi_theme = NULL;
1094 }
1095 TICK_N("Parsed theme");
1096 }
1097 // Parse command line for settings, independent of other -no-config.
1098 if (list_of_error_msgs == NULL) {
1099 // Only call this when there are no errors.
1100 // This might clear existing errors.
1102 }
1103
1104 if (rofi_theme == NULL || rofi_theme->num_widgets == 0) {
1105 g_debug("Failed to load theme. Try to load default: ");
1106 rofi_theme_parse_string("@theme \"default\"");
1107 }
1108 TICK_N("Load cmd config ");
1109
1110 // Get the path to the cache dir.
1111 cache_dir = g_get_user_cache_dir();
1112
1113 if (config.cache_dir != NULL) {
1115 }
1116
1117 if (g_mkdir_with_parents(cache_dir, 0700) < 0) {
1118 g_warning("Failed to create cache directory: %s", g_strerror(errno));
1119 return EXIT_FAILURE;
1120 }
1121
1123 char *windowid = NULL;
1124 if (!rofi_is_in_dmenu_mode) {
1125 // setup_modes
1126 if (setup_modes()) {
1127 cleanup();
1128 return EXIT_FAILURE;
1129 }
1130 TICK_N("Setup Modes");
1131 } else {
1132 // Hack for dmenu compatibility.
1133 if (find_arg_str("-w", &windowid) == TRUE) {
1134 config.monitor = g_strdup_printf("wid:%s", windowid);
1135 windowid = config.monitor;
1136 }
1137 }
1138
1142 const char **theme_str = find_arg_strv("-theme-str");
1143 if (theme_str) {
1144 for (int index = 0; theme_str[index]; index++) {
1145 if (rofi_theme_parse_string(theme_str[index])) {
1146 g_warning("Failed to parse -theme-str option: \"%s\"",
1147 theme_str[index]);
1149 rofi_theme = NULL;
1150 }
1151 }
1152 g_free(theme_str);
1153 }
1154
1156 if (find_arg("-dump-theme") >= 0) {
1158 cleanup();
1159 return EXIT_SUCCESS;
1160 }
1161 if (find_arg("-dump-processed-theme") >= 0) {
1164 cleanup();
1165 return EXIT_SUCCESS;
1166 }
1167 if (find_arg("-dump-config") >= 0) {
1169 cleanup();
1170 return EXIT_SUCCESS;
1171 }
1172 // Dump.
1173 // catch help request
1174 if (find_arg("-h") >= 0 || find_arg("-help") >= 0 ||
1175 find_arg("--help") >= 0) {
1176 help(argc, argv);
1177 cleanup();
1178 return EXIT_SUCCESS;
1179 }
1180 if (find_arg("-list-keybindings") >= 0) {
1181 int is_term = isatty(fileno(stdout));
1182 abe_list_all_bindings(is_term);
1183 return EXIT_SUCCESS;
1184 }
1185
1186 unsigned int interval = 1;
1187 if (find_arg_uint("-record-screenshots", &interval)) {
1188 g_timeout_add((guint)(1000 / (double)interval), record, NULL);
1189 }
1190 if (find_arg_uint("-take-screenshot-quit", &interval)) {
1191 g_timeout_add(interval, take_screenshot_quit, NULL);
1192 }
1193 if (find_arg("-benchmark-ui") >= 0) {
1194 config.benchmark_ui = TRUE;
1195 }
1196
1198 TICK_N("Workers initialize");
1200 TICK_N("Icon fetcher initialize");
1201
1202 gboolean kill_running = FALSE;
1203 if (find_arg("-replace") >= 0) {
1204 kill_running = TRUE;
1205 }
1206 // Create pid file
1207 int pfd = create_pid_file(pidfile, kill_running);
1208 TICK_N("Pid file created");
1209 if (pfd < 0) {
1210 cleanup();
1211 return EXIT_FAILURE;
1212 }
1213 textbox_setup();
1214 TICK_N("Text box setup");
1215
1216 if (!display_late_setup()) {
1217 g_warning("Failed to properly finish display setup");
1218 cleanup();
1219 return EXIT_FAILURE;
1220 }
1221 TICK_N("Setup late Display");
1222
1225 TICK_N("Theme setup");
1226
1227 // Setup signal handling sources.
1228 // SIGINT
1229 g_unix_signal_add(SIGINT, main_loop_signal_handler_int, NULL);
1230
1231 g_idle_add(startup, NULL);
1232
1233 // Start mainloop.
1234 g_main_loop_run(main_loop);
1235 teardown(pfd);
1236 cleanup();
1237
1238 /* dirty hack */
1239 g_free(windowid);
1240 return return_code;
1241}
1242
1244extern GList *list_of_error_msgs;
1245int rofi_theme_rasi_validate(const char *filename) {
1246 rofi_theme_parse_file(filename);
1248 if (list_of_error_msgs == NULL && list_of_warning_msgs == NULL) {
1249 return EXIT_SUCCESS;
1250 }
1251
1252 for (GList *iter = g_list_first(list_of_error_msgs); iter != NULL;
1253 iter = g_list_next(iter)) {
1254 fputs(((GString *)iter->data)->str, stderr);
1255 fputs("\n", stderr);
1256 }
1257 for (GList *iter = g_list_first(list_of_warning_msgs); iter != NULL;
1258 iter = g_list_next(iter)) {
1259 fputs(((GString *)iter->data)->str, stderr);
1260 fputs("\n", stderr);
1261 }
1262
1263 return EXIT_FAILURE;
1264}
1265
1267 const Mode *index = mode_available_lookup(config.completer_mode);
1268 if (index != NULL) {
1269 return index;
1270 }
1271 const char *name =
1272 config.completer_mode == NULL ? "(null)" : config.completer_mode;
1273 g_warning("Mode: %s not found or is not valid for use as completer.", name);
1274 return NULL;
1275}
Mode combi_mode
Definition combi.c:333
void config_parse_cmd_options(void)
Definition xrmoptions.c:631
void print_options(void)
void config_parser_add_option(XrmOptionType type, const char *key, void **value, const char *comment)
Definition xrmoptions.c:523
void print_help_msg(const char *option, const char *type, const char *text, const char *def, int isatty)
void config_parse_dump_config_rasi_format(FILE *out, gboolean changes)
Dump configuration in rasi format.
Definition xrmoptions.c:892
@ xrm_String
Definition xrmoptions.h:74
void config_xresource_free(void)
Definition xrmoptions.c:830
int dmenu_mode_dialog(void)
Definition dmenu.c:920
void print_dmenu_options(void)
Definition dmenu.c:1014
Mode recursive_browser_mode
Mode file_browser_mode
void cmd_set_arguments(int argc, char **argv)
Definition helper.c:98
const char ** find_arg_strv(const char *const key)
Definition helper.c:345
char * rofi_expand_path(const char *input)
Definition helper.c:781
void remove_pid_file(int fd)
Definition helper.c:645
int find_arg_str(const char *const key, char **val)
Definition helper.c:335
int find_arg_uint(const char *const key, unsigned int *val)
Definition helper.c:374
int find_arg(const char *const key)
Definition helper.c:326
int create_pid_file(const char *pidfile, gboolean kill_running)
Definition helper.c:586
int config_sanity_check(void)
Definition helper.c:672
Mode help_keys_mode
Definition help-keys.c:113
void rofi_icon_fetcher_destroy(void)
void rofi_icon_fetcher_init(void)
gboolean parse_keys_abe(NkBindings *bindings)
Definition keyb.c:445
void setup_abe(void)
Definition keyb.c:411
void abe_list_all_bindings(gboolean is_term)
Definition keyb.c:392
void mode_destroy(Mode *mode)
Definition mode.c:64
const char * mode_get_name(const Mode *mode)
Definition mode.c:157
int mode_init(Mode *mode)
Definition mode.c:44
struct rofi_mode Mode
Definition mode.h:49
void mode_free(Mode **mode)
Definition mode.c:167
int mode_get_abi_version(Mode *const mode)
Definition mode.c:162
ModeMode mode_result(Mode *mode, int menu_retv, char **input, unsigned int selected_line)
Definition mode.c:131
void mode_plugin_set_module(Mode *mode, GModule *mod)
Definition mode.c:253
MenuReturn
Definition mode.h:70
GModule * mode_plugin_get_module(Mode *mode)
Definition mode.c:256
ModeMode
Definition mode.h:54
void mode_set_config(Mode *mode)
Definition mode.c:205
@ MODE_EXIT
Definition mode.h:56
@ NEXT_DIALOG
Definition mode.h:58
@ RELOAD_DIALOG
Definition mode.h:60
@ PREVIOUS_DIALOG
Definition mode.h:62
@ RESET_DIALOG
Definition mode.h:64
const Mode * rofi_get_mode(unsigned int index)
Definition rofi.c:150
void rofi_quit_main_loop(void)
Definition rofi.c:736
#define color_reset
Definition rofi.h:115
#define color_bold
Definition rofi.h:117
unsigned int rofi_get_num_enabled_modes(void)
Definition rofi.c:148
void rofi_clear_error_messages(void)
Definition rofi.c:94
void rofi_clear_warning_messages(void)
Definition rofi.c:107
#define color_red
Definition rofi.h:123
#define ERROR_MSG_MARKUP
Definition rofi.h:136
void rofi_set_return_code(int code)
Definition rofi.c:146
const Mode * rofi_get_completer(void)
Definition rofi.c:1266
Mode * rofi_collect_modes_search(const char *name)
Definition rofi.c:560
const char * cache_dir
Definition rofi.c:80
void rofi_add_error_message(GString *str)
Definition rofi.c:91
#define color_green
Definition rofi.h:121
void rofi_add_warning_message(GString *str)
Definition rofi.c:104
Mode run_mode
Definition run.c:598
void script_mode_gather_user_scripts(void)
Definition script.c:556
gboolean script_mode_is_valid(const char *token)
Definition script.c:647
void script_user_list(gboolean is_term)
Definition script.c:654
void script_mode_cleanup(void)
Definition script.c:549
Mode * script_mode_parse_setup(const char *str)
Definition script.c:595
Mode ssh_mode
Definition ssh.c:637
#define TICK()
Definition timings.h:64
#define TIMINGS_START()
Definition timings.h:60
#define TIMINGS_STOP()
Definition timings.h:73
#define TICK_N(a)
Definition timings.h:69
void textbox_cleanup(void)
Definition textbox.c:999
void textbox_setup(void)
Definition textbox.c:967
void textbox_cursor_end(textbox *tb)
Definition textbox.c:739
void textbox_text(textbox *tb, const char *text)
Definition textbox.c:404
void rofi_view_cleanup(void)
Definition view.c:2728
void __create_window(MenuFlags menu_flags)
Definition view.c:1022
void rofi_view_clear_input(RofiViewState *state)
Definition view.c:2889
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Definition view.c:2901
void rofi_view_remove_active(RofiViewState *state)
Definition view.c:625
int rofi_view_error_dialog(const char *msg, int markup)
Definition view.c:2675
void rofi_view_set_active(RofiViewState *state)
Definition view.c:632
RofiViewState * rofi_view_get_active(void)
Definition view.c:623
MenuFlags
Definition view.h:50
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition view.c:692
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition view.c:713
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition view.c:655
void rofi_view_free(RofiViewState *state)
Definition view.c:674
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition view.c:2565
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition view.c:696
@ MENU_TRANSIENT_WINDOW
Definition view.h:60
@ MENU_NORMAL_WINDOW
Definition view.h:56
@ MENU_NORMAL
Definition view.h:52
void rofi_capture_screenshot(void)
Definition view.c:233
void rofi_view_workers_initialize(void)
Definition view.c:2809
void rofi_view_workers_finalize(void)
Definition view.c:2838
char * helper_get_theme_path(const char *file, const char **ext, const char *parent_file)
Definition helper.c:1197
#define ABI_VERSION
Definition mode.h:36
static void help(G_GNUC_UNUSED int argc, char **argv)
Definition rofi.c:353
static void rofi_collect_modes(void)
Definition rofi.c:630
int main(int argc, char *argv[])
Definition rofi.c:887
GList * list_of_warning_msgs
Definition rofi.c:88
GList * list_of_error_msgs
Definition rofi.c:86
static gboolean record(G_GNUC_UNUSED void *data)
Definition rofi.c:868
G_MODULE_EXPORT char * config_path
Definition rofi.c:119
NkBindings * bindings
Definition rofi.c:134
static void print_main_application_options(int is_term)
Definition rofi.c:308
static void print_list_of_modes(int is_term)
Definition rofi.c:294
static void run_mode_index(ModeMode mode)
Definition rofi.c:199
static void rofi_custom_log_function(const char *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, const gchar *message, gpointer user_data)
Definition rofi.c:872
static void help_print_mode_not_found(const char *mode)
Definition rofi.c:459
static void cleanup(void)
Definition rofi.c:512
Mode ** modes
Definition rofi.c:122
static gboolean startup(G_GNUC_UNUSED gpointer data)
Definition rofi.c:763
static gboolean setup_modes(void)
Definition rofi.c:715
Mode ** available_modes
Definition rofi.c:125
int rofi_theme_rasi_validate(const char *filename)
Definition rofi.c:1245
unsigned int num_modes
Definition rofi.c:129
static void rofi_collectmodes_setup(void)
Definition rofi.c:665
GMainLoop * main_loop
Definition rofi.c:137
static void teardown(int pfd)
Definition rofi.c:186
static gboolean rofi_collectmodes_add(Mode *mode)
Definition rofi.c:573
static gboolean take_screenshot_quit(G_GNUC_UNUSED void *data)
Definition rofi.c:863
static void rofi_collectmodes_destroy(void)
Definition rofi.c:670
char * pidfile
Definition rofi.c:78
int return_code
Definition rofi.c:142
void process_result(RofiViewState *state)
Definition rofi.c:233
static const Mode * mode_available_lookup(const char *name)
Definition rofi.c:174
static int add_mode(const char *token)
Definition rofi.c:693
static gboolean main_loop_signal_handler_int(G_GNUC_UNUSED gpointer data)
Definition rofi.c:738
static void show_error_dialog(void)
Definition rofi.c:743
char * cache_dir_alloc
Definition rofi.c:83
int rofi_is_in_dmenu_mode
Definition rofi.c:140
static void help_print_no_arguments(void)
Definition rofi.c:476
static int mode_lookup(const char *name)
Definition rofi.c:159
static void help_print_disabled_mode(const char *mode)
Definition rofi.c:446
unsigned int num_available_modes
Definition rofi.c:127
static void rofi_collectmodes_dir(const char *base_dir)
Definition rofi.c:586
unsigned int curr_mode
Definition rofi.c:131
Settings config
textbox * text
void rofi_theme_free_parsed_files(void)
Definition theme.c:54
void rofi_theme_print_parsed_files(gboolean is_term)
Definition theme.c:64
void rofi_theme_print(ThemeWidget *wid)
Definition theme.c:593
void rofi_theme_parse_process_links(void)
Definition theme.c:1598
void rofi_theme_parse_process_conditionals(void)
Definition theme.c:1602
void rofi_theme_free(ThemeWidget *wid)
Definition theme.c:240
void rofi_theme_reset(void)
Definition theme.c:234
gboolean rofi_theme_parse_string(const char *string)
gboolean rofi_theme_parse_file(const char *file)
ThemeWidget * rofi_theme
Definition theme.h:43
gboolean display_late_setup(void)
Definition xcb.c:1916
void display_early_cleanup(void)
Definition xcb.c:1951
void display_cleanup(void)
Definition xcb.c:1957
char * x11_helper_get_window_manager(void)
Definition xcb.c:1625
gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings)
Definition xcb.c:1670
void display_dump_monitor_layout(void)
Definition xcb.c:694
ThemeWidget * rofi_configuration
Definition xrmoptions.c:46