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