From a6da0186e033c008c088ff7c0b39fd9570ad3762 Mon Sep 17 00:00:00 2001 From: o9000 Date: Fri, 1 Jan 2016 04:57:08 +0100 Subject: [PATCH] Cache pixmaps for mouse effects to improve performance --- src/battery/battery.c | 9 ++++---- src/clock/clock.c | 8 +++---- src/execplugin/execplugin.c | 8 +++---- src/freespace/freespace.c | 2 +- src/launcher/launcher.c | 8 +++---- src/systray/systraybar.c | 8 +++---- src/taskbar/task.c | 15 ++++++------ src/taskbar/taskbar.c | 10 ++++---- src/taskbar/taskbarname.c | 8 +++---- src/util/area.c | 46 +++++++++++++++++++++++++++++-------- src/util/area.h | 5 +++- 11 files changed, 80 insertions(+), 47 deletions(-) diff --git a/src/battery/battery.c b/src/battery/battery.c index b4317ef..ea88989 100644 --- a/src/battery/battery.c +++ b/src/battery/battery.c @@ -155,8 +155,9 @@ void init_battery_panel(void *p) battery->area._resize = resize_battery; battery->area.on_screen = TRUE; 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.has_mouse_over_effect = panel_config.mouse_effects && + (battery_lclick_command || battery_mclick_command || battery_rclick_command || + battery_uwheel_command || battery_dwheel_command); battery->area.has_mouse_press_effect = battery->area.has_mouse_over_effect; if (battery_tooltip_enabled) battery->area._get_tooltip_text = battery_get_tooltip; @@ -193,7 +194,7 @@ void battery_default_font_changed() battery_init_fonts(); for (int i = 0; i < num_panels; i++) { panels[i].battery.area.resize_needed = TRUE; - panels[i].battery.area.redraw_needed = TRUE; + schedule_redraw(&panels[i].battery.area); } panel_refresh = TRUE; } @@ -292,7 +293,7 @@ gboolean resize_battery(void *obj) int bat_time_height, bat_time_width, bat_time_height_ink; int ret = 0; - battery->area.redraw_needed = TRUE; + schedule_redraw(&battery->area); snprintf(buf_bat_percentage, sizeof(buf_bat_percentage), "%d%%", battery_state.percentage); if (battery_state.state == BATTERY_FULL) { diff --git a/src/clock/clock.c b/src/clock/clock.c index 6064d39..9032ee4 100644 --- a/src/clock/clock.c +++ b/src/clock/clock.c @@ -181,8 +181,8 @@ void init_clock_panel(void *p) clock->area.parent = p; clock->area.panel = p; 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; + panel_config.mouse_effects && (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 = LAYOUT_FIXED; clock->area._resize = resize_clock; @@ -231,7 +231,7 @@ void clock_default_font_changed() clock_init_fonts(); for (int i = 0; i < num_panels; i++) { panels[i].clock.area.resize_needed = TRUE; - panels[i].clock.area.redraw_needed = TRUE; + schedule_redraw(&panels[i].clock.area); } panel_refresh = TRUE; } @@ -243,7 +243,7 @@ gboolean resize_clock(void *obj) int time_height_ink, time_height, time_width, date_height_ink, date_height, date_width; gboolean result = FALSE; - clock->area.redraw_needed = TRUE; + schedule_redraw(&clock->area); date_height = date_width = 0; strftime(buf_time, sizeof(buf_time), time1_format, clock_gettime_for_tz(time1_timezone)); diff --git a/src/execplugin/execplugin.c b/src/execplugin/execplugin.c index 7f5e140..b270f43 100644 --- a/src/execplugin/execplugin.c +++ b/src/execplugin/execplugin.c @@ -162,9 +162,9 @@ void init_execp_panel(void *p) execp->area.size_mode = LAYOUT_FIXED; execp->area._resize = resize_execp; execp->area._get_tooltip_text = execp_get_tooltip; - execp->area.has_mouse_press_effect = execp->area.has_mouse_over_effect = - execp->backend->lclick_command || execp->backend->mclick_command || execp->backend->rclick_command || - execp->backend->uwheel_command || execp->backend->dwheel_command; + execp->area.has_mouse_press_effect = panel_config.mouse_effects && (execp->area.has_mouse_over_effect = + execp->backend->lclick_command || execp->backend->mclick_command || execp->backend->rclick_command || + execp->backend->uwheel_command || execp->backend->dwheel_command); execp->area.resize_needed = TRUE; execp->area.on_screen = TRUE; @@ -205,7 +205,7 @@ void execp_default_font_changed() if (!execp->backend->has_font) { execp->area.resize_needed = TRUE; - execp->area.redraw_needed = TRUE; + schedule_redraw(&execp->area); } } } diff --git a/src/freespace/freespace.c b/src/freespace/freespace.c index 676880f..56b81a6 100644 --- a/src/freespace/freespace.c +++ b/src/freespace/freespace.c @@ -87,7 +87,7 @@ gboolean resize_freespace(void *obj) freespace->area.height = size; } - freespace->area.redraw_needed = TRUE; + schedule_redraw(&freespace->area); panel_refresh = TRUE; return TRUE; } diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c index c56d63d..639f00c 100644 --- a/src/launcher/launcher.c +++ b/src/launcher/launcher.c @@ -87,7 +87,7 @@ void init_launcher_panel(void *p) launcher->area.size_mode = LAYOUT_FIXED; launcher->area._resize = resize_launcher; launcher->area.resize_needed = 1; - launcher->area.redraw_needed = TRUE; + schedule_redraw(&launcher->area); if (!launcher->area.bg) launcher->area.bg = &g_array_index(backgrounds, Background, 0); @@ -441,9 +441,9 @@ void launcher_load_icons(Launcher *launcher) launcherIcon->area.size_mode = LAYOUT_FIXED; launcherIcon->area._resize = NULL; launcherIcon->area.resize_needed = 0; - launcherIcon->area.redraw_needed = TRUE; - launcherIcon->area.has_mouse_over_effect = 1; - launcherIcon->area.has_mouse_press_effect = 1; + schedule_redraw(&launcherIcon->area); + launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects; + launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect; launcherIcon->area.bg = launcher_icon_bg; launcherIcon->area.on_screen = TRUE; launcherIcon->area._on_change_layout = launcher_icon_on_change_layout; diff --git a/src/systray/systraybar.c b/src/systray/systraybar.c index 8c7845b..febac85 100644 --- a/src/systray/systraybar.c +++ b/src/systray/systraybar.c @@ -116,8 +116,8 @@ void init_systray_panel(void *p) systray.area.bg = &g_array_index(backgrounds, Background, 0); show(&systray.area); systray.area.resize_needed = 1; - systray.area.redraw_needed = TRUE; panel->area.resize_needed = 1; + schedule_redraw(&systray.area); panel_refresh = TRUE; refresh_systray = 1; } @@ -721,7 +721,7 @@ gboolean add_icon(Window win) if (systray_profile) fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__); systray.area.resize_needed = TRUE; - systray.area.redraw_needed = TRUE; + schedule_redraw(&systray.area); panel->area.resize_needed = TRUE; panel_refresh = TRUE; refresh_systray = TRUE; @@ -984,7 +984,7 @@ void remove_icon(TrayWindow *traywin) if (systray_profile) fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__); systray.area.resize_needed = TRUE; - systray.area.redraw_needed = TRUE; + schedule_redraw(&systray.area); panel->area.resize_needed = TRUE; panel_refresh = TRUE; refresh_systray = TRUE; @@ -1399,7 +1399,7 @@ void systray_render_icon_composited(void *t) __FUNCTION__, __LINE__); systray.area.resize_needed = 1; - systray.area.redraw_needed = TRUE; + schedule_redraw(&systray.area); panel->area.resize_needed = 1; panel_refresh = TRUE; refresh_systray = 1; diff --git a/src/taskbar/task.c b/src/taskbar/task.c index bd53fc3..93b155a 100644 --- a/src/taskbar/task.c +++ b/src/taskbar/task.c @@ -67,8 +67,8 @@ Task *add_task(Window win) Task task_template; memset(&task_template, 0, sizeof(task_template)); - task_template.area.has_mouse_over_effect = TRUE; - task_template.area.has_mouse_press_effect = TRUE; + task_template.area.has_mouse_over_effect = panel_config.mouse_effects; + task_template.area.has_mouse_press_effect = panel_config.mouse_effects; task_template.win = win; task_template.desktop = get_window_desktop(win); task_template.area.panel = &panels[monitor]; @@ -96,8 +96,8 @@ Task *add_task(Window win) Taskbar *taskbar = &panels[monitor].taskbar[j]; Task *task_instance = calloc(1, sizeof(Task)); memcpy(&task_instance->area, &panels[monitor].g_task.area, sizeof(Area)); - task_instance->area.has_mouse_over_effect = TRUE; - task_instance->area.has_mouse_press_effect = TRUE; + task_instance->area.has_mouse_over_effect = panel_config.mouse_effects; + task_instance->area.has_mouse_press_effect = panel_config.mouse_effects; task_instance->win = task_template.win; task_instance->desktop = task_template.desktop; task_instance->win_x = task_template.win_x; @@ -576,9 +576,10 @@ void set_task_state(Task *task, TaskState state) if (!panel_config.mouse_effects) { task1->area.pix = task1->state_pix[state]; if (!task1->area.pix) - task1->area.redraw_needed = TRUE; + schedule_redraw(&task1->area); + panel_refresh = TRUE; } else { - task1->area.redraw_needed = TRUE; + schedule_redraw(&task1->area); } if (state == TASK_ACTIVE && g_slist_find(urgent_list, task1)) del_urgent(task1); @@ -620,7 +621,7 @@ void set_task_redraw(Task *task) task->state_pix[k] = 0; } task->area.pix = 0; - task->area.redraw_needed = TRUE; + schedule_redraw(&task->area); } void blink_urgent(void *arg) diff --git a/src/taskbar/taskbar.c b/src/taskbar/taskbar.c index ac0a7c6..fd7aed9 100644 --- a/src/taskbar/taskbar.c +++ b/src/taskbar/taskbar.c @@ -323,7 +323,7 @@ void taskbar_default_font_changed() for (GList *c = taskbar->area.children; c; c = c->next) { Task *t = c->data; t->area.resize_needed = TRUE; - t->area.redraw_needed = TRUE; + schedule_redraw(&t->area); } } } @@ -429,7 +429,7 @@ void on_change_taskbar(void *obj) taskbar->state_pix[k] = 0; } taskbar->area.pix = 0; - taskbar->area.redraw_needed = TRUE; + schedule_redraw(&taskbar->area); } void set_taskbar_state(Taskbar *taskbar, TaskbarState state) @@ -450,13 +450,13 @@ void set_taskbar_state(Taskbar *taskbar, TaskbarState state) } if (taskbar->area.on_screen) { if (!taskbar->state_pix[state]) - taskbar->area.redraw_needed = TRUE; + schedule_redraw(&taskbar->area); if (taskbarname_enabled) { if (!panel_config.mouse_effects) { if (!taskbar->bar_name.state_pix[state]) - taskbar->bar_name.area.redraw_needed = TRUE; + schedule_redraw(&taskbar->bar_name.area); } else { - taskbar->bar_name.area.redraw_needed = TRUE; + schedule_redraw(&taskbar->bar_name.area); } } if (taskbar_mode == MULTI_DESKTOP && diff --git a/src/taskbar/taskbarname.c b/src/taskbar/taskbarname.c index 2352523..17242e2 100644 --- a/src/taskbar/taskbarname.c +++ b/src/taskbar/taskbarname.c @@ -59,8 +59,8 @@ void init_taskbarname_panel(void *p) taskbar = &panel->taskbar[j]; memcpy(&taskbar->bar_name.area, &panel->g_taskbar.area_name, sizeof(Area)); taskbar->bar_name.area.parent = taskbar; - taskbar->bar_name.area.has_mouse_over_effect = 1; - taskbar->bar_name.area.has_mouse_press_effect = 1; + taskbar->bar_name.area.has_mouse_over_effect = panel_config.mouse_effects; + taskbar->bar_name.area.has_mouse_press_effect = panel_config.mouse_effects; if (j == server.desktop) taskbar->bar_name.area.bg = panel->g_taskbar.background_name[TASKBAR_ACTIVE]; else @@ -106,7 +106,7 @@ void taskbarname_default_font_changed() for (int j = 0; j < panels[i].num_desktops; j++) { Taskbar *taskbar = &panels[i].taskbar[j]; taskbar->bar_name.area.resize_needed = TRUE; - taskbar->bar_name.area.redraw_needed = TRUE; + schedule_redraw(&taskbar->bar_name.area); } } panel_refresh = TRUE; @@ -142,7 +142,7 @@ gboolean resize_taskbarname(void *obj) int name_height, name_width, name_height_ink; int ret = 0; - taskbar_name->area.redraw_needed = TRUE; + schedule_redraw(&taskbar_name->area); get_text_size2(panel_config.taskbarname_font_desc, &name_height_ink, &name_height, diff --git a/src/util/area.c b/src/util/area.c index 8b6b5db..36f3c45 100644 --- a/src/util/area.c +++ b/src/util/area.c @@ -205,7 +205,7 @@ void relayout_dynamic(Area *a, int level) if (a->_changed) { // pos/size changed - a->redraw_needed = TRUE; + a->_redraw_needed = TRUE; if (a->_on_change_layout) a->_on_change_layout(a); } @@ -222,8 +222,8 @@ void draw_tree(Area *a) if (!a->on_screen) return; - if (a->redraw_needed) { - a->redraw_needed = 0; + if (a->_redraw_needed) { + a->_redraw_needed = 0; draw(a); } @@ -325,7 +325,20 @@ int relayout_with_constraint(Area *a, int maximum_size) void schedule_redraw(Area *a) { - a->redraw_needed = TRUE; + a->_redraw_needed = TRUE; + + if (a->has_mouse_over_effect) { + for (int i = 0; i < MOUSE_STATE_COUNT; i++) { + XFreePixmap(server.dsp, a->pix_by_state[i]); + if (a->pix == a->pix_by_state[i]) + a->pix = None; + a->pix_by_state[i] = None; + } + if (a->pix) { + XFreePixmap(server.dsp, a->pix); + a->pix = None; + } + } for (GList *l = a->children; l; l = l->next) schedule_redraw((Area *)l->data); @@ -357,9 +370,13 @@ void show(Area *a) void draw(Area *a) { - if (a->pix) + if (a->pix) { XFreePixmap(server.dsp, a->pix); + if (a->pix_by_state[a->has_mouse_over_effect ? a->mouse_state : 0] != a->pix) + XFreePixmap(server.dsp, a->pix_by_state[a->has_mouse_over_effect ? a->mouse_state : 0]); + } a->pix = XCreatePixmap(server.dsp, server.root_win, a->width, a->height, server.depth); + a->pix_by_state[a->has_mouse_over_effect ? a->mouse_state : 0] = a->pix; // Add layer of root pixmap (or clear pixmap if real_transparency==true) if (server.real_transparency) @@ -482,11 +499,18 @@ void free_area(Area *a) if (a->children) { g_list_free(a->children); - a->children = 0; + a->children = NULL; + } + for (int i = 0; i < MOUSE_STATE_COUNT; i++) { + XFreePixmap(server.dsp, a->pix_by_state[i]); + if (a->pix == a->pix_by_state[i]) { + a->pix = None; + } + a->pix_by_state[i] = None; } if (a->pix) { XFreePixmap(server.dsp, a->pix); - a->pix = 0; + a->pix = None; } if (mouse_over_area == a) { mouse_over_area = NULL; @@ -519,7 +543,9 @@ void mouse_over(Area *area, int pressed) mouse_over_area = area; mouse_over_area->mouse_state = new_state; - schedule_redraw(mouse_over_area); + mouse_over_area->pix = mouse_over_area->pix_by_state[mouse_over_area->has_mouse_over_effect ? mouse_over_area->mouse_state : 0]; + if (!mouse_over_area->pix) + mouse_over_area->_redraw_needed = TRUE; panel_refresh = TRUE; } @@ -528,7 +554,9 @@ void mouse_out() if (!mouse_over_area) return; mouse_over_area->mouse_state = MOUSE_NORMAL; - schedule_redraw(mouse_over_area); + mouse_over_area->pix = mouse_over_area->pix_by_state[mouse_over_area->has_mouse_over_effect ? mouse_over_area->mouse_state : 0]; + if (!mouse_over_area->pix) + mouse_over_area->_redraw_needed = TRUE; panel_refresh = TRUE; mouse_over_area = NULL; } diff --git a/src/util/area.h b/src/util/area.h index 6075c5f..dbc25ff 100644 --- a/src/util/area.h +++ b/src/util/area.h @@ -160,6 +160,7 @@ typedef enum MouseState { MOUSE_NORMAL = 0, MOUSE_OVER = 1, MOUSE_DOWN = 2, + MOUSE_STATE_COUNT } MouseState; struct Panel; @@ -191,11 +192,13 @@ typedef struct Area { // 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; + // Do not set this directly; use schedule_redraw() instead. + 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; + Pixmap pix_by_state[MOUSE_STATE_COUNT]; // Callbacks