Compare commits

...

13 Commits

18 changed files with 159 additions and 66 deletions

View File

@@ -1,3 +1,10 @@
2016-04-02 0.12.9
- Fixes:
- Regression: Do not detect empty areas as clickable (issue #572)
- Regression: Position and resize task icon correctly (issue #575)
- Use imlib2 for taking screenshot; if it fails, use Xlib (issue #574)
- Battery: lower sample frequency when there is no support for reading current/power
2016-03-25 0.12.8
- Major changes (see details below):
- Icon cache and lazy icon theme loading to improve performance in tint2 and tint2conf

View File

@@ -1,26 +1,26 @@
# New stable release: 0.12.8
Changes: https://gitlab.com/o9000/tint2/blob/0.12.8/ChangeLog
# New stable release: 0.12.9
Changes: https://gitlab.com/o9000/tint2/blob/0.12.9/ChangeLog
Documentation: https://gitlab.com/o9000/tint2/wikis/Configure
Try it out with (see also [dependencies](https://gitlab.com/o9000/tint2/wikis/Install#dependencies)):
Compile it with (see also [dependencies](https://gitlab.com/o9000/tint2/wikis/Install#dependencies)):
```
git clone https://gitlab.com/o9000/tint2.git
cd tint2
git checkout 0.12.8
git checkout 0.12.9
mkdir build
cd build
cmake ..
make -j4
./tint2 &
./src/tint2conf/tint2conf &
```
To install from source, also run (as root):
To install, run (as root):
```
make install
```
And then you can run the panel `tint2` and the configuration program `tint2conf`.
Please report any problems to https://gitlab.com/o9000/tint2/issues. Your feedback is much appreciated.
P.S. GitLab is now the official location of the tint2 project, migrated from Google Code, which is shutting down. In case you are wondering why not GitHub, BitBucket etc., we chose GitLab because it is open source, it is mature and works well, looks cool and has a very nice team.

View File

@@ -150,6 +150,7 @@ void init_battery_panel(void *p)
battery->area.parent = p;
battery->area.panel = p;
snprintf(battery->area.name, sizeof(battery->area.name), "Battery");
battery->area._draw_foreground = draw_battery;
battery->area.size_mode = LAYOUT_FIXED;
battery->area._resize = resize_battery;

View File

@@ -306,6 +306,7 @@ static gboolean update_linux_battery(struct psy_battery *bat)
gint64 old_timestamp = bat->timestamp;
int old_energy_now = bat->energy_now;
gint old_power_now = bat->power_now;
/* reset values */
bat->present = 0;
@@ -356,6 +357,12 @@ static gboolean update_linux_battery(struct psy_battery *bat)
/* some hardware does not support reading current power consumption */
g_error_free(error);
bat->power_now = estimate_power_usage(bat, old_energy_now, old_timestamp);
if (bat->power_now == 0 && bat->status != BATTERY_FULL) {
/* If the hardware updates the level slower than our sampling period,
* we need to sample more rarely */
bat->power_now = old_power_now;
bat->timestamp = old_timestamp;
}
} else if (error) {
g_error_free(error);
return FALSE;

View File

@@ -180,6 +180,7 @@ void init_clock_panel(void *p)
clock_init_fonts();
clock->area.parent = p;
clock->area.panel = p;
snprintf(clock->area.name, sizeof(clock->area.name), "Clock");
clock->area._is_under_mouse = full_width_area_is_under_mouse;
clock->area.has_mouse_press_effect = clock->area.has_mouse_over_effect =
panel_config.mouse_effects && (clock_lclick_command || clock_mclick_command || clock_rclick_command ||

View File

@@ -155,9 +155,9 @@ void init_execp_panel(void *p)
execp->area.paddingx = execp->backend->paddingx;
execp->area.paddingy = execp->backend->paddingy;
execp->area.paddingxlr = execp->backend->paddingxlr;
execp->area.parent = panel;
execp->area.panel = panel;
snprintf(execp->area.name, sizeof(execp->area.name), "Execp %s", execp->backend->command ? execp->backend->command : "null");
execp->area._draw_foreground = draw_execp;
execp->area.size_mode = LAYOUT_FIXED;
execp->area._resize = resize_execp;

View File

@@ -39,6 +39,7 @@ void init_freespace_panel(void *p)
freespace->area.bg = &g_array_index(backgrounds, Background, 0);
freespace->area.parent = p;
freespace->area.panel = p;
snprintf(freespace->area.name, sizeof(freespace->area.name), "Freespace");
freespace->area.size_mode = LAYOUT_FIXED;
freespace->area.resize_needed = 1;
freespace->area.on_screen = TRUE;

View File

@@ -83,6 +83,7 @@ void init_launcher_panel(void *p)
launcher->area.parent = p;
launcher->area.panel = p;
snprintf(launcher->area.name, sizeof(launcher->area.name), "Launcher");
launcher->area._draw_foreground = NULL;
launcher->area.size_mode = LAYOUT_FIXED;
launcher->area._resize = resize_launcher;
@@ -452,6 +453,7 @@ void launcher_load_icons(Launcher *launcher)
if (entry.exec) {
LauncherIcon *launcherIcon = calloc(1, sizeof(LauncherIcon));
launcherIcon->area.panel = launcher->area.panel;
snprintf(launcherIcon->area.name, sizeof(launcherIcon->area.name), "LauncherIcon %s", entry.name ? entry.name : "null");
launcherIcon->area._draw_foreground = draw_launcher_icon;
launcherIcon->area.size_mode = LAYOUT_FIXED;
launcherIcon->area._resize = NULL;

View File

@@ -99,6 +99,7 @@ void default_panel()
backgrounds = g_array_new(0, 0, sizeof(Background));
memset(&panel_config, 0, sizeof(Panel));
snprintf(panel_config.area.name, sizeof(panel_config.area.name), "Panel");
panel_config.mouse_over_alpha = 100;
panel_config.mouse_over_saturation = 0;
panel_config.mouse_over_brightness = 10;
@@ -196,6 +197,7 @@ void init_panel()
p->area.bg = &g_array_index(backgrounds, Background, 0);
p->area.parent = p;
p->area.panel = p;
snprintf(p->area.name, sizeof(p->area.name), "Panel %d", i);
p->area.on_screen = TRUE;
p->area.resize_needed = 1;
p->area.size_mode = LAYOUT_DYNAMIC;

View File

@@ -113,6 +113,7 @@ void init_systray_panel(void *p)
Panel *panel = (Panel *)p;
systray.area.parent = panel;
systray.area.panel = panel;
snprintf(systray.area.name, sizeof(systray.area.name), "Systray");
if (!systray.area.bg)
systray.area.bg = &g_array_index(backgrounds, Background, 0);
show(&systray.area);

View File

@@ -65,6 +65,7 @@ Task *add_task(Window win)
Task task_template;
memset(&task_template, 0, sizeof(task_template));
snprintf(task_template.area.name, sizeof(task_template.area.name), "Task %d", (int)win);
task_template.area.has_mouse_over_effect = panel_config.mouse_effects;
task_template.area.has_mouse_press_effect = panel_config.mouse_effects;
task_template.area._is_under_mouse = full_width_area_is_under_mouse;
@@ -82,6 +83,7 @@ Task *add_task(Window win)
}
task_update_title(&task_template);
task_update_icon(&task_template);
snprintf(task_template.area.name, sizeof(task_template.area.name), "Task %d %s", (int)win, task_template.title ? task_template.title : "null");
// fprintf(stderr, "%s %d: win = %ld, task = %s\n", __FUNCTION__, __LINE__, win, task_template.title ?
// task_template.title : "??");
@@ -367,7 +369,7 @@ void draw_task_icon(Task *task, int text_width)
else
pos_x = (task->area.width - panel->g_task.icon_size1) / 2;
} else {
pos_x = panel->g_task.area.paddingxlr + task->area.bg->border.width;
pos_x = task->area.bg->border.width + task->area.paddingxlr;
}
// Render
@@ -386,12 +388,12 @@ void draw_task_icon(Task *task, int text_width)
}
imlib_context_set_image(image);
render_image(task->area.pix, pos_x, panel->g_task.icon_posy);
render_image(task->area.pix, pos_x, (task->area.height - panel->g_task.icon_size1) / 2);
if (0) {
fprintf(stderr, "Task icon size: %d %d pos %d\n", imlib_image_get_width(), imlib_image_get_height(), pos_x);
fprintf(stderr, "Task icon size: %d %d pos %d %d\n", imlib_image_get_width(), imlib_image_get_height(), pos_x, panel->g_task.icon_posy);
fprintf(stderr, "Task max size : %d %d\n", panel->g_task.maximum_width, panel->g_task.maximum_height);
fprintf(stderr, "Task area size: %d %d\n", task->area.width, task->area.height);
fprintf(stderr, "Task area bord: %d\n", task->area.bg->border.width);
fprintf(stderr, "Task border : %d\n", task->area.bg->border.width);
fprintf(stderr, "\n");
}
}

View File

@@ -147,6 +147,7 @@ void init_taskbar_panel(void *p)
// taskbar name
panel->g_taskbar.area_name.panel = panel;
snprintf(panel->g_taskbar.area_name.name, sizeof(panel->g_taskbar.area_name.name), "Taskbarname");
panel->g_taskbar.area_name.size_mode = LAYOUT_FIXED;
panel->g_taskbar.area_name._resize = resize_taskbarname;
panel->g_taskbar.area_name._is_under_mouse = full_width_area_is_under_mouse;
@@ -158,6 +159,7 @@ void init_taskbar_panel(void *p)
// taskbar
panel->g_taskbar.area.parent = panel;
panel->g_taskbar.area.panel = panel;
snprintf(panel->g_taskbar.area.name, sizeof(panel->g_taskbar.area.name), "Taskbar");
panel->g_taskbar.area.size_mode = LAYOUT_DYNAMIC;
panel->g_taskbar.area.alignment = taskbar_alignment;
panel->g_taskbar.area._resize = resize_taskbar;
@@ -178,6 +180,7 @@ void init_taskbar_panel(void *p)
// task
panel->g_task.area.panel = panel;
snprintf(panel->g_task.area.name, sizeof(panel->g_task.area.name), "Task");
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;
@@ -220,10 +223,16 @@ void init_taskbar_panel(void *p)
if ((panel->g_task.config_background_mask & (1 << TASK_URGENT)) == 0)
panel->g_task.background[TASK_URGENT] = panel->g_task.background[TASK_ACTIVE];
if (!panel->g_task.maximum_width)
panel->g_task.maximum_width = server.monitors[panel->monitor].width;
if (!panel->g_task.maximum_height)
panel->g_task.maximum_height = server.monitors[panel->monitor].height;
if (panel_horizontal) {
panel->g_task.area.posy = panel->g_taskbar.area.posy +
panel->g_taskbar.background[TASKBAR_NORMAL]->border.width +
panel->g_taskbar.area.paddingy;
panel->g_task.area.width = panel->g_task.maximum_width;
panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy);
} else {
panel->g_task.area.posx = panel->g_taskbar.area.posx +
@@ -259,19 +268,26 @@ void init_taskbar_panel(void *p)
PANGO_ELLIPSIZE_END,
FALSE);
if (!panel->g_task.maximum_width && panel_horizontal)
panel->g_task.maximum_width = server.monitors[panel->monitor].width;
panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr;
panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
if (panel->g_task.has_icon) {
panel->g_task.icon_size1 =
MIN(panel->g_task.maximum_width, MIN(panel->g_task.maximum_height, panel->g_task.area.height)) -
MIN(MIN(panel->g_task.maximum_width, panel->g_task.maximum_height),
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
(2 * panel->g_task.area.paddingy) - 2 * panel->g_task.area.bg->border.width;
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx;
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
if (0)
printf("task: icon_size = %d, textx = %f, texth = %f, icony = %d, w = %d, h = %d, maxw = %d, maxh = %d\n",
panel->g_task.icon_size1,
panel->g_task.text_posx,
panel->g_task.text_height,
panel->g_task.icon_posy,
panel->g_task.area.width,
panel->g_task.area.height,
panel->g_task.maximum_width,
panel->g_task.maximum_height);
}
// printf("monitor %d, task_maximum_width %d\n", panel->monitor, panel->g_task.maximum_width);
Taskbar *taskbar;
panel->num_desktops = server.num_desktops;

View File

@@ -505,6 +505,11 @@ void init_X11_post_config()
default_icon = imlib_load_image(path);
g_free(path);
}
if (!default_icon) {
fprintf(stderr,
RED "Could not load default_icon.png. Please check that tint2 has been installed correctly!" RESET
"\n");
}
}
void cleanup()
@@ -560,18 +565,45 @@ void get_snapshot(const char *path)
XCreatePixmap(server.display, server.root_win, panel->area.width, panel->area.height, server.depth);
render_panel(panel);
Imlib_Image img = NULL;
imlib_context_set_drawable(panel->temp_pmap);
img = imlib_create_image_from_drawable(0, 0, 0, panel->area.width, panel->area.height, 0);
XSync(server.display, False);
imlib_context_set_image(img);
if (!panel_horizontal) {
// rotate 90° vertical panel
imlib_image_flip_horizontal();
imlib_image_flip_diagonal();
imlib_context_set_drawable(panel->temp_pmap);
Imlib_Image img = imlib_create_image_from_drawable(0, 0, 0, panel->area.width, panel->area.height, 1);
if (!img) {
XImage *ximg =
XGetImage(server.display, panel->temp_pmap, 0, 0, panel->area.width, panel->area.height, AllPlanes, ZPixmap);
if (ximg) {
DATA32 *pixels = calloc(panel->area.width * panel->area.height, sizeof(DATA32));
for (int x = 0; x < panel->area.width; x++) {
for (int y = 0; y < panel->area.height; y++) {
DATA32 xpixel = XGetPixel(ximg, x, y);
DATA32 r = (xpixel >> 16) & 0xff;
DATA32 g = (xpixel >> 8) & 0xff;
DATA32 b = (xpixel >> 0) & 0xff;
DATA32 a = 0x0;
DATA32 argb = (a << 24) | (r << 16) | (g << 8) | b;
pixels[y * panel->area.width + x] = argb;
}
}
XDestroyImage(ximg);
img = imlib_create_image_using_data(panel->area.width, panel->area.height, pixels);
}
}
if (img) {
imlib_context_set_image(img);
if (!panel_horizontal) {
// rotate 90° vertical panel
imlib_image_flip_horizontal();
imlib_image_flip_diagonal();
}
imlib_save_image(path);
imlib_free_image();
}
imlib_save_image(path);
imlib_free_image();
}
void window_action(Task *task, MouseAction action)

View File

@@ -18,3 +18,4 @@
gboolean update_snapshot();
void menuApply();
void refresh_current_theme();
extern GtkWidget *g_window;

View File

@@ -18,6 +18,7 @@
**************************************************************************/
#include "main.h"
#include "properties.h"
#include "strnatcmp.h"
#include "theme_view.h"
#include "common.h"
@@ -28,17 +29,15 @@ GtkListStore *theme_list_store;
int g_width_list, g_height_list;
GtkCellRenderer *g_renderer;
gint theme_name_compare(GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
gpointer user_data);
gint theme_name_compare(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data);
GtkWidget *create_view()
{
GtkTreeViewColumn *col;
GtkCellRenderer *renderer;
theme_list_store = gtk_list_store_new(NB_COL, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF);
theme_list_store =
gtk_list_store_new(NB_COL, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_INT, G_TYPE_INT);
GtkWidget *view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(theme_list_store));
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
@@ -51,25 +50,23 @@ GtkWidget *create_view()
gtk_tree_view_column_pack_start(col, renderer, TRUE);
gtk_tree_view_column_add_attribute(col, renderer, "text", COL_THEME_FILE);
gtk_tree_view_column_set_visible(col, FALSE);
gtk_tree_view_append_column(GTK_TREE_VIEW(view),col);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
renderer = gtk_cell_renderer_text_new();
col = gtk_tree_view_column_new();
gtk_tree_view_column_pack_start(col, renderer, TRUE);
gtk_tree_view_column_add_attribute(col, renderer, "text", COL_THEME_NAME);
gtk_tree_view_append_column(GTK_TREE_VIEW(view),col);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
g_width_list = 200;
g_height_list = 30;
g_renderer = gtk_cell_renderer_pixbuf_new();
g_object_set(g_renderer, "xalign", 0.0, NULL);
gtk_cell_renderer_set_fixed_size(g_renderer, g_width_list, g_height_list);
// specific to gtk-2.18 or higher
// gtk_cell_renderer_set_padding(g_renderer, 5, 5);
gtk_cell_renderer_set_fixed_size(g_renderer, 200, 30);
col = gtk_tree_view_column_new();
gtk_tree_view_column_pack_start(col, g_renderer, TRUE);
gtk_tree_view_column_add_attribute(col, g_renderer, "pixbuf", COL_SNAPSHOT);
gtk_tree_view_append_column(GTK_TREE_VIEW(view),col);
gtk_tree_view_column_add_attribute(col, g_renderer, "width", COL_WIDTH);
gtk_tree_view_column_add_attribute(col, g_renderer, "height", COL_HEIGHT);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
GtkTreeSortable *sortable = GTK_TREE_SORTABLE(theme_list_store);
gtk_tree_sortable_set_sort_column_id(sortable, COL_THEME_FILE, GTK_SORT_ASCENDING);
@@ -77,10 +74,7 @@ GtkWidget *create_view()
return view;
}
gint theme_name_compare(GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
gpointer user_data)
gint theme_name_compare(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
gchar *path_a, *path_b;
gtk_tree_model_get(model, a, COL_THEME_FILE, &path_a, -1);
@@ -158,23 +152,35 @@ void theme_list_append(const gchar *path)
g_free(suffix);
}
gboolean update_snapshot()
{
GtkTreeModel *model;
const gint PADDING = 20;
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
GtkTreeIter iter;
gboolean have_iter;
gint pixWidth = 200, pixHeight = 30;
int num_updates = 0;
have_iter = gtk_tree_model_get_iter_first(model, &iter);
while (have_iter) {
GdkPixbuf *pixbuf;
gtk_tree_model_get(model, &iter, COL_SNAPSHOT, &pixbuf, -1);
if (pixbuf)
g_object_unref(pixbuf);
else
num_updates++;
have_iter = gtk_tree_model_iter_next(model, &iter);
}
gboolean need_pls_wait = num_updates > 3;
if (need_pls_wait)
create_please_wait(GTK_WINDOW(g_window));
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
have_iter = gtk_tree_model_get_iter_first(model, &iter);
while (have_iter) {
GdkPixbuf *pixbuf;
gtk_tree_model_get(model, &iter, COL_SNAPSHOT, &pixbuf, -1);
if (pixbuf) {
pixWidth = MAX(pixWidth, gdk_pixbuf_get_width(pixbuf));
pixHeight = MAX(pixHeight, gdk_pixbuf_get_height(pixbuf));
g_object_unref(pixbuf);
have_iter = gtk_tree_model_iter_next(model, &iter);
continue;
@@ -182,9 +188,7 @@ gboolean update_snapshot()
// build panel's snapshot
gchar *path;
gtk_tree_model_get(model, &iter,
COL_THEME_FILE, &path,
-1);
gtk_tree_model_get(model, &iter, COL_THEME_FILE, &path, -1);
char fname[128];
sprintf(fname, "tint2-%d.jpg", (int)getpid());
@@ -206,16 +210,26 @@ gboolean update_snapshot()
g_free(snap);
g_free(path);
pixWidth = MAX(pixWidth, gdk_pixbuf_get_width(pixbuf));
pixHeight = MAX(pixHeight, gdk_pixbuf_get_height(pixbuf));
gtk_list_store_set(theme_list_store, &iter, COL_SNAPSHOT, pixbuf, -1);
gtk_list_store_set(theme_list_store,
&iter,
COL_SNAPSHOT,
pixbuf,
COL_WIDTH,
gdk_pixbuf_get_width(pixbuf) + PADDING,
COL_HEIGHT,
gdk_pixbuf_get_height(pixbuf) + PADDING,
-1);
if (pixbuf)
g_object_unref(pixbuf);
if (need_pls_wait)
process_events();
have_iter = gtk_tree_model_iter_next(model, &iter);
}
gtk_cell_renderer_set_fixed_size(g_renderer, pixWidth + 30, pixHeight + 30);
if (need_pls_wait)
destroy_please_wait();
return FALSE;
}

View File

@@ -5,7 +5,12 @@
extern GtkWidget *g_theme_view;
extern GtkListStore *theme_list_store;
enum { COL_THEME_FILE = 0, COL_THEME_NAME, COL_SNAPSHOT, NB_COL, };
enum { COL_THEME_FILE = 0,
COL_THEME_NAME,
COL_SNAPSHOT,
COL_WIDTH,
COL_HEIGHT,
NB_COL, };
GtkWidget *create_view();

View File

@@ -594,7 +594,7 @@ gboolean area_is_first(void *obj)
Area *node = &panel->area;
while (node) {
if (!node->on_screen)
if (!node->on_screen || node->width == 0 || node->height == 0)
return FALSE;
if (node == a)
return TRUE;
@@ -603,7 +603,7 @@ gboolean area_is_first(void *obj)
node = NULL;
for (; l; l = l->next) {
Area *child = l->data;
if (!child->on_screen)
if (!child->on_screen || child->width == 0 || child->height == 0)
continue;
node = child;
break;
@@ -624,7 +624,7 @@ gboolean area_is_last(void *obj)
Area *node = &panel->area;
while (node) {
if (!node->on_screen)
if (!node->on_screen || node->width == 0 || node->height == 0)
return FALSE;
if (node == a)
return TRUE;
@@ -633,7 +633,7 @@ gboolean area_is_last(void *obj)
node = NULL;
for (; l; l = l->next) {
Area *child = l->data;
if (!child->on_screen)
if (!child->on_screen || child->width == 0 || child->height == 0)
continue;
node = child;
}
@@ -645,7 +645,7 @@ gboolean area_is_last(void *obj)
gboolean area_is_under_mouse(void *obj, int x, int y)
{
Area *a = obj;
if (!a->on_screen)
if (!a->on_screen || a->width == 0 || a->height == 0)
return FALSE;
if (a->_is_under_mouse)
@@ -664,9 +664,9 @@ gboolean full_width_area_is_under_mouse(void *obj, int x, int y)
return a->_is_under_mouse(a, x, y);
if (panel_horizontal)
return (x >= a->posx || area_is_first(a)) && (x <= a->posx + a->width || area_is_last(a));
return (x >= a->posx) && (x <= a->posx + a->width);
else
return (y >= a->posy || area_is_first(a)) && (y <= a->posy + a->height || area_is_last(a));
return (y >= a->posy) && (y <= a->posy + a->height);
}
Area *find_area_under_mouse(void *root, int x, int y)

View File

@@ -194,6 +194,7 @@ typedef struct Area {
// 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];
char name[32];
// Callbacks