Compare commits
14 Commits
16.6
...
thumb-xren
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36c8d41914 | ||
|
|
4dafea185f | ||
|
|
77890d463a | ||
|
|
e1211a929f | ||
|
|
00f0bbd354 | ||
|
|
15d2570a3e | ||
|
|
c76f056746 | ||
|
|
cacd4b8dad | ||
|
|
b539c0a1c0 | ||
|
|
970c597796 | ||
|
|
a82b9a1d7f | ||
|
|
89a6cadfcd | ||
|
|
fb9da655df | ||
|
|
cb137674e4 |
@@ -1,3 +1,12 @@
|
|||||||
|
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
|
2018-08-04 16.6
|
||||||
- Fix regression in task icon brightness (issue #714)
|
- Fix regression in task icon brightness (issue #714)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Latest stable release: 16.6
|
# Latest stable release: 16.6.1
|
||||||
Changes: https://gitlab.com/o9000/tint2/blob/16.6/ChangeLog
|
Changes: https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog
|
||||||
|
|
||||||
Documentation: [doc/tint2.md](doc/tint2.md)
|
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
|
git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 16.6
|
git checkout 16.6.1
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
|
|||||||
@@ -199,9 +199,9 @@ pre {
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 id="latest-stable-release-16-6"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.6</span><a name="latest-stable-release-16-6" href="#latest-stable-release-16-6" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.6/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.6/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
|
cd tint2
|
||||||
git checkout 16.6
|
git checkout 16.6.1
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.TH TINT2 1 "2018\-08\-04" 16.6
|
.TH TINT2 1 "2018\-08\-05" 16.6.1
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
tint2 \- lightweight panel/taskbar
|
tint2 \- lightweight panel/taskbar
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# TINT2 1 "2018-08-04" 16.6
|
# TINT2 1 "2018-08-05" 16.6.1
|
||||||
|
|
||||||
## NAME
|
## NAME
|
||||||
tint2 - lightweight panel/taskbar
|
tint2 - lightweight panel/taskbar
|
||||||
|
|||||||
@@ -76,19 +76,23 @@ def get_last_version():
|
|||||||
return tags[-1]
|
return tags[-1]
|
||||||
|
|
||||||
|
|
||||||
def inc_version(v, feature=False):
|
def inc_version(v, feature=False, tiny=False):
|
||||||
if v.startswith("v0."):
|
if v.startswith("v0."):
|
||||||
assert v == "v0.14.6"
|
assert v == "v0.14.6"
|
||||||
return "v15.0"
|
return "v15.0"
|
||||||
# v4.11 -> v4.12 or v5.0
|
# v4.11 -> v4.12 or v5.0 or v4.11.1
|
||||||
parts = v.split(".")
|
parts = v.split(".")
|
||||||
while len(parts) < 2:
|
while len(parts) < 3:
|
||||||
parts.append("0")
|
parts.append("0")
|
||||||
assert len(parts) == 2
|
assert len(parts) == 3
|
||||||
if feature:
|
if feature:
|
||||||
|
del parts[-1]
|
||||||
parts[-2] = "v" + str(int(parts[-2].replace("v", "")) + 1)
|
parts[-2] = "v" + str(int(parts[-2].replace("v", "")) + 1)
|
||||||
parts[-1] = "0"
|
parts[-1] = "0"
|
||||||
|
elif tiny:
|
||||||
|
parts[-1] = str(int(parts[-1]) + 1)
|
||||||
else:
|
else:
|
||||||
|
del parts[-1]
|
||||||
parts[-1] = str(int(parts[-1]) + 1)
|
parts[-1] = str(int(parts[-1]) + 1)
|
||||||
return ".".join([s for s in parts if s])
|
return ".".join([s for s in parts if s])
|
||||||
|
|
||||||
@@ -153,23 +157,14 @@ def update_log(path, version, date):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--feature", action="store_true")
|
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()
|
args = parser.parse_args()
|
||||||
logging.basicConfig(format=ansi_lblue + "%(asctime)s %(pathname)s %(levelname)s" + ansi_reset + " %(message)s", level=logging.DEBUG)
|
logging.basicConfig(format=ansi_lblue + "%(asctime)s %(pathname)s %(levelname)s" + ansi_reset + " %(message)s", level=logging.DEBUG)
|
||||||
test_inc_version()
|
test_inc_version()
|
||||||
# Read version from last tag and increment
|
# Read version from last tag and increment
|
||||||
old_version = get_last_version()
|
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)
|
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", "")
|
readable_version = version.replace("v", "")
|
||||||
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
info("New version:", readable_version, version, date)
|
info("New version:", readable_version, version, date)
|
||||||
|
|||||||
5
configure → packaging/configure
vendored
5
configure → packaging/configure
vendored
@@ -240,7 +240,7 @@ LFLAGS = shlex.split(os.environ.get('LDFLAGS', ''))
|
|||||||
LIBS = []
|
LIBS = []
|
||||||
|
|
||||||
# Get paths
|
# 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')
|
build_dir = os.path.join(os.getcwd(), 'build')
|
||||||
if not args.home:
|
if not args.home:
|
||||||
prefix = args.prefix or '/usr/local'
|
prefix = args.prefix or '/usr/local'
|
||||||
@@ -510,7 +510,8 @@ tint2conf.cflags += ['-DTINT2CONF',
|
|||||||
'-DINSTALL_PREFIX=\\"{}\\"'.format(prefix),
|
'-DINSTALL_PREFIX=\\"{}\\"'.format(prefix),
|
||||||
'-DLOCALEDIR=\\"{}\\"'.format(localedir),
|
'-DLOCALEDIR=\\"{}\\"'.format(localedir),
|
||||||
'-DGETTEXT_PACKAGE=\\"tint2conf\\"',
|
'-DGETTEXT_PACKAGE=\\"tint2conf\\"',
|
||||||
'-DHAVE_VERSION_H']
|
'-DHAVE_VERSION_H',
|
||||||
|
'-Wno-shadow']
|
||||||
|
|
||||||
tint2conf.sources = ['src/util/bt.c',
|
tint2conf.sources = ['src/util/bt.c',
|
||||||
'src/util/common.c',
|
'src/util/common.c',
|
||||||
@@ -289,7 +289,7 @@ def get_gentoo_versions():
|
|||||||
|
|
||||||
def get_void_versions():
|
def get_void_versions():
|
||||||
print >> sys.stderr, "Void ..."
|
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 = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
maintainer = None
|
maintainer = None
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ gboolean battery_enabled;
|
|||||||
gboolean battery_tooltip_enabled;
|
gboolean battery_tooltip_enabled;
|
||||||
int percentage_hide;
|
int percentage_hide;
|
||||||
static Timer battery_timer;
|
static Timer battery_timer;
|
||||||
|
static Timer battery_blink_timer;
|
||||||
|
|
||||||
#define BATTERY_BUF_SIZE 256
|
#define BATTERY_BUF_SIZE 256
|
||||||
static char buf_bat_line1[BATTERY_BUF_SIZE];
|
static char buf_bat_line1[BATTERY_BUF_SIZE];
|
||||||
@@ -60,6 +61,9 @@ char *battery_rclick_command;
|
|||||||
char *battery_uwheel_command;
|
char *battery_uwheel_command;
|
||||||
char *battery_dwheel_command;
|
char *battery_dwheel_command;
|
||||||
gboolean battery_found;
|
gboolean battery_found;
|
||||||
|
gboolean battery_warn;
|
||||||
|
gboolean battery_warn_red;
|
||||||
|
Background *battery_warn_bg;
|
||||||
|
|
||||||
char *battery_sys_prefix = (char *)"";
|
char *battery_sys_prefix = (char *)"";
|
||||||
|
|
||||||
@@ -77,6 +81,10 @@ void default_battery()
|
|||||||
battery_low_cmd_sent = FALSE;
|
battery_low_cmd_sent = FALSE;
|
||||||
battery_full_cmd_sent = FALSE;
|
battery_full_cmd_sent = FALSE;
|
||||||
INIT_TIMER(battery_timer);
|
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_has_font = FALSE;
|
||||||
bat1_font_desc = NULL;
|
bat1_font_desc = NULL;
|
||||||
bat1_format = NULL;
|
bat1_format = NULL;
|
||||||
@@ -128,7 +136,9 @@ void cleanup_battery()
|
|||||||
free(ac_disconnected_cmd);
|
free(ac_disconnected_cmd);
|
||||||
ac_disconnected_cmd = NULL;
|
ac_disconnected_cmd = NULL;
|
||||||
destroy_timer(&battery_timer);
|
destroy_timer(&battery_timer);
|
||||||
|
destroy_timer(&battery_blink_timer);
|
||||||
battery_found = FALSE;
|
battery_found = FALSE;
|
||||||
|
free_and_null(battery_warn_bg);
|
||||||
|
|
||||||
battery_os_free();
|
battery_os_free();
|
||||||
}
|
}
|
||||||
@@ -310,6 +320,40 @@ void battery_default_font_changed()
|
|||||||
schedule_panel_redraw();
|
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)
|
void update_battery_tick(void *arg)
|
||||||
{
|
{
|
||||||
if (!battery_enabled)
|
if (!battery_enabled)
|
||||||
@@ -320,6 +364,7 @@ void update_battery_tick(void *arg)
|
|||||||
gboolean old_ac_connected = battery_state.ac_connected;
|
gboolean old_ac_connected = battery_state.ac_connected;
|
||||||
int16_t old_hours = battery_state.time.hours;
|
int16_t old_hours = battery_state.time.hours;
|
||||||
int8_t old_minutes = battery_state.time.minutes;
|
int8_t old_minutes = battery_state.time.minutes;
|
||||||
|
gboolean old_warn = battery_warn;
|
||||||
|
|
||||||
if (!battery_found) {
|
if (!battery_found) {
|
||||||
init_battery();
|
init_battery();
|
||||||
@@ -357,6 +402,20 @@ void update_battery_tick(void *arg)
|
|||||||
battery_full_cmd_sent = FALSE;
|
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++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
// Show/hide if needed
|
// Show/hide if needed
|
||||||
if (!battery_found) {
|
if (!battery_found) {
|
||||||
@@ -370,8 +429,11 @@ void update_battery_tick(void *arg)
|
|||||||
// Redraw if needed
|
// Redraw if needed
|
||||||
if (panels[i].battery.area.on_screen) {
|
if (panels[i].battery.area.on_screen) {
|
||||||
if (old_found != battery_found || old_percentage != battery_state.percentage ||
|
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;
|
panels[i].battery.area.resize_needed = TRUE;
|
||||||
|
if (!battery_warn)
|
||||||
|
panels[i].battery.area.bg = panel_config.battery.area.bg;
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
button->frontend->textx,
|
button->frontend->textx,
|
||||||
button->frontend->texty,
|
button->frontend->texty,
|
||||||
&button->backend->font_color,
|
&button->backend->font_color,
|
||||||
panel_config.font_shadow);
|
panel_config.font_shadow ? layout : NULL);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
g_object_unref(context);
|
g_object_unref(context);
|
||||||
|
|||||||
@@ -173,7 +173,13 @@ gboolean time_format_needs_sec_ticks(char *time_format)
|
|||||||
{
|
{
|
||||||
if (!time_format)
|
if (!time_format)
|
||||||
return FALSE;
|
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 TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = *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));
|
*new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area));
|
||||||
} else {
|
} 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) {
|
if (*new_size != area->height) {
|
||||||
*resized = TRUE;
|
*resized = TRUE;
|
||||||
@@ -441,10 +445,17 @@ gboolean resize_execp(void *obj)
|
|||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
||||||
} else {
|
} else {
|
||||||
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
if (strlen(execp->backend->text)) {
|
||||||
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
||||||
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
||||||
execp->frontend->textx = (execp->area.width - txt_width) / 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 {
|
} else {
|
||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
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->texty = (execp->area.height - txt_height) / 2;
|
||||||
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
||||||
} else {
|
} else {
|
||||||
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
if (strlen(execp->backend->text)) {
|
||||||
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
||||||
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
||||||
execp->frontend->textx = execp->frontend->iconx;
|
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 {
|
} else {
|
||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
@@ -473,6 +491,18 @@ gboolean resize_execp(void *obj)
|
|||||||
return resized;
|
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)
|
void draw_execp(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Execp *execp = (Execp *)obj;
|
Execp *execp = (Execp *)obj;
|
||||||
@@ -480,7 +510,8 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
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) {
|
if (execp->backend->has_icon && execp->backend->icon) {
|
||||||
imlib_context_set_image(execp->backend->icon);
|
imlib_context_set_image(execp->backend->icon);
|
||||||
@@ -489,16 +520,18 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw layout
|
// draw layout
|
||||||
pango_layout_set_font_description(layout, execp->backend->font_desc);
|
if (!execp->backend->has_markup) {
|
||||||
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)
|
|
||||||
pango_layout_set_text(layout, execp->backend->text, strlen(execp->backend->text));
|
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));
|
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);
|
pango_cairo_update_layout(c, layout);
|
||||||
draw_text(layout,
|
draw_text(layout,
|
||||||
@@ -506,7 +539,7 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
execp->frontend->textx,
|
execp->frontend->textx,
|
||||||
execp->frontend->texty,
|
execp->frontend->texty,
|
||||||
&execp->backend->font_color,
|
&execp->backend->font_color,
|
||||||
panel_config.font_shadow);
|
shadow_layout);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
g_object_unref(context);
|
g_object_unref(context);
|
||||||
@@ -531,12 +564,13 @@ void execp_dump_geometry(void *obj, int indent)
|
|||||||
imlib_context_set_image(tmp);
|
imlib_context_set_image(tmp);
|
||||||
}
|
}
|
||||||
fprintf(stderr,
|
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,
|
indent,
|
||||||
"",
|
"",
|
||||||
execp->frontend->textx,
|
execp->frontend->textx,
|
||||||
execp->frontend->texty,
|
execp->frontend->texty,
|
||||||
execp->frontend->textw,
|
execp->frontend->textw,
|
||||||
|
execp->frontend->texth,
|
||||||
execp->backend->centered ? "center" : "left",
|
execp->backend->centered ? "center" : "left",
|
||||||
execp->backend->text);
|
execp->backend->text);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,8 +209,8 @@ void init_X11_pre_config()
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
server.x11_fd = ConnectionNumber(server.display);
|
server.x11_fd = ConnectionNumber(server.display);
|
||||||
XSetErrorHandler((XErrorHandler)server_catch_error);
|
XSetErrorHandler(server_catch_error);
|
||||||
XSetIOErrorHandler((XIOErrorHandler)x11_io_error);
|
XSetIOErrorHandler(x11_io_error);
|
||||||
server_init_atoms();
|
server_init_atoms();
|
||||||
server.screen = DefaultScreen(server.display);
|
server.screen = DefaultScreen(server.display);
|
||||||
server.root_win = RootWindow(server.display, server.screen);
|
server.root_win = RootWindow(server.display, server.screen);
|
||||||
@@ -247,8 +247,9 @@ void init(int argc, char **argv)
|
|||||||
if (!config_read()) {
|
if (!config_read()) {
|
||||||
fprintf(stderr, "tint2: Could not read config file.\n");
|
fprintf(stderr, "tint2: Could not read config file.\n");
|
||||||
print_usage();
|
print_usage();
|
||||||
|
warnings_for_timers = false;
|
||||||
cleanup();
|
cleanup();
|
||||||
return;
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_post_config();
|
init_post_config();
|
||||||
|
|||||||
@@ -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 scale_icon(Imlib_Image original, int icon_size)
|
||||||
{
|
{
|
||||||
Imlib_Image icon_scaled;
|
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);
|
imlib_context_set_image(original);
|
||||||
icon_scaled = imlib_create_cropped_scaled_image(0,
|
icon_scaled = imlib_create_cropped_scaled_image(0,
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -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;
|
task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0;
|
||||||
|
|
||||||
Color *config_text = &panel->g_task.font[task->current_state];
|
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(layout);
|
||||||
g_object_unref(context);
|
g_object_unref(context);
|
||||||
|
|||||||
@@ -845,7 +845,8 @@ void taskbar_update_thumbnails(void *arg)
|
|||||||
c;
|
c;
|
||||||
c = c->next) {
|
c = c->next) {
|
||||||
Task *t = (Task *)c->data;
|
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)) {
|
(mode == THUMB_MODE_TOOLTIP_WINDOW && g_tooltip.mapped && g_tooltip.area == &t->area)) {
|
||||||
task_refresh_thumbnail(t);
|
task_refresh_thumbnail(t);
|
||||||
if (mode == THUMB_MODE_ALL)
|
if (mode == THUMB_MODE_ALL)
|
||||||
|
|||||||
@@ -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);
|
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);
|
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(layout);
|
||||||
g_object_unref(context);
|
g_object_unref(context);
|
||||||
|
|||||||
@@ -383,6 +383,11 @@ static void menuAbout()
|
|||||||
|
|
||||||
// ====== Theme import/copy/delete ======
|
// ====== 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.
|
// Shows open dialog and copies the selected files to ~ without overwrite.
|
||||||
static void menuImportFile()
|
static void menuImportFile()
|
||||||
{
|
{
|
||||||
@@ -407,7 +412,7 @@ static void menuImportFile()
|
|||||||
gchar *newpath = import_no_overwrite(l->data);
|
gchar *newpath = import_no_overwrite(l->data);
|
||||||
g_free(newpath);
|
g_free(newpath);
|
||||||
}
|
}
|
||||||
g_slist_foreach(list, (GFunc)g_free, NULL);
|
g_slist_foreach(list, free_data, NULL);
|
||||||
g_slist_free(list);
|
g_slist_free(list);
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -478,14 +478,14 @@ void draw(Area *a)
|
|||||||
a->_clear(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);
|
cairo_t *c = cairo_create(cs);
|
||||||
|
|
||||||
draw_background(a, c);
|
draw_background(a, c);
|
||||||
|
|
||||||
if (a->_draw_foreground)
|
if (a->_draw_foreground)
|
||||||
a->_draw_foreground(a, c);
|
a->_draw_foreground(a, c);
|
||||||
|
|
||||||
|
draw_cairo_surface_to_xpixmap(cs, a->pix);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
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_font_description(layout, line1_font_desc);
|
||||||
pango_layout_set_text(layout, line1, strlen(line1));
|
pango_layout_set_text(layout, line1, strlen(line1));
|
||||||
pango_cairo_update_layout(c, layout);
|
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]) {
|
if (line2 && line2[0]) {
|
||||||
@@ -1092,7 +1092,7 @@ void draw_text_area(Area *area,
|
|||||||
pango_layout_set_indent(layout, 0);
|
pango_layout_set_indent(layout, 0);
|
||||||
pango_layout_set_text(layout, line2, strlen(line2));
|
pango_layout_set_text(layout, line2, strlen(line2));
|
||||||
pango_cairo_update_layout(c, layout);
|
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);
|
g_object_unref(layout);
|
||||||
|
|||||||
@@ -362,8 +362,12 @@ pid_t tint_exec(const char *command,
|
|||||||
// Allow children to exist after parent destruction
|
// Allow children to exist after parent destruction
|
||||||
setsid();
|
setsid();
|
||||||
// Run the command
|
// Run the command
|
||||||
if (dir)
|
if (dir) {
|
||||||
chdir(dir);
|
int ret = chdir(dir);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "tint2: failed to chdir to %s\n", dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
close_all_fds();
|
close_all_fds();
|
||||||
reset_signals();
|
reset_signals();
|
||||||
if (terminal) {
|
if (terminal) {
|
||||||
@@ -724,27 +728,60 @@ void render_image(Drawable d, int x, int y)
|
|||||||
XFreePixmap(server.display, pixmap);
|
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) {
|
return attr->klass->type == PANGO_ATTR_FOREGROUND ||
|
||||||
const int shadow_size = 3;
|
attr->klass->type == PANGO_ATTR_BACKGROUND ||
|
||||||
const double shadow_edge_alpha = 0.0;
|
attr->klass->type == PANGO_ATTR_UNDERLINE_COLOR ||
|
||||||
int i, j;
|
attr->klass->type == PANGO_ATTR_STRIKETHROUGH_COLOR ||
|
||||||
for (i = -shadow_size; i <= shadow_size; i++) {
|
attr->klass->type == PANGO_ATTR_FOREGROUND_ALPHA ||
|
||||||
for (j = -shadow_size; j <= shadow_size; j++) {
|
attr->klass->type == PANGO_ATTR_BACKGROUND_ALPHA;
|
||||||
cairo_set_source_rgba(c,
|
}
|
||||||
0.0,
|
|
||||||
0.0,
|
gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup)
|
||||||
0.0,
|
{
|
||||||
1.0 -
|
PangoAttrList *attrs = NULL;
|
||||||
(1.0 - shadow_edge_alpha) *
|
char *text = NULL;
|
||||||
sqrt((i * i + j * j) / (double)(shadow_size * shadow_size)));
|
GError *error = NULL;
|
||||||
pango_cairo_update_layout(c, layout);
|
if (!pango_parse_markup(markup, -1, 0, &attrs, &text, NULL, &error)) {
|
||||||
cairo_move_to(c, posx + i, posy + j);
|
g_error_free(error);
|
||||||
pango_cairo_show_layout(c, layout);
|
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);
|
cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha);
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
cairo_move_to(c, posx, posy);
|
cairo_move_to(c, posx, posy);
|
||||||
@@ -1192,3 +1229,19 @@ void dump_image_data(const char *file_name, const char *name)
|
|||||||
|
|
||||||
imlib_free_image();
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,7 +126,8 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
gboolean markup,
|
gboolean markup,
|
||||||
double scale);
|
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
|
// Draws a rounded rectangle
|
||||||
void draw_rect(cairo_t *c, double x, double y, double w, double h, double r);
|
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 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) \
|
#define free_and_null(p) \
|
||||||
{ \
|
{ \
|
||||||
free(p); \
|
free(p); \
|
||||||
|
|||||||
@@ -36,8 +36,9 @@
|
|||||||
|
|
||||||
Server server;
|
Server server;
|
||||||
|
|
||||||
void server_catch_error(Display *d, XErrorEvent *ev)
|
int server_catch_error(Display *d, XErrorEvent *ev)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_init_atoms()
|
void server_init_atoms()
|
||||||
@@ -676,9 +677,10 @@ void handle_crash(const char *reason)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void x11_io_error(Display *display)
|
int x11_io_error(Display *display)
|
||||||
{
|
{
|
||||||
handle_crash("X11 I/O error");
|
handle_crash("X11 I/O error");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
|
|||||||
@@ -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);
|
int get_property32(Window win, Atom at, Atom type);
|
||||||
void *server_get_property(Window win, Atom at, Atom type, int *num_results);
|
void *server_get_property(Window win, Atom at, Atom type, int *num_results);
|
||||||
Atom server_get_atom(char *atom_name);
|
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_atoms();
|
||||||
void server_init_visual();
|
void server_init_visual();
|
||||||
void server_init_xdamage();
|
void server_init_xdamage();
|
||||||
|
|
||||||
void x11_io_error(Display *display);
|
int x11_io_error(Display *display);
|
||||||
void handle_crash(const char *reason);
|
void handle_crash(const char *reason);
|
||||||
|
|
||||||
// detect root background
|
// detect root background
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
bool warnings_for_timers = true;
|
||||||
bool debug_timers = false;
|
bool debug_timers = false;
|
||||||
#define MOCK_ORIGIN 1000000
|
#define MOCK_ORIGIN 1000000
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ void init_timer(Timer *timer, const char *name)
|
|||||||
|
|
||||||
void destroy_timer(Timer *timer)
|
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_);
|
fprintf(stderr, RED "tint2: Attempt to destroy nonexisting timer: %s" RESET "\n", timer->name_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "bool.h"
|
#include "bool.h"
|
||||||
|
|
||||||
|
extern bool warnings_for_timers;
|
||||||
extern bool debug_timers;
|
extern bool debug_timers;
|
||||||
|
|
||||||
typedef void TimerCallback(void *arg);
|
typedef void TimerCallback(void *arg);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -383,28 +384,42 @@ void smooth_thumbnail(cairo_surface_t *image_surface)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is measured to be slightly faster.
|
// This is measured to be slightly faster than XGetPixel.
|
||||||
#define GetPixel(ximg, x, y) ((u_int32_t *)&(ximg->data[y * ximg->bytes_per_line]))[x]
|
static u_int32_t GetPixel(XImage *ximg, unsigned x, unsigned y)
|
||||||
//#define GetPixel XGetPixel
|
{
|
||||||
|
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)
|
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;
|
cairo_surface_t *result = NULL;
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 ||
|
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;
|
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;
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t w, h;
|
size_t w, h;
|
||||||
w = (size_t)wa.width;
|
w = (size_t)wa.width + wa.x;
|
||||||
h = (size_t)wa.height;
|
h = (size_t)wa.height + wa.y;
|
||||||
size_t tw, th, fw;
|
size_t tw, th, fw;
|
||||||
size_t ox, oy;
|
size_t ox, oy;
|
||||||
tw = size;
|
tw = size;
|
||||||
th = h * tw / w;
|
th = h * tw / w;
|
||||||
|
double scale = th / (double)h;
|
||||||
if (th > tw * 0.618) {
|
if (th > tw * 0.618) {
|
||||||
th = (size_t)(tw * 0.618);
|
th = (size_t)(tw * 0.618);
|
||||||
fw = w * th / h;
|
fw = w * th / h;
|
||||||
@@ -414,20 +429,69 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
|
|||||||
fw = tw;
|
fw = tw;
|
||||||
ox = oy = 0;
|
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 = NULL;
|
||||||
XImage *ximg;
|
|
||||||
if (use_shm)
|
XGetWindowAttributes(server.display, win, &wa);
|
||||||
ximg = XShmCreateImage(server.display,
|
if (wa.map_state != IsViewable) {
|
||||||
wa.visual,
|
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for non-viewable window" RESET "\n", win);
|
||||||
(unsigned)wa.depth,
|
goto err4;
|
||||||
ZPixmap,
|
}
|
||||||
NULL,
|
|
||||||
&shminfo,
|
Pixmap pix = XCreatePixmap(server.display, win, tw, th, wa.depth);
|
||||||
(unsigned)w,
|
if (!pix) {
|
||||||
(unsigned)h);
|
fprintf(stderr, YELLOW "tint2: win=%u: no pixmap" RESET "\n", win);
|
||||||
else
|
goto err4;
|
||||||
ximg = XGetImage(server.display, win, 0, 0, (unsigned)w, (unsigned)h, AllPlanes, ZPixmap);
|
}
|
||||||
|
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) {
|
if (!ximg) {
|
||||||
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
|
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
|
||||||
goto err0;
|
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");
|
fprintf(stderr, RED "tint2: unusual bits_per_pixel" RESET "\n");
|
||||||
goto err1;
|
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);
|
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);
|
u_int32_t *data = (u_int32_t *)cairo_image_surface_get_data(result);
|
||||||
memset(data, 0, tw * th);
|
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 rmask = (u_int32_t)ximg->red_mask;
|
||||||
const u_int32_t gmask = (u_int32_t)ximg->green_mask;
|
const u_int32_t gmask = (u_int32_t)ximg->green_mask;
|
||||||
const u_int32_t bmask = (u_int32_t)ximg->blue_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 y = 0; y < th; y++) {
|
||||||
for (size_t xt = 0, x = 0; xt < fw; xt++, x += xstep) {
|
for (size_t x = 0; x < tw; x++) {
|
||||||
size_t j = yt * tw + ox + xt;
|
u_int32_t c = (u_int32_t)XGetPixel(ximg, x, y);
|
||||||
u_int32_t c1 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x1) / prec), (int)((y + offset_y1) / prec));
|
data[y * tw + x] = c;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// Convert to argb32
|
||||||
if (rmask & 0xff0000) {
|
if (rmask & 0xff0000) {
|
||||||
// argb32 or rgb24 => Nothing to do
|
// 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
|
// 2nd pass
|
||||||
smooth_thumbnail(result);
|
//smooth_thumbnail(result);
|
||||||
|
cairo_surface_flush(result);
|
||||||
|
|
||||||
if (ximg) {
|
if (ximg) {
|
||||||
XDestroyImage(ximg);
|
XDestroyImage(ximg);
|
||||||
ximg = NULL;
|
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:
|
err1:
|
||||||
|
err4:
|
||||||
if (ximg)
|
if (ximg)
|
||||||
XDestroyImage(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:
|
err0:
|
||||||
return result;
|
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 *get_window_thumbnail(Window win, int size)
|
||||||
{
|
{
|
||||||
cairo_surface_t *image_surface = NULL;
|
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) {
|
if (!image_surface) {
|
||||||
image_surface = get_window_thumbnail_ximage(win, (size_t)size, FALSE);
|
image_surface = get_window_thumbnail_ximage(win, (size_t)size, FALSE);
|
||||||
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
||||||
|
fprintf(stderr, RED "tint2: captured blank thumbnail" RESET "\n");
|
||||||
cairo_surface_destroy(image_surface);
|
cairo_surface_destroy(image_surface);
|
||||||
image_surface = NULL;
|
image_surface = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user