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