Compare commits

...

144 Commits
15.1 ... 16.0

Author SHA1 Message Date
o9000
63d0d98a5c Release 16.0 2017-12-20 20:19:49 +01:00
o9000
e739023529 Set C standard version depending on feature tests 2017-12-20 19:59:35 +01:00
o9000
a7a9c5cdae Regression tests: check compilation on BSD 2017-12-20 19:56:49 +01:00
o9000
50822bd2fd Regression tests: check compilation on BSD 2017-12-20 19:43:23 +01:00
o9000
00c79073f0 Regression tests: check compilation on BSD 2017-12-20 19:32:29 +01:00
o9000
f5b36b37b6 Regression tests: check compilation on BSD 2017-12-20 19:24:18 +01:00
o9000
c635f46439 Feature test C11 generics, since GCC lies about compliance 2017-12-20 18:55:50 +01:00
o9000
16a359f944 Upodate readme 2017-12-20 18:21:14 +01:00
o9000
9a972f4c25 Upodate ide files 2017-12-20 17:51:19 +01:00
o9000
9d06ac0157 Upodate changelog 2017-12-20 16:54:22 +01:00
o9000
cfac6a645d Fix alignment when taskbar_distribute_size = 1 and task_align is not left (issue #688) 2017-12-20 16:47:55 +01:00
o9000
648c7c109f Move files to util 2017-12-20 16:40:23 +01:00
o9000
8946f93254 New unit testing skeleton 2017-12-19 15:32:23 +01:00
o9000
58e030de5d New unit testing skeleton 2017-12-19 15:28:57 +01:00
o9000
c2f8c210f8 gitignore 2017-12-19 12:36:18 +01:00
o9000
978e1c90fc Update translations 2017-11-26 21:45:26 +01:00
o9000
3fba8aa1cf tint2conf: Fix tooltip (issue #588) 2017-11-26 21:40:07 +01:00
o9000
26251849c6 Include also timestamp in version number for unstable builds, so that version numbers increase 2017-11-26 18:38:17 +01:00
o9000
abeb7ce2e6 Include commit hash if possible in versioning script, if a non-stable tree is compiled 2017-11-26 18:28:25 +01:00
o9000
abdb1aeff9 Include commit hash if possible in versioning script, if a non-stable tree is compiled 2017-11-26 18:20:26 +01:00
o9000
7e383c395e Include commit hash if possible in versioning script, if a non-stable tree is compiled 2017-11-26 18:14:46 +01:00
o9000
c3ed2dadf3 Fix issue #684 2017-11-26 17:22:58 +01:00
o9000
bd2ca94ffe Cleanup versioning script 2017-11-26 16:22:12 +01:00
o9000
1753641fc9 Fix issue #684 2017-11-26 16:14:31 +01:00
o9000
467ea1332c Taskbar: thumbnails (cleanup) 2017-11-26 10:24:40 +01:00
o9000
68c2ad7062 Taskbar: thumbnails (disable cairo method as it leaks heavily when screensaver is on) 2017-11-25 22:27:46 +01:00
o9000
cc5842463d Simplify get_text_size 2017-11-23 22:38:55 +01:00
o9000
5e124c7a97 Separator: fix memory leak 2017-11-23 22:37:42 +01:00
o9000
07865142b2 Refactoring 2017-11-23 22:31:19 +01:00
o9000
0c71fda5e1 Button: fix memory leak 2017-11-23 22:28:26 +01:00
o9000
8eaf187984 Implement tinting by icon content (refactoring) 2017-11-23 22:05:41 +01:00
o9000
abe8a0eeb1 Implement tinting by icon content (do not apply task state asb effects) 2017-11-22 09:06:10 +01:00
o9000
d82d782541 Update authors 2017-11-21 13:30:46 +01:00
o9000
715eb556da Taskbar: thumbnails (initialize settings) 2017-11-21 12:51:54 +01:00
o9000
b9e64da9da Update translations 2017-11-21 12:40:27 +01:00
o9000
224b7fba82 Regenerate man page 2017-11-21 12:06:01 +01:00
o9000
d72fff9653 Taskbar: thumbnails (update doc) 2017-11-21 12:05:37 +01:00
o9000
67c3e47414 Implement tinting by icon content (config and documentation) 2017-11-21 12:04:36 +01:00
o9000
e96e7fbee7 Taskbar: thumbnails (fix bad copy paste) 2017-11-20 14:12:26 +01:00
o9000
65c91667f9 Implement tinting by icon content (bugfixes) 2017-11-20 10:15:12 +01:00
o9000
9f4087b471 Implement tinting by icon content (issue #638; thanks @heisenbug) 2017-11-19 22:15:24 +01:00
o9000
247687307b Taskbar: thumbnails (update periodically only the active window) 2017-11-17 17:32:49 +01:00
o9000
2c9d1fdf7d Taskbar: thumbnails (twaked blur a bit) 2017-11-17 17:25:53 +01:00
o9000
500b8f5bea Taskbar: thumbnails (improved fixed point precision) 2017-11-17 17:09:46 +01:00
o9000
7e6f7df55e Taskbar: thumbnails (interleave slow periodic throttling with event processing) 2017-11-17 15:53:23 +01:00
o9000
47201cab84 Taskbar: thumbnails (interleave slow periodic throttling with event processing) 2017-11-17 15:40:59 +01:00
o9000
f7d083904f Timer: do not clear timers restarted from their own callback function - fix check 2017-11-17 15:40:48 +01:00
o9000
f11d30f076 Taskbar: thumbnails (only print debug info if DEBUG_THUMBNAILS environment variable is set) 2017-11-17 15:15:15 +01:00
o9000
c0eaa8274f Taskbar: thumbnails (update every 1s for the active tooltip) 2017-11-17 15:08:34 +01:00
o9000
38488b8d75 Timer: do not clear timers restarted from their own callback function 2017-11-17 15:08:27 +01:00
o9000
07339c09a0 Taskbar: thumbnails (update every 1s for the active tooltip) 2017-11-17 11:45:42 +01:00
o9000
0521223899 Taskbar: thumbnails (interleave slow periodic throttling with event processing) 2017-11-17 08:19:23 +01:00
o9000
cbf3cebbb0 Taskbar: thumbnails (XShmGetImage - avoid leaking in X) 2017-11-16 12:14:09 +01:00
o9000
4b50446a7b Taskbar: thumbnails (use slower but safed XGetImage) 2017-11-16 11:39:44 +01:00
o9000
e8a6c93b28 Fix tooltip use after free 2017-11-16 08:32:19 +01:00
o9000
5e6e1184fe Taskbar: thumbnails (small fixes and disable shm for now) 2017-11-15 21:33:52 +01:00
o9000
89ab1fa6c4 Taskbar: thumbnails (make sure we are using rgb24) 2017-11-15 14:11:39 +01:00
o9000
e597973cd7 Taskbar: thumbnails (optimizations - get rid of XGetPixel calls) 2017-11-15 13:00:27 +01:00
o9000
ebe30774ac Taskbar: thumbnails (make sure window is not minimized) 2017-11-15 12:14:37 +01:00
o9000
d463dcb5b4 Taskbar: thumbnails (optimizations) 2017-11-15 12:10:49 +01:00
o9000
23782a4414 Timer: fix use after free 2017-11-15 12:08:29 +01:00
o9000
1be85e66fe Taskbar: thumbnails (optimizations) 2017-11-15 12:08:12 +01:00
o9000
2fe7efd4fe Taskbar: thumbnails (optimizations) 2017-11-15 11:44:35 +01:00
o9000
1b6fd91611 Taskbar: thumbnails (optimizations) 2017-11-15 11:28:03 +01:00
o9000
5730725762 Taskbar: thumbnails (tint2conf) 2017-11-14 17:51:35 +01:00
o9000
87da8c76cc Taskbar: thumbnails (config, tint2conf and doc) 2017-11-14 17:09:04 +01:00
o9000
e5ecc0c15d Taskbar: thumbnails (use image size without cosidering frame) 2017-11-14 15:41:21 +01:00
o9000
812e306376 Taskbar: thumbnails (use gaussian filtering, seems faster) 2017-11-14 13:53:37 +01:00
o9000
3155a5fc89 Taskbar: thumbnails (profiling) 2017-11-14 13:08:53 +01:00
o9000
bc4af51e82 Taskbar: thumbnails (alignment) 2017-11-14 12:58:42 +01:00
o9000
01de174919 Taskbar: thumbnails (timers) 2017-11-14 12:21:08 +01:00
o9000
7ddb373cb4 Taskbar: thumbnails 2017-11-14 11:04:55 +01:00
o9000
8ba1f26309 Taskbar: thumbnails 2017-11-14 10:48:47 +01:00
o9000
5a867a83c6 Taskbar: thumbnails 2017-11-14 10:34:57 +01:00
o9000
8a7e7e4281 Update changelog 2017-11-10 13:52:21 +01:00
o9000
0e8a6dd961 Systray: warn on duplicate config option systray_name_filter (issue #652) 2017-11-10 13:44:04 +01:00
o9000
c4a0ec4140 Executor: update tooltip documentation (fixes issue #676) 2017-11-10 13:37:41 +01:00
o9000
07d907fc43 Add Spanish translation (contributed by Vicmz) 2017-11-10 13:23:03 +01:00
o9000
b1f83baf04 Update periodic testing scripts 2017-11-05 19:54:17 +01:00
o9000
1ff3404e56 Update periodic testing scripts 2017-11-05 19:51:09 +01:00
o9000
41190204b3 Update periodic testing script 2017-11-05 19:33:09 +01:00
o9000
5bc978ee44 Update periodic testing script 2017-11-05 19:16:02 +01:00
o9000
3b4028f443 Update periodic testing script 2017-11-05 19:14:34 +01:00
o9000
acc3ee9205 Update periodic testing script 2017-11-05 15:38:33 +01:00
o9000
d8770ed590 Release 15.3 2017-11-05 12:28:35 +01:00
o9000
be7873a688 Update release script 2017-11-05 12:28:02 +01:00
o9000
cf81f1c9f9 Update release script 2017-11-05 12:27:05 +01:00
o9000
cde05df1bc Update release script 2017-11-05 12:24:46 +01:00
o9000
5fee459945 Update changelog 2017-11-05 12:19:56 +01:00
o9000
6d67291928 Update release script 2017-11-05 12:18:24 +01:00
o9000
4171e23153 Do not run regression tests more than once for a commit 2017-10-16 11:09:56 +02:00
o9000
725f625aba Use correct whitespace in debian/rules (makefile) 2017-10-15 20:48:28 +02:00
o9000
a6ea1eb5a9 Packaging: Workaround cmake issues 2017-10-15 20:41:46 +02:00
o9000
14b983cd0c Packaging: Workaround cmake issues 2017-10-15 20:30:39 +02:00
o9000
23ddb47e0c Reset signal mask at startup 2017-10-15 13:07:12 +02:00
o9000
407aef3786 Reset signal mask before executing commands (issue #674) 2017-10-15 13:00:18 +02:00
o9000
50c7bf77de Do not hardcode path to /etc 2017-10-04 19:15:44 +02:00
o9000
9a7d5a1a51 Release 15.2 2017-10-01 18:45:36 +02:00
o9000
031bd23849 Print tint2: before geometry dumps 2017-10-01 18:33:53 +02:00
o9000
7e2dc91ce7 Silence warning 2017-10-01 14:04:34 +02:00
o9000
c7a81655c4 Merge branch 'warning' into 'master'
Fix warning ISO C does not support __FUNCTION__

See merge request o9000/tint2!28
2017-10-01 11:54:43 +00:00
fafryd
9aa50104db Fix warning ISO C does not support __FUNCTION__
"warning: ISO C does not support ‘__FUNCTION__’ predefined identifier"

Among others -Wpedantic now warns about non-standard predefined identifiers.
The fix is either to use the standard predefined identifier __func__ (since C99),
or to use the __extension__ keyword.
2017-10-01 09:37:05 +02:00
o9000
3320ee8e05 Regression testing 2017-09-29 10:32:24 +02:00
o9000
ec380e25ec Regression testing 2017-09-28 20:06:39 +02:00
o9000
e1b29d0204 Regression testing 2017-09-28 19:39:30 +02:00
o9000
13313f64c5 Regression testing 2017-09-28 19:18:34 +02:00
o9000
9cb64e9cf5 Regression testing 2017-09-28 19:10:10 +02:00
o9000
fd0a1bef65 Regression testing 2017-09-28 18:51:07 +02:00
o9000
ae9ae098cc Regression testing 2017-09-28 18:47:42 +02:00
o9000
18f49d0d52 Regression testing 2017-09-28 18:39:15 +02:00
o9000
a57b6a4706 Regression testing 2017-09-28 18:38:54 +02:00
o9000
f8aa84a91b Regression testing 2017-09-28 18:36:34 +02:00
o9000
0154fe6a5a Regression testing 2017-09-28 15:59:29 +02:00
o9000
6f96818438 Regression testing 2017-09-28 15:43:12 +02:00
o9000
6433767a98 Regression testing 2017-09-28 15:39:10 +02:00
o9000
f8037b7ff5 Regression testing 2017-09-28 15:19:51 +02:00
o9000
7dddd4a5a2 Regression testing 2017-09-28 15:15:00 +02:00
o9000
85ac37d019 Regression testing 2017-09-28 15:11:31 +02:00
o9000
499b2bd938 Regression testing 2017-09-28 15:09:57 +02:00
o9000
5302fb4ba7 Regression testing 2017-09-28 15:08:26 +02:00
o9000
b58a6512b3 Update changelog 2017-09-28 12:27:26 +02:00
o9000
e38ccf5376 Remember window order on panel restart (issue #615) 2017-09-28 12:26:46 +02:00
o9000
3c9a0ff2f7 Updated changelog 2017-09-28 11:28:17 +02:00
o9000
b8675fa208 Compute text size correctly (issue #671) 2017-09-28 11:23:31 +02:00
o9000
ddac8f7802 Battery: add data gathering script 2017-09-17 15:20:38 +02:00
o9000
c21930de2b Battery: check that data files are readable and non-empty 2017-09-17 14:26:29 +02:00
o9000
f2cc1b68c1 More battery data 2017-09-17 14:12:41 +02:00
o9000
fc61676732 Battery: Do not show time remaining if rate is zero 2017-09-17 14:09:48 +02:00
o9000
1772d0a894 More battery data 2017-09-17 14:04:07 +02:00
o9000
3de424b129 Allow batteries that do not provide the charging rate 2017-09-17 14:04:03 +02:00
o9000
d8c289e0cc More battery data 2017-09-17 13:50:58 +02:00
o9000
5a17bb2fda Update packaging info script 2017-09-12 23:41:06 +02:00
o9000
c45b06657a Update packaging info script 2017-09-12 23:38:21 +02:00
o9000
7666077c63 Update packaging info script 2017-09-12 23:34:53 +02:00
o9000
542aa56840 Update packaging info script 2017-09-12 23:28:49 +02:00
o9000
d2f990366b Update packaging info script 2017-09-12 23:26:27 +02:00
o9000
1480faf32f Update packaging info script 2017-09-12 23:15:12 +02:00
o9000
38ff3318eb Update packaging info script 2017-09-12 23:14:08 +02:00
o9000
5bd253c0da Update packaging info script 2017-09-12 23:07:57 +02:00
o9000
9e94ee15e4 Update packaging info script 2017-09-12 22:56:25 +02:00
o9000
a026cd91fe Update memory reporting script 2017-09-12 22:36:52 +02:00
o9000
a52c45bd08 Remove duplicate entry 2017-09-12 22:36:30 +02:00
o9000
88c91aae25 Update version checker 2017-09-12 22:36:13 +02:00
o9000
b793544cf8 Add memory analysis script 2017-09-11 19:02:02 +02:00
170 changed files with 6756 additions and 2020 deletions

4
.gitignore vendored
View File

@@ -1,3 +1,7 @@
build
*.user
version.h
*.pyc
*.todo
packaging/make_ubuntu2.sh
test_*.log

View File

@@ -31,6 +31,7 @@ Contributors:
Matthew Otnel : config option systray_name_filter
Ryan Gray, Jeff Blake (https://gitlab.com/berkley4) : battery format
aaaz (https://gitlab.com/aaaz) : clock fixes
heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color
Translations:
Bosnian:
@@ -45,3 +46,5 @@ Translations:
Daniel Napora <napcok@gmail.com>
Serbian:
Dino Duratović <dinomol@mail.com>
Spanish:
Vic <vicmz@yandex.com>

View File

@@ -25,7 +25,7 @@ endif()
include( FindPkgConfig )
include( CheckLibraryExists )
include( CheckCSourceCompiles )
pkg_check_modules( X11 REQUIRED x11 xcomposite xdamage xinerama xrender xrandr>=1.3 )
pkg_check_modules( X11 REQUIRED x11 xcomposite xdamage xinerama xext xrender xrandr>=1.3 )
pkg_check_modules( PANGOCAIRO REQUIRED pangocairo )
pkg_check_modules( PANGO REQUIRED pango )
pkg_check_modules( CAIRO REQUIRED cairo )
@@ -62,6 +62,17 @@ else()
set(BACKTRACE_L_FLAGS "")
endif()
check_c_source_compiles(
"#define print(x) _Generic((x), default : print_unknown)(x) \n void print_unknown(){} \n int main () { print(0); }"
HAS_GENERIC)
if(HAS_GENERIC)
add_definitions(-DHAS_GENERIC)
set(CSTD "c11")
else()
set(CSTD "c99")
endif(HAS_GENERIC)
if( ENABLE_RSVG )
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
endif( ENABLE_RSVG )
@@ -116,11 +127,11 @@ include_directories( ${PROJECT_BINARY_DIR}
set( SOURCES src/config.c
src/panel.c
src/server.c
src/util/server.c
src/main.c
src/init.c
src/signals.c
src/tracing.c
src/util/signals.c
src/util/tracing.c
src/mouse_actions.c
src/drag_and_drop.c
src/clock/clock.c
@@ -146,7 +157,9 @@ set( SOURCES src/config.c
src/util/timer.c
src/util/cache.c
src/util/color.c
src/util/print.c
src/util/gradient.c
src/util/test.c
src/util/uevent.c
src/util/window.c )
@@ -188,7 +201,6 @@ endif( ENABLE_SN)
if( ENABLE_UEVENT )
add_definitions( -DENABLE_UEVENT )
set( SOURCES ${SOURCES} src/util/uevent.c)
endif( ENABLE_UEVENT )
if(ENABLE_BACKTRACE)
@@ -268,13 +280,13 @@ endif( RT_LIBRARY )
target_link_libraries( tint2 m )
add_dependencies( tint2 version )
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=c99 ${ASAN_C_FLAGS} ${TRACING_C_FLAGS}" )
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=${CSTD} ${ASAN_C_FLAGS} ${TRACING_C_FLAGS}" )
set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS} ${BACKTRACE_L_FLAGS} ${TRACING_L_FLAGS}" )
install( TARGETS tint2 DESTINATION bin )
install( FILES tint2.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps )
install( FILES tint2.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )
install( FILES themes/tint2rc DESTINATION /etc/xdg/tint2 )
install( FILES themes/tint2rc DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/xdg/tint2 )
install( FILES default_icon.png DESTINATION ${CMAKE_INSTALL_DATADIR}/tint2 )
install( FILES AUTHORS ChangeLog README.md doc/tint2.md DESTINATION ${docdir} )
install( FILES doc/manual.html doc/readme.html DESTINATION ${htmldir} )

View File

@@ -1,3 +1,24 @@
2017-12-20 16.0
- Fixes:
- Taskbar: `taskbar_distribute_size = 1` now playes well with `task_align = center` and
`task_align = right` (issue #688)
- Enhancements:
- Added Spanish translation (contributed by Vicmz)
- Executor: updated tooltip documentation (issue #676)
- Systray: warn on duplicate config option systray_name_filter (issue #652)
- Changed standard from C99 to C11 to support generic printing for unit tests
2017-11-05 15.3
- Fixes:
- Launcher: Reset signal mask before executing commands (issue #674)
- cmake: Do not hardcode path to /etc
2017-10-01 15.2
- Fixes:
- Battery info is now again displayed even when current sensor is missing (https://github.com/jmc-88/tint3/issues/34)
- Text elements compute their size correctly (issue #671)
- Window order persists on panel restart (issue #615)
2017-09-08 15.1
- Fixes:
- Fixed build on non-Linux and non-x86 systems
@@ -952,3 +973,6 @@ released tint-0.2
while the projet is no longer in developpement, have not changed the name of 'tint'.
.
.
.
.
.

View File

@@ -1,5 +1,5 @@
# Latest stable release: 15.1
Changes: https://gitlab.com/o9000/tint2/blob/15.1/ChangeLog
# Latest stable release: 16.0
Changes: https://gitlab.com/o9000/tint2/blob/16.0/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 15.1
git checkout 16.0
mkdir build
cd build
cmake ..
@@ -61,9 +61,9 @@ tint2 is a simple panel/taskbar made for modern X window managers. It was specif
# Known issues
* Graphic glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA ([issue 595](https://gitlab.com/o9000/tint2/issues/595))
* Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (known issues for [awesome](https://gitlab.com/o9000/tint2/issues/385), [bspwm](https://gitlab.com/o9000/tint2/issues/524). [openbox-multihead](https://gitlab.com/o9000/tint2/issues/456))
* Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE)
* Graphical glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA ([issue 595](https://gitlab.com/o9000/tint2/issues/595))
* Window managers that do not follow exactly the EWMH specification might not interact well with tint2 ([issue 627](https://gitlab.com/o9000/tint2/issues/627)).
* Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE).
# How can I help out?

View File

@@ -270,6 +270,8 @@ Try to respect as much as possible the order of the options as given below.</p><
<li><code>color</code> is specified in hex RGB, e.g. #ff0000 is red</li>
<li><code>opacity</code> varies from (0 to 100), where 0 is fully transparent, 100 is fully opaque</li>
</ul></li>
<li><p><code>border_content_tint_weight = integer</code> : Mixes the border color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). <em>(since 16.0)</em></p></li>
<li><p><code>background_content_tint_weight = integer</code> : Mixes the background color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). <em>(since 16.0)</em></p></li>
</ul>
<p>You can define as many backgrounds as you want. For example, the following config defines two backgrounds:</p><pre class="highlight plaintext"><code>rounded = 1
border_width = 0
@@ -481,6 +483,8 @@ panel_size = 94% 30
<li><p><code>task_text = boolean (0 or 1)</code> : Whether to display the task text.</p></li>
<li><p><code>task_centered = boolean (0 or 1)</code> : Whether the task text is centered.</p></li>
<li><p><code>task_tooltip = boolean (0 or 1)</code> : Whether to show tooltips for tasks.</p></li>
<li><p><code>task_thumbnail = boolean (0 or 1)</code> : Whether to show thumbnail tooltips for tasks. <em>(since 16.0)</em></p></li>
<li><p><code>task_thumbnail_size = width</code> : Thumbnail size. <em>(since 16.0)</em></p></li>
<li><p><code>task_maximum_size = width height</code></p>
<ul>
<li><code>width</code> is used with horizontal panels to limit the size of the tasks. Use <code>width = 0</code> to get full taskbar width.</li>
@@ -601,7 +605,7 @@ panel_size = 94% 30
<li><p><code>execp_cache_icon = boolean (0 or 1)</code> : If <code>execp_cache_icon = 0</code>, the image is reloaded each time the command is executed (useful if the image file is changed on disk by the program executed by <code>execp_command</code>). <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_icon_w = integer</code> : You can use <code>execp_icon_w</code> and <code>execp_icon_h</code> to resize the image. If one of them is zero/missing, the image is rescaled proportionally. If both of them are zero/missing, the image is not rescaled. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_icon_h = integer</code> : See <code>execp_icon_w</code>. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_tooltip = text</code> : The tooltip. Leave it empty to not display a tooltip. Not specifying this option leads to showing an automatically generated tooltip with information about when the command was last executed. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_tooltip = text</code> : The tooltip. If left empty, no tooltip is displayed. If missing, the standard error of the command is shown as a tooltip (an ANSI clear screen sequence can reset the contents, bash: <code>printf '\e[2J'</code>, C: <code>printf(&quot;\x1b[2J&quot;);</code>). If the standard error is empty, the tooltip will show information about the time when the command was last executed. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code> : The font used to draw the text. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_font_color = color opacity</code> : The font color. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_markup = boolean (0 or 1)</code> : If non-zero, the output of the command is treated as Pango markup, which allows rich text formatting. The format is <a href="https://developer.gnome.org/pygtk/stable/pango-markup-language.html">documented here</a>. Note that using this with commands that print data downloaded from the Internet is a possible security risk. <em>(since 0.12.4)</em></p></li>

View File

@@ -199,9 +199,9 @@ pre {
</style>
</head>
<body>
<h1 id="latest-stable-release-15-1"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">15.1</span><a name="latest-stable-release-15-1" href="#latest-stable-release-15-1" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/15.1/ChangeLog">https://gitlab.com/o9000/tint2/blob/15.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
<h1 id="latest-stable-release-16-0"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.0</span><a name="latest-stable-release-16-0" href="#latest-stable-release-16-0" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.0/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.0/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 15.1
git checkout 16.0
mkdir build
cd build
cmake ..
@@ -239,9 +239,9 @@ update-mime-database /usr/local/share/mime
</ul>
<h1 id="known-issues">Known issues<a name="known-issues" href="#known-issues" class="md2man-permalink" title="permalink"></a></h1>
<ul>
<li>Graphic glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA (<a href="https://gitlab.com/o9000/tint2/issues/595">issue 595</a>)</li>
<li>Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (known issues for <a href="https://gitlab.com/o9000/tint2/issues/385">awesome</a>, <a href="https://gitlab.com/o9000/tint2/issues/524">bspwm</a>. <a href="https://gitlab.com/o9000/tint2/issues/456">openbox-multihead</a>)</li>
<li>Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE)</li>
<li>Graphical glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA (<a href="https://gitlab.com/o9000/tint2/issues/595">issue 595</a>)</li>
<li>Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (<a href="https://gitlab.com/o9000/tint2/issues/627">issue 627</a>).</li>
<li>Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE).</li>
</ul>
<h1 id="how-can-i-help-out">How can I help out?<a name="how-can-i-help-out" href="#how-can-i-help-out" class="md2man-permalink" title="permalink"></a></h1>
<ul>

View File

@@ -1,4 +1,4 @@
.TH TINT2 1 "2017\-09\-08" 15.1
.TH TINT2 1 "2017\-12\-20" 16.0
.SH NAME
.PP
tint2 \- lightweight panel/taskbar
@@ -150,6 +150,10 @@ The tint2 config file starts with the options defining background elements with
.IP \(bu 2
\fB\fCopacity\fR varies from (0 to 100), where 0 is fully transparent, 100 is fully opaque
.RE
.IP \(bu 2
\fB\fCborder_content_tint_weight = integer\fR : Mixes the border color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). \fI(since 16.0)\fP
.IP \(bu 2
\fB\fCbackground_content_tint_weight = integer\fR : Mixes the background color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). \fI(since 16.0)\fP
.RE
.PP
You can define as many backgrounds as you want. For example, the following config defines two backgrounds:
@@ -508,6 +512,10 @@ The following options configure the task buttons in the taskbar:
.IP \(bu 2
\fB\fCtask_tooltip = boolean (0 or 1)\fR : Whether to show tooltips for tasks.
.IP \(bu 2
\fB\fCtask_thumbnail = boolean (0 or 1)\fR : Whether to show thumbnail tooltips for tasks. \fI(since 16.0)\fP
.IP \(bu 2
\fB\fCtask_thumbnail_size = width\fR : Thumbnail size. \fI(since 16.0)\fP
.IP \(bu 2
\fB\fCtask_maximum_size = width height\fR
.RS
.IP \(bu 2
@@ -716,7 +724,7 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
.IP \(bu 2
\fB\fCexecp_icon_h = integer\fR : See \fB\fCexecp_icon_w\fR\&. \fI(since 0.12.4)\fP
.IP \(bu 2
\fB\fCexecp_tooltip = text\fR : The tooltip. Leave it empty to not display a tooltip. Not specifying this option leads to showing an automatically generated tooltip with information about when the command was last executed. \fI(since 0.12.4)\fP
\fB\fCexecp_tooltip = text\fR : The tooltip. If left empty, no tooltip is displayed. If missing, the standard error of the command is shown as a tooltip (an ANSI clear screen sequence can reset the contents, bash: \fB\fCprintf '\\e[2J'\fR, C: \fB\fCprintf("\\x1b[2J");\fR). If the standard error is empty, the tooltip will show information about the time when the command was last executed. \fI(since 0.12.4)\fP
.IP \(bu 2
\fB\fCexecp_font = [FAMILY\-LIST] [STYLE\-OPTIONS] [SIZE]\fR : The font used to draw the text. \fI(since 0.12.4)\fP
.IP \(bu 2

View File

@@ -1,4 +1,4 @@
# TINT2 1 "2017-09-08" 15.1
# TINT2 1 "2017-12-20" 16.0
## NAME
tint2 - lightweight panel/taskbar
@@ -119,6 +119,10 @@ The tint2 config file starts with the options defining background elements with
* `color` is specified in hex RGB, e.g. #ff0000 is red
* `opacity` varies from (0 to 100), where 0 is fully transparent, 100 is fully opaque
* `border_content_tint_weight = integer` : Mixes the border color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). *(since 16.0)*
* `background_content_tint_weight = integer` : Mixes the background color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). *(since 16.0)*
You can define as many backgrounds as you want. For example, the following config defines two backgrounds:
```
@@ -409,6 +413,10 @@ The following options configure the task buttons in the taskbar:
* `task_tooltip = boolean (0 or 1)` : Whether to show tooltips for tasks.
* `task_thumbnail = boolean (0 or 1)` : Whether to show thumbnail tooltips for tasks. *(since 16.0)*
* `task_thumbnail_size = width` : Thumbnail size. *(since 16.0)*
* `task_maximum_size = width height`
* `width` is used with horizontal panels to limit the size of the tasks. Use `width = 0` to get full taskbar width.
* `height` is used with vertical panels.
@@ -591,7 +599,7 @@ The action semantics:
* `execp_icon_h = integer` : See `execp_icon_w`. *(since 0.12.4)*
* `execp_tooltip = text` : The tooltip. Leave it empty to not display a tooltip. Not specifying this option leads to showing an automatically generated tooltip with information about when the command was last executed. *(since 0.12.4)*
* `execp_tooltip = text` : The tooltip. If left empty, no tooltip is displayed. If missing, the standard error of the command is shown as a tooltip (an ANSI clear screen sequence can reset the contents, bash: `printf '\e[2J'`, C: `printf("\x1b[2J");`). If the standard error is empty, the tooltip will show information about the time when the command was last executed. *(since 0.12.4)*
* `execp_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]` : The font used to draw the text. *(since 0.12.4)*

View File

@@ -1,9 +1,10 @@
#!/bin/sh
MAJOR=0.14
SCRIPT_DIR=$(dirname "$0")
DIRTY=""
VERSION=""
if git status 1>/dev/null 2>/dev/null
if [ -d ${SCRIPT_DIR}/.git ] && git status 1>/dev/null 2>/dev/null
then
git update-index -q --ignore-submodules --refresh
# Disallow unstaged changes in the working tree
@@ -31,9 +32,23 @@ then
DIRTY="-dirty"
fi
fi
VERSION=$(git describe --exact-match 2>/dev/null || echo "$MAJOR-git$(git show -s --pretty=format:%ci | cut -d ' ' -f 1 | tr -d '-').$(git show -s --pretty=format:%h)")$DIRTY
else
SCRIPT_DIR=$(dirname "$0")
if git describe 1>/dev/null 2>/dev/null
then
VERSION=$(git describe 2>/dev/null)$DIRTY
elif git log -n 1 1>/dev/null 2>/dev/null
then
VERSION=$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 2)
if [ "$VERSION" = "master" ]
then
PREVIOUS=$(grep '^2' "${SCRIPT_DIR}/ChangeLog" | head -n 2 | tail -n 1 | cut -d ' ' -f 2)
HASH=$(git log -n 1 --pretty=format:%cI.%ct.%h | tr -d ':' | tr -d '-' | tr '.' '-' | sed 's/T[0-9\+]*//g' 2>/dev/null)
VERSION=$PREVIOUS-next-$HASH
fi
fi
fi
if [ -z "$VERSION" ]
then
VERSION=$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 2)
if [ "$VERSION" = "master" ]
then
@@ -41,7 +56,6 @@ else
fi
fi
VERSION=$(echo "$VERSION" | sed 's/^v//')
echo '#define VERSION_STRING "'$VERSION'"' > version.h

View File

@@ -190,3 +190,7 @@ if __name__ == '__main__':
run("cd tint2-%s ; mkdir build ; cd build ; cmake .. ; make" % readable_version)
assert_equal(run("./tint2-%s/build/tint2 -v" % readable_version).strip(), "tint2 version %s" % readable_version)
os.system("git log -p -1 --word-diff")
print "Does this look correct? [y/n]"
choice = raw_input().lower()
if choice != "y":
run("git reset --hard HEAD~ ; git tag -d %s ; git tag -d %s" % (version, readable_version))

View File

@@ -4,7 +4,7 @@
dh $@
override_dh_auto_configure:
dh_auto_configure -- -DCMAKE_BUILD_TYPE=RelWithDebInfo
dh_auto_configure -- -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_SYSCONFDIR=/etc
override_dh_auto_install:
dh_auto_install --destdir=$(CURDIR)/debian/tmp

View File

@@ -0,0 +1,23 @@
#!/bin/bash
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
set -e
set -x
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
exec > ~/tint2.runner-version.log
exec 2>&1
cd ~/tint2.wiki
git reset --hard
git pull
~/tint2/packaging/version_status.py > packaging.tmp.md
cat packaging.tmp.md > packaging.md
rm packaging.tmp.md
git commit -am 'Update packaging info'
git push origin master

View File

@@ -161,12 +161,14 @@ def get_debian_release_version(release):
def get_debian_versions():
print >> sys.stderr, "Debian ..."
return "Debian", "debian", [get_debian_release_version(release) for release in ["stable", "testing", "unstable", "experimental"]]
# Ubuntu
def get_ubuntu_versions():
print >> sys.stderr, "Ubuntu ..."
data = http_download_txt("https://api.launchpad.net/1.0/ubuntu/+archive/primary?ws.op=getPublishedSources&source_name=tint2&exact_match=true")
data = json.loads(data)["entries"]
data.reverse()
@@ -183,6 +185,7 @@ def get_ubuntu_versions():
# BunsenLabs
def get_bunsenlabs_versions():
print >> sys.stderr, "BunsenLabs ..."
dirs = http_list_dir("https://eu.pkg.bunsenlabs.org/debian/dists/")
versions = []
for d in dirs:
@@ -198,6 +201,7 @@ def get_bunsenlabs_versions():
# Arch
def get_arch_versions():
print >> sys.stderr, "Arch ..."
pkgbuild = http_download_txt("https://git.archlinux.org/svntogit/community.git/plain/trunk/PKGBUILD?h=packages/tint2")
version, maintainer = arch_pkgbuild_extract_version(pkgbuild)
return "Arch Linux", "archlinux", [("Community", version, maintainer)]
@@ -206,6 +210,7 @@ def get_arch_versions():
# Fedora
def get_fedora_versions():
print >> sys.stderr, "Fedora ..."
dirs = http_list_dir("http://mirror.switch.ch/ftp/mirror/fedora/linux/development/")
versions = []
for d in dirs:
@@ -224,6 +229,7 @@ def get_fedora_versions():
# Red Hat (EPEL)
def get_redhat_epel_versions():
print >> sys.stderr, "RedHat ..."
dirs = http_list_dir("http://mirror.switch.ch/ftp/mirror/epel/")
versions = []
for d in dirs:
@@ -242,12 +248,13 @@ def get_redhat_epel_versions():
# SUSE
def get_suse_versions():
print >> sys.stderr, "Suse ..."
ftp = ftplib.FTP("mirror.switch.ch")
ftp.login()
releases, _ = ftp_list_dir(ftp, "/mirror/opensuse/opensuse/distribution/leap/")
releases, _ = ftp_list_dir(ftp, "/mirror/opensuse/opensuse/ports/update/leap/")
versions = []
for release in releases:
root = "/mirror/opensuse/opensuse/distribution/leap/{0}/repo/oss/suse/repodata/".format(release)
root = "/mirror/opensuse/opensuse/ports/update/leap/{0}/oss/repodata/".format(release)
_, files = ftp_list_dir(ftp, root)
for fname in files:
if fname.endswith("-primary.xml.gz"):
@@ -266,6 +273,7 @@ def get_suse_versions():
# Gentoo
def get_gentoo_versions():
print >> sys.stderr, "Gentoo ..."
files = http_list_dir("https://gitweb.gentoo.org/repo/gentoo.git/tree/x11-misc/tint2")
versions = []
for f in files:
@@ -280,6 +288,7 @@ def get_gentoo_versions():
# Void
def get_void_versions():
print >> sys.stderr, "Void ..."
template = http_download_txt("https://raw.githubusercontent.com/voidlinux/void-packages/master/srcpkgs/tint2/template")
versions = []
version = None
@@ -297,6 +306,7 @@ def get_void_versions():
# Alpine
def get_alpine_versions():
print >> sys.stderr, "Alpine ..."
apkbuild = http_download_txt("https://git.alpinelinux.org/cgit/aports/plain/community/tint2/APKBUILD")
versions = []
version = None
@@ -314,6 +324,7 @@ def get_alpine_versions():
# Slackware
def get_slack_versions():
print >> sys.stderr, "Slackware ..."
dirs = http_list_dir("https://slackbuilds.org/slackbuilds/")
versions = []
for d in dirs:
@@ -337,6 +348,7 @@ def get_slack_versions():
# FreeBSD
def get_freebsd_versions():
print >> sys.stderr, "FreeBSD ..."
makefile = http_download_txt("https://svnweb.freebsd.org/ports/head/x11/tint/Makefile?view=co")
versions = []
version = None
@@ -354,6 +366,7 @@ def get_freebsd_versions():
# OpenBSD
def get_openbsd_versions():
print >> sys.stderr, "OpenBSD ..."
makefile = http_download_txt("http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/ports/x11/tint2/Makefile?rev=1.5&content-type=text/plain")
versions = []
version = None
@@ -368,6 +381,7 @@ def get_openbsd_versions():
# Upstream
def get_tint2_version():
print >> sys.stderr, "Upstream ..."
readme = http_download_txt("https://gitlab.com/o9000/tint2/raw/master/README.md")
version = readme.split("\n", 1)[0].split(":", 1)[-1].strip()
return version
@@ -381,7 +395,7 @@ def main():
distros.append(get_ubuntu_versions())
distros.append(get_fedora_versions())
distros.append(get_redhat_epel_versions())
distros.append(get_suse_versions())
#distros.append(get_suse_versions())
distros.append(get_alpine_versions())
distros.append(get_slack_versions())
distros.append(get_arch_versions())

View File

@@ -197,7 +197,7 @@ void battery_update_text(char *dest, char *format)
if (battery_state.state == BATTERY_FULL) {
snprintf(buf, sizeof(buf), "Full");
strnappend(dest, buf, BATTERY_BUF_SIZE);
} else {
} else if (battery_state.time.hours > 0 && battery_state.time.minutes > 0) {
snprintf(buf, sizeof(buf), "%02d:%02d", battery_state.time.hours, battery_state.time.minutes);
strnappend(dest, buf, BATTERY_BUF_SIZE);
}

View File

@@ -60,6 +60,20 @@ struct psy_mains {
gboolean online;
};
static gboolean is_file_non_empty(const char *path)
{
FILE *f = fopen(path, "r");
if (!f)
return FALSE;
char buffer[1024];
size_t count = fread(buffer, 1, sizeof(buffer), f);
fclose(f);
if (count > 0)
return TRUE;
else
return FALSE;
}
static void uevent_battery_update()
{
update_battery_tick(NULL);
@@ -73,11 +87,11 @@ static void uevent_battery_plug()
}
static struct uevent_notify psy_plug = {UEVENT_ADD | UEVENT_REMOVE, "power_supply", NULL, uevent_battery_plug};
#define RETURN_ON_ERROR(err) \
if (err) { \
g_error_free(err); \
#define RETURN_ON_ERROR(err) \
if (err) { \
g_error_free(err); \
fprintf(stderr, RED "tint2: %s:%d: errror" RESET "\n", __FILE__, __LINE__); \
return FALSE; \
return FALSE; \
}
static GList *batteries = NULL;
@@ -96,12 +110,13 @@ static enum psy_type power_supply_get_type(const gchar *entryname)
gsize typelen;
g_file_get_contents(path_type, &type, &typelen, &error);
g_free(path_type);
if (error) {
fprintf(stderr, RED "tint2: %s:%d: read failed" RESET "\n", __FILE__, __LINE__);
fprintf(stderr, RED "tint2: %s:%d: read failed for %s" RESET "\n", __FILE__, __LINE__, path_type);
g_free(path_type);
g_error_free(error);
return PSY_UNKNOWN;
}
g_free(path_type);
if (!g_strcmp0(type, "Battery\n")) {
g_free(type);
@@ -123,8 +138,8 @@ static gboolean init_linux_battery(struct psy_battery *bat)
const gchar *entryname = bat->name;
bat->path_present = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "present", NULL);
if (!g_file_test(bat->path_present, G_FILE_TEST_EXISTS)) {
fprintf(stderr, RED "tint2: %s:%d: read failed" RESET "\n", __FILE__, __LINE__);
if (!is_file_non_empty(bat->path_present)) {
fprintf(stderr, RED "tint2: %s:%d: read failed for %s" RESET "\n", __FILE__, __LINE__, bat->path_present);
goto err0;
}
@@ -135,9 +150,8 @@ static gboolean init_linux_battery(struct psy_battery *bat)
bat->path_rate_now = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "power_now", NULL);
bat->unit = 'W';
if (!g_file_test(bat->path_level_now, G_FILE_TEST_EXISTS) ||
!g_file_test(bat->path_level_full, G_FILE_TEST_EXISTS) ||
!g_file_test(bat->path_rate_now, G_FILE_TEST_EXISTS)) {
if (!is_file_non_empty(bat->path_level_now) ||
!is_file_non_empty(bat->path_level_full)) {
g_free(bat->path_level_now);
g_free(bat->path_level_full);
g_free(bat->path_rate_now);
@@ -149,16 +163,18 @@ static gboolean init_linux_battery(struct psy_battery *bat)
g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "current_now", NULL);
bat->unit = 'A';
}
if (!g_file_test(bat->path_level_now, G_FILE_TEST_EXISTS) ||
!g_file_test(bat->path_level_full, G_FILE_TEST_EXISTS) ||
!g_file_test(bat->path_rate_now, G_FILE_TEST_EXISTS)) {
fprintf(stderr, RED "tint2: %s:%d: read failed" RESET "\n", __FILE__, __LINE__);
if (!is_file_non_empty(bat->path_level_now)) {
fprintf(stderr, RED "tint2: %s:%d: read failed for %s" RESET "\n", __FILE__, __LINE__, bat->path_level_now);
goto err1;
}
if (!is_file_non_empty(bat->path_level_full)) {
fprintf(stderr, RED "tint2: %s:%d: read failed for %s" RESET "\n", __FILE__, __LINE__, bat->path_level_full);
goto err1;
}
bat->path_status = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "status", NULL);
if (!g_file_test(bat->path_status, G_FILE_TEST_EXISTS)) {
fprintf(stderr, RED "tint2: %s:%d: read failed" RESET "\n", __FILE__, __LINE__);
if (!is_file_non_empty(bat->path_status)) {
fprintf(stderr, RED "tint2: %s:%d: read failed for %s" RESET "\n", __FILE__, __LINE__, bat->path_status);
goto err2;
}
@@ -181,8 +197,8 @@ static gboolean init_linux_mains(struct psy_mains *ac)
const gchar *entryname = ac->name;
ac->path_online = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "online", NULL);
if (!g_file_test(ac->path_online, G_FILE_TEST_EXISTS)) {
fprintf(stderr, RED "tint2: %s:%d: read failed" RESET "\n", __FILE__, __LINE__);
if (!is_file_non_empty(ac->path_online)) {
fprintf(stderr, RED "tint2: %s:%d: read failed for %s" RESET "\n", __FILE__, __LINE__, ac->path_online);
g_free(ac->path_online);
return FALSE;
}

View File

@@ -52,11 +52,9 @@ void destroy_button(void *obj)
Button *button = (Button *)obj;
if (button->frontend) {
// This is a frontend element
if (button->frontend->icon) {
imlib_context_set_image(button->frontend->icon);
imlib_free_image();
button->frontend->icon = NULL;
}
free_icon(button->frontend->icon);
free_icon(button->frontend->icon_hover);
free_icon(button->frontend->icon_pressed);
button->backend->instances = g_list_remove_all(button->backend->instances, button);
free_and_null(button->frontend);
remove_area(&button->area);
@@ -79,7 +77,7 @@ void destroy_button(void *obj)
if (button->backend->instances) {
fprintf(stderr, "tint2: Error: Attempt to destroy backend while there are still frontend instances!\n");
exit(-1);
exit(EXIT_FAILURE);
}
free(button->backend);
free(button);
@@ -488,7 +486,7 @@ void button_dump_geometry(void *obj, int indent)
Imlib_Image tmp = imlib_context_get_image();
imlib_context_set_image(button->frontend->icon);
fprintf(stderr,
"%*sIcon: x = %d, y = %d, w = %d, h = %d\n",
"tint2: %*sIcon: x = %d, y = %d, w = %d, h = %d\n",
indent,
"",
button->frontend->iconx,
@@ -499,7 +497,7 @@ void button_dump_geometry(void *obj, int indent)
imlib_context_set_image(tmp);
}
fprintf(stderr,
"%*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n",
"tint2: %*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n",
indent,
"",
button->frontend->textx,

View File

@@ -350,6 +350,12 @@ void add_entry(char *key, char *value)
id = (id < gradients->len && id >= 0) ? id : -1;
if (id >= 0)
bg->gradients[MOUSE_DOWN] = &g_array_index(gradients, GradientClass, id);
} else if (strcmp(key, "border_content_tint_weight") == 0) {
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
bg->border_content_tint_weight = MAX(0.0, MIN(1.0, atoi(value) / 100.));
} else if (strcmp(key, "background_content_tint_weight") == 0) {
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
bg->fill_content_tint_weight = MAX(0.0, MIN(1.0, atoi(value) / 100.));
}
/* Gradients */
@@ -1086,11 +1092,18 @@ void add_entry(char *key, char *value)
panel_config.g_task.config_background_mask |= (1 << status);
if (status == TASK_NORMAL)
panel_config.g_task.area.bg = panel_config.g_task.background[TASK_NORMAL];
if (panel_config.g_task.background[status]->border_content_tint_weight > 0 ||
panel_config.g_task.background[status]->fill_content_tint_weight > 0)
panel_config.g_task.has_content_tint = TRUE;
}
}
// "tooltip" is deprecated but here for backwards compatibility
else if (strcmp(key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0)
panel_config.g_task.tooltip_enabled = atoi(value);
else if (strcmp(key, "task_thumbnail") == 0)
panel_config.g_task.thumbnail_enabled = atoi(value);
else if (strcmp(key, "task_thumbnail_size") == 0)
panel_config.g_task.thumbnail_width = MAX(8, atoi(value));
/* Systray */
else if (strcmp(key, "systray_padding") == 0) {
@@ -1133,8 +1146,11 @@ void add_entry(char *key, char *value)
} else if (strcmp(key, "systray_monitor") == 0) {
systray_monitor = MAX(0, config_get_monitor(value));
} else if (strcmp(key, "systray_name_filter") == 0) {
if (systray_hide_name_filter)
if (systray_hide_name_filter) {
fprintf(stderr, "tint2: Error: duplicate option 'systray_name_filter'. Please use it only once. See "
"https://gitlab.com/o9000/tint2/issues/652\n");
free(systray_hide_name_filter);
}
systray_hide_name_filter = strdup(value);
}

View File

@@ -70,11 +70,7 @@ void destroy_execp(void *obj)
stop_timeout(execp->backend->timer);
execp->backend->timer = NULL;
if (execp->backend->icon) {
imlib_context_set_image(execp->backend->icon);
imlib_free_image();
execp->backend->icon = NULL;
}
free_icon(execp->backend->icon);
free_and_null(execp->backend->buf_stdout);
free_and_null(execp->backend->buf_stderr);
free_and_null(execp->backend->text);
@@ -109,7 +105,7 @@ void destroy_execp(void *obj)
if (execp->backend->instances) {
fprintf(stderr, "tint2: Error: Attempt to destroy backend while there are still frontend instances!\n");
exit(-1);
exit(EXIT_FAILURE);
}
free(execp->backend);
free(execp);
@@ -518,7 +514,7 @@ void execp_dump_geometry(void *obj, int indent)
Imlib_Image tmp = imlib_context_get_image();
imlib_context_set_image(execp->backend->icon);
fprintf(stderr,
"%*sIcon: x = %d, y = %d, w = %d, h = %d\n",
"tint2: %*sIcon: x = %d, y = %d, w = %d, h = %d\n",
indent,
"",
execp->frontend->iconx,
@@ -529,7 +525,7 @@ void execp_dump_geometry(void *obj, int indent)
imlib_context_set_image(tmp);
}
fprintf(stderr,
"%*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n",
"tint2: %*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n",
indent,
"",
execp->frontend->textx,

View File

@@ -6,12 +6,18 @@
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/XShm.h>
#include "config.h"
#include "drag_and_drop.h"
#include "fps_distribution.h"
#include "panel.h"
#include "server.h"
#include "signals.h"
#include "test.h"
#include "tooltip.h"
#include "tracing.h"
#include "uevent.h"
@@ -43,6 +49,9 @@ void handle_cli_arguments(int argc, char **argv)
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
fprintf(stdout, "tint2 version %s\n", VERSION_STRING);
exit(0);
} else if (strcmp(argv[i], "--test") == 0) {
run_all_tests();
exit(0);
} else if (strcmp(argv[i], "-c") == 0) {
if (i + 1 < argc) {
i++;
@@ -75,7 +84,7 @@ void handle_cli_arguments(int argc, char **argv)
}
if (error) {
print_usage();
exit(1);
exit(EXIT_FAILURE);
}
}
}
@@ -88,6 +97,7 @@ void handle_env_vars()
debug_fps = getenv("DEBUG_FPS") != NULL;
debug_frames = getenv("DEBUG_FRAMES") != NULL;
debug_dnd = getenv("DEBUG_DND") != NULL;
debug_thumbnails = getenv("DEBUG_THUMBNAILS") != NULL;
if (debug_fps) {
init_fps_distribution();
char *s = getenv("TRACING_FPS_THRESHOLD");
@@ -184,7 +194,7 @@ void init_X11_pre_config()
server.display = XOpenDisplay(NULL);
if (!server.display) {
fprintf(stderr, "tint2: could not open display!\n");
exit(1);
exit(EXIT_FAILURE);
}
server.x11_fd = ConnectionNumber(server.display);
XSetErrorHandler((XErrorHandler)server_catch_error);
@@ -193,6 +203,7 @@ void init_X11_pre_config()
server.screen = DefaultScreen(server.display);
server.root_win = RootWindow(server.display, server.screen);
server.desktop = get_current_desktop();
server.has_shm = XShmQueryExtension(server.display);
// Needed since the config file uses '.' as decimal separator
setlocale(LC_ALL, "");
@@ -251,6 +262,7 @@ void cleanup()
#ifdef ENABLE_BATTERY
cleanup_battery();
#endif
cleanup_separator();
cleanup_panel();
cleanup_config();

View File

@@ -104,7 +104,7 @@ void handle_event_property_notify(XEvent *e)
// Change name of desktops
else if (at == server.atom._NET_DESKTOP_NAMES) {
if (debug)
fprintf(stderr, "tint2: %s %d: win = root, atom = _NET_DESKTOP_NAMES\n", __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: %s %d: win = root, atom = _NET_DESKTOP_NAMES\n", __func__, __LINE__);
update_desktop_names();
}
// Change desktops
@@ -112,7 +112,7 @@ void handle_event_property_notify(XEvent *e)
at == server.atom._NET_DESKTOP_VIEWPORT || at == server.atom._NET_WORKAREA ||
at == server.atom._NET_CURRENT_DESKTOP) {
if (debug)
fprintf(stderr, "tint2: %s %d: win = root, atom = ?? desktops changed\n", __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: %s %d: win = root, atom = ?? desktops changed\n", __func__, __LINE__);
if (!taskbar_enabled)
return;
int old_num_desktops = server.num_desktops;
@@ -202,7 +202,7 @@ void handle_event_property_notify(XEvent *e)
// Window list
else if (at == server.atom._NET_CLIENT_LIST) {
if (debug)
fprintf(stderr, "tint2: %s %d: win = root, atom = _NET_CLIENT_LIST\n", __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: %s %d: win = root, atom = _NET_CLIENT_LIST\n", __func__, __LINE__);
taskbar_refresh_tasklist();
update_all_taskbars_visibility();
schedule_panel_redraw();
@@ -210,12 +210,12 @@ void handle_event_property_notify(XEvent *e)
// Change active
else if (at == server.atom._NET_ACTIVE_WINDOW) {
if (debug)
fprintf(stderr, "tint2: %s %d: win = root, atom = _NET_ACTIVE_WINDOW\n", __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: %s %d: win = root, atom = _NET_ACTIVE_WINDOW\n", __func__, __LINE__);
reset_active_task();
schedule_panel_redraw();
} else if (at == server.atom._XROOTPMAP_ID || at == server.atom._XROOTMAP_ID) {
if (debug)
fprintf(stderr, "tint2: %s %d: win = root, atom = _XROOTPMAP_ID\n", __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: %s %d: win = root, atom = _XROOTPMAP_ID\n", __func__, __LINE__);
// change Wallpaper
for (int i = 0; i < num_panels; i++) {
set_panel_background(&panels[i]);
@@ -234,7 +234,7 @@ void handle_event_property_notify(XEvent *e)
char *atom_name = XGetAtomName(server.display, at);
fprintf(stderr,
"%s %d: win = %ld, task = %s, atom = %s\n",
__FUNCTION__,
__func__,
__LINE__,
win,
task ? (task->title ? task->title : "??") : "null",
@@ -243,7 +243,7 @@ void handle_event_property_notify(XEvent *e)
}
if (!task) {
if (debug)
fprintf(stderr, "tint2: %s %d\n", __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: %s %d\n", __func__, __LINE__);
if (at == server.atom._NET_WM_STATE) {
// xfce4 sends _NET_WM_STATE after minimized to tray, so we need to check if window is mapped
// if it is mapped and not set as skip_taskbar, we must add it to our task list
@@ -262,7 +262,7 @@ void handle_event_property_notify(XEvent *e)
if (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) {
if (task_update_title(task)) {
if (g_tooltip.mapped && (g_tooltip.area == (Area *)task)) {
tooltip_copy_text((Area *)task);
tooltip_update_contents_for((Area *)task);
tooltip_update();
}
if (taskbar_sort_method == TASKBAR_SORT_TITLE)
@@ -277,7 +277,7 @@ void handle_event_property_notify(XEvent *e)
Atom *atom_state = server_get_property(win, server.atom._NET_WM_STATE, XA_ATOM, &count);
for (int j = 0; j < count; j++) {
char *atom_state_name = XGetAtomName(server.display, atom_state[j]);
fprintf(stderr, "tint2: %s %d: _NET_WM_STATE = %s\n", __FUNCTION__, __LINE__, atom_state_name);
fprintf(stderr, "tint2: %s %d: _NET_WM_STATE = %s\n", __func__, __LINE__, atom_state_name);
XFree(atom_state_name);
}
XFree(atom_state);

View File

@@ -58,6 +58,7 @@ char *panel_window_name = NULL;
gboolean debug_geometry;
gboolean debug_gradients;
gboolean startup_notifications;
gboolean debug_thumbnails;
gboolean panel_autohide;
int panel_autohide_show_timeout;
@@ -493,9 +494,11 @@ gboolean resize_panel(void *obj)
}
}
// Distribute the remaining size between tasks
// Distribute the remaining size between taskbars
if (num_tasks > 0) {
int task_size = total_size / num_tasks;
if (taskbar_alignment != ALIGN_LEFT)
task_size = MIN(task_size, panel_horizontal ? panel_config.g_task.maximum_width : panel_config.g_task.maximum_height);
for (int i = 0; i < panel->num_desktops; i++) {
Taskbar *taskbar = &panel->taskbar[i];
if (!taskbar->area.on_screen)
@@ -512,6 +515,43 @@ gboolean resize_panel(void *obj)
taskbar->area.height += task_size;
}
}
int slack = total_size - task_size * num_tasks;
if (taskbar_alignment == ALIGN_RIGHT) {
for (int i = 0; i < panel->num_desktops; i++) {
Taskbar *taskbar = &panel->taskbar[i];
if (!taskbar->area.on_screen)
continue;
if (panel_horizontal)
taskbar->area.width += slack;
else
taskbar->area.height += slack;
break;
}
} else if (taskbar_alignment == ALIGN_CENTER) {
slack /= 2;
for (int i = 0; i < panel->num_desktops; i++) {
Taskbar *taskbar = &panel->taskbar[i];
if (!taskbar->area.on_screen)
continue;
if (panel_horizontal)
taskbar->area.width += slack;
else
taskbar->area.height += slack;
taskbar->area.alignment = ALIGN_RIGHT;
break;
}
for (int i = panel->num_desktops - 1; i >= 0; i--) {
Taskbar *taskbar = &panel->taskbar[i];
if (!taskbar->area.on_screen)
continue;
if (panel_horizontal)
taskbar->area.width += slack;
else
taskbar->area.height += slack;
taskbar->area.alignment = ALIGN_LEFT;
break;
}
}
} else {
// No tasks => expand the first visible taskbar
for (int i = 0; i < panel->num_desktops; i++) {

View File

@@ -94,6 +94,7 @@ extern gboolean debug_geometry;
extern gboolean debug_fps;
extern double tracing_fps_threshold;
extern gboolean debug_frames;
extern gboolean debug_thumbnails;
typedef struct Panel {
Area area;
@@ -165,7 +166,7 @@ gboolean resize_panel(void *obj);
void render_panel(Panel *panel);
void shrink_panel(Panel *panel);
void _schedule_panel_redraw(const char *file, const char *function, const int line);
#define schedule_panel_redraw() _schedule_panel_redraw(__FILE__, __FUNCTION__, __LINE__)
#define schedule_panel_redraw() _schedule_panel_redraw(__FILE__, __func__, __LINE__)
void set_panel_items_order(Panel *p);
void place_panel_all_desktops(Panel *p);

View File

@@ -184,7 +184,7 @@ int systray_compute_desired_size(void *obj)
gboolean resize_systray(void *obj)
{
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __func__, __LINE__);
int size;
systray_compute_geometry(&size);
@@ -227,7 +227,7 @@ gboolean resize_systray(void *obj)
void draw_systray(void *obj, cairo_t *c)
{
if (systray_profile)
fprintf(stderr, BLUE "tint2: [%f] %s:%d" RESET "\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, BLUE "tint2: [%f] %s:%d" RESET "\n", profiling_get_time(), __func__, __LINE__);
if (systray_composited) {
if (render_background)
XFreePixmap(server.display, render_background);
@@ -257,7 +257,7 @@ void systray_dump_geometry(void *obj, int indent)
for (GSList *l = tray->list_icons; l; l = l->next) {
TrayWindow *traywin = (TrayWindow *)l->data;
fprintf(stderr,
"%*sIcon: x = %d, y = %d, w = %d, h = %d, name = %s\n",
"tint2: %*sIcon: x = %d, y = %d, w = %d, h = %d, name = %s\n",
indent,
"",
traywin->x,
@@ -271,7 +271,7 @@ void systray_dump_geometry(void *obj, int indent)
void on_change_systray(void *obj)
{
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __func__, __LINE__);
if (systray.icons_per_column == 0 || systray.icons_per_row == 0)
return;
@@ -301,7 +301,7 @@ void on_change_systray(void *obj)
if (systray_profile)
fprintf(stderr,
"%s:%d win = %lu (%s), parent = %lu, x = %d, y = %d\n",
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name,
@@ -358,7 +358,7 @@ void on_change_systray(void *obj)
void start_net()
{
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __func__, __LINE__);
if (net_sel_win) {
// protocol already started
if (!systray_enabled)
@@ -464,7 +464,7 @@ void start_net()
fprintf(stderr, GREEN "tint2: systray started" RESET "\n");
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __func__, __LINE__);
XClientMessageEvent ev;
ev.type = ClientMessage;
ev.window = server.root_win;
@@ -481,7 +481,7 @@ void start_net()
void handle_systray_event(XClientMessageEvent *e)
{
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __func__, __LINE__);
Window win;
unsigned long opcode = e->data.l[1];
@@ -509,7 +509,7 @@ void handle_systray_event(XClientMessageEvent *e)
void stop_net()
{
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __func__, __LINE__);
if (systray.list_icons) {
// remove_icon change systray.list_icons
while (systray.list_icons)
@@ -529,7 +529,7 @@ gboolean error;
int window_error_handler(Display *d, XErrorEvent *e)
{
if (systray_profile)
fprintf(stderr, RED "tint2: [%f] %s:%d" RESET "\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, RED "tint2: [%f] %s:%d" RESET "\n", profiling_get_time(), __func__, __LINE__);
error = TRUE;
if (e->error_code != BadWindow) {
fprintf(stderr, RED "tint2: systray: error code %d" RESET "\n", e->error_code);
@@ -623,7 +623,7 @@ gboolean add_icon(Window win)
char *name = get_window_name(win);
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, win, name);
fprintf(stderr, "tint2: [%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __func__, __LINE__, win, name);
Panel *panel = systray.area.panel;
// Get the process ID of the application that created the window
@@ -679,7 +679,7 @@ gboolean add_icon(Window win)
win,
name,
pid,
attr.visual,
(void*)attr.visual,
attr.colormap,
attr.depth,
attr.width,
@@ -748,14 +748,14 @@ gboolean add_icon(Window win)
}
if (systray_profile)
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, "tint2: [%f] %s:%d\n", profiling_get_time(), __func__, __LINE__);
// Resize and redraw the systray
if (systray_profile)
fprintf(stderr,
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__);
systray.area.resize_needed = TRUE;
panel->area.resize_needed = TRUE;
@@ -770,7 +770,7 @@ gboolean reparent_icon(TrayWindow *traywin)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -832,7 +832,7 @@ gboolean reparent_icon(TrayWindow *traywin)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -846,7 +846,7 @@ gboolean embed_icon(TrayWindow *traywin)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -903,7 +903,7 @@ gboolean embed_icon(TrayWindow *traywin)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -917,7 +917,7 @@ void remove_icon(TrayWindow *traywin)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -963,7 +963,7 @@ void remove_icon(TrayWindow *traywin)
fprintf(stderr,
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__);
systray.area.resize_needed = TRUE;
panel->area.resize_needed = TRUE;
@@ -1086,7 +1086,7 @@ void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
fprintf(stderr,
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__);
schedule_panel_redraw();
refresh_systray = TRUE;
@@ -1165,7 +1165,7 @@ void systray_resize_request_event(TrayWindow *traywin, XEvent *e)
fprintf(stderr,
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__);
schedule_panel_redraw();
refresh_systray = TRUE;
@@ -1177,7 +1177,7 @@ void systray_destroy_event(TrayWindow *traywin)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -1212,7 +1212,7 @@ void systray_render_icon_composited(void *t)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -1230,7 +1230,7 @@ void systray_render_icon_composited(void *t)
fprintf(stderr,
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -1250,7 +1250,7 @@ void systray_render_icon_composited(void *t)
fprintf(stderr,
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -1381,7 +1381,7 @@ void systray_render_icon_composited(void *t)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -1419,7 +1419,7 @@ void systray_render_icon(void *t)
// fprintf(stderr,
// YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
// profiling_get_time(),
// __FUNCTION__,
// __func__,
// __LINE__,
// traywin->win,
// traywin->name);
@@ -1433,7 +1433,7 @@ void systray_render_icon(void *t)
fprintf(stderr,
"[%f] %s:%d win = %lu (%s)\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -1466,7 +1466,7 @@ void systray_render_icon(void *t)
fprintf(stderr,
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
profiling_get_time(),
__FUNCTION__,
__func__,
__LINE__,
traywin->win,
traywin->name);
@@ -1500,7 +1500,7 @@ void systray_render_icon(void *t)
void refresh_systray_icons()
{
if (systray_profile)
fprintf(stderr, BLUE "tint2: [%f] %s:%d" RESET "\n", profiling_get_time(), __FUNCTION__, __LINE__);
fprintf(stderr, BLUE "tint2: [%f] %s:%d" RESET "\n", profiling_get_time(), __func__, __LINE__);
TrayWindow *traywin;
GSList *l;
for (l = systray.list_icons; l; l = l->next) {

View File

@@ -40,6 +40,8 @@ GSList *urgent_list;
void task_dump_geometry(void *obj, int indent);
int task_compute_desired_size(void *obj);
void task_refresh_thumbnail(Task *task);
void task_get_content_color(void *obj, Color *color);
char *task_get_tooltip(void *obj)
{
@@ -47,6 +49,17 @@ char *task_get_tooltip(void *obj)
return strdup(t->title);
}
cairo_surface_t *task_get_thumbnail(void *obj)
{
if (!panel_config.g_task.thumbnail_enabled)
return NULL;
Task *t = (Task *)obj;
if (!t->thumbnail)
task_refresh_thumbnail(t);
taskbar_start_thumbnail_timer(THUMB_MODE_TOOLTIP_WINDOW);
return t->thumbnail;
}
Task *add_task(Window win)
{
if (!win)
@@ -73,6 +86,7 @@ Task *add_task(Window win)
task_template.area.has_mouse_press_effect = panel_config.mouse_effects;
task_template.area._dump_geometry = task_dump_geometry;
task_template.area._is_under_mouse = full_width_area_is_under_mouse;
task_template.area._get_content_color = task_get_content_color;
task_template.win = win;
task_template.desktop = get_window_desktop(win);
task_template.area.panel = &panels[monitor];
@@ -93,10 +107,6 @@ Task *add_task(Window win)
(int)win,
task_template.title ? task_template.title : "null");
// fprintf(stderr, "tint2: %s %d: win = %ld, task = %s\n", __FUNCTION__, __LINE__, win, task_template.title ?
// task_template.title : "??");
// fprintf(stderr, "tint2: new task %s win %u: desktop %d, monitor %d\n", new_task.title, win, new_task.desktop, monitor);
GPtrArray *task_buttons = g_ptr_array_new();
for (int j = 0; j < panels[monitor].num_desktops; j++) {
if (task_template.desktop != ALL_DESKTOPS && task_template.desktop != j)
@@ -110,6 +120,7 @@ Task *add_task(Window win)
task_instance->area._dump_geometry = task_dump_geometry;
task_instance->area._is_under_mouse = full_width_area_is_under_mouse;
task_instance->area._compute_desired_size = task_compute_desired_size;
task_instance->area._get_content_color = task_get_content_color;
task_instance->win = task_template.win;
task_instance->desktop = task_template.desktop;
task_instance->win_x = task_template.win_x;
@@ -118,12 +129,16 @@ Task *add_task(Window win)
task_instance->win_h = task_template.win_h;
task_instance->current_state = TASK_UNDEFINED; // to update the current state later in set_task_state...
if (task_instance->desktop == ALL_DESKTOPS && server.desktop != j) {
// fprintf(stderr, "tint2: %s %d: win = %ld hiding task: another desktop\n", __FUNCTION__, __LINE__, win);
task_instance->area.on_screen = always_show_all_desktop_tasks;
}
task_instance->title = task_template.title;
if (panels[monitor].g_task.tooltip_enabled)
if (panels[monitor].g_task.tooltip_enabled) {
task_instance->area._get_tooltip_text = task_get_tooltip;
task_instance->area._get_tooltip_image = task_get_thumbnail;
}
task_instance->icon_color = task_template.icon_color;
task_instance->icon_color_hover = task_template.icon_color_hover;
task_instance->icon_color_press = task_template.icon_color_press;
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
task_instance->icon[k] = task_template.icon[k];
task_instance->icon_hover[k] = task_template.icon_hover[k];
@@ -186,9 +201,6 @@ void remove_task(Task *task)
if (!task)
return;
// fprintf(stderr, "tint2: %s %d: win = %ld, task = %s\n", __FUNCTION__, __LINE__, task->win, task->title ? task->title :
// "??");
if (taskbar_mode == MULTI_DESKTOP) {
Panel *panel = task->area.panel;
panel->area.resize_needed = 1;
@@ -198,9 +210,10 @@ void remove_task(Task *task)
// free title and icon just for the first task
// even with task_on_all_desktop and with task_on_all_panel
// fprintf(stderr, "tint2: remove_task %s %d\n", task->title, task->desktop);
if (task->title)
free(task->title);
if (task->thumbnail)
cairo_surface_destroy(task->thumbnail);
task_remove_icon(task);
GPtrArray *task_buttons = g_hash_table_lookup(win_to_task, &win);
@@ -212,6 +225,8 @@ void remove_task(Task *task)
task_drag = 0;
if (g_slist_find(urgent_list, task2))
del_urgent(task2);
if (g_tooltip.area == &task2->area)
tooltip_hide(NULL);
remove_area((Area *)task2);
free(task2);
}
@@ -266,36 +281,23 @@ gboolean task_update_title(Task *task)
return TRUE;
}
void task_update_icon(Task *task)
Imlib_Image task_get_icon(Window win, int icon_size)
{
Panel *panel = task->area.panel;
if (!panel->g_task.has_icon)
return;
task_remove_icon(task);
Imlib_Image img = NULL;
if (!img) {
int len;
gulong *data = server_get_property(task->win, server.atom._NET_WM_ICON, XA_CARDINAL, &len);
gulong *data = server_get_property(win, server.atom._NET_WM_ICON, XA_CARDINAL, &len);
if (data) {
if (len > 0) {
// get ARGB icon
int w, h;
gulong *tmp_data = get_best_icon(data, get_icon_count(data, len), len, &w, &h, panel->g_task.icon_size1);
gulong *tmp_data = get_best_icon(data, get_icon_count(data, len), len, &w, &h, icon_size);
if (tmp_data) {
DATA32 icon_data[w * h];
for (int j = 0; j < w * h; ++j)
icon_data[j] = tmp_data[j];
img = imlib_create_image_using_copied_data(w, h, icon_data);
if (0 && img)
fprintf(stderr,
"%s: Got %dx%d icon via _NET_WM_ICON for %s\n",
__FUNCTION__,
w,
h,
task->title ? task->title : "task");
}
}
XFree(data);
@@ -303,7 +305,7 @@ void task_update_icon(Task *task)
}
if (!img) {
XWMHints *hints = XGetWMHints(server.display, task->win);
XWMHints *hints = XGetWMHints(server.display, win);
if (hints) {
if (hints->flags & IconPixmapHint && hints->icon_pixmap != 0) {
// get width, height and depth for the pixmap
@@ -315,13 +317,6 @@ void task_update_icon(Task *task)
XGetGeometry(server.display, hints->icon_pixmap, &root, &icon_x, &icon_y, &w, &h, &border_width, &bpp);
imlib_context_set_drawable(hints->icon_pixmap);
img = imlib_create_image_from_drawable(hints->icon_mask, 0, 0, w, h, 0);
if (0 && img)
fprintf(stderr,
"%s: Got %dx%d pixmap icon via WM_HINTS for %s\n",
__FUNCTION__,
w,
h,
task->title ? task->title : "task");
}
XFree(hints);
}
@@ -332,6 +327,44 @@ void task_update_icon(Task *task)
img = imlib_clone_image();
}
return img;
}
void task_set_icon_color(Task *task, Imlib_Image icon)
{
get_image_mean_color(icon, &task->icon_color);
if (panel_config.mouse_effects) {
task->icon_color_hover = task->icon_color;
adjust_color(&task->icon_color_hover,
panel_config.mouse_over_alpha,
panel_config.mouse_over_saturation,
panel_config.mouse_over_brightness);
task->icon_color_press = task->icon_color;
adjust_color(&task->icon_color_press,
panel_config.mouse_pressed_alpha,
panel_config.mouse_pressed_saturation,
panel_config.mouse_pressed_brightness);
}
}
void task_update_icon(Task *task)
{
Panel *panel = task->area.panel;
if (!panel->g_task.has_icon) {
if (panel_config.g_task.has_content_tint) {
Imlib_Image img = task_get_icon(task->win, panel->g_task.icon_size1);
task_set_icon_color(task, img);
imlib_context_set_image(img);
imlib_free_image();
}
return;
}
task_remove_icon(task);
Imlib_Image img = task_get_icon(task->win, panel->g_task.icon_size1);
task_set_icon_color(task, img);
// transform icons
imlib_context_set_image(img);
imlib_image_set_has_alpha(1);
@@ -345,20 +378,10 @@ void task_update_icon(Task *task)
task->icon_width = imlib_image_get_width();
task->icon_height = imlib_image_get_height();
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
imlib_context_set_image(orig_image);
task->icon[k] = imlib_clone_image();
imlib_context_set_image(task->icon[k]);
DATA32 *data32;
if (panel->g_task.alpha[k] != 100 || panel->g_task.saturation[k] != 0 || panel->g_task.brightness[k] != 0) {
data32 = imlib_image_get_data();
adjust_asb(data32,
task->icon_width,
task->icon_height,
panel->g_task.alpha[k] / 100.0,
panel->g_task.saturation[k] / 100.0,
panel->g_task.brightness[k] / 100.0);
imlib_image_put_back_data(data32);
}
task->icon[k] = adjust_icon(orig_image,
panel->g_task.alpha[k],
panel->g_task.saturation[k],
panel->g_task.brightness[k] != 0);
if (panel_config.mouse_effects) {
task->icon_hover[k] = adjust_icon(task->icon[k],
panel_config.mouse_over_alpha,
@@ -376,9 +399,12 @@ void task_update_icon(Task *task)
GPtrArray *task_buttons = get_task_buttons(task->win);
if (task_buttons) {
for (int i = 0; i < task_buttons->len; ++i) {
Task *task2 = g_ptr_array_index(task_buttons, i);
Task *task2 = (Task *)g_ptr_array_index(task_buttons, i);
task2->icon_width = task->icon_width;
task2->icon_height = task->icon_height;
task2->icon_color = task->icon_color;
task2->icon_color_hover = task->icon_color_hover;
task2->icon_color_press = task->icon_color_press;
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
task2->icon[k] = task->icon[k];
task2->icon_hover[k] = task->icon_hover[k];
@@ -466,7 +492,7 @@ void task_dump_geometry(void *obj, int indent)
Panel *panel = (Panel *)task->area.panel;
fprintf(stderr,
"%*sText: x = %d, y = %d, w = %d, h = %d, align = %s, text = %s\n",
"tint2: %*sText: x = %d, y = %d, w = %d, h = %d, align = %s, text = %s\n",
indent,
"",
(int)panel->g_task.text_posx,
@@ -476,7 +502,7 @@ void task_dump_geometry(void *obj, int indent)
panel->g_task.centered ? "center" : "left",
task->title);
fprintf(stderr,
"%*sIcon: x = %d, y = %d, w = h = %d\n",
"tint2: %*sIcon: x = %d, y = %d, w = h = %d\n",
indent,
"",
task->_icon_x,
@@ -484,6 +510,24 @@ void task_dump_geometry(void *obj, int indent)
panel->g_task.icon_size1);
}
void task_get_content_color(void *obj, Color *color)
{
Task *task = (Task *)obj;
Color *content_color = NULL;
if (panel_config.mouse_effects) {
if (task->area.mouse_state == MOUSE_OVER)
content_color = &task->icon_color_hover;
else if (task->area.mouse_state == MOUSE_DOWN)
content_color = &task->icon_color_press;
else
content_color = &task->icon_color;
} else {
content_color = &task->icon_color;
}
if (content_color)
*color = *content_color;
}
int task_compute_desired_size(void *obj)
{
Task *task = (Task *)obj;
@@ -591,7 +635,6 @@ void reset_active_task()
}
Window w1 = get_active_window();
// fprintf(stderr, "tint2: Change active task %ld\n", w1);
if (w1) {
if (!get_task_buttons(w1)) {
@@ -603,11 +646,49 @@ void reset_active_task()
}
}
void task_refresh_thumbnail(Task *task)
{
if (!panel_config.g_task.thumbnail_enabled)
return;
if (task->current_state == TASK_ICONIFIED)
return;
double now = get_time();
if (now - task->thumbnail_last_update < 0.1)
return;
if (debug_thumbnails)
fprintf(stderr, "tint2: thumbnail for window: %s" RESET "\n", task->title ? task->title : "");
cairo_surface_t *thumbnail = get_window_thumbnail(task->win, panel_config.g_task.thumbnail_width);
if (!thumbnail)
return;
if (task->thumbnail)
cairo_surface_destroy(task->thumbnail);
task->thumbnail = thumbnail;
task->thumbnail_last_update = get_time();
if (debug_thumbnails)
fprintf(stderr,
YELLOW "tint2: %s took %f ms (window: %s)" RESET "\n",
__func__,
1000 * (task->thumbnail_last_update - now),
task->title ? task->title : "");
if (g_tooltip.mapped && (g_tooltip.area == &task->area)) {
tooltip_update_contents_for(&task->area);
tooltip_update();
}
}
void set_task_state(Task *task, TaskState state)
{
if (!task || state == TASK_UNDEFINED || state >= TASK_STATE_COUNT)
return;
if (!task->thumbnail)
task_refresh_thumbnail(task);
if (state == TASK_ACTIVE) {
// For active windows, we get the thumbnail twice with a small delay in between.
// This is because they sometimes redraw their windows slowly.
taskbar_start_thumbnail_timer(THUMB_MODE_ACTIVE_WINDOW);
}
if (state == TASK_ACTIVE && task->current_state != state) {
clock_gettime(CLOCK_MONOTONIC, &task->last_activation_time);
if (taskbar_sort_method == TASKBAR_SORT_LRU || taskbar_sort_method == TASKBAR_SORT_MRU) {
@@ -783,7 +864,6 @@ void task_handle_mouse_event(Task *task, MouseAction action)
void task_update_desktop(Task *task)
{
// fprintf(stderr, "tint2: %s %d:\n", __FUNCTION__, __LINE__);
Window win = task->win;
remove_task(task);
task = add_task(win);

View File

@@ -42,10 +42,13 @@ typedef struct GlobalTask {
// starting position for text ~ task_padding + task_border + icon_size
double text_posx, text_height;
gboolean has_font;
gboolean has_content_tint;
PangoFontDescription *font_desc;
Color font[TASK_STATE_COUNT];
int config_font_mask;
gboolean tooltip_enabled;
gboolean thumbnail_enabled;
int thumbnail_width;
} GlobalTask;
// Stores information about a task.
@@ -61,6 +64,9 @@ typedef struct Task {
Imlib_Image icon_press[TASK_STATE_COUNT];
unsigned int icon_width;
unsigned int icon_height;
Color icon_color;
Color icon_color_hover;
Color icon_color_press;
char *title;
int urgent_tick;
// These may not be up-to-date
@@ -74,6 +80,8 @@ typedef struct Task {
double _text_posy;
int _icon_x;
int _icon_y;
cairo_surface_t *thumbnail;
double thumbnail_last_update;
} Task;
extern timeout *urgent_timeout;
@@ -91,6 +99,7 @@ gboolean task_update_title(Task *task);
void reset_active_task();
void set_task_state(Task *task, TaskState state);
void task_handle_mouse_event(Task *task, MouseAction action);
void task_refresh_thumbnail(Task *task);
// Given a pointer to the task that is currently under the mouse (current_task),
// returns a pointer to the Task for the active window on the same taskbar.

View File

@@ -32,6 +32,7 @@
#include "window.h"
#include "panel.h"
#include "strnatcmp.h"
#include "tooltip.h"
GHashTable *win_to_task;
@@ -46,6 +47,12 @@ gboolean hide_taskbar_if_empty;
gboolean always_show_all_desktop_tasks;
TaskbarSortMethod taskbar_sort_method;
Alignment taskbar_alignment;
static timeout *thumbnail_update_timer_all;
static timeout *thumbnail_update_timer_active;
static timeout *thumbnail_update_timer_tooltip;
static GList *taskbar_task_orderings = NULL;
static GList *taskbar_thumbnail_jobs_done = NULL;
void taskbar_init_fonts();
int taskbar_compute_desired_size(void *obj);
@@ -53,6 +60,8 @@ int taskbar_compute_desired_size(void *obj);
// Removes the task with &win = key. The other args are ignored.
void taskbar_remove_task(Window *win);
void taskbar_update_thumbnails(void *arg);
guint win_hash(gconstpointer key)
{
return *((const Window *)key);
@@ -80,13 +89,56 @@ void default_taskbar()
hide_task_diff_monitor = FALSE;
hide_taskbar_if_empty = FALSE;
always_show_all_desktop_tasks = FALSE;
thumbnail_update_timer_all = NULL;
thumbnail_update_timer_active = NULL;
thumbnail_update_timer_tooltip = NULL;
taskbar_thumbnail_jobs_done = NULL;
taskbar_sort_method = TASKBAR_NOSORT;
taskbar_alignment = ALIGN_LEFT;
default_taskbarname();
}
void taskbar_clear_orderings()
{
if (!taskbar_task_orderings)
return;
for (GList *order = taskbar_task_orderings; order; order = order->next) {
g_list_free_full((GList *)order->data, free);
}
g_list_free(taskbar_task_orderings);
taskbar_task_orderings = NULL;
}
void taskbar_save_orderings()
{
taskbar_clear_orderings();
taskbar_task_orderings = NULL;
for (int i = 0; i < num_panels; i++) {
Panel *panel = &panels[i];
for (int j = 0; j < panel->num_desktops; j++) {
Taskbar *taskbar = &panel->taskbar[j];
GList *task_order = NULL;
for (GList *c = (taskbar->area.children && taskbarname_enabled) ? taskbar->area.children->next
: taskbar->area.children;
c;
c = c->next) {
Task *t = (Task *)c->data;
Window *window = calloc(1, sizeof(Window));
*window = t->win;
task_order = g_list_append(task_order, window);
}
taskbar_task_orderings = g_list_append(taskbar_task_orderings, task_order);
}
}
}
void cleanup_taskbar()
{
stop_timeout(thumbnail_update_timer_all);
stop_timeout(thumbnail_update_timer_active);
stop_timeout(thumbnail_update_timer_tooltip);
g_list_free(taskbar_thumbnail_jobs_done);
taskbar_save_orderings();
if (win_to_task) {
while (g_hash_table_size(win_to_task)) {
GHashTableIter iter;
@@ -136,6 +188,9 @@ void init_taskbar()
panel_config.g_task.has_text = panel_config.g_task.has_icon = 1;
}
if (panel_config.g_task.thumbnail_width < 8)
panel_config.g_task.thumbnail_width = 210;
if (!win_to_task)
win_to_task = g_hash_table_new_full(win_hash, win_compare, free, free_ptr_array);
@@ -267,8 +322,9 @@ void init_taskbar_panel(void *p)
if (!panel->g_task.background[j])
panel->g_task.background[j] = &g_array_index(backgrounds, Background, 0);
if (panel->g_task.background[j]->border.radius > panel->g_task.area.height / 2) {
fprintf(stderr, "tint2: task%sbackground_id has a too large rounded value. Please fix your tint2rc\n",
j == 0 ? "_" : j == 1 ? "_active_" : j == 2 ? "_iconified_" : "_urgent_");
fprintf(stderr,
"tint2: task%sbackground_id has a too large rounded value. Please fix your tint2rc\n",
j == 0 ? "_" : j == 1 ? "_active_" : j == 2 ? "_iconified_" : "_urgent_");
g_array_append_val(backgrounds, *panel->g_task.background[j]);
panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len - 1);
panel->g_task.background[j]->border.radius = panel->g_task.area.height / 2;
@@ -319,6 +375,21 @@ void init_taskbar_panel(void *p)
}
}
init_taskbarname_panel(panel);
taskbar_start_thumbnail_timer(THUMB_MODE_ALL);
}
void taskbar_start_thumbnail_timer(ThumbnailUpdateMode mode)
{
if (!panel_config.g_task.thumbnail_enabled)
return;
if (debug_thumbnails)
fprintf(stderr, BLUE "tint2: taskbar_start_thumbnail_timer %s" RESET "\n", mode == THUMB_MODE_ACTIVE_WINDOW ? "active" : mode == THUMB_MODE_TOOLTIP_WINDOW ? "tooltip" : "all");
change_timeout(mode == THUMB_MODE_ALL ? &thumbnail_update_timer_all :
mode == THUMB_MODE_ACTIVE_WINDOW ? &thumbnail_update_timer_active : &thumbnail_update_timer_tooltip,
mode == THUMB_MODE_TOOLTIP_WINDOW ? 1000 : 500,
mode == THUMB_MODE_ALL ? 10 * 1000 : 0,
taskbar_update_thumbnails,
(void *)(long)mode);
}
void taskbar_init_fonts()
@@ -381,14 +452,67 @@ GPtrArray *get_task_buttons(Window win)
return NULL;
}
static Window *sort_windows = NULL;
int compare_windows(const void *a, const void *b)
{
if (!sort_windows)
return 0;
int ia = *(int *)a;
int ib = *(int *)b;
Window wina = sort_windows[ia];
Window winb = sort_windows[ib];
for (GList *order = taskbar_task_orderings; order; order = order->next) {
int posa = -1;
int posb = -1;
int pos = 0;
for (GList *item = (GList *)order->data; item; item = item->next, pos++) {
Window win = *(Window *)item->data;
if (win == wina)
posa = pos;
if (win == winb)
posb = pos;
}
if (posa >= 0 && posb >= 0) {
return posa - posb;
}
}
return ia - ib;
}
void sort_win_list(Window *windows, int count)
{
int *indices = (int *)calloc(count, sizeof(int));
for (int i = 0; i < count; i++)
indices[i] = i;
sort_windows = windows;
qsort(indices, count, sizeof(int), compare_windows);
Window *result = (Window *)calloc(count, sizeof(Window));
for (int i = 0; i < count; i++)
result[i] = windows[indices[i]];
memcpy(windows, result, count * sizeof(Window));
free(result);
free(indices);
sort_windows = NULL;
}
void taskbar_refresh_tasklist()
{
if (!taskbar_enabled)
return;
// fprintf(stderr, "tint2: %s %d:\n", __FUNCTION__, __LINE__);
int num_results;
Window *win = server_get_property(server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
Window *sorted = (Window *)calloc(num_results, sizeof(Window));
memcpy(sorted, win, num_results * sizeof(Window));
if (taskbar_task_orderings) {
sort_win_list(sorted, num_results);
taskbar_clear_orderings();
}
if (!win)
return;
@@ -396,7 +520,7 @@ void taskbar_refresh_tasklist()
for (GList *it = win_list; it; it = it->next) {
int i;
for (i = 0; i < num_results; i++)
if (*((Window *)it->data) == win[i])
if (*((Window *)it->data) == sorted[i])
break;
if (i == num_results)
taskbar_remove_task(it->data);
@@ -405,10 +529,11 @@ void taskbar_refresh_tasklist()
// Add any new
for (int i = 0; i < num_results; i++)
if (!get_task(win[i]))
add_task(win[i]);
if (!get_task(sorted[i]))
add_task(sorted[i]);
XFree(win);
free(sorted);
}
int taskbar_compute_desired_size(void *obj)
@@ -432,7 +557,6 @@ gboolean resize_taskbar(void *obj)
Taskbar *taskbar = (Taskbar *)obj;
Panel *panel = (Panel *)taskbar->area.panel;
// fprintf(stderr, "tint2: resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy);
if (panel_horizontal) {
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_width);
@@ -690,3 +814,48 @@ void update_minimized_icon_positions(void *p)
}
}
}
void taskbar_update_thumbnails(void *arg)
{
if (!panel_config.g_task.thumbnail_enabled)
return;
ThumbnailUpdateMode mode = (ThumbnailUpdateMode)(long)arg;
if (debug_thumbnails)
fprintf(stderr, BLUE "tint2: taskbar_update_thumbnails %s" RESET "\n", mode == THUMB_MODE_ACTIVE_WINDOW ? "active" : mode == THUMB_MODE_TOOLTIP_WINDOW ? "tooltip" : "all");
double start_time = get_time();
for (int i = 0; i < num_panels; i++) {
Panel *panel = &panels[i];
for (int j = 0; j < panel->num_desktops; j++) {
Taskbar *taskbar = &panel->taskbar[j];
for (GList *c = (taskbar->area.children && taskbarname_enabled) ? taskbar->area.children->next
: taskbar->area.children;
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) ||
(mode == THUMB_MODE_TOOLTIP_WINDOW && g_tooltip.mapped && g_tooltip.area == &t->area)) {
task_refresh_thumbnail(t);
if (mode == THUMB_MODE_ALL)
taskbar_thumbnail_jobs_done = g_list_append(taskbar_thumbnail_jobs_done, t);
if (t->thumbnail && mode == THUMB_MODE_TOOLTIP_WINDOW) {
taskbar_start_thumbnail_timer(THUMB_MODE_TOOLTIP_WINDOW);
}
}
if (mode == THUMB_MODE_ALL) {
double now = get_time();
if (now - start_time > 0.030) {
change_timeout(&thumbnail_update_timer_all, 50, 10 * 1000, taskbar_update_thumbnails, arg);
return;
}
}
}
}
}
if (mode == THUMB_MODE_ALL) {
if (taskbar_thumbnail_jobs_done) {
g_list_free(taskbar_thumbnail_jobs_done);
taskbar_thumbnail_jobs_done = NULL;
change_timeout(&thumbnail_update_timer_all, 10 * 1000, 10 * 1000, taskbar_update_thumbnails, arg);
}
}
}

View File

@@ -25,6 +25,12 @@ typedef enum TaskbarSortMethod {
TASKBAR_SORT_MRU,
} TaskbarSortMethod;
typedef enum ThumbnailUpdateMode {
THUMB_MODE_ACTIVE_WINDOW = 0,
THUMB_MODE_TOOLTIP_WINDOW,
THUMB_MODE_ALL
} ThumbnailUpdateMode;
typedef struct {
Area area;
gchar *name;
@@ -72,6 +78,7 @@ void init_taskbar_panel(void *p);
gboolean resize_taskbar(void *obj);
void taskbar_default_font_changed();
void taskbar_start_thumbnail_timer(ThumbnailUpdateMode mode);
// Reloads the entire list of tasks from the window manager and recreates the task buttons.
void taskbar_refresh_tasklist();

View File

@@ -24,7 +24,7 @@ set(SOURCES ../util/common.c
../util/cache.c
../util/timer.c
../config.c
../server.c
../util/server.c
../launcher/apps-common.c
../launcher/icon-theme-common.c
md4.c

View File

@@ -6,7 +6,7 @@ GtkWidget *current_background, *background_fill_color, *background_border_color,
*background_fill_color_over, *background_border_color_over, *background_gradient_over, *background_fill_color_press,
*background_border_color_press, *background_gradient_press, *background_border_width, *background_corner_radius,
*background_border_sides_top, *background_border_sides_bottom, *background_border_sides_left,
*background_border_sides_right;
*background_border_sides_right, *background_border_content_tint_weight, *background_fill_content_tint_weight;
GtkWidget *create_background_combo(const char *label)
{
@@ -115,7 +115,9 @@ void create_background(GtkWidget *parent)
GTK_TYPE_BOOL,
GTK_TYPE_BOOL,
GTK_TYPE_BOOL,
GTK_TYPE_BOOL);
GTK_TYPE_BOOL,
GTK_TYPE_DOUBLE,
GTK_TYPE_DOUBLE);
GtkWidget *table, *label, *button;
int row, col;
@@ -175,6 +177,19 @@ void create_background(GtkWidget *parent)
col++;
gtk_tooltips_set_tip(tooltips, background_fill_color, _("The fill color of the current background"), NULL);
row++, col = 2;
label = gtk_label_new(_("Fill tint"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
background_fill_content_tint_weight = gtk_spin_button_new_with_range(0, 100, 1);
gtk_widget_show(background_fill_content_tint_weight);
gtk_table_attach(GTK_TABLE(table), background_fill_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips, background_fill_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL);
row++, col = 2;
label = gtk_label_new(_("Border color"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
@@ -189,6 +204,19 @@ void create_background(GtkWidget *parent)
col++;
gtk_tooltips_set_tip(tooltips, background_border_color, _("The border color of the current background"), NULL);
row++, col = 2;
label = gtk_label_new(_("Border tint"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
background_border_content_tint_weight = gtk_spin_button_new_with_range(0, 100, 1);
gtk_widget_show(background_border_content_tint_weight);
gtk_table_attach(GTK_TABLE(table), background_border_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips, background_border_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL);
row++, col = 2;
label = gtk_label_new(_("Gradient"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
@@ -366,6 +394,8 @@ void create_background(GtkWidget *parent)
g_signal_connect(G_OBJECT(background_border_sides_bottom), "toggled", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_border_sides_left), "toggled", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_border_sides_right), "toggled", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_border_content_tint_weight), "value-changed", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_fill_content_tint_weight), "value-changed", G_CALLBACK(background_update), NULL);
change_paragraph(parent);
}
@@ -750,6 +780,9 @@ void background_update(GtkWidget *widget, gpointer data)
r = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_corner_radius));
b = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_border_width));
double fill_weight = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_fill_content_tint_weight));
double border_weight = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_border_content_tint_weight));
gboolean sideTop = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_border_sides_top));
gboolean sideBottom = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_border_sides_bottom));
gboolean sideLeft = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_border_sides_left));
@@ -836,6 +869,10 @@ void background_update(GtkWidget *widget, gpointer data)
sideLeft,
bgColBorderSidesRight,
sideRight,
bgColFillWeight,
fill_weight,
bgColBorderWeight,
border_weight,
-1);
background_update_image(index);
}
@@ -862,6 +899,8 @@ void current_background_changed(GtkWidget *widget, gpointer data)
gtk_widget_set_sensitive(background_border_sides_left, index > 0);
gtk_widget_set_sensitive(background_border_sides_right, index > 0);
gtk_widget_set_sensitive(background_corner_radius, index > 0);
gtk_widget_set_sensitive(background_border_content_tint_weight, index > 0);
gtk_widget_set_sensitive(background_fill_content_tint_weight, index > 0);
background_updates_disabled = TRUE;
@@ -875,6 +914,9 @@ void current_background_changed(GtkWidget *widget, gpointer data)
int r;
int b;
double fill_weight;
double border_weight;
gboolean sideTop;
gboolean sideBottom;
gboolean sideLeft;
@@ -938,6 +980,10 @@ void current_background_changed(GtkWidget *widget, gpointer data)
&sideLeft,
bgColBorderSidesRight,
&sideRight,
bgColFillWeight,
&fill_weight,
bgColBorderWeight,
&border_weight,
-1);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(background_border_sides_top), sideTop);
@@ -968,6 +1014,9 @@ void current_background_changed(GtkWidget *widget, gpointer data)
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_border_width), b);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_corner_radius), r);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_fill_content_tint_weight), fill_weight);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_border_content_tint_weight), border_weight);
g_boxed_free(GDK_TYPE_COLOR, fillColor);
g_boxed_free(GDK_TYPE_COLOR, borderColor);
g_boxed_free(GDK_TYPE_COLOR, fillColorOver);

File diff suppressed because it is too large Load Diff

2418
src/tint2conf/po/es.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,3 +15,22 @@ do
cat ${lang}.pox > ${lang}.po
rm ${lang}.pox
done
set +e
set +x
echo "Status:"
for f in *.po
do
lang=$(basename $f .po)
fuzzy=$(cat ${lang}.po | grep -A2 "#, fuzzy")
missing=$(cat ${lang}.po | grep -B1 'msgstr ""')
if [ -z "$fuzzy" ] && [ -z "$missing" ]
then
echo $lang ": Up to date"
else
count=$(( $(echo -e "$fuzzy" "\n" "$missing" | grep "^--$" | wc -l) + 1))
echo "${lang}: Translation incomplete: ${count} strings to be updated. See ${lang}.todo"
echo "$fuzzy" > ${lang}.todo
echo "$missing" >> ${lang}.todo
fi
done

View File

@@ -97,7 +97,7 @@ GtkWidget *systray_background, *systray_monitor, *systray_name_filter;
// tooltip
GtkWidget *tooltip_padding_x, *tooltip_padding_y, *tooltip_font, *tooltip_font_set, *tooltip_font_color;
GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after;
GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after, *tooltip_task_thumbnail, *tooltip_task_thumbnail_size;
GtkWidget *clock_format_tooltip, *clock_tmz_tooltip;
GtkWidget *tooltip_background;
@@ -3288,6 +3288,36 @@ void create_task(GtkWidget *parent)
"over task buttons."),
NULL);
row++, col = 2;
label = gtk_label_new(_("Thumbnails"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
tooltip_task_thumbnail = gtk_check_button_new();
gtk_widget_show(tooltip_task_thumbnail);
gtk_table_attach(GTK_TABLE(table), tooltip_task_thumbnail, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips,
tooltip_task_thumbnail,
_("If enabled, a tooltip showing the window thumbnail is displayed when the mouse cursor moves "
"over task buttons."),
NULL);
row++, col = 2;
label = gtk_label_new(_("Thumbnail size"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
tooltip_task_thumbnail_size = gtk_spin_button_new_with_range(8, 9000, 1);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(tooltip_task_thumbnail_size), 210);
gtk_widget_show(tooltip_task_thumbnail_size);
gtk_table_attach(GTK_TABLE(table), tooltip_task_thumbnail_size, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
row++, col = 2;
label = gtk_label_new(_("Maximum width"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
@@ -5136,8 +5166,8 @@ void create_systemtray(GtkWidget *parent)
_("Specifies the order used to arrange the system tray icons. \n"
"'Ascending' means that icons are sorted in ascending order of their window names. \n"
"'Descending' means that icons are sorted in descending order of their window names. \n"
"'Left to right' means that icons are always added to the left. \n"
"'Right to left' means that icons are always added to the right."),
"'Left to right' means that icons are always added to the right. \n"
"'Right to left' means that icons are always added to the left."),
NULL);
row++;

View File

@@ -105,7 +105,7 @@ extern GtkWidget *systray_background, *systray_monitor, *systray_name_filter;
// tooltip
extern GtkWidget *tooltip_padding_x, *tooltip_padding_y, *tooltip_font, *tooltip_font_set, *tooltip_font_color;
extern GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after;
extern GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after, *tooltip_task_thumbnail, *tooltip_task_thumbnail_size;
extern GtkWidget *clock_format_tooltip, *clock_tmz_tooltip;
extern GtkWidget *tooltip_background;
@@ -203,6 +203,8 @@ enum {
bgColBorderSidesBottom,
bgColBorderSidesLeft,
bgColBorderSidesRight,
bgColFillWeight,
bgColBorderWeight,
bgNumCols
};
@@ -211,7 +213,7 @@ extern GtkWidget *current_background, *background_fill_color, *background_border
*background_fill_color_over, *background_border_color_over, *background_gradient_over, *background_fill_color_press,
*background_border_color_press, *background_gradient_press, *background_border_width, *background_border_sides_top,
*background_border_sides_bottom, *background_border_sides_left, *background_border_sides_right,
*background_corner_radius;
*background_corner_radius, *background_border_content_tint_weight, *background_fill_content_tint_weight;
// gradients
enum { grColPixbuf = 0, grColId, grColText, grNumCols };

View File

@@ -161,6 +161,8 @@ void config_write_backgrounds(FILE *fp)
int r;
int b;
double fill_weight;
double border_weight;
gboolean sideTop;
gboolean sideBottom;
gboolean sideLeft;
@@ -228,6 +230,10 @@ void config_write_backgrounds(FILE *fp)
&sideLeft,
bgColBorderSidesRight,
&sideRight,
bgColFillWeight,
&fill_weight,
bgColBorderWeight,
&border_weight,
-1);
fprintf(fp, "# Background %d: %s\n", index, text ? text : "");
fprintf(fp, "rounded = %d\n", r);
@@ -245,6 +251,9 @@ void config_write_backgrounds(FILE *fp)
strcat(sides, "R");
fprintf(fp, "border_sides = %s\n", sides);
fprintf(fp, "border_content_tint_weight = %d\n", (int)(border_weight));
fprintf(fp, "background_content_tint_weight = %d\n", (int)(fill_weight));
config_write_color(fp, "background_color", *fillColor, fillOpacity);
config_write_color(fp, "border_color", *borderColor, borderOpacity);
if (gradient_id >= 0)
@@ -517,6 +526,11 @@ void config_write_task(FILE *fp)
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(task_font_set)))
fprintf(fp, "task_font = %s\n", gtk_font_button_get_font_name(GTK_FONT_BUTTON(task_font)));
fprintf(fp, "task_tooltip = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tooltip_task_show)) ? 1 : 0);
fprintf(fp, "task_thumbnail = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tooltip_task_thumbnail)) ? 1 : 0);
fprintf(fp,
"task_thumbnail_size = %d\n",
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(tooltip_task_thumbnail_size)));
// same for: "" _normal _active _urgent _iconified
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(task_default_color_set))) {
@@ -1225,6 +1239,12 @@ void add_entry(char *key, char *value)
int id = gradient_index_safe(atoi(value));
gtk_combo_box_set_active(GTK_COMBO_BOX(background_gradient_press), id);
background_force_update();
} else if (strcmp(key, "border_content_tint_weight") == 0) {
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_border_content_tint_weight), atoi(value));
background_force_update();
} else if (strcmp(key, "background_content_tint_weight") == 0) {
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_fill_content_tint_weight), atoi(value));
background_force_update();
}
/* Panel */
@@ -1732,6 +1752,10 @@ void add_entry(char *key, char *value)
else if (strcmp(key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltip_task_show), atoi(value));
}
else if (strcmp(key, "task_thumbnail") == 0)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltip_task_thumbnail), atoi(value));
else if (strcmp(key, "task_thumbnail_size") == 0)
gtk_spin_button_set_value(GTK_SPIN_BUTTON(tooltip_task_thumbnail_size), MAX(8, atoi(value)));
/* Systray */
else if (strcmp(key, "systray") == 0) {

View File

@@ -54,8 +54,9 @@ void default_tooltip()
void cleanup_tooltip()
{
stop_tooltip_timeout();
stop_timeout(g_tooltip.update_timeout);
tooltip_hide(NULL);
tooltip_copy_text(NULL);
tooltip_update_contents_for(NULL);
if (g_tooltip.window)
XDestroyWindow(server.display, g_tooltip.window);
g_tooltip.window = 0;
@@ -118,7 +119,7 @@ void tooltip_trigger_show(Area *area, Panel *p, XEvent *e)
just_shown = TRUE;
g_tooltip.panel = p;
if (g_tooltip.mapped && g_tooltip.area != area) {
tooltip_copy_text(area);
tooltip_update_contents_for(area);
tooltip_update();
stop_tooltip_timeout();
} else if (!g_tooltip.mapped) {
@@ -133,7 +134,7 @@ void tooltip_show(void *arg)
XTranslateCoordinates(server.display, server.root_win, g_tooltip.panel->main_win, x, y, &mx, &my, &w);
Area *area = find_area_under_mouse(g_tooltip.panel, mx, my);
if (!g_tooltip.mapped && area->_get_tooltip_text) {
tooltip_copy_text(area);
tooltip_update_contents_for(area);
g_tooltip.mapped = True;
XMapWindow(server.display, g_tooltip.window);
tooltip_update();
@@ -144,7 +145,7 @@ void tooltip_show(void *arg)
void tooltip_update_geometry()
{
Panel *panel = g_tooltip.panel;
int screen_width = server.monitors[panel->monitor].x + server.monitors[panel->monitor].width;
int screen_width = server.monitors[panel->monitor].width;
cairo_surface_t *cs = cairo_xlib_surface_create(server.display, g_tooltip.window, server.visual, width, height);
cairo_t *c = cairo_create(cs);
@@ -152,16 +153,25 @@ void tooltip_update_geometry()
pango_layout_set_font_description(layout, g_tooltip.font_desc);
PangoRectangle r1, r2;
pango_layout_set_text(layout, "1234567890", -1);
pango_layout_set_text(layout, "1234567890abcdef", -1);
pango_layout_get_pixel_extents(layout, &r1, &r2);
int max_width = MIN(r2.width * 7, screen_width * 2 / 3);
int max_width = MIN(r2.width * 5, screen_width * 2 / 3);
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
max_width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx +
cairo_image_surface_get_width(g_tooltip.image);
}
pango_layout_set_width(layout, max_width * PANGO_SCALE);
pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
pango_layout_set_text(layout, g_tooltip.tooltip_text ? g_tooltip.tooltip_text : "1234567890abcdef", -1);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
pango_layout_get_pixel_extents(layout, &r1, &r2);
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx + r2.width;
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy + r2.height;
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx +
cairo_image_surface_get_width(g_tooltip.image);
height += g_tooltip.paddingy + cairo_image_surface_get_height(g_tooltip.image);
}
if (panel_horizontal && panel_position & BOTTOM)
y = panel->posy - height;
@@ -278,8 +288,16 @@ void tooltip_update()
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy);
pango_cairo_show_layout(c, layout);
g_object_unref(layout);
if (g_tooltip.image) {
cairo_translate(c,
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy - cairo_image_surface_get_height(g_tooltip.image));
cairo_set_source_surface(c, g_tooltip.image, 0, 0);
cairo_paint(c);
}
cairo_destroy(c);
cairo_surface_destroy(cs);
}
@@ -287,7 +305,7 @@ void tooltip_update()
void tooltip_trigger_hide()
{
if (g_tooltip.mapped) {
tooltip_copy_text(0);
tooltip_update_contents_for(NULL);
start_hide_timeout();
} else {
// tooltip not visible yet, but maybe a timeout is still pending
@@ -302,6 +320,7 @@ void tooltip_hide(void *arg)
XUnmapWindow(server.display, g_tooltip.window);
XFlush(server.display);
}
g_tooltip.area = NULL;
}
void start_show_timeout()
@@ -319,12 +338,25 @@ void stop_tooltip_timeout()
stop_timeout(g_tooltip.timeout);
}
void tooltip_copy_text(Area *area)
void tooltip_update_contents_timeout(void *arg)
{
free(g_tooltip.tooltip_text);
tooltip_update_contents_for(g_tooltip.area);
}
void tooltip_update_contents_for(Area *area)
{
free_and_null(g_tooltip.tooltip_text);
if (g_tooltip.image)
cairo_surface_destroy(g_tooltip.image);
g_tooltip.image = NULL;
if (area && area->_get_tooltip_text)
g_tooltip.tooltip_text = area->_get_tooltip_text(area);
else
g_tooltip.tooltip_text = NULL;
if (area && area->_get_tooltip_image) {
g_tooltip.image = area->_get_tooltip_image(area);
if (g_tooltip.image)
cairo_surface_reference(g_tooltip.image);
else
change_timeout(&g_tooltip.update_timeout, 300, 0, tooltip_update_contents_timeout, NULL);
}
g_tooltip.area = area;
}

View File

@@ -37,6 +37,8 @@ typedef struct {
Color font_color;
Background *bg;
timeout *timeout;
timeout *update_timeout;
cairo_surface_t *image;
} Tooltip;
extern Tooltip g_tooltip;
@@ -53,7 +55,7 @@ void tooltip_show(void * /*arg*/);
void tooltip_update();
void tooltip_trigger_hide();
void tooltip_hide(void * /*arg*/);
void tooltip_copy_text(Area *area);
void tooltip_update_contents_for(Area *area);
void tooltip_default_font_changed();
#endif // TOOLTIP_H

View File

@@ -490,28 +490,59 @@ void draw(Area *a)
cairo_surface_destroy(cs);
}
double tint_color_channel(double a, double b, double tint_weight)
{
double gamma = 2.2;
if (tint_weight == 0.0)
return a;
double result = sqrt((1.-tint_weight)*pow(a, gamma) + tint_weight * pow(b, gamma));
return result;
}
void set_cairo_source_tinted(cairo_t *c, Color *color1, Color *color2, double tint_weight)
{
cairo_set_source_rgba(c,
tint_color_channel(color1->rgb[0], color2->rgb[0], tint_weight),
tint_color_channel(color1->rgb[1], color2->rgb[1], tint_weight),
tint_color_channel(color1->rgb[2], color2->rgb[2], tint_weight),
color1->alpha);
}
void set_cairo_source_bg_color(Area *a, cairo_t *c)
{
Color content_color;
if (a->_get_content_color)
a->_get_content_color(a, &content_color);
else
bzero(&content_color, sizeof(content_color));
if (a->mouse_state == MOUSE_OVER)
set_cairo_source_tinted(c, &a->bg->fill_color_hover, &content_color, a->bg->fill_content_tint_weight);
else if (a->mouse_state == MOUSE_DOWN)
set_cairo_source_tinted(c, &a->bg->fill_color_pressed, &content_color, a->bg->fill_content_tint_weight);
else
set_cairo_source_tinted(c, &a->bg->fill_color, &content_color, a->bg->fill_content_tint_weight);
}
void set_cairo_source_border_color(Area *a, cairo_t *c)
{
Color content_color;
if (a->_get_content_color)
a->_get_content_color(a, &content_color);
else
bzero(&content_color, sizeof(content_color));
if (a->mouse_state == MOUSE_OVER)
set_cairo_source_tinted(c, &a->bg->border_color_hover, &content_color, a->bg->border_content_tint_weight);
else if (a->mouse_state == MOUSE_DOWN)
set_cairo_source_tinted(c, &a->bg->border_color_pressed, &content_color, a->bg->border_content_tint_weight);
else
set_cairo_source_tinted(c, &a->bg->border.color, &content_color, a->bg->border_content_tint_weight);
}
void draw_background(Area *a, cairo_t *c)
{
if ((a->bg->fill_color.alpha > 0.0) ||
(panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect))) {
if (a->mouse_state == MOUSE_OVER)
cairo_set_source_rgba(c,
a->bg->fill_color_hover.rgb[0],
a->bg->fill_color_hover.rgb[1],
a->bg->fill_color_hover.rgb[2],
a->bg->fill_color_hover.alpha);
else if (a->mouse_state == MOUSE_DOWN)
cairo_set_source_rgba(c,
a->bg->fill_color_pressed.rgb[0],
a->bg->fill_color_pressed.rgb[1],
a->bg->fill_color_pressed.rgb[2],
a->bg->fill_color_pressed.alpha);
else
cairo_set_source_rgba(c,
a->bg->fill_color.rgb[0],
a->bg->fill_color.rgb[1],
a->bg->fill_color.rgb[2],
a->bg->fill_color.alpha);
// Not sure about this
draw_rect(c,
left_border_width(a),
@@ -519,7 +550,7 @@ void draw_background(Area *a, cairo_t *c)
a->width - left_right_border_width(a),
a->height - top_bottom_border_width(a),
a->bg->border.radius - a->bg->border.width / 1.571);
set_cairo_source_bg_color(a, c);
cairo_fill(c);
}
for (GList *l = a->gradient_instances_by_state[a->mouse_state]; l; l = l->next) {
@@ -540,24 +571,7 @@ void draw_background(Area *a, cairo_t *c)
cairo_set_line_width(c, a->bg->border.width);
// draw border inside (x, y, width, height)
if (a->mouse_state == MOUSE_OVER)
cairo_set_source_rgba(c,
a->bg->border_color_hover.rgb[0],
a->bg->border_color_hover.rgb[1],
a->bg->border_color_hover.rgb[2],
a->bg->border_color_hover.alpha);
else if (a->mouse_state == MOUSE_DOWN)
cairo_set_source_rgba(c,
a->bg->border_color_pressed.rgb[0],
a->bg->border_color_pressed.rgb[1],
a->bg->border_color_pressed.rgb[2],
a->bg->border_color_pressed.alpha);
else
cairo_set_source_rgba(c,
a->bg->border.color.rgb[0],
a->bg->border.color.rgb[1],
a->bg->border.color.rgb[2],
a->bg->border.color.alpha);
set_cairo_source_border_color(a, c);
draw_rect_on_sides(c,
left_border_width(a) / 2.,
top_border_width(a) / 2.,
@@ -850,7 +864,7 @@ void area_dump_geometry(Area *area, int indent)
return;
}
fprintf(stderr,
"%*sBox: x = %d, y = %d, w = %d, h = %d, desired size = %d\n",
"tint2: %*sBox: x = %d, y = %d, w = %d, h = %d, desired size = %d\n",
indent,
"",
area->posx,
@@ -859,7 +873,7 @@ void area_dump_geometry(Area *area, int indent)
area->height,
compute_desired_size(area));
fprintf(stderr,
"%*sBorder: left = %d, right = %d, top = %d, bottom = %d\n",
"tint2: %*sBorder: left = %d, right = %d, top = %d, bottom = %d\n",
indent,
"",
left_border_width(area),
@@ -867,7 +881,7 @@ void area_dump_geometry(Area *area, int indent)
top_border_width(area),
bottom_border_width(area));
fprintf(stderr,
"%*sPadding: left = right = %d, top = bottom = %d, spacing = %d\n",
"tint2: %*sPadding: left = right = %d, top = bottom = %d, spacing = %d\n",
indent,
"",
area->paddingxlr,
@@ -883,6 +897,33 @@ void area_dump_geometry(Area *area, int indent)
}
}
void area_compute_available_size(Area *area,
int *available_w,
int *available_h)
{
Panel *panel = (Panel *)area->panel;
if (panel_horizontal) {
*available_w = panel->area.width;
*available_h = area->height - 2 * area->paddingy - left_right_border_width(area);
} else {
*available_w = area->width - 2 * area->paddingxlr - left_right_border_width(area);
*available_h = panel->area.height;
}
}
void area_compute_inner_size(Area *area,
int *inner_w,
int *inner_h)
{
if (panel_horizontal) {
*inner_w = area->width - 2 * area->paddingxlr - left_right_border_width(area);
*inner_h = area->height - 2 * area->paddingy - top_bottom_border_width(area);
} else {
*inner_w = area->width - 2 * area->paddingxlr - left_right_border_width(area);
*inner_h = area->height - 2 * area->paddingy - top_bottom_border_width(area);
}
}
void area_compute_text_geometry(Area *area,
const char *line1,
const char *line2,
@@ -895,15 +936,8 @@ void area_compute_text_geometry(Area *area,
int *line2_height,
int *line2_width)
{
Panel *panel = (Panel *)area->panel;
int available_w, available_h;
if (panel_horizontal) {
available_w = panel->area.width;
available_h = area->height - 2 * area->paddingy - left_right_border_width(area);
} else {
available_w = area->width - 2 * area->paddingxlr - left_right_border_width(area);
available_h = panel->area.height;
}
area_compute_available_size(area, &available_w, &available_h);
if (line1 && line1[0])
get_text_size2(line1_font_desc,
@@ -959,7 +993,7 @@ int text_area_compute_desired_size(Area *area,
int new_size = MAX(line1_width, line2_width) + 2 * area->paddingxlr + left_right_border_width(area);
return new_size;
} else {
int new_size = line1_height + line2_height + 2 * area->paddingxlr + top_bottom_border_width(area);
int new_size = line1_height + line2_height + 2 * area->paddingy + top_bottom_border_width(area);
return new_size;
}
}
@@ -1035,18 +1069,22 @@ void draw_text_area(Area *area,
int line2_posy,
Color *color)
{
int inner_w, inner_h;
area_compute_inner_size(area, &inner_w, &inner_h);
PangoLayout *layout = pango_cairo_create_layout(c);
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
pango_layout_set_width(layout, area->width * PANGO_SCALE);
pango_layout_set_width(layout, inner_w * PANGO_SCALE);
pango_layout_set_height(layout, inner_h * PANGO_SCALE);
cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha);
if (line1 && line1[0]) {
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, 0, 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);
}
if (line2 && line2[0]) {
@@ -1054,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, 0, 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);
}
g_object_unref(layout);

View File

@@ -154,6 +154,8 @@ typedef struct Background {
Color border_color_pressed;
// Pointer to a GradientClass or NULL, no ownership
GradientClass *gradients[MOUSE_STATE_COUNT];
double fill_content_tint_weight;
double border_content_tint_weight;
} Background;
typedef enum Layout {
@@ -233,6 +235,7 @@ typedef struct Area {
// Returns a copy of the tooltip to be displayed for this widget.
// The caller takes ownership of the pointer.
char *(*_get_tooltip_text)(void *obj);
cairo_surface_t *(*_get_tooltip_image)(void *obj);
// Returns true if the Area handles a mouse event at the given x, y coordinates relative to the window.
// Leave this to NULL to use a default implementation.
@@ -240,6 +243,8 @@ typedef struct Area {
// Prints the geometry of the object on stderr, with left indentation of indent spaces.
void (*_dump_geometry)(void *obj, int indent);
void (*_get_content_color)(void *obj, Color *color);
} Area;
// Initializes the Background member to default values.

17
src/util/bool.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef BOOL_H
#define BOOL_H
#ifndef bool
#define bool int
#define false 0
#define true 1
#endif
#define SUCCESS true
#define FAILURE false
#ifndef Status
typedef int Status;
#endif
#endif

10
src/util/colors.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef COLORS_H
#define COLORS_H
#define GREEN "\033[1;32m"
#define YELLOW "\033[1;33m"
#define RED "\033[1;31m"
#define BLUE "\033[1;34m"
#define RESET "\033[0m"
#endif

View File

@@ -31,7 +31,7 @@
#include <glib.h>
#include <glib/gstdio.h>
#include "common.h"
#include "../server.h"
#include "server.h"
#include <sys/wait.h>
#include <sys/types.h>
#include <pwd.h>
@@ -59,6 +59,7 @@
#include "../panel.h"
#include "timer.h"
#include "signals.h"
void write_string(int fd, const char *s)
{
@@ -398,18 +399,21 @@ pid_t tint_exec(const char *command,
if (dir)
chdir(dir);
close_all_fds();
reset_signals();
if (terminal) {
#if !defined(__OpenBSD__)
fprintf(stderr, "tint2: executing in x-terminal-emulator: %s\n", command);
wordexp_t words;
words.we_offs = 2;
if (wordexp(command, &words, WRDE_DOOFFS | WRDE_SHOWERR) == 0) {
words.we_wordv[0] = (char*)"x-terminal-emulator";
words.we_wordv[1] = (char*)"-e";
words.we_wordv[0] = (char *)"x-terminal-emulator";
words.we_wordv[1] = (char *)"-e";
execvp("x-terminal-emulator", words.we_wordv);
}
#endif
fprintf(stderr, "tint2: could not execute command in x-terminal-emulator: %s, executting in shell\n", command);
fprintf(stderr,
"tint2: could not execute command in x-terminal-emulator: %s, executting in shell\n",
command);
}
execlp("sh", "sh", "-c", command, NULL);
fprintf(stderr, "tint2: Failed to execute %s\n", command);
@@ -806,7 +810,7 @@ Imlib_Image load_image(const char *path, int cached)
GdkPixbuf *pixbuf = rsvg_handle_get_pixbuf(svg);
gdk_pixbuf_save(pixbuf, tmp_filename, "png", NULL, NULL);
}
exit(0);
_exit(0);
} else {
// Parent
close(fd);
@@ -933,10 +937,9 @@ void get_text_size2(const PangoFontDescription *font,
available_width = MAX(0, available_width);
available_height = MAX(0, available_height);
Pixmap pmap = XCreatePixmap(server.display, server.root_win, available_height, available_width, server.depth);
cairo_surface_t *cs =
cairo_xlib_surface_create(server.display, pmap, server.visual, available_height, available_width);
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, available_height, available_width);
cairo_t *c = cairo_create(cs);
PangoLayout *layout = pango_cairo_create_layout(c);
@@ -960,7 +963,6 @@ void get_text_size2(const PangoFontDescription *font,
g_object_unref(layout);
cairo_destroy(c);
cairo_surface_destroy(cs);
XFreePixmap(server.display, pmap);
}
#if !GLIB_CHECK_VERSION(2, 34, 0)
@@ -1055,3 +1057,57 @@ GString *tint2_g_string_replace(GString *s, const char *from, const char *to)
g_string_free(result, TRUE);
return s;
}
void get_image_mean_color(const Imlib_Image image, Color *mean_color)
{
bzero(mean_color, sizeof(*mean_color));
if (!image)
return;
imlib_context_set_image(image);
imlib_image_set_has_alpha(1);
size_t size = (size_t)imlib_image_get_width() * (size_t)imlib_image_get_height();
DATA32 *data = imlib_image_get_data_for_reading_only();
DATA32 sum_r, sum_g, sum_b, count;
sum_r = sum_g = sum_b = count = 0;
for (size_t i = 0; i < size; i++) {
DATA32 argb, a, r, g, b;
argb = data[i];
a = (argb >> 24) & 0xff;
r = (argb >> 16) & 0xff;
g = (argb >> 8) & 0xff;
b = (argb) & 0xff;
if (a) {
sum_r += r;
sum_g += g;
sum_b += b;
count++;
}
}
if (!count)
count = 1;
mean_color->alpha = 1.0;
mean_color->rgb[0] = sum_r / 255.0 / count;
mean_color->rgb[1] = sum_g / 255.0 / count;
mean_color->rgb[2] = sum_b / 255.0 / count;
}
void adjust_color(Color *color, int alpha, int saturation, int brightness)
{
if (alpha == 100 && saturation == 0 && brightness == 0)
return;
DATA32 argb = (((DATA32)(color->alpha * 255) & 0xff) << 24) |
(((DATA32)(color->rgb[0] * 255) & 0xff) << 16) |
(((DATA32)(color->rgb[1] * 255) & 0xff) << 8) |
(((DATA32)(color->rgb[2] * 255) & 0xff) << 0);
adjust_asb(&argb, 1, 1, alpha / 100.0, saturation / 100.0, brightness / 100.0);
DATA32 a = (argb >> 24) & 0xff;
DATA32 r = (argb >> 16) & 0xff;
DATA32 g = (argb >> 8) & 0xff;
DATA32 b = (argb) & 0xff;
color->alpha = a / 255.;
color->rgb[0] = r / 255.;
color->rgb[1] = g / 255.;
color->rgb[2] = b / 255.;
}

View File

@@ -12,12 +12,7 @@
#include <Imlib2.h>
#include <pango/pangocairo.h>
#include "area.h"
#define GREEN "\033[1;32m"
#define YELLOW "\033[1;33m"
#define RED "\033[1;31m"
#define BLUE "\033[1;34m"
#define RESET "\033[0m"
#include "colors.h"
#define MAX3(a, b, c) MAX(MAX(a, b), c)
#define MIN3(a, b, c) MIN(MIN(a, b), c)
@@ -109,6 +104,7 @@ Imlib_Image load_image(const char *path, int cached);
// * 1 = white
void adjust_asb(DATA32 *data, int w, int h, float alpha_adjust, float satur_adjust, float bright_adjust);
Imlib_Image adjust_icon(Imlib_Image original, int alpha, int saturation, int brightness);
void adjust_color(Color *color, int alpha, int saturation, int brightness);
void create_heuristic_mask(DATA32 *data, int w, int h);
@@ -150,6 +146,8 @@ gint cmp_ptr(gconstpointer a, gconstpointer b);
GString *tint2_g_string_replace(GString *s, const char *from, const char *to);
void get_image_mean_color(const Imlib_Image image, Color *mean_color);
#define free_and_null(p) \
{ \
free(p); \

83
src/util/print.c Normal file
View File

@@ -0,0 +1,83 @@
#include <stdio.h>
#include "print.h"
int print_uchar(unsigned char v)
{
return printf("%u", v);
}
int print_char(char v)
{
return printf("%c", v);
}
int print_short(short v)
{
return printf("%d", v);
}
int print_ushort(unsigned short v)
{
return printf("%u", v);
}
int print_int(int v)
{
return printf("%d", v);
}
int print_uint(unsigned v)
{
return printf("%u", v);
}
int print_long(long v)
{
return printf("%ld", v);
}
int print_ulong(unsigned long v)
{
return printf("%lu", v);
}
int print_long_long(long long v)
{
return printf("%lld", v);
}
int print_ulong_long(unsigned long long v)
{
return printf("%llu", v);
}
int print_float(float v)
{
return printf("%f", (double)v);
}
int print_double(double v)
{
return printf("%f", v);
}
int print_long_double(long double v)
{
return printf("%Lf", v);
}
int print_string(char *s)
{
return printf("%s", s);
}
int print_pointer(void *v)
{
return printf("%p", v);
}
int print_unknown()
{
return printf("(variable of unknown type)");
}

61
src/util/print.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef PRINT_H
#define PRINT_H
#ifdef HAS_GENERIC
int print_uchar(unsigned char v);
int print_char(char v);
int print_short(short v);
int print_ushort(unsigned short v);
int print_int(int v);
int print_uint(unsigned v);
int print_long(long v);
int print_ulong(unsigned long v);
int print_long_long(long long v);
int print_ulong_long(unsigned long long v);
int print_float(float v);
int print_double(double v);
int print_long_double(long double v);
int print_string(char *s);
int print_pointer(void *v);
int print_unknown();
#define print(x) \
_Generic((x), \
unsigned char: print_uchar, \
char: print_char, \
short int: print_short, \
unsigned short int: print_ushort, \
int: print_int, \
unsigned int: print_uint, \
long int: print_long, \
unsigned long int: print_ulong, \
long long int: print_long_long, \
unsigned long long int: print_ulong_long, \
float: print_float, \
double: print_double, \
long double: print_long_double, \
char *: print_string, \
void *: print_pointer, \
default : print_unknown)(x)
#else
#define print(...) printf("Omitted, the compiler does not support C11 generics.\n")
#endif
#endif

View File

@@ -147,6 +147,7 @@ typedef struct Server {
Global_atom atom;
int xdamage_event_type;
int xdamage_event_error_type;
gboolean has_shm;
#ifdef HAVE_SN
SnDisplay *sn_display;
GTree *pids;

View File

@@ -24,11 +24,23 @@ void signal_handler(int sig)
signal_pending = sig;
}
void reset_signals()
{
for (int sig = 1; sig < 32; sig++) {
signal(sig, SIG_DFL);
}
sigset_t signal_set;
sigemptyset(&signal_set);
sigprocmask(SIG_SETMASK, &signal_set, NULL);
}
void init_signals()
{
// Set signal handlers
signal_pending = 0;
reset_signals();
struct sigaction sa_chld = {.sa_handler = SIG_IGN};
sigaction(SIGCHLD, &sa_chld, 0);

View File

@@ -5,6 +5,7 @@ void init_signals();
void init_signals_postconfig();
void emit_self_restart(const char *reason);
int get_signal_pending();
void reset_signals();
void handle_sigchld_events();

159
src/util/test.c Normal file
View File

@@ -0,0 +1,159 @@
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <glib.h>
#include "colors.h"
#include "signals.h"
#include "test.h"
typedef struct TestListItem {
Test *test;
const char *name;
} TestListItem;
static GList *all_tests = NULL;
void register_test_(Test *test, const char *name)
{
TestListItem *item = (TestListItem *)calloc(sizeof(TestListItem), 1);
item->test = test;
item->name = name;
all_tests = g_list_append(all_tests, item);
}
static char *test_log_name_from_test_name(const char *test_name)
{
char *output_name = g_strdup_printf("test_%s.log", test_name);
char *result = strdup(output_name);
g_free(output_name);
return result;
}
static void redirect_test_output(const char *test_name)
{
char *output_name = test_log_name_from_test_name(test_name);
int fd = open(output_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd == -1)
goto err;
if (dup2(fd, STDOUT_FILENO) == -1)
goto err;
if (dup2(fd, STDERR_FILENO) == -1)
goto err;
close(fd);
free(output_name);
return;
err:
fprintf(stderr, "tint2: Could not redirect test output to file name: %s\n", output_name);
if (fd != -1)
close(fd);
free(output_name);
}
__attribute__((noreturn))
static void run_test_child(TestListItem *item)
{
reset_signals();
redirect_test_output(item->name);
bool result = true;
item->test(&result);
exit(result ? EXIT_SUCCESS : EXIT_FAILURE);
}
static FILE *open_test_log(const char *test_name)
{
char *output_name = test_log_name_from_test_name(test_name);
FILE *log = fopen(output_name, "a");
free(output_name);
return log;
}
static Status run_test_parent(TestListItem *item, pid_t child)
{
FILE *log = open_test_log(item->name);
if (child == -1) {
fprintf(log, "\n" "Test failed, fork failed\n");
fclose(log);
return FAILURE;
}
int child_status;
pid_t ret_pid = waitpid(child, &child_status, 0);
if (ret_pid != child) {
fprintf(log, "\n" "Test failed, waitpid failed\n");
fclose(log);
return FAILURE;
}
if (WIFEXITED(child_status)) {
int exit_status = WEXITSTATUS(child_status);
if (exit_status == EXIT_SUCCESS) {
fprintf(log, "\n" "Test succeeded.\n");
fclose(log);
return SUCCESS;
} else {
fprintf(log, "\n" "Test failed, exit status: %d.\n", exit_status);
fclose(log);
return FAILURE;
}
} else if (WIFSIGNALED(child_status)) {
int signal = WTERMSIG(child_status);
fprintf(log, "\n" "Test failed, child killed by signal: %d.\n", signal);
fclose(log);
return FAILURE;
} else {
fprintf(log, "\n" "Test failed, waitpid failed.\n");
fclose(log);
return FAILURE;
}
}
static Status run_test(TestListItem *item)
{
pid_t pid = fork();
if (pid == 0)
run_test_child(item);
return run_test_parent(item, pid);
}
void run_all_tests()
{
fprintf(stdout, BLUE "tint2: Running %d tests..." RESET "\n", g_list_length(all_tests));
size_t count = 0, succeeded = 0, failed = 0;
for (GList *l = all_tests; l; l = l->next) {
TestListItem *item = (TestListItem *)l->data;
Status status = run_test(item);
count++;
fprintf(stdout, BLUE "tint2: Test " YELLOW "%s" BLUE ": ", item->name);
if (status == SUCCESS) {
fprintf(stdout, GREEN "succeeded" RESET "\n");
succeeded++;
} else {
fprintf(stdout, RED "failed" RESET "\n");
failed++;
}
}
if (failed == 0)
fprintf(stdout, BLUE "tint2: " GREEN "all %lu tests succeeded." RESET "\n", count);
else
fprintf(stdout, BLUE "tint2: " RED "%lu" BLUE " out of %lu tests " RED "failed." RESET "\n", failed, count);
}
TEST(dummy) {
int x = 2;
int y = 2;
ASSERT_EQUAL(x, y);
}
TEST(dummyBad) {
int x = 2;
int y = 3;
ASSERT_EQUAL(x, y);
}

72
src/util/test.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef TEST_H
#define TEST_H
#include "bool.h"
#include "print.h"
typedef void Test(Status *test_result_);
void register_test_(Test *test, const char *name);
#define TEST(name) \
void test_##name(Status *test_result_); \
__attribute__((constructor)) void test_register_##name() \
{ \
register_test_(test_##name, #name); \
} \
void test_##name(Status *test_result_)
void run_all_tests();
#define FAIL_TEST_ \
*test_result_ = FAILURE; \
return;
#define ASSERT(value) \
if (!(value)) { \
FAIL_TEST_ \
}
#define ASSERT_EQUAL(a, b) \
if (!(a == b)) { \
printf("Assertion failed: %s == %s: ", #a, #b); \
print(a); \
printf(" != "); \
print(b); \
FAIL_TEST_ \
}
#define ASSERT_DIFFERENT(a, b) \
if (a == b) { \
printf("Assertion failed: %s != %s: ", #a, #b); \
print(a); \
printf(" == "); \
print(b); \
FAIL_TEST_ \
}
#define ASSERT_STR_EQUAL(a, b) \
if (strcmp(a, b) != 0) { \
printf("Assertion failed: %s == %s: ", #a, #b); \
print(a); \
printf(" != "); \
print(b); \
FAIL_TEST_ \
}
#define ASSERT_STR_DIFFERENT(a, b) \
if (strcmp(a, b) == 0) { \
printf("Assertion failed: %s != %s: ", #a, #b); \
print(a); \
printf(" == "); \
print(b); \
FAIL_TEST_ \
}
#define ASSERT_TRUE(value) ASSERT_EQUAL(value, 1)
#define ASSERT_FALSE(value) ASSERT_EQUAL(value, 0)
#define ASSERT_NULL(value) ASSERT_EQUAL(value, NULL)
#define ASSERT_NON_NULL(value) ASSERT_DIFFERENT(value, NULL)
#endif

View File

@@ -45,6 +45,8 @@ struct _timeout {
multi_timeout *multi_timeout;
timeout **self;
gboolean expired;
// timer has been restarted from its own callback function
gboolean reactivated;
};
void add_timeout_intern(int value_msec, int interval_msec, void (*_callback)(void *), void *arg, timeout *t);
@@ -158,18 +160,21 @@ void handle_expired_timers()
if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
// it's time for the callback function
t->expired = t->interval_msec == 0;
t->reactivated = FALSE;
t->_callback(t->arg);
// If _callback() calls stop_timeout(t) the timer 't' was freed and is not in the timeout_list
if (g_slist_find(timeout_list, t)) {
// Timer still exists
timeout_list = g_slist_remove(timeout_list, t);
if (t->interval_msec > 0) {
add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t->arg, t);
} else {
// Destroy single-shot timer
if (t->self)
*t->self = NULL;
free(t);
if (!t->reactivated) {
timeout_list = g_slist_remove(timeout_list, t);
if (t->interval_msec > 0) {
add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t->arg, t);
} else {
// Destroy single-shot timer
if (t->self)
*t->self = NULL;
free(t);
}
}
}
} else {
@@ -208,6 +213,7 @@ void add_timeout_intern(int value_msec, int interval_msec, void (*_callback)(),
can_align = align_with_existing_timeouts(t);
if (!can_align)
timeout_list = g_slist_insert_sorted(timeout_list, t, compare_timeouts);
t->reactivated = TRUE;
}
gint compare_timeouts(gconstpointer t1, gconstpointer t2)
@@ -384,6 +390,7 @@ void callback_multi_timeout(void *arg)
gettime(&cur_time);
GSList *it = mth->timeout_list;
while (it) {
GSList *next = it->next;
timeout *t = it->data;
if (++t->multi_timeout->current_count >= t->multi_timeout->count_to_expiration) {
t->_callback(t->arg);
@@ -395,7 +402,7 @@ void callback_multi_timeout(void *arg)
return;
}
}
it = it->next;
it = next;
}
}

View File

@@ -24,11 +24,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <Imlib2.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "common.h"
#include "window.h"
#include "server.h"
@@ -157,7 +163,8 @@ int get_window_desktop(Window win)
if (best_match < 0)
best_match = 0;
// fprintf(stderr, "tint2: window %lx %s : viewport %d, (%d, %d)\n", win, get_task(win) ? get_task(win)->title : "??",
// fprintf(stderr, "tint2: window %lx %s : viewport %d, (%d, %d)\n", win, get_task(win) ? get_task(win)->title :
// "??",
// best_match+1, x, y);
return best_match;
}
@@ -190,15 +197,18 @@ int get_window_monitor(Window win)
return best_match;
}
void get_window_coordinates(Window win, int *x, int *y, int *w, int *h)
gboolean get_window_coordinates(Window win, int *x, int *y, int *w, int *h)
{
int dummy_int;
unsigned ww, wh, bw, bh;
Window src;
XTranslateCoordinates(server.display, win, server.root_win, 0, 0, x, y, &src);
XGetGeometry(server.display, win, &src, &dummy_int, &dummy_int, &ww, &wh, &bw, &bh);
if (!XTranslateCoordinates(server.display, win, server.root_win, 0, 0, x, y, &src))
return FALSE;
if (!XGetGeometry(server.display, win, &src, &dummy_int, &dummy_int, &ww, &wh, &bw, &bh))
return FALSE;
*w = ww + bw;
*h = wh + bh;
*h = wh + bw;
return TRUE;
}
gboolean window_is_iconified(Window win)
@@ -352,3 +362,251 @@ char *get_window_name(Window win)
XFree(text_property.value);
return result;
}
void smooth_thumbnail(cairo_surface_t *image_surface)
{
u_int32_t *data = (u_int32_t *)cairo_image_surface_get_data(image_surface);
const size_t tw = cairo_image_surface_get_width(image_surface);
const size_t th = cairo_image_surface_get_height(image_surface);
const size_t rmask = 0xff0000;
const size_t gmask = 0xff00;
const size_t bmask = 0xff;
for (size_t i = 0; i < tw * (th - 1) - 1; i++) {
u_int32_t c1 = data[i];
u_int32_t c2 = data[i + 1];
u_int32_t c3 = data[i + tw];
u_int32_t c4 = data[i + tw + 1];
u_int32_t b = (5 * (c1 & bmask) + 1 * (c2 & bmask) + 1 * (c3 & bmask) + 1 * (c4 & bmask)) / 8;
u_int32_t g = (5 * (c1 & gmask) + 1 * (c2 & gmask) + 1 * (c3 & gmask) + 1 * (c4 & gmask)) / 8;
u_int32_t r = (5 * (c1 & rmask) + 1 * (c2 & rmask) + 1 * (c3 & rmask) + 1 * (c4 & rmask)) / 8;
data[i] = (r & rmask) | (g & gmask) | (b & bmask);
}
}
// 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
cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm)
{
cairo_surface_t *result = NULL;
XWindowAttributes wa;
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 ||
wa.map_state != IsViewable)
goto err0;
if (window_is_iconified(win))
goto err0;
size_t w, h;
w = (size_t)wa.width;
h = (size_t)wa.height;
size_t tw, th, fw;
size_t ox, oy;
tw = size;
th = h * tw / w;
if (th > tw * 0.618) {
th = (size_t)(tw * 0.618);
fw = w * th / h;
ox = (tw - fw) / 2;
oy = 0;
} else {
fw = tw;
ox = oy = 0;
}
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);
if (!ximg) {
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
goto err0;
}
if (ximg->bits_per_pixel != 24 && ximg->bits_per_pixel != 32) {
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;
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);
}
}
// Convert to argb32
if (rmask & 0xff0000) {
// argb32 or rgb24 => Nothing to do
} else if (rmask & 0xff) {
// bgr24
for (size_t i = 0; i < tw * th; i++) {
u_int32_t r = (data[i] & rmask) << 16;
u_int32_t g = (data[i] & gmask);
u_int32_t b = (data[i] & bmask) >> 16;
data[i] = (r & 0xff0000) | (g & 0x00ff00) | (b & 0x0000ff);
}
} else if (rmask & 0xff00) {
// bgra32
for (size_t i = 0; i < tw * th; i++) {
u_int32_t r = (data[i] & rmask) << 8;
u_int32_t g = (data[i] & gmask) >> 8;
u_int32_t b = (data[i] & bmask) >> 24;
data[i] = (r & 0xff0000) | (g & 0x00ff00) | (b & 0x0000ff);
}
}
// 2nd pass
smooth_thumbnail(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:
if (ximg)
XDestroyImage(ximg);
err0:
return result;
}
gboolean cairo_surface_is_blank(cairo_surface_t *image_surface)
{
uint32_t *pixels = (uint32_t *)cairo_image_surface_get_data(image_surface);
gboolean empty = TRUE;
int size = cairo_image_surface_get_width(image_surface) * cairo_image_surface_get_height(image_surface);
for (int i = 0; empty && i < size; i++) {
if (pixels[i] & 0xffFFff)
empty = FALSE;
}
return empty;
}
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)) {
cairo_surface_destroy(image_surface);
image_surface = NULL;
}
if (debug_thumbnails) {
if (!image_surface)
fprintf(stderr, YELLOW "tint2: XGetImage failed, trying slower method" RESET "\n");
else
fprintf(stderr, "tint2: captured window using XGetImage\n");
}
}
if (!image_surface)
return NULL;
return image_surface;
}

View File

@@ -25,7 +25,7 @@ int get_window_monitor(Window win);
void activate_window(Window win);
void close_window(Window win);
void get_window_coordinates(Window win, int *x, int *y, int *w, int *h);
gboolean get_window_coordinates(Window win, int *x, int *y, int *w, int *h);
void toggle_window_maximized(Window win);
void toggle_window_shade(Window win);
void change_window_desktop(Window win, int desktop);
@@ -34,5 +34,6 @@ int get_icon_count(gulong *data, int num);
gulong *get_best_icon(gulong *data, int icon_count, int num, int *iw, int *ih, int best_icon_size);
char *get_window_name(Window win);
cairo_surface_t *get_window_thumbnail(Window win, int size);
#endif

View File

@@ -0,0 +1,130 @@
AC0/type:Mains
AC0/power/control:auto
AC0/power/wakeup_prevent_sleep_time_ms:0
AC0/power/async:disabled
AC0/power/wakeup_abort_count:0
AC0/power/wakeup_active:0
AC0/power/wakeup_total_time_ms:0
AC0/power/wakeup_active_count:4
AC0/power/runtime_enabled:disabled
AC0/power/runtime_active_kids:0
AC0/power/runtime_active_time:0
AC0/power/wakeup_max_time_ms:0
AC0/power/wakeup_count:4
AC0/power/wakeup_last_time_ms:18773802
AC0/power/wakeup:enabled
AC0/power/runtime_status:unsupported
AC0/power/runtime_usage:0
AC0/power/wakeup_expire_count:0
AC0/power/runtime_suspended_time:0
AC0/online:1
AC0/uevent:POWER_SUPPLY_NAME=AC0
AC0/uevent:POWER_SUPPLY_ONLINE=1
BAT0/temp:26
BAT0/type:Battery
BAT0/power/control:auto
BAT0/power/wakeup_prevent_sleep_time_ms:0
BAT0/power/async:disabled
BAT0/power/wakeup_abort_count:0
BAT0/power/wakeup_active:0
BAT0/power/wakeup_total_time_ms:0
BAT0/power/wakeup_active_count:4
BAT0/power/runtime_enabled:disabled
BAT0/power/runtime_active_kids:0
BAT0/power/runtime_active_time:0
BAT0/power/wakeup_max_time_ms:0
BAT0/power/wakeup_count:4
BAT0/power/wakeup_last_time_ms:18773802
BAT0/power/wakeup:enabled
BAT0/power/runtime_status:unsupported
BAT0/power/runtime_usage:0
BAT0/power/wakeup_expire_count:0
BAT0/power/runtime_suspended_time:0
BAT0/charge_full_design:100
BAT0/charge_now:17
BAT0/charge_full:100
BAT0/charge_type:Fast
BAT0/capacity:17
BAT0/health:Good
BAT0/capacity_level:Critical
BAT0/status:Charging
BAT0/voltage_now:3300
BAT0/uevent:POWER_SUPPLY_NAME=BAT0
BAT0/uevent:POWER_SUPPLY_STATUS=Charging
BAT0/uevent:POWER_SUPPLY_CHARGE_TYPE=Fast
BAT0/uevent:POWER_SUPPLY_HEALTH=Good
BAT0/uevent:POWER_SUPPLY_PRESENT=1
BAT0/uevent:POWER_SUPPLY_TECHNOLOGY=Li-ion
BAT0/uevent:POWER_SUPPLY_CHARGE_FULL_DESIGN=100
BAT0/uevent:POWER_SUPPLY_CHARGE_FULL=100
BAT0/uevent:POWER_SUPPLY_CHARGE_NOW=17
BAT0/uevent:POWER_SUPPLY_CAPACITY=17
BAT0/uevent:POWER_SUPPLY_CAPACITY_LEVEL=Critical
BAT0/uevent:POWER_SUPPLY_TIME_TO_EMPTY_AVG=612
BAT0/uevent:POWER_SUPPLY_TIME_TO_FULL_NOW=612
BAT0/uevent:POWER_SUPPLY_MODEL_NAME=Fake battery 1
BAT0/uevent:POWER_SUPPLY_MANUFACTURER=Linux
BAT0/uevent:POWER_SUPPLY_SERIAL_NUMBER=12345678
BAT0/uevent:POWER_SUPPLY_TEMP=26
BAT0/uevent:POWER_SUPPLY_VOLTAGE_NOW=3300
BAT0/model_name:Fake battery 1
BAT0/manufacturer:Linux
BAT0/technology:Li-ion
BAT0/time_to_full_now:612
BAT0/time_to_empty_avg:612
BAT0/serial_number:12345678
BAT0/present:1
BAT1/temp:26
BAT1/type:Battery
BAT1/power/control:auto
BAT1/power/wakeup_prevent_sleep_time_ms:0
BAT1/power/async:disabled
BAT1/power/wakeup_abort_count:0
BAT1/power/wakeup_active:0
BAT1/power/wakeup_total_time_ms:0
BAT1/power/wakeup_active_count:4
BAT1/power/runtime_enabled:disabled
BAT1/power/runtime_active_kids:0
BAT1/power/runtime_active_time:0
BAT1/power/wakeup_max_time_ms:0
BAT1/power/wakeup_count:4
BAT1/power/wakeup_last_time_ms:18773802
BAT1/power/wakeup:enabled
BAT1/power/runtime_status:unsupported
BAT1/power/runtime_usage:0
BAT1/power/wakeup_expire_count:0
BAT1/power/runtime_suspended_time:0
BAT1/charge_full_design:100
BAT1/charge_now:7
BAT1/charge_full:100
BAT1/charge_type:Fast
BAT1/capacity:7
BAT1/health:Good
BAT1/capacity_level:Low
BAT1/status:Charging
BAT1/voltage_now:3300
BAT1/uevent:POWER_SUPPLY_NAME=BAT1
BAT1/uevent:POWER_SUPPLY_STATUS=Charging
BAT1/uevent:POWER_SUPPLY_CHARGE_TYPE=Fast
BAT1/uevent:POWER_SUPPLY_HEALTH=Good
BAT1/uevent:POWER_SUPPLY_PRESENT=1
BAT1/uevent:POWER_SUPPLY_TECHNOLOGY=Li-ion
BAT1/uevent:POWER_SUPPLY_CHARGE_FULL_DESIGN=100
BAT1/uevent:POWER_SUPPLY_CHARGE_FULL=100
BAT1/uevent:POWER_SUPPLY_CHARGE_NOW=7
BAT1/uevent:POWER_SUPPLY_CAPACITY=7
BAT1/uevent:POWER_SUPPLY_CAPACITY_LEVEL=Low
BAT1/uevent:POWER_SUPPLY_TIME_TO_EMPTY_AVG=252
BAT1/uevent:POWER_SUPPLY_TIME_TO_FULL_NOW=252
BAT1/uevent:POWER_SUPPLY_MODEL_NAME=Fake battery 2
BAT1/uevent:POWER_SUPPLY_MANUFACTURER=Linux
BAT1/uevent:POWER_SUPPLY_SERIAL_NUMBER=12345678
BAT1/uevent:POWER_SUPPLY_TEMP=26
BAT1/uevent:POWER_SUPPLY_VOLTAGE_NOW=3300
BAT1/model_name:Fake battery 2
BAT1/manufacturer:Linux
BAT1/technology:Li-ion
BAT1/time_to_full_now:252
BAT1/time_to_empty_avg:252
BAT1/serial_number:12345678
BAT1/present:1

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1 @@
disabled

View File

@@ -0,0 +1 @@
auto

View File

@@ -0,0 +1 @@
disabled

View File

@@ -0,0 +1 @@
unsupported

View File

@@ -0,0 +1 @@
enabled

View File

@@ -0,0 +1 @@
18773802

View File

@@ -0,0 +1 @@
Mains

View File

@@ -0,0 +1 @@
POWER_SUPPLY_ONLINE=1

View File

@@ -0,0 +1 @@
17

View File

@@ -0,0 +1 @@
Critical

View File

@@ -0,0 +1 @@
100

View File

@@ -0,0 +1 @@
17

View File

@@ -0,0 +1 @@
Fast

View File

@@ -0,0 +1 @@
Good

View File

@@ -0,0 +1 @@
Linux

View File

@@ -0,0 +1 @@
Fake battery 1

View File

@@ -0,0 +1 @@
disabled

View File

@@ -0,0 +1 @@
auto

View File

@@ -0,0 +1 @@
disabled

View File

@@ -0,0 +1 @@
unsupported

Some files were not shown because too many files have changed in this diff Show More