Cache pixmaps for mouse effects to improve performance

This commit is contained in:
o9000 2016-01-01 04:57:08 +01:00
parent a38b90dbab
commit a6da0186e0
11 changed files with 80 additions and 47 deletions

View file

@ -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) {

View file

@ -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));

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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 &&

View file

@ -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,

View file

@ -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;
}

View file

@ -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