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