Cleanup: area.h
jump to
@@ -121,7 +121,7 @@ }
} } if (panel1[i].battery.area.on_screen == 1) { - panel1[i].battery.area.resize = 1; + panel1[i].battery.area.resize_needed = 1; panel_refresh = 1; } }@@ -223,16 +223,16 @@
battery->area.parent = p; battery->area.panel = p; battery->area._draw_foreground = draw_battery; - battery->area.size_mode = SIZE_BY_CONTENT; - battery->area._resize = resize_battery; + battery->area.size_mode = LAYOUT_FIXED; + battery->area._resize = resize_battery; battery->area.on_screen = 1; - battery->area.resize = 1; - battery->area.mouse_over_effect = battery_lclick_command || + battery->area.resize_needed = 1; + battery->area.has_mouse_over_effect = battery_lclick_command || battery_mclick_command || battery_rclick_command || battery_uwheel_command || battery_dwheel_command; - battery->area.mouse_press_effect = battery->area.mouse_over_effect; + battery->area.has_mouse_press_effect = battery->area.has_mouse_over_effect; if (battery_tooltip_enabled) battery->area._get_tooltip_text = battery_get_tooltip; }@@ -273,7 +273,7 @@ pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); pango_layout_set_text(layout, buf_bat_percentage, strlen(buf_bat_percentage)); - cairo_set_source_rgba(c, battery->font.color[0], battery->font.color[1], battery->font.color[2], battery->font.alpha); + cairo_set_source_rgba(c, battery->font.rgb[0], battery->font.rgb[1], battery->font.rgb[2], battery->font.alpha); pango_cairo_update_layout(c, layout); draw_text(layout, c, 0, battery->bat1_posy, &battery->font, ((Panel*)battery->area.panel)->font_shadow);@@ -301,7 +301,7 @@ int bat_percentage_height, bat_percentage_width, bat_percentage_height_ink;
int bat_time_height, bat_time_width, bat_time_height_ink; int ret = 0; - battery->area.redraw = 1; + battery->area.redraw_needed = 1; snprintf(buf_bat_percentage, sizeof(buf_bat_percentage), "%d%%", battery_state.percentage); if (battery_state.state == BATTERY_FULL) {
@@ -111,7 +111,7 @@ gettimeofday(&time_clock, 0);
int i; if (time1_format) { for (i=0 ; i < nb_panel ; i++) - panel1[i].clock.area.resize = 1; + panel1[i].clock.area.resize_needed = 1; } panel_refresh = 1; }@@ -126,7 +126,7 @@ if (time_clock.tv_sec % 60 == 0 || time_clock.tv_sec - old_sec > 60) {
int i; if (time1_format) { for (i=0 ; i < nb_panel ; i++) - panel1[i].clock.area.resize = 1; + panel1[i].clock.area.resize_needed = 1; } panel_refresh = 1; }@@ -185,19 +185,19 @@ if (!clock->area.bg)
clock->area.bg = &g_array_index(backgrounds, Background, 0); clock->area.parent = p; clock->area.panel = p; - clock->area.mouse_press_effect = clock->area.mouse_over_effect = clock_lclick_command || + clock->area.has_mouse_press_effect = clock->area.has_mouse_over_effect = clock_lclick_command || clock_mclick_command || clock_rclick_command || clock_uwheel_command || clock_dwheel_command; clock->area._draw_foreground = draw_clock; - clock->area.size_mode = SIZE_BY_CONTENT; - clock->area._resize = resize_clock; + clock->area.size_mode = LAYOUT_FIXED; + clock->area._resize = resize_clock; // check consistency if (!time1_format) return; - clock->area.resize = 1; + clock->area.resize_needed = 1; clock->area.on_screen = 1; if (time_tooltip_format) {@@ -222,7 +222,7 @@ pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); pango_layout_set_text (layout, buf_time, strlen(buf_time)); - cairo_set_source_rgba (c, clock->font.color[0], clock->font.color[1], clock->font.color[2], clock->font.alpha); + cairo_set_source_rgba (c, clock->font.rgb[0], clock->font.rgb[1], clock->font.rgb[2], clock->font.alpha); pango_cairo_update_layout (c, layout); draw_text(layout, c, 0, clock->time1_posy, &clock->font, ((Panel*)clock->area.panel)->font_shadow);@@ -247,7 +247,7 @@ Clock *clock = obj;
Panel *panel = clock->area.panel; int time_height_ink, time_height, time_width, date_height_ink, date_height, date_width, ret = 0; - clock->area.redraw = 1; + clock->area.redraw_needed = 1; date_height = date_width = 0; strftime(buf_time, sizeof(buf_time), time1_format, clock_gettime_for_tz(time1_timezone));@@ -265,7 +265,7 @@ if (panel_horizontal) {
int new_size = (time_width > date_width) ? time_width : date_width; new_size += (2*clock->area.paddingxlr) + (2*clock->area.bg->border.width); if (new_size > clock->area.width || new_size < (clock->area.width-6)) { - // we try to limit the number of resize + // we try to limit the number of resizes clock->area.width = new_size + 1; clock->time1_posy = (clock->area.height - time_height) / 2; if (time2_format) {@@ -278,7 +278,7 @@ }
else { int new_size = time_height + date_height + (2 * (clock->area.paddingxlr + clock->area.bg->border.width)); if (new_size != clock->area.height) { - // we try to limit the number of resize + // we try to limit the number of resizes clock->area.height = new_size; clock->time1_posy = (clock->area.height - time_height) / 2; if (time2_format) {
@@ -213,17 +213,17 @@ // 'rounded' is the first parameter => alloc a new background
if (backgrounds->len > 0) { Background *bg = &g_array_index(backgrounds, Background, backgrounds->len-1); if (!read_bg_color_hover) - memcpy(&bg->back_hover, &bg->back, sizeof(Color)); + memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color)); if (!read_border_color_hover) - memcpy(&bg->border_hover, &bg->border, sizeof(Color)); + memcpy(&bg->border_color_hover, &bg->border, sizeof(Color)); if (!read_bg_color_press) - memcpy(&bg->back_pressed, &bg->back_hover, sizeof(Color)); + memcpy(&bg->fill_color_pressed, &bg->fill_color_hover, sizeof(Color)); if (!read_border_color_press) - memcpy(&bg->border_pressed, &bg->border_hover, sizeof(Color)); + memcpy(&bg->border_color_pressed, &bg->border_color_hover, sizeof(Color)); } Background bg; init_background(&bg); - bg.border.rounded = atoi(value); + bg.border.radius = atoi(value); g_array_append_val(backgrounds, bg); read_bg_color_hover = 0; read_border_color_hover = 0;@@ -236,47 +236,47 @@ }
else if (strcmp (key, "background_color") == 0) { Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1); extract_values(value, &value1, &value2, &value3); - get_color (value1, bg->back.color); - if (value2) bg->back.alpha = (atoi (value2) / 100.0); - else bg->back.alpha = 0.5; + get_color (value1, bg->fill_color.rgb); + if (value2) bg->fill_color.alpha = (atoi (value2) / 100.0); + else bg->fill_color.alpha = 0.5; } else if (strcmp (key, "border_color") == 0) { Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1); extract_values(value, &value1, &value2, &value3); - get_color (value1, bg->border.color); - if (value2) bg->border.alpha = (atoi (value2) / 100.0); - else bg->border.alpha = 0.5; + get_color (value1, bg->border.color.rgb); + if (value2) bg->border.color.alpha = (atoi (value2) / 100.0); + else bg->border.color.alpha = 0.5; } else if (strcmp (key, "background_color_hover") == 0) { Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1); extract_values(value, &value1, &value2, &value3); - get_color (value1, bg->back_hover.color); - if (value2) bg->back_hover.alpha = (atoi (value2) / 100.0); - else bg->back_hover.alpha = 0.5; + get_color (value1, bg->fill_color_hover.rgb); + if (value2) bg->fill_color_hover.alpha = (atoi (value2) / 100.0); + else bg->fill_color_hover.alpha = 0.5; read_bg_color_hover = 1; } else if (strcmp (key, "border_color_hover") == 0) { Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1); extract_values(value, &value1, &value2, &value3); - get_color (value1, bg->border_hover.color); - if (value2) bg->border_hover.alpha = (atoi (value2) / 100.0); - else bg->border_hover.alpha = 0.5; + get_color (value1, bg->border_color_hover.rgb); + if (value2) bg->border_color_hover.alpha = (atoi (value2) / 100.0); + else bg->border_color_hover.alpha = 0.5; read_border_color_hover = 1; } else if (strcmp (key, "background_color_pressed") == 0) { Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1); extract_values(value, &value1, &value2, &value3); - get_color (value1, bg->back_pressed.color); - if (value2) bg->back_pressed.alpha = (atoi (value2) / 100.0); - else bg->back_pressed.alpha = 0.5; + get_color (value1, bg->fill_color_pressed.rgb); + if (value2) bg->fill_color_pressed.alpha = (atoi (value2) / 100.0); + else bg->fill_color_pressed.alpha = 0.5; read_bg_color_press = 1; } else if (strcmp (key, "border_color_pressed") == 0) { Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1); extract_values(value, &value1, &value2, &value3); - get_color (value1, bg->border_pressed.color); - if (value2) bg->border_pressed.alpha = (atoi (value2) / 100.0); - else bg->border_pressed.alpha = 0.5; + get_color (value1, bg->border_color_pressed.rgb); + if (value2) bg->border_color_pressed.alpha = (atoi (value2) / 100.0); + else bg->border_color_pressed.alpha = 0.5; read_border_color_press = 1; }@@ -471,7 +471,7 @@ }
else if (strcmp (key, "battery_font_color") == 0) { #ifdef ENABLE_BATTERY extract_values(value, &value1, &value2, &value3); - get_color (value1, panel_config.battery.font.color); + get_color (value1, panel_config.battery.font.rgb); if (value2) panel_config.battery.font.alpha = (atoi (value2) / 100.0); else panel_config.battery.font.alpha = 0.5; #endif@@ -542,7 +542,7 @@ time2_font_desc = pango_font_description_from_string (value);
} else if (strcmp (key, "clock_font_color") == 0) { extract_values(value, &value1, &value2, &value3); - get_color (value1, panel_config.clock.font.color); + get_color (value1, panel_config.clock.font.rgb); if (value2) panel_config.clock.font.alpha = (atoi (value2) / 100.0); else panel_config.clock.font.alpha = 0.5; }@@ -637,13 +637,13 @@ panel_config.taskbarname_font_desc = pango_font_description_from_string(value);
} else if (strcmp (key, "taskbar_name_font_color") == 0) { extract_values(value, &value1, &value2, &value3); - get_color (value1, taskbarname_font.color); + get_color (value1, taskbarname_font.rgb); if (value2) taskbarname_font.alpha = (atoi (value2) / 100.0); else taskbarname_font.alpha = 0.5; } else if (strcmp (key, "taskbar_name_active_font_color") == 0) { extract_values(value, &value1, &value2, &value3); - get_color (value1, taskbarname_active_font.color); + get_color (value1, taskbarname_active_font.rgb); if (value2) taskbarname_active_font.alpha = (atoi (value2) / 100.0); else taskbarname_active_font.alpha = 0.5; }@@ -708,7 +708,7 @@ if (status >= 0) {
extract_values(value, &value1, &value2, &value3); float alpha = 1; if (value2) alpha = (atoi (value2) / 100.0); - get_color (value1, panel_config.g_task.font[status].color); + get_color (value1, panel_config.g_task.font[status].rgb); panel_config.g_task.font[status].alpha = alpha; panel_config.g_task.config_font_mask |= (1<<status); }@@ -859,7 +859,7 @@ g_tooltip.bg = &g_array_index(backgrounds, Background, id);
} else if (strcmp (key, "tooltip_font_color") == 0) { extract_values(value, &value1, &value2, &value3); - get_color(value1, g_tooltip.font_color.color); + get_color(value1, g_tooltip.font_color.rgb); if (value2) g_tooltip.font_color.alpha = (atoi (value2) / 100.0); else g_tooltip.font_color.alpha = 0.1; }@@ -1039,13 +1039,13 @@
if (backgrounds->len > 0) { Background *bg = &g_array_index(backgrounds, Background, backgrounds->len-1); if (!read_bg_color_hover) - memcpy(&bg->back_hover, &bg->back, sizeof(Color)); + memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color)); if (!read_border_color_hover) - memcpy(&bg->border_hover, &bg->border, sizeof(Color)); + memcpy(&bg->border_color_hover, &bg->border, sizeof(Color)); if (!read_bg_color_press) - memcpy(&bg->back_pressed, &bg->back_hover, sizeof(Color)); + memcpy(&bg->fill_color_pressed, &bg->fill_color_hover, sizeof(Color)); if (!read_border_color_press) - memcpy(&bg->border_pressed, &bg->border_hover, sizeof(Color)); + memcpy(&bg->border_color_pressed, &bg->border_color_hover, sizeof(Color)); } return 1;
@@ -40,8 +40,8 @@ if (freespace->area.bg == 0)
freespace->area.bg = &g_array_index(backgrounds, Background, 0); freespace->area.parent = p; freespace->area.panel = p; - freespace->area.size_mode = SIZE_BY_CONTENT; - freespace->area.resize = 1; + freespace->area.size_mode = LAYOUT_FIXED; + freespace->area.resize_needed = 1; freespace->area.on_screen = 1; freespace->area._resize = resize_freespace; }@@ -87,7 +87,7 @@ } else {
freespace->area.height = size; } - freespace->area.redraw = 1; + freespace->area.redraw_needed = 1; panel_refresh = 1; return 1; }
@@ -92,10 +92,10 @@
launcher->area.parent = p; launcher->area.panel = p; launcher->area._draw_foreground = NULL; - launcher->area.size_mode = SIZE_BY_CONTENT; + launcher->area.size_mode = LAYOUT_FIXED; launcher->area._resize = resize_launcher; - launcher->area.resize = 1; - launcher->area.redraw = 1; + launcher->area.resize_needed = 1; + launcher->area.redraw_needed = 1; if (!launcher->area.bg) launcher->area.bg = &g_array_index(backgrounds, Background, 0);@@ -446,15 +446,14 @@ DesktopEntry entry;
read_desktop_file(app->data, &entry); if (entry.exec) { LauncherIcon *launcherIcon = calloc(1, sizeof(LauncherIcon)); - launcherIcon->area.parent = launcher; launcherIcon->area.panel = launcher->area.panel; launcherIcon->area._draw_foreground = draw_launcher_icon; - launcherIcon->area.size_mode = SIZE_BY_CONTENT; + launcherIcon->area.size_mode = LAYOUT_FIXED; launcherIcon->area._resize = NULL; - launcherIcon->area.resize = 0; - launcherIcon->area.redraw = 1; - launcherIcon->area.mouse_over_effect = 1; - launcherIcon->area.mouse_press_effect = 1; + launcherIcon->area.resize_needed = 0; + launcherIcon->area.redraw_needed = 1; + launcherIcon->area.has_mouse_over_effect = 1; + launcherIcon->area.has_mouse_press_effect = 1; launcherIcon->area.bg = launcher_icon_bg; launcherIcon->area.on_screen = 1; launcherIcon->area._on_change_layout = launcher_icon_on_change_layout;@@ -470,7 +469,7 @@ launcherIcon->icon_size = 1;
launcherIcon->icon_tooltip = entry.name ? strdup(entry.name) : strdup(entry.exec); free_desktop_entry(&entry); launcher->list_icons = g_slist_append(launcher->list_icons, launcherIcon); - add_area(&launcherIcon->area); + add_area(&launcherIcon->area, (Area*)launcher); } app = g_slist_next(app); }
@@ -64,7 +64,7 @@ Launcher *launcher = &panel1[i].launcher;
cleanup_launcher_theme(launcher); launcher_load_themes(launcher); launcher_load_icons(launcher); - launcher->area.resize = 1; + launcher->area.resize_needed = 1; } } }
@@ -192,11 +192,11 @@ p->area.bg = &g_array_index(backgrounds, Background, 0);
p->area.parent = p; p->area.panel = p; p->area.on_screen = 1; - p->area.resize = 1; - p->area.size_mode = SIZE_BY_LAYOUT; + p->area.resize_needed = 1; + p->area.size_mode = LAYOUT_DYNAMIC; p->area._resize = resize_panel; init_panel_size_and_position(p); - // add childs according to panel_items + // add children according to panel_items for (k=0 ; k < strlen(panel_items_order) ; k++) { if (panel_items_order[k] == 'L') init_launcher_panel(p);@@ -265,11 +265,11 @@ if (panel->pourcenty)
panel->area.height = (float)server.monitor[panel->monitor].height * panel->area.height / 100; if (panel->area.width + panel->marginx > server.monitor[panel->monitor].width) panel->area.width = server.monitor[panel->monitor].width - panel->marginx; - if (panel->area.bg->border.rounded > panel->area.height/2) { + if (panel->area.bg->border.radius > panel->area.height/2) { printf("panel_background_id rounded is too big... please fix your tint2rc\n"); g_array_append_val(backgrounds, *panel->area.bg); panel->area.bg = &g_array_index(backgrounds, Background, backgrounds->len-1); - panel->area.bg->border.rounded = panel->area.height/2; + panel->area.bg->border.radius = panel->area.height/2; } } else {@@ -284,11 +284,11 @@ else
panel->area.width = old_panel_height; if (panel->area.height + panel->marginy > server.monitor[panel->monitor].height) panel->area.height = server.monitor[panel->monitor].height - panel->marginy; - if (panel->area.bg->border.rounded > panel->area.width/2) { + if (panel->area.bg->border.radius > panel->area.width/2) { printf("panel_background_id rounded is too big... please fix your tint2rc\n"); g_array_append_val(backgrounds, *panel->area.bg); panel->area.bg = &g_array_index(backgrounds, Background, backgrounds->len-1); - panel->area.bg->border.rounded = panel->area.width/2; + panel->area.bg->border.radius = panel->area.width/2; } }@@ -336,7 +336,7 @@
int resize_panel(void *obj) { Panel *panel = (Panel*)obj; - resize_by_layout(panel, 0); + relayout_with_constraint(&panel->area, 0); //printf("resize_panel\n"); if (panel_mode != MULTI_DESKTOP && taskbar_enabled) {@@ -347,7 +347,7 @@ height = panel->taskbar[server.desktop].area.height;
for (i=0 ; i < panel->nb_desktop ; i++) { panel->taskbar[i].area.width = width; panel->taskbar[i].area.height = height; - panel->taskbar[i].area.resize = 1; + panel->taskbar[i].area.resize_needed = 1; } } if (panel_mode == MULTI_DESKTOP && taskbar_enabled && taskbar_distribute_size) {@@ -426,7 +426,7 @@ taskbar->area.width = actual_name_size + items / (float)total_items * total_size;
} else { taskbar->area.height = actual_name_size + items / (float)total_items * total_size; } - taskbar->area.resize = 1; + taskbar->area.resize_needed = 1; } } }@@ -503,7 +503,7 @@
for (k=0 ; k < strlen(panel_items_order) ; k++) { if (panel_items_order[k] == 'L') { p->area.children = g_list_append(p->area.children, &p->launcher); - p->launcher.area.resize = 1; + p->launcher.area.resize_needed = 1; } if (panel_items_order[k] == 'T') { for (j=0 ; j < p->nb_desktop ; j++)@@ -522,7 +522,7 @@ p->area.children = g_list_append(p->area.children, &p->clock);
if (panel_items_order[k] == 'F') p->area.children = g_list_append(p->area.children, &p->freespace); } - init_rendering(&p->area, 0); + initialize_positions(&p->area, 0); }@@ -649,7 +649,7 @@ GList *l0;
Area *a; for (l0 = p->area.children; l0 ; l0 = l0->next) { a = l0->data; - set_redraw(a); + schedule_redraw(a); } // reset task/taskbar 'state_pix'@@ -924,3 +924,9 @@ if (child) return; // mouse over one of the system tray icons
change_timeout(&p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p); } + +void render_panel(Panel *panel) +{ + relayout(&panel->area); + draw_tree(&panel->area); +}
@@ -153,6 +153,7 @@ void init_panel();
void init_panel_size_and_position(Panel *panel); int resize_panel(void *obj); +void render_panel(Panel *panel); void set_panel_items_order(Panel *p); void set_panel_properties(Panel *p);
@@ -197,7 +197,7 @@ if (!win) return 0;
result = XGetWindowProperty(server.dsp, win, at, 0, 0x7fffffff, False, type, &type_ret, &format_ret, &nitems_ret, &bafter_ret, &prop_value); - // Send back resultcount + // Send fill_color resultcount if (num_results) *num_results = (int)nitems_ret; if (result == Success && prop_value) return prop_value;
@@ -74,7 +74,7 @@ systray.alpha = 100;
systray.sort = SYSTRAY_SORT_LEFT2RIGHT; systray.area._draw_foreground = draw_systray; systray.area._on_change_layout = on_change_systray; - systray.area.size_mode = SIZE_BY_CONTENT; + systray.area.size_mode = LAYOUT_FIXED; systray.area._resize = resize_systray; systray_profile = getenv("SYSTRAY_PROFILING") != NULL; }@@ -117,9 +117,9 @@ systray.area.panel = panel;
if (!systray.area.bg) systray.area.bg = &g_array_index(backgrounds, Background, 0); show(&systray.area); - systray.area.resize = 1; - systray.area.redraw = 1; - panel->area.resize = 1; + systray.area.resize_needed = 1; + systray.area.redraw_needed = 1; + panel->area.resize_needed = 1; panel_refresh = 1; refresh_systray = 1; }@@ -615,9 +615,9 @@
// Resize and redraw the systray if (systray_profile) fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__); - systray.area.resize = 1; - systray.area.redraw = 1; - panel->area.resize = 1; + systray.area.resize_needed = 1; + systray.area.redraw_needed = 1; + panel->area.resize_needed = 1; panel_refresh = 1; refresh_systray = 1; return TRUE;@@ -817,9 +817,9 @@
// Resize and redraw the systray if (systray_profile) fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__); - systray.area.resize = 1; - systray.area.redraw = 1; - panel->area.resize = 1; + systray.area.resize_needed = 1; + systray.area.redraw_needed = 1; + panel->area.resize_needed = 1; panel_refresh = 1; refresh_systray = 1; }@@ -906,7 +906,7 @@ traywin->bad_size_counter++;
fprintf(stderr, RED "Detected resize loop for tray icon %lu (%s), throttling resize events\n" RESET, traywin->win, traywin->name); } // Delayed resize - // FIXME Normally we should force the icon to resize back to the size we resized it to when we embedded it. + // FIXME Normally we should force the icon to resize fill_color to the size we resized it to when we embedded it. // However this triggers a resize loop in new versions of GTK, which we must avoid. if (!traywin->resize_timeout) traywin->resize_timeout = add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);@@ -959,7 +959,7 @@ traywin->bad_size_counter++;
fprintf(stderr, RED "Detected resize loop for tray icon %lu (%s), throttling resize events\n" RESET, traywin->win, traywin->name); } // Delayed resize - // FIXME Normally we should force the icon to resize back to the size we resized it to when we embedded it. + // FIXME Normally we should force the icon to resize fill_color to the size we resized it to when we embedded it. // However this triggers a resize loop in new versions of GTK, which we must avoid. if (!traywin->resize_timeout) traywin->resize_timeout = add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);@@ -1139,9 +1139,9 @@ systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
// Resize and redraw the systray if (systray_profile) fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__); - systray.area.resize = 1; - systray.area.redraw = 1; - panel->area.resize = 1; + systray.area.resize_needed = 1; + systray.area.redraw_needed = 1; + panel->area.resize_needed = 1; panel_refresh = 1; refresh_systray = 1; }
@@ -62,8 +62,8 @@ else monitor = 0;
Task new_tsk; memset(&new_tsk, 0, sizeof(new_tsk)); - new_tsk.area.mouse_over_effect = 1; - new_tsk.area.mouse_press_effect = 1; + new_tsk.area.has_mouse_over_effect = 1; + new_tsk.area.has_mouse_press_effect = 1; new_tsk.win = win; new_tsk.desktop = window_get_desktop (win); new_tsk.area.panel = &panel1[monitor];@@ -94,8 +94,8 @@ tskbar = &panel1[monitor].taskbar[j];
new_tsk2 = calloc(1, sizeof(Task)); memcpy(&new_tsk2->area, &panel1[monitor].g_task.area, sizeof(Area)); new_tsk2->area.parent = tskbar; - new_tsk2->area.mouse_over_effect = 1; - new_tsk2->area.mouse_press_effect = 1; + new_tsk2->area.has_mouse_over_effect = 1; + new_tsk2->area.has_mouse_press_effect = 1; new_tsk2->win = new_tsk.win; new_tsk2->desktop = new_tsk.desktop; new_tsk2->win_x = new_tsk.win_x;@@ -119,7 +119,7 @@ }
new_tsk2->icon_width = new_tsk.icon_width; new_tsk2->icon_height = new_tsk.icon_height; tskbar->area.children = g_list_append(tskbar->area.children, new_tsk2); - tskbar->area.resize = 1; + tskbar->area.resize_needed = 1; g_ptr_array_add(task_group, new_tsk2); //printf("add_task panel %d, desktop %d, task %s\n", i, j, new_tsk2->title); }@@ -132,7 +132,7 @@ sort_taskbar_for_win(win);
if (panel_mode == MULTI_DESKTOP) { Panel *panel = new_tsk2->area.panel; - panel->area.resize = 1; + panel->area.resize_needed = 1; } if (window_is_urgent(win)) {@@ -149,7 +149,7 @@ if (!tsk) return;
if (panel_mode == MULTI_DESKTOP) { Panel *panel = tsk->area.panel; - panel->area.resize = 1; + panel->area.resize_needed = 1; } Window win = tsk->win;@@ -187,7 +187,7 @@ tsk2 = g_ptr_array_index(task_group, i);
if (tsk2 == task_active) task_active = 0; if (tsk2 == task_drag) task_drag = 0; if (g_slist_find(urgent_list, tsk2)) del_urgent(tsk2); - remove_area(tsk2); + remove_area((Area*)tsk2); free(tsk2); } g_hash_table_remove(win_to_task_table, &win);@@ -555,9 +555,9 @@ tsk1->area.bg = panel1[0].g_task.background[state];
if (!panel_config.mouse_effects) { tsk1->area.pix = tsk1->state_pix[state]; if (!tsk1->area.pix) - tsk1->area.redraw = 1; + tsk1->area.redraw_needed = 1; } else { - tsk1->area.redraw = 1; + tsk1->area.redraw_needed = 1; } if (state == TASK_ACTIVE && g_slist_find(urgent_list, tsk1)) del_urgent(tsk1);@@ -581,9 +581,9 @@ if (1 - hide != tsk1->area.on_screen) {
tsk1->area.on_screen = 1 - hide; set_task_redraw(tsk1); Panel *p = (Panel*)tsk->area.panel; - tsk->area.resize = 1; - p->taskbar->area.resize = 1; - p->area.resize = 1; + tsk->area.resize_needed = 1; + p->taskbar->area.resize_needed = 1; + p->area.resize_needed = 1; } } panel_refresh = 1;@@ -600,7 +600,7 @@ if (tsk->state_pix[k]) XFreePixmap(server.dsp, tsk->state_pix[k]);
tsk->state_pix[k] = 0; } tsk->area.pix = 0; - tsk->area.redraw = 1; + tsk->area.redraw_needed = 1; }
@@ -99,7 +99,7 @@ tskbar->state_pix[k] = 0;
} free_area(&tskbar->area); // remove taskbar from the panel - remove_area(tskbar); + remove_area((Area*)tskbar); } if (panel->taskbar) { free(panel->taskbar);@@ -144,22 +144,22 @@ panel->g_task.area.bg = &g_array_index(backgrounds, Background, 0);
// taskbar name panel->g_taskbar.area_name.panel = panel; - panel->g_taskbar.area_name.size_mode = SIZE_BY_CONTENT; + panel->g_taskbar.area_name.size_mode = LAYOUT_FIXED; panel->g_taskbar.area_name._resize = resize_taskbarname; panel->g_taskbar.area_name._draw_foreground = draw_taskbarname; panel->g_taskbar.area_name._on_change_layout = 0; - panel->g_taskbar.area_name.resize = 1; + panel->g_taskbar.area_name.resize_needed = 1; panel->g_taskbar.area_name.on_screen = 1; // taskbar panel->g_taskbar.area.parent = panel; panel->g_taskbar.area.panel = panel; - panel->g_taskbar.area.size_mode = SIZE_BY_LAYOUT; + panel->g_taskbar.area.size_mode = LAYOUT_DYNAMIC; panel->g_taskbar.area.alignment = taskbar_alignment; panel->g_taskbar.area._resize = resize_taskbar; panel->g_taskbar.area._draw_foreground = draw_taskbar; panel->g_taskbar.area._on_change_layout = on_change_taskbar; - panel->g_taskbar.area.resize = 1; + panel->g_taskbar.area.resize_needed = 1; panel->g_taskbar.area.on_screen = 1; if (panel_horizontal) { panel->g_taskbar.area.posy = panel->area.bg->border.width + panel->area.paddingy;@@ -176,10 +176,10 @@ }
// task panel->g_task.area.panel = panel; - panel->g_task.area.size_mode = SIZE_BY_LAYOUT; + panel->g_task.area.size_mode = LAYOUT_DYNAMIC; panel->g_task.area._draw_foreground = draw_task; panel->g_task.area._on_change_layout = on_change_task; - panel->g_task.area.resize = 1; + panel->g_task.area.resize_needed = 1; panel->g_task.area.on_screen = 1; if ((panel->g_task.config_asb_mask & (1<<TASK_NORMAL)) == 0) { panel->g_task.alpha[TASK_NORMAL] = 100;@@ -223,11 +223,11 @@
for (j=0; j<TASK_STATE_COUNT; ++j) { if (panel->g_task.background[j] == 0) panel->g_task.background[j] = &g_array_index(backgrounds, Background, 0); - if (panel->g_task.background[j]->border.rounded > panel->g_task.area.height/2) { + if (panel->g_task.background[j]->border.radius > panel->g_task.area.height/2) { printf("task%sbackground_id has a too large rounded value. Please fix your tint2rc\n", j==0 ? "_" : j==1 ? "_active_" : j==2 ? "_iconified_" : "_urgent_"); g_array_append_val(backgrounds, *panel->g_task.background[j]); panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len-1); - panel->g_task.background[j]->border.rounded = panel->g_task.area.height/2; + panel->g_task.background[j]->border.radius = panel->g_task.area.height/2; } }@@ -334,7 +334,7 @@ int text_width;
//printf("resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy); if (panel_horizontal) { - resize_by_layout(obj, panel->g_task.maximum_width); + relayout_with_constraint(&taskbar->area, panel->g_task.maximum_width); text_width = panel->g_task.maximum_width; GList *l = taskbar->area.children;@@ -348,7 +348,7 @@ }
taskbar->text_width = text_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingxlr; } else { - resize_by_layout(obj, panel->g_task.maximum_height); + relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height); taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy) - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingxlr; }@@ -367,7 +367,7 @@ if (tskbar->state_pix[k]) XFreePixmap(server.dsp, tskbar->state_pix[k]);
tskbar->state_pix[k] = 0; } tskbar->area.pix = 0; - tskbar->area.redraw = 1; + tskbar->area.redraw_needed = 1; }@@ -389,13 +389,13 @@ tskbar->area.on_screen = 1;
} if (tskbar->area.on_screen == 1) { if (tskbar->state_pix[state] == 0) - tskbar->area.redraw = 1; + tskbar->area.redraw_needed = 1; if (taskbarname_enabled) { if (!panel_config.mouse_effects) { if (tskbar->bar_name.state_pix[state] == 0) - tskbar->bar_name.area.redraw = 1; + tskbar->bar_name.area.redraw_needed = 1; } else { - tskbar->bar_name.area.redraw = 1; + tskbar->bar_name.area.redraw_needed = 1; } } if (panel_mode == MULTI_DESKTOP && panel1[0].g_taskbar.background[TASKBAR_NORMAL] != panel1[0].g_taskbar.background[TASKBAR_ACTIVE]) {@@ -540,9 +540,9 @@ if (!taskbar_needs_sort(taskbar)) {
return; } taskbar->area.children = g_list_sort_with_data(taskbar->area.children, (GCompareDataFunc)compare_tasks, taskbar); - taskbar->area.resize = 1; + taskbar->area.resize_needed = 1; panel_refresh = 1; - ((Panel*)taskbar->area.panel)->area.resize = 1; + ((Panel*)taskbar->area.panel)->area.resize_needed = 1; }
@@ -62,8 +62,8 @@ for (j=0, l=list ; j < panel->nb_desktop ; j++) {
tskbar = &panel->taskbar[j]; memcpy(&tskbar->bar_name.area, &panel->g_taskbar.area_name, sizeof(Area)); tskbar->bar_name.area.parent = tskbar; - tskbar->bar_name.area.mouse_over_effect = 1; - tskbar->bar_name.area.mouse_press_effect = 1; + tskbar->bar_name.area.has_mouse_over_effect = 1; + tskbar->bar_name.area.has_mouse_press_effect = 1; if (j == server.desktop) tskbar->bar_name.area.bg = panel->g_taskbar.background_name[TASKBAR_ACTIVE]; else@@ -105,7 +105,7 @@ if (tskbar->bar_name.state_pix[k])
XFreePixmap(server.dsp, tskbar->bar_name.state_pix[k]); tskbar->bar_name.state_pix[k] = 0; } - remove_area(&tskbar->bar_name); + remove_area((Area*)&tskbar->bar_name); } } }@@ -131,7 +131,7 @@ pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); pango_layout_set_text (layout, taskbar_name->name, strlen(taskbar_name->name)); - cairo_set_source_rgba (c, config_text->color[0], config_text->color[1], config_text->color[2], config_text->alpha); + cairo_set_source_rgba (c, config_text->rgb[0], config_text->rgb[1], config_text->rgb[2], config_text->alpha); pango_cairo_update_layout (c, layout); draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel*)taskbar_name->area.panel)->font_shadow);@@ -148,7 +148,7 @@ Panel *panel = taskbar_name->area.panel;
int name_height, name_width, name_height_ink; int ret = 0; - taskbar_name->area.redraw = 1; + taskbar_name->area.redraw_needed = 1; get_text_size2(panel_config.taskbarname_font_desc, &name_height_ink, &name_height, &name_width, panel->area.height, panel->area.width, taskbar_name->name, strlen(taskbar_name->name), PANGO_WRAP_WORD_CHAR, PANGO_ELLIPSIZE_NONE);
@@ -354,7 +354,7 @@ if (panel->area.width > server.monitor[0].width)
panel->area.width = server.monitor[0].width; panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth); - rendering(panel); + render_panel(panel); Imlib_Image img = NULL; imlib_context_set_drawable(panel->temp_pmap);@@ -545,7 +545,7 @@ if (drag_iter && task_iter) {
gpointer temp = task_iter->data; task_iter->data = drag_iter->data; drag_iter->data = temp; - event_taskbar->area.resize = 1; + event_taskbar->area.resize_needed = 1; panel_refresh = 1; task_dragged = 1; }@@ -557,7 +557,7 @@ if (task_drag->desktop == ALLDESKTOP || panel_mode != MULTI_DESKTOP)
return; Taskbar * drag_taskbar = (Taskbar*)task_drag->area.parent; - remove_area(task_drag); + remove_area((Area*)task_drag); if (event_taskbar->area.posx > drag_taskbar->area.posx || event_taskbar->area.posy > drag_taskbar->area.posy) { int i = (taskbarname_enabled) ? 1 : 0;@@ -576,11 +576,11 @@ if (taskbar_sort_method != TASKBAR_NOSORT) {
sort_tasks(event_taskbar); } - event_taskbar->area.resize = 1; - drag_taskbar->area.resize = 1; + event_taskbar->area.resize_needed = 1; + drag_taskbar->area.resize_needed = 1; task_dragged = 1; panel_refresh = 1; - panel->area.resize = 1; + panel->area.resize_needed = 1; } }@@ -714,7 +714,7 @@ tskbar = &panel1[i].taskbar[j];
if (strcmp(name, tskbar->bar_name.name) != 0) { g_free(tskbar->bar_name.name); tskbar->bar_name.name = name; - tskbar->bar_name.area.resize = 1; + tskbar->bar_name.area.resize_needed = 1; } else g_free(name);@@ -738,7 +738,7 @@ for (i=0 ; i < nb_panel ; i++) {
init_taskbar_panel(&panel1[i]); set_panel_items_order(&panel1[i]); visible_taskbar(&panel1[i]); - panel1[i].area.resize = 1; + panel1[i].area.resize_needed = 1; } task_refresh_tasklist(); active_task();@@ -764,10 +764,10 @@ for (; l ; l = l->next) {
tsk = l->data; if (tsk->desktop == ALLDESKTOP) { tsk->area.on_screen = 0; - tskbar->area.resize = 1; + tskbar->area.resize_needed = 1; panel_refresh = 1; if (panel_mode == MULTI_DESKTOP) - panel->area.resize = 1; + panel->area.resize_needed = 1; } } }@@ -778,9 +778,9 @@ for (; l ; l = l->next) {
tsk = l->data; if (tsk->desktop == ALLDESKTOP) { tsk->area.on_screen = 1; - tskbar->area.resize = 1; + tskbar->area.resize_needed = 1; if (panel_mode == MULTI_DESKTOP) - panel->area.resize = 1; + panel->area.resize_needed = 1; } } }@@ -1225,7 +1225,7 @@ } else {
if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap); panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth); - rendering(panel); + render_panel(panel); if (panel == (Panel*)systray.area.panel) { if (refresh_systray && panel && !panel->is_hidden) { refresh_systray = 0;
@@ -43,9 +43,9 @@ {
// give the tooltip some reasonable default values memset(&g_tooltip, 0, sizeof(Tooltip)); - g_tooltip.font_color.color[0] = 1; - g_tooltip.font_color.color[1] = 1; - g_tooltip.font_color.color[2] = 1; + g_tooltip.font_color.rgb[0] = 1; + g_tooltip.font_color.rgb[1] = 1; + g_tooltip.font_color.rgb[2] = 1; g_tooltip.font_color.alpha = 1; just_shown = 0; }@@ -217,28 +217,28 @@ cairo_t *c;
PangoLayout* layout; cs = cairo_xlib_surface_create(server.dsp, g_tooltip.window, server.visual, width, height); c = cairo_create(cs); - Color bc = g_tooltip.bg->back; + Color bc = g_tooltip.bg->fill_color; Border b = g_tooltip.bg->border; if (server.real_transparency) { clear_pixmap(g_tooltip.window, 0, 0, width, height); - draw_rect(c, b.width, b.width, width-2*b.width, height-2*b.width, b.rounded-b.width/1.571); - cairo_set_source_rgba(c, bc.color[0], bc.color[1], bc.color[2], bc.alpha); + draw_rect(c, b.width, b.width, width-2*b.width, height-2*b.width, b.radius-b.width/1.571); + cairo_set_source_rgba(c, bc.rgb[0], bc.rgb[1], bc.rgb[2], bc.alpha); } else { cairo_rectangle(c, 0., 0, width, height); - cairo_set_source_rgb(c, bc.color[0], bc.color[1], bc.color[2]); + cairo_set_source_rgb(c, bc.rgb[0], bc.rgb[1], bc.rgb[2]); } cairo_fill(c); cairo_set_line_width(c, b.width); if (server.real_transparency) - draw_rect(c, b.width/2.0, b.width/2.0, width - b.width, height - b.width, b.rounded); + draw_rect(c, b.width/2.0, b.width/2.0, width - b.width, height - b.width, b.radius); else cairo_rectangle(c, b.width/2.0, b.width/2.0, width-b.width, height-b.width); - cairo_set_source_rgba(c, b.color[0], b.color[1], b.color[2], b.alpha); + cairo_set_source_rgba(c, b.color.rgb[0], b.color.rgb[1], b.color.rgb[2], b.color.alpha); cairo_stroke(c); Color fc = g_tooltip.font_color; - cairo_set_source_rgba(c, fc.color[0], fc.color[1], fc.color[2], fc.alpha); + cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha); layout = pango_cairo_create_layout(c); pango_layout_set_font_description(layout, g_tooltip.font_desc); pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
@@ -30,50 +30,9 @@ #include "area.h"
#include "server.h" #include "panel.h" - -/************************************************************ - * !!! This design is experimental and not yet fully implemented !!!!!!!!!!!!! - * - * DATA ORGANISATION : - * Areas in tint2 are similar to widgets in a GUI. - * All graphical objects (panel, taskbar, task, systray, clock, ...) 'inherit' an abstract class 'Area'. - * This class 'Area' manage the background, border, size, position and padding. - * Area is at the begining of each object (&object == &area). - * - * tint2 define one panel per monitor. And each panel have a tree of Area. - * The root of the tree is Panel.Area. And task, clock, systray, taskbar,... are nodes. - * - * The tree give the localisation of each object : - * - tree's root is in the background while tree's leafe are foreground objects - * - position of a node/Area depend on the layout : parent's position (posx, posy), size of previous brothers and parent's padding - * - size of a node/Area depend on the content (SIZE_BY_CONTENT objects) or on the layout (SIZE_BY_LAYOUT objects) - * - * DRAWING AND LAYERING ENGINE : - * Redrawing an object (like the clock) could come from an 'external event' (date change) - * or from a 'layering event' (position change). - * The following 'drawing engine' take care of : - * - posx/posy of all Area - * - 'layering event' propagation between object - * 1) browse tree SIZE_BY_CONTENT - * - resize SIZE_BY_CONTENT node : children are resized before parent - * - if 'size' changed then 'resize = 1' on the parent - * 2) browse tree SIZE_BY_LAYOUT and POSITION - * - resize SIZE_BY_LAYOUT node : parent is resized before children - * - calculate position (posx,posy) : parent is calculated before children - * - if 'position' changed then 'redraw = 1' - * 3) browse tree REDRAW - * - redraw needed objects : parent is drawn before children - * - * CONFIGURE PANEL'S LAYOUT : - * 'panel_items' parameter (in config) define the list and the order of nodes in tree's panel. - * 'panel_items = SC' define a panel with just Systray and Clock. - * So the tree 'Panel.Area' will have 2 childs (Systray and Clock). - * - ************************************************************/ - Area *mouse_over_area = NULL; -void init_rendering(void *obj, int pos) +void initialize_positions(void *obj, int pos) { Area *a = (Area*)obj;@@ -86,58 +45,47 @@ child->posy = pos + a->bg->border.width + a->paddingy;
child->height = a->height - (2 * (a->bg->border.width + a->paddingy)); if (child->_on_change_layout) child->_on_change_layout(child); - init_rendering(child, child->posy); + initialize_positions(child, child->posy); } else { child->posx = pos + a->bg->border.width + a->paddingy; child->width = a->width - (2 * (a->bg->border.width + a->paddingy)); if (child->_on_change_layout) child->_on_change_layout(child); - init_rendering(child, child->posx); + initialize_positions(child, child->posx); } } } -void rendering(void *obj) -{ - Panel *panel = (Panel*)obj; - - size_by_content(&panel->area); - size_by_layout(&panel->area, 1); - - refresh(&panel->area); -} - - -void size_by_content (Area *a) +void _relayout_fixed(Area *a) { - // don't resize hiden objects if (!a->on_screen) return; - // children node are resized before its parent + // Children are resized before the parent GList *l; for (l = a->children; l ; l = l->next) - size_by_content(l->data); + _relayout_fixed(l->data); - // calculate area's size - a->on_changed = 0; - if (a->resize && a->size_mode == SIZE_BY_CONTENT) { - a->resize = 0; + // Recalculate size + a->_changed = 0; + if (a->resize_needed && a->size_mode == LAYOUT_FIXED) { + a->resize_needed = 0; if (a->_resize) { if (a->_resize(a)) { - // 'size' changed => 'resize = 1' on the parent - ((Area*)a->parent)->resize = 1; - a->on_changed = 1; + // The size hash changed => resize needed for the parent + if (a->parent) + ((Area*)a->parent)->resize_needed = 1; + a->_changed = 1; } } } } -void size_by_layout (Area *a, int level) +void _relayout_dynamic(Area *a, int level) { // don't resize hiden objects if (!a->on_screen)@@ -146,16 +94,16 @@
// parent node is resized before its children // calculate area's size GList *l; - if (a->resize && a->size_mode == SIZE_BY_LAYOUT) { - a->resize = 0; + if (a->resize_needed && a->size_mode == LAYOUT_DYNAMIC) { + a->resize_needed = 0; if (a->_resize) { a->_resize(a); - // resize childs with SIZE_BY_LAYOUT + // resize children with LAYOUT_DYNAMIC for (l = a->children; l ; l = l->next) { Area *child = ((Area*)l->data); - if (child->size_mode == SIZE_BY_LAYOUT && child->children) - child->resize = 1; + if (child->size_mode == LAYOUT_DYNAMIC && child->children) + child->resize_needed = 1; } } }@@ -174,17 +122,17 @@ if (panel_horizontal) {
if (pos != child->posx) { // pos changed => redraw child->posx = pos; - child->on_changed = 1; + child->_changed = 1; } } else { if (pos != child->posy) { // pos changed => redraw child->posy = pos; - child->on_changed = 1; + child->_changed = 1; } } - size_by_layout(child, level+1); + _relayout_dynamic(child, level+1); pos += panel_horizontal ? child->width + a->paddingx : child->height + a->paddingx; }@@ -202,17 +150,17 @@ if (panel_horizontal) {
if (pos != child->posx) { // pos changed => redraw child->posx = pos; - child->on_changed = 1; + child->_changed = 1; } } else { if (pos != child->posy) { // pos changed => redraw child->posy = pos; - child->on_changed = 1; + child->_changed = 1; } } - size_by_layout(child, level+1); + _relayout_dynamic(child, level+1); pos -= a->paddingx; }@@ -241,76 +189,77 @@ if (panel_horizontal) {
if (pos != child->posx) { // pos changed => redraw child->posx = pos; - child->on_changed = 1; + child->_changed = 1; } } else { if (pos != child->posy) { // pos changed => redraw child->posy = pos; - child->on_changed = 1; + child->_changed = 1; } } - size_by_layout(child, level+1); + _relayout_dynamic(child, level+1); pos += panel_horizontal ? child->width + a->paddingx : child->height + a->paddingx; } } } - if (a->on_changed) { + if (a->_changed) { // pos/size changed - a->redraw = 1; + a->redraw_needed = 1; if (a->_on_change_layout) a->_on_change_layout (a); } } -void refresh (Area *a) +void draw_tree (Area *a) { - // don't draw and resize hide objects - if (!a->on_screen) return; + if (!a->on_screen) + return; // don't draw transparent objects (without foreground and without background) - if (a->redraw) { - a->redraw = 0; + if (a->redraw_needed) { + a->redraw_needed = 0; // force redraw of child //GList *l; //for (l = a->children ; l ; l = l->next) - //((Area*)l->data)->redraw = 1; + //((Area*)l->data)->redraw_needed = 1; //printf("draw area posx %d, width %d\n", a->posx, a->width); draw(a); } // draw current Area - if (a->pix == 0) printf("empty area posx %d, width %d\n", a->posx, a->width); - XCopyArea (server.dsp, a->pix, ((Panel *)a->panel)->temp_pmap, server.gc, 0, 0, a->width, a->height, a->posx, a->posy); + if (a->pix == 0) + printf("empty area posx %d, width %d\n", a->posx, a->width); + XCopyArea(server.dsp, a->pix, ((Panel *)a->panel)->temp_pmap, server.gc, 0, 0, a->width, a->height, a->posx, a->posy); - // and then refresh child object + // and then draw child objects GList *l; for (l = a->children; l ; l = l->next) - refresh((Area*)l->data); + draw_tree((Area*)l->data); } -int resize_by_layout(void *obj, int maximum_size) +int relayout_with_constraint(Area *a, int maximum_size) { - Area *child, *a = (Area*)obj; + Area *child; int size, nb_by_content=0, nb_by_layout=0; if (panel_horizontal) { - // detect free size for SIZE_BY_LAYOUT's Area + // detect free size for LAYOUT_DYNAMIC's Area size = a->width - (2 * (a->paddingxlr + a->bg->border.width)); GList *l; for (l = a->children ; l ; l = l->next) { child = (Area*)l->data; - if (child->on_screen && child->size_mode == SIZE_BY_CONTENT) { + if (child->on_screen && child->size_mode == LAYOUT_FIXED) { size -= child->width; nb_by_content++; } - if (child->on_screen && child->size_mode == SIZE_BY_LAYOUT) + if (child->on_screen && child->size_mode == LAYOUT_DYNAMIC) nb_by_layout++; } //printf(" resize_by_layout Deb %d, %d\n", nb_by_content, nb_by_layout);@@ -327,10 +276,10 @@ modulo = 0;
} } - // resize SIZE_BY_LAYOUT objects + // resize LAYOUT_DYNAMIC objects for (l = a->children ; l ; l = l->next) { child = (Area*)l->data; - if (child->on_screen && child->size_mode == SIZE_BY_LAYOUT) { + if (child->on_screen && child->size_mode == LAYOUT_DYNAMIC) { old_width = child->width; child->width = width; if (modulo) {@@ -338,21 +287,21 @@ child->width++;
modulo--; } if (child->width != old_width) - child->on_changed = 1; + child->_changed = 1; } } } else { - // detect free size for SIZE_BY_LAYOUT's Area + // detect free size for LAYOUT_DYNAMIC's Area size = a->height - (2 * (a->paddingxlr + a->bg->border.width)); GList *l; for (l = a->children ; l ; l = l->next) { child = (Area*)l->data; - if (child->on_screen && child->size_mode == SIZE_BY_CONTENT) { + if (child->on_screen && child->size_mode == LAYOUT_FIXED) { size -= child->height; nb_by_content++; } - if (child->on_screen && child->size_mode == SIZE_BY_LAYOUT) + if (child->on_screen && child->size_mode == LAYOUT_DYNAMIC) nb_by_layout++; } if (nb_by_content+nb_by_layout)@@ -368,10 +317,10 @@ modulo = 0;
} } - // resize SIZE_BY_LAYOUT objects + // resize LAYOUT_DYNAMIC objects for (l = a->children ; l ; l = l->next) { child = (Area*)l->data; - if (child->on_screen && child->size_mode == SIZE_BY_LAYOUT) { + if (child->on_screen && child->size_mode == LAYOUT_DYNAMIC) { int old_height = child->height; child->height = height; if (modulo) {@@ -379,7 +328,7 @@ child->height++;
modulo--; } if (child->height != old_height) - child->on_changed = 1; + child->_changed = 1; } } }@@ -387,13 +336,13 @@ return 0;
} -void set_redraw (Area *a) +void schedule_redraw(Area *a) { - a->redraw = 1; + a->redraw_needed = 1; GList *l; for (l = a->children ; l ; l = l->next) - set_redraw((Area*)l->data); + schedule_redraw((Area*)l->data); } void hide(Area *a)@@ -401,7 +350,8 @@ {
Area *parent = (Area*)a->parent; a->on_screen = 0; - parent->resize = 1; + if (parent) + parent->resize_needed = 1; if (panel_horizontal) a->width = 0; else@@ -413,19 +363,21 @@ {
Area *parent = (Area*)a->parent; a->on_screen = 1; - parent->resize = 1; - a->resize = 1; + if (parent) + parent->resize_needed = 1; + a->resize_needed = 1; } -void draw (Area *a) +void draw(Area *a) { - if (a->pix) XFreePixmap (server.dsp, a->pix); - a->pix = XCreatePixmap (server.dsp, server.root_win, a->width, a->height, server.depth); + if (a->pix) + XFreePixmap(server.dsp, a->pix); + a->pix = XCreatePixmap(server.dsp, server.root_win, a->width, a->height, server.depth); // add layer of root pixmap (or clear pixmap if real_transparency==true) if (server.real_transparency) clear_pixmap(a->pix, 0 ,0, a->width, a->height); - XCopyArea (server.dsp, ((Panel *)a->panel)->temp_pmap, a->pix, server.gc, a->posx, a->posy, a->width, a->height, 0, 0); + XCopyArea(server.dsp, ((Panel *)a->panel)->temp_pmap, a->pix, server.gc, a->posx, a->posy, a->width, a->height, 0, 0); cairo_surface_t *cs; cairo_t *c;@@ -433,28 +385,28 @@
cs = cairo_xlib_surface_create (server.dsp, a->pix, server.visual, a->width, a->height); c = cairo_create (cs); - draw_background (a, c); + draw_background(a, c); if (a->_draw_foreground) a->_draw_foreground(a, c); - cairo_destroy (c); - cairo_surface_destroy (cs); + cairo_destroy(c); + cairo_surface_destroy(cs); } void draw_background (Area *a, cairo_t *c) { - if (a->bg->back.alpha > 0.0 || - (panel_config.mouse_effects && (a->mouse_over_effect || a->mouse_press_effect))) { - //printf(" draw_background (%d %d) RGBA (%lf, %lf, %lf, %lf)\n", a->posx, a->posy, pix->back.color[0], pix->back.color[1], pix->back.color[2], pix->back.alpha); + if (a->bg->fill_color.alpha > 0.0 || + (panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect))) { + //printf(" draw_background (%d %d) RGBA (%lf, %lf, %lf, %lf)\n", a->posx, a->posy, pix->fill_color.rgb[0], pix->fill_color.rgb[1], pix->fill_color.rgb[2], pix->fill_color.alpha); if (a->mouse_state == MOUSE_OVER) - cairo_set_source_rgba(c, a->bg->back_hover.color[0], a->bg->back_hover.color[1], a->bg->back_hover.color[2], a->bg->back_hover.alpha); + cairo_set_source_rgba(c, a->bg->fill_color_hover.rgb[0], a->bg->fill_color_hover.rgb[1], a->bg->fill_color_hover.rgb[2], a->bg->fill_color_hover.alpha); else if (a->mouse_state == MOUSE_DOWN) - cairo_set_source_rgba(c, a->bg->back_pressed.color[0], a->bg->back_pressed.color[1], a->bg->back_pressed.color[2], a->bg->back_pressed.alpha); + cairo_set_source_rgba(c, a->bg->fill_color_pressed.rgb[0], a->bg->fill_color_pressed.rgb[1], a->bg->fill_color_pressed.rgb[2], a->bg->fill_color_pressed.alpha); else - cairo_set_source_rgba(c, a->bg->back.color[0], a->bg->back.color[1], a->bg->back.color[2], a->bg->back.alpha); - draw_rect(c, a->bg->border.width, a->bg->border.width, a->width-(2.0 * a->bg->border.width), a->height-(2.0*a->bg->border.width), a->bg->border.rounded - a->bg->border.width/1.571); + cairo_set_source_rgba(c, a->bg->fill_color.rgb[0], a->bg->fill_color.rgb[1], a->bg->fill_color.rgb[2], a->bg->fill_color.alpha); + draw_rect(c, a->bg->border.width, a->bg->border.width, a->width-(2.0 * a->bg->border.width), a->height-(2.0*a->bg->border.width), a->bg->border.radius - a->bg->border.width/1.571); cairo_fill(c); }@@ -463,27 +415,27 @@ cairo_set_line_width (c, a->bg->border.width);
// draw border inside (x, y, width, height) if (a->mouse_state == MOUSE_OVER) - cairo_set_source_rgba(c, a->bg->border_hover.color[0], a->bg->border_hover.color[1], a->bg->border_hover.color[2], a->bg->border_hover.alpha); + cairo_set_source_rgba(c, a->bg->border_color_hover.rgb[0], a->bg->border_color_hover.rgb[1], a->bg->border_color_hover.rgb[2], a->bg->border_color_hover.alpha); else if (a->mouse_state == MOUSE_DOWN) - cairo_set_source_rgba(c, a->bg->border_pressed.color[0], a->bg->border_pressed.color[1], a->bg->border_pressed.color[2], a->bg->border_pressed.alpha); + cairo_set_source_rgba(c, a->bg->border_color_pressed.rgb[0], a->bg->border_color_pressed.rgb[1], a->bg->border_color_pressed.rgb[2], a->bg->border_color_pressed.alpha); else - cairo_set_source_rgba(c, a->bg->border.color[0], a->bg->border.color[1], a->bg->border.color[2], a->bg->border.alpha); - draw_rect(c, a->bg->border.width/2.0, a->bg->border.width/2.0, a->width - a->bg->border.width, a->height - a->bg->border.width, a->bg->border.rounded); + cairo_set_source_rgba(c, a->bg->border.color.rgb[0], a->bg->border.color.rgb[1], a->bg->border.color.rgb[2], a->bg->border.color.alpha); + draw_rect(c, a->bg->border.width/2.0, a->bg->border.width/2.0, a->width - a->bg->border.width, a->height - a->bg->border.width, a->bg->border.radius); cairo_stroke(c); } } -void remove_area (void *a) +void remove_area(Area *a) { Area *area = (Area*)a; Area *parent = (Area*)area->parent; if (parent) { parent->children = g_list_remove(parent->children, area); - parent->resize = 1; - set_redraw(parent); + parent->resize_needed = 1; + schedule_redraw(parent); } if (mouse_over_area == a) {@@ -492,13 +444,15 @@ }
} -void add_area (Area *a) +void add_area(Area *a, Area *parent) { - Area *parent = (Area*)a->parent; + g_assert_null(a->parent); - parent->children = g_list_append(parent->children, a); - set_redraw (parent); - + a->parent = parent; + if (parent) { + parent->children = g_list_append(parent->children, a); + schedule_redraw(parent); + } }@@ -525,34 +479,6 @@ }
} -void draw_rect(cairo_t *c, double x, double y, double w, double h, double r) -{ - if (r > 0.0) { - double c1 = 0.55228475 * r; - - cairo_move_to(c, x+r, y); - cairo_rel_line_to(c, w-2*r, 0); - cairo_rel_curve_to(c, c1, 0.0, r, c1, r, r); - cairo_rel_line_to(c, 0, h-2*r); - cairo_rel_curve_to(c, 0.0, c1, c1-r, r, -r, r); - cairo_rel_line_to (c, -w +2*r, 0); - cairo_rel_curve_to (c, -c1, 0, -r, -c1, -r, -r); - cairo_rel_line_to (c, 0, -h + 2 * r); - cairo_rel_curve_to (c, 0, -c1, r - c1, -r, r, -r); - } - else - cairo_rectangle(c, x, y, w, h); -} - - -void clear_pixmap(Pixmap p, int x, int y, int w, int h) -{ - Picture pict = XRenderCreatePicture(server.dsp, p, XRenderFindVisualFormat(server.dsp, server.visual), 0, 0); - XRenderColor col = { .red=0, .green=0, .blue=0, .alpha=0 }; - XRenderFillRectangle(server.dsp, PictOpSrc, pict, &col, x, y, w, h); - XRenderFreePicture(server.dsp, pict); -} - void mouse_over(Area *area, int pressed) { if (mouse_over_area == area && !area)@@ -561,11 +487,11 @@
MouseState new_state = MOUSE_NORMAL; if (area) { if (!pressed) { - new_state = area->mouse_over_effect ? MOUSE_OVER : MOUSE_NORMAL; + new_state = area->has_mouse_over_effect ? MOUSE_OVER : MOUSE_NORMAL; } else { - new_state = area->mouse_press_effect + new_state = area->has_mouse_press_effect ? MOUSE_DOWN - : area->mouse_over_effect + : area->has_mouse_over_effect ? MOUSE_OVER : MOUSE_NORMAL; }@@ -579,7 +505,7 @@ return;
mouse_over_area = area; mouse_over_area->mouse_state = new_state; - set_redraw(mouse_over_area); + schedule_redraw(mouse_over_area); panel_refresh = 1; }@@ -588,7 +514,7 @@ {
if (!mouse_over_area) return; mouse_over_area->mouse_state = MOUSE_NORMAL; - set_redraw(mouse_over_area); + schedule_redraw(mouse_over_area); panel_refresh = 1; mouse_over_area = NULL; }@@ -597,3 +523,9 @@ void init_background(Background *bg)
{ memset(bg, 0, sizeof(Background)); } + +void relayout(Area *a) +{ + _relayout_fixed(a); + _relayout_dynamic(a, 1); +}
@@ -1,19 +1,6 @@
/************************************************************************** * Copyright (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr) * -* base class for all graphical objects (panel, taskbar, task, systray, clock, ...). -* Area is at the begining of each object (&object == &area). -* -* Area manage the background and border drawing, size and padding. -* Each Area has one Pixmap (pix). -* -* Area manage the tree of all objects. Parent object drawn before child object. -* panel -> taskbars -> tasks -* -> systray -> icons -* -> clock -* -* draw_foreground(obj) and resize(obj) are virtual function. -* **************************************************************************/ #ifndef AREA_H@@ -24,129 +11,250 @@ #include <X11/Xlib.h>
#include <cairo.h> #include <cairo-xlib.h> +// DATA ORGANISATION +// +// Areas in tint2 are similar to widgets in a GUI. +// All graphical objects (panel, taskbar, task, systray, clock, ...) inherit the abstract class Area. +// This class 'Area' stores data about the background, border, size, position, padding and the child areas. +// Inheritance is simulated by having an Area member as the first member of each object (thus &object == &area). +// +// tint2 uses multiple panels, one per monitor. Each panel has an area containing the children objects in a tree of +// areas. The level in the tree gives the z-order: child areas are always displayed on top of their parents. +// +// +// LAYOUT +// +// Sibling areas never overlap. +// +// The position of an Area (posx, posy) is relative to the window (i.e. absolute) and +// is computed based on a simple box model: +// * parent position + parent padding + sum of the sizes of the previous siblings and spacing +// +// The size of an Area is: +// * SIZE_BY_CONTENT objects: +// * fixed and set by the Area +// * childred are resized before the parent +// * if a child size has changed then the parent is resized +// * SIZE_BY_LAYOUT objects: +// * expandable and computed as the total size of the parent - padding - +// the size of the fixed sized siblings - spacing and divided by the number of expandable siblings +// * the parent is resized before the children +// +// +// RENDERING +// +// Redrawing an object (like the clock) could come from an 'external event' (date change) +// or from a 'layout event' (position change). +// +// +// WIDGET LIFECYCLE +// +// Each widget that occurs once per panel is defined as a struct (e.g. Clock) which is stored as a member of Panel. +// Widgets that can occur more than once should be stored as an array, still as a member of Panel. +// +// There is a special Panel instance called 'panel_config' which stores the config options and the state variables +// of the widgets (however some config options are stored as global variables by the widgets). +// +// Tint2 maintains an array of Panel instances, one for each monitor. These contain the actual Areas that are used to +// render the panels on screen, interact with user input etc. +// Each Panel is initialized as a raw copy (memcpy, see init_panel()) of panel_config. +// +// Normally, widgets should implement the following functions: +// +// * void default_widget(); +// +// Called before the config is read and panel_config/panels are created. +// Afterwards, the config parsing code creates the widget/widget array in panel_config and +// populates the configuration fields. +// If the widget uses global variables to store config options or other state variables, they should be initialized +// here (e.g. with zero, NULL etc). +// +// * void init_widget(); +// +// Called after the config is read and panel_config is populated, but before panels are created. +// Initializes the state of the widget in panel_config. +// If the widget uses global variables to store config options or other state variables which depend on the config +// options but not on the panel instance, they should be initialized here. +// panel_config.panel_items can be used to determine which backend items are enabled. +// +// * void init_widget_panel(void *panel); +// +// Called after each on-screen panel is created, with a pointer to the panel. +// Completes the initialization of the widget. +// At this point the widget Area has not been added yet to the GUI tree, but it will be added right afterwards. +// +// * void cleanup_widget(); +// +// Called just before the panels are destroyed. Afterwards, tint2 exits or restarts and reads the config again. +// Must releases all resources. +// The widget itself should not be freed by this function, only its members or global variables that were set. +// The widget is freed by the Area tree cleanup function (remove_area). +// +// * void draw_widget(void *obj, cairo_t *c); +// +// Called on draw, obj = pointer to the widget instance from the panel that is redrawn. +// The Area's _draw_foreground member must point to this function. +// +// * int resize_widget(void *obj); +// +// Called on resize, obj = pointer to the front-end Execp item. +// Returns 1 if the new size is different than the previous size. +// The Area's _resize member must point to this function. +// +// * void widget_action(void *obj, int button); +// +// Called on mouse click event. +// +// * void widget_on_change_layout(void *obj); +// +// Implemented only to override the default layout algorithm for this widget. +// For example, if this widget is a cell in a table, its position and size should be computed here. +// The Area's _on_change_layout member must point to this function. +// +// * char* widget_get_tooltip_text(void *obj); +// +// Returns a copy of the tooltip to be displayed for this widget. +// The caller takes ownership of the pointer. +// The Area's _get_tooltip_text member must point to this function. -typedef struct -{ - double color[3]; +typedef struct Color { + // Values are in [0, 1], with 0 meaning no intensity. + double rgb[3]; + // Values are in [0, 1], with 0 meaning fully transparent, 1 meaning fully opaque. double alpha; +} Color; + +typedef struct Border { + // It's essential that the first member is color + Color color; + // Width in pixels int width; - int rounded; + // Corner radius + int radius; } Border; - -typedef struct -{ - double color[3]; - double alpha; -} Color; - -typedef struct -{ - Color back; +typedef struct Background { + // Normal state + Color fill_color; Border border; - Color back_hover; - Color border_hover; - Color back_pressed; - Color border_pressed; + // On mouse hover + Color fill_color_hover; + Color border_color_hover; + // On mouse press + Color fill_color_pressed; + Color border_color_pressed; } Background; +typedef enum Layout { + LAYOUT_DYNAMIC, + LAYOUT_FIXED +} Layout; -// way to calculate the size -// SIZE_BY_LAYOUT objects : taskbar and task -// SIZE_BY_CONTENT objects : clock, battery, launcher, systray -enum { SIZE_BY_LAYOUT, SIZE_BY_CONTENT }; -enum { ALIGN_LEFT = 0, ALIGN_CENTER = 1, ALIGN_RIGHT = 2 }; +typedef enum Alignment { + ALIGN_LEFT = 0, + ALIGN_CENTER = 1, + ALIGN_RIGHT = 2 +} Alignment; -typedef enum { +typedef enum MouseState { MOUSE_NORMAL = 0, MOUSE_OVER = 1, MOUSE_DOWN = 2 } MouseState; - -typedef struct { - // coordinate relative to panel window +typedef struct Area { + // Position relative to the panel window int posx, posy; - // width and height including border + // Size, including borders int width, height; - Pixmap pix; Background *bg; - - // list of child : Area object + // List of children, each one a pointer to Area GList *children; - - // object visible on screen. - // An object (like systray) could be enabled but hidden (because no tray icon). - int on_screen; - // way to calculate the size (SIZE_BY_CONTENT or SIZE_BY_LAYOUT) - int size_mode; - - int alignment; - // need to calculate position and width - int resize; - // need redraw Pixmap - int redraw; - // paddingxlr = horizontal padding left/right - // paddingx = horizontal padding between childs - int paddingxlr, paddingx, paddingy; - // parent Area + // Pointer to the parent Area or NULL void *parent; - // panel + // Pointer to the Panel that contains this Area void *panel; + Layout size_mode; + Alignment alignment; + gboolean has_mouse_over_effect; + gboolean has_mouse_press_effect; + // TODO padding/spacing is a clusterfuck + // paddingxlr = padding + // paddingy = vertical padding, sometimes + // paddingx = spacing + int paddingxlr, paddingx, paddingy; + MouseState mouse_state; + // Set to non-zero if the Area is visible. An object may exist but stay hidden. + gboolean on_screen; + // Set to non-zero if the size of the Area has to be recalculated. + gboolean resize_needed; + // Set to non-zero if the Area has to be redrawn. + gboolean redraw_needed; + // Set to non-zero if the position/size has changed, thus _on_change_layout needs to be called + gboolean _changed; + // This is the pixmap on which the Area is rendered. Render to it directly if needed. + Pixmap pix; - int mouse_over_effect; - int mouse_press_effect; - MouseState mouse_state; + // Callbacks - // each object can overwrite following function + // Called on draw, obj = pointer to the Area void (*_draw_foreground)(void *obj, cairo_t *c); - // update area's content and update size (width/heith). - // return '1' if size changed, '0' otherwise. + + // Called on resize, obj = pointer to the Area + // Returns 1 if the new size is different than the previous size. int (*_resize)(void *obj); - // after pos/size changed, the rendering engine will call _on_change_layout(Area*) - int on_changed; + + // Implemented only to override the default layout algorithm for this widget. + // For example, if this widget is a cell in a table, its position and size should be computed here. void (*_on_change_layout)(void *obj); - // returns allocated string, that must be free'd after usage + + // Returns a copy of the tooltip to be displayed for this widget. + // The caller takes ownership of the pointer. char* (*_get_tooltip_text)(void *obj); } Area; + +// Initializes the Background member to default values. void init_background(Background *bg); -// on startup, initialize fixed pos/size -void init_rendering(void *obj, int pos); +// Layout -void rendering(void *obj); -void size_by_content (Area *a); -void size_by_layout (Area *a, int level); -// draw background and foreground -void refresh (Area *a); - -// generic resize for SIZE_BY_LAYOUT objects -int resize_by_layout(void *obj, int maximum_size); +// Called on startup to initialize the positions of all Areas in the Area tree. +// Parameters: +// * obj: pointer to Area +// * pos: offset in pixels from left/top +void initialize_positions(void *obj, int pos); +// Relayouts the Area and its children. Normally called on the root of the tree (i.e. the Panel). +void relayout(Area *a); +// Distributes the Area's size to its children, repositioning them as needed. +// If maximum_size > 0, it is an upper limit for the child size. +int relayout_with_constraint(Area *a, int maximum_size); -// set 'redraw' on an area and childs -void set_redraw (Area *a); +// Rendering -// hide/unhide area +// Sets the redraw_needed flag on the area and its descendants +void schedule_redraw(Area *a); +// Recreates the Area pixmap and draws the background and the foreground +void draw(Area *a); +// Draws the background of the Area +void draw_background(Area *a, cairo_t *c); +// Explores the entire Area subtree (only if the on_screen flag set) +// and draws the areas with the redraw_needed flag set +void draw_tree(Area *a); +// Clears the on_screen flag, sets the size to zero and triggers a parent resize void hide(Area *a); +// Sets the on_screen flag and triggers a parent and area resize void show(Area *a); -// draw pixmap -void draw (Area *a); -void draw_background (Area *a, cairo_t *c); - -void remove_area (void *a); -void add_area (Area *a); -void free_area (Area *a); +// Area tree -// draw rounded rectangle -void draw_rect(cairo_t *c, double x, double y, double w, double h, double r); +void add_area(Area *a, Area *parent); +void remove_area(Area *a); +void free_area(Area *a); -// clear pixmap with transparent color -void clear_pixmap(Pixmap p, int x, int y, int w, int h); +// Mouse move events void mouse_over(Area *area, int pressed); void mouse_out(); #endif -
@@ -455,7 +455,7 @@ pango_cairo_show_layout(c, layout);
} } } - cairo_set_source_rgba (c, color->color[0], color->color[1], color->color[2], color->alpha); + cairo_set_source_rgba (c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha); pango_cairo_update_layout (c, layout); cairo_move_to (c, posx, posy); pango_cairo_show_layout (c, layout);@@ -524,3 +524,31 @@ adjust_asb(data, imlib_image_get_width(), imlib_image_get_height(), alpha, (float)saturation/100, (float)brightness/100);
imlib_image_put_back_data(data); return copy; } + +void draw_rect(cairo_t *c, double x, double y, double w, double h, double r) +{ + if (r > 0.0) { + double c1 = 0.55228475 * r; + + cairo_move_to(c, x+r, y); + cairo_rel_line_to(c, w-2*r, 0); + cairo_rel_curve_to(c, c1, 0.0, r, c1, r, r); + cairo_rel_line_to(c, 0, h-2*r); + cairo_rel_curve_to(c, 0.0, c1, c1-r, r, -r, r); + cairo_rel_line_to (c, -w +2*r, 0); + cairo_rel_curve_to (c, -c1, 0, -r, -c1, -r, -r); + cairo_rel_line_to (c, 0, -h + 2 * r); + cairo_rel_curve_to (c, 0, -c1, r - c1, -r, r, -r); + } + else + cairo_rectangle(c, x, y, w, h); +} + + +void clear_pixmap(Pixmap p, int x, int y, int w, int h) +{ + Picture pict = XRenderCreatePicture(server.dsp, p, XRenderFindVisualFormat(server.dsp, server.visual), 0, 0); + XRenderColor col = { .red=0, .green=0, .blue=0, .alpha=0 }; + XRenderFillRectangle(server.dsp, PictOpSrc, pict, &col, x, y, w, h); + XRenderFreePicture(server.dsp, pict); +}
@@ -78,5 +78,11 @@ Imlib_Image load_image(const char *path, int cached);
Imlib_Image adjust_icon(Imlib_Image original, int alpha, int saturation, int brightness); +// draw rounded rectangle +void draw_rect(cairo_t *c, double x, double y, double w, double h, double r); + +// clear pixmap with transparent color +void clear_pixmap(Pixmap p, int x, int y, int w, int h); + #endif