Compare commits

..

16 Commits

Author SHA1 Message Date
Chris Lee
36c8d41914 use xrender to capture screenshots 2019-02-24 01:49:01 +01:00
Chris Lee
4dafea185f thumbnails: do not crash if window size is 0x0 2019-02-23 22:49:58 +01:00
Chris Lee
77890d463a blink battery between two colors (issue #723) 2019-02-23 20:06:47 +01:00
Chris Lee
e1211a929f do not draw text with cairo directly on xlib pixmap (workaround for intel graphics bug, see emacs implementation) 2019-02-23 20:06:06 +01:00
Chris Lee
00f0bbd354 blink battery when low (issue #723) 2019-02-20 23:38:17 +01:00
Chris Lee
15d2570a3e Silence warnings 2018-12-31 18:23:41 +01:00
Chris Lee
c76f056746 Fix markup drawing when font shadow enabled (fixes issue #709) 2018-12-31 18:22:50 +01:00
Chris Lee
cacd4b8dad Fix: Bug: Clock Only Updates Every Minute With Format %s (issue #724) 2018-12-27 08:01:11 +01:00
Chris Lee
b539c0a1c0 fix crash if bad config path given #719 2018-09-25 19:55:55 +00:00
Chris Lee
970c597796 #716 fix executor spacing 2018-09-15 05:46:14 +00:00
Chris Lee
a82b9a1d7f Release 16.6.1 2018-08-05 21:27:23 +00:00
Chris Lee
89a6cadfcd add patch version number option to release script 2018-08-05 21:27:15 +00:00
Chris Lee
fb9da655df remove configure script from main dir as it breaks debian packaging 2018-08-05 21:12:17 +00:00
Chris Lee
cb137674e4 fix ci script 2018-08-05 09:35:28 +00:00
Chris Lee
1054aac7ca Release 16.6 2018-08-04 18:43:09 +00:00
Chris Lee
81c7c65a9f Fix regression in task icon brightness (issue #714) 2018-08-04 18:41:53 +00:00
26 changed files with 380 additions and 202 deletions

View File

@@ -1,3 +1,15 @@
2019-02-17 master
- Fix spacing around icons in executor without text in vertical panels (issue #716)
- Fix Bug: Clock Only Updates Every Minute With Format %s (issue #724)
- Fix markup drawing when font shadow enabled (issue #709)
- Blink battery when low (issue #723)
2018-08-05 16.6.1
- Fix packaging regression for debian (issue #715)
2018-08-04 16.6
- Fix regression in task icon brightness (issue #714)
2018-08-04 16.5
- Add new build script
- Add option to sort taskbar by application name
@@ -1012,3 +1024,4 @@ released tint-0.2
.
.
.
.

View File

@@ -1,5 +1,5 @@
# Latest stable release: 16.5
Changes: https://gitlab.com/o9000/tint2/blob/16.5/ChangeLog
# Latest stable release: 16.6.1
Changes: https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog
Documentation: [doc/tint2.md](doc/tint2.md)
@@ -8,7 +8,7 @@ Compile it with (after you install the [dependencies](https://gitlab.com/o9000/t
```
git clone https://gitlab.com/o9000/tint2.git
cd tint2
git checkout 16.5
git checkout 16.6.1
mkdir build
cd build
cmake ..

View File

@@ -199,9 +199,9 @@ pre {
</style>
</head>
<body>
<h1 id="latest-stable-release-16-5"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.5</span><a name="latest-stable-release-16-5" href="#latest-stable-release-16-5" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.5/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.5/ChangeLog</a></p><p>Documentation: <a href="manual.html">manual.html</a></p><p>Compile it with (after you install the <a href="https://gitlab.com/o9000/tint2/wikis/Install#dependencies">dependencies</a>):</p><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git
<h1 id="latest-stable-release-16-6-1"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.6.1</span><a name="latest-stable-release-16-6-1" href="#latest-stable-release-16-6-1" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog</a></p><p>Documentation: <a href="manual.html">manual.html</a></p><p>Compile it with (after you install the <a href="https://gitlab.com/o9000/tint2/wikis/Install#dependencies">dependencies</a>):</p><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git
cd tint2
git checkout 16.5
git checkout 16.6.1
mkdir build
cd build
cmake ..

View File

@@ -1,4 +1,4 @@
.TH TINT2 1 "2018\-08\-04" 16.5
.TH TINT2 1 "2018\-08\-05" 16.6.1
.SH NAME
.PP
tint2 \- lightweight panel/taskbar

View File

@@ -1,4 +1,4 @@
# TINT2 1 "2018-08-04" 16.5
# TINT2 1 "2018-08-05" 16.6.1
## NAME
tint2 - lightweight panel/taskbar

View File

@@ -76,19 +76,23 @@ def get_last_version():
return tags[-1]
def inc_version(v, feature=False):
def inc_version(v, feature=False, tiny=False):
if v.startswith("v0."):
assert v == "v0.14.6"
return "v15.0"
# v4.11 -> v4.12 or v5.0
# v4.11 -> v4.12 or v5.0 or v4.11.1
parts = v.split(".")
while len(parts) < 2:
while len(parts) < 3:
parts.append("0")
assert len(parts) == 2
assert len(parts) == 3
if feature:
del parts[-1]
parts[-2] = "v" + str(int(parts[-2].replace("v", "")) + 1)
parts[-1] = "0"
elif tiny:
parts[-1] = str(int(parts[-1]) + 1)
else:
del parts[-1]
parts[-1] = str(int(parts[-1]) + 1)
return ".".join([s for s in parts if s])
@@ -153,23 +157,14 @@ def update_log(path, version, date):
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--feature", action="store_true")
parser.add_argument("--undo", action="store_true")
parser.add_argument("--tiny", action="store_true")
args = parser.parse_args()
logging.basicConfig(format=ansi_lblue + "%(asctime)s %(pathname)s %(levelname)s" + ansi_reset + " %(message)s", level=logging.DEBUG)
test_inc_version()
# Read version from last tag and increment
old_version = get_last_version()
if args.undo:
info("Revering last commit...")
run("git tag -d %s" % old_version)
run("git tag -d %s" % old_version.replace("v", ""))
run("git reset --soft HEAD~")
run("git reset")
run("git stash")
os.system("git log -1")
sys.exit(0)
info("Old version:", old_version)
version = inc_version(old_version, args.feature)
version = inc_version(old_version, args.feature, args.tiny)
readable_version = version.replace("v", "")
date = datetime.datetime.now().strftime("%Y-%m-%d")
info("New version:", readable_version, version, date)

View File

@@ -240,7 +240,7 @@ LFLAGS = shlex.split(os.environ.get('LDFLAGS', ''))
LIBS = []
# Get paths
source_dir = os.path.dirname(os.path.realpath(__file__))
source_dir = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + '/..')
build_dir = os.path.join(os.getcwd(), 'build')
if not args.home:
prefix = args.prefix or '/usr/local'
@@ -510,7 +510,8 @@ tint2conf.cflags += ['-DTINT2CONF',
'-DINSTALL_PREFIX=\\"{}\\"'.format(prefix),
'-DLOCALEDIR=\\"{}\\"'.format(localedir),
'-DGETTEXT_PACKAGE=\\"tint2conf\\"',
'-DHAVE_VERSION_H']
'-DHAVE_VERSION_H',
'-Wno-shadow']
tint2conf.sources = ['src/util/bt.c',
'src/util/common.c',

View File

@@ -289,7 +289,7 @@ def get_gentoo_versions():
def get_void_versions():
print >> sys.stderr, "Void ..."
template = http_download_txt("https://raw.githubusercontent.com/voidlinux/void-packages/master/srcpkgs/tint2/template")
template = http_download_txt("https://raw.githubusercontent.com/void-linux/void-packages/master/srcpkgs/tint2/template")
versions = []
version = None
maintainer = None

View File

@@ -42,6 +42,7 @@ gboolean battery_enabled;
gboolean battery_tooltip_enabled;
int percentage_hide;
static Timer battery_timer;
static Timer battery_blink_timer;
#define BATTERY_BUF_SIZE 256
static char buf_bat_line1[BATTERY_BUF_SIZE];
@@ -60,6 +61,9 @@ char *battery_rclick_command;
char *battery_uwheel_command;
char *battery_dwheel_command;
gboolean battery_found;
gboolean battery_warn;
gboolean battery_warn_red;
Background *battery_warn_bg;
char *battery_sys_prefix = (char *)"";
@@ -77,6 +81,10 @@ void default_battery()
battery_low_cmd_sent = FALSE;
battery_full_cmd_sent = FALSE;
INIT_TIMER(battery_timer);
INIT_TIMER(battery_blink_timer);
battery_warn = FALSE;
battery_warn_red = FALSE;
battery_warn_bg = NULL;
bat1_has_font = FALSE;
bat1_font_desc = NULL;
bat1_format = NULL;
@@ -128,7 +136,9 @@ void cleanup_battery()
free(ac_disconnected_cmd);
ac_disconnected_cmd = NULL;
destroy_timer(&battery_timer);
destroy_timer(&battery_blink_timer);
battery_found = FALSE;
free_and_null(battery_warn_bg);
battery_os_free();
}
@@ -310,6 +320,40 @@ void battery_default_font_changed()
schedule_panel_redraw();
}
void blink_battery(void *arg)
{
if (!battery_enabled)
return;
battery_warn_red = battery_warn ? !battery_warn_red : FALSE;
if (battery_warn_red && !battery_warn_bg) {
battery_warn_bg = calloc(1, sizeof(*battery_warn_bg));
*battery_warn_bg = *panel_config.battery.area.bg;
battery_warn_bg->fill_color.alpha = 1.0;
battery_warn_bg->border.color.alpha = 1.0;
}
if (battery_warn_red) {
battery_warn_bg->fill_color.rgb[0] = 0.6;
battery_warn_bg->fill_color.rgb[1] = 0.1;
battery_warn_bg->fill_color.rgb[2] = 0.1;
battery_warn_bg->border.color.rgb[0] = 0.5;
battery_warn_bg->border.color.rgb[1] = 0.0;
battery_warn_bg->border.color.rgb[2] = 0.0;
} else {
battery_warn_bg->fill_color.rgb[0] = 0.9;
battery_warn_bg->fill_color.rgb[1] = 0.7;
battery_warn_bg->fill_color.rgb[2] = 0.1;
battery_warn_bg->border.color.rgb[0] = 0.7;
battery_warn_bg->border.color.rgb[1] = 0.5;
battery_warn_bg->border.color.rgb[2] = 0.1;
}
for (int i = 0; i < num_panels; i++) {
if (panels[i].battery.area.on_screen) {
panels[i].battery.area.bg = battery_warn_bg;
schedule_redraw(&panels[i].battery.area);
}
}
}
void update_battery_tick(void *arg)
{
if (!battery_enabled)
@@ -320,6 +364,7 @@ void update_battery_tick(void *arg)
gboolean old_ac_connected = battery_state.ac_connected;
int16_t old_hours = battery_state.time.hours;
int8_t old_minutes = battery_state.time.minutes;
gboolean old_warn = battery_warn;
if (!battery_found) {
init_battery();
@@ -357,6 +402,20 @@ void update_battery_tick(void *arg)
battery_full_cmd_sent = FALSE;
}
if (!battery_blink_timer.enabled_) {
if (battery_state.percentage < battery_low_status &&
battery_state.state == BATTERY_DISCHARGING) {
change_timer(&battery_blink_timer, true, 10, 1000, blink_battery, 0);
battery_warn = TRUE;
}
} else {
if (battery_state.percentage > battery_low_status ||
battery_state.state != BATTERY_DISCHARGING) {
stop_timer(&battery_blink_timer);
battery_warn = FALSE;
}
}
for (int i = 0; i < num_panels; i++) {
// Show/hide if needed
if (!battery_found) {
@@ -370,8 +429,11 @@ void update_battery_tick(void *arg)
// Redraw if needed
if (panels[i].battery.area.on_screen) {
if (old_found != battery_found || old_percentage != battery_state.percentage ||
old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes) {
old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes ||
old_warn != battery_warn) {
panels[i].battery.area.resize_needed = TRUE;
if (!battery_warn)
panels[i].battery.area.bg = panel_config.battery.area.bg;
schedule_panel_redraw();
}
}

View File

@@ -478,7 +478,7 @@ void draw_button(void *obj, cairo_t *c)
button->frontend->textx,
button->frontend->texty,
&button->backend->font_color,
panel_config.font_shadow);
panel_config.font_shadow ? layout : NULL);
g_object_unref(layout);
g_object_unref(context);

View File

@@ -173,7 +173,13 @@ gboolean time_format_needs_sec_ticks(char *time_format)
{
if (!time_format)
return FALSE;
if (strchr(time_format, 'S') || strchr(time_format, 'T') || strchr(time_format, 'r'))
if (strchr(time_format, 'c') ||
strchr(time_format, 'r') ||
strchr(time_format, 's') ||
strchr(time_format, 'S') ||
strchr(time_format, 'T') ||
strchr(time_format, 'X') ||
strchr(time_format, '+'))
return TRUE;
return FALSE;
}

View File

@@ -373,7 +373,11 @@ void execp_compute_icon_text_geometry(Execp *execp,
*new_size = *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
*new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area));
} else {
*new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
if (strlen(execp->backend->text)) {
*new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
} else {
*new_size = *icon_h + 2 * *vert_padding + top_bottom_border_width(area);
}
}
if (*new_size != area->height) {
*resized = TRUE;
@@ -441,10 +445,17 @@ gboolean resize_execp(void *obj)
execp->frontend->texty = (execp->area.height - txt_height) / 2;
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
} else {
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = (execp->area.width - txt_width) / 2;
if (strlen(execp->backend->text)) {
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = (execp->area.width - txt_width) / 2;
} else {
execp->frontend->icony = (execp->area.height - icon_h) / 2;
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = (execp->area.width - txt_width) / 2;
}
}
} else {
execp->frontend->texty = (execp->area.height - txt_height) / 2;
@@ -458,10 +469,17 @@ gboolean resize_execp(void *obj)
execp->frontend->texty = (execp->area.height - txt_height) / 2;
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
} else {
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = execp->frontend->iconx;
if (strlen(execp->backend->text)) {
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = execp->frontend->iconx;
} else {
execp->frontend->icony = (execp->area.height - icon_h) / 2;
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = execp->frontend->iconx;
}
}
} else {
execp->frontend->texty = (execp->area.height - txt_height) / 2;
@@ -473,6 +491,18 @@ gboolean resize_execp(void *obj)
return resized;
}
PangoLayout *create_execp_text_layout(Execp *execp, PangoContext *context)
{
PangoLayout *layout = pango_layout_new(context);
pango_layout_set_font_description(layout, execp->backend->font_desc);
pango_layout_set_width(layout, (execp->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_height(layout, (execp->frontend->texth + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
return layout;
}
void draw_execp(void *obj, cairo_t *c)
{
Execp *execp = (Execp *)obj;
@@ -480,7 +510,8 @@ void draw_execp(void *obj, cairo_t *c)
PangoContext *context = pango_cairo_create_context(c);
pango_cairo_context_set_resolution(context, 96 * panel->scale);
PangoLayout *layout = pango_layout_new(context);
PangoLayout *layout = create_execp_text_layout(execp, context);
PangoLayout *shadow_layout = NULL;
if (execp->backend->has_icon && execp->backend->icon) {
imlib_context_set_image(execp->backend->icon);
@@ -489,16 +520,18 @@ void draw_execp(void *obj, cairo_t *c)
}
// draw layout
pango_layout_set_font_description(layout, execp->backend->font_desc);
pango_layout_set_width(layout, (execp->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_height(layout, (execp->frontend->texth + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
if (!execp->backend->has_markup)
if (!execp->backend->has_markup) {
pango_layout_set_text(layout, execp->backend->text, strlen(execp->backend->text));
else
} else {
pango_layout_set_markup(layout, execp->backend->text, strlen(execp->backend->text));
if (panel_config.font_shadow) {
shadow_layout = create_execp_text_layout(execp, context);
if (!layout_set_markup_strip_colors(shadow_layout, execp->backend->text)) {
g_object_unref(shadow_layout);
shadow_layout = NULL;
}
}
}
pango_cairo_update_layout(c, layout);
draw_text(layout,
@@ -506,7 +539,7 @@ void draw_execp(void *obj, cairo_t *c)
execp->frontend->textx,
execp->frontend->texty,
&execp->backend->font_color,
panel_config.font_shadow);
shadow_layout);
g_object_unref(layout);
g_object_unref(context);
@@ -531,12 +564,13 @@ void execp_dump_geometry(void *obj, int indent)
imlib_context_set_image(tmp);
}
fprintf(stderr,
"tint2: %*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n",
"tint2: %*sText: x = %d, y = %d, w = %d, h = %d, align = %s, text = %s\n",
indent,
"",
execp->frontend->textx,
execp->frontend->texty,
execp->frontend->textw,
execp->frontend->texth,
execp->backend->centered ? "center" : "left",
execp->backend->text);
}

View File

@@ -209,8 +209,8 @@ void init_X11_pre_config()
exit(EXIT_FAILURE);
}
server.x11_fd = ConnectionNumber(server.display);
XSetErrorHandler((XErrorHandler)server_catch_error);
XSetIOErrorHandler((XIOErrorHandler)x11_io_error);
XSetErrorHandler(server_catch_error);
XSetIOErrorHandler(x11_io_error);
server_init_atoms();
server.screen = DefaultScreen(server.display);
server.root_win = RootWindow(server.display, server.screen);
@@ -247,8 +247,9 @@ void init(int argc, char **argv)
if (!config_read()) {
fprintf(stderr, "tint2: Could not read config file.\n");
print_usage();
warnings_for_timers = false;
cleanup();
return;
exit(EXIT_FAILURE);
}
init_post_config();

View File

@@ -399,7 +399,12 @@ void launcher_icon_dump_geometry(void *obj, int indent)
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
{
Imlib_Image icon_scaled;
if (original) {
if (!icon_size) {
icon_scaled = imlib_create_image(1, 1);
imlib_context_set_image(icon_scaled);
imlib_context_set_color(255, 255, 255, 255);
imlib_image_fill_rectangle(0, 0, icon_size, icon_size);
} else if (original) {
imlib_context_set_image(original);
icon_scaled = imlib_create_cropped_scaled_image(0,
0,

View File

@@ -399,7 +399,7 @@ void task_update_icon(Task *task)
task->icon[k] = adjust_icon(orig_image,
panel->g_task.alpha[k],
panel->g_task.saturation[k],
panel->g_task.brightness[k] != 0);
panel->g_task.brightness[k]);
if (panel_config.mouse_effects) {
task->icon_hover[k] = adjust_icon(task->icon[k],
panel_config.mouse_over_alpha,
@@ -497,7 +497,7 @@ void draw_task(void *obj, cairo_t *c)
task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0;
Color *config_text = &panel->g_task.font[task->current_state];
draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow);
draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow ? layout : NULL);
g_object_unref(layout);
g_object_unref(context);

View File

@@ -845,7 +845,8 @@ void taskbar_update_thumbnails(void *arg)
c;
c = c->next) {
Task *t = (Task *)c->data;
if ((mode == THUMB_MODE_ALL && t->current_state == TASK_ACTIVE && !g_list_find(taskbar_thumbnail_jobs_done, t)) || (mode == THUMB_MODE_ACTIVE_WINDOW && t->current_state == TASK_ACTIVE) ||
if ((mode == THUMB_MODE_ALL && t->current_state == TASK_ACTIVE && !g_list_find(taskbar_thumbnail_jobs_done, t)) ||
(mode == THUMB_MODE_ACTIVE_WINDOW && t->current_state == TASK_ACTIVE) ||
(mode == THUMB_MODE_TOOLTIP_WINDOW && g_tooltip.mapped && g_tooltip.area == &t->area)) {
task_refresh_thumbnail(t);
if (mode == THUMB_MODE_ALL)

View File

@@ -215,7 +215,7 @@ void draw_taskbarname(void *obj, cairo_t *c)
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);
draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel *)taskbar_name->area.panel)->font_shadow ? layout : NULL);
g_object_unref(layout);
g_object_unref(context);

View File

@@ -383,6 +383,11 @@ static void menuAbout()
// ====== Theme import/copy/delete ======
static void free_data(gpointer data, gpointer userdata)
{
g_free(data);
}
// Shows open dialog and copies the selected files to ~ without overwrite.
static void menuImportFile()
{
@@ -407,7 +412,7 @@ static void menuImportFile()
gchar *newpath = import_no_overwrite(l->data);
g_free(newpath);
}
g_slist_foreach(list, (GFunc)g_free, NULL);
g_slist_foreach(list, free_data, NULL);
g_slist_free(list);
gtk_widget_destroy(dialog);
}

View File

@@ -478,14 +478,14 @@ void draw(Area *a)
a->_clear(a);
}
cairo_surface_t *cs = cairo_xlib_surface_create(server.display, a->pix, server.visual, a->width, a->height);
cairo_surface_t *cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, a->width, a->height);
cairo_t *c = cairo_create(cs);
draw_background(a, c);
if (a->_draw_foreground)
a->_draw_foreground(a, c);
draw_cairo_surface_to_xpixmap(cs, a->pix);
cairo_destroy(c);
cairo_surface_destroy(cs);
}
@@ -1084,7 +1084,7 @@ void draw_text_area(Area *area,
pango_layout_set_font_description(layout, line1_font_desc);
pango_layout_set_text(layout, line1, strlen(line1));
pango_cairo_update_layout(c, layout);
draw_text(layout, c, (area->width - inner_w) / 2, line1_posy, color, ((Panel *)area->panel)->font_shadow);
draw_text(layout, c, (area->width - inner_w) / 2, line1_posy, color, ((Panel *)area->panel)->font_shadow ? layout : NULL);
}
if (line2 && line2[0]) {
@@ -1092,7 +1092,7 @@ void draw_text_area(Area *area,
pango_layout_set_indent(layout, 0);
pango_layout_set_text(layout, line2, strlen(line2));
pango_cairo_update_layout(c, layout);
draw_text(layout, c, (area->width - inner_w) / 2, line2_posy, color, ((Panel *)area->panel)->font_shadow);
draw_text(layout, c, (area->width - inner_w) / 2, line2_posy, color, ((Panel *)area->panel)->font_shadow ? layout : NULL);
}
g_object_unref(layout);

View File

@@ -362,8 +362,12 @@ pid_t tint_exec(const char *command,
// Allow children to exist after parent destruction
setsid();
// Run the command
if (dir)
chdir(dir);
if (dir) {
int ret = chdir(dir);
if (ret != 0) {
fprintf(stderr, "tint2: failed to chdir to %s\n", dir);
}
}
close_all_fds();
reset_signals();
if (terminal) {
@@ -724,27 +728,60 @@ void render_image(Drawable d, int x, int y)
XFreePixmap(server.display, pixmap);
}
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow)
gboolean is_color_attribute(PangoAttribute *attr, gpointer user_data)
{
if (font_shadow) {
const int shadow_size = 3;
const double shadow_edge_alpha = 0.0;
int i, j;
for (i = -shadow_size; i <= shadow_size; i++) {
for (j = -shadow_size; j <= shadow_size; j++) {
cairo_set_source_rgba(c,
0.0,
0.0,
0.0,
1.0 -
(1.0 - shadow_edge_alpha) *
sqrt((i * i + j * j) / (double)(shadow_size * shadow_size)));
pango_cairo_update_layout(c, layout);
cairo_move_to(c, posx + i, posy + j);
pango_cairo_show_layout(c, layout);
}
return attr->klass->type == PANGO_ATTR_FOREGROUND ||
attr->klass->type == PANGO_ATTR_BACKGROUND ||
attr->klass->type == PANGO_ATTR_UNDERLINE_COLOR ||
attr->klass->type == PANGO_ATTR_STRIKETHROUGH_COLOR ||
attr->klass->type == PANGO_ATTR_FOREGROUND_ALPHA ||
attr->klass->type == PANGO_ATTR_BACKGROUND_ALPHA;
}
gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup)
{
PangoAttrList *attrs = NULL;
char *text = NULL;
GError *error = NULL;
if (!pango_parse_markup(markup, -1, 0, &attrs, &text, NULL, &error)) {
g_error_free(error);
return FALSE;
}
pango_layout_set_text(layout, text, -1);
g_free(text);
pango_attr_list_filter(attrs, is_color_attribute, NULL);
pango_layout_set_attributes(layout, attrs);
pango_attr_list_unref(attrs);
return TRUE;
}
void draw_shadow(cairo_t *c, int posx, int posy, PangoLayout *shadow_layout)
{
const int shadow_size = 3;
const double shadow_edge_alpha = 0.0;
int i, j;
for (i = -shadow_size; i <= shadow_size; i++) {
for (j = -shadow_size; j <= shadow_size; j++) {
cairo_set_source_rgba(c,
0.0,
0.0,
0.0,
1.0 -
(1.0 - shadow_edge_alpha) *
sqrt((i * i + j * j) / (double)(shadow_size * shadow_size)));
pango_cairo_update_layout(c, shadow_layout);
cairo_move_to(c, posx + i, posy + j);
pango_cairo_show_layout(c, shadow_layout);
}
}
}
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, PangoLayout *shadow_layout)
{
if (shadow_layout)
draw_shadow(c, posx, posy, shadow_layout);
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);
@@ -1192,3 +1229,19 @@ void dump_image_data(const char *file_name, const char *name)
imlib_free_image();
}
void draw_cairo_surface_to_xpixmap(cairo_surface_t *cs, Pixmap pix)
{
int w = cairo_image_surface_get_width(cs);
int h = cairo_image_surface_get_height(cs);
cairo_surface_t *cs_xlib = cairo_xlib_surface_create(server.display, pix, server.visual, w, h);
cairo_xlib_surface_set_size(cs_xlib, w, h);
cairo_t *c_xlib = cairo_create(cs_xlib);
cairo_set_source_surface(c_xlib, cs, 0, 0);
cairo_paint(c_xlib);
cairo_surface_flush(cs_xlib);
cairo_destroy(c_xlib);
cairo_surface_destroy(cs_xlib);
}

View File

@@ -126,7 +126,8 @@ void get_text_size2(const PangoFontDescription *font,
gboolean markup,
double scale);
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup);
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, PangoLayout *shadow_layout);
// Draws a rounded rectangle
void draw_rect(cairo_t *c, double x, double y, double w, double h, double r);
@@ -153,6 +154,8 @@ void get_image_mean_color(const Imlib_Image image, Color *mean_color);
void dump_image_data(const char *file_name, const char *name);
void draw_cairo_surface_to_xpixmap(cairo_surface_t *cs, Pixmap pix);
#define free_and_null(p) \
{ \
free(p); \

View File

@@ -36,8 +36,9 @@
Server server;
void server_catch_error(Display *d, XErrorEvent *ev)
int server_catch_error(Display *d, XErrorEvent *ev)
{
return 0;
}
void server_init_atoms()
@@ -676,9 +677,10 @@ void handle_crash(const char *reason)
#endif
}
void x11_io_error(Display *display)
int x11_io_error(Display *display)
{
handle_crash("X11 I/O error");
return 0;
}
#ifdef HAVE_SN

View File

@@ -164,12 +164,12 @@ void send_event32(Window win, Atom at, long data1, long data2, long data3);
int get_property32(Window win, Atom at, Atom type);
void *server_get_property(Window win, Atom at, Atom type, int *num_results);
Atom server_get_atom(char *atom_name);
void server_catch_error(Display *d, XErrorEvent *ev);
int server_catch_error(Display *d, XErrorEvent *ev);
void server_init_atoms();
void server_init_visual();
void server_init_xdamage();
void x11_io_error(Display *display);
int x11_io_error(Display *display);
void handle_crash(const char *reason);
// detect root background

View File

@@ -25,6 +25,7 @@
#include "timer.h"
#include "test.h"
bool warnings_for_timers = true;
bool debug_timers = false;
#define MOCK_ORIGIN 1000000
@@ -59,7 +60,7 @@ void init_timer(Timer *timer, const char *name)
void destroy_timer(Timer *timer)
{
if (!g_list_find(timers, timer)) {
if (warnings_for_timers && !g_list_find(timers, timer)) {
fprintf(stderr, RED "tint2: Attempt to destroy nonexisting timer: %s" RESET "\n", timer->name_);
return;
}

View File

@@ -23,6 +23,7 @@
#include <sys/time.h>
#include "bool.h"
extern bool warnings_for_timers;
extern bool debug_timers;
typedef void TimerCallback(void *arg);

View File

@@ -21,6 +21,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -383,28 +384,42 @@ void smooth_thumbnail(cairo_surface_t *image_surface)
}
}
// This is measured to be slightly faster.
#define GetPixel(ximg, x, y) ((u_int32_t *)&(ximg->data[y * ximg->bytes_per_line]))[x]
//#define GetPixel XGetPixel
// This is measured to be slightly faster than XGetPixel.
static u_int32_t GetPixel(XImage *ximg, unsigned x, unsigned y)
{
if (x >= ximg->width || y >= ximg->height) {
fprintf(stderr, RED "GetPixel read overflow: %u %u %d %d\n",
x, y, ximg->width, ximg->height);
return 0;
}
return ((u_int32_t *)&(ximg->data[y * ximg->bytes_per_line]))[x];
}
// TODO: the xrender method only works well if there is a compositor running
cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm)
{
fprintf(stderr, GREEN "tint2: win=%u: getting thumbnail of size %u" RESET "\n", win, size);
cairo_surface_t *result = NULL;
XWindowAttributes wa;
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 ||
wa.map_state != IsViewable)
wa.map_state != IsViewable) {
fprintf(stderr, YELLOW "tint2: win=%u: no win attributes" RESET "\n", win);
goto err0;
}
if (window_is_iconified(win))
if (window_is_iconified(win)) {
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for minimized window" RESET "\n", win);
goto err0;
}
size_t w, h;
w = (size_t)wa.width;
h = (size_t)wa.height;
w = (size_t)wa.width + wa.x;
h = (size_t)wa.height + wa.y;
size_t tw, th, fw;
size_t ox, oy;
tw = size;
th = h * tw / w;
double scale = th / (double)h;
if (th > tw * 0.618) {
th = (size_t)(tw * 0.618);
fw = w * th / h;
@@ -414,20 +429,69 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
fw = tw;
ox = oy = 0;
}
if (!w || !h || !tw || !th || !fw) {
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for size 0x0" RESET "\n", win);
goto err0;
}
XShmSegmentInfo shminfo;
XImage *ximg;
if (use_shm)
ximg = XShmCreateImage(server.display,
wa.visual,
(unsigned)wa.depth,
ZPixmap,
NULL,
&shminfo,
(unsigned)w,
(unsigned)h);
else
ximg = XGetImage(server.display, win, 0, 0, (unsigned)w, (unsigned)h, AllPlanes, ZPixmap);
XImage *ximg = NULL;
XGetWindowAttributes(server.display, win, &wa);
if (wa.map_state != IsViewable) {
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for non-viewable window" RESET "\n", win);
goto err4;
}
Pixmap pix = XCreatePixmap(server.display, win, tw, th, wa.depth);
if (!pix) {
fprintf(stderr, YELLOW "tint2: win=%u: no pixmap" RESET "\n", win);
goto err4;
}
XRenderPictureAttributes attrs = {
.repeat = RepeatNone
};
XRenderPictFormat *fmt = XRenderFindVisualFormat(server.display, wa.visual);
if (!fmt) {
fprintf(stderr, YELLOW "tint2: win=%u: no XRender format" RESET "\n", win);
goto err4;
}
Picture src_pic = XRenderCreatePicture(server.display, win, fmt, CPRepeat, &attrs);
if (!src_pic) {
fprintf(stderr, YELLOW "tint2: win=%u: no src picture" RESET "\n", win);
goto err4;
}
Picture dst_pic = XRenderCreatePicture(server.display, pix, fmt, CPRepeat, &attrs);
if (!dst_pic) {
fprintf(stderr, YELLOW "tint2: win=%u: no src picture" RESET "\n", win);
goto err4;
}
fprintf(stderr, GREEN "tint2: win=%u: transformation %u %u %f xy %d %d" RESET "\n", win, ox, oy, scale,
wa.x, wa.y);
XTransform transform = {
{
{
XDoubleToFixed(1./scale),
XDoubleToFixed(0),
XDoubleToFixed(ox-wa.x/scale)
},
{
XDoubleToFixed(0),
XDoubleToFixed(1./scale),
XDoubleToFixed(oy-wa.y/scale)
},
{
XDoubleToFixed(0),
XDoubleToFixed(0),
XDoubleToFixed(1)
}
}
};
XRenderSetPictureTransform(server.display, src_pic, &transform);
XRenderSetPictureFilter(server.display, src_pic, FilterBilinear, NULL, 0);
XRenderComposite(server.display, PictOpSrc, src_pic, None, dst_pic, 0, 0, 0, 0, 0, 0, w, h);
XSync(server.display, False);
ximg = XGetImage(server.display, pix, 0, 0, (unsigned)tw, (unsigned)th, AllPlanes, ZPixmap);
if (!ximg) {
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
goto err0;
@@ -436,87 +500,32 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
fprintf(stderr, RED "tint2: unusual bits_per_pixel" RESET "\n");
goto err1;
}
if (use_shm) {
shminfo.shmid = shmget(IPC_PRIVATE, (size_t)(ximg->bytes_per_line * ximg->height), IPC_CREAT | 0777);
if (shminfo.shmid < 0) {
fprintf(stderr, RED "tint2: !shmget" RESET "\n");
goto err1;
}
shminfo.shmaddr = ximg->data = (char *)shmat(shminfo.shmid, 0, 0);
if (!shminfo.shmaddr) {
fprintf(stderr, RED "tint2: !shmat" RESET "\n");
goto err2;
}
shminfo.readOnly = False;
if (!XShmAttach(server.display, &shminfo)) {
fprintf(stderr, RED "tint2: !xshmattach" RESET "\n");
goto err3;
}
if (!XShmGetImage(server.display, win, ximg, 0, 0, AllPlanes)) {
fprintf(stderr, RED "tint2: !xshmgetimage" RESET "\n");
goto err4;
}
}
XGetWindowAttributes(server.display, win, &wa);
if (wa.map_state != IsViewable)
goto err4;
fprintf(stderr, GREEN "tint2: creating image surface %ux%u" RESET "\n", tw, th);
result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, (int)tw, (int)th);
u_int32_t *data = (u_int32_t *)cairo_image_surface_get_data(result);
memset(data, 0, tw * th);
// Fixed-point precision
const size_t prec = 1 << 16;
const size_t xstep = w * prec / fw;
const size_t ystep = h * prec / th;
const size_t offset_y1 = 0 * ystep / 8;
const size_t offset_x1 = 3 * xstep / 8;
const size_t offset_y2 = 1 * ystep / 8;
const size_t offset_x2 = 6 * xstep / 8;
const size_t offset_y3 = 4 * ystep / 8;
const size_t offset_x3 = 2 * xstep / 8;
const size_t offset_y4 = 4 * ystep / 8;
const size_t offset_x4 = 4 * xstep / 8;
const size_t offset_y5 = 4 * ystep / 8;
const size_t offset_x5 = 7 * xstep / 8;
const size_t offset_y6 = 6 * ystep / 8;
const size_t offset_x6 = 1 * xstep / 8;
const size_t offset_y7 = 7 * ystep / 8;
const size_t offset_x7 = 6 * xstep / 8;
const u_int32_t rmask = (u_int32_t)ximg->red_mask;
const u_int32_t gmask = (u_int32_t)ximg->green_mask;
const u_int32_t bmask = (u_int32_t)ximg->blue_mask;
for (size_t yt = 0, y = 0; yt < th; yt++, y += ystep) {
for (size_t xt = 0, x = 0; xt < fw; xt++, x += xstep) {
size_t j = yt * tw + ox + xt;
u_int32_t c1 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x1) / prec), (int)((y + offset_y1) / prec));
u_int32_t c2 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x2) / prec), (int)((y + offset_y2) / prec));
u_int32_t c3 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x3) / prec), (int)((y + offset_y3) / prec));
u_int32_t c4 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x4) / prec), (int)((y + offset_y4) / prec));
u_int32_t c5 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x5) / prec), (int)((y + offset_y5) / prec));
u_int32_t c6 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x6) / prec), (int)((y + offset_y6) / prec));
u_int32_t c7 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x7) / prec), (int)((y + offset_y7) / prec));
u_int32_t b = ((c1 & bmask) + (c2 & bmask) + (c3 & bmask) + (c4 & bmask) + (c5 & bmask) * 2 + (c6 & bmask) +
(c7 & bmask)) /
8;
u_int32_t g = ((c1 & gmask) + (c2 & gmask) + (c3 & gmask) + (c4 & gmask) + (c5 & gmask) * 2 + (c6 & gmask) +
(c7 & gmask)) /
8;
u_int32_t r = ((c1 & rmask) + (c2 & rmask) + (c3 & rmask) + (c4 & rmask) + (c5 & rmask) * 2 + (c6 & rmask) +
(c7 & rmask)) /
8;
data[j] = (r & rmask) | (g & gmask) | (b & bmask);
for (size_t y = 0; y < th; y++) {
for (size_t x = 0; x < tw; x++) {
u_int32_t c = (u_int32_t)XGetPixel(ximg, x, y);
data[y * tw + x] = c;
}
}
imlib_context_set_drawable(pix);
Imlib_Image img = imlib_create_image_from_drawable(0, 0, 0, tw, th, 1);
//Imlib_Image img = imlib_create_image_using_data(tw, th, data);
imlib_context_set_image(img);
char path[256];
static unsigned count = 0;
sprintf(path, "thumb-%u-%u.png", win, count++);
imlib_save_image(path);
imlib_free_image();
// Convert to argb32
if (rmask & 0xff0000) {
// argb32 or rgb24 => Nothing to do
@@ -539,24 +548,23 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
}
// 2nd pass
smooth_thumbnail(result);
//smooth_thumbnail(result);
cairo_surface_flush(result);
if (ximg) {
XDestroyImage(ximg);
ximg = NULL;
}
err4:
if (use_shm)
XShmDetach(server.display, &shminfo);
err3:
if (use_shm)
shmdt(shminfo.shmaddr);
err2:
if (use_shm)
shmctl(shminfo.shmid, IPC_RMID, NULL);
err1:
err4:
if (ximg)
XDestroyImage(ximg);
if (src_pic)
XRenderFreePicture(server.display, src_pic);
if (dst_pic)
XRenderFreePicture(server.display, dst_pic);
if (pix)
XFreePixmap(server.display, pix);
err0:
return result;
}
@@ -576,24 +584,11 @@ gboolean cairo_surface_is_blank(cairo_surface_t *image_surface)
cairo_surface_t *get_window_thumbnail(Window win, int size)
{
cairo_surface_t *image_surface = NULL;
const gboolean shm_allowed = FALSE;
if (shm_allowed && server.has_shm && server.composite_manager) {
image_surface = get_window_thumbnail_ximage(win, (size_t)size, TRUE);
if (image_surface && cairo_surface_is_blank(image_surface)) {
cairo_surface_destroy(image_surface);
image_surface = NULL;
}
if (debug_thumbnails) {
if (!image_surface)
fprintf(stderr, YELLOW "tint2: XShmGetImage failed, trying slower method" RESET "\n");
else
fprintf(stderr, "tint2: captured window using XShmGetImage\n");
}
}
if (!image_surface) {
image_surface = get_window_thumbnail_ximage(win, (size_t)size, FALSE);
if (image_surface && cairo_surface_is_blank(image_surface)) {
fprintf(stderr, RED "tint2: captured blank thumbnail" RESET "\n");
cairo_surface_destroy(image_surface);
image_surface = NULL;
}