rofi  1.7.3
theme.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27 
29 #define G_LOG_DOMAIN "Theme"
30 
31 #include "config.h"
32 #include <errno.h>
33 #include <math.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 // GFile stuff.
38 #include "helper.h"
39 #include "rofi-icon-fetcher.h"
40 #include "rofi-types.h"
41 #include "rofi.h"
42 #include "settings.h"
43 #include "theme-parser.h"
44 #include "theme.h"
45 #include "view.h"
46 #include "widgets/textbox.h"
47 #include <gio/gio.h>
48 
49 GList *parsed_config_files = NULL;
50 
52  g_list_free_full(parsed_config_files, g_free);
53  parsed_config_files = NULL;
54 }
55 
56 void rofi_theme_print_parsed_files(gboolean is_term) {
57  printf("\nParsed files:\n");
58  for (GList *iter = g_list_first(parsed_config_files); iter != NULL;
59  iter = g_list_next(iter)) {
60  printf("\t\u2022 %s%s%s\n", is_term ? color_bold : "",
61  (const char *)(iter->data), is_term ? color_reset : "");
62  }
63  printf("\n");
64 }
65 
66 void yyerror(YYLTYPE *yylloc, const char *, const char *);
68  // TODO UPDATE
69  return d.base.type == e.base.type && d.base.distance == e.base.distance &&
70  d.style == e.style;
71 }
72 
74  const char *name) {
75  for (unsigned int i = 0; i < base->num_widgets; i++) {
76  if (g_strcmp0(base->widgets[i]->name, name) == 0) {
77  return base->widgets[i];
78  }
79  }
80 
81  base->widgets =
82  g_realloc(base->widgets, sizeof(ThemeWidget *) * (base->num_widgets + 1));
83  base->widgets[base->num_widgets] = g_slice_new0(ThemeWidget);
84  ThemeWidget *retv = base->widgets[base->num_widgets];
85  retv->parent = base;
86  retv->name = g_strdup(name);
87  base->num_widgets++;
88  return retv;
89 }
94  Property *retv = g_slice_new0(Property);
95  retv->type = type;
96  return retv;
97 }
98 
99 static RofiDistanceUnit *
101  RofiDistanceUnit *retv = g_slice_new0(RofiDistanceUnit);
102  *retv = *unit;
103  if (unit->left) {
105  }
106  if (unit->right) {
108  }
109  return retv;
110 }
112  RofiDistance retv = distance;
113  if (distance.base.left) {
115  }
116  if (distance.base.right) {
117  retv.base.right =
119  }
120  return retv;
121 }
122 
125  retv->name = g_strdup(p->name);
126 
127  switch (p->type) {
128  case P_STRING:
129  retv->value.s = g_strdup(p->value.s);
130  break;
131  case P_LIST:
132  retv->value.list = g_list_copy_deep(
133  p->value.list, (GCopyFunc)rofi_theme_property_copy, NULL);
134  break;
135  case P_LINK:
136  retv->value.link.name = g_strdup(p->value.link.name);
137  retv->value.link.ref = NULL;
138  if (p->value.link.def_value) {
139  retv->value.link.def_value =
141  }
142  break;
143  case P_PADDING: {
144  retv->value = p->value;
145  retv->value.padding.top =
147  retv->value.padding.left =
149  retv->value.padding.bottom =
151  retv->value.padding.right =
153  break;
154  }
155  case P_IMAGE: {
156  retv->value = p->value;
157  retv->value.image.url = g_strdup(p->value.image.url);
158  retv->value.image.colors = NULL;
159  for (GList *l = g_list_first(p->value.image.colors); l;
160  l = g_list_next(l)) {
161  retv->value.image.colors = g_list_append(
162  retv->value.image.colors, g_memdup(l->data, sizeof(ThemeColor)));
163  }
164  break;
165  }
166  default:
167  retv->value = p->value;
168  }
169  return retv;
170 }
171 
173  if (unit->left) {
175  unit->left = NULL;
176  }
177  if (unit->right) {
179  unit->right = NULL;
180  }
181  g_slice_free(RofiDistanceUnit, unit);
182 }
184  if (distance->base.left) {
186  distance->base.left = NULL;
187  }
188  if (distance->base.right) {
190  distance->base.right = NULL;
191  }
192 }
193 
195  if (p == NULL) {
196  return;
197  }
198  g_free(p->name);
199  if (p->type == P_STRING) {
200  g_free(p->value.s);
201  } else if (p->type == P_LIST) {
202  g_list_free_full(p->value.list, (GDestroyNotify)rofi_theme_property_free);
203  p->value.list = 0;
204  } else if (p->type == P_LINK) {
205  g_free(p->value.link.name);
206  if (p->value.link.def_value) {
208  }
209  } else if (p->type == P_PADDING) {
214  } else if (p->type == P_IMAGE) {
215  if (p->value.image.url) {
216  g_free(p->value.image.url);
217  }
218  if (p->value.image.colors) {
219  g_list_free_full(p->value.image.colors, g_free);
220  }
221  }
222  g_slice_free(Property, p);
223 }
224 
225 void rofi_theme_reset(void) {
227  rofi_theme = g_slice_new0(ThemeWidget);
228  rofi_theme->name = g_strdup("Root");
229 }
230 
232  if (widget == NULL) {
233  return;
234  }
235  if (widget->properties) {
236  g_hash_table_destroy(widget->properties);
237  widget->properties = NULL;
238  }
239  if (widget->media) {
240  g_slice_free(ThemeMedia, widget->media);
241  }
242  for (unsigned int i = 0; i < widget->num_widgets; i++) {
243  rofi_theme_free(widget->widgets[i]);
244  }
245  g_free(widget->widgets);
246  g_free(widget->name);
247  g_slice_free(ThemeWidget, widget);
248 }
249 
253 inline static void printf_double(double d) {
254  char buf[G_ASCII_DTOSTR_BUF_SIZE];
255  g_ascii_formatd(buf, G_ASCII_DTOSTR_BUF_SIZE, "%.4lf", d);
256  fputs(buf, stdout);
257 }
258 
260  if (unit->modtype == ROFI_DISTANCE_MODIFIER_GROUP) {
261  fputs("( ", stdout);
262  }
263  if (unit->left) {
265  }
266 
267  if (unit->modtype == ROFI_DISTANCE_MODIFIER_ADD) {
268  fputs(" + ", stdout);
269  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_SUBTRACT) {
270  fputs(" - ", stdout);
271  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_DIVIDE) {
272  fputs(" / ", stdout);
273  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MULTIPLY) {
274  fputs(" * ", stdout);
275  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MODULO) {
276  fputs(" % ", stdout);
277  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MIN) {
278  fputs(" min ", stdout);
279  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MAX) {
280  fputs(" max ", stdout);
281  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_ROUND) {
282  fputs(" round ", stdout);
283  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_FLOOR) {
284  fputs(" floor ", stdout);
285  } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_CEIL) {
286  fputs(" ceil ", stdout);
287  }
288  if (unit->right) {
290  }
291 
292  if (unit->modtype == ROFI_DISTANCE_MODIFIER_NONE) {
293  if (unit->type == ROFI_PU_PX) {
294  printf("%upx ", (unsigned int)unit->distance);
295  } else if (unit->type == ROFI_PU_MM) {
296  printf_double(unit->distance);
297  fputs("mm ", stdout);
298  } else if (unit->type == ROFI_PU_PERCENT) {
299  printf_double(unit->distance);
300  fputs("% ", stdout);
301  } else if (unit->type == ROFI_PU_CH) {
302  printf_double(unit->distance);
303  fputs("ch ", stdout);
304  } else {
305  printf_double(unit->distance);
306  fputs("em ", stdout);
307  }
308  }
309  if (unit->modtype == ROFI_DISTANCE_MODIFIER_GROUP) {
310  fputs(" )", stdout);
311  }
312 }
313 
314 static void rofi_theme_print_color(ThemeColor color) {
315  uint8_t r, g, b;
316  g = 255 * color.green;
317  r = 255 * color.red;
318  b = 255 * color.blue;
319  if (color.alpha < 0.00001) {
320  printf("transparent");
321  return;
322  }
323  for (uint32_t x = 0; x < num_CSSColors; x++) {
324  if (CSSColors[x].r == r && CSSColors[x].g == g && CSSColors[x].b == b) {
325  printf("%s", CSSColors[x].name);
326  if (color.alpha < 1) {
327  printf("/%.0f%%", color.alpha * 100.0);
328  }
329  return;
330  }
331  }
332  printf("rgba ( %.0f, %.0f, %.0f, %.0f %% )", (color.red * 255.0),
333  (color.green * 255.0), (color.blue * 255.0), (color.alpha * 100.0));
334 }
337  fputs("calc( ", stdout);
338  }
341  fputs(")", stdout);
342  }
343  if (d.style == ROFI_HL_DASH) {
344  printf("dash ");
345  }
346 }
348 const char *const RofiCursorTypeStr[3] = {
349  "default",
350  "pointer",
351  "text",
352 };
353 
355  switch (p->type) {
356  case P_LIST:
357  printf("[ ");
358  for (GList *iter = p->value.list; iter != NULL; iter = g_list_next(iter)) {
360  if (iter->next != NULL) {
361  printf(",");
362  }
363  }
364  printf(" ]");
365  break;
366  case P_ORIENTATION:
367  printf("%s", (p->value.i == ROFI_ORIENTATION_HORIZONTAL) ? "horizontal"
368  : "vertical");
369  break;
370  case P_CURSOR:
371  printf("%s", RofiCursorTypeStr[p->value.i]);
372  break;
373  case P_HIGHLIGHT:
374  if (p->value.highlight.style & ROFI_HL_BOLD) {
375  printf("bold ");
376  }
378  printf("underline ");
379  }
381  printf("strikethrough ");
382  }
383  if (p->value.highlight.style & ROFI_HL_ITALIC) {
384  printf("italic ");
385  }
386  if (p->value.highlight.style & ROFI_HL_COLOR) {
388  }
389  break;
390  case P_POSITION: {
391  switch (p->value.i) {
392  case WL_CENTER:
393  fputs("center", stdout);
394  break;
395  case WL_NORTH:
396  fputs("north", stdout);
397  break;
398  case WL_SOUTH:
399  fputs("south", stdout);
400  break;
401  case WL_WEST:
402  fputs("west", stdout);
403  break;
404  case WL_EAST:
405  fputs("east", stdout);
406  break;
407  case WL_NORTH | WL_EAST:
408  fputs("northeast", stdout);
409  break;
410  case WL_SOUTH | WL_EAST:
411  fputs("southeast", stdout);
412  break;
413  case WL_NORTH | WL_WEST:
414  fputs("northwest", stdout);
415  break;
416  case WL_SOUTH | WL_WEST:
417  fputs("southwest", stdout);
418  break;
419  }
420  break;
421  }
422  case P_STRING:
423  printf("\"%s\"", p->value.s);
424  break;
425  case P_INTEGER:
426  printf("%d", p->value.i);
427  break;
428  case P_DOUBLE: {
429  char sign = (p->value.f < 0);
430  int top = (int)fabs(p->value.f);
431  int bottom = (fabs(fmod(p->value.f, 1.0))) * 100;
432  printf("%s%d.%02d", sign ? "-" : "", top, bottom);
433  break;
434  }
435  case P_BOOLEAN:
436  printf("%s", p->value.b ? "true" : "false");
437  break;
438  case P_COLOR:
440  break;
441  case P_IMAGE: {
442  if (p->value.image.type == ROFI_IMAGE_URL) {
443  printf("url (\"%s\")", p->value.s);
444  } else if (p->value.image.type == ROFI_IMAGE_LINEAR_GRADIENT) {
445  printf("linear-gradient ( ");
446  guint length = g_list_length(p->value.image.colors);
447  guint index = 0;
448  for (GList *l = g_list_first(p->value.image.colors); l != NULL;
449  l = g_list_next(l)) {
450  ThemeColor *color = (ThemeColor *)l->data;
451  rofi_theme_print_color(*color);
452  index++;
453  if (index < length) {
454  printf(", ");
455  }
456  }
457  printf(")");
458  }
459 
460  break;
461  }
462  case P_PADDING:
467  } else if (distance_compare(p->value.padding.top,
468  p->value.padding.bottom) &&
470  p->value.padding.right)) {
473  } else if (!distance_compare(p->value.padding.top,
474  p->value.padding.bottom) &&
476  p->value.padding.right)) {
480  } else {
485  }
486  break;
487  case P_LINK:
488  if (p->value.link.def_value) {
489  printf("var( %s, ", p->value.link.name);
491  printf(")");
492  } else {
493  printf("var(%s)", p->value.link.name);
494  }
495  break;
496  case P_INHERIT:
497  printf("inherit");
498  break;
499  default:
500  break;
501  }
502 }
503 
504 static void rofi_theme_print_property_index(size_t pnl, int depth,
505  Property *p) {
506  int pl = strlen(p->name);
507  printf("%*s%s:%*s ", depth, "", p->name, (int)pnl - pl, "");
509  putchar(';');
510  putchar('\n');
511 }
512 
514  GHashTableIter iter;
515  gpointer key, value;
516 
517  if (widget->media) {
518  printf("%s {\n", widget->name);
519  for (unsigned int i = 0; i < widget->num_widgets; i++) {
520  rofi_theme_print_index(widget->widgets[i], index + 4);
521  }
522  printf("}\n");
523  } else {
524  if (widget->properties) {
525  GList *list = NULL;
526  ThemeWidget *w = widget;
527  while (w) {
528  if (g_strcmp0(w->name, "Root") == 0) {
529  break;
530  }
531  if (w->media) {
532  break;
533  }
534  list = g_list_prepend(list, w->name);
535  w = w->parent;
536  }
537  if (g_list_length(list) > 0) {
538  printf("%*s", index, "");
539  for (GList *citer = g_list_first(list); citer != NULL;
540  citer = g_list_next(citer)) {
541  char *name = (char *)citer->data;
542  fputs(name, stdout);
543  if (citer->prev == NULL && citer->next) {
544  putchar(' ');
545  } else if (citer->next) {
546  putchar('.');
547  }
548  }
549  printf(" {\n");
550  } else {
551  printf("%*s* {\n", index, "");
552  }
553  size_t property_name_length = 0;
554  g_hash_table_iter_init(&iter, widget->properties);
555  while (g_hash_table_iter_next(&iter, &key, &value)) {
556  Property *pv = (Property *)value;
557  property_name_length = MAX(strlen(pv->name), property_name_length);
558  }
559  g_hash_table_iter_init(&iter, widget->properties);
560  while (g_hash_table_iter_next(&iter, &key, &value)) {
561  Property *pv = (Property *)value;
562  rofi_theme_print_property_index(property_name_length, index + 4, pv);
563  }
564  printf("%*s}\n", index, "");
565  g_list_free(list);
566  }
567  for (unsigned int i = 0; i < widget->num_widgets; i++) {
568  rofi_theme_print_index(widget->widgets[i], index);
569  }
570  }
571 }
572 
574  if (widget != NULL) {
575  printf("/**\n * rofi -dump-theme output.\n * Rofi version: %s\n **/\n",
576  PACKAGE_VERSION);
578  }
579 }
580 
584 int yyparse();
585 
589 void yylex_destroy(void);
590 
594 extern FILE *yyin;
595 
603 void yyerror(YYLTYPE *yylloc, const char *what, const char *s) {
604  char *what_esc = what ? g_markup_escape_text(what, -1) : g_strdup("");
605  GString *str = g_string_new("");
606  g_string_printf(str,
607  "<big><b>Error while parsing theme:</b></big> <i>%s</i>\n",
608  what_esc);
609  g_free(what_esc);
610  char *esc = g_markup_escape_text(s, -1);
611  g_string_append_printf(
612  str,
613  "\tParser error: <span size=\"smaller\" style=\"italic\">%s</span>\n",
614  esc);
615  g_free(esc);
616  if (yylloc->filename != NULL) {
617  g_string_append_printf(
618  str,
619  "\tLocation: line %d column %d to line %d column %d.\n"
620  "\tFile '%s'\n",
621  yylloc->first_line, yylloc->first_column, yylloc->last_line,
622  yylloc->last_column, yylloc->filename);
623  } else {
624  g_string_append_printf(
625  str, "\tLocation: line %d column %d to line %d column %d\n",
626  yylloc->first_line, yylloc->first_column, yylloc->last_line,
627  yylloc->last_column);
628  }
629  g_log("Parser", G_LOG_LEVEL_DEBUG, "Failed to parse theme:\n%s", str->str);
631 }
632 
633 static void rofi_theme_copy_property_int(G_GNUC_UNUSED gpointer key,
634  gpointer value, gpointer user_data) {
635  GHashTable *table = (GHashTable *)user_data;
637  g_hash_table_replace(table, p->name, p);
638 }
640  if (table == NULL) {
641  return;
642  }
643  if (widget->properties == NULL) {
644  widget->properties =
645  g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
646  (GDestroyNotify)rofi_theme_property_free);
647  }
648  g_hash_table_foreach(table, rofi_theme_copy_property_int, widget->properties);
649 }
650 
656  const char *name) {
657  for (unsigned int j = 0; widget && j < widget->num_widgets; j++) {
658  if (g_strcmp0(widget->widgets[j]->name, name) == 0) {
659  return widget->widgets[j];
660  }
661  }
662  return widget;
663 }
664 
665 static ThemeWidget *rofi_theme_find(ThemeWidget *widget, const char *name,
666  const gboolean exact) {
667  if (widget == NULL || name == NULL) {
668  return widget;
669  }
670  char *tname = g_strdup(name);
671  char *saveptr = NULL;
672  int found = TRUE;
673  for (const char *iter = strtok_r(tname, ".", &saveptr); iter != NULL;
674  iter = strtok_r(NULL, ".", &saveptr)) {
675  found = FALSE;
677  if (f != widget) {
678  widget = f;
679  found = TRUE;
680  } else if (exact) {
681  break;
682  }
683  }
684  g_free(tname);
685  if (!exact || found) {
686  return widget;
687  }
688  return NULL;
689 }
690 
692  // Set name, remove '@' prefix.
693  const char *name = p->value.link.name; // + (*(p->value.link.name)== '@'?1:0;
694  g_info("Resolving link to %s", p->value.link.name);
695  if (depth > 20) {
696  g_warning("Found more then 20 redirects for property. Stopping.");
697  p->value.link.ref = p;
698  return;
699  }
700 
701  if (rofi_theme->properties &&
702  g_hash_table_contains(rofi_theme->properties, name)) {
703  Property *pr = g_hash_table_lookup(rofi_theme->properties, name);
704  g_info("Resolving link %s found: %s", p->value.link.name, pr->name);
705  if (pr->type == P_LINK) {
706  if (pr->value.link.ref == NULL) {
708  }
709  if (pr->value.link.ref != pr) {
710  p->value.link.ref = pr->value.link.ref;
711  return;
712  }
713  } else {
714  p->value.link.ref = pr;
715  return;
716  }
717  }
718  // No found and we have default value.
719  if (p->value.link.def_value) {
720  p->value.link.ref = p->value.link.def_value;
721  return;
722  }
723 
724  // No found, set ref to self.
725  p->value.link.ref = p;
726 }
727 
729  const char *property, gboolean exact) {
730  while (widget) {
731  if (widget->properties &&
732  g_hash_table_contains(widget->properties, property)) {
733  Property *p = g_hash_table_lookup(widget->properties, property);
734  if (p->type == P_INHERIT) {
735  return p;
736  }
737  if (p->type == P_LINK) {
738  if (p->value.link.ref == NULL) {
739  // Resolve link.
741  }
742  if (p->value.link.ref != NULL && p->value.link.ref->type == type) {
743  return p->value.link.ref;
744  }
745  }
746  if (p->type == type) {
747  return p;
748  }
749  // RofiPadding and integer can be converted.
750  if (p->type == P_INTEGER && type == P_PADDING) {
751  return p;
752  }
753  g_debug("Found property: '%s' on '%s', but type %s does not match "
754  "expected type %s.",
755  property, widget->name, PropertyTypeName[p->type],
756  PropertyTypeName[type]);
757  }
758  if (exact) {
759  return NULL;
760  }
761  // Fall back to defaults.
762  widget = widget->parent;
763  }
764  return NULL;
765 }
766 ThemeWidget *rofi_config_find_widget(const char *name, const char *state,
767  gboolean exact) {
768  // First find exact match based on name.
770  widget = rofi_theme_find(widget, state, exact);
771 
772  return widget;
773 }
774 ThemeWidget *rofi_theme_find_widget(const char *name, const char *state,
775  gboolean exact) {
776  // First find exact match based on name.
778  widget = rofi_theme_find(widget, state, exact);
779 
780  return widget;
781 }
782 
784  const char *property, int def) {
785  if (p) {
786  if (p->type == P_INHERIT) {
787  if (widget->parent) {
788  ThemeWidget *parent =
790  Property *pv =
791  rofi_theme_find_property(parent, P_POSITION, property, FALSE);
792  return rofi_theme_get_position_inside(pv, widget->parent, property,
793  def);
794  }
795  return def;
796  }
797  return p->value.i;
798  }
799  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
800  widget->state ? widget->state : "", property);
801  return def;
802 }
803 int rofi_theme_get_position(const widget *widget, const char *property,
804  int def) {
806  Property *p = rofi_theme_find_property(wid, P_POSITION, property, FALSE);
807  return rofi_theme_get_position_inside(p, widget, property, def);
808 }
810  const char *property, int def) {
811  if (p) {
812  if (p->type == P_INHERIT) {
813  if (widget->parent) {
814  ThemeWidget *parent =
816  Property *pv =
817  rofi_theme_find_property(parent, P_INTEGER, property, FALSE);
818  return rofi_theme_get_integer_inside(pv, widget->parent, property, def);
819  }
820  return def;
821  }
822  return p->value.i;
823  }
824  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
825  widget->state ? widget->state : "", property);
826  return def;
827 }
828 int rofi_theme_get_integer(const widget *widget, const char *property,
829  int def) {
831  Property *p = rofi_theme_find_property(wid, P_INTEGER, property, FALSE);
832  return (int)rofi_theme_get_integer_inside(p, widget, property, (double)def);
833 }
835  const widget *widget,
836  const char *property,
837  int def) {
838  if (p) {
839  if (p->type == P_INHERIT) {
840  if (widget->parent) {
841  ThemeWidget *parent =
843  Property *pv =
844  rofi_theme_find_property(parent, P_PADDING, property, FALSE);
845  return rofi_theme_get_distance_inside(pv, widget->parent, property,
846  def);
847  }
848  return (RofiDistance){
849  .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
850  .style = ROFI_HL_SOLID};
851  }
852  if (p->type == P_INTEGER) {
853  return (RofiDistance){.base = {p->value.i, ROFI_PU_PX,
854  ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
855  .style = ROFI_HL_SOLID};
856  }
857  return p->value.padding.left;
858  }
859  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
860  widget->state ? widget->state : "", property);
861  return (RofiDistance){
862  .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
863  .style = ROFI_HL_SOLID};
864 }
865 RofiDistance rofi_theme_get_distance(const widget *widget, const char *property,
866  int def) {
868  Property *p = rofi_theme_find_property(wid, P_PADDING, property, FALSE);
869  return rofi_theme_get_distance_inside(p, widget, property, def);
870 }
871 
873  const char *property, int def) {
874  if (p) {
875  if (p->type == P_INHERIT) {
876  if (widget->parent) {
877  ThemeWidget *parent =
879  Property *pv =
880  rofi_theme_find_property(parent, P_BOOLEAN, property, FALSE);
881  return rofi_theme_get_boolean_inside(pv, widget->parent, property, def);
882  }
883  return def;
884  }
885  return p->value.b;
886  }
887  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
888  widget->state ? widget->state : "", property);
889  return def;
890 }
891 int rofi_theme_get_boolean(const widget *widget, const char *property,
892  int def) {
894  Property *p = rofi_theme_find_property(wid, P_BOOLEAN, property, FALSE);
895  return rofi_theme_get_boolean_inside(p, widget, property, def);
896 }
897 
899  const widget *widget,
900  const char *property,
901  RofiOrientation def) {
902  if (p) {
903  if (p->type == P_INHERIT) {
904  if (widget->parent) {
905  ThemeWidget *parent =
907  Property *pv =
908  rofi_theme_find_property(parent, P_ORIENTATION, property, FALSE);
909  return rofi_theme_get_orientation_inside(pv, widget->parent, property,
910  def);
911  }
912  return def;
913  }
914  return p->value.b;
915  }
916  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
917  widget->state ? widget->state : "", property);
918  return def;
919 }
921  const char *property,
922  RofiOrientation def) {
924  Property *p = rofi_theme_find_property(wid, P_ORIENTATION, property, FALSE);
925  return rofi_theme_get_orientation_inside(p, widget, property, def);
926 }
927 
929  const widget *widget,
930  const char *property,
931  RofiCursorType def) {
932  if (p) {
933  if (p->type == P_INHERIT) {
934  if (widget->parent) {
935  ThemeWidget *parent =
937  Property *pv =
938  rofi_theme_find_property(parent, P_CURSOR, property, FALSE);
939  return rofi_theme_get_cursor_type_inside(pv, widget->parent, property,
940  def);
941  }
942  return def;
943  }
944  return p->value.i;
945  }
946  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
947  widget->state ? widget->state : "", property);
948  return def;
949 }
951  const char *property,
952  RofiCursorType def) {
954  Property *p = rofi_theme_find_property(wid, P_CURSOR, property, FALSE);
955  return rofi_theme_get_cursor_type_inside(p, widget, property, def);
956 }
958  const widget *widget,
959  const char *property,
960  const char *def) {
961  if (p) {
962  if (p->type == P_INHERIT) {
963  if (widget->parent) {
964  ThemeWidget *parent =
966  Property *pv =
967  rofi_theme_find_property(parent, P_STRING, property, FALSE);
968  return rofi_theme_get_string_inside(pv, widget->parent, property, def);
969  }
970  return def;
971  }
972  return p->value.s;
973  }
974  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
975  widget->state ? widget->state : "", property);
976  return def;
977 }
978 const char *rofi_theme_get_string(const widget *widget, const char *property,
979  const char *def) {
981  Property *p = rofi_theme_find_property(wid, P_STRING, property, FALSE);
982  return rofi_theme_get_string_inside(p, widget, property, def);
983 }
984 
986  const widget *widget,
987  const char *property,
988  double def) {
989  if (p) {
990  if (p->type == P_INHERIT) {
991  if (widget->parent) {
992  ThemeWidget *parent =
994  Property *pv =
995  rofi_theme_find_property(parent, P_INTEGER, property, FALSE);
997  property, def);
998  }
999  return def;
1000  }
1001  return p->value.i;
1002  }
1003  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1004  widget->state ? widget->state : "", property);
1005  return def;
1006 }
1007 static double rofi_theme_get_double_inside(const widget *orig, Property *p,
1008  const widget *widget,
1009  const char *property, double def) {
1010  if (p) {
1011  if (p->type == P_INHERIT) {
1012  if (widget->parent) {
1013  ThemeWidget *parent =
1015  Property *pv =
1016  rofi_theme_find_property(parent, P_DOUBLE, property, FALSE);
1017  return rofi_theme_get_double_inside(orig, pv, widget, property, def);
1018  }
1019  return def;
1020  }
1021  return p->value.f;
1022  }
1023  ThemeWidget *wid = rofi_theme_find_widget(orig->name, widget->state, FALSE);
1024  // Fallback to integer if double is not found.
1025  p = rofi_theme_find_property(wid, P_INTEGER, property, FALSE);
1026  return rofi_theme_get_double_integer_fb_inside(p, widget, property, def);
1027 }
1028 double rofi_theme_get_double(const widget *widget, const char *property,
1029  double def) {
1031  Property *p = rofi_theme_find_property(wid, P_DOUBLE, property, FALSE);
1032  return rofi_theme_get_double_inside(widget, p, widget, property, def);
1033 }
1035  const char *property, cairo_t *d) {
1036  if (p) {
1037  if (p->type == P_INHERIT) {
1038  if (widget->parent) {
1039  ThemeWidget *parent =
1041  Property *pv =
1042  rofi_theme_find_property(parent, P_COLOR, property, FALSE);
1043  rofi_theme_get_color_inside(widget->parent, pv, property, d);
1044  }
1045  return;
1046  }
1047  cairo_set_source_rgba(d, p->value.color.red, p->value.color.green,
1048  p->value.color.blue, p->value.color.alpha);
1049  } else {
1050  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1051  widget->state ? widget->state : "", property);
1052  }
1053 }
1054 
1055 void rofi_theme_get_color(const widget *widget, const char *property,
1056  cairo_t *d) {
1058  Property *p = rofi_theme_find_property(wid, P_COLOR, property, FALSE);
1059  rofi_theme_get_color_inside(widget, p, property, d);
1060 }
1061 
1063  const char *property, cairo_t *d) {
1064  if (p) {
1065  if (p->type == P_INHERIT) {
1066  if (widget->parent) {
1067  ThemeWidget *parent =
1069  Property *pv =
1070  rofi_theme_find_property(parent, P_IMAGE, property, FALSE);
1071  return rofi_theme_get_image_inside(pv, widget->parent, property, d);
1072  }
1073  return FALSE;
1074  }
1075  if (p->value.image.type == ROFI_IMAGE_URL) {
1076  int wsize = -1;
1077  int hsize = -1;
1078  switch (p->value.image.scaling) {
1079  case ROFI_SCALE_BOTH:
1080  wsize = widget->w;
1081  hsize = widget->h;
1082  break;
1083  case ROFI_SCALE_WIDTH:
1084  wsize = widget->w;
1085  break;
1086  case ROFI_SCALE_HEIGHT:
1087  hsize = widget->h;
1088  break;
1089  case ROFI_SCALE_NONE:
1090  default:
1091  break;
1092  }
1093  if (p->value.image.surface_id == 0 || p->value.image.wsize != wsize ||
1094  p->value.image.hsize != hsize) {
1095  p->value.image.surface_id =
1096  rofi_icon_fetcher_query_advanced(p->value.image.url, wsize, hsize);
1097  p->value.image.wsize = wsize;
1098  p->value.image.hsize = hsize;
1099  }
1100  cairo_surface_t *img = rofi_icon_fetcher_get(p->value.image.surface_id);
1101 
1102  if (img != NULL) {
1103  cairo_pattern_t *pat = cairo_pattern_create_for_surface(img);
1104  cairo_pattern_set_extend(pat, CAIRO_EXTEND_REPEAT);
1105  cairo_set_source(d, pat);
1106  cairo_pattern_destroy(pat);
1107  return TRUE;
1108  }
1109  } else if (p->value.image.type == ROFI_IMAGE_LINEAR_GRADIENT) {
1110  cairo_pattern_t *pat = NULL;
1111  switch (p->value.image.dir) {
1112  case ROFI_DIRECTION_RIGHT:
1113  pat = cairo_pattern_create_linear(0.0, 0.0, widget->w, 0.0);
1114  break;
1115  case ROFI_DIRECTION_LEFT:
1116  pat = cairo_pattern_create_linear(widget->w, 0.0, 0.0, 0.0);
1117  break;
1118  case ROFI_DIRECTION_BOTTOM:
1119  pat = cairo_pattern_create_linear(0.0, 0.0, 0.0, widget->h);
1120  break;
1121  case ROFI_DIRECTION_TOP:
1122  pat = cairo_pattern_create_linear(0.0, widget->h, 0.0, 0.0);
1123  break;
1124  case ROFI_DIRECTION_ANGLE: {
1125  double offsety1 =
1126  sin(G_PI * 2 * p->value.image.angle) * (widget->h / 2.0);
1127  double offsetx1 =
1128  cos(G_PI * 2 * p->value.image.angle) * (widget->w / 2.0);
1129  pat = cairo_pattern_create_linear(
1130  widget->w / 2.0 - offsetx1, widget->h / 2.0 - offsety1,
1131  widget->w / 2.0 + offsetx1, widget->h / 2.0 + offsety1);
1132  break;
1133  }
1134  };
1135  guint length = g_list_length(p->value.image.colors);
1136  if (length > 1) {
1137  length--;
1138  guint color_index = 0;
1139  for (GList *l = g_list_first(p->value.image.colors); l != NULL;
1140  l = g_list_next(l)) {
1141  ThemeColor *c = (ThemeColor *)(l->data);
1142  cairo_pattern_add_color_stop_rgba(pat, (color_index) / (double)length,
1143  c->red, c->green, c->blue,
1144  c->alpha);
1145  color_index++;
1146  }
1147  cairo_set_source(d, pat);
1148  cairo_pattern_destroy(pat);
1149  return TRUE;
1150  }
1151  if (length == 1) {
1152  ThemeColor *c = (ThemeColor *)(p->value.image.colors->data);
1153  cairo_pattern_add_color_stop_rgba(pat, 0, c->red, c->green, c->blue,
1154  c->alpha);
1155  cairo_set_source(d, pat);
1156  cairo_pattern_destroy(pat);
1157  return TRUE;
1158  }
1159  }
1160  } else {
1161  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1162  widget->state ? widget->state : "", property);
1163  }
1164  return FALSE;
1165 }
1166 gboolean rofi_theme_get_image(const widget *widget, const char *property,
1167  cairo_t *d) {
1169  Property *p = rofi_theme_find_property(wid, P_IMAGE, property, FALSE);
1170  return rofi_theme_get_image_inside(p, widget, property, d);
1171 }
1173  const widget *widget,
1174  const char *property,
1175  RofiPadding pad) {
1176  if (p) {
1177  if (p->type == P_INHERIT) {
1178  if (widget->parent) {
1179  ThemeWidget *parent =
1181  Property *pv =
1182  rofi_theme_find_property(parent, P_PADDING, property, FALSE);
1183  return rofi_theme_get_padding_inside(pv, widget->parent, property, pad);
1184  }
1185  return pad;
1186  }
1187  if (p->type == P_PADDING) {
1188  pad = p->value.padding;
1189  } else {
1190  RofiDistance d =
1191  (RofiDistance){.base = {p->value.i, ROFI_PU_PX,
1192  ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
1193  .style = ROFI_HL_SOLID};
1194  return (RofiPadding){d, d, d, d};
1195  }
1196  }
1197  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1198  widget->state ? widget->state : "", property);
1199  return pad;
1200 }
1201 RofiPadding rofi_theme_get_padding(const widget *widget, const char *property,
1202  RofiPadding pad) {
1204  Property *p = rofi_theme_find_property(wid, P_PADDING, property, FALSE);
1205  return rofi_theme_get_padding_inside(p, widget, property, pad);
1206 }
1207 
1209  const char *property,
1210  PropertyType child_type) {
1211  if (p) {
1212  if (p->type == P_INHERIT) {
1213  if (widget->parent) {
1214  ThemeWidget *parent =
1216  Property *pv =
1217  rofi_theme_find_property(parent, P_LIST, property, FALSE);
1218  return rofi_theme_get_list_inside(pv, widget->parent, property,
1219  child_type);
1220  }
1221  } else if (p->type == P_LIST) {
1222  return p->value.list;
1223  }
1224  }
1225  return NULL;
1226 }
1228  const char *property) {
1229  ThemeWidget *wid2 =
1231  Property *p = rofi_theme_find_property(wid2, P_LIST, property, FALSE);
1232  GList *list = rofi_theme_get_list_inside(p, widget, property, P_PADDING);
1233  GList *retv = NULL;
1234  for (GList *iter = g_list_first(list); iter != NULL;
1235  iter = g_list_next(iter)) {
1236  Property *prop = (Property *)(iter->data);
1237  if (prop->type == P_PADDING) {
1238  RofiDistance *p = g_new0(RofiDistance, 1);
1239  *p = prop->value.padding.left;
1240  retv = g_list_append(retv, p);
1241  } else if (prop->type == P_INTEGER) {
1242  RofiDistance *p = g_new0(RofiDistance, 1);
1243  RofiDistance d =
1244  (RofiDistance){.base = {prop->value.i, ROFI_PU_PX,
1245  ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
1246  .style = ROFI_HL_SOLID};
1247  *p = d;
1248  retv = g_list_append(retv, p);
1249  } else {
1250  g_warning("Invalid type detected in list.");
1251  }
1252  }
1253  return retv;
1254 }
1255 GList *rofi_theme_get_list_strings(const widget *widget, const char *property) {
1256  ThemeWidget *wid2 =
1258  Property *p = rofi_theme_find_property(wid2, P_LIST, property, FALSE);
1259  GList *list = rofi_theme_get_list_inside(p, widget, property, P_STRING);
1260  GList *retv = NULL;
1261  for (GList *iter = g_list_first(list); iter != NULL;
1262  iter = g_list_next(iter)) {
1263  Property *prop = (Property *)(iter->data);
1264  if (prop->type == P_STRING) {
1265  retv = g_list_append(retv, g_strdup(prop->value.s));
1266  } else {
1267  g_warning("Invalid type detected in list.");
1268  }
1269  }
1270  return retv;
1271 }
1272 
1275  const char *property,
1277  if (p) {
1278  if (p->type == P_INHERIT) {
1279  if (widget->parent) {
1280  ThemeWidget *parent =
1282  Property *pv =
1283  rofi_theme_find_property(parent, P_HIGHLIGHT, property, FALSE);
1284  return rofi_theme_get_highlight_inside(pv, widget->parent, property,
1285  th);
1286  }
1287  return th;
1288  } else if (p->type == P_COLOR) {
1290  th.color = p->value.color;
1291  return th;
1292  }
1293 
1294  return p->value.highlight;
1295  } else {
1296  ThemeWidget *wid =
1298  Property *p2 = rofi_theme_find_property(wid, P_COLOR, property, FALSE);
1299  if (p2 != NULL) {
1300  return rofi_theme_get_highlight_inside(p2, widget, property, th);
1301  }
1302  return th;
1303  }
1304  g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1305  widget->state ? widget->state : "", property);
1306  return th;
1307 }
1309  const char *property,
1312  Property *p = rofi_theme_find_property(wid, P_HIGHLIGHT, property, FALSE);
1313  if (p == NULL) {
1314  p = rofi_theme_find_property(wid, P_COLOR, property, FALSE);
1315  }
1316  return rofi_theme_get_highlight_inside(p, widget, property, th);
1317 }
1319  int val = unit->distance;
1320 
1321  if (unit->type == ROFI_PU_EM) {
1323  } else if (unit->type == ROFI_PU_CH) {
1324  val = unit->distance * textbox_get_estimated_ch();
1325  } else if (unit->type == ROFI_PU_PERCENT) {
1326  if (ori == ROFI_ORIENTATION_VERTICAL) {
1327  int height = 0;
1328  rofi_view_get_current_monitor(NULL, &height);
1329  val = (unit->distance * height) / (100.0);
1330  } else {
1331  int width = 0;
1332  rofi_view_get_current_monitor(&width, NULL);
1333  val = (unit->distance * width) / (100.0);
1334  }
1335  } else if (unit->type == ROFI_PU_MM) {
1336  val = unit->distance * config.dpi / 25.4;
1337  }
1338  return val;
1339 }
1340 
1342  RofiOrientation ori) {
1343  switch (unit->modtype) {
1345  return distance_unit_get_pixel(unit->left, ori);
1346  break;
1348  return distance_unit_get_pixel(unit->left, ori) +
1349  distance_unit_get_pixel(unit->right, ori);
1351  return distance_unit_get_pixel(unit->left, ori) -
1352  distance_unit_get_pixel(unit->right, ori);
1354  return distance_unit_get_pixel(unit->left, ori) *
1355  distance_unit_get_pixel(unit->right, ori);
1357  int a = distance_unit_get_pixel(unit->left, ori);
1358  int b = distance_unit_get_pixel(unit->right, ori);
1359  if (b != 0) {
1360  return a / b;
1361  }
1362  return a;
1363  }
1365  int a = distance_unit_get_pixel(unit->left, ori);
1366  int b = distance_unit_get_pixel(unit->right, ori);
1367  if (b != 0) {
1368  return a % b;
1369  }
1370  return 0;
1371  }
1373  int a = distance_unit_get_pixel(unit->left, ori);
1374  int b = distance_unit_get_pixel(unit->right, ori);
1375  return MIN(a, b);
1376  }
1378  int a = distance_unit_get_pixel(unit->left, ori);
1379  int b = distance_unit_get_pixel(unit->right, ori);
1380  return MAX(a, b);
1381  }
1383  double a = (double)distance_unit_get_pixel(unit->left, ori);
1384  double b = (double)distance_unit_get_pixel(unit->right, ori);
1385  return (int)(round(a / b) * b);
1386  }
1388  double a = (double)distance_unit_get_pixel(unit->left, ori);
1389  double b = (double)distance_unit_get_pixel(unit->right, ori);
1390  return (int)(ceil(a / b) * b);
1391  }
1393  double a = (double)distance_unit_get_pixel(unit->left, ori);
1394  double b = (double)distance_unit_get_pixel(unit->right, ori);
1395  return (int)(floor(a / b) * b);
1396  }
1397  default:
1398  break;
1399  }
1400  return get_pixels(unit, ori);
1401 }
1402 
1404  return distance_unit_get_pixel(&(d.base), ori);
1405 }
1406 
1407 void distance_get_linestyle(RofiDistance d, cairo_t *draw) {
1408  if (d.style == ROFI_HL_DASH) {
1409  const double dashes[1] = {4};
1410  cairo_set_dash(draw, dashes, 1, 0.0);
1411  } else {
1412  cairo_set_dash(draw, NULL, 0, 0.0);
1413  }
1414 }
1415 
1416 char *rofi_theme_parse_prepare_file(const char *file, const char *parent_file) {
1417  char *filename = rofi_expand_path(file);
1418  // If no absolute path specified, expand it.
1419  if (parent_file != NULL && !g_path_is_absolute(filename)) {
1420  char *basedir = g_path_get_dirname(parent_file);
1421  char *path = g_build_filename(basedir, filename, NULL);
1422  g_free(filename);
1423  filename = path;
1424  g_free(basedir);
1425  }
1426  GFile *gf = g_file_new_for_path(filename);
1427  parsed_config_files = g_list_append(parsed_config_files, filename);
1428  filename = g_file_get_path(gf);
1429  g_object_unref(gf);
1430 
1431  return filename;
1432 }
1433 
1435  g_assert(parent != NULL);
1436  g_assert(child != NULL);
1437 
1438  if (parent == rofi_theme && g_strcmp0(child->name, "*") == 0) {
1440  return;
1441  }
1442 
1443  ThemeWidget *w = rofi_theme_find_or_create_name(parent, child->name);
1444  if (child->media) {
1445  w->media = g_slice_new0(ThemeMedia);
1446  *(w->media) = *(child->media);
1447  }
1449  for (unsigned int i = 0; i < child->num_widgets; i++) {
1451  }
1452 }
1453 
1455  ThemeWidget *rwidget) {
1456  if (rwidget == NULL) {
1457  return;
1458  }
1459  unsigned int i = 0;
1460  // for (unsigned int i = 0; i < rwidget->num_widgets; i++) {
1461  while (i < rwidget->num_widgets) {
1462  ThemeWidget *widget = rwidget->widgets[i];
1463  if (widget->media != NULL) {
1464  rwidget->num_widgets--;
1465  for (unsigned x = i; x < rwidget->num_widgets; x++) {
1466  rwidget->widgets[x] = rwidget->widgets[x + 1];
1467  }
1468  rwidget->widgets[rwidget->num_widgets] = NULL;
1469  switch (widget->media->type) {
1471  int w = widget->media->value;
1472  if (mon.w >= w) {
1473  for (unsigned int x = 0; x < widget->num_widgets; x++) {
1474  rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1475  }
1476  }
1477  break;
1478  }
1480  int w = widget->media->value;
1481  if (mon.w < w) {
1482  for (unsigned int x = 0; x < widget->num_widgets; x++) {
1483  rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1484  }
1485  }
1486  break;
1487  }
1489  int h = widget->media->value;
1490  if (mon.h >= h) {
1491  for (unsigned int x = 0; x < widget->num_widgets; x++) {
1492  rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1493  }
1494  } else {
1495  }
1496  break;
1497  }
1499  int h = widget->media->value;
1500  if (mon.h < h) {
1501  for (unsigned int x = 0; x < widget->num_widgets; x++) {
1502  rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1503  }
1504  }
1505  break;
1506  }
1507  case THEME_MEDIA_TYPE_MON_ID: {
1508  if (mon.monitor_id == widget->media->value) {
1509  for (unsigned int x = 0; x < widget->num_widgets; x++) {
1510  rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1511  }
1512  }
1513  break;
1514  }
1516  double r = widget->media->value;
1517  if ((mon.w / (double)mon.h) >= r) {
1518  for (unsigned int x = 0; x < widget->num_widgets; x++) {
1519  rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1520  }
1521  }
1522  break;
1523  }
1525  double r = widget->media->value;
1526  if ((mon.w / (double)mon.h) < r) {
1527  for (unsigned int x = 0; x < widget->num_widgets; x++) {
1528  rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1529  }
1530  }
1531  break;
1532  }
1533  default: {
1534  break;
1535  }
1536  }
1538  // endif
1539  } else {
1541  i++;
1542  }
1543  }
1544 }
1546  workarea mon;
1547  monitor_active(&mon);
1549 }
1550 
1552  if (g_strcmp0(type, "monitor-id") == 0) {
1553  return THEME_MEDIA_TYPE_MON_ID;
1554  }
1555  if (g_strcmp0(type, "min-width") == 0) {
1557  }
1558  if (g_strcmp0(type, "min-height") == 0) {
1560  }
1561  if (g_strcmp0(type, "max-width") == 0) {
1563  }
1564  if (g_strcmp0(type, "max-height") == 0) {
1566  }
1567  if (g_strcmp0(type, "min-aspect-ratio") == 0) {
1569  }
1570  if (g_strcmp0(type, "max-aspect-ratio") == 0) {
1572  }
1573  return THEME_MEDIA_TYPE_INVALID;
1574 }
1575 
1577  const widget *widget,
1578  const char *property) {
1579  if (p) {
1580  if (p->type == P_INHERIT) {
1581  if (widget->parent) {
1582  ThemeWidget *parent =
1584  Property *pp =
1585  rofi_theme_find_property(parent, P_STRING, property, FALSE);
1586  return rofi_theme_has_property_inside(pp, widget->parent, property);
1587  }
1588  return FALSE;
1589  }
1590  return TRUE;
1591  }
1592  return FALSE;
1593 }
1594 gboolean rofi_theme_has_property(const widget *widget, const char *property) {
1596  Property *p = rofi_theme_find_property(wid, P_STRING, property, FALSE);
1597  return rofi_theme_has_property_inside(p, widget, property);
1598 }
@ WL_CENTER
Definition: rofi-types.h:233
@ WL_SOUTH
Definition: rofi-types.h:239
@ WL_WEST
Definition: rofi-types.h:241
@ WL_NORTH
Definition: rofi-types.h:235
@ WL_EAST
Definition: rofi-types.h:237
const unsigned int num_CSSColors
Definition: css-colors.c:152
const CSSColor CSSColors[]
Definition: css-colors.c:2
char * rofi_expand_path(const char *input)
Definition: helper.c:717
uint32_t rofi_icon_fetcher_query_advanced(const char *name, const int wsize, const int hsize)
cairo_surface_t * rofi_icon_fetcher_get(const uint32_t uid)
#define color_reset
Definition: rofi.h:95
#define color_bold
Definition: rofi.h:97
void rofi_add_error_message(GString *str)
Definition: rofi.c:89
double textbox_get_estimated_char_height(void)
Definition: textbox.c:914
double textbox_get_estimated_ch(void)
Definition: textbox.c:928
void rofi_view_get_current_monitor(int *width, int *height)
Definition: view.c:139
struct _widget widget
Definition: widget.h:51
const char *const PropertyTypeName[P_NUM_TYPES]
Definition: rofi-types.c:6
@ ROFI_IMAGE_URL
Definition: rofi-types.h:168
@ ROFI_IMAGE_LINEAR_GRADIENT
Definition: rofi-types.h:168
@ ROFI_DIRECTION_LEFT
Definition: rofi-types.h:171
@ ROFI_DIRECTION_RIGHT
Definition: rofi-types.h:172
@ ROFI_DIRECTION_BOTTOM
Definition: rofi-types.h:174
@ ROFI_DIRECTION_TOP
Definition: rofi-types.h:173
@ ROFI_DIRECTION_ANGLE
Definition: rofi-types.h:175
PropertyType
Definition: rofi-types.h:10
@ P_INTEGER
Definition: rofi-types.h:12
@ P_INHERIT
Definition: rofi-types.h:40
@ P_HIGHLIGHT
Definition: rofi-types.h:32
@ P_LINK
Definition: rofi-types.h:28
@ P_IMAGE
Definition: rofi-types.h:24
@ P_PADDING
Definition: rofi-types.h:26
@ P_LIST
Definition: rofi-types.h:34
@ P_BOOLEAN
Definition: rofi-types.h:20
@ P_COLOR
Definition: rofi-types.h:22
@ P_CURSOR
Definition: rofi-types.h:38
@ P_DOUBLE
Definition: rofi-types.h:14
@ P_ORIENTATION
Definition: rofi-types.h:36
@ P_STRING
Definition: rofi-types.h:16
@ P_POSITION
Definition: rofi-types.h:30
@ ROFI_PU_EM
Definition: rofi-types.h:86
@ ROFI_PU_CH
Definition: rofi-types.h:90
@ ROFI_PU_PX
Definition: rofi-types.h:82
@ ROFI_PU_MM
Definition: rofi-types.h:84
@ ROFI_PU_PERCENT
Definition: rofi-types.h:88
RofiOrientation
Definition: rofi-types.h:137
@ ROFI_ORIENTATION_HORIZONTAL
Definition: rofi-types.h:139
@ ROFI_ORIENTATION_VERTICAL
Definition: rofi-types.h:138
@ ROFI_DISTANCE_MODIFIER_GROUP
Definition: rofi-types.h:103
@ ROFI_DISTANCE_MODIFIER_CEIL
Definition: rofi-types.h:108
@ ROFI_DISTANCE_MODIFIER_SUBTRACT
Definition: rofi-types.h:99
@ ROFI_DISTANCE_MODIFIER_MODULO
Definition: rofi-types.h:102
@ ROFI_DISTANCE_MODIFIER_FLOOR
Definition: rofi-types.h:107
@ ROFI_DISTANCE_MODIFIER_ROUND
Definition: rofi-types.h:106
@ ROFI_DISTANCE_MODIFIER_MULTIPLY
Definition: rofi-types.h:101
@ ROFI_DISTANCE_MODIFIER_MAX
Definition: rofi-types.h:105
@ ROFI_DISTANCE_MODIFIER_MIN
Definition: rofi-types.h:104
@ ROFI_DISTANCE_MODIFIER_DIVIDE
Definition: rofi-types.h:100
@ ROFI_DISTANCE_MODIFIER_ADD
Definition: rofi-types.h:98
@ ROFI_DISTANCE_MODIFIER_NONE
Definition: rofi-types.h:97
@ ROFI_HL_SOLID
Definition: rofi-types.h:72
@ ROFI_HL_DASH
Definition: rofi-types.h:74
@ ROFI_SCALE_HEIGHT
Definition: rofi-types.h:181
@ ROFI_SCALE_NONE
Definition: rofi-types.h:179
@ ROFI_SCALE_BOTH
Definition: rofi-types.h:180
@ ROFI_SCALE_WIDTH
Definition: rofi-types.h:182
RofiCursorType
Definition: rofi-types.h:145
@ ROFI_HL_STRIKETHROUGH
Definition: rofi-types.h:60
@ ROFI_HL_NONE
Definition: rofi-types.h:54
@ ROFI_HL_ITALIC
Definition: rofi-types.h:64
@ ROFI_HL_UNDERLINE
Definition: rofi-types.h:58
@ ROFI_HL_BOLD
Definition: rofi-types.h:56
@ ROFI_HL_COLOR
Definition: rofi-types.h:66
Settings config
PropertyValue value
Definition: rofi-types.h:293
PropertyType type
Definition: rofi-types.h:291
char * name
Definition: rofi-types.h:289
RofiDistanceModifier modtype
Definition: rofi-types.h:118
RofiPixelUnit type
Definition: rofi-types.h:115
struct RofiDistanceUnit * right
Definition: rofi-types.h:124
struct RofiDistanceUnit * left
Definition: rofi-types.h:121
RofiDistanceUnit base
Definition: rofi-types.h:129
RofiLineStyle style
Definition: rofi-types.h:131
RofiHighlightStyle style
Definition: rofi-types.h:217
RofiDirection dir
Definition: rofi-types.h:192
RofiImageType type
Definition: rofi-types.h:186
double angle
Definition: rofi-types.h:193
uint32_t surface_id
Definition: rofi-types.h:198
char * url
Definition: rofi-types.h:187
RofiScaleType scaling
Definition: rofi-types.h:188
GList * colors
Definition: rofi-types.h:195
RofiDistance bottom
Definition: rofi-types.h:208
RofiDistance top
Definition: rofi-types.h:206
RofiDistance right
Definition: rofi-types.h:207
RofiDistance left
Definition: rofi-types.h:209
int dpi
Definition: settings.h:141
double blue
Definition: rofi-types.h:160
double green
Definition: rofi-types.h:158
double red
Definition: rofi-types.h:156
double alpha
Definition: rofi-types.h:162
struct ThemeWidget ** widgets
Definition: theme.h:73
struct ThemeWidget * parent
Definition: theme.h:79
ThemeMedia * media
Definition: theme.h:75
unsigned int num_widgets
Definition: theme.h:72
char * name
Definition: theme.h:70
GHashTable * properties
Definition: theme.h:77
const char * state
char * name
struct _widget * parent
WidgetType type
Definition: xcb.h:94
int w
Definition: xcb.h:104
int monitor_id
Definition: xcb.h:96
int h
Definition: xcb.h:106
RofiPadding rofi_theme_get_padding(const widget *widget, const char *property, RofiPadding pad)
Definition: theme.c:1201
gboolean rofi_theme_get_image(const widget *widget, const char *property, cairo_t *d)
Definition: theme.c:1166
void rofi_theme_free_parsed_files(void)
Definition: theme.c:51
GList * parsed_config_files
Definition: theme.c:49
static void rofi_theme_print_property_index(size_t pnl, int depth, Property *p)
Definition: theme.c:504
const char *const RofiCursorTypeStr[3]
Definition: theme.c:348
static RofiDistanceUnit * rofi_theme_property_copy_distance_unit(RofiDistanceUnit *unit)
Definition: theme.c:100
static int distance_unit_get_pixel(RofiDistanceUnit *unit, RofiOrientation ori)
Definition: theme.c:1341
GList * rofi_theme_get_list_distance(const widget *widget, const char *property)
Definition: theme.c:1227
static void int_rofi_theme_print_property(Property *p)
Definition: theme.c:354
GList * rofi_theme_get_list_strings(const widget *widget, const char *property)
Definition: theme.c:1255
void rofi_theme_print_parsed_files(gboolean is_term)
Definition: theme.c:56
Property * rofi_theme_property_copy(const Property *p)
Definition: theme.c:123
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition: theme.c:865
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
Definition: theme.c:766
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition: theme.c:891
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition: theme.c:1403
FILE * yyin
static RofiHighlightColorStyle rofi_theme_get_highlight_inside(Property *p, widget *widget, const char *property, RofiHighlightColorStyle th)
Definition: theme.c:1274
Property * rofi_theme_find_property(ThemeWidget *widget, PropertyType type, const char *property, gboolean exact)
Definition: theme.c:728
RofiCursorType rofi_theme_get_cursor_type(const widget *widget, const char *property, RofiCursorType def)
Definition: theme.c:950
void yylex_destroy(void)
ThemeWidget * rofi_theme_find_widget(const char *name, const char *state, gboolean exact)
Definition: theme.c:774
static int rofi_theme_get_integer_inside(Property *p, const widget *widget, const char *property, int def)
Definition: theme.c:809
static RofiDistance rofi_theme_get_distance_inside(Property *p, const widget *widget, const char *property, int def)
Definition: theme.c:834
static gboolean distance_compare(RofiDistance d, RofiDistance e)
Definition: theme.c:67
static void rofi_theme_get_color_inside(const widget *widget, Property *p, const char *property, cairo_t *d)
Definition: theme.c:1034
void rofi_theme_parse_process_conditionals(void)
Definition: theme.c:1545
void rofi_theme_get_color(const widget *widget, const char *property, cairo_t *d)
Definition: theme.c:1055
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
Definition: theme.c:1308
static RofiCursorType rofi_theme_get_cursor_type_inside(Property *p, const widget *widget, const char *property, RofiCursorType def)
Definition: theme.c:928
static void rofi_theme_print_distance_unit(RofiDistanceUnit *unit)
Definition: theme.c:259
static void rofi_theme_copy_property_int(G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data)
Definition: theme.c:633
static void rofi_theme_distance_property_free(RofiDistance *distance)
Definition: theme.c:183
RofiOrientation rofi_theme_get_orientation(const widget *widget, const char *property, RofiOrientation def)
Definition: theme.c:920
static int get_pixels(RofiDistanceUnit *unit, RofiOrientation ori)
Definition: theme.c:1318
Property * rofi_theme_property_create(PropertyType type)
Definition: theme.c:93
char * rofi_theme_parse_prepare_file(const char *file, const char *parent_file)
Definition: theme.c:1416
ThemeMediaType rofi_theme_parse_media_type(const char *type)
Definition: theme.c:1551
void rofi_theme_widget_add_properties(ThemeWidget *widget, GHashTable *table)
Definition: theme.c:639
static double rofi_theme_get_double_inside(const widget *orig, Property *p, const widget *widget, const char *property, double def)
Definition: theme.c:1007
static RofiOrientation rofi_theme_get_orientation_inside(Property *p, const widget *widget, const char *property, RofiOrientation def)
Definition: theme.c:898
double rofi_theme_get_double(const widget *widget, const char *property, double def)
Definition: theme.c:1028
static void rofi_theme_print_distance(RofiDistance d)
Definition: theme.c:335
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition: theme.c:828
void rofi_theme_print(ThemeWidget *widget)
Definition: theme.c:573
static gboolean rofi_theme_has_property_inside(Property *p, const widget *widget, const char *property)
Definition: theme.c:1576
static void printf_double(double d)
Definition: theme.c:253
gboolean rofi_theme_has_property(const widget *widget, const char *property)
Definition: theme.c:1594
void rofi_theme_reset(void)
Definition: theme.c:225
static int rofi_theme_get_position_inside(Property *p, const widget *widget, const char *property, int def)
Definition: theme.c:783
void rofi_theme_parse_merge_widgets(ThemeWidget *parent, ThemeWidget *child)
Definition: theme.c:1434
static void rofi_theme_distance_unit_property_free(RofiDistanceUnit *unit)
Definition: theme.c:172
static void rofi_theme_print_color(ThemeColor color)
Definition: theme.c:314
static ThemeWidget * rofi_theme_find_single(ThemeWidget *widget, const char *name)
Definition: theme.c:655
int yyparse()
int rofi_theme_get_position(const widget *widget, const char *property, int def)
Definition: theme.c:803
static void rofi_theme_resolve_link_property(Property *p, int depth)
Definition: theme.c:691
static void rofi_theme_parse_process_conditionals_int(workarea mon, ThemeWidget *rwidget)
Definition: theme.c:1454
void rofi_theme_print_index(ThemeWidget *widget, int index)
Definition: theme.c:513
void rofi_theme_free(ThemeWidget *widget)
Definition: theme.c:231
static const char * rofi_theme_get_string_inside(Property *p, const widget *widget, const char *property, const char *def)
Definition: theme.c:957
static GList * rofi_theme_get_list_inside(Property *p, const widget *widget, const char *property, PropertyType child_type)
Definition: theme.c:1208
ThemeWidget * rofi_theme_find_or_create_name(ThemeWidget *base, const char *name)
Definition: theme.c:73
static ThemeWidget * rofi_theme_find(ThemeWidget *widget, const char *name, const gboolean exact)
Definition: theme.c:665
static int rofi_theme_get_boolean_inside(Property *p, const widget *widget, const char *property, int def)
Definition: theme.c:872
void yyerror(YYLTYPE *yylloc, const char *, const char *)
Definition: theme.c:603
RofiDistance rofi_theme_property_copy_distance(RofiDistance const distance)
Definition: theme.c:111
void rofi_theme_property_free(Property *p)
Definition: theme.c:194
static RofiPadding rofi_theme_get_padding_inside(Property *p, const widget *widget, const char *property, RofiPadding pad)
Definition: theme.c:1172
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
Definition: theme.c:978
static gboolean rofi_theme_get_image_inside(Property *p, const widget *widget, const char *property, cairo_t *d)
Definition: theme.c:1062
void distance_get_linestyle(RofiDistance d, cairo_t *draw)
Definition: theme.c:1407
static double rofi_theme_get_double_integer_fb_inside(Property *p, const widget *widget, const char *property, double def)
Definition: theme.c:985
ThemeMediaType
Definition: theme.h:38
@ THEME_MEDIA_TYPE_MAX_HEIGHT
Definition: theme.h:46
@ THEME_MEDIA_TYPE_MON_ID
Definition: theme.h:48
@ THEME_MEDIA_TYPE_INVALID
Definition: theme.h:54
@ THEME_MEDIA_TYPE_MIN_WIDTH
Definition: theme.h:40
@ THEME_MEDIA_TYPE_MIN_ASPECT_RATIO
Definition: theme.h:50
@ THEME_MEDIA_TYPE_MAX_ASPECT_RATIO
Definition: theme.h:52
@ THEME_MEDIA_TYPE_MAX_WIDTH
Definition: theme.h:42
@ THEME_MEDIA_TYPE_MIN_HEIGHT
Definition: theme.h:44
ThemeWidget * rofi_theme
Definition: theme.h:90
struct _PropertyValue::@6 link
ThemeColor color
Definition: rofi-types.h:264
struct Property * ref
Definition: rofi-types.h:272
RofiHighlightColorStyle highlight
Definition: rofi-types.h:277
struct Property * def_value
Definition: rofi-types.h:274
GList * list
Definition: rofi-types.h:281
RofiImage image
Definition: rofi-types.h:279
gboolean b
Definition: rofi-types.h:262
RofiPadding padding
Definition: rofi-types.h:266
workarea mon
Definition: view.c:111
int monitor_active(workarea *mon)
Definition: xcb.c:973
xcb_depth_t * depth
Definition: xcb.c:96
ThemeWidget * rofi_configuration
Definition: xrmoptions.c:46