rofi  1.7.0
filebrowser.c
Go to the documentation of this file.
1 
26 #include <errno.h>
27 #include <gio/gio.h>
28 #include <gmodule.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 #include <dirent.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 
38 #include "dialogs/filebrowser.h"
39 #include "helper.h"
40 #include "history.h"
41 #include "mode-private.h"
42 #include "mode.h"
43 #include "rofi.h"
44 #include "theme.h"
45 
46 #include <stdint.h>
47 
48 #include "rofi-icon-fetcher.h"
49 
50 #define FILEBROWSER_CACHE_FILE "rofi3.filebrowsercache"
51 
55 enum FBFileType {
56  UP,
60 };
61 
68 };
69 
77 };
78 
80 const char *icon_name[NUM_FILE_TYPES] = {"go-up", "folder", "gtk-file"};
81 typedef struct {
82  char *name;
83  char *path;
84  enum FBFileType type;
85  uint32_t icon_fetch_uid;
86  gboolean link;
87  time_t time;
88 } FBFile;
89 
90 typedef struct {
91  GFile *current_dir;
93  unsigned int array_length;
95 
99 struct {
107  .sorting_method = FB_SORT_NAME,
108  .sorting_time = FB_MTIME,
109  .directories_first = TRUE,
110 };
111 
113  for (unsigned int i = 0; i < pd->array_length; i++) {
114  FBFile *fb = &(pd->array[i]);
115  g_free(fb->name);
116  g_free(fb->path);
117  }
118  g_free(pd->array);
119  pd->array = NULL;
120  pd->array_length = 0;
121 }
122 #include <dirent.h>
123 #include <sys/types.h>
124 
125 static gint compare_name(gconstpointer a, gconstpointer b,
126  G_GNUC_UNUSED gpointer data) {
127  FBFile *fa = (FBFile *)a;
128  FBFile *fb = (FBFile *)b;
129 
130  if (file_browser_config.directories_first && fa->type != fb->type) {
131  return fa->type - fb->type;
132  }
133 
134  return g_strcmp0(fa->name, fb->name);
135 }
136 
137 static gint compare_time(gconstpointer a, gconstpointer b,
138  G_GNUC_UNUSED gpointer data) {
139  FBFile *fa = (FBFile *)a;
140  FBFile *fb = (FBFile *)b;
141 
142  if (file_browser_config.directories_first && fa->type != fb->type) {
143  return fa->type - fb->type;
144  }
145 
146  if (fa->time < 0) {
147  return -1;
148  }
149 
150  if (fb->time < 0) {
151  return 1;
152  }
153 
154  return fb->time - fa->time;
155 }
156 
157 static gint compare(gconstpointer a, gconstpointer b, gpointer data) {
158  GCompareDataFunc comparator = NULL;
159 
160  switch (file_browser_config.sorting_method) {
161  case FB_SORT_NAME:
162  comparator = compare_name;
163  break;
164  case FB_SORT_TIME:
165  comparator = compare_time;
166  break;
167  default:
168  comparator = compare_name;
169  break;
170  }
171 
172  return comparator(a, b, data);
173 }
174 
175 static time_t get_time(const struct stat *statbuf) {
176  switch (file_browser_config.sorting_time) {
177  case FB_MTIME:
178  return statbuf->st_mtim.tv_sec;
179  case FB_ATIME:
180  return statbuf->st_atim.tv_sec;
181  case FB_CTIME:
182  return statbuf->st_ctim.tv_sec;
183  default:
184  return 0;
185  }
186 }
187 
188 static void set_time(FBFile *file) {
189  gchar *path = g_filename_from_utf8(file->path, -1, NULL, NULL, NULL);
190 
191  struct stat statbuf;
192 
193  if (stat(path, &statbuf) == 0) {
194  file->time = get_time(&statbuf);
195  } else {
196  g_warning("Failed to stat file: %s, %s", path, strerror(errno));
197  }
198 
199  g_free(path);
200 }
201 
202 static void get_file_browser(Mode *sw) {
209  char *cdir = g_file_get_path(pd->current_dir);
210  DIR *dir = opendir(cdir);
211  if (dir) {
212  struct dirent *rd = NULL;
213  while ((rd = readdir(dir)) != NULL) {
214  if (g_strcmp0(rd->d_name, "..") == 0) {
215  pd->array =
216  g_realloc(pd->array, (pd->array_length + 1) * sizeof(FBFile));
217  // Rofi expects utf-8, so lets convert the filename.
218  pd->array[pd->array_length].name = g_strdup("..");
219  pd->array[pd->array_length].path = NULL;
220  pd->array[pd->array_length].type = UP;
221  pd->array[pd->array_length].icon_fetch_uid = 0;
222  pd->array[pd->array_length].link = FALSE;
223  pd->array[pd->array_length].time = -1;
224  pd->array_length++;
225  continue;
226  }
227  if (rd->d_name[0] == '.') {
228  continue;
229  }
230 
231  switch (rd->d_type) {
232  case DT_BLK:
233  case DT_CHR:
234  case DT_FIFO:
235  case DT_UNKNOWN:
236  case DT_SOCK:
237  default:
238  break;
239  case DT_REG:
240  case DT_DIR:
241  pd->array =
242  g_realloc(pd->array, (pd->array_length + 1) * sizeof(FBFile));
243  // Rofi expects utf-8, so lets convert the filename.
244  pd->array[pd->array_length].name =
245  g_filename_to_utf8(rd->d_name, -1, NULL, NULL, NULL);
246  pd->array[pd->array_length].path =
247  g_build_filename(cdir, rd->d_name, NULL);
248  pd->array[pd->array_length].type =
249  (rd->d_type == DT_DIR) ? DIRECTORY : RFILE;
250  pd->array[pd->array_length].icon_fetch_uid = 0;
251  pd->array[pd->array_length].link = FALSE;
252 
253  if (file_browser_config.sorting_method == FB_SORT_TIME) {
254  set_time(&pd->array[pd->array_length]);
255  }
256 
257  pd->array_length++;
258  break;
259  case DT_LNK:
260  pd->array =
261  g_realloc(pd->array, (pd->array_length + 1) * sizeof(FBFile));
262  // Rofi expects utf-8, so lets convert the filename.
263  pd->array[pd->array_length].name =
264  g_filename_to_utf8(rd->d_name, -1, NULL, NULL, NULL);
265  pd->array[pd->array_length].path =
266  g_build_filename(cdir, rd->d_name, NULL);
267  pd->array[pd->array_length].icon_fetch_uid = 0;
268  pd->array[pd->array_length].link = TRUE;
269  // Default to file.
270  pd->array[pd->array_length].type = RFILE;
271  {
272  // If we have link, use a stat to fine out what it is, if we fail, we
273  // mark it as file.
274  // TODO have a 'broken link' mode?
275  // Convert full path to right encoding.
276  char *file = g_filename_from_utf8(pd->array[pd->array_length].path,
277  -1, NULL, NULL, NULL);
278  if (file) {
279  struct stat statbuf;
280  if (stat(file, &statbuf) == 0) {
281  if (S_ISDIR(statbuf.st_mode)) {
282  pd->array[pd->array_length].type = DIRECTORY;
283  } else if (S_ISREG(statbuf.st_mode)) {
284  pd->array[pd->array_length].type = RFILE;
285  }
286 
287  if (file_browser_config.sorting_method == FB_SORT_TIME) {
288  pd->array[pd->array_length].time = get_time(&statbuf);
289  }
290  } else {
291  g_warning("Failed to stat file: %s, %s", file, strerror(errno));
292  }
293 
294  g_free(file);
295  }
296  }
297  pd->array_length++;
298  break;
299  }
300  }
301  closedir(dir);
302  }
303  g_qsort_with_data(pd->array, pd->array_length, sizeof(FBFile), compare, NULL);
304 }
305 
307  char *msg = NULL;
308  gboolean found_error = FALSE;
309 
310  ThemeWidget *wid = rofi_config_find_widget(sw->name, NULL, TRUE);
311 
312  Property *p = rofi_theme_find_property(wid, P_STRING, "sorting-method", TRUE);
313  if (p != NULL && p->type == P_STRING) {
314  if (g_strcmp0(p->value.s, "name") == 0) {
315  file_browser_config.sorting_method = FB_SORT_NAME;
316  } else if (g_strcmp0(p->value.s, "mtime") == 0) {
317  file_browser_config.sorting_method = FB_SORT_TIME;
318  file_browser_config.sorting_time = FB_MTIME;
319  } else if (g_strcmp0(p->value.s, "atime") == 0) {
320  file_browser_config.sorting_method = FB_SORT_TIME;
321  file_browser_config.sorting_time = FB_ATIME;
322  } else if (g_strcmp0(p->value.s, "ctime") == 0) {
323  file_browser_config.sorting_method = FB_SORT_TIME;
324  file_browser_config.sorting_time = FB_CTIME;
325  } else {
326  found_error = TRUE;
327 
328  msg = g_strdup_printf("\"%s\" is not a valid filebrowser sorting method",
329  p->value.s);
330  }
331  }
332 
333  p = rofi_theme_find_property(wid, P_BOOLEAN, "directories-first", TRUE);
334  if (p != NULL && p->type == P_BOOLEAN) {
335  file_browser_config.directories_first = p->value.b;
336  }
337 
338  if (found_error) {
339  rofi_view_error_dialog(msg, FALSE);
340 
341  g_free(msg);
342  }
343 }
344 
348 
349  ThemeWidget *wid = rofi_config_find_widget(sw->name, NULL, TRUE);
350 
351  Property *p = rofi_theme_find_property(wid, P_STRING, "directory", TRUE);
352 
353  gboolean config_has_valid_dir = p != NULL && p->type == P_STRING &&
354  g_file_test(p->value.s, G_FILE_TEST_IS_DIR);
355 
356  if (config_has_valid_dir) {
357  pd->current_dir = g_file_new_for_path(p->value.s);
358  } else {
359  char *current_dir = NULL;
360  char *cache_file =
361  g_build_filename(cache_dir, FILEBROWSER_CACHE_FILE, NULL);
362 
363  if (g_file_get_contents(cache_file, &current_dir, NULL, NULL)) {
364  if (g_file_test(current_dir, G_FILE_TEST_IS_DIR)) {
365  pd->current_dir = g_file_new_for_path(current_dir);
366  }
367 
368  g_free(current_dir);
369  }
370 
371  // Store it based on the unique identifiers (desktop_id).
372  g_free(cache_file);
373  }
374 
375  if (pd->current_dir == NULL) {
376  pd->current_dir = g_file_new_for_path(g_get_home_dir());
377  }
378 }
379 
380 static int file_browser_mode_init(Mode *sw) {
384  if (mode_get_private_data(sw) == NULL) {
385  FileBrowserModePrivateData *pd = g_malloc0(sizeof(*pd));
386  mode_set_private_data(sw, (void *)pd);
387 
390 
391  // Load content.
392  get_file_browser(sw);
393  }
394  return TRUE;
395 }
396 static unsigned int file_browser_mode_get_num_entries(const Mode *sw) {
397  const FileBrowserModePrivateData *pd =
399  return pd->array_length;
400 }
401 
402 static ModeMode file_browser_mode_result(Mode *sw, int mretv, char **input,
403  unsigned int selected_line) {
404  ModeMode retv = MODE_EXIT;
407  if (mretv & MENU_NEXT) {
408  retv = NEXT_DIALOG;
409  } else if (mretv & MENU_PREVIOUS) {
410  retv = PREVIOUS_DIALOG;
411  } else if (mretv & MENU_QUICK_SWITCH) {
412  retv = (mretv & MENU_LOWER_MASK);
413  } else if (mretv & MENU_CUSTOM_COMMAND) {
414  retv = (mretv & MENU_LOWER_MASK);
415  } else if ((mretv & MENU_OK)) {
416  if (selected_line < pd->array_length) {
417  if (pd->array[selected_line].type == UP) {
418  GFile *new = g_file_get_parent(pd->current_dir);
419  if (new) {
420  g_object_unref(pd->current_dir);
421  pd->current_dir = new;
422  free_list(pd);
423  get_file_browser(sw);
424  return RESET_DIALOG;
425  }
426  } else if (pd->array[selected_line].type == DIRECTORY) {
427  char *path = g_build_filename(cache_dir, FILEBROWSER_CACHE_FILE, NULL);
428  g_file_set_contents(path, pd->array[selected_line].path, -1, NULL);
429  g_free(path);
430  GFile *new = g_file_new_for_path(pd->array[selected_line].path);
431  g_object_unref(pd->current_dir);
432  pd->current_dir = new;
433  free_list(pd);
434  get_file_browser(sw);
435  return RESET_DIALOG;
436  } else if (pd->array[selected_line].type == RFILE) {
437  char *d = g_filename_from_utf8(pd->array[selected_line].path, -1, NULL,
438  NULL, NULL);
439  char *d_esc = g_shell_quote(d);
440  char *cmd = g_strdup_printf("xdg-open %s", d_esc);
441  g_free(d_esc);
442  g_free(d);
443  char *cdir = g_file_get_path(pd->current_dir);
444  helper_execute_command(cdir, cmd, FALSE, NULL);
445  g_free(cdir);
446  g_free(cmd);
447  return MODE_EXIT;
448  }
449  }
450  retv = RELOAD_DIALOG;
451  } else if ((mretv & MENU_CUSTOM_INPUT) && *input) {
452  char *p = rofi_expand_path(*input);
453  char *dir = g_filename_from_utf8(p, -1, NULL, NULL, NULL);
454  g_free(p);
455  if (g_file_test(dir, G_FILE_TEST_EXISTS)) {
456  if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
457  g_object_unref(pd->current_dir);
458  pd->current_dir = g_file_new_for_path(dir);
459  g_free(dir);
460  free_list(pd);
461  get_file_browser(sw);
462  return RESET_DIALOG;
463  }
464  }
465  g_free(dir);
466  retv = RELOAD_DIALOG;
467  } else if ((mretv & MENU_ENTRY_DELETE) == MENU_ENTRY_DELETE) {
468  retv = RELOAD_DIALOG;
469  }
470  return retv;
471 }
472 
473 static void file_browser_mode_destroy(Mode *sw) {
476  if (pd != NULL) {
477  g_object_unref(pd->current_dir);
478  free_list(pd);
479  g_free(pd);
480  mode_set_private_data(sw, NULL);
481  }
482 }
483 
484 static char *_get_display_value(const Mode *sw, unsigned int selected_line,
485  G_GNUC_UNUSED int *state,
486  G_GNUC_UNUSED GList **attr_list,
487  int get_entry) {
490 
491  // Only return the string if requested, otherwise only set state.
492  if (!get_entry) {
493  return NULL;
494  }
495  if (pd->array[selected_line].type == UP) {
496  return g_strdup(" ..");
497  }
498  if (pd->array[selected_line].link) {
499  return g_strconcat("@", pd->array[selected_line].name, NULL);
500  }
501  return g_strdup(pd->array[selected_line].name);
502 }
503 
513 static int file_browser_token_match(const Mode *sw, rofi_int_matcher **tokens,
514  unsigned int index) {
517 
518  // Call default matching function.
519  return helper_token_match(tokens, pd->array[index].name);
520 }
521 
522 static cairo_surface_t *_get_icon(const Mode *sw, unsigned int selected_line,
523  int height) {
526  g_return_val_if_fail(pd->array != NULL, NULL);
527  FBFile *dr = &(pd->array[selected_line]);
528  if (dr->icon_fetch_uid > 0) {
530  }
532  dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->path, height);
533  } else {
535  }
537 }
538 
539 static char *_get_message(const Mode *sw) {
542  if (pd->current_dir) {
543  char *dirname = g_file_get_parse_name(pd->current_dir);
544  char *str =
545  g_markup_printf_escaped("<b>Current directory:</b> %s", dirname);
546  g_free(dirname);
547  return str;
548  }
549  return "n/a";
550 }
551 
552 static char *_get_completion(const Mode *sw, unsigned int index) {
555 
556  char *d = g_strescape(pd->array[index].path, NULL);
557  return d;
558 }
559 
561  Mode *sw = g_malloc0(sizeof(Mode));
562 
563  *sw = file_browser_mode;
564 
565  sw->private_data = NULL;
566  return sw;
567 }
568 
569 #if 1
570 ModeMode file_browser_mode_completer(Mode *sw, int mretv, char **input,
571  unsigned int selected_line, char **path) {
572  ModeMode retv = MODE_EXIT;
575  if (mretv & MENU_NEXT) {
576  retv = NEXT_DIALOG;
577  } else if (mretv & MENU_PREVIOUS) {
578  retv = PREVIOUS_DIALOG;
579  } else if (mretv & MENU_QUICK_SWITCH) {
580  retv = (mretv & MENU_LOWER_MASK);
581  } else if ((mretv & MENU_OK)) {
582  if (selected_line < pd->array_length) {
583  if (pd->array[selected_line].type == UP) {
584  GFile *new = g_file_get_parent(pd->current_dir);
585  if (new) {
586  g_object_unref(pd->current_dir);
587  pd->current_dir = new;
588  free_list(pd);
589  get_file_browser(sw);
590  return RESET_DIALOG;
591  }
592  } else if (pd->array[selected_line].type == DIRECTORY) {
593  GFile *new = g_file_new_for_path(pd->array[selected_line].path);
594  g_object_unref(pd->current_dir);
595  pd->current_dir = new;
596  free_list(pd);
597  get_file_browser(sw);
598  return RESET_DIALOG;
599  } else if (pd->array[selected_line].type == RFILE) {
600  *path = g_strescape(pd->array[selected_line].path, NULL);
601  return MODE_EXIT;
602  }
603  }
604  retv = RELOAD_DIALOG;
605  } else if ((mretv & MENU_CUSTOM_INPUT) && *input) {
606  char *p = rofi_expand_path(*input);
607  char *dir = g_filename_from_utf8(p, -1, NULL, NULL, NULL);
608  g_free(p);
609  if (g_file_test(dir, G_FILE_TEST_EXISTS)) {
610  if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
611  g_object_unref(pd->current_dir);
612  pd->current_dir = g_file_new_for_path(dir);
613  g_free(dir);
614  free_list(pd);
615  get_file_browser(sw);
616  return RESET_DIALOG;
617  }
618  }
619  g_free(dir);
620  retv = RELOAD_DIALOG;
621  } else if ((mretv & MENU_ENTRY_DELETE) == MENU_ENTRY_DELETE) {
622  retv = RELOAD_DIALOG;
623  }
624  return retv;
625 }
626 #endif
627 
629  .display_name = NULL,
630  .abi_version = ABI_VERSION,
631  .name = "filebrowser",
632  .cfg_name_key = "display-filebrowser",
633  ._init = file_browser_mode_init,
634  ._get_num_entries = file_browser_mode_get_num_entries,
635  ._result = file_browser_mode_result,
636  ._destroy = file_browser_mode_destroy,
637  ._token_match = file_browser_token_match,
638  ._get_display_value = _get_display_value,
639  ._get_icon = _get_icon,
640  ._get_message = _get_message,
641  ._get_completion = _get_completion,
642  ._preprocess_input = NULL,
643  .private_data = NULL,
644  .free = NULL,
645 };
static int file_browser_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
Definition: filebrowser.c:513
static void free_list(FileBrowserModePrivateData *pd)
Definition: filebrowser.c:112
static cairo_surface_t * _get_icon(const Mode *sw, unsigned int selected_line, int height)
Definition: filebrowser.c:522
struct @0 file_browser_config
static unsigned int file_browser_mode_get_num_entries(const Mode *sw)
Definition: filebrowser.c:396
static char * _get_message(const Mode *sw)
Definition: filebrowser.c:539
FBFileType
Definition: filebrowser.c:55
@ NUM_FILE_TYPES
Definition: filebrowser.c:59
@ DIRECTORY
Definition: filebrowser.c:57
@ UP
Definition: filebrowser.c:56
@ RFILE
Definition: filebrowser.c:58
static char * _get_completion(const Mode *sw, unsigned int index)
Definition: filebrowser.c:552
static char * _get_display_value(const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **attr_list, int get_entry)
Definition: filebrowser.c:484
static void file_browser_mode_init_current_dir(Mode *sw)
Definition: filebrowser.c:345
static void set_time(FBFile *file)
Definition: filebrowser.c:188
#define FILEBROWSER_CACHE_FILE
Definition: filebrowser.c:50
static gint compare_time(gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data)
Definition: filebrowser.c:137
static void file_browser_mode_destroy(Mode *sw)
Definition: filebrowser.c:473
enum FBSortingMethod sorting_method
Definition: filebrowser.c:101
enum FBSortingTime sorting_time
Definition: filebrowser.c:103
static gint compare_name(gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data)
Definition: filebrowser.c:125
FBSortingMethod
Definition: filebrowser.c:65
@ FB_SORT_NAME
Definition: filebrowser.c:66
@ FB_SORT_TIME
Definition: filebrowser.c:67
static time_t get_time(const struct stat *statbuf)
Definition: filebrowser.c:175
static void get_file_browser(Mode *sw)
Definition: filebrowser.c:202
FBSortingTime
Definition: filebrowser.c:73
@ FB_CTIME
Definition: filebrowser.c:76
@ FB_MTIME
Definition: filebrowser.c:74
@ FB_ATIME
Definition: filebrowser.c:75
static int file_browser_mode_init(Mode *sw)
Definition: filebrowser.c:380
static ModeMode file_browser_mode_result(Mode *sw, int mretv, char **input, unsigned int selected_line)
Definition: filebrowser.c:402
static void file_browser_mode_init_config(Mode *sw)
Definition: filebrowser.c:306
const char * icon_name[NUM_FILE_TYPES]
Definition: filebrowser.c:80
gboolean directories_first
Definition: filebrowser.c:105
static gint compare(gconstpointer a, gconstpointer b, gpointer data)
Definition: filebrowser.c:157
Mode file_browser_mode
Definition: filebrowser.c:628
ModeMode file_browser_mode_completer(Mode *sw, int mretv, char **input, unsigned int selected_line, char **path)
Definition: filebrowser.c:570
Mode * create_new_file_browser(void)
Definition: filebrowser.c:560
gboolean helper_execute_command(const char *wd, const char *cmd, gboolean run_in_term, RofiHelperExecuteContext *context)
Definition: helper.c:1012
char * rofi_expand_path(const char *input)
Definition: helper.c:713
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
Definition: helper.c:494
gboolean rofi_icon_fetcher_file_is_image(const char *const path)
cairo_surface_t * rofi_icon_fetcher_get(const uint32_t uid)
uint32_t rofi_icon_fetcher_query(const char *name, const int size)
void mode_set_private_data(Mode *mode, void *pd)
Definition: mode.c:136
void * mode_get_private_data(const Mode *mode)
Definition: mode.c:131
ModeMode
Definition: mode.h:49
@ MENU_CUSTOM_COMMAND
Definition: mode.h:79
@ MENU_LOWER_MASK
Definition: mode.h:87
@ MENU_PREVIOUS
Definition: mode.h:81
@ MENU_QUICK_SWITCH
Definition: mode.h:77
@ MENU_ENTRY_DELETE
Definition: mode.h:75
@ MENU_NEXT
Definition: mode.h:71
@ MENU_OK
Definition: mode.h:67
@ MENU_CUSTOM_INPUT
Definition: mode.h:73
@ MODE_EXIT
Definition: mode.h:51
@ NEXT_DIALOG
Definition: mode.h:53
@ RELOAD_DIALOG
Definition: mode.h:55
@ PREVIOUS_DIALOG
Definition: mode.h:57
@ RESET_DIALOG
Definition: mode.h:59
const char * cache_dir
Definition: rofi.c:83
int rofi_view_error_dialog(const char *msg, int markup)
Definition: view.c:2018
#define ABI_VERSION
Definition: mode-private.h:34
@ P_BOOLEAN
Definition: rofi-types.h:20
@ P_STRING
Definition: rofi-types.h:16
enum FBFileType type
Definition: filebrowser.c:84
gboolean link
Definition: filebrowser.c:86
char * path
Definition: filebrowser.c:83
char * name
Definition: filebrowser.c:82
uint32_t icon_fetch_uid
Definition: filebrowser.c:85
time_t time
Definition: filebrowser.c:87
PropertyValue value
Definition: rofi-types.h:290
PropertyType type
Definition: rofi-types.h:288
char * display_name
Definition: mode-private.h:165
char * name
Definition: mode-private.h:163
void * private_data
Definition: mode-private.h:192
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
Definition: theme.c:732
Property * rofi_theme_find_property(ThemeWidget *widget, PropertyType type, const char *property, gboolean exact)
Definition: theme.c:694
gboolean b
Definition: rofi-types.h:259