rofi  1.5.4
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-2017 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 <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <stdint.h>
38 #include <errno.h>
39 #include <time.h>
40 #include <locale.h>
41 #include <gmodule.h>
42 #include <xcb/xcb.h>
43 #include <sys/types.h>
44 #include <sysexits.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 "rofi.h"
60 #include "display.h"
61 
62 #include "settings.h"
63 #include "mode.h"
64 #include "helper.h"
65 #include "widgets/textbox.h"
66 #include "xrmoptions.h"
67 #include "dialogs/dialogs.h"
68 
69 #include "view.h"
70 #include "view-internal.h"
71 
72 #include "theme.h"
73 #include "rofi-icon-fetcher.h"
74 
75 #include "timings.h"
76 
77 // Plugin abi version.
78 // TODO: move this check to mode.c
79 #include "mode-private.h"
80 
82 char *pidfile = NULL;
84 const char *cache_dir = NULL;
85 
87 GList *list_of_error_msgs = NULL;
88 
89 static void rofi_collect_modi_destroy ( void );
90 void rofi_add_error_message ( GString *str )
91 {
92  list_of_error_msgs = g_list_append ( list_of_error_msgs, str );
93 }
94 
96 G_MODULE_EXPORT char *config_path = NULL;
98 G_MODULE_EXPORT char *config_path_new = NULL;
100 Mode **modi = NULL;
101 
105 unsigned int num_available_modi = 0;
107 unsigned int num_modi = 0;
109 unsigned int curr_switcher = 0;
110 
112 NkBindings *bindings = NULL;
113 
115 GMainLoop *main_loop = NULL;
116 
118 static int dmenu_mode = FALSE;
120 int return_code = EXIT_SUCCESS;
121 
122 void process_result ( RofiViewState *state );
123 
124 void rofi_set_return_code ( int code )
125 {
126  return_code = code;
127 }
128 
129 unsigned int rofi_get_num_enabled_modi ( void )
130 {
131  return num_modi;
132 }
133 
134 const Mode * rofi_get_mode ( unsigned int index )
135 {
136  return modi[index];
137 }
138 
146 static int switcher_get ( const char *name )
147 {
148  for ( unsigned int i = 0; i < num_modi; i++ ) {
149  if ( strcmp ( mode_get_name ( modi[i] ), name ) == 0 ) {
150  return i;
151  }
152  }
153  return -1;
154 }
155 
159 static void teardown ( int pfd )
160 {
161  g_debug ( "Teardown" );
162  // Cleanup font setup.
163  textbox_cleanup ( );
164 
166 
167  // Cleanup view
169  // Cleanup pid file.
170  remove_pid_file ( pfd );
171 }
172 static void run_switcher ( ModeMode mode )
173 {
174  // Otherwise check if requested mode is enabled.
175  for ( unsigned int i = 0; i < num_modi; i++ ) {
176  if ( !mode_init ( modi[i] ) ) {
177  GString *str = g_string_new ( "Failed to initialize the mode: " );
178  g_string_append ( str, modi[i]->name );
179  g_string_append ( str, "\n" );
180 
182  g_string_free ( str, FALSE );
183  break;
184  }
185  }
186  // Error dialog must have been created.
187  if ( rofi_view_get_active () != NULL ) {
188  return;
189  }
190  curr_switcher = mode;
192  if ( state ) {
193  rofi_view_set_active ( state );
194  }
195  if ( rofi_view_get_active () == NULL ) {
196  g_main_loop_quit ( main_loop );
197  }
198 }
200 {
201  Mode *sw = state->sw;
202  rofi_view_set_active ( NULL );
203  if ( sw != NULL ) {
204  unsigned int selected_line = rofi_view_get_selected_line ( state );;
205  MenuReturn mretv = rofi_view_get_return_value ( state );
206  char *input = g_strdup ( rofi_view_get_user_input ( state ) );
207  ModeMode retv = mode_result ( sw, mretv, &input, selected_line );
208  g_free ( input );
209 
210  ModeMode mode = curr_switcher;
211  // Find next enabled
212  if ( retv == NEXT_DIALOG ) {
213  mode = ( mode + 1 ) % num_modi;
214  }
215  else if ( retv == PREVIOUS_DIALOG ) {
216  if ( mode == 0 ) {
217  mode = num_modi - 1;
218  }
219  else {
220  mode = ( mode - 1 ) % num_modi;
221  }
222  }
223  else if ( retv == RELOAD_DIALOG ) {
224  // do nothing.
225  }
226  else if ( retv == RESET_DIALOG ) {
227  rofi_view_clear_input ( state );
228  }
229  else if ( retv < MODE_EXIT ) {
230  mode = ( retv ) % num_modi;
231  }
232  else {
233  mode = retv;
234  }
235  if ( mode != MODE_EXIT ) {
239  rofi_view_switch_mode ( state, modi[mode] );
240  rofi_view_set_active ( state );
241  curr_switcher = mode;
242  return;
243  }
244  }
245  rofi_view_free ( state );
246 }
247 
251 static void print_list_of_modi ( int is_term )
252 {
253  for ( unsigned int i = 0; i < num_available_modi; i++ ) {
254  gboolean active = FALSE;
255  for ( unsigned int j = 0; j < num_modi; j++ ) {
256  if ( modi[j] == available_modi[i] ) {
257  active = TRUE;
258  break;
259  }
260  }
261  printf ( " * %s%s%s%s\n",
262  active ? "+" : "",
263  is_term ? ( active ? color_green : color_red ) : "",
264  available_modi[i]->name,
265  is_term ? color_reset : ""
266  );
267  }
268 }
269 static void print_main_application_options ( int is_term )
270 {
271  print_help_msg ( "-no-config", "", "Do not load configuration, use default values.", NULL, is_term );
272  print_help_msg ( "-v,-version", "", "Print the version number and exit.", NULL, is_term );
273  print_help_msg ( "-dmenu", "", "Start in dmenu mode.", NULL, is_term );
274  print_help_msg ( "-display", "[string]", "X server to contact.", "${DISPLAY}", is_term );
275  print_help_msg ( "-h,-help", "", "This help message.", NULL, is_term );
276  print_help_msg ( "-dump-xresources", "", "Dump the current configuration in Xresources format and exit.", NULL, is_term );
277  print_help_msg ( "-e", "[string]", "Show a dialog displaying the passed message and exit.", NULL, is_term );
278  print_help_msg ( "-markup", "", "Enable pango markup where possible.", NULL, is_term );
279  print_help_msg ( "-normal-window", "", "In dmenu mode, behave as a normal window. (experimental)", NULL, is_term );
280  print_help_msg ( "-show", "[mode]", "Show the mode 'mode' and exit. The mode has to be enabled.", NULL, is_term );
281  print_help_msg ( "-no-lazy-grab", "", "Disable lazy grab that, when fail to grab keyboard, does not block but retry later.", NULL, is_term );
282  print_help_msg ( "-no-plugins", "", "Disable loading of external plugins.", NULL, is_term );
283  print_help_msg ( "-plugin-path", "", "Directory used to search for rofi plugins.", NULL, is_term );
284  print_help_msg ( "-dump-config", "", "Dump the current configuration in rasi format and exit.", NULL, is_term );
285  print_help_msg ( "-dump-theme", "", "Dump the current theme in rasi format and exit.", NULL, is_term );
286 }
287 static void help ( G_GNUC_UNUSED int argc, char **argv )
288 {
289  int is_term = isatty ( fileno ( stdout ) );
290  printf ( "%s usage:\n", argv[0] );
291  printf ( "\t%s [-options ...]\n\n", argv[0] );
292  printf ( "Command line only options:\n" );
293  print_main_application_options ( is_term );
294  printf ( "DMENU command line options:\n" );
296  printf ( "Global options:\n" );
297  print_options ();
298  printf ( "\n" );
300  printf ( "\n" );
301  printf ( "Detected modi:\n" );
302  print_list_of_modi ( is_term );
303  printf ( "\n" );
304  printf ( "Compile time options:\n" );
305 #ifdef WINDOW_MODE
306  printf ( "\t* window %senabled%s\n", is_term ? color_green : "", is_term ? color_reset : "" );
307 #else
308  printf ( "\t* window %sdisabled%s\n", is_term ? color_red : "", is_term ? color_reset : "" );
309 #endif
310 #ifdef ENABLE_DRUN
311  printf ( "\t* drun %senabled%s\n", is_term ? color_green : "", is_term ? color_reset : "" );
312 #else
313  printf ( "\t* drun %sdisabled%s\n", is_term ? color_red : "", is_term ? color_reset : "" );
314 #endif
315 #ifdef ENABLE_GCOV
316  printf ( "\t* gcov %senabled%s\n", is_term ? color_green : "", is_term ? color_reset : "" );
317 #else
318  printf ( "\t* gcov %sdisabled%s\n", is_term ? color_red : "", is_term ? color_reset : "" );
319 #endif
320 #ifdef ENABLE_ASAN
321  printf ( "\t* asan %senabled%s\n", is_term ? color_green : "", is_term ? color_reset : "" );
322 #else
323  printf ( "\t* asan %sdisabled%s\n", is_term ? color_red : "", is_term ? color_reset : "" );
324 #endif
325  printf ( "\n" );
326  printf ( "For more information see: %sman rofi%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
327 #ifdef GIT_VERSION
328  printf ( " Version: %s"GIT_VERSION "%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
329 #else
330  printf ( " Version: %s"VERSION "%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
331 #endif
332  printf ( " Bugreports: %s"PACKAGE_BUGREPORT "%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
333  printf ( " Support: %s"PACKAGE_URL "%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
334  printf ( " %s#rofi @ freenode.net%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
335  if ( find_arg ( "-no-config" ) < 0 ) {
336  if ( config_path_new ) {
337  printf ( " Configuration file: %s%s%s\n", is_term ? color_bold : "", config_path_new, is_term ? color_reset : "" );
338  }
339  else {
340  printf ( " Configuration file: %s%s%s\n", is_term ? color_bold : "", config_path, is_term ? color_reset : "" );
341  }
342  }
343  else {
344  printf ( " Configuration file: %sDisabled%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
345  }
346 }
347 
348 static void help_print_disabled_mode ( const char *mode )
349 {
350  int is_term = isatty ( fileno ( stdout ) );
351  // Only output to terminal
352  if ( is_term ) {
353  fprintf ( stderr, "Mode %s%s%s is not enabled. I have enabled it for now.\n",
354  color_red, mode, color_reset );
355  fprintf ( stderr, "Please consider adding %s%s%s to the list of enabled modi: %smodi: %s%s%s,%s%s.\n",
356  color_red, mode, color_reset,
358  color_red, mode, color_reset
359  );
360  }
361 }
362 static void help_print_mode_not_found ( const char *mode )
363 {
364  GString *str = g_string_new ("");
365  g_string_printf(str, "Mode %s is not found.\nThe following modi are known:\n", mode );
366  for ( unsigned int i = 0; i < num_available_modi; i++ ) {
367  gboolean active = FALSE;
368  for ( unsigned int j = 0; j < num_modi; j++ ) {
369  if ( modi[j] == available_modi[i] ) {
370  active = TRUE;
371  break;
372  }
373  }
374  g_string_append_printf (str, " * %s%s\n",
375  active ? "+" : "",
376  available_modi[i]->name
377  );
378  }
379  rofi_add_error_message ( str );
380 }
381 static void help_print_no_arguments ( void )
382 {
383  int is_term = isatty ( fileno ( stdout ) );
384  // Daemon mode
385  fprintf ( stderr, "Rofi is unsure what to show.\n" );
386  fprintf ( stderr, "Please specify the mode you want to show.\n\n" );
387  fprintf ( stderr, " %srofi%s -show %s{mode}%s\n\n",
388  is_term ? color_bold : "", is_term ? color_reset : "",
389  is_term ? color_green : "", is_term ? color_reset : "" );
390  fprintf ( stderr, "The following modi are enabled:\n" );
391  for ( unsigned int j = 0; j < num_modi; j++ ) {
392  fprintf ( stderr, " * %s%s%s\n",
393  is_term ? color_green : "",
394  modi[j]->name,
395  is_term ? color_reset : "" );
396  }
397  fprintf ( stderr, "\nThe following can be enabled:\n" );
398  for ( unsigned int i = 0; i < num_available_modi; i++ ) {
399  gboolean active = FALSE;
400  for ( unsigned int j = 0; j < num_modi; j++ ) {
401  if ( modi[j] == available_modi[i] ) {
402  active = TRUE;
403  break;
404  }
405  }
406  if ( !active ) {
407  fprintf ( stderr, " * %s%s%s\n",
408  is_term ? color_red : "",
409  available_modi[i]->name,
410  is_term ? color_reset : "" );
411  }
412  }
413  fprintf ( stderr, "\nTo activate a mode, add it to the list of modi in the %smodi%s setting.\n",
414  is_term ? color_green : "", is_term ? color_reset : "" );
415 }
416 
420 static void cleanup ()
421 {
422  for ( unsigned int i = 0; i < num_modi; i++ ) {
423  mode_destroy ( modi[i] );
424  }
426  if ( main_loop != NULL ) {
427  g_main_loop_unref ( main_loop );
428  main_loop = NULL;
429  }
430  // Cleanup
431  display_cleanup ();
432 
433  nk_bindings_free ( bindings );
434 
435  // Cleaning up memory allocated by the Xresources file.
437  g_free ( modi );
438 
439  g_free ( config_path );
440  g_free ( config_path_new );
441 
442  if ( list_of_error_msgs ) {
443  for ( GList *iter = g_list_first ( list_of_error_msgs );
444  iter != NULL; iter = g_list_next ( iter ) ) {
445  g_string_free ( (GString *) iter->data, TRUE );
446  }
447  g_list_free ( list_of_error_msgs );
448  }
449 
450  if ( rofi_theme ) {
452  rofi_theme = NULL;
453  }
454  TIMINGS_STOP ();
457 }
458 
468 Mode * rofi_collect_modi_search ( const char *name )
469 {
470  for ( unsigned int i = 0; i < num_available_modi; i++ ) {
471  if ( g_strcmp0 ( name, available_modi[i]->name ) == 0 ) {
472  return available_modi[i];
473  }
474  }
475  return NULL;
476 }
482 static gboolean rofi_collect_modi_add ( Mode *mode )
483 {
484  Mode *m = rofi_collect_modi_search ( mode->name );
485  if ( m == NULL ) {
486  available_modi = g_realloc ( available_modi, sizeof ( Mode * ) * ( num_available_modi + 1 ) );
487  // Set mode.
490  return TRUE;
491  }
492  return FALSE;
493 }
494 
495 static void rofi_collect_modi_dir ( const char *base_dir )
496 {
497  GDir *dir = g_dir_open ( base_dir, 0, NULL );
498  if ( dir ) {
499  const char *dn = NULL;
500  while ( ( dn = g_dir_read_name ( dir ) ) ) {
501  if ( !g_str_has_suffix ( dn, G_MODULE_SUFFIX ) ) {
502  continue;
503  }
504  char *fn = g_build_filename ( base_dir, dn, NULL );
505  GModule *mod = g_module_open ( fn, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL );
506  if ( mod ) {
507  Mode *m = NULL;
508  if ( g_module_symbol ( mod, "mode", (gpointer *) &m ) ) {
509  if ( m->abi_version != ABI_VERSION ) {
510  g_warning ( "ABI version of plugin: '%s' does not match: %08X expecting: %08X", dn, m->abi_version, ABI_VERSION );
511  g_module_close ( mod );
512  }
513  else {
514  m->module = mod;
515  if ( !rofi_collect_modi_add ( m ) ) {
516  g_module_close ( mod );
517  }
518  }
519  }
520  else {
521  g_warning ( "Symbol 'mode' not found in module: %s", dn );
522  g_module_close ( mod );
523  }
524  }
525  else {
526  g_warning ( "Failed to open 'mode' plugin: '%s', error: %s", dn, g_module_error () );
527  }
528  g_free ( fn );
529  }
530  g_dir_close ( dir );
531  }
532 }
533 
537 static void rofi_collect_modi ( void )
538 {
539 #ifdef WINDOW_MODE
540  rofi_collect_modi_add ( &window_mode );
541  rofi_collect_modi_add ( &window_mode_cd );
542 #endif
545 #ifdef ENABLE_DRUN
546  rofi_collect_modi_add ( &drun_mode );
547 #endif
550 
551  if ( find_arg ( "-no-plugins" ) < 0 ) {
552  find_arg_str ( "-plugin-path", &( config.plugin_path ) );
553  g_debug ( "Parse plugin path: %s", config.plugin_path );
555  }
556 }
557 
561 static void rofi_collect_modi_setup ( void )
562 {
563  for ( unsigned int i = 0; i < num_available_modi; i++ ) {
565  }
566 }
567 static void rofi_collect_modi_destroy ( void )
568 {
569  for ( unsigned int i = 0; i < num_available_modi; i++ ) {
570  if ( available_modi[i]->module ) {
571  GModule *mod = available_modi[i]->module;
572  available_modi[i] = NULL;
573  g_module_close ( mod );
574  }
575  if ( available_modi[i] ) {
576  mode_free ( &( available_modi[i] ) );
577  }
578  }
579  g_free ( available_modi );
580  available_modi = NULL;
581  num_available_modi = 0;
582 }
583 
591 static int add_mode ( const char * token )
592 {
593  unsigned int index = num_modi;
594  // Resize and add entry.
595  modi = (Mode * *) g_realloc ( modi, sizeof ( Mode* ) * ( num_modi + 1 ) );
596 
597  Mode *mode = rofi_collect_modi_search ( token );
598  if ( mode ) {
599  modi[num_modi] = mode;
600  num_modi++;
601  }
602  else if ( script_switcher_is_valid ( token ) ) {
603  // If not build in, use custom modi.
604  Mode *sw = script_switcher_parse_setup ( token );
605  if ( sw != NULL ) {
606  // Add to available list, so combi can find it.
607  rofi_collect_modi_add ( sw );
608  modi[num_modi] = sw;
609  num_modi++;
610  }
611  }
612  return ( index == num_modi ) ? -1 : (int) index;
613 }
614 static gboolean setup_modi ( void )
615 {
616  const char *const sep = ",#";
617  char *savept = NULL;
618  // Make a copy, as strtok will modify it.
619  char *switcher_str = g_strdup ( config.modi );
620  // Split token on ','. This modifies switcher_str.
621  for ( char *token = strtok_r ( switcher_str, sep, &savept ); token != NULL; token = strtok_r ( NULL, sep, &savept ) ) {
622  if ( add_mode ( token ) == -1 ) {
623  help_print_mode_not_found ( token );
624  }
625  }
626  // Free string that was modified by strtok_r
627  g_free ( switcher_str );
628  return FALSE;
629 }
630 
635 void rofi_quit_main_loop ( void )
636 {
637  g_main_loop_quit ( main_loop );
638 }
639 
640 static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
641 {
642  // Break out of loop.
643  g_main_loop_quit ( main_loop );
644  return G_SOURCE_CONTINUE;
645 }
646 static void show_error_dialog ()
647 {
648  GString *emesg = g_string_new ( "The following errors were detected when starting rofi:\n" );
649  GList *iter = g_list_first ( list_of_error_msgs );
650  int index = 0;
651  for (; iter != NULL && index < 2; iter = g_list_next ( iter ) ) {
652  GString *msg = (GString *) ( iter->data );
653  g_string_append ( emesg, "\n\n" );
654  g_string_append ( emesg, msg->str );
655  index++;
656  }
657  if ( g_list_length ( iter ) > 1 ) {
658  g_string_append_printf ( emesg, "\nThere are <b>%d</b> more errors.", g_list_length ( iter ) - 1 );
659  }
661  g_string_free ( emesg, TRUE );
662  rofi_set_return_code ( EX_DATAERR );
663 
664 }
665 
666 static gboolean startup ( G_GNUC_UNUSED gpointer data )
667 {
668  TICK_N ( "Startup" );
669  // flags to run immediately and exit
670  char *sname = NULL;
671  char *msg = NULL;
672  MenuFlags window_flags = MENU_NORMAL;
673 
674  if ( find_arg ( "-normal-window" ) >= 0 ) {
675  window_flags |= MENU_NORMAL_WINDOW;
676  }
677  TICK_N ( "Grab keyboard" );
678  __create_window ( window_flags );
679  TICK_N ( "Create Window" );
680  // Parse the keybindings.
681  TICK_N ( "Parse ABE" );
682  // Sanity check
684  TICK_N ( "Config sanity check" );
685 
686  if ( list_of_error_msgs != NULL ) {
688  return G_SOURCE_REMOVE;
689  }
690  // Dmenu mode.
691  if ( dmenu_mode == TRUE ) {
692  // force off sidebar mode:
693  config.sidebar_mode = FALSE;
694  int retv = dmenu_switcher_dialog ();
695  if ( retv ) {
696  rofi_set_return_code ( EXIT_SUCCESS );
697  // Directly exit.
698  g_main_loop_quit ( main_loop );
699  }
700  }
701  else if ( find_arg_str ( "-e", &( msg ) ) ) {
702  int markup = FALSE;
703  if ( find_arg ( "-markup" ) >= 0 ) {
704  markup = TRUE;
705  }
706  if ( !rofi_view_error_dialog ( msg, markup ) ) {
707  g_main_loop_quit ( main_loop );
708  }
709  }
710  else if ( find_arg_str ( "-show", &sname ) == TRUE ) {
711  int index = switcher_get ( sname );
712  if ( index < 0 ) {
713  // Add it to the list
714  index = add_mode ( sname );
715  // Complain
716  if ( index >= 0 ) {
717  help_print_disabled_mode ( sname );
718  }
719  // Run it anyway if found.
720  }
721  if ( index >= 0 ) {
722  run_switcher ( index );
723  }
724  else {
725  help_print_mode_not_found ( sname );
727  return G_SOURCE_REMOVE;
728  }
729  }
730  else if ( find_arg ( "-show" ) >= 0 && num_modi > 0 ) {
731  run_switcher ( 0 );
732  }
733  else{
735 
736  g_main_loop_quit ( main_loop );
737  }
738 
739  return G_SOURCE_REMOVE;
740 }
741 
742 static gboolean record ( G_GNUC_UNUSED void *data )
743 {
745  return G_SOURCE_CONTINUE;
746 }
755 int main ( int argc, char *argv[] )
756 {
757  TIMINGS_START ();
758 
759  cmd_set_arguments ( argc, argv );
760 
761  // Version
762  if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) {
763 #ifdef GIT_VERSION
764  g_print ( "Version: "GIT_VERSION "\n" );
765 #else
766  g_print ( "Version: "VERSION "\n" );
767 #endif
768  return EXIT_SUCCESS;
769  }
770 
771  // Detect if we are in dmenu mode.
772  // This has two possible causes.
773  // 1 the user specifies it on the command-line.
774  if ( find_arg ( "-dmenu" ) >= 0 ) {
775  dmenu_mode = TRUE;
776  }
777  // 2 the binary that executed is called dmenu (e.g. symlink to rofi)
778  else{
779  // Get the base name of the executable called.
780  char *base_name = g_path_get_basename ( argv[0] );
781  const char * const dmenu_str = "dmenu";
782  dmenu_mode = ( strcmp ( base_name, dmenu_str ) == 0 );
783  // Free the basename for dmenu detection.
784  g_free ( base_name );
785  }
786  TICK ();
787 
788  // Create pid file path.
789  const char *path = g_get_user_runtime_dir ();
790  if ( path ) {
791  if ( g_mkdir_with_parents ( path, 0700 ) < 0 ) {
792  g_warning ( "Failed to create user runtime directory: %s with error: %s", path, g_strerror ( errno ) );
793  pidfile = g_build_filename ( g_get_home_dir (), ".rofi.pid", NULL );
794  }
795  else {
796  pidfile = g_build_filename ( path, "rofi.pid", NULL );
797  }
798  }
799  config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" );
800 
801  if ( find_arg ( "-config" ) < 0 ) {
802  const char *cpath = g_get_user_config_dir ();
803  if ( cpath ) {
804  config_path = g_build_filename ( cpath, "rofi", "config", NULL );
805  config_path_new = g_strconcat ( config_path, ".rasi", NULL );
806  }
807  }
808  else {
809  char *c = NULL;
810  find_arg_str ( "-config", &c );
811  if ( g_str_has_suffix ( c, ".rasi" ) ) {
813  }
814  else {
816  }
817  }
818 
819  TICK ();
820  if ( setlocale ( LC_ALL, "" ) == NULL ) {
821  g_warning ( "Failed to set locale." );
822  cleanup ();
823  return EXIT_FAILURE;
824  }
825 
826  TICK_N ( "Setup Locale" );
828  TICK_N ( "Collect MODI" );
830  TICK_N ( "Setup MODI" );
831 
832  main_loop = g_main_loop_new ( NULL, FALSE );
833 
834  TICK_N ( "Setup mainloop" );
835 
836  bindings = nk_bindings_new ( 0 );
837  TICK_N ( "NK Bindings" );
838 
839  if ( !display_setup ( main_loop, bindings ) ) {
840  g_warning ( "Connection has error" );
841  cleanup ();
842  return EXIT_FAILURE;
843  }
844  TICK_N ( "Setup Display" );
845 
846  // Setup keybinding
847  setup_abe ();
848  TICK_N ( "Setup abe" );
849 
850  if ( find_arg ( "-no-config" ) < 0 ) {
851  // Load distro default settings
852  gchar *etc = g_build_filename ( SYSCONFDIR, "rofi.conf", NULL );
853  if ( g_file_test ( etc, G_FILE_TEST_IS_REGULAR ) ) {
855  }
856  g_free ( etc );
857  // Load in config from X resources.
859  if ( config_path_new && g_file_test ( config_path_new, G_FILE_TEST_IS_REGULAR ) ) {
862  rofi_theme = NULL;
863  }
864  }
865  else {
866  g_free ( config_path_new );
867  config_path_new = NULL;
869  }
870  }
871  find_arg_str ( "-theme", &( config.theme ) );
872  if ( config.theme ) {
873  TICK_N ( "Parse theme" );
874  if ( rofi_theme_parse_file ( config.theme ) ) {
875  // TODO: instantiate fallback theme.?
877  rofi_theme = NULL;
878  }
879  TICK_N ( "Parsed theme" );
880  }
881  // Parse command line for settings, independent of other -no-config.
883  TICK_N ( "Load cmd config " );
884 
886 
887  // Get the path to the cache dir.
888  cache_dir = g_get_user_cache_dir ();
889 
890  if ( config.cache_dir != NULL ) {
892  }
893 
894  if ( g_mkdir_with_parents ( cache_dir, 0700 ) < 0 ) {
895  g_warning ( "Failed to create cache directory: %s", g_strerror ( errno ) );
896  return EXIT_FAILURE;
897  }
898 
900  char *windowid = NULL;
901  if ( !dmenu_mode ) {
902  // setup_modi
903  if ( setup_modi () ) {
904  cleanup ();
905  return EXIT_FAILURE;
906  }
907  TICK_N ( "Setup Modi" );
908  }
909  else {
910  // Hack for dmenu compatibility.
911  if ( find_arg_str ( "-w", &windowid ) == TRUE ) {
912  config.monitor = g_strdup_printf ( "wid:%s", windowid );
913  windowid = config.monitor;
914  }
915  }
916  if ( rofi_theme_is_empty ( ) ) {
917  GBytes *theme_data = g_resource_lookup_data (
918  resources_get_resource (),
919  "/org/qtools/rofi/default_theme.rasi",
920  G_RESOURCE_LOOKUP_FLAGS_NONE,
921  NULL );
922  if ( theme_data ) {
923  const char *theme = g_bytes_get_data ( theme_data, NULL );
924  if ( rofi_theme_parse_string ( (const char *) theme ) ) {
925  g_warning ( "Failed to parse default theme. Giving up.." );
926  if ( list_of_error_msgs ) {
927  for ( GList *iter = g_list_first ( list_of_error_msgs );
928  iter != NULL; iter = g_list_next ( iter ) ) {
929  g_warning ( "Error: %s%s%s",
930  color_bold, ( (GString *) iter->data )->str, color_reset );
931  }
932  }
933  rofi_theme = NULL;
934  cleanup ();
935  return EXIT_FAILURE;
936  }
937  g_bytes_unref ( theme_data );
938  }
939  rofi_theme_convert_old ();
940  }
941 
945  const char ** theme_str = find_arg_strv ( "-theme-str" );
946  if ( theme_str ) {
947  for ( int index = 0; theme_str && theme_str[index]; index++ ) {
948  if ( rofi_theme_parse_string ( theme_str[index] ) ) {
950  rofi_theme = NULL;
951  }
952  }
953  g_free ( theme_str );
954  }
955 
956  if ( find_arg ( "-dump-theme" ) >= 0 ) {
958  cleanup ();
959  return EXIT_SUCCESS;
960  }
961  if ( find_arg ( "-dump-config" ) >= 0 ) {
963  cleanup ();
964  return EXIT_SUCCESS;
965  }
966  // Dump.
967  // catch help request
968  if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) {
969  help ( argc, argv );
970  cleanup ();
971  return EXIT_SUCCESS;
972  }
973  if ( find_arg ( "-dump-xresources" ) >= 0 ) {
975  cleanup ();
976  return EXIT_SUCCESS;
977  }
978 
979  unsigned int interval = 1;
980  if ( find_arg_uint ( "-record-screenshots", &interval ) ) {
981  g_timeout_add ( 1000 / (double) interval, record, NULL );
982  }
983 
986 
987  // Create pid file
988  int pfd = create_pid_file ( pidfile );
989  if ( pfd < 0 ) {
990  cleanup ();
991  return EXIT_FAILURE;
992  }
993  textbox_setup ();
994 
995  if ( !display_late_setup () ) {
996  g_warning ( "Failed to properly finish display setup" );
997  cleanup ();
998  return EXIT_FAILURE;
999  }
1000  TICK_N ( "Setup late Display" );
1001 
1002  // Setup signal handling sources.
1003  // SIGINT
1004  g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL );
1005 
1006  g_idle_add ( startup, NULL );
1007 
1008  // Start mainloop.
1009  g_main_loop_run ( main_loop );
1010  teardown ( pfd );
1011  cleanup ();
1012 
1013  /* dirty hack */
1014  g_free ( windowid );
1015  return return_code;
1016 }
TIMINGS_START
#define TIMINGS_START()
Definition: timings.h:59
RofiViewState::sw
Mode * sw
Definition: view-internal.h:50
RESET_DIALOG
@ RESET_DIALOG
Definition: mode.h:60
ERROR_MSG_MARKUP
#define ERROR_MSG_MARKUP
Definition: rofi.h:110
dmenu_switcher_dialog
int dmenu_switcher_dialog(void)
Definition: dmenu.c:586
Settings::cache_dir
char * cache_dir
Definition: settings.h:186
find_arg_strv
const char ** find_arg_strv(const char *const key)
Definition: helper.c:288
MenuFlags
MenuFlags
Definition: view.h:44
xcb
xcb_stuff * xcb
Definition: xcb.c:87
xrmoptions.h
TIMINGS_STOP
#define TIMINGS_STOP()
Definition: timings.h:72
print_main_application_options
static void print_main_application_options(int is_term)
Definition: rofi.c:269
rofi_collect_modi_add
static gboolean rofi_collect_modi_add(Mode *mode)
Definition: rofi.c:482
parse_keys_abe
gboolean parse_keys_abe(NkBindings *bindings)
Definition: keyb.c:148
list_of_error_msgs
GList * list_of_error_msgs
Definition: rofi.c:87
cache_dir
const char * cache_dir
Definition: rofi.c:84
dialogs.h
num_available_modi
unsigned int num_available_modi
Definition: rofi.c:105
rofi_view_workers_initialize
void rofi_view_workers_initialize(void)
Definition: view.c:1852
rofi_capture_screenshot
void rofi_capture_screenshot(void)
Definition: view.c:177
pidfile
char * pidfile
Definition: rofi.c:82
rofi_mode::name
char * name
Definition: mode-private.h:156
settings.h
main_loop_signal_handler_int
static gboolean main_loop_signal_handler_int(G_GNUC_UNUSED gpointer data)
Definition: rofi.c:640
color_red
#define color_red
Definition: rofi.h:98
rofi_view_clear_input
void rofi_view_clear_input(RofiViewState *state)
Definition: view.c:1906
dmenu_mode
static int dmenu_mode
Definition: rofi.c:118
help
static void help(G_GNUC_UNUSED int argc, char **argv)
Definition: rofi.c:287
rofi_view_get_active
RofiViewState * rofi_view_get_active(void)
Definition: view.c:447
cleanup
static void cleanup()
Definition: rofi.c:420
config_path
G_MODULE_EXPORT char * config_path
Definition: rofi.c:96
Settings::monitor
char * monitor
Definition: settings.h:147
rofi_theme
ThemeWidget * rofi_theme
display_late_setup
gboolean display_late_setup(void)
Definition: xcb.c:1289
main
int main(int argc, char *argv[])
Definition: rofi.c:755
PREVIOUS_DIALOG
@ PREVIOUS_DIALOG
Definition: mode.h:58
mode.h
textbox_setup
void textbox_setup(void)
Definition: textbox.c:833
rofi_view_error_dialog
int rofi_view_error_dialog(const char *msg, int markup)
Definition: view.c:1763
display_cleanup
void display_cleanup(void)
Definition: xcb.c:1334
rofi_get_mode
const Mode * rofi_get_mode(unsigned int index)
Definition: rofi.c:134
config_parse_xresource_dump
void config_parse_xresource_dump(void)
Definition: xrmoptions.c:555
Settings::plugin_path
char * plugin_path
Definition: settings.h:177
print_help_msg
void print_help_msg(const char *option, const char *type, const char *text, const char *def, int isatty)
Definition: xrmoptions.c:754
rofi_view_get_selected_line
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition: view.c:515
mode_init
int mode_init(Mode *mode)
Definition: mode.c:42
config_parse_xresource_options_file
void config_parse_xresource_options_file(const char *filename)
Definition: xrmoptions.c:334
NEXT_DIALOG
@ NEXT_DIALOG
Definition: mode.h:54
MENU_NORMAL
@ MENU_NORMAL
Definition: view.h:46
remove_pid_file
void remove_pid_file(int fd)
Definition: helper.c:519
__create_window
void __create_window(MenuFlags menu_flags)
Definition: view.c:678
find_arg
int find_arg(const char *const key)
Definition: helper.c:267
rofi_view_free
void rofi_view_free(RofiViewState *state)
Definition: view.c:491
MenuReturn
MenuReturn
Definition: mode.h:67
rofi_icon_fetcher_destroy
void rofi_icon_fetcher_destroy(void)
Definition: rofi-icon-fetcher.c:119
rofi_theme_parse_file
gboolean rofi_theme_parse_file(const char *file)
timings.h
Settings::theme
char * theme
Definition: settings.h:175
cmd_set_arguments
void cmd_set_arguments(int argc, char **argv)
Definition: helper.c:76
rofi_view_get_return_value
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition: view.c:510
Settings::sidebar_mode
unsigned int sidebar_mode
Definition: settings.h:132
theme.h
mode-private.h
rofi_quit_main_loop
void rofi_quit_main_loop(void)
Definition: rofi.c:635
rofi_view_set_active
void rofi_view_set_active(RofiViewState *state)
Definition: view.c:452
mode_get_name
const char * mode_get_name(const Mode *mode)
Definition: mode.c:112
ABI_VERSION
#define ABI_VERSION
Definition: mode-private.h:34
script_switcher_parse_setup
Mode * script_switcher_parse_setup(const char *str)
Definition: script.c:339
rofi_collect_modi_destroy
static void rofi_collect_modi_destroy(void)
Definition: rofi.c:567
mode_free
void mode_free(Mode **mode)
Definition: mode.c:118
rofi_theme_print
void rofi_theme_print(ThemeWidget *widget)
Definition: theme.c:352
MODE_EXIT
@ MODE_EXIT
Definition: mode.h:52
help_print_no_arguments
static void help_print_no_arguments(void)
Definition: rofi.c:381
help_keys_mode
Mode help_keys_mode
Definition: help-keys.c:122
find_arg_uint
int find_arg_uint(const char *const key, unsigned int *val)
Definition: helper.c:319
modi
Mode ** modi
Definition: rofi.c:100
rofi_theme_free
void rofi_theme_free(ThemeWidget *widget)
Definition: theme.c:134
TICK_N
#define TICK_N(a)
Definition: timings.h:68
color_bold
#define color_bold
Definition: rofi.h:92
display_dump_monitor_layout
void display_dump_monitor_layout(void)
Definition: xcb.c:426
view-internal.h
mode_destroy
void mode_destroy(Mode *mode)
Definition: mode.c:49
rofi_collect_modi_search
Mode * rofi_collect_modi_search(const char *name)
Definition: rofi.c:468
print_list_of_modi
static void print_list_of_modi(int is_term)
Definition: rofi.c:251
rofi_theme_parse_string
gboolean rofi_theme_parse_string(const char *string)
teardown
static void teardown(int pfd)
Definition: rofi.c:159
record
static gboolean record(G_GNUC_UNUSED void *data)
Definition: rofi.c:742
rofi_expand_path
char * rofi_expand_path(const char *input)
Definition: helper.c:658
rofi_collect_modi_dir
static void rofi_collect_modi_dir(const char *base_dir)
Definition: rofi.c:495
show_error_dialog
static void show_error_dialog()
Definition: rofi.c:646
config_sanity_check
int config_sanity_check(void)
Definition: helper.c:546
print_dmenu_options
void print_dmenu_options(void)
Definition: dmenu.c:677
rofi_mode
Definition: mode-private.h:152
config_xresource_free
void config_xresource_free(void)
Definition: xrmoptions.c:497
rofi.h
rofi_theme_is_empty
gboolean rofi_theme_is_empty(void)
Definition: theme.c:799
ssh_mode
Mode ssh_mode
Definition: ssh.c:643
config_parse_cmd_options
void config_parse_cmd_options(void)
Definition: xrmoptions.c:402
config_parser_add_option
void config_parser_add_option(XrmOptionType type, const char *key, void **value, const char *comment)
Definition: xrmoptions.c:230
create_pid_file
int create_pid_file(const char *pidfile)
Definition: helper.c:480
textbox_cleanup
void textbox_cleanup(void)
Definition: textbox.c:851
combi_mode
Mode combi_mode
Definition: combi.c:300
Settings::modi
char * modi
Definition: settings.h:59
config_parse_dump_config_rasi_format
void config_parse_dump_config_rasi_format(gboolean changes)
Dump configuration in rasi format.
Definition: xrmoptions.c:617
rofi_add_error_message
void rofi_add_error_message(GString *str)
Definition: rofi.c:90
rofi_get_num_enabled_modi
unsigned int rofi_get_num_enabled_modi(void)
Definition: rofi.c:129
find_arg_str
int find_arg_str(const char *const key, char **val)
Definition: helper.c:277
xrm_String
@ xrm_String
Definition: xrmoptions.h:72
display_setup
gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings)
Definition: xcb.c:1094
display.h
setup_modi
static gboolean setup_modi(void)
Definition: rofi.c:614
available_modi
Mode ** available_modi
Definition: rofi.c:103
MENU_NORMAL_WINDOW
@ MENU_NORMAL_WINDOW
Definition: view.h:50
bindings
NkBindings * bindings
Definition: rofi.c:112
num_modi
unsigned int num_modi
Definition: rofi.c:107
display_early_cleanup
void display_early_cleanup(void)
Definition: xcb.c:1327
script_switcher_is_valid
gboolean script_switcher_is_valid(const char *token)
Definition: script.c:376
config_parse_xresource_options
void config_parse_xresource_options(xcb_stuff *xcb)
Definition: xrmoptions.c:325
run_mode
Mode run_mode
Definition: run.c:412
view.h
run_switcher
static void run_switcher(ModeMode mode)
Definition: rofi.c:172
rofi_set_return_code
void rofi_set_return_code(int code)
Definition: rofi.c:124
Settings::filter
char * filter
Definition: settings.h:152
textbox.h
rofi-icon-fetcher.h
help_print_disabled_mode
static void help_print_disabled_mode(const char *mode)
Definition: rofi.c:348
ModeMode
ModeMode
Definition: mode.h:50
TICK
#define TICK()
Definition: timings.h:63
rofi_mode::module
GModule * module
Definition: mode-private.h:197
rofi_view_create
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition: view.c:1693
main_loop
GMainLoop * main_loop
Definition: rofi.c:115
RELOAD_DIALOG
@ RELOAD_DIALOG
Definition: mode.h:56
curr_switcher
unsigned int curr_switcher
Definition: rofi.c:109
add_mode
static int add_mode(const char *token)
Definition: rofi.c:591
rofi_view_get_user_input
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition: view.c:535
switcher_get
static int switcher_get(const char *name)
Definition: rofi.c:146
color_reset
#define color_reset
Definition: rofi.h:90
rofi_view_workers_finalize
void rofi_view_workers_finalize(void)
Definition: view.c:1879
rofi_view_cleanup
void rofi_view_cleanup()
Definition: view.c:1814
mode_result
ModeMode mode_result(Mode *mode, int menu_retv, char **input, unsigned int selected_line)
Definition: mode.c:97
helper.h
startup
static gboolean startup(G_GNUC_UNUSED gpointer data)
Definition: rofi.c:666
setup_abe
void setup_abe(void)
Definition: keyb.c:134
rofi_icon_fetcher_init
void rofi_icon_fetcher_init(void)
Definition: rofi-icon-fetcher.c:99
RofiViewState
Definition: view-internal.h:48
rofi_collect_modi_setup
static void rofi_collect_modi_setup(void)
Definition: rofi.c:561
config
Settings config
print_options
void print_options(void)
Definition: xrmoptions.c:736
help_print_mode_not_found
static void help_print_mode_not_found(const char *mode)
Definition: rofi.c:362
color_green
#define color_green
Definition: rofi.h:96
mode_set_config
void mode_set_config(Mode *mode)
Definition: mode.c:151
rofi_collect_modi
static void rofi_collect_modi(void)
Definition: rofi.c:537
return_code
int return_code
Definition: rofi.c:120
config_path_new
G_MODULE_EXPORT char * config_path_new
Definition: rofi.c:98
rofi_view_switch_mode
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Definition: view.c:1914
process_result
void process_result(RofiViewState *state)
Definition: rofi.c:199