rofi 1.7.5
theme.c
Go to the documentation of this file.
1/*
2 * rofi
3 *
4 * MIT/X11 License
5 * Copyright © 2013-2022 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
49GList *parsed_config_files = NULL;
50
52 g_list_free_full(parsed_config_files, g_free);
54}
55
56void 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
66void 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
99static 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
124 G_GNUC_UNUSED void *data) {
126 retv->name = g_strdup(p->name);
127
128 switch (p->type) {
129 case P_STRING:
130 retv->value.s = g_strdup(p->value.s);
131 break;
132 case P_LIST:
133 retv->value.list = g_list_copy_deep(
134 p->value.list, (GCopyFunc)rofi_theme_property_copy, NULL);
135 break;
136 case P_LINK:
137 retv->value.link.name = g_strdup(p->value.link.name);
138 retv->value.link.ref = NULL;
139 if (p->value.link.def_value) {
140 retv->value.link.def_value =
142 }
143 break;
144 case P_PADDING: {
145 retv->value = p->value;
146 retv->value.padding.top =
148 retv->value.padding.left =
150 retv->value.padding.bottom =
152 retv->value.padding.right =
154 break;
155 }
156 case P_IMAGE: {
157 retv->value = p->value;
158 retv->value.image.url = g_strdup(p->value.image.url);
159 retv->value.image.colors = NULL;
160 for (GList *l = g_list_first(p->value.image.colors); l;
161 l = g_list_next(l)) {
162 retv->value.image.colors = g_list_append(
163 retv->value.image.colors, g_memdup(l->data, sizeof(ThemeColor)));
164 }
165 break;
166 }
167 default:
168 retv->value = p->value;
169 }
170 return retv;
171}
172
174 if (unit->left) {
176 unit->left = NULL;
177 }
178 if (unit->right) {
180 unit->right = NULL;
181 }
182 g_slice_free(RofiDistanceUnit, unit);
183}
185 if (distance->base.left) {
187 distance->base.left = NULL;
188 }
189 if (distance->base.right) {
191 distance->base.right = NULL;
192 }
193}
194
196 if (p == NULL) {
197 return;
198 }
199 g_free(p->name);
200 if (p->type == P_STRING) {
201 g_free(p->value.s);
202 } else if (p->type == P_LIST) {
203 g_list_free_full(p->value.list, (GDestroyNotify)rofi_theme_property_free);
204 p->value.list = 0;
205 } else if (p->type == P_LINK) {
206 g_free(p->value.link.name);
207 if (p->value.link.def_value) {
209 }
210 } else if (p->type == P_PADDING) {
215 } else if (p->type == P_IMAGE) {
216 if (p->value.image.url) {
217 g_free(p->value.image.url);
218 }
219 if (p->value.image.colors) {
220 g_list_free_full(p->value.image.colors, g_free);
221 }
222 }
223 g_slice_free(Property, p);
224}
225
228 rofi_theme = g_slice_new0(ThemeWidget);
229 rofi_theme->name = g_strdup("Root");
230}
231
233 if (widget == NULL) {
234 return;
235 }
236 if (widget->properties) {
237 g_hash_table_destroy(widget->properties);
238 widget->properties = NULL;
239 }
240 if (widget->media) {
241 g_slice_free(ThemeMedia, widget->media);
242 }
243 for (unsigned int i = 0; i < widget->num_widgets; i++) {
244 rofi_theme_free(widget->widgets[i]);
245 }
246 g_free(widget->widgets);
247 g_free(widget->name);
248 g_slice_free(ThemeWidget, widget);
249}
250
254inline static void printf_double(double d) {
255 char buf[G_ASCII_DTOSTR_BUF_SIZE + 1] = {
256 0,
257 };
258 g_ascii_formatd(buf, G_ASCII_DTOSTR_BUF_SIZE, "%.4f", d);
259 fputs(buf, stdout);
260}
261
264 fputs("( ", stdout);
265 }
266 if (unit->left) {
268 }
269
270 if (unit->modtype == ROFI_DISTANCE_MODIFIER_ADD) {
271 fputs(" + ", stdout);
272 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_SUBTRACT) {
273 fputs(" - ", stdout);
274 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_DIVIDE) {
275 fputs(" / ", stdout);
276 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MULTIPLY) {
277 fputs(" * ", stdout);
278 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MODULO) {
279 fputs(" % ", stdout);
280 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MIN) {
281 fputs(" min ", stdout);
282 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_MAX) {
283 fputs(" max ", stdout);
284 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_ROUND) {
285 fputs(" round ", stdout);
286 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_FLOOR) {
287 fputs(" floor ", stdout);
288 } else if (unit->modtype == ROFI_DISTANCE_MODIFIER_CEIL) {
289 fputs(" ceil ", stdout);
290 }
291 if (unit->right) {
293 }
294
296 if (unit->type == ROFI_PU_PX) {
297 printf("%upx ", (unsigned int)unit->distance);
298 } else if (unit->type == ROFI_PU_MM) {
299 printf_double(unit->distance);
300 fputs("mm ", stdout);
301 } else if (unit->type == ROFI_PU_PERCENT) {
302 printf_double(unit->distance);
303 fputs("% ", stdout);
304 } else if (unit->type == ROFI_PU_CH) {
305 printf_double(unit->distance);
306 fputs("ch ", stdout);
307 } else {
308 printf_double(unit->distance);
309 fputs("em ", stdout);
310 }
311 }
313 fputs(" )", stdout);
314 }
315}
316
318 uint8_t r, g, b;
319 g = 255 * color.green;
320 r = 255 * color.red;
321 b = 255 * color.blue;
322 if (color.alpha < 0.00001) {
323 printf("transparent");
324 return;
325 }
326 for (uint32_t x = 0; x < num_CSSColors; x++) {
327 if (CSSColors[x].r == r && CSSColors[x].g == g && CSSColors[x].b == b) {
328 printf("%s", CSSColors[x].name);
329 if (color.alpha < 1) {
330 printf("/%.0f%%", color.alpha * 100.0);
331 }
332 return;
333 }
334 }
335 printf("rgba ( %.0f, %.0f, %.0f, %.0f %% )", (color.red * 255.0),
336 (color.green * 255.0), (color.blue * 255.0), (color.alpha * 100.0));
337}
340 fputs("calc( ", stdout);
341 }
344 fputs(")", stdout);
345 }
346 if (d.style == ROFI_HL_DASH) {
347 printf("dash ");
348 }
349}
351const char *const RofiCursorTypeStr[3] = {
352 "default",
353 "pointer",
354 "text",
355};
356
358 switch (p->type) {
359 case P_LIST:
360 printf("[ ");
361 for (GList *iter = p->value.list; iter != NULL; iter = g_list_next(iter)) {
363 if (iter->next != NULL) {
364 printf(",");
365 }
366 }
367 printf(" ]");
368 break;
369 case P_ORIENTATION:
370 printf("%s", (p->value.i == ROFI_ORIENTATION_HORIZONTAL) ? "horizontal"
371 : "vertical");
372 break;
373 case P_CURSOR:
374 printf("%s", RofiCursorTypeStr[p->value.i]);
375 break;
376 case P_HIGHLIGHT:
378 printf("bold ");
379 }
381 printf("underline ");
382 }
384 printf("strikethrough ");
385 }
387 printf("italic ");
388 }
390 printf("uppercase ");
391 }
393 printf("lowercase ");
394 }
396 printf("capitalize ");
397 }
400 }
401 break;
402 case P_POSITION: {
403 switch (p->value.i) {
404 case WL_CENTER:
405 fputs("center", stdout);
406 break;
407 case WL_NORTH:
408 fputs("north", stdout);
409 break;
410 case WL_SOUTH:
411 fputs("south", stdout);
412 break;
413 case WL_WEST:
414 fputs("west", stdout);
415 break;
416 case WL_EAST:
417 fputs("east", stdout);
418 break;
419 case WL_NORTH | WL_EAST:
420 fputs("northeast", stdout);
421 break;
422 case WL_SOUTH | WL_EAST:
423 fputs("southeast", stdout);
424 break;
425 case WL_NORTH | WL_WEST:
426 fputs("northwest", stdout);
427 break;
428 case WL_SOUTH | WL_WEST:
429 fputs("southwest", stdout);
430 break;
431 }
432 break;
433 }
434 case P_STRING:
435 printf("\"%s\"", p->value.s);
436 break;
437 case P_INTEGER:
438 printf("%d", p->value.i);
439 break;
440 case P_DOUBLE: {
441 char sign = (p->value.f < 0);
442 int top = (int)fabs(p->value.f);
443 int bottom = (fabs(fmod(p->value.f, 1.0))) * 100;
444 printf("%s%d.%02d", sign ? "-" : "", top, bottom);
445 break;
446 }
447 case P_BOOLEAN:
448 printf("%s", p->value.b ? "true" : "false");
449 break;
450 case P_COLOR:
452 break;
453 case P_IMAGE: {
454 if (p->value.image.type == ROFI_IMAGE_URL) {
455 printf("url (\"%s\")", p->value.s);
456 } else if (p->value.image.type == ROFI_IMAGE_LINEAR_GRADIENT) {
457 printf("linear-gradient ( ");
458 guint length = g_list_length(p->value.image.colors);
459 guint index = 0;
460 for (GList *l = g_list_first(p->value.image.colors); l != NULL;
461 l = g_list_next(l)) {
462 ThemeColor *color = (ThemeColor *)l->data;
464 index++;
465 if (index < length) {
466 printf(", ");
467 }
468 }
469 printf(")");
470 }
471
472 break;
473 }
474 case P_PADDING:
479 } else if (distance_compare(p->value.padding.top,
480 p->value.padding.bottom) &&
482 p->value.padding.right)) {
485 } else if (!distance_compare(p->value.padding.top,
486 p->value.padding.bottom) &&
488 p->value.padding.right)) {
492 } else {
497 }
498 break;
499 case P_LINK:
500 if (p->value.link.def_value) {
501 printf("var( %s, ", p->value.link.name);
503 printf(")");
504 } else {
505 printf("var(%s)", p->value.link.name);
506 }
507 break;
508 case P_INHERIT:
509 printf("inherit");
510 break;
511 default:
512 break;
513 }
514}
515
516static void rofi_theme_print_property_index(size_t pnl, int depth,
517 Property *p) {
518 int pl = strlen(p->name);
519 printf("%*s%s:%*s ", depth, "", p->name, (int)pnl - pl, "");
521 putchar(';');
522 putchar('\n');
523}
524
526 GHashTableIter iter;
527 gpointer key, value;
528
529 if (widget->media) {
530 printf("%s {\n", widget->name);
531 for (unsigned int i = 0; i < widget->num_widgets; i++) {
532 rofi_theme_print_index(widget->widgets[i], index + 4);
533 }
534 printf("}\n");
535 } else {
536 if (widget->properties) {
537 GList *list = NULL;
538 ThemeWidget *w = widget;
539 while (w) {
540 if (g_strcmp0(w->name, "Root") == 0) {
541 break;
542 }
543 if (w->media) {
544 break;
545 }
546 list = g_list_prepend(list, w->name);
547 w = w->parent;
548 }
549 if (g_list_length(list) > 0) {
550 printf("%*s", index, "");
551 for (GList *citer = g_list_first(list); citer != NULL;
552 citer = g_list_next(citer)) {
553 char *name = (char *)citer->data;
554 fputs(name, stdout);
555 if (citer->prev == NULL && citer->next) {
556 putchar(' ');
557 } else if (citer->next) {
558 putchar('.');
559 }
560 }
561 printf(" {\n");
562 } else {
563 printf("%*s* {\n", index, "");
564 }
565 size_t property_name_length = 0;
566 g_hash_table_iter_init(&iter, widget->properties);
567 while (g_hash_table_iter_next(&iter, &key, &value)) {
568 Property *pv = (Property *)value;
569 property_name_length = MAX(strlen(pv->name), property_name_length);
570 }
571 g_hash_table_iter_init(&iter, widget->properties);
572 while (g_hash_table_iter_next(&iter, &key, &value)) {
573 Property *pv = (Property *)value;
574 rofi_theme_print_property_index(property_name_length, index + 4, pv);
575 }
576 printf("%*s}\n", index, "");
577 g_list_free(list);
578 }
579 for (unsigned int i = 0; i < widget->num_widgets; i++) {
580 rofi_theme_print_index(widget->widgets[i], index);
581 }
582 }
583}
584
586 if (widget != NULL) {
587 printf("/**\n * rofi -dump-theme output.\n * Rofi version: %s\n **/\n",
588 PACKAGE_VERSION);
590 }
591}
592
597
601void yylex_destroy(void);
602
606extern FILE *yyin;
607
615void yyerror(YYLTYPE *yylloc, const char *what, const char *s) {
616 char *what_esc = what ? g_markup_escape_text(what, -1) : g_strdup("");
617 GString *str = g_string_new("");
618 g_string_printf(str,
619 "<big><b>Error while parsing theme:</b></big> <i>%s</i>\n",
620 what_esc);
621 g_free(what_esc);
622 char *esc = g_markup_escape_text(s, -1);
623 g_string_append_printf(
624 str,
625 "\tParser error: <span size=\"smaller\" style=\"italic\">%s</span>\n",
626 esc);
627 g_free(esc);
628 if (yylloc->filename != NULL) {
629 g_string_append_printf(
630 str,
631 "\tLocation: line %d column %d to line %d column %d.\n"
632 "\tFile '%s'\n",
633 yylloc->first_line, yylloc->first_column, yylloc->last_line,
634 yylloc->last_column, yylloc->filename);
635 } else {
636 g_string_append_printf(
637 str, "\tLocation: line %d column %d to line %d column %d\n",
638 yylloc->first_line, yylloc->first_column, yylloc->last_line,
639 yylloc->last_column);
640 }
641 g_log("Parser", G_LOG_LEVEL_DEBUG, "Failed to parse theme:\n%s", str->str);
643}
644
645static void rofi_theme_copy_property_int(G_GNUC_UNUSED gpointer key,
646 gpointer value, gpointer user_data) {
647 GHashTable *table = (GHashTable *)user_data;
648 Property *p = rofi_theme_property_copy((Property *)value, NULL);
649 g_hash_table_replace(table, p->name, p);
650}
652 if (table == NULL) {
653 return;
654 }
655 if (widget->properties == NULL) {
656 widget->properties =
657 g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
658 (GDestroyNotify)rofi_theme_property_free);
659 }
660 g_hash_table_foreach(table, rofi_theme_copy_property_int, widget->properties);
661}
662
668 const char *name) {
669 for (unsigned int j = 0; widget && j < widget->num_widgets; j++) {
670 if (g_strcmp0(widget->widgets[j]->name, name) == 0) {
671 return widget->widgets[j];
672 }
673 }
674 return widget;
675}
676
678 const gboolean exact) {
679 if (widget == NULL || name == NULL) {
680 return widget;
681 }
682 char *tname = g_strdup(name);
683 char *saveptr = NULL;
684 int found = TRUE;
685 for (const char *iter = strtok_r(tname, ".", &saveptr); iter != NULL;
686 iter = strtok_r(NULL, ".", &saveptr)) {
687 found = FALSE;
689 if (f != widget) {
690 widget = f;
691 found = TRUE;
692 } else if (exact) {
693 break;
694 }
695 }
696 g_free(tname);
697 if (!exact || found) {
698 return widget;
699 }
700 return NULL;
701}
702
704 // Set name, remove '@' prefix.
705 const char *name = p->value.link.name; // + (*(p->value.link.name)== '@'?1:0;
706 g_info("Resolving link to %s", p->value.link.name);
707 if (depth > 20) {
708 g_warning("Found more then 20 redirects for property. Stopping.");
709 p->value.link.ref = p;
710 return;
711 }
712
713 if (rofi_theme->properties &&
714 g_hash_table_contains(rofi_theme->properties, name)) {
715 Property *pr = g_hash_table_lookup(rofi_theme->properties, name);
716 g_info("Resolving link %s found: %s", p->value.link.name, pr->name);
717 if (pr->type == P_LINK) {
718 if (pr->value.link.ref == NULL) {
720 }
721 if (pr->value.link.ref != pr) {
722 p->value.link.ref = pr->value.link.ref;
723 return;
724 }
725 } else {
726 p->value.link.ref = pr;
727 return;
728 }
729 }
730 // No found and we have default value.
731 if (p->value.link.def_value) {
733 return;
734 }
735
736 // No found, set ref to self.
737 p->value.link.ref = p;
738}
739
741 const char *property, gboolean exact) {
742 while (widget) {
743 if (widget->properties &&
744 g_hash_table_contains(widget->properties, property)) {
745 Property *p = g_hash_table_lookup(widget->properties, property);
746 if (p->type == P_INHERIT) {
747 return p;
748 }
749 if (p->type == P_LINK) {
750 if (p->value.link.ref == NULL) {
751 // Resolve link.
753 }
754 if (p->value.link.ref != NULL && p->value.link.ref->type == type) {
755 return p->value.link.ref;
756 }
757 }
758 if (p->type == type) {
759 return p;
760 }
761 // RofiPadding and integer can be converted.
762 if (p->type == P_INTEGER && type == P_PADDING) {
763 return p;
764 }
765 g_debug("Found property: '%s' on '%s', but type %s does not match "
766 "expected type %s.",
767 property, widget->name, PropertyTypeName[p->type],
768 PropertyTypeName[type]);
769 }
770 if (exact) {
771 return NULL;
772 }
773 // Fall back to defaults.
775 }
776 return NULL;
777}
778ThemeWidget *rofi_config_find_widget(const char *name, const char *state,
779 gboolean exact) {
780 // First find exact match based on name.
782 widget = rofi_theme_find(widget, state, exact);
783
784 return widget;
785}
786ThemeWidget *rofi_theme_find_widget(const char *name, const char *state,
787 gboolean exact) {
788 // First find exact match based on name.
790 widget = rofi_theme_find(widget, state, exact);
791
792 return widget;
793}
794
796 const char *property, int def) {
797 if (p) {
798 if (p->type == P_INHERIT) {
799 if (widget->parent) {
800 ThemeWidget *parent =
802 Property *pv =
803 rofi_theme_find_property(parent, P_POSITION, property, FALSE);
804 return rofi_theme_get_position_inside(pv, widget->parent, property,
805 def);
806 }
807 return def;
808 }
809 return p->value.i;
810 }
811 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
812 widget->state ? widget->state : "", property);
813 return def;
814}
815int rofi_theme_get_position(const widget *widget, const char *property,
816 int def) {
818 Property *p = rofi_theme_find_property(wid, P_POSITION, property, FALSE);
819 return rofi_theme_get_position_inside(p, widget, property, def);
820}
822 const char *property, int def) {
823 if (p) {
824 if (p->type == P_INHERIT) {
825 if (widget->parent) {
826 ThemeWidget *parent =
828 Property *pv =
829 rofi_theme_find_property(parent, P_INTEGER, property, FALSE);
830 return rofi_theme_get_integer_inside(pv, widget->parent, property, def);
831 }
832 return def;
833 }
834 return p->value.i;
835 }
836 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
837 widget->state ? widget->state : "", property);
838 return def;
839}
840int rofi_theme_get_integer(const widget *widget, const char *property,
841 int def) {
843 Property *p = rofi_theme_find_property(wid, P_INTEGER, property, FALSE);
844 return (int)rofi_theme_get_integer_inside(p, widget, property, (double)def);
845}
847 const widget *widget,
848 const char *property,
849 int def) {
850 if (p) {
851 if (p->type == P_INHERIT) {
852 if (widget->parent) {
853 ThemeWidget *parent =
855 Property *pv =
856 rofi_theme_find_property(parent, P_PADDING, property, FALSE);
857 return rofi_theme_get_distance_inside(pv, widget->parent, property,
858 def);
859 }
860 return (RofiDistance){
861 .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
862 .style = ROFI_HL_SOLID};
863 }
864 if (p->type == P_INTEGER) {
865 return (RofiDistance){.base = {p->value.i, ROFI_PU_PX,
866 ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
867 .style = ROFI_HL_SOLID};
868 }
869 return p->value.padding.left;
870 }
871 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
872 widget->state ? widget->state : "", property);
873 return (RofiDistance){
874 .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
875 .style = ROFI_HL_SOLID};
876}
878 int def) {
880 Property *p = rofi_theme_find_property(wid, P_PADDING, property, FALSE);
881 return rofi_theme_get_distance_inside(p, widget, property, def);
882}
883
885 const char *property, int def) {
886 if (p) {
887 if (p->type == P_INHERIT) {
888 if (widget->parent) {
889 ThemeWidget *parent =
891 Property *pv =
892 rofi_theme_find_property(parent, P_BOOLEAN, property, FALSE);
893 return rofi_theme_get_boolean_inside(pv, widget->parent, property, def);
894 }
895 return def;
896 }
897 return p->value.b;
898 }
899 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
900 widget->state ? widget->state : "", property);
901 return def;
902}
903int rofi_theme_get_boolean(const widget *widget, const char *property,
904 int def) {
906 Property *p = rofi_theme_find_property(wid, P_BOOLEAN, property, FALSE);
907 return rofi_theme_get_boolean_inside(p, widget, property, def);
908}
909
911 const widget *widget,
912 const char *property,
913 RofiOrientation def) {
914 if (p) {
915 if (p->type == P_INHERIT) {
916 if (widget->parent) {
917 ThemeWidget *parent =
919 Property *pv =
920 rofi_theme_find_property(parent, P_ORIENTATION, property, FALSE);
921 return rofi_theme_get_orientation_inside(pv, widget->parent, property,
922 def);
923 }
924 return def;
925 }
926 return p->value.b;
927 }
928 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
929 widget->state ? widget->state : "", property);
930 return def;
931}
933 const char *property,
934 RofiOrientation def) {
936 Property *p = rofi_theme_find_property(wid, P_ORIENTATION, property, FALSE);
937 return rofi_theme_get_orientation_inside(p, widget, property, def);
938}
939
941 const widget *widget,
942 const char *property,
943 RofiCursorType def) {
944 if (p) {
945 if (p->type == P_INHERIT) {
946 if (widget->parent) {
947 ThemeWidget *parent =
949 Property *pv =
950 rofi_theme_find_property(parent, P_CURSOR, property, FALSE);
951 return rofi_theme_get_cursor_type_inside(pv, widget->parent, property,
952 def);
953 }
954 return def;
955 }
956 return p->value.i;
957 }
958 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
959 widget->state ? widget->state : "", property);
960 return def;
961}
963 const char *property,
964 RofiCursorType def) {
966 Property *p = rofi_theme_find_property(wid, P_CURSOR, property, FALSE);
967 return rofi_theme_get_cursor_type_inside(p, widget, property, def);
968}
970 const widget *widget,
971 const char *property,
972 const char *def) {
973 if (p) {
974 if (p->type == P_INHERIT) {
975 if (widget->parent) {
976 ThemeWidget *parent =
978 Property *pv =
979 rofi_theme_find_property(parent, P_STRING, property, FALSE);
980 return rofi_theme_get_string_inside(pv, widget->parent, property, def);
981 }
982 return def;
983 }
984 return p->value.s;
985 }
986 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
987 widget->state ? widget->state : "", property);
988 return def;
989}
990const char *rofi_theme_get_string(const widget *widget, const char *property,
991 const char *def) {
993 Property *p = rofi_theme_find_property(wid, P_STRING, property, FALSE);
994 return rofi_theme_get_string_inside(p, widget, property, def);
995}
996
998 const widget *widget,
999 const char *property,
1000 double def) {
1001 if (p) {
1002 if (p->type == P_INHERIT) {
1003 if (widget->parent) {
1004 ThemeWidget *parent =
1006 Property *pv =
1007 rofi_theme_find_property(parent, P_INTEGER, property, FALSE);
1009 property, def);
1010 }
1011 return def;
1012 }
1013 return p->value.i;
1014 }
1015 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1016 widget->state ? widget->state : "", property);
1017 return def;
1018}
1019static double rofi_theme_get_double_inside(const widget *orig, Property *p,
1020 const widget *widget,
1021 const char *property, double def) {
1022 if (p) {
1023 if (p->type == P_INHERIT) {
1024 if (widget->parent) {
1025 ThemeWidget *parent =
1027 Property *pv =
1028 rofi_theme_find_property(parent, P_DOUBLE, property, FALSE);
1029 return rofi_theme_get_double_inside(orig, pv, widget, property, def);
1030 }
1031 return def;
1032 }
1033 return p->value.f;
1034 }
1035 ThemeWidget *wid = rofi_theme_find_widget(orig->name, widget->state, FALSE);
1036 // Fallback to integer if double is not found.
1037 p = rofi_theme_find_property(wid, P_INTEGER, property, FALSE);
1038 return rofi_theme_get_double_integer_fb_inside(p, widget, property, def);
1039}
1040double rofi_theme_get_double(const widget *widget, const char *property,
1041 double def) {
1043 Property *p = rofi_theme_find_property(wid, P_DOUBLE, property, FALSE);
1044 return rofi_theme_get_double_inside(widget, p, widget, property, def);
1045}
1047 const char *property, cairo_t *d) {
1048 if (p) {
1049 if (p->type == P_INHERIT) {
1050 if (widget->parent) {
1051 ThemeWidget *parent =
1053 Property *pv =
1054 rofi_theme_find_property(parent, P_COLOR, property, FALSE);
1055 rofi_theme_get_color_inside(widget->parent, pv, property, d);
1056 }
1057 return;
1058 }
1059 cairo_set_source_rgba(d, p->value.color.red, p->value.color.green,
1060 p->value.color.blue, p->value.color.alpha);
1061 } else {
1062 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1063 widget->state ? widget->state : "", property);
1064 }
1065}
1066
1067void rofi_theme_get_color(const widget *widget, const char *property,
1068 cairo_t *d) {
1070 Property *p = rofi_theme_find_property(wid, P_COLOR, property, FALSE);
1071 rofi_theme_get_color_inside(widget, p, property, d);
1072}
1073
1075 const char *property, cairo_t *d) {
1076 if (p) {
1077 if (p->type == P_INHERIT) {
1078 if (widget->parent) {
1079 ThemeWidget *parent =
1081 Property *pv =
1082 rofi_theme_find_property(parent, P_IMAGE, property, FALSE);
1083 return rofi_theme_get_image_inside(pv, widget->parent, property, d);
1084 }
1085 return FALSE;
1086 }
1087 if (p->value.image.type == ROFI_IMAGE_URL) {
1088 int wsize = -1;
1089 int hsize = -1;
1090 switch (p->value.image.scaling) {
1091 case ROFI_SCALE_BOTH:
1092 wsize = widget->w;
1093 hsize = widget->h;
1094 break;
1095 case ROFI_SCALE_WIDTH:
1096 wsize = widget->w;
1097 break;
1098 case ROFI_SCALE_HEIGHT:
1099 hsize = widget->h;
1100 break;
1101 case ROFI_SCALE_NONE:
1102 default:
1103 break;
1104 }
1105 if (p->value.image.surface_id == 0 || p->value.image.wsize != wsize ||
1106 p->value.image.hsize != hsize) {
1109 p->value.image.wsize = wsize;
1110 p->value.image.hsize = hsize;
1111 }
1112 cairo_surface_t *img = rofi_icon_fetcher_get(p->value.image.surface_id);
1113
1114 if (img != NULL) {
1115 cairo_pattern_t *pat = cairo_pattern_create_for_surface(img);
1116 cairo_pattern_set_extend(pat, CAIRO_EXTEND_REPEAT);
1117 cairo_set_source(d, pat);
1118 cairo_pattern_destroy(pat);
1119 return TRUE;
1120 }
1121 } else if (p->value.image.type == ROFI_IMAGE_LINEAR_GRADIENT) {
1122 cairo_pattern_t *pat = NULL;
1123 switch (p->value.image.dir) {
1125 pat = cairo_pattern_create_linear(0.0, 0.0, widget->w, 0.0);
1126 break;
1128 pat = cairo_pattern_create_linear(widget->w, 0.0, 0.0, 0.0);
1129 break;
1131 pat = cairo_pattern_create_linear(0.0, 0.0, 0.0, widget->h);
1132 break;
1133 case ROFI_DIRECTION_TOP:
1134 pat = cairo_pattern_create_linear(0.0, widget->h, 0.0, 0.0);
1135 break;
1136 case ROFI_DIRECTION_ANGLE: {
1137 double offsety1 =
1138 sin(G_PI * 2 * p->value.image.angle) * (widget->h / 2.0);
1139 double offsetx1 =
1140 cos(G_PI * 2 * p->value.image.angle) * (widget->w / 2.0);
1141 pat = cairo_pattern_create_linear(
1142 widget->w / 2.0 - offsetx1, widget->h / 2.0 - offsety1,
1143 widget->w / 2.0 + offsetx1, widget->h / 2.0 + offsety1);
1144 break;
1145 }
1146 };
1147 guint length = g_list_length(p->value.image.colors);
1148 if (length > 1) {
1149 length--;
1150 guint color_index = 0;
1151 for (GList *l = g_list_first(p->value.image.colors); l != NULL;
1152 l = g_list_next(l)) {
1153 ThemeColor *c = (ThemeColor *)(l->data);
1154 cairo_pattern_add_color_stop_rgba(pat, (color_index) / (double)length,
1155 c->red, c->green, c->blue,
1156 c->alpha);
1157 color_index++;
1158 }
1159 cairo_set_source(d, pat);
1160 cairo_pattern_destroy(pat);
1161 return TRUE;
1162 }
1163 if (length == 1) {
1164 ThemeColor *c = (ThemeColor *)(p->value.image.colors->data);
1165 cairo_pattern_add_color_stop_rgba(pat, 0, c->red, c->green, c->blue,
1166 c->alpha);
1167 cairo_set_source(d, pat);
1168 cairo_pattern_destroy(pat);
1169 return TRUE;
1170 }
1171 }
1172 } else {
1173 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1174 widget->state ? widget->state : "", property);
1175 }
1176 return FALSE;
1177}
1178gboolean rofi_theme_get_image(const widget *widget, const char *property,
1179 cairo_t *d) {
1181 Property *p = rofi_theme_find_property(wid, P_IMAGE, property, FALSE);
1182 return rofi_theme_get_image_inside(p, widget, property, d);
1183}
1185 const widget *widget,
1186 const char *property,
1187 RofiPadding pad) {
1188 if (p) {
1189 if (p->type == P_INHERIT) {
1190 if (widget->parent) {
1191 ThemeWidget *parent =
1193 Property *pv =
1194 rofi_theme_find_property(parent, P_PADDING, property, FALSE);
1195 return rofi_theme_get_padding_inside(pv, widget->parent, property, pad);
1196 }
1197 return pad;
1198 }
1199 if (p->type == P_PADDING) {
1200 pad = p->value.padding;
1201 } else {
1202 RofiDistance d =
1204 ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
1205 .style = ROFI_HL_SOLID};
1206 return (RofiPadding){d, d, d, d};
1207 }
1208 }
1209 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1210 widget->state ? widget->state : "", property);
1211 return pad;
1212}
1214 RofiPadding pad) {
1216 Property *p = rofi_theme_find_property(wid, P_PADDING, property, FALSE);
1217 return rofi_theme_get_padding_inside(p, widget, property, pad);
1218}
1219
1221 const char *property,
1222 PropertyType child_type) {
1223 if (p) {
1224 if (p->type == P_INHERIT) {
1225 if (widget->parent) {
1226 ThemeWidget *parent =
1228 Property *pv =
1229 rofi_theme_find_property(parent, P_LIST, property, FALSE);
1230 return rofi_theme_get_list_inside(pv, widget->parent, property,
1231 child_type);
1232 }
1233 } else if (p->type == P_LIST) {
1234 return p->value.list;
1235 }
1236 }
1237 return NULL;
1238}
1240 const char *property) {
1241 ThemeWidget *wid2 =
1243 Property *p = rofi_theme_find_property(wid2, P_LIST, property, FALSE);
1244 GList *list = rofi_theme_get_list_inside(p, widget, property, P_PADDING);
1245 GList *retv = NULL;
1246 for (GList *iter = g_list_first(list); iter != NULL;
1247 iter = g_list_next(iter)) {
1248 Property *prop = (Property *)(iter->data);
1249 if (prop->type == P_PADDING) {
1250 RofiDistance *pnew = g_new0(RofiDistance, 1);
1251 *pnew = prop->value.padding.left;
1252 retv = g_list_append(retv, pnew);
1253 } else if (prop->type == P_INTEGER) {
1254 RofiDistance *pnew = g_new0(RofiDistance, 1);
1255 RofiDistance d =
1256 (RofiDistance){.base = {prop->value.i, ROFI_PU_PX,
1257 ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL},
1258 .style = ROFI_HL_SOLID};
1259 *pnew = d;
1260 retv = g_list_append(retv, pnew);
1261 } else {
1262 g_warning("Invalid type detected in list.");
1263 }
1264 }
1265 return retv;
1266}
1267GList *rofi_theme_get_list_strings(const widget *widget, const char *property) {
1268 ThemeWidget *wid2 =
1270 Property *p = rofi_theme_find_property(wid2, P_LIST, property, FALSE);
1271 GList *list = rofi_theme_get_list_inside(p, widget, property, P_STRING);
1272 GList *retv = NULL;
1273 for (GList *iter = g_list_first(list); iter != NULL;
1274 iter = g_list_next(iter)) {
1275 Property *prop = (Property *)(iter->data);
1276 if (prop->type == P_STRING) {
1277 retv = g_list_append(retv, g_strdup(prop->value.s));
1278 } else {
1279 g_warning("Invalid type detected in list.");
1280 }
1281 }
1282 return retv;
1283}
1284
1287 const char *property,
1289 if (p) {
1290 if (p->type == P_INHERIT) {
1291 if (widget->parent) {
1292 ThemeWidget *parent =
1294 Property *pv =
1295 rofi_theme_find_property(parent, P_HIGHLIGHT, property, FALSE);
1296 return rofi_theme_get_highlight_inside(pv, widget->parent, property,
1297 th);
1298 }
1299 return th;
1300 } else if (p->type == P_COLOR) {
1302 th.color = p->value.color;
1303 return th;
1304 }
1305
1306 return p->value.highlight;
1307 } else {
1308 ThemeWidget *wid =
1310 Property *p2 = rofi_theme_find_property(wid, P_COLOR, property, FALSE);
1311 if (p2 != NULL) {
1312 return rofi_theme_get_highlight_inside(p2, widget, property, th);
1313 }
1314 return th;
1315 }
1316 g_debug("Theme entry: #%s %s property %s unset.", widget->name,
1317 widget->state ? widget->state : "", property);
1318 return th;
1319}
1321 const char *property,
1324 Property *p = rofi_theme_find_property(wid, P_HIGHLIGHT, property, FALSE);
1325 if (p == NULL) {
1326 p = rofi_theme_find_property(wid, P_COLOR, property, FALSE);
1327 }
1328 return rofi_theme_get_highlight_inside(p, widget, property, th);
1329}
1331 int val = unit->distance;
1332
1333 if (unit->type == ROFI_PU_EM) {
1335 } else if (unit->type == ROFI_PU_CH) {
1336 val = unit->distance * textbox_get_estimated_ch();
1337 } else if (unit->type == ROFI_PU_PERCENT) {
1338 if (ori == ROFI_ORIENTATION_VERTICAL) {
1339 int height = 0;
1340 rofi_view_get_current_monitor(NULL, &height);
1341 val = (unit->distance * height) / (100.0);
1342 } else {
1343 int width = 0;
1344 rofi_view_get_current_monitor(&width, NULL);
1345 val = (unit->distance * width) / (100.0);
1346 }
1347 } else if (unit->type == ROFI_PU_MM) {
1348 val = unit->distance * config.dpi / 25.4;
1349 }
1350 return val;
1351}
1352
1354 RofiOrientation ori) {
1355 switch (unit->modtype) {
1357 return distance_unit_get_pixel(unit->left, ori);
1358 break;
1360 return distance_unit_get_pixel(unit->left, ori) +
1361 distance_unit_get_pixel(unit->right, ori);
1363 return distance_unit_get_pixel(unit->left, ori) -
1364 distance_unit_get_pixel(unit->right, ori);
1366 return distance_unit_get_pixel(unit->left, ori) *
1367 distance_unit_get_pixel(unit->right, ori);
1369 int a = distance_unit_get_pixel(unit->left, ori);
1370 int b = distance_unit_get_pixel(unit->right, ori);
1371 if (b != 0) {
1372 return a / b;
1373 }
1374 return a;
1375 }
1377 int a = distance_unit_get_pixel(unit->left, ori);
1378 int b = distance_unit_get_pixel(unit->right, ori);
1379 if (b != 0) {
1380 return a % b;
1381 }
1382 return 0;
1383 }
1385 int a = distance_unit_get_pixel(unit->left, ori);
1386 int b = distance_unit_get_pixel(unit->right, ori);
1387 return MIN(a, b);
1388 }
1390 int a = distance_unit_get_pixel(unit->left, ori);
1391 int b = distance_unit_get_pixel(unit->right, ori);
1392 return MAX(a, b);
1393 }
1395 double a = (double)distance_unit_get_pixel(unit->left, ori);
1396 double b = (double)distance_unit_get_pixel(unit->right, ori);
1397 return (int)(round(a / b) * b);
1398 }
1400 double a = (double)distance_unit_get_pixel(unit->left, ori);
1401 double b = (double)distance_unit_get_pixel(unit->right, ori);
1402 return (int)(ceil(a / b) * b);
1403 }
1405 double a = (double)distance_unit_get_pixel(unit->left, ori);
1406 double b = (double)distance_unit_get_pixel(unit->right, ori);
1407 return (int)(floor(a / b) * b);
1408 }
1409 default:
1410 break;
1411 }
1412 return get_pixels(unit, ori);
1413}
1414
1418
1419void distance_get_linestyle(RofiDistance d, cairo_t *draw) {
1420 if (d.style == ROFI_HL_DASH) {
1421 const double dashes[1] = {4};
1422 cairo_set_dash(draw, dashes, 1, 0.0);
1423 } else {
1424 cairo_set_dash(draw, NULL, 0, 0.0);
1425 }
1426}
1427
1428char *rofi_theme_parse_prepare_file(const char *file, const char *parent_file) {
1429 char *filename = rofi_expand_path(file);
1430 // If no absolute path specified, expand it.
1431 if (parent_file != NULL && !g_path_is_absolute(filename)) {
1432 char *basedir = g_path_get_dirname(parent_file);
1433 char *path = g_build_filename(basedir, filename, NULL);
1434 g_free(filename);
1435 filename = path;
1436 g_free(basedir);
1437 }
1438 GFile *gf = g_file_new_for_path(filename);
1439 parsed_config_files = g_list_append(parsed_config_files, filename);
1440 filename = g_file_get_path(gf);
1441 g_object_unref(gf);
1442
1443 return filename;
1444}
1445
1447 g_assert(parent != NULL);
1448 g_assert(child != NULL);
1449
1450 if (parent == rofi_theme && g_strcmp0(child->name, "*") == 0) {
1452 return;
1453 }
1454
1455 ThemeWidget *w = rofi_theme_find_or_create_name(parent, child->name);
1456 if (child->media) {
1457 w->media = g_slice_new0(ThemeMedia);
1458 *(w->media) = *(child->media);
1459 }
1461 for (unsigned int i = 0; i < child->num_widgets; i++) {
1463 }
1464}
1465
1467 ThemeWidget *rwidget) {
1468 if (rwidget == NULL) {
1469 return;
1470 }
1471 unsigned int i = 0;
1472 // for (unsigned int i = 0; i < rwidget->num_widgets; i++) {
1473 while (i < rwidget->num_widgets) {
1474 ThemeWidget *widget = rwidget->widgets[i];
1475 if (widget->media != NULL) {
1476 rwidget->num_widgets--;
1477 for (unsigned x = i; x < rwidget->num_widgets; x++) {
1478 rwidget->widgets[x] = rwidget->widgets[x + 1];
1479 }
1480 rwidget->widgets[rwidget->num_widgets] = NULL;
1481 switch (widget->media->type) {
1483 int w = widget->media->value;
1484 if (mon.w >= w) {
1485 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1486 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1487 }
1488 }
1489 break;
1490 }
1492 int w = widget->media->value;
1493 if (mon.w < w) {
1494 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1495 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1496 }
1497 }
1498 break;
1499 }
1501 int h = widget->media->value;
1502 if (mon.h >= h) {
1503 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1504 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1505 }
1506 } else {
1507 }
1508 break;
1509 }
1511 int h = widget->media->value;
1512 if (mon.h < h) {
1513 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1514 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1515 }
1516 }
1517 break;
1518 }
1520 if (mon.monitor_id == widget->media->value) {
1521 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1522 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1523 }
1524 }
1525 break;
1526 }
1528 double r = widget->media->value;
1529 if ((mon.w / (double)mon.h) >= r) {
1530 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1531 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1532 }
1533 }
1534 break;
1535 }
1537 double r = widget->media->value;
1538 if ((mon.w / (double)mon.h) < r) {
1539 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1540 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1541 }
1542 }
1543 break;
1544 }
1546 if (widget->media->boolv) {
1547 for (unsigned int x = 0; x < widget->num_widgets; x++) {
1548 rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]);
1549 }
1550 }
1551 break;
1552 }
1553
1554 default: {
1555 break;
1556 }
1557 }
1559 // endif
1560 } else {
1562 i++;
1563 }
1564 }
1565}
1566
1568 GString *str = g_string_new(wid->name);
1569 for (ThemeWidget *i = wid->parent; i->parent != NULL; i = i->parent) {
1570 g_string_prepend_c(str, ' ');
1571 g_string_prepend(str, i->name);
1572 }
1573 char *retv = str->str;
1574 g_string_free(str, FALSE);
1575 return retv;
1576}
1577
1579 if (wid == NULL) {
1580 return;
1581 }
1582
1583 for (unsigned int i = 0; i < wid->num_widgets; i++) {
1584 ThemeWidget *widget = wid->widgets[i];
1586 if (widget->properties == NULL) {
1587 continue;
1588 }
1589 GHashTableIter iter;
1590 gpointer key, value;
1591 g_hash_table_iter_init(&iter, widget->properties);
1592 while (g_hash_table_iter_next(&iter, &key, &value)) {
1593 Property *pv = (Property *)value;
1594 if (pv->type == P_LINK) {
1595 if (pv->value.link.ref == NULL) {
1597 if (pv->value.link.ref == pv) {
1599 GString *str = g_string_new(NULL);
1600 g_string_printf(str,
1601 "Validating the theme failed: the variable '%s' in "
1602 "`%s { %s: var(%s);}` failed to resolve.",
1603 pv->value.link.name, n, pv->name,
1604 pv->value.link.name);
1605
1607 g_free(n);
1608 }
1609 }
1610 }
1611 }
1612 }
1613}
1614
1618
1624
1626 if (g_strcmp0(type, "monitor-id") == 0) {
1628 }
1629 if (g_strcmp0(type, "min-width") == 0) {
1631 }
1632 if (g_strcmp0(type, "min-height") == 0) {
1634 }
1635 if (g_strcmp0(type, "max-width") == 0) {
1637 }
1638 if (g_strcmp0(type, "max-height") == 0) {
1640 }
1641 if (g_strcmp0(type, "min-aspect-ratio") == 0) {
1643 }
1644 if (g_strcmp0(type, "max-aspect-ratio") == 0) {
1646 }
1647 if (g_strcmp0(type, "enabled") == 0) {
1649 }
1651}
1652
1654 const widget *widget,
1655 const char *property) {
1656 if (p) {
1657 if (p->type == P_INHERIT) {
1658 if (widget->parent) {
1659 ThemeWidget *parent =
1661 Property *pp =
1662 rofi_theme_find_property(parent, P_STRING, property, FALSE);
1663 return rofi_theme_has_property_inside(pp, widget->parent, property);
1664 }
1665 return FALSE;
1666 }
1667 return TRUE;
1668 }
1669 return FALSE;
1670}
1671gboolean rofi_theme_has_property(const widget *widget, const char *property) {
1673 Property *p = rofi_theme_find_property(wid, P_STRING, property, FALSE);
1674 return rofi_theme_has_property_inside(p, widget, property);
1675}
@ WL_CENTER
Definition rofi-types.h:237
@ WL_SOUTH
Definition rofi-types.h:243
@ WL_WEST
Definition rofi-types.h:245
@ WL_NORTH
Definition rofi-types.h:239
@ WL_EAST
Definition rofi-types.h:241
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:740
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:107
#define color_bold
Definition rofi.h:109
void rofi_add_error_message(GString *str)
Definition rofi.c:90
void rofi_add_warning_message(GString *str)
Definition rofi.c:103
double textbox_get_estimated_char_height(void)
Definition textbox.c:932
double textbox_get_estimated_ch(void)
Definition textbox.c:946
void rofi_view_get_current_monitor(int *width, int *height)
Definition view.c:144
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:172
@ ROFI_IMAGE_LINEAR_GRADIENT
Definition rofi-types.h:172
@ ROFI_DIRECTION_LEFT
Definition rofi-types.h:175
@ ROFI_DIRECTION_RIGHT
Definition rofi-types.h:176
@ ROFI_DIRECTION_BOTTOM
Definition rofi-types.h:178
@ ROFI_DIRECTION_TOP
Definition rofi-types.h:177
@ ROFI_DIRECTION_ANGLE
Definition rofi-types.h:179
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:90
@ ROFI_PU_CH
Definition rofi-types.h:94
@ ROFI_PU_PX
Definition rofi-types.h:86
@ ROFI_PU_MM
Definition rofi-types.h:88
@ ROFI_PU_PERCENT
Definition rofi-types.h:92
RofiOrientation
Definition rofi-types.h:141
@ ROFI_ORIENTATION_HORIZONTAL
Definition rofi-types.h:143
@ ROFI_ORIENTATION_VERTICAL
Definition rofi-types.h:142
@ ROFI_DISTANCE_MODIFIER_GROUP
Definition rofi-types.h:107
@ ROFI_DISTANCE_MODIFIER_CEIL
Definition rofi-types.h:112
@ ROFI_DISTANCE_MODIFIER_SUBTRACT
Definition rofi-types.h:103
@ ROFI_DISTANCE_MODIFIER_MODULO
Definition rofi-types.h:106
@ ROFI_DISTANCE_MODIFIER_FLOOR
Definition rofi-types.h:111
@ ROFI_DISTANCE_MODIFIER_ROUND
Definition rofi-types.h:110
@ ROFI_DISTANCE_MODIFIER_MULTIPLY
Definition rofi-types.h:105
@ ROFI_DISTANCE_MODIFIER_MAX
Definition rofi-types.h:109
@ ROFI_DISTANCE_MODIFIER_MIN
Definition rofi-types.h:108
@ ROFI_DISTANCE_MODIFIER_DIVIDE
Definition rofi-types.h:104
@ ROFI_DISTANCE_MODIFIER_ADD
Definition rofi-types.h:102
@ ROFI_DISTANCE_MODIFIER_NONE
Definition rofi-types.h:101
@ ROFI_HL_SOLID
Definition rofi-types.h:76
@ ROFI_HL_DASH
Definition rofi-types.h:78
@ ROFI_SCALE_HEIGHT
Definition rofi-types.h:185
@ ROFI_SCALE_NONE
Definition rofi-types.h:183
@ ROFI_SCALE_BOTH
Definition rofi-types.h:184
@ ROFI_SCALE_WIDTH
Definition rofi-types.h:186
RofiCursorType
Definition rofi-types.h:149
@ ROFI_HL_UPPERCASE
Definition rofi-types.h:66
@ ROFI_HL_STRIKETHROUGH
Definition rofi-types.h:60
@ ROFI_HL_NONE
Definition rofi-types.h:54
@ ROFI_HL_ITALIC
Definition rofi-types.h:62
@ ROFI_HL_UNDERLINE
Definition rofi-types.h:58
@ ROFI_HL_CAPITALIZE
Definition rofi-types.h:70
@ ROFI_HL_BOLD
Definition rofi-types.h:56
@ ROFI_HL_LOWERCASE
Definition rofi-types.h:68
@ ROFI_HL_COLOR
Definition rofi-types.h:64
Settings config
PropertyValue value
Definition rofi-types.h:297
PropertyType type
Definition rofi-types.h:295
char * name
Definition rofi-types.h:293
RofiDistanceModifier modtype
Definition rofi-types.h:122
RofiPixelUnit type
Definition rofi-types.h:119
struct RofiDistanceUnit * right
Definition rofi-types.h:128
struct RofiDistanceUnit * left
Definition rofi-types.h:125
RofiDistanceUnit base
Definition rofi-types.h:133
RofiLineStyle style
Definition rofi-types.h:135
RofiHighlightStyle style
Definition rofi-types.h:221
RofiDirection dir
Definition rofi-types.h:196
RofiImageType type
Definition rofi-types.h:190
double angle
Definition rofi-types.h:197
uint32_t surface_id
Definition rofi-types.h:202
char * url
Definition rofi-types.h:191
RofiScaleType scaling
Definition rofi-types.h:192
GList * colors
Definition rofi-types.h:199
RofiDistance bottom
Definition rofi-types.h:212
RofiDistance top
Definition rofi-types.h:210
RofiDistance right
Definition rofi-types.h:211
RofiDistance left
Definition rofi-types.h:213
int dpi
Definition settings.h:141
double blue
Definition rofi-types.h:164
double green
Definition rofi-types.h:162
double red
Definition rofi-types.h:160
double alpha
Definition rofi-types.h:166
struct ThemeWidget ** widgets
Definition theme.h:76
struct ThemeWidget * parent
Definition theme.h:82
ThemeMedia * media
Definition theme.h:78
unsigned int num_widgets
Definition theme.h:75
char * name
Definition theme.h:73
GHashTable * properties
Definition theme.h:80
const char * state
struct _widget * parent
WidgetType type
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:1213
ThemeWidget * rofi_theme_find_or_create_name(ThemeWidget *base, const char *name)
Definition theme.c:73
gboolean rofi_theme_get_image(const widget *widget, const char *property, cairo_t *d)
Definition theme.c:1178
GList * rofi_theme_get_list_strings(const widget *widget, const char *property)
Definition theme.c:1267
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:516
const char *const RofiCursorTypeStr[3]
Definition theme.c:351
static int distance_unit_get_pixel(RofiDistanceUnit *unit, RofiOrientation ori)
Definition theme.c:1353
static void int_rofi_theme_print_property(Property *p)
Definition theme.c:357
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
Definition theme.c:990
void rofi_theme_print_parsed_files(gboolean is_term)
Definition theme.c:56
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition theme.c:877
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition theme.c:903
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition theme.c:1415
void rofi_theme_parse_process_links(void)
Definition theme.c:1615
FILE * yyin
static RofiHighlightColorStyle rofi_theme_get_highlight_inside(Property *p, widget *widget, const char *property, RofiHighlightColorStyle th)
Definition theme.c:1286
Property * rofi_theme_find_property(ThemeWidget *widget, PropertyType type, const char *property, gboolean exact)
Definition theme.c:740
static void rofi_theme_parse_process_links_int(ThemeWidget *wid)
Definition theme.c:1578
RofiCursorType rofi_theme_get_cursor_type(const widget *widget, const char *property, RofiCursorType def)
Definition theme.c:962
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
Definition theme.c:778
void yylex_destroy(void)
static int rofi_theme_get_integer_inside(Property *p, const widget *widget, const char *property, int def)
Definition theme.c:821
static RofiDistance rofi_theme_get_distance_inside(Property *p, const widget *widget, const char *property, int def)
Definition theme.c:846
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:1046
void rofi_theme_parse_process_conditionals(void)
Definition theme.c:1619
void rofi_theme_get_color(const widget *widget, const char *property, cairo_t *d)
Definition theme.c:1067
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
Definition theme.c:1320
static RofiCursorType rofi_theme_get_cursor_type_inside(Property *p, const widget *widget, const char *property, RofiCursorType def)
Definition theme.c:940
static void rofi_theme_print_distance_unit(RofiDistanceUnit *unit)
Definition theme.c:262
static void rofi_theme_copy_property_int(G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data)
Definition theme.c:645
static void rofi_theme_distance_property_free(RofiDistance *distance)
Definition theme.c:184
RofiOrientation rofi_theme_get_orientation(const widget *widget, const char *property, RofiOrientation def)
Definition theme.c:932
static int get_pixels(RofiDistanceUnit *unit, RofiOrientation ori)
Definition theme.c:1330
static GList * rofi_theme_get_list_inside(Property *p, const widget *widget, const char *property, PropertyType child_type)
Definition theme.c:1220
static ThemeWidget * rofi_theme_find_single(ThemeWidget *widget, const char *name)
Definition theme.c:667
Property * rofi_theme_property_create(PropertyType type)
Definition theme.c:93
ThemeMediaType rofi_theme_parse_media_type(const char *type)
Definition theme.c:1625
void rofi_theme_widget_add_properties(ThemeWidget *widget, GHashTable *table)
Definition theme.c:651
static double rofi_theme_get_double_inside(const widget *orig, Property *p, const widget *widget, const char *property, double def)
Definition theme.c:1019
static RofiOrientation rofi_theme_get_orientation_inside(Property *p, const widget *widget, const char *property, RofiOrientation def)
Definition theme.c:910
double rofi_theme_get_double(const widget *widget, const char *property, double def)
Definition theme.c:1040
static void rofi_theme_print_distance(RofiDistance d)
Definition theme.c:338
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition theme.c:840
void rofi_theme_print(ThemeWidget *widget)
Definition theme.c:585
static gboolean rofi_theme_has_property_inside(Property *p, const widget *widget, const char *property)
Definition theme.c:1653
static RofiDistanceUnit * rofi_theme_property_copy_distance_unit(RofiDistanceUnit *unit)
Definition theme.c:100
static const char * rofi_theme_get_string_inside(Property *p, const widget *widget, const char *property, const char *def)
Definition theme.c:969
static void printf_double(double d)
Definition theme.c:254
gboolean rofi_theme_has_property(const widget *widget, const char *property)
Definition theme.c:1671
static ThemeWidget * rofi_theme_find(ThemeWidget *widget, const char *name, const gboolean exact)
Definition theme.c:677
static char * rofi_theme_widget_get_name(ThemeWidget *wid)
Definition theme.c:1567
void rofi_theme_reset(void)
Definition theme.c:226
char * rofi_theme_parse_prepare_file(const char *file, const char *parent_file)
Definition theme.c:1428
static int rofi_theme_get_position_inside(Property *p, const widget *widget, const char *property, int def)
Definition theme.c:795
void rofi_theme_parse_merge_widgets(ThemeWidget *parent, ThemeWidget *child)
Definition theme.c:1446
static void rofi_theme_distance_unit_property_free(RofiDistanceUnit *unit)
Definition theme.c:173
static void rofi_theme_print_color(ThemeColor color)
Definition theme.c:317
ThemeWidget * rofi_theme_find_widget(const char *name, const char *state, gboolean exact)
Definition theme.c:786
Property * rofi_theme_property_copy(const Property *p, G_GNUC_UNUSED void *data)
Definition theme.c:123
int yyparse()
int rofi_theme_get_position(const widget *widget, const char *property, int def)
Definition theme.c:815
static void rofi_theme_resolve_link_property(Property *p, int depth)
Definition theme.c:703
GList * rofi_theme_get_list_distance(const widget *widget, const char *property)
Definition theme.c:1239
static void rofi_theme_parse_process_conditionals_int(workarea mon, ThemeWidget *rwidget)
Definition theme.c:1466
void rofi_theme_print_index(ThemeWidget *widget, int index)
Definition theme.c:525
void rofi_theme_free(ThemeWidget *widget)
Definition theme.c:232
static int rofi_theme_get_boolean_inside(Property *p, const widget *widget, const char *property, int def)
Definition theme.c:884
void yyerror(YYLTYPE *yylloc, const char *, const char *)
Definition theme.c:615
RofiDistance rofi_theme_property_copy_distance(RofiDistance const distance)
Definition theme.c:111
void rofi_theme_property_free(Property *p)
Definition theme.c:195
static RofiPadding rofi_theme_get_padding_inside(Property *p, const widget *widget, const char *property, RofiPadding pad)
Definition theme.c:1184
static gboolean rofi_theme_get_image_inside(Property *p, const widget *widget, const char *property, cairo_t *d)
Definition theme.c:1074
void distance_get_linestyle(RofiDistance d, cairo_t *draw)
Definition theme.c:1419
static double rofi_theme_get_double_integer_fb_inside(Property *p, const widget *widget, const char *property, double def)
Definition theme.c:997
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:56
@ THEME_MEDIA_TYPE_MIN_WIDTH
Definition theme.h:40
@ THEME_MEDIA_TYPE_MIN_ASPECT_RATIO
Definition theme.h:50
@ THEME_MEDIA_TYPE_BOOLEAN
Definition theme.h:54
@ 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:93
struct _PropertyValue::@6 link
ThemeColor color
Definition rofi-types.h:268
struct Property * ref
Definition rofi-types.h:276
RofiHighlightColorStyle highlight
Definition rofi-types.h:281
struct Property * def_value
Definition rofi-types.h:278
RofiImage image
Definition rofi-types.h:283
RofiPadding padding
Definition rofi-types.h:270
workarea mon
Definition view.c:111
int monitor_active(workarea *mon)
Definition xcb.c:992
xcb_depth_t * depth
Definition xcb.c:96
ThemeWidget * rofi_configuration
Definition xrmoptions.c:46