Compare commits
258
Commits
v15.0
...
thumb-xrender
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36c8d41914 | ||
|
|
4dafea185f | ||
|
|
77890d463a | ||
|
|
e1211a929f | ||
|
|
00f0bbd354 | ||
|
|
15d2570a3e | ||
|
|
c76f056746 | ||
|
|
cacd4b8dad | ||
|
|
b539c0a1c0 | ||
|
|
970c597796 | ||
|
|
a82b9a1d7f | ||
|
|
89a6cadfcd | ||
|
|
fb9da655df | ||
|
|
cb137674e4 | ||
|
|
1054aac7ca | ||
|
|
81c7c65a9f | ||
|
|
044bad6c40 | ||
|
|
aaa0e40af7 | ||
|
|
34f9fcaca4 | ||
|
|
f8c6dc1ecc | ||
|
|
11c468816d | ||
|
|
595d04451b | ||
|
|
6681cfbca6 | ||
|
|
14074894f9 | ||
|
|
3fcbf58873 | ||
|
|
1c2a12eb05 | ||
|
|
ec5bda6ddf | ||
|
|
5875015c11 | ||
|
|
21e9303502 | ||
|
|
94d4a219ee | ||
|
|
8a7ba9bf50 | ||
|
|
ffa6e5ba49 | ||
|
|
d1f5a46a73 | ||
|
|
131704081c | ||
|
|
21466cc94e | ||
|
|
e06b63e1dc | ||
|
|
9a03b8b4e6 | ||
|
|
47bc01d608 | ||
|
|
0e4b3bd32e | ||
|
|
9ac0cd1254 | ||
|
|
73ab9b6930 | ||
|
|
96361ab1cd | ||
|
|
b9589450bb | ||
|
|
b810bad93f | ||
|
|
b85362b5c7 | ||
|
|
03675b152d | ||
|
|
c3fdd76b58 | ||
|
|
04ba5a6617 | ||
|
|
f5f8792d42 | ||
|
|
965a2665b0 | ||
|
|
b2b0119f4d | ||
|
|
41e49ef4e6 | ||
|
|
25dd623618 | ||
|
|
28b1174c0f | ||
|
|
b70edc437c | ||
|
|
bf58e16b83 | ||
|
|
3190c5b7de | ||
|
|
5db0dceec2 | ||
|
|
5c5f507e54 | ||
|
|
d301ada47a | ||
|
|
b3f9834313 | ||
|
|
c7b23ee94a | ||
|
|
12f04e3055 | ||
|
|
7f62594cf6 | ||
|
|
405c2c9286 | ||
|
|
90a445868c | ||
|
|
427afc61b5 | ||
|
|
ee92fac10e | ||
|
|
95eea350fe | ||
|
|
8242b494bc | ||
|
|
1c6377f570 | ||
|
|
dd1fd28114 | ||
|
|
b4610fcb6e | ||
|
|
eb0e6765f9 | ||
|
|
5ee278d3ca | ||
|
|
fb438031c3 | ||
|
|
e5380f8e29 | ||
|
|
c064ec70ed | ||
|
|
a9a9a753bc | ||
|
|
38bee65b58 | ||
|
|
f64cf199e4 | ||
|
|
0911dcaed1 | ||
|
|
c41d75e54e | ||
|
|
8e0bdcaedd | ||
|
|
be4554b89d | ||
|
|
82d7fdc8f9 | ||
|
|
e046cb88ab | ||
|
|
300ef518cb | ||
|
|
457d51e267 | ||
|
|
1b48efe738 | ||
|
|
40e01e2abf | ||
|
|
a7ca1b739b | ||
|
|
750cbd572c | ||
|
|
75c2a2084d | ||
|
|
9b17461f74 | ||
|
|
a185f625f9 | ||
|
|
3a9181eff5 | ||
|
|
5cea67171b | ||
|
|
328a35f949 | ||
|
|
cab9c3bddd | ||
|
|
5dd814773a | ||
|
|
f4384b786c | ||
|
|
5bc83561e0 | ||
|
|
375e965a3a | ||
|
|
67e25b8102 | ||
|
|
c96201930b | ||
|
|
6bf72a030a | ||
|
|
63d0d98a5c | ||
|
|
e739023529 | ||
|
|
a7a9c5cdae | ||
|
|
50822bd2fd | ||
|
|
00c79073f0 | ||
|
|
f5b36b37b6 | ||
|
|
c635f46439 | ||
|
|
16a359f944 | ||
|
|
9a972f4c25 | ||
|
|
9d06ac0157 | ||
|
|
cfac6a645d | ||
|
|
648c7c109f | ||
|
|
8946f93254 | ||
|
|
58e030de5d | ||
|
|
c2f8c210f8 | ||
|
|
978e1c90fc | ||
|
|
3fba8aa1cf | ||
|
|
26251849c6 | ||
|
|
abeb7ce2e6 | ||
|
|
abdb1aeff9 | ||
|
|
7e383c395e | ||
|
|
c3ed2dadf3 | ||
|
|
bd2ca94ffe | ||
|
|
1753641fc9 | ||
|
|
467ea1332c | ||
|
|
68c2ad7062 | ||
|
|
cc5842463d | ||
|
|
5e124c7a97 | ||
|
|
07865142b2 | ||
|
|
0c71fda5e1 | ||
|
|
8eaf187984 | ||
|
|
abe8a0eeb1 | ||
|
|
d82d782541 | ||
|
|
715eb556da | ||
|
|
b9e64da9da | ||
|
|
224b7fba82 | ||
|
|
d72fff9653 | ||
|
|
67c3e47414 | ||
|
|
e96e7fbee7 | ||
|
|
65c91667f9 | ||
|
|
9f4087b471 | ||
|
|
247687307b | ||
|
|
2c9d1fdf7d | ||
|
|
500b8f5bea | ||
|
|
7e6f7df55e | ||
|
|
47201cab84 | ||
|
|
f7d083904f | ||
|
|
f11d30f076 | ||
|
|
c0eaa8274f | ||
|
|
38488b8d75 | ||
|
|
07339c09a0 | ||
|
|
0521223899 | ||
|
|
cbf3cebbb0 | ||
|
|
4b50446a7b | ||
|
|
e8a6c93b28 | ||
|
|
5e6e1184fe | ||
|
|
89ab1fa6c4 | ||
|
|
e597973cd7 | ||
|
|
ebe30774ac | ||
|
|
d463dcb5b4 | ||
|
|
23782a4414 | ||
|
|
1be85e66fe | ||
|
|
2fe7efd4fe | ||
|
|
1b6fd91611 | ||
|
|
5730725762 | ||
|
|
87da8c76cc | ||
|
|
e5ecc0c15d | ||
|
|
812e306376 | ||
|
|
3155a5fc89 | ||
|
|
bc4af51e82 | ||
|
|
01de174919 | ||
|
|
7ddb373cb4 | ||
|
|
8ba1f26309 | ||
|
|
5a867a83c6 | ||
|
|
8a7e7e4281 | ||
|
|
0e8a6dd961 | ||
|
|
c4a0ec4140 | ||
|
|
07d907fc43 | ||
|
|
b1f83baf04 | ||
|
|
1ff3404e56 | ||
|
|
41190204b3 | ||
|
|
5bc978ee44 | ||
|
|
3b4028f443 | ||
|
|
acc3ee9205 | ||
|
|
d8770ed590 | ||
|
|
be7873a688 | ||
|
|
cf81f1c9f9 | ||
|
|
cde05df1bc | ||
|
|
5fee459945 | ||
|
|
6d67291928 | ||
|
|
4171e23153 | ||
|
|
725f625aba | ||
|
|
a6ea1eb5a9 | ||
|
|
14b983cd0c | ||
|
|
23ddb47e0c | ||
|
|
407aef3786 | ||
|
|
50c7bf77de | ||
|
|
9a7d5a1a51 | ||
|
|
031bd23849 | ||
|
|
7e2dc91ce7 | ||
|
|
c7a81655c4 | ||
|
|
9aa50104db | ||
|
|
3320ee8e05 | ||
|
|
ec380e25ec | ||
|
|
e1b29d0204 | ||
|
|
13313f64c5 | ||
|
|
9cb64e9cf5 | ||
|
|
fd0a1bef65 | ||
|
|
ae9ae098cc | ||
|
|
18f49d0d52 | ||
|
|
a57b6a4706 | ||
|
|
f8aa84a91b | ||
|
|
0154fe6a5a | ||
|
|
6f96818438 | ||
|
|
6433767a98 | ||
|
|
f8037b7ff5 | ||
|
|
7dddd4a5a2 | ||
|
|
85ac37d019 | ||
|
|
499b2bd938 | ||
|
|
5302fb4ba7 | ||
|
|
b58a6512b3 | ||
|
|
e38ccf5376 | ||
|
|
3c9a0ff2f7 | ||
|
|
b8675fa208 | ||
|
|
ddac8f7802 | ||
|
|
c21930de2b | ||
|
|
f2cc1b68c1 | ||
|
|
fc61676732 | ||
|
|
1772d0a894 | ||
|
|
3de424b129 | ||
|
|
d8c289e0cc | ||
|
|
5a17bb2fda | ||
|
|
c45b06657a | ||
|
|
7666077c63 | ||
|
|
542aa56840 | ||
|
|
d2f990366b | ||
|
|
1480faf32f | ||
|
|
38ff3318eb | ||
|
|
5bd253c0da | ||
|
|
9e94ee15e4 | ||
|
|
a026cd91fe | ||
|
|
a52c45bd08 | ||
|
|
88c91aae25 | ||
|
|
b793544cf8 | ||
|
|
63c3690fa8 | ||
|
|
e2ece2c35b | ||
|
|
86d6e96f7a | ||
|
|
87e1ccc6bf | ||
|
|
aa355e22f9 | ||
|
|
d21f758158 | ||
|
|
f2741116a7 |
@@ -1,3 +1,7 @@
|
|||||||
build
|
build
|
||||||
*.user
|
*.user
|
||||||
version.h
|
version.h
|
||||||
|
*.pyc
|
||||||
|
*.todo
|
||||||
|
packaging/make_ubuntu2.sh
|
||||||
|
test_*.log
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ tint2 is developped by :
|
|||||||
- Ovidiu M <mrovi9000 at gmail.com> : launcher, bug fixes
|
- Ovidiu M <mrovi9000 at gmail.com> : launcher, bug fixes
|
||||||
- Mishael A Sibiryakov (death@junki.org) : freespace
|
- Mishael A Sibiryakov (death@junki.org) : freespace
|
||||||
- Sebastian Reichel <sre@ring0.de> : battery, various fixes, debian package maintainer
|
- Sebastian Reichel <sre@ring0.de> : battery, various fixes, debian package maintainer
|
||||||
|
- Chris Lee <chrlee at protonmail> : bug fixes, maintainer starting with v16.3
|
||||||
|
|
||||||
tint2 is based on the ttm source code (http://code.google.com/p/ttm/)
|
tint2 is based on the ttm source code (http://code.google.com/p/ttm/)
|
||||||
- 2007-2008 Pål Staurland <staura@gmail.com>
|
- 2007-2008 Pål Staurland <staura@gmail.com>
|
||||||
@@ -31,6 +32,8 @@ Contributors:
|
|||||||
Matthew Otnel : config option systray_name_filter
|
Matthew Otnel : config option systray_name_filter
|
||||||
Ryan Gray, Jeff Blake (https://gitlab.com/berkley4) : battery format
|
Ryan Gray, Jeff Blake (https://gitlab.com/berkley4) : battery format
|
||||||
aaaz (https://gitlab.com/aaaz) : clock fixes
|
aaaz (https://gitlab.com/aaaz) : clock fixes
|
||||||
|
heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color
|
||||||
|
Fabian Carlström : taskbar sort order by app name
|
||||||
|
|
||||||
Translations:
|
Translations:
|
||||||
Bosnian:
|
Bosnian:
|
||||||
@@ -45,3 +48,5 @@ Translations:
|
|||||||
Daniel Napora <napcok@gmail.com>
|
Daniel Napora <napcok@gmail.com>
|
||||||
Serbian:
|
Serbian:
|
||||||
Dino Duratović <dinomol@mail.com>
|
Dino Duratović <dinomol@mail.com>
|
||||||
|
Spanish:
|
||||||
|
Vic <vicmz@yandex.com>
|
||||||
|
|||||||
+27
-11
@@ -25,7 +25,7 @@ endif()
|
|||||||
include( FindPkgConfig )
|
include( FindPkgConfig )
|
||||||
include( CheckLibraryExists )
|
include( CheckLibraryExists )
|
||||||
include( CheckCSourceCompiles )
|
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( PANGOCAIRO REQUIRED pangocairo )
|
||||||
pkg_check_modules( PANGO REQUIRED pango )
|
pkg_check_modules( PANGO REQUIRED pango )
|
||||||
pkg_check_modules( CAIRO REQUIRED cairo )
|
pkg_check_modules( CAIRO REQUIRED cairo )
|
||||||
@@ -62,6 +62,17 @@ else()
|
|||||||
set(BACKTRACE_L_FLAGS "")
|
set(BACKTRACE_L_FLAGS "")
|
||||||
endif()
|
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 )
|
if( ENABLE_RSVG )
|
||||||
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
|
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
|
||||||
endif( ENABLE_RSVG )
|
endif( ENABLE_RSVG )
|
||||||
@@ -84,10 +95,10 @@ if( NOT IMLIB_BUILD_WITH_X )
|
|||||||
endif( NOT IMLIB_BUILD_WITH_X )
|
endif( NOT IMLIB_BUILD_WITH_X )
|
||||||
|
|
||||||
|
|
||||||
|
add_definitions( -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_WITH_GETLINE )
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
add_definitions( -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE -D_DEFAULT_SOURCE )
|
add_definitions( -D_POSIX_C_SOURCE=200809L )
|
||||||
else(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
add_definitions( -D_WITH_GETLINE )
|
|
||||||
endif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
endif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
|
||||||
|
|
||||||
@@ -116,13 +127,14 @@ include_directories( ${PROJECT_BINARY_DIR}
|
|||||||
|
|
||||||
set( SOURCES src/config.c
|
set( SOURCES src/config.c
|
||||||
src/panel.c
|
src/panel.c
|
||||||
src/server.c
|
src/util/server.c
|
||||||
src/main.c
|
src/main.c
|
||||||
src/init.c
|
src/init.c
|
||||||
src/signals.c
|
src/util/signals.c
|
||||||
src/tracing.c
|
src/util/tracing.c
|
||||||
src/mouse_actions.c
|
src/mouse_actions.c
|
||||||
src/drag_and_drop.c
|
src/drag_and_drop.c
|
||||||
|
src/default_icon.c
|
||||||
src/clock/clock.c
|
src/clock/clock.c
|
||||||
src/systray/systraybar.c
|
src/systray/systraybar.c
|
||||||
src/launcher/launcher.c
|
src/launcher/launcher.c
|
||||||
@@ -140,13 +152,18 @@ set( SOURCES src/config.c
|
|||||||
src/separator/separator.c
|
src/separator/separator.c
|
||||||
src/tint2rc.c
|
src/tint2rc.c
|
||||||
src/util/area.c
|
src/util/area.c
|
||||||
|
src/util/bt.c
|
||||||
src/util/common.c
|
src/util/common.c
|
||||||
src/util/fps_distribution.c
|
src/util/fps_distribution.c
|
||||||
src/util/strnatcmp.c
|
src/util/strnatcmp.c
|
||||||
src/util/timer.c
|
src/util/timer.c
|
||||||
src/util/cache.c
|
src/util/cache.c
|
||||||
src/util/color.c
|
src/util/color.c
|
||||||
|
src/util/strlcat.c
|
||||||
|
src/util/print.c
|
||||||
src/util/gradient.c
|
src/util/gradient.c
|
||||||
|
src/util/test.c
|
||||||
|
src/util/uevent.c
|
||||||
src/util/window.c )
|
src/util/window.c )
|
||||||
|
|
||||||
if( ENABLE_BATTERY )
|
if( ENABLE_BATTERY )
|
||||||
@@ -187,7 +204,6 @@ endif( ENABLE_SN)
|
|||||||
|
|
||||||
if( ENABLE_UEVENT )
|
if( ENABLE_UEVENT )
|
||||||
add_definitions( -DENABLE_UEVENT )
|
add_definitions( -DENABLE_UEVENT )
|
||||||
set( SOURCES ${SOURCES} src/util/uevent.c)
|
|
||||||
endif( ENABLE_UEVENT )
|
endif( ENABLE_UEVENT )
|
||||||
|
|
||||||
if(ENABLE_BACKTRACE)
|
if(ENABLE_BACKTRACE)
|
||||||
@@ -233,7 +249,7 @@ else()
|
|||||||
SET(TRACING_L_FLAGS "")
|
SET(TRACING_L_FLAGS "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" -- "\"${PROJECT_SOURCE_DIR}/\"" )
|
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" )
|
||||||
|
|
||||||
link_directories( ${X11_LIBRARY_DIRS}
|
link_directories( ${X11_LIBRARY_DIRS}
|
||||||
${PANGOCAIRO_LIBRARY_DIRS}
|
${PANGOCAIRO_LIBRARY_DIRS}
|
||||||
@@ -267,13 +283,13 @@ endif( RT_LIBRARY )
|
|||||||
target_link_libraries( tint2 m )
|
target_link_libraries( tint2 m )
|
||||||
|
|
||||||
add_dependencies( tint2 version )
|
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}" )
|
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( TARGETS tint2 DESTINATION bin )
|
||||||
install( FILES tint2.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps )
|
install( FILES tint2.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps )
|
||||||
install( FILES tint2.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )
|
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 default_icon.png DESTINATION ${CMAKE_INSTALL_DATADIR}/tint2 )
|
||||||
install( FILES AUTHORS ChangeLog README.md doc/tint2.md DESTINATION ${docdir} )
|
install( FILES AUTHORS ChangeLog README.md doc/tint2.md DESTINATION ${docdir} )
|
||||||
install( FILES doc/manual.html doc/readme.html DESTINATION ${htmldir} )
|
install( FILES doc/manual.html doc/readme.html DESTINATION ${htmldir} )
|
||||||
|
|||||||
@@ -1,3 +1,71 @@
|
|||||||
|
2019-02-17 master
|
||||||
|
- Fix spacing around icons in executor without text in vertical panels (issue #716)
|
||||||
|
- Fix Bug: Clock Only Updates Every Minute With Format %s (issue #724)
|
||||||
|
- Fix markup drawing when font shadow enabled (issue #709)
|
||||||
|
- Blink battery when low (issue #723)
|
||||||
|
|
||||||
|
2018-08-05 16.6.1
|
||||||
|
- Fix packaging regression for debian (issue #715)
|
||||||
|
|
||||||
|
2018-08-04 16.6
|
||||||
|
- Fix regression in task icon brightness (issue #714)
|
||||||
|
|
||||||
|
2018-08-04 16.5
|
||||||
|
- Add new build script
|
||||||
|
- Add option to sort taskbar by application name
|
||||||
|
- Fix regression in image loading
|
||||||
|
|
||||||
|
2018-05-03 16.4
|
||||||
|
- Update AUTHORS
|
||||||
|
- Fixes:
|
||||||
|
- Fix leak in image loading (issue #704)
|
||||||
|
- Executors no longer log unless env var DEBUG_EXECUTORS is set
|
||||||
|
|
||||||
|
2018-04-17 16.3
|
||||||
|
- Fixes:
|
||||||
|
- Layout in executor (issue #695)
|
||||||
|
- Other small issues
|
||||||
|
|
||||||
|
2018-01-21 16.2
|
||||||
|
- Fixes:
|
||||||
|
- Proper fix for issue #688
|
||||||
|
- Fix bad word wrapping (issue #693)
|
||||||
|
- Enhancements:
|
||||||
|
- Preliminary high DPI support
|
||||||
|
|
||||||
|
2017-12-30 16.1
|
||||||
|
- Fixes:
|
||||||
|
- Fixed several use-after-free errors in the timer code
|
||||||
|
- Merged patches and fixed other warnings on OpenBSD
|
||||||
|
- Task, Button, Executor: add a bit of slack in the pango text layout,
|
||||||
|
to avoid wrapping due to rounding errors
|
||||||
|
|
||||||
|
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)
|
||||||
|
- Taskbar: thumbnail support in tooltips
|
||||||
|
- Use C11 if possible to support generic printing for unit tests (should fall back to C99)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
2017-09-02 15.0
|
2017-09-02 15.0
|
||||||
- Fixes:
|
- Fixes:
|
||||||
- Clock, executors and other timers fire correctly after waking up from suspend
|
- Clock, executors and other timers fire correctly after waking up from suspend
|
||||||
@@ -947,3 +1015,13 @@ released tint-0.2
|
|||||||
- fork ttm projet from p://code.google.com/p/ttm/ (by Pål Staurland staura@gmail.com)
|
- fork ttm projet from p://code.google.com/p/ttm/ (by Pål Staurland staura@gmail.com)
|
||||||
while the projet is no longer in developpement, have not changed the name of 'tint'.
|
while the projet is no longer in developpement, have not changed the name of 'tint'.
|
||||||
.
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Latest stable release: 15.0
|
# Latest stable release: 16.6.1
|
||||||
Changes: https://gitlab.com/o9000/tint2/blob/15.0/ChangeLog
|
Changes: https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog
|
||||||
|
|
||||||
Documentation: [doc/tint2.md](doc/tint2.md)
|
Documentation: [doc/tint2.md](doc/tint2.md)
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ Compile it with (after you install the [dependencies](https://gitlab.com/o9000/t
|
|||||||
```
|
```
|
||||||
git clone https://gitlab.com/o9000/tint2.git
|
git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 15.0
|
git checkout 16.6.1
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
@@ -61,9 +61,9 @@ tint2 is a simple panel/taskbar made for modern X window managers. It was specif
|
|||||||
|
|
||||||
# Known issues
|
# 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))
|
* 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 (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))
|
* 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)
|
* 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?
|
# How can I help out?
|
||||||
|
|
||||||
@@ -97,4 +97,3 @@ tint2 is a simple panel/taskbar made for modern X window managers. It was specif
|
|||||||
## More
|
## More
|
||||||
|
|
||||||
* [Tint2 wiki](https://gitlab.com/o9000/tint2/wikis/Home)
|
* [Tint2 wiki](https://gitlab.com/o9000/tint2/wikis/Home)
|
||||||
Home)
|
|
||||||
|
|||||||
+9
-2
@@ -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>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>
|
<li><code>opacity</code> varies from (0 to 100), where 0 is fully transparent, 100 is fully opaque</li>
|
||||||
</ul></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>
|
</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
|
<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
|
border_width = 0
|
||||||
@@ -384,6 +386,8 @@ gradient_id_pressed = 2
|
|||||||
<li><code>width</code> and <code>height</code> can be specified without units (e.g. <code>123</code>) as pixels, or followed by <code>%</code> as percentages of the monitor size (e.g. <code>50%</code>). Use <code>100%</code> for full monitor width/height.
|
<li><code>width</code> and <code>height</code> can be specified without units (e.g. <code>123</code>) as pixels, or followed by <code>%</code> as percentages of the monitor size (e.g. <code>50%</code>). Use <code>100%</code> for full monitor width/height.
|
||||||
Example:</li>
|
Example:</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
<li><p><code>scale_relative_to_dpi = integer</code> : If set to a non-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI - this is the DPI for which exising user configs looked normal, for backward compatibility.</p></li>
|
||||||
|
<li><p><code>scale_relative_to_screen_height = integer</code> : Similar to <code>scale_relative_to_dpi</code>, except the scaling factor is computed as the ratio between the monitor height and <code>scale_relative_to_screen_height</code>. The effect is cumulative with <code>scale_relative_to_dpi</code>, i.e. if both options are present, the factors are multiplied.</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
<pre class="highlight plaintext"><code># The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
<pre class="highlight plaintext"><code># The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
||||||
panel_size = 94% 30
|
panel_size = 94% 30
|
||||||
@@ -462,6 +466,7 @@ panel_size = 94% 30
|
|||||||
<ul>
|
<ul>
|
||||||
<li><code>none</code> : No sorting. New tasks are simply appended at the end of the taskbar when they appear.</li>
|
<li><code>none</code> : No sorting. New tasks are simply appended at the end of the taskbar when they appear.</li>
|
||||||
<li><code>title</code> : Sorts the tasks by title.</li>
|
<li><code>title</code> : Sorts the tasks by title.</li>
|
||||||
|
<li><code>application</code> : Sorts the tasks by application name. <em>(since 16.3)</em></li>
|
||||||
<li><code>center</code> : Sorts the tasks by their window centers.</li>
|
<li><code>center</code> : Sorts the tasks by their window centers.</li>
|
||||||
<li><code>mru</code> : Shows the most recently used tasks first. <em>(since 0.12.4)</em></li>
|
<li><code>mru</code> : Shows the most recently used tasks first. <em>(since 0.12.4)</em></li>
|
||||||
<li><code>lru</code> : Shows the most recently used tasks last. <em>(since 0.12.4)</em></li>
|
<li><code>lru</code> : Shows the most recently used tasks last. <em>(since 0.12.4)</em></li>
|
||||||
@@ -481,6 +486,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_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_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_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>
|
<li><p><code>task_maximum_size = width height</code></p>
|
||||||
<ul>
|
<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>
|
<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>
|
||||||
@@ -566,7 +573,7 @@ panel_size = 94% 30
|
|||||||
<ul>
|
<ul>
|
||||||
<li><p><code>battery_hide = never/integer (0 to 100)</code> : At what battery percentage the battery item is hidden.</p></li>
|
<li><p><code>battery_hide = never/integer (0 to 100)</code> : At what battery percentage the battery item is hidden.</p></li>
|
||||||
<li><p><code>battery_low_status = integer</code>: At what battery percentage the low command is executed.</p></li>
|
<li><p><code>battery_low_status = integer</code>: At what battery percentage the low command is executed.</p></li>
|
||||||
<li><p><code>battery_low_cmd = notify-send "battery low"</code> : Command to execute when the battery is low.</p></li>
|
<li><p><code>battery_low_cmd = xmessage 'tint2: Battery low!'</code> : Command to execute when the battery is low.</p></li>
|
||||||
<li><p><code>battery_full_cmd = notify-send "battery full"</code> : Command to execute when the battery is full.</p></li>
|
<li><p><code>battery_full_cmd = notify-send "battery full"</code> : Command to execute when the battery is full.</p></li>
|
||||||
<li><p><code>bat1_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
<li><p><code>bat1_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
||||||
<li><p><code>bat2_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
<li><p><code>bat2_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
||||||
@@ -601,7 +608,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_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_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_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("\x1b[2J");</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 = [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_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>
|
<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>
|
||||||
|
|||||||
+6
-7
@@ -199,9 +199,9 @@ pre {
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 id="latest-stable-release-15-0"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">15.0</span><a name="latest-stable-release-15-0" href="#latest-stable-release-15-0" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/15.0/ChangeLog">https://gitlab.com/o9000/tint2/blob/15.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
|
<h1 id="latest-stable-release-16-6-1"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.6.1</span><a name="latest-stable-release-16-6-1" href="#latest-stable-release-16-6-1" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog</a></p><p>Documentation: <a href="manual.html">manual.html</a></p><p>Compile it with (after you install the <a href="https://gitlab.com/o9000/tint2/wikis/Install#dependencies">dependencies</a>):</p><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 15.0
|
git checkout 16.6.1
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
@@ -239,9 +239,9 @@ update-mime-database /usr/local/share/mime
|
|||||||
</ul>
|
</ul>
|
||||||
<h1 id="known-issues">Known issues<a name="known-issues" href="#known-issues" class="md2man-permalink" title="permalink"></a></h1>
|
<h1 id="known-issues">Known issues<a name="known-issues" href="#known-issues" class="md2man-permalink" title="permalink"></a></h1>
|
||||||
<ul>
|
<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>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 (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>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>
|
<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>
|
</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>
|
<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>
|
<ul>
|
||||||
@@ -269,8 +269,7 @@ update-mime-database /usr/local/share/mime
|
|||||||
</ul>
|
</ul>
|
||||||
<h2 id="more">More<a name="more" href="#more" class="md2man-permalink" title="permalink"></a></h2>
|
<h2 id="more">More<a name="more" href="#more" class="md2man-permalink" title="permalink"></a></h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://gitlab.com/o9000/tint2/wikis/Home">Tint2 wiki</a>
|
<li><a href="https://gitlab.com/o9000/tint2/wikis/Home">Tint2 wiki</a></li>
|
||||||
Home)</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-3
@@ -1,4 +1,4 @@
|
|||||||
.TH TINT2 1 "2017\-09\-02" 15.0
|
.TH TINT2 1 "2018\-08\-05" 16.6.1
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
tint2 \- lightweight panel/taskbar
|
tint2 \- lightweight panel/taskbar
|
||||||
@@ -150,6 +150,10 @@ The tint2 config file starts with the options defining background elements with
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCopacity\fR varies from (0 to 100), where 0 is fully transparent, 100 is fully opaque
|
\fB\fCopacity\fR varies from (0 to 100), where 0 is fully transparent, 100 is fully opaque
|
||||||
.RE
|
.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
|
.RE
|
||||||
.PP
|
.PP
|
||||||
You can define as many backgrounds as you want. For example, the following config defines two backgrounds:
|
You can define as many backgrounds as you want. For example, the following config defines two backgrounds:
|
||||||
@@ -339,6 +343,10 @@ Use \fB\fCpanel_monitor = all\fR to get a separate panel per monitor
|
|||||||
\fB\fCwidth\fR and \fB\fCheight\fR can be specified without units (e.g. \fB\fC123\fR) as pixels, or followed by \fB\fC%\fR as percentages of the monitor size (e.g. \fB\fC50%\fR). Use \fB\fC100%\fR for full monitor width/height.
|
\fB\fCwidth\fR and \fB\fCheight\fR can be specified without units (e.g. \fB\fC123\fR) as pixels, or followed by \fB\fC%\fR as percentages of the monitor size (e.g. \fB\fC50%\fR). Use \fB\fC100%\fR for full monitor width/height.
|
||||||
Example:
|
Example:
|
||||||
.RE
|
.RE
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fCscale_relative_to_dpi = integer\fR : If set to a non\-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI \- this is the DPI for which exising user configs looked normal, for backward compatibility.
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fCscale_relative_to_screen_height = integer\fR : Similar to \fB\fCscale_relative_to_dpi\fR, except the scaling factor is computed as the ratio between the monitor height and \fB\fCscale_relative_to_screen_height\fR\&. The effect is cumulative with \fB\fCscale_relative_to_dpi\fR, i.e. if both options are present, the factors are multiplied.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
@@ -472,6 +480,8 @@ You can switch between virtual desktops.
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCtitle\fR : Sorts the tasks by title.
|
\fB\fCtitle\fR : Sorts the tasks by title.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
|
\fB\fCapplication\fR : Sorts the tasks by application name. \fI(since 16.3)\fP
|
||||||
|
.IP \(bu 2
|
||||||
\fB\fCcenter\fR : Sorts the tasks by their window centers.
|
\fB\fCcenter\fR : Sorts the tasks by their window centers.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCmru\fR : Shows the most recently used tasks first. \fI(since 0.12.4)\fP
|
\fB\fCmru\fR : Shows the most recently used tasks first. \fI(since 0.12.4)\fP
|
||||||
@@ -508,6 +518,10 @@ The following options configure the task buttons in the taskbar:
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCtask_tooltip = boolean (0 or 1)\fR : Whether to show tooltips for tasks.
|
\fB\fCtask_tooltip = boolean (0 or 1)\fR : Whether to show tooltips for tasks.
|
||||||
.IP \(bu 2
|
.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
|
\fB\fCtask_maximum_size = width height\fR
|
||||||
.RS
|
.RS
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
@@ -651,7 +665,7 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCbattery_low_status = integer\fR: At what battery percentage the low command is executed.
|
\fB\fCbattery_low_status = integer\fR: At what battery percentage the low command is executed.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCbattery_low_cmd = notify\-send "battery low"\fR : Command to execute when the battery is low.
|
\fB\fCbattery_low_cmd = xmessage 'tint2: Battery low!'\fR : Command to execute when the battery is low.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCbattery_full_cmd = notify\-send "battery full"\fR : Command to execute when the battery is full.
|
\fB\fCbattery_full_cmd = notify\-send "battery full"\fR : Command to execute when the battery is full.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
@@ -716,7 +730,7 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCexecp_icon_h = integer\fR : See \fB\fCexecp_icon_w\fR\&. \fI(since 0.12.4)\fP
|
\fB\fCexecp_icon_h = integer\fR : See \fB\fCexecp_icon_w\fR\&. \fI(since 0.12.4)\fP
|
||||||
.IP \(bu 2
|
.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
|
.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
|
\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
|
.IP \(bu 2
|
||||||
|
|||||||
+16
-3
@@ -1,4 +1,4 @@
|
|||||||
# TINT2 1 "2017-09-02" 15.0
|
# TINT2 1 "2018-08-05" 16.6.1
|
||||||
|
|
||||||
## NAME
|
## NAME
|
||||||
tint2 - lightweight panel/taskbar
|
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
|
* `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
|
* `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:
|
You can define as many backgrounds as you want. For example, the following config defines two backgrounds:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -275,6 +279,10 @@ gradient_id_pressed = 2
|
|||||||
* `width` and `height` can be specified without units (e.g. `123`) as pixels, or followed by `%` as percentages of the monitor size (e.g. `50%`). Use `100%` for full monitor width/height.
|
* `width` and `height` can be specified without units (e.g. `123`) as pixels, or followed by `%` as percentages of the monitor size (e.g. `50%`). Use `100%` for full monitor width/height.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
* `scale_relative_to_dpi = integer` : If set to a non-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI - this is the DPI for which exising user configs looked normal, for backward compatibility.
|
||||||
|
|
||||||
|
* `scale_relative_to_screen_height = integer` : Similar to `scale_relative_to_dpi`, except the scaling factor is computed as the ratio between the monitor height and `scale_relative_to_screen_height`. The effect is cumulative with `scale_relative_to_dpi`, i.e. if both options are present, the factors are multiplied.
|
||||||
|
|
||||||
```
|
```
|
||||||
# The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
# The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
||||||
panel_size = 94% 30
|
panel_size = 94% 30
|
||||||
@@ -377,6 +385,7 @@ panel_size = 94% 30
|
|||||||
* `taskbar_sort_order = none/title/center` : Specifies the sort order of the tasks on the taskbar. *(since 0.12)*
|
* `taskbar_sort_order = none/title/center` : Specifies the sort order of the tasks on the taskbar. *(since 0.12)*
|
||||||
* `none` : No sorting. New tasks are simply appended at the end of the taskbar when they appear.
|
* `none` : No sorting. New tasks are simply appended at the end of the taskbar when they appear.
|
||||||
* `title` : Sorts the tasks by title.
|
* `title` : Sorts the tasks by title.
|
||||||
|
* `application` : Sorts the tasks by application name. *(since 16.3)*
|
||||||
* `center` : Sorts the tasks by their window centers.
|
* `center` : Sorts the tasks by their window centers.
|
||||||
* `mru` : Shows the most recently used tasks first. *(since 0.12.4)*
|
* `mru` : Shows the most recently used tasks first. *(since 0.12.4)*
|
||||||
* `lru` : Shows the most recently used tasks last. *(since 0.12.4)*
|
* `lru` : Shows the most recently used tasks last. *(since 0.12.4)*
|
||||||
@@ -409,6 +418,10 @@ The following options configure the task buttons in the taskbar:
|
|||||||
|
|
||||||
* `task_tooltip = boolean (0 or 1)` : Whether to show tooltips for tasks.
|
* `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`
|
* `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.
|
* `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.
|
* `height` is used with vertical panels.
|
||||||
@@ -534,7 +547,7 @@ The action semantics:
|
|||||||
|
|
||||||
* `battery_low_status = integer`: At what battery percentage the low command is executed.
|
* `battery_low_status = integer`: At what battery percentage the low command is executed.
|
||||||
|
|
||||||
* `battery_low_cmd = notify-send "battery low"` : Command to execute when the battery is low.
|
* `battery_low_cmd = xmessage 'tint2: Battery low!'` : Command to execute when the battery is low.
|
||||||
|
|
||||||
* `battery_full_cmd = notify-send "battery full"` : Command to execute when the battery is full.
|
* `battery_full_cmd = notify-send "battery full"` : Command to execute when the battery is full.
|
||||||
|
|
||||||
@@ -591,7 +604,7 @@ The action semantics:
|
|||||||
|
|
||||||
* `execp_icon_h = integer` : See `execp_icon_w`. *(since 0.12.4)*
|
* `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)*
|
* `execp_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]` : The font used to draw the text. *(since 0.12.4)*
|
||||||
|
|
||||||
|
|||||||
+26
-7
@@ -1,9 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
MAJOR=0.14
|
SCRIPT_DIR=$(dirname "$0")
|
||||||
DIRTY=""
|
DIRTY=""
|
||||||
|
VERSION=""
|
||||||
|
|
||||||
if git status 1>/dev/null 2>/dev/null
|
OLD_DIR=$(pwd)
|
||||||
|
cd ${SCRIPT_DIR}
|
||||||
|
|
||||||
|
if [ -d .git ] && git status 1>/dev/null 2>/dev/null
|
||||||
then
|
then
|
||||||
git update-index -q --ignore-submodules --refresh
|
git update-index -q --ignore-submodules --refresh
|
||||||
# Disallow unstaged changes in the working tree
|
# Disallow unstaged changes in the working tree
|
||||||
@@ -31,16 +35,31 @@ then
|
|||||||
DIRTY="-dirty"
|
DIRTY="-dirty"
|
||||||
fi
|
fi
|
||||||
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
|
if git describe 1>/dev/null 2>/dev/null
|
||||||
else
|
then
|
||||||
SCRIPT_DIR=$(dirname "$0")
|
VERSION=$(git describe 2>/dev/null)$DIRTY
|
||||||
VERSION=$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 2)
|
elif git log -n 1 1>/dev/null 2>/dev/null
|
||||||
|
then
|
||||||
|
VERSION=$(head -n 1 "ChangeLog" | cut -d ' ' -f 2)
|
||||||
if [ "$VERSION" = "master" ]
|
if [ "$VERSION" = "master" ]
|
||||||
then
|
then
|
||||||
VERSION=$VERSION-$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 1)
|
PREVIOUS=$(grep '^2' "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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "$VERSION" ]
|
||||||
|
then
|
||||||
|
VERSION=$(head -n 1 "ChangeLog" | cut -d ' ' -f 2)
|
||||||
|
if [ "$VERSION" = "master" ]
|
||||||
|
then
|
||||||
|
VERSION=$VERSION-$(head -n 1 "ChangeLog" | cut -d ' ' -f 1)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "${OLD_DIR}"
|
||||||
|
|
||||||
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
||||||
|
|
||||||
|
|||||||
+20
-15
@@ -76,19 +76,23 @@ def get_last_version():
|
|||||||
return tags[-1]
|
return tags[-1]
|
||||||
|
|
||||||
|
|
||||||
def inc_version(v, feature=False):
|
def inc_version(v, feature=False, tiny=False):
|
||||||
if v.startswith("v0."):
|
if v.startswith("v0."):
|
||||||
assert v == "v0.14.6"
|
assert v == "v0.14.6"
|
||||||
return "v15.0"
|
return "v15.0"
|
||||||
# v4.11 -> v4.12 or v5.0
|
# v4.11 -> v4.12 or v5.0 or v4.11.1
|
||||||
parts = v.split(".")
|
parts = v.split(".")
|
||||||
while len(parts) < 2:
|
while len(parts) < 3:
|
||||||
parts.append("0")
|
parts.append("0")
|
||||||
assert len(parts) == 2
|
assert len(parts) == 3
|
||||||
if feature:
|
if feature:
|
||||||
|
del parts[-1]
|
||||||
parts[-2] = "v" + str(int(parts[-2].replace("v", "")) + 1)
|
parts[-2] = "v" + str(int(parts[-2].replace("v", "")) + 1)
|
||||||
parts[-1] = "0"
|
parts[-1] = "0"
|
||||||
|
elif tiny:
|
||||||
|
parts[-1] = str(int(parts[-1]) + 1)
|
||||||
else:
|
else:
|
||||||
|
del parts[-1]
|
||||||
parts[-1] = str(int(parts[-1]) + 1)
|
parts[-1] = str(int(parts[-1]) + 1)
|
||||||
return ".".join([s for s in parts if s])
|
return ".".join([s for s in parts if s])
|
||||||
|
|
||||||
@@ -153,23 +157,14 @@ def update_log(path, version, date):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--feature", action="store_true")
|
parser.add_argument("--feature", action="store_true")
|
||||||
parser.add_argument("--undo", action="store_true")
|
parser.add_argument("--tiny", action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
logging.basicConfig(format=ansi_lblue + "%(asctime)s %(pathname)s %(levelname)s" + ansi_reset + " %(message)s", level=logging.DEBUG)
|
logging.basicConfig(format=ansi_lblue + "%(asctime)s %(pathname)s %(levelname)s" + ansi_reset + " %(message)s", level=logging.DEBUG)
|
||||||
test_inc_version()
|
test_inc_version()
|
||||||
# Read version from last tag and increment
|
# Read version from last tag and increment
|
||||||
old_version = get_last_version()
|
old_version = get_last_version()
|
||||||
if args.undo:
|
|
||||||
info("Revering last commit...")
|
|
||||||
run("git tag -d %s" % old_version)
|
|
||||||
run("git tag -d %s" % old_version.replace("v", ""))
|
|
||||||
run("git reset --soft HEAD~")
|
|
||||||
run("git reset")
|
|
||||||
run("git stash")
|
|
||||||
os.system("git log -1")
|
|
||||||
sys.exit(0)
|
|
||||||
info("Old version:", old_version)
|
info("Old version:", old_version)
|
||||||
version = inc_version(old_version, args.feature)
|
version = inc_version(old_version, args.feature, args.tiny)
|
||||||
readable_version = version.replace("v", "")
|
readable_version = version.replace("v", "")
|
||||||
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
info("New version:", readable_version, version, date)
|
info("New version:", readable_version, version, date)
|
||||||
@@ -190,3 +185,13 @@ if __name__ == '__main__':
|
|||||||
run("cd tint2-%s ; mkdir build ; cd build ; cmake .. ; make" % readable_version)
|
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)
|
assert_equal(run("./tint2-%s/build/tint2 -v" % readable_version).strip(), "tint2 version %s" % readable_version)
|
||||||
os.system("git log -p -1 --word-diff")
|
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))
|
||||||
|
sys.exit(1)
|
||||||
|
print "Publish? [y/n]"
|
||||||
|
choice = raw_input().lower()
|
||||||
|
if choice != "y":
|
||||||
|
sys.exit(1)
|
||||||
|
run("git push origin master && git push --tags origin master")
|
||||||
|
|||||||
+544
@@ -0,0 +1,544 @@
|
|||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
def check_c_compiles(cmd, code):
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.c') as f:
|
||||||
|
f.write(code)
|
||||||
|
f.flush()
|
||||||
|
cmd += [f.name, '-o', '/dev/null']
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
out, err = proc.communicate()
|
||||||
|
ret = proc.returncode
|
||||||
|
return ret == 0
|
||||||
|
|
||||||
|
|
||||||
|
def makedirs(path):
|
||||||
|
try:
|
||||||
|
os.makedirs(path)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.EEXIST and os.path.isdir(path):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def pkg_config(lib):
|
||||||
|
def _pkgconfig(lib, query):
|
||||||
|
lib = lib.replace('>=', ' >= ')
|
||||||
|
cmd = 'pkg-config {} {}'.format(query, lib).split()
|
||||||
|
popen = subprocess.Popen(cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
out, err = popen.communicate()
|
||||||
|
if popen.returncode != 0:
|
||||||
|
print(cmd)
|
||||||
|
print(err)
|
||||||
|
raise ValueError("Could not find library: {}".format(lib))
|
||||||
|
return out.split()
|
||||||
|
|
||||||
|
lf = _pkgconfig(lib, '--libs-only-l')
|
||||||
|
cf = _pkgconfig(lib, '--cflags')
|
||||||
|
ldf = _pkgconfig(lib, '--libs-only-L')
|
||||||
|
return (lf, cf, ldf)
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_escape(s):
|
||||||
|
s = s.replace(' ', '$ ')
|
||||||
|
s = s.replace('\n', '$\n')
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_join(words):
|
||||||
|
indent = ' '
|
||||||
|
if len(words) > 1:
|
||||||
|
prefix = '$\n' + indent
|
||||||
|
else:
|
||||||
|
prefix = ''
|
||||||
|
spacer = ' $\n' + indent
|
||||||
|
return prefix + spacer.join(ninja_escape(s) for s in words)
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_write_vars(f, **kwargs):
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
f.write('{} = {}\n'.format(k, v))
|
||||||
|
f.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_write_rule(f, name, **kwargs):
|
||||||
|
f.write('rule {}\n'.format(name))
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
f.write(' {} = {}\n'.format(k, v))
|
||||||
|
f.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
def remove_prefix(s, prefix):
|
||||||
|
while prefix and s.startswith(prefix):
|
||||||
|
s = s[len(prefix):]
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def install(prefix, suffix, dest_dir, dest_suffix=''):
|
||||||
|
src_path = os.path.join(prefix, suffix) if suffix else prefix
|
||||||
|
fname = os.path.basename(src_path)
|
||||||
|
if dest_suffix:
|
||||||
|
dest_dir = os.path.join(dest_dir, dest_suffix)
|
||||||
|
dst_path = os.path.join(dest_dir, fname)
|
||||||
|
return [(src_path, dst_path)]
|
||||||
|
|
||||||
|
|
||||||
|
def install_dir(prefix, suffix, dest_dir, dest_suffix=''):
|
||||||
|
result = []
|
||||||
|
src_path = os.path.join(prefix, suffix)
|
||||||
|
for root, dirs, files in os.walk(src_path):
|
||||||
|
for f in files:
|
||||||
|
fname = os.path.join(root, f)
|
||||||
|
fsuffix = remove_prefix(remove_prefix(fname, prefix), '/')
|
||||||
|
result += install(prefix, fsuffix, dest_dir, os.path.join(dest_suffix, os.path.dirname(fsuffix)))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class Executable(object):
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.cc = 'cc'
|
||||||
|
self.cflags = []
|
||||||
|
self.lflags = []
|
||||||
|
self.libs = []
|
||||||
|
self.sources = []
|
||||||
|
self.pos = []
|
||||||
|
self.install_exec = []
|
||||||
|
self.install_data = []
|
||||||
|
|
||||||
|
def write_ninja(self, f):
|
||||||
|
f.write('# Executable: {}\n'.format(self.name))
|
||||||
|
ninja_write_vars(f, **{
|
||||||
|
'cc_' + self.name: self.cc,
|
||||||
|
'cflags_' + self.name: ninja_join(self.cflags),
|
||||||
|
'lflags_' + self.name: ninja_join(self.lflags),
|
||||||
|
'libs_' + self.name: ninja_join(self.libs)})
|
||||||
|
ninja_write_rule(f, 'cc_' + self.name,
|
||||||
|
command='$cc_{} -MMD -MT $out -MF $out.d $cflags_{} -c $in -o $out'.format(self.name, self.name),
|
||||||
|
description='CC $out',
|
||||||
|
depfile='$out.d',
|
||||||
|
deps='gcc')
|
||||||
|
ninja_write_rule(f, 'link_' + self.name,
|
||||||
|
command='$cc_{} $lflags_{} -o $out $in $libs_{}'.format(self.name, self.name, self.name),
|
||||||
|
description='LINK $out')
|
||||||
|
ninja_write_rule(f, 'po2mo_' + self.name,
|
||||||
|
command='msgfmt -o $out $in',
|
||||||
|
description='GEN $out')
|
||||||
|
f.write('# Compilation\n')
|
||||||
|
for src in self.sources:
|
||||||
|
f.write('build $build_dir/{}.{}.o: cc_{} $source_dir/{}\n'.format(src, self.name, self.name, src))
|
||||||
|
f.write('# Translation\n')
|
||||||
|
for po in self.pos:
|
||||||
|
f.write('build $build_dir/{}.mo: po2mo_{} $source_dir/{}\n'.format(os.path.splitext(po)[0], self.name, po))
|
||||||
|
f.write('# Linking\n')
|
||||||
|
f.write('build $build_dir/{}: link_{} '.format(self.name, self.name))
|
||||||
|
f.write(ninja_join(['$build_dir/{}.{}.o'.format(src, self.name) for src in self.sources]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('# Installation\n')
|
||||||
|
for fin, fout in self.install_exec:
|
||||||
|
f.write('build {}: install_exec {}\n'.format(fout, fin))
|
||||||
|
for fin, fout in self.install_data:
|
||||||
|
f.write('build {}: install_data {}\n'.format(fout, fin))
|
||||||
|
f.write('build install_{}: phony '.format(self.name))
|
||||||
|
f.write(ninja_join([fout for fin, fout in self.install_exec + self.install_data]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('# Uninstallation\n')
|
||||||
|
for fin, fout in self.install_exec + self.install_data:
|
||||||
|
f.write('build uninstall_{}: uninstall {}\n'.format(fout, fout))
|
||||||
|
f.write('build uninstall_{}: phony '.format(self.name))
|
||||||
|
f.write(ninja_join(['uninstall_{}'.format(fout) for fin, fout in self.install_exec + self.install_data]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate_ninja(targets, source_dir, build_dir):
|
||||||
|
ninja_file_name = os.path.join(build_dir, 'build.ninja')
|
||||||
|
f = open(ninja_file_name, 'w')
|
||||||
|
# `deps` was introduced in ninja 1.3.
|
||||||
|
ninja_write_vars(f, ninja_required_version='1.3')
|
||||||
|
ninja_write_vars(f, **{
|
||||||
|
'source_dir':source_dir,
|
||||||
|
'build_dir':build_dir
|
||||||
|
})
|
||||||
|
ninja_write_rule(f, 'install_exec',
|
||||||
|
command='install -D -m0755 $in $out',
|
||||||
|
description='INSTALL $out')
|
||||||
|
ninja_write_rule(f, 'install_data',
|
||||||
|
command='install -D -m0644 $in $out',
|
||||||
|
description='INSTALL $out')
|
||||||
|
ninja_write_rule(f, 'uninstall',
|
||||||
|
command='rm -f $in',
|
||||||
|
description='RM $in')
|
||||||
|
for t in targets:
|
||||||
|
t.write_ninja(f)
|
||||||
|
f.write('# Targets\n')
|
||||||
|
f.write('build all: phony ')
|
||||||
|
f.write(ninja_join(['$build_dir/{}'.format(t.name) for t in targets]))
|
||||||
|
f.write('\n')
|
||||||
|
installs = sum([(t.install_exec + t.install_data) for t in targets], [])
|
||||||
|
if installs:
|
||||||
|
f.write('build install: phony ')
|
||||||
|
f.write(ninja_join(['install_{}'.format(t.name) for t in targets]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('build uninstall: phony ')
|
||||||
|
f.write(ninja_join(['uninstall_{}'.format(t.name) for t in targets]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('\n')
|
||||||
|
f.write('default all\n')
|
||||||
|
f.close()
|
||||||
|
print('Wrote {}.'.format(ninja_file_name))
|
||||||
|
print('Run `ninja -v -C {} all` to compile.'.format(build_dir))
|
||||||
|
print('Run `ninja -v -C {} install` to install.'.format(build_dir))
|
||||||
|
|
||||||
|
|
||||||
|
# Parse CLI options
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--uevent', dest='uevent', action='store_true',
|
||||||
|
help='Enable uevent support. Default: on under Linux')
|
||||||
|
parser.add_argument('--debug', dest='debug', action='store_true',
|
||||||
|
help='Enable debug build. Default: off')
|
||||||
|
parser.add_argument('--asan', dest='asan', action='store_true',
|
||||||
|
help='Enable AddressSanitizer. Default: off')
|
||||||
|
parser.add_argument('--tracing', dest='tracing', action='store_true',
|
||||||
|
help='Enable tracing. Default: off')
|
||||||
|
parser.add_argument('--memory-tracing', dest='memory_tracing', action='store_true',
|
||||||
|
help='Enable memory allocation tracing. Default: off')
|
||||||
|
parser.add_argument('--prefix', help='Prefix for constructing the file installation paths. Default: /usr/local', default=None)
|
||||||
|
parser.add_argument('--exec_prefix', help='Prefix for binary paths. Default: $prefix', default=None)
|
||||||
|
parser.add_argument('--bindir', help='Path where executables must be installed. Default: $exec_prefix/bin', default=None)
|
||||||
|
parser.add_argument('--sysconfdir', help='Path where config files must be installed. Default: /etc', default=None)
|
||||||
|
parser.add_argument('--datarootdir', help='Path where data files must be installed. Default: $prefix/share', default=None)
|
||||||
|
parser.add_argument('--localedir', help='Path where locale files must be installed. Default: $datarootdir/locale', default=None)
|
||||||
|
parser.add_argument('--docdir', help='Path where documentation files must be installed. Default: $datarootdir/doc/tint2', default=None)
|
||||||
|
parser.add_argument('--htmldir', help='Path where documentation files must be installed. Default: $docdir/html', default=None)
|
||||||
|
parser.add_argument('--mandir', help='Path where man files must be installed. Default: $datarootdir/man', default=None)
|
||||||
|
parser.add_argument('--home', dest='home', action='store_true',
|
||||||
|
help='Install to $HOME (sets all paths accordingly). Default: off')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Get relevant environment variables
|
||||||
|
CC = os.environ.get('CC', 'cc')
|
||||||
|
CFLAGS = shlex.split(os.environ.get('CFLAGS', ''))
|
||||||
|
LFLAGS = shlex.split(os.environ.get('LDFLAGS', ''))
|
||||||
|
LIBS = []
|
||||||
|
|
||||||
|
# Get paths
|
||||||
|
source_dir = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + '/..')
|
||||||
|
build_dir = os.path.join(os.getcwd(), 'build')
|
||||||
|
if not args.home:
|
||||||
|
prefix = args.prefix or '/usr/local'
|
||||||
|
exec_prefix = args.exec_prefix or prefix
|
||||||
|
bindir = args.bindir or os.path.join(exec_prefix, 'bin')
|
||||||
|
datarootdir = args.datarootdir or os.path.join(prefix, 'share')
|
||||||
|
sysconfdir = args.sysconfdir or '/etc'
|
||||||
|
docdir = args.docdir or os.path.join(datarootdir, 'doc/tint2')
|
||||||
|
htmldir = args.htmldir or os.path.join(docdir, 'html')
|
||||||
|
localedir = args.localedir or os.path.join(datarootdir, 'locale')
|
||||||
|
mandir = args.mandir or os.path.join(datarootdir, 'man')
|
||||||
|
else:
|
||||||
|
prefix = args.prefix or os.path.expanduser("~")
|
||||||
|
exec_prefix = args.exec_prefix or prefix
|
||||||
|
bindir = args.bindir or os.path.join(exec_prefix, 'bin')
|
||||||
|
datarootdir = args.datarootdir or os.path.join(prefix, '.local/share')
|
||||||
|
sysconfdir = args.sysconfdir or os.path.expanduser("~/.config/tint2")
|
||||||
|
docdir = args.docdir or os.path.join(datarootdir, 'doc/tint2')
|
||||||
|
htmldir = args.htmldir or os.path.join(docdir, 'html')
|
||||||
|
localedir = args.localedir or os.path.join(datarootdir, 'locale')
|
||||||
|
mandir = args.mandir or os.path.join(datarootdir, 'man')
|
||||||
|
|
||||||
|
|
||||||
|
# Check if C11 is supported by the compiler, fall back to C99
|
||||||
|
if check_c_compiles([CC],
|
||||||
|
'''#define print(x) _Generic((x), default : print_unknown)(x)
|
||||||
|
void print_unknown() {
|
||||||
|
}
|
||||||
|
int main () {
|
||||||
|
print(0);
|
||||||
|
}'''):
|
||||||
|
CFLAGS += ['-std=c11', '-DHAS_GENERIC']
|
||||||
|
else:
|
||||||
|
print("No C11 support.")
|
||||||
|
CFLAGS += ['-std=c99']
|
||||||
|
|
||||||
|
# Set mandatory flags
|
||||||
|
CFLAGS += ['-g',
|
||||||
|
'-Wall',
|
||||||
|
'-Wextra',
|
||||||
|
'-Wshadow',
|
||||||
|
'-Wpointer-arith',
|
||||||
|
'-Wno-deprecated',
|
||||||
|
'-Wno-missing-field-initializers',
|
||||||
|
'-Wno-unused-parameter',
|
||||||
|
'-Wno-sign-compare',
|
||||||
|
'-fno-strict-aliasing',
|
||||||
|
'-pthread',
|
||||||
|
'-D_BSD_SOURCE',
|
||||||
|
'-D_DEFAULT_SOURCE',
|
||||||
|
'-D_WITH_GETLINE',
|
||||||
|
'-DENABLE_BATTERY']
|
||||||
|
LFLAGS += ['-fno-strict-aliasing',
|
||||||
|
'-pthread']
|
||||||
|
LFLAGS += ['-L' + build_dir]
|
||||||
|
|
||||||
|
# Set platform dependent C flags
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
CFLAGS += ['-D_POSIX_C_SOURCE=200809L']
|
||||||
|
|
||||||
|
if sys.platform.startswith('freebsd') or sys.platform.startswith('openbsd') or sys.platform.startswith('dragonfly'):
|
||||||
|
CFLAGS += ['-I/usr/local/include']
|
||||||
|
LFLAGS += ['-L/usr/local/lib']
|
||||||
|
|
||||||
|
if sys.platform.startswith('linux') or args.uevent:
|
||||||
|
CFLAGS += ['-DENABLE_UEVENT']
|
||||||
|
|
||||||
|
# Turn on color messages if supported
|
||||||
|
if check_c_compiles([CC, '-fdiagnostics-color', '-c', '-x', 'c'], ''):
|
||||||
|
CFLAGS += ['-fdiagnostics-color=always']
|
||||||
|
|
||||||
|
# Set project-specific include dirs
|
||||||
|
CFLAGS += ['-I.']
|
||||||
|
for inc in ['src',
|
||||||
|
'src/battery',
|
||||||
|
'src/clock',
|
||||||
|
'src/systray',
|
||||||
|
'src/taskbar',
|
||||||
|
'src/launcher',
|
||||||
|
'src/tooltip',
|
||||||
|
'src/util',
|
||||||
|
'src/execplugin',
|
||||||
|
'src/button',
|
||||||
|
'src/freespace',
|
||||||
|
'src/separator']:
|
||||||
|
CFLAGS += ['-I' + os.path.join(source_dir, inc)]
|
||||||
|
|
||||||
|
# Add mandatory library dependencies
|
||||||
|
LIBS += ['-lm', '-lrt']
|
||||||
|
|
||||||
|
# Add mandatory libray dependencies detected with pkg-config
|
||||||
|
for dep in ['x11',
|
||||||
|
'xcomposite',
|
||||||
|
'xdamage',
|
||||||
|
'xinerama',
|
||||||
|
'xext',
|
||||||
|
'xrender',
|
||||||
|
'xrandr>=1.3',
|
||||||
|
'pangocairo',
|
||||||
|
'pango',
|
||||||
|
'cairo',
|
||||||
|
'glib-2.0',
|
||||||
|
'gobject-2.0',
|
||||||
|
'imlib2>=1.4.2']:
|
||||||
|
lib, cf, lf = pkg_config(dep)
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf
|
||||||
|
LFLAGS += lf
|
||||||
|
|
||||||
|
# Add optional library dependencies detected with pkg-config
|
||||||
|
try:
|
||||||
|
lib, cf, lf = pkg_config('librsvg-2.0>=2.14.0')
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf + ['-DHAVE_RSVG']
|
||||||
|
LFLAGS += lf
|
||||||
|
except:
|
||||||
|
print("No SVG support.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
lib, cf, lf = pkg_config('libstartup-notification-1.0>=0.12')
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf + ['-DHAVE_SN', '-DSN_API_NOT_YET_FROZEN']
|
||||||
|
LFLAGS += lf
|
||||||
|
except:
|
||||||
|
print("No startup notification support.")
|
||||||
|
|
||||||
|
# Add library dependencies detected with using successful compilation test
|
||||||
|
bt = False
|
||||||
|
if not bt:
|
||||||
|
try:
|
||||||
|
lib, cf, lf = pkg_config('libunwind')
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf + ['-DHAS_LIBUNWIND']
|
||||||
|
LFLAGS += lf
|
||||||
|
bt = True
|
||||||
|
print("Backtrace support via libunwind.")
|
||||||
|
except:
|
||||||
|
print("No backtrace support via libunwind.")
|
||||||
|
if not bt:
|
||||||
|
if check_c_compiles([CC, '-lbacktrace'], '''#include <backtrace.h>
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}'''):
|
||||||
|
CFLAGS += ['-DHAS_BACKTRACE']
|
||||||
|
LIBS += ['-lbacktrace']
|
||||||
|
bt = True
|
||||||
|
print("Backtrace support via libbacktrace.")
|
||||||
|
else:
|
||||||
|
print("No backtrace support via libbacktrace.")
|
||||||
|
|
||||||
|
# Add option-dependent flags
|
||||||
|
if not args.debug:
|
||||||
|
CFLAGS += ['-O2']
|
||||||
|
|
||||||
|
if args.asan:
|
||||||
|
asan_flags = ['-fsanitize=address']
|
||||||
|
CFLAGS += asan_flags
|
||||||
|
LFLAGS += asan_flags
|
||||||
|
|
||||||
|
if args.tracing:
|
||||||
|
CFLAGS += ['-finstrument-functions',
|
||||||
|
'-finstrument-functions-exclude-file-list=tracing.c',
|
||||||
|
'-finstrument-functions-exclude-function-list=get_time,gettime']
|
||||||
|
|
||||||
|
if args.asan or args.memory_tracing or args.tracing:
|
||||||
|
trace_flags = ['-O0',
|
||||||
|
'-fno-common',
|
||||||
|
'-fno-omit-frame-pointer',
|
||||||
|
'-rdynamic']
|
||||||
|
CFLAGS += trace_flags
|
||||||
|
LFLAGS += trace_flags + ['-fuse-ld=gold']
|
||||||
|
|
||||||
|
if args.memory_tracing:
|
||||||
|
LIBS += ['-ldl']
|
||||||
|
|
||||||
|
# Define targets
|
||||||
|
tint2 = Executable('tint2')
|
||||||
|
tint2.cflags += CFLAGS
|
||||||
|
tint2.lflags += LFLAGS
|
||||||
|
tint2.libs += LIBS
|
||||||
|
tint2.sources = ['src/config.c',
|
||||||
|
'src/panel.c',
|
||||||
|
'src/util/server.c',
|
||||||
|
'src/main.c',
|
||||||
|
'src/init.c',
|
||||||
|
'src/util/signals.c',
|
||||||
|
'src/util/tracing.c',
|
||||||
|
'src/mouse_actions.c',
|
||||||
|
'src/drag_and_drop.c',
|
||||||
|
'src/default_icon.c',
|
||||||
|
'src/clock/clock.c',
|
||||||
|
'src/systray/systraybar.c',
|
||||||
|
'src/launcher/launcher.c',
|
||||||
|
'src/launcher/apps-common.c',
|
||||||
|
'src/launcher/icon-theme-common.c',
|
||||||
|
'src/launcher/xsettings-client.c',
|
||||||
|
'src/launcher/xsettings-common.c',
|
||||||
|
'src/taskbar/task.c',
|
||||||
|
'src/taskbar/taskbar.c',
|
||||||
|
'src/taskbar/taskbarname.c',
|
||||||
|
'src/tooltip/tooltip.c',
|
||||||
|
'src/execplugin/execplugin.c',
|
||||||
|
'src/button/button.c',
|
||||||
|
'src/freespace/freespace.c',
|
||||||
|
'src/separator/separator.c',
|
||||||
|
'src/tint2rc.c',
|
||||||
|
'src/util/area.c',
|
||||||
|
'src/util/bt.c',
|
||||||
|
'src/util/common.c',
|
||||||
|
'src/util/fps_distribution.c',
|
||||||
|
'src/util/strnatcmp.c',
|
||||||
|
'src/util/timer.c',
|
||||||
|
'src/util/cache.c',
|
||||||
|
'src/util/color.c',
|
||||||
|
'src/util/strlcat.c',
|
||||||
|
'src/util/print.c',
|
||||||
|
'src/util/gradient.c',
|
||||||
|
'src/util/test.c',
|
||||||
|
'src/util/uevent.c',
|
||||||
|
'src/util/window.c',
|
||||||
|
'src/battery/battery.c']
|
||||||
|
|
||||||
|
# Battery implementation is platform-specific
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
tint2.sources += ['src/battery/linux.c']
|
||||||
|
elif sys.platform.startswith('freebsd') or \
|
||||||
|
sys.platform.startswith('dragonfly') or \
|
||||||
|
sys.platform.startswith('gnukfreebsd'):
|
||||||
|
tint2.sources += ['src/battery/freebsd.c']
|
||||||
|
elif sys.platform.startswith('openbsd') or \
|
||||||
|
sys.platform.startswith('netbsd'):
|
||||||
|
tint2.sources += ['src/battery/openbsd.c']
|
||||||
|
else:
|
||||||
|
print("No battery support for platform:", sys.platform)
|
||||||
|
tint2.sources += ['src/battery/dummy.c']
|
||||||
|
|
||||||
|
if args.memory_tracing:
|
||||||
|
tint2.sources += ['src/util/mem.c']
|
||||||
|
|
||||||
|
tint2.install_exec = install(build_dir, 'tint2', bindir)
|
||||||
|
tint2.install_data = (install(source_dir, 'tint2.svg', datarootdir, 'icons/hicolor/scalable/apps') +
|
||||||
|
install(source_dir, 'tint2.desktop', datarootdir, 'applications') +
|
||||||
|
install(source_dir, 'themes/tint2rc', sysconfdir, 'xdg/tint2') +
|
||||||
|
install(source_dir, 'default_icon.png', datarootdir, 'tint2') +
|
||||||
|
install(source_dir, 'AUTHORS', docdir) +
|
||||||
|
install(source_dir, 'ChangeLog', docdir) +
|
||||||
|
install(source_dir, 'README.md', docdir) +
|
||||||
|
install(source_dir, 'doc/tint2.md', docdir) +
|
||||||
|
install(source_dir, 'doc/manual.html', htmldir) +
|
||||||
|
install(source_dir, 'doc/readme.html', htmldir) +
|
||||||
|
install_dir(source_dir, 'doc/images', htmldir) +
|
||||||
|
install(source_dir, 'doc/tint2.1', mandir, 'man1'))
|
||||||
|
|
||||||
|
tint2conf = Executable('tint2conf')
|
||||||
|
tint2conf.cflags += CFLAGS
|
||||||
|
tint2conf.lflags += LFLAGS
|
||||||
|
tint2conf.libs += LIBS
|
||||||
|
|
||||||
|
for dep in ['gthread-2.0',
|
||||||
|
'gtk+-x11-2.0']:
|
||||||
|
lib, cf, lf = pkg_config(dep)
|
||||||
|
tint2conf.libs += lib
|
||||||
|
tint2conf.cflags += cf
|
||||||
|
tint2conf.lflags += lf
|
||||||
|
|
||||||
|
tint2conf.cflags += ['-DTINT2CONF',
|
||||||
|
'-DINSTALL_PREFIX=\\"{}\\"'.format(prefix),
|
||||||
|
'-DLOCALEDIR=\\"{}\\"'.format(localedir),
|
||||||
|
'-DGETTEXT_PACKAGE=\\"tint2conf\\"',
|
||||||
|
'-DHAVE_VERSION_H',
|
||||||
|
'-Wno-shadow']
|
||||||
|
|
||||||
|
tint2conf.sources = ['src/util/bt.c',
|
||||||
|
'src/util/common.c',
|
||||||
|
'src/util/strnatcmp.c',
|
||||||
|
'src/util/cache.c',
|
||||||
|
'src/util/timer.c',
|
||||||
|
'src/util/test.c',
|
||||||
|
'src/util/print.c',
|
||||||
|
'src/util/signals.c',
|
||||||
|
'src/config.c',
|
||||||
|
'src/util/server.c',
|
||||||
|
'src/util/strlcat.c',
|
||||||
|
'src/launcher/apps-common.c',
|
||||||
|
'src/launcher/icon-theme-common.c',
|
||||||
|
'src/tint2conf/md4.c',
|
||||||
|
'src/tint2conf/main.c',
|
||||||
|
'src/tint2conf/properties.c',
|
||||||
|
'src/tint2conf/properties_rw.c',
|
||||||
|
'src/tint2conf/theme_view.c',
|
||||||
|
'src/tint2conf/background_gui.c',
|
||||||
|
'src/tint2conf/gradient_gui.c']
|
||||||
|
tint2conf.pos = [os.path.join('src/tint2conf/po', f) for f in os.listdir('src/tint2conf/po') if f.endswith('.po')]
|
||||||
|
tint2conf.install_exec = install(build_dir, 'tint2conf', bindir)
|
||||||
|
tint2conf.install_data = (install(source_dir, 'src/tint2conf/tint2conf.svg', datarootdir, 'icons/hicolor/scalable/apps') +
|
||||||
|
install(source_dir, 'src/tint2conf/tint2conf.desktop', datarootdir, 'applications') +
|
||||||
|
install(source_dir, 'src/tint2conf/tint2conf.xml', datarootdir, 'mime/packages'))
|
||||||
|
|
||||||
|
makedirs(build_dir)
|
||||||
|
assert 0 == os.system('cd {}; {}/get_version.sh'.format(build_dir, source_dir))
|
||||||
|
generate_ninja([tint2, tint2conf], source_dir, build_dir)
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
dh $@
|
dh $@
|
||||||
|
|
||||||
override_dh_auto_configure:
|
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:
|
override_dh_auto_install:
|
||||||
dh_auto_install --destdir=$(CURDIR)/debian/tmp
|
dh_auto_install --destdir=$(CURDIR)/debian/tmp
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm -f version.h
|
rm -f version.h
|
||||||
VERSION=$(git describe --exact-match 2>/dev/null)
|
VERSION=$(false 2>/dev/null)
|
||||||
if [ $? -eq 0 ]
|
if [ $? -eq 0 ]
|
||||||
then
|
then
|
||||||
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
||||||
@@ -49,7 +49,7 @@ echo "echo \"#define VERSION_STRING \\\"$VERSION\\\"\" > version.h" > $DIR/get_v
|
|||||||
# Copy the debian files into the source directory
|
# Copy the debian files into the source directory
|
||||||
cp -r debian $DIR/debian
|
cp -r debian $DIR/debian
|
||||||
|
|
||||||
for DISTRO in trusty xenial zesty artful
|
for DISTRO in trusty xenial artful bionic
|
||||||
do
|
do
|
||||||
# Cleanup from previous builds
|
# Cleanup from previous builds
|
||||||
rm -rf tint2_$VERSION-*
|
rm -rf tint2_$VERSION-*
|
||||||
|
|||||||
Executable
+23
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
timeout -k 10 600 ~/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
|
||||||
@@ -161,12 +161,14 @@ def get_debian_release_version(release):
|
|||||||
|
|
||||||
|
|
||||||
def get_debian_versions():
|
def get_debian_versions():
|
||||||
|
print >> sys.stderr, "Debian ..."
|
||||||
return "Debian", "debian", [get_debian_release_version(release) for release in ["stable", "testing", "unstable", "experimental"]]
|
return "Debian", "debian", [get_debian_release_version(release) for release in ["stable", "testing", "unstable", "experimental"]]
|
||||||
|
|
||||||
|
|
||||||
# Ubuntu
|
# Ubuntu
|
||||||
|
|
||||||
def get_ubuntu_versions():
|
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 = 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 = json.loads(data)["entries"]
|
||||||
data.reverse()
|
data.reverse()
|
||||||
@@ -183,6 +185,7 @@ def get_ubuntu_versions():
|
|||||||
# BunsenLabs
|
# BunsenLabs
|
||||||
|
|
||||||
def get_bunsenlabs_versions():
|
def get_bunsenlabs_versions():
|
||||||
|
print >> sys.stderr, "BunsenLabs ..."
|
||||||
dirs = http_list_dir("https://eu.pkg.bunsenlabs.org/debian/dists/")
|
dirs = http_list_dir("https://eu.pkg.bunsenlabs.org/debian/dists/")
|
||||||
versions = []
|
versions = []
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
@@ -198,6 +201,7 @@ def get_bunsenlabs_versions():
|
|||||||
# Arch
|
# Arch
|
||||||
|
|
||||||
def get_arch_versions():
|
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")
|
pkgbuild = http_download_txt("https://git.archlinux.org/svntogit/community.git/plain/trunk/PKGBUILD?h=packages/tint2")
|
||||||
version, maintainer = arch_pkgbuild_extract_version(pkgbuild)
|
version, maintainer = arch_pkgbuild_extract_version(pkgbuild)
|
||||||
return "Arch Linux", "archlinux", [("Community", version, maintainer)]
|
return "Arch Linux", "archlinux", [("Community", version, maintainer)]
|
||||||
@@ -206,6 +210,7 @@ def get_arch_versions():
|
|||||||
# Fedora
|
# Fedora
|
||||||
|
|
||||||
def get_fedora_versions():
|
def get_fedora_versions():
|
||||||
|
print >> sys.stderr, "Fedora ..."
|
||||||
dirs = http_list_dir("http://mirror.switch.ch/ftp/mirror/fedora/linux/development/")
|
dirs = http_list_dir("http://mirror.switch.ch/ftp/mirror/fedora/linux/development/")
|
||||||
versions = []
|
versions = []
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
@@ -224,6 +229,7 @@ def get_fedora_versions():
|
|||||||
# Red Hat (EPEL)
|
# Red Hat (EPEL)
|
||||||
|
|
||||||
def get_redhat_epel_versions():
|
def get_redhat_epel_versions():
|
||||||
|
print >> sys.stderr, "RedHat ..."
|
||||||
dirs = http_list_dir("http://mirror.switch.ch/ftp/mirror/epel/")
|
dirs = http_list_dir("http://mirror.switch.ch/ftp/mirror/epel/")
|
||||||
versions = []
|
versions = []
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
@@ -242,12 +248,13 @@ def get_redhat_epel_versions():
|
|||||||
# SUSE
|
# SUSE
|
||||||
|
|
||||||
def get_suse_versions():
|
def get_suse_versions():
|
||||||
|
print >> sys.stderr, "Suse ..."
|
||||||
ftp = ftplib.FTP("mirror.switch.ch")
|
ftp = ftplib.FTP("mirror.switch.ch")
|
||||||
ftp.login()
|
ftp.login()
|
||||||
releases, _ = ftp_list_dir(ftp, "/mirror/opensuse/opensuse/distribution/leap/")
|
releases, _ = ftp_list_dir(ftp, "/mirror/opensuse/opensuse/ports/update/leap/")
|
||||||
versions = []
|
versions = []
|
||||||
for release in releases:
|
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)
|
_, files = ftp_list_dir(ftp, root)
|
||||||
for fname in files:
|
for fname in files:
|
||||||
if fname.endswith("-primary.xml.gz"):
|
if fname.endswith("-primary.xml.gz"):
|
||||||
@@ -266,6 +273,7 @@ def get_suse_versions():
|
|||||||
# Gentoo
|
# Gentoo
|
||||||
|
|
||||||
def get_gentoo_versions():
|
def get_gentoo_versions():
|
||||||
|
print >> sys.stderr, "Gentoo ..."
|
||||||
files = http_list_dir("https://gitweb.gentoo.org/repo/gentoo.git/tree/x11-misc/tint2")
|
files = http_list_dir("https://gitweb.gentoo.org/repo/gentoo.git/tree/x11-misc/tint2")
|
||||||
versions = []
|
versions = []
|
||||||
for f in files:
|
for f in files:
|
||||||
@@ -280,7 +288,8 @@ def get_gentoo_versions():
|
|||||||
# Void
|
# Void
|
||||||
|
|
||||||
def get_void_versions():
|
def get_void_versions():
|
||||||
template = http_download_txt("https://raw.githubusercontent.com/voidlinux/void-packages/master/srcpkgs/tint2/template")
|
print >> sys.stderr, "Void ..."
|
||||||
|
template = http_download_txt("https://raw.githubusercontent.com/void-linux/void-packages/master/srcpkgs/tint2/template")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
maintainer = None
|
maintainer = None
|
||||||
@@ -297,6 +306,7 @@ def get_void_versions():
|
|||||||
# Alpine
|
# Alpine
|
||||||
|
|
||||||
def get_alpine_versions():
|
def get_alpine_versions():
|
||||||
|
print >> sys.stderr, "Alpine ..."
|
||||||
apkbuild = http_download_txt("https://git.alpinelinux.org/cgit/aports/plain/community/tint2/APKBUILD")
|
apkbuild = http_download_txt("https://git.alpinelinux.org/cgit/aports/plain/community/tint2/APKBUILD")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
@@ -314,6 +324,7 @@ def get_alpine_versions():
|
|||||||
# Slackware
|
# Slackware
|
||||||
|
|
||||||
def get_slack_versions():
|
def get_slack_versions():
|
||||||
|
print >> sys.stderr, "Slackware ..."
|
||||||
dirs = http_list_dir("https://slackbuilds.org/slackbuilds/")
|
dirs = http_list_dir("https://slackbuilds.org/slackbuilds/")
|
||||||
versions = []
|
versions = []
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
@@ -337,6 +348,7 @@ def get_slack_versions():
|
|||||||
# FreeBSD
|
# FreeBSD
|
||||||
|
|
||||||
def get_freebsd_versions():
|
def get_freebsd_versions():
|
||||||
|
print >> sys.stderr, "FreeBSD ..."
|
||||||
makefile = http_download_txt("https://svnweb.freebsd.org/ports/head/x11/tint/Makefile?view=co")
|
makefile = http_download_txt("https://svnweb.freebsd.org/ports/head/x11/tint/Makefile?view=co")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
@@ -354,7 +366,8 @@ def get_freebsd_versions():
|
|||||||
# OpenBSD
|
# OpenBSD
|
||||||
|
|
||||||
def get_openbsd_versions():
|
def get_openbsd_versions():
|
||||||
makefile = http_download_txt("http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/ports/x11/tint2/Makefile?rev=1.5&content-type=text/plain")
|
print >> sys.stderr, "OpenBSD ..."
|
||||||
|
makefile = http_download_txt("http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/ports/x11/tint2/Makefile?content-type=text/plain")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
for line in makefile.split("\n"):
|
for line in makefile.split("\n"):
|
||||||
@@ -368,6 +381,7 @@ def get_openbsd_versions():
|
|||||||
# Upstream
|
# Upstream
|
||||||
|
|
||||||
def get_tint2_version():
|
def get_tint2_version():
|
||||||
|
print >> sys.stderr, "Upstream ..."
|
||||||
readme = http_download_txt("https://gitlab.com/o9000/tint2/raw/master/README.md")
|
readme = http_download_txt("https://gitlab.com/o9000/tint2/raw/master/README.md")
|
||||||
version = readme.split("\n", 1)[0].split(":", 1)[-1].strip()
|
version = readme.split("\n", 1)[0].split(":", 1)[-1].strip()
|
||||||
return version
|
return version
|
||||||
@@ -381,7 +395,7 @@ def main():
|
|||||||
distros.append(get_ubuntu_versions())
|
distros.append(get_ubuntu_versions())
|
||||||
distros.append(get_fedora_versions())
|
distros.append(get_fedora_versions())
|
||||||
distros.append(get_redhat_epel_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_alpine_versions())
|
||||||
distros.append(get_slack_versions())
|
distros.append(get_slack_versions())
|
||||||
distros.append(get_arch_versions())
|
distros.append(get_arch_versions())
|
||||||
|
|||||||
+73
-8
@@ -41,7 +41,8 @@ struct BatteryState battery_state;
|
|||||||
gboolean battery_enabled;
|
gboolean battery_enabled;
|
||||||
gboolean battery_tooltip_enabled;
|
gboolean battery_tooltip_enabled;
|
||||||
int percentage_hide;
|
int percentage_hide;
|
||||||
static timeout *battery_timeout;
|
static Timer battery_timer;
|
||||||
|
static Timer battery_blink_timer;
|
||||||
|
|
||||||
#define BATTERY_BUF_SIZE 256
|
#define BATTERY_BUF_SIZE 256
|
||||||
static char buf_bat_line1[BATTERY_BUF_SIZE];
|
static char buf_bat_line1[BATTERY_BUF_SIZE];
|
||||||
@@ -60,6 +61,9 @@ char *battery_rclick_command;
|
|||||||
char *battery_uwheel_command;
|
char *battery_uwheel_command;
|
||||||
char *battery_dwheel_command;
|
char *battery_dwheel_command;
|
||||||
gboolean battery_found;
|
gboolean battery_found;
|
||||||
|
gboolean battery_warn;
|
||||||
|
gboolean battery_warn_red;
|
||||||
|
Background *battery_warn_bg;
|
||||||
|
|
||||||
char *battery_sys_prefix = (char *)"";
|
char *battery_sys_prefix = (char *)"";
|
||||||
|
|
||||||
@@ -76,7 +80,11 @@ void default_battery()
|
|||||||
percentage_hide = 101;
|
percentage_hide = 101;
|
||||||
battery_low_cmd_sent = FALSE;
|
battery_low_cmd_sent = FALSE;
|
||||||
battery_full_cmd_sent = FALSE;
|
battery_full_cmd_sent = FALSE;
|
||||||
battery_timeout = NULL;
|
INIT_TIMER(battery_timer);
|
||||||
|
INIT_TIMER(battery_blink_timer);
|
||||||
|
battery_warn = FALSE;
|
||||||
|
battery_warn_red = FALSE;
|
||||||
|
battery_warn_bg = NULL;
|
||||||
bat1_has_font = FALSE;
|
bat1_has_font = FALSE;
|
||||||
bat1_font_desc = NULL;
|
bat1_font_desc = NULL;
|
||||||
bat1_format = NULL;
|
bat1_format = NULL;
|
||||||
@@ -127,9 +135,10 @@ void cleanup_battery()
|
|||||||
ac_connected_cmd = NULL;
|
ac_connected_cmd = NULL;
|
||||||
free(ac_disconnected_cmd);
|
free(ac_disconnected_cmd);
|
||||||
ac_disconnected_cmd = NULL;
|
ac_disconnected_cmd = NULL;
|
||||||
stop_timeout(battery_timeout);
|
destroy_timer(&battery_timer);
|
||||||
battery_timeout = NULL;
|
destroy_timer(&battery_blink_timer);
|
||||||
battery_found = FALSE;
|
battery_found = FALSE;
|
||||||
|
free_and_null(battery_warn_bg);
|
||||||
|
|
||||||
battery_os_free();
|
battery_os_free();
|
||||||
}
|
}
|
||||||
@@ -197,7 +206,7 @@ void battery_update_text(char *dest, char *format)
|
|||||||
if (battery_state.state == BATTERY_FULL) {
|
if (battery_state.state == BATTERY_FULL) {
|
||||||
snprintf(buf, sizeof(buf), "Full");
|
snprintf(buf, sizeof(buf), "Full");
|
||||||
strnappend(dest, buf, BATTERY_BUF_SIZE);
|
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);
|
snprintf(buf, sizeof(buf), "%02d:%02d", battery_state.time.hours, battery_state.time.minutes);
|
||||||
strnappend(dest, buf, BATTERY_BUF_SIZE);
|
strnappend(dest, buf, BATTERY_BUF_SIZE);
|
||||||
}
|
}
|
||||||
@@ -226,7 +235,8 @@ void init_battery()
|
|||||||
|
|
||||||
battery_found = battery_os_init();
|
battery_found = battery_os_init();
|
||||||
|
|
||||||
battery_timeout = add_timeout(10, 30000, update_battery_tick, 0, &battery_timeout);
|
if (!battery_timer.enabled_)
|
||||||
|
change_timer(&battery_timer, true, 30000, 30000, update_battery_tick, 0);
|
||||||
|
|
||||||
update_battery();
|
update_battery();
|
||||||
}
|
}
|
||||||
@@ -273,6 +283,7 @@ void init_battery_panel(void *p)
|
|||||||
bat1_format = strdup("%p");
|
bat1_format = strdup("%p");
|
||||||
bat2_format = strdup("%t");
|
bat2_format = strdup("%t");
|
||||||
}
|
}
|
||||||
|
update_battery_tick(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_init_fonts()
|
void battery_init_fonts()
|
||||||
@@ -309,6 +320,40 @@ void battery_default_font_changed()
|
|||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void blink_battery(void *arg)
|
||||||
|
{
|
||||||
|
if (!battery_enabled)
|
||||||
|
return;
|
||||||
|
battery_warn_red = battery_warn ? !battery_warn_red : FALSE;
|
||||||
|
if (battery_warn_red && !battery_warn_bg) {
|
||||||
|
battery_warn_bg = calloc(1, sizeof(*battery_warn_bg));
|
||||||
|
*battery_warn_bg = *panel_config.battery.area.bg;
|
||||||
|
battery_warn_bg->fill_color.alpha = 1.0;
|
||||||
|
battery_warn_bg->border.color.alpha = 1.0;
|
||||||
|
}
|
||||||
|
if (battery_warn_red) {
|
||||||
|
battery_warn_bg->fill_color.rgb[0] = 0.6;
|
||||||
|
battery_warn_bg->fill_color.rgb[1] = 0.1;
|
||||||
|
battery_warn_bg->fill_color.rgb[2] = 0.1;
|
||||||
|
battery_warn_bg->border.color.rgb[0] = 0.5;
|
||||||
|
battery_warn_bg->border.color.rgb[1] = 0.0;
|
||||||
|
battery_warn_bg->border.color.rgb[2] = 0.0;
|
||||||
|
} else {
|
||||||
|
battery_warn_bg->fill_color.rgb[0] = 0.9;
|
||||||
|
battery_warn_bg->fill_color.rgb[1] = 0.7;
|
||||||
|
battery_warn_bg->fill_color.rgb[2] = 0.1;
|
||||||
|
battery_warn_bg->border.color.rgb[0] = 0.7;
|
||||||
|
battery_warn_bg->border.color.rgb[1] = 0.5;
|
||||||
|
battery_warn_bg->border.color.rgb[2] = 0.1;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < num_panels; i++) {
|
||||||
|
if (panels[i].battery.area.on_screen) {
|
||||||
|
panels[i].battery.area.bg = battery_warn_bg;
|
||||||
|
schedule_redraw(&panels[i].battery.area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void update_battery_tick(void *arg)
|
void update_battery_tick(void *arg)
|
||||||
{
|
{
|
||||||
if (!battery_enabled)
|
if (!battery_enabled)
|
||||||
@@ -319,6 +364,7 @@ void update_battery_tick(void *arg)
|
|||||||
gboolean old_ac_connected = battery_state.ac_connected;
|
gboolean old_ac_connected = battery_state.ac_connected;
|
||||||
int16_t old_hours = battery_state.time.hours;
|
int16_t old_hours = battery_state.time.hours;
|
||||||
int8_t old_minutes = battery_state.time.minutes;
|
int8_t old_minutes = battery_state.time.minutes;
|
||||||
|
gboolean old_warn = battery_warn;
|
||||||
|
|
||||||
if (!battery_found) {
|
if (!battery_found) {
|
||||||
init_battery();
|
init_battery();
|
||||||
@@ -356,6 +402,20 @@ void update_battery_tick(void *arg)
|
|||||||
battery_full_cmd_sent = FALSE;
|
battery_full_cmd_sent = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!battery_blink_timer.enabled_) {
|
||||||
|
if (battery_state.percentage < battery_low_status &&
|
||||||
|
battery_state.state == BATTERY_DISCHARGING) {
|
||||||
|
change_timer(&battery_blink_timer, true, 10, 1000, blink_battery, 0);
|
||||||
|
battery_warn = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (battery_state.percentage > battery_low_status ||
|
||||||
|
battery_state.state != BATTERY_DISCHARGING) {
|
||||||
|
stop_timer(&battery_blink_timer);
|
||||||
|
battery_warn = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
// Show/hide if needed
|
// Show/hide if needed
|
||||||
if (!battery_found) {
|
if (!battery_found) {
|
||||||
@@ -369,8 +429,11 @@ void update_battery_tick(void *arg)
|
|||||||
// Redraw if needed
|
// Redraw if needed
|
||||||
if (panels[i].battery.area.on_screen) {
|
if (panels[i].battery.area.on_screen) {
|
||||||
if (old_found != battery_found || old_percentage != battery_state.percentage ||
|
if (old_found != battery_found || old_percentage != battery_state.percentage ||
|
||||||
old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes) {
|
old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes ||
|
||||||
|
old_warn != battery_warn) {
|
||||||
panels[i].battery.area.resize_needed = TRUE;
|
panels[i].battery.area.resize_needed = TRUE;
|
||||||
|
if (!battery_warn)
|
||||||
|
panels[i].battery.area.bg = panel_config.battery.area.bg;
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -421,6 +484,7 @@ gboolean resize_battery(void *obj)
|
|||||||
void draw_battery(void *obj, cairo_t *c)
|
void draw_battery(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Battery *battery = (Battery *)obj;
|
Battery *battery = (Battery *)obj;
|
||||||
|
Panel *panel = (Panel *)battery->area.panel;
|
||||||
draw_text_area(&battery->area,
|
draw_text_area(&battery->area,
|
||||||
c,
|
c,
|
||||||
buf_bat_line1,
|
buf_bat_line1,
|
||||||
@@ -429,7 +493,8 @@ void draw_battery(void *obj, cairo_t *c)
|
|||||||
bat2_font_desc,
|
bat2_font_desc,
|
||||||
battery->bat1_posy,
|
battery->bat1_posy,
|
||||||
battery->bat2_posy,
|
battery->bat2_posy,
|
||||||
&battery->font_color);
|
&battery->font_color,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_dump_geometry(void *obj, int indent)
|
void battery_dump_geometry(void *obj, int indent)
|
||||||
|
|||||||
+31
-15
@@ -60,6 +60,20 @@ struct psy_mains {
|
|||||||
gboolean online;
|
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()
|
static void uevent_battery_update()
|
||||||
{
|
{
|
||||||
update_battery_tick(NULL);
|
update_battery_tick(NULL);
|
||||||
@@ -96,12 +110,13 @@ static enum psy_type power_supply_get_type(const gchar *entryname)
|
|||||||
gsize typelen;
|
gsize typelen;
|
||||||
|
|
||||||
g_file_get_contents(path_type, &type, &typelen, &error);
|
g_file_get_contents(path_type, &type, &typelen, &error);
|
||||||
g_free(path_type);
|
|
||||||
if (error) {
|
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);
|
g_error_free(error);
|
||||||
return PSY_UNKNOWN;
|
return PSY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
g_free(path_type);
|
||||||
|
|
||||||
if (!g_strcmp0(type, "Battery\n")) {
|
if (!g_strcmp0(type, "Battery\n")) {
|
||||||
g_free(type);
|
g_free(type);
|
||||||
@@ -123,8 +138,8 @@ static gboolean init_linux_battery(struct psy_battery *bat)
|
|||||||
const gchar *entryname = bat->name;
|
const gchar *entryname = bat->name;
|
||||||
|
|
||||||
bat->path_present = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "present", NULL);
|
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)) {
|
if (!is_file_non_empty(bat->path_present)) {
|
||||||
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__, bat->path_present);
|
||||||
goto err0;
|
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->path_rate_now = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "power_now", NULL);
|
||||||
bat->unit = 'W';
|
bat->unit = 'W';
|
||||||
|
|
||||||
if (!g_file_test(bat->path_level_now, G_FILE_TEST_EXISTS) ||
|
if (!is_file_non_empty(bat->path_level_now) ||
|
||||||
!g_file_test(bat->path_level_full, G_FILE_TEST_EXISTS) ||
|
!is_file_non_empty(bat->path_level_full)) {
|
||||||
!g_file_test(bat->path_rate_now, G_FILE_TEST_EXISTS)) {
|
|
||||||
g_free(bat->path_level_now);
|
g_free(bat->path_level_now);
|
||||||
g_free(bat->path_level_full);
|
g_free(bat->path_level_full);
|
||||||
g_free(bat->path_rate_now);
|
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);
|
g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "current_now", NULL);
|
||||||
bat->unit = 'A';
|
bat->unit = 'A';
|
||||||
}
|
}
|
||||||
if (!g_file_test(bat->path_level_now, G_FILE_TEST_EXISTS) ||
|
if (!is_file_non_empty(bat->path_level_now)) {
|
||||||
!g_file_test(bat->path_level_full, G_FILE_TEST_EXISTS) ||
|
fprintf(stderr, RED "tint2: %s:%d: read failed for %s" RESET "\n", __FILE__, __LINE__, bat->path_level_now);
|
||||||
!g_file_test(bat->path_rate_now, G_FILE_TEST_EXISTS)) {
|
goto err1;
|
||||||
fprintf(stderr, RED "tint2: %s:%d: read failed" RESET "\n", __FILE__, __LINE__);
|
}
|
||||||
|
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;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bat->path_status = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "status", NULL);
|
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)) {
|
if (!is_file_non_empty(bat->path_status)) {
|
||||||
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__, bat->path_status);
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +197,8 @@ static gboolean init_linux_mains(struct psy_mains *ac)
|
|||||||
const gchar *entryname = ac->name;
|
const gchar *entryname = ac->name;
|
||||||
|
|
||||||
ac->path_online = g_build_filename(battery_sys_prefix, "/sys/class/power_supply", entryname, "online", NULL);
|
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)) {
|
if (!is_file_non_empty(ac->path_online)) {
|
||||||
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__, ac->path_online);
|
||||||
g_free(ac->path_online);
|
g_free(ac->path_online);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-31
@@ -52,11 +52,9 @@ void destroy_button(void *obj)
|
|||||||
Button *button = (Button *)obj;
|
Button *button = (Button *)obj;
|
||||||
if (button->frontend) {
|
if (button->frontend) {
|
||||||
// This is a frontend element
|
// This is a frontend element
|
||||||
if (button->frontend->icon) {
|
free_icon(button->frontend->icon);
|
||||||
imlib_context_set_image(button->frontend->icon);
|
free_icon(button->frontend->icon_hover);
|
||||||
imlib_free_image();
|
free_icon(button->frontend->icon_pressed);
|
||||||
button->frontend->icon = NULL;
|
|
||||||
}
|
|
||||||
button->backend->instances = g_list_remove_all(button->backend->instances, button);
|
button->backend->instances = g_list_remove_all(button->backend->instances, button);
|
||||||
free_and_null(button->frontend);
|
free_and_null(button->frontend);
|
||||||
remove_area(&button->area);
|
remove_area(&button->area);
|
||||||
@@ -79,7 +77,7 @@ void destroy_button(void *obj)
|
|||||||
|
|
||||||
if (button->backend->instances) {
|
if (button->backend->instances) {
|
||||||
fprintf(stderr, "tint2: Error: Attempt to destroy backend while there are still frontend instances!\n");
|
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->backend);
|
||||||
free(button);
|
free(button);
|
||||||
@@ -271,9 +269,9 @@ int button_compute_desired_size(void *obj)
|
|||||||
{
|
{
|
||||||
Button *button = (Button *)obj;
|
Button *button = (Button *)obj;
|
||||||
Panel *panel = (Panel *)button->area.panel;
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy);
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy) * panel->scale;
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
||||||
int interior_padding = button->area.paddingx;
|
int interior_padding = button->area.paddingx * panel->scale;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -282,18 +280,17 @@ int button_compute_desired_size(void *obj)
|
|||||||
else
|
else
|
||||||
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
||||||
if (button->backend->max_icon_size) {
|
if (button->backend->max_icon_size) {
|
||||||
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
icon_w = MIN(icon_w, button->backend->max_icon_size * panel->scale);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -302,10 +299,11 @@ int button_compute_desired_size(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
} else {
|
} else {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -315,10 +313,12 @@ int button_compute_desired_size(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
txt_height_ink = txt_height = txt_width = 0;
|
txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -338,9 +338,9 @@ gboolean resize_button(void *obj)
|
|||||||
Button *button = (Button *)obj;
|
Button *button = (Button *)obj;
|
||||||
Panel *panel = (Panel *)button->area.panel;
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
Area *area = &button->area;
|
Area *area = &button->area;
|
||||||
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy);
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy) * panel->scale;
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
||||||
int interior_padding = button->area.paddingx;
|
int interior_padding = button->area.paddingx * panel->scale;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -349,8 +349,8 @@ gboolean resize_button(void *obj)
|
|||||||
else
|
else
|
||||||
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
||||||
if (button->backend->max_icon_size) {
|
if (button->backend->max_icon_size) {
|
||||||
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
icon_w = MIN(icon_w, button->backend->max_icon_size * panel->scale);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
@@ -371,10 +371,9 @@ gboolean resize_button(void *obj)
|
|||||||
available_h = panel->area.height;
|
available_h = panel->area.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -383,9 +382,11 @@ gboolean resize_button(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
} else {
|
} else {
|
||||||
txt_height_ink = txt_height = txt_width = 0;
|
txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
@@ -438,6 +439,7 @@ gboolean resize_button(void *obj)
|
|||||||
void draw_button(void *obj, cairo_t *c)
|
void draw_button(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Button *button = obj;
|
Button *button = obj;
|
||||||
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
|
|
||||||
if (button->frontend->icon) {
|
if (button->frontend->icon) {
|
||||||
// Render icon
|
// Render icon
|
||||||
@@ -459,10 +461,12 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
// Render text
|
// Render text
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_font_description(layout, button->backend->font_desc);
|
pango_layout_set_font_description(layout, button->backend->font_desc);
|
||||||
pango_layout_set_width(layout, button->frontend->textw * PANGO_SCALE);
|
pango_layout_set_width(layout, (button->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
pango_layout_set_alignment(layout, button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
pango_layout_set_alignment(layout, button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
||||||
@@ -474,9 +478,10 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
button->frontend->textx,
|
button->frontend->textx,
|
||||||
button->frontend->texty,
|
button->frontend->texty,
|
||||||
&button->backend->font_color,
|
&button->backend->font_color,
|
||||||
panel_config.font_shadow);
|
panel_config.font_shadow ? layout : NULL);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +493,7 @@ void button_dump_geometry(void *obj, int indent)
|
|||||||
Imlib_Image tmp = imlib_context_get_image();
|
Imlib_Image tmp = imlib_context_get_image();
|
||||||
imlib_context_set_image(button->frontend->icon);
|
imlib_context_set_image(button->frontend->icon);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%*sIcon: x = %d, y = %d, w = %d, h = %d\n",
|
"tint2: %*sIcon: x = %d, y = %d, w = %d, h = %d\n",
|
||||||
indent,
|
indent,
|
||||||
"",
|
"",
|
||||||
button->frontend->iconx,
|
button->frontend->iconx,
|
||||||
@@ -499,7 +504,7 @@ void button_dump_geometry(void *obj, int indent)
|
|||||||
imlib_context_set_image(tmp);
|
imlib_context_set_image(tmp);
|
||||||
}
|
}
|
||||||
fprintf(stderr,
|
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,
|
indent,
|
||||||
"",
|
"",
|
||||||
button->frontend->textx,
|
button->frontend->textx,
|
||||||
|
|||||||
+16
-13
@@ -51,7 +51,7 @@ static char buf_time[256];
|
|||||||
static char buf_date[256];
|
static char buf_date[256];
|
||||||
static char buf_tooltip[512];
|
static char buf_tooltip[512];
|
||||||
int clock_enabled;
|
int clock_enabled;
|
||||||
static timeout *clock_timeout;
|
static Timer clock_timer;
|
||||||
|
|
||||||
void clock_init_fonts();
|
void clock_init_fonts();
|
||||||
char *clock_get_tooltip(void *obj);
|
char *clock_get_tooltip(void *obj);
|
||||||
@@ -61,11 +61,11 @@ void clock_dump_geometry(void *obj, int indent);
|
|||||||
void default_clock()
|
void default_clock()
|
||||||
{
|
{
|
||||||
clock_enabled = 0;
|
clock_enabled = 0;
|
||||||
clock_timeout = NULL;
|
|
||||||
time1_format = NULL;
|
time1_format = NULL;
|
||||||
time1_timezone = NULL;
|
time1_timezone = NULL;
|
||||||
time2_format = NULL;
|
time2_format = NULL;
|
||||||
time2_timezone = NULL;
|
time2_timezone = NULL;
|
||||||
|
INIT_TIMER(clock_timer);
|
||||||
time_tooltip_format = NULL;
|
time_tooltip_format = NULL;
|
||||||
time_tooltip_timezone = NULL;
|
time_tooltip_timezone = NULL;
|
||||||
clock_lclick_command = NULL;
|
clock_lclick_command = NULL;
|
||||||
@@ -110,8 +110,7 @@ void cleanup_clock()
|
|||||||
clock_uwheel_command = NULL;
|
clock_uwheel_command = NULL;
|
||||||
free(clock_dwheel_command);
|
free(clock_dwheel_command);
|
||||||
clock_dwheel_command = NULL;
|
clock_dwheel_command = NULL;
|
||||||
stop_timeout(clock_timeout);
|
destroy_timer(&clock_timer);
|
||||||
clock_timeout = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tm *clock_gettime_for_tz(const char *timezone)
|
struct tm *clock_gettime_for_tz(const char *timezone)
|
||||||
@@ -155,7 +154,7 @@ void update_clocks_sec(void *arg)
|
|||||||
{
|
{
|
||||||
gettimeofday(&time_clock, 0);
|
gettimeofday(&time_clock, 0);
|
||||||
update_clocks();
|
update_clocks();
|
||||||
clock_timeout = add_timeout(ms_until_second_change(&time_clock), 0, update_clocks_sec, 0, &clock_timeout);
|
change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_sec, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_clocks_min(void *arg)
|
void update_clocks_min(void *arg)
|
||||||
@@ -167,14 +166,20 @@ void update_clocks_min(void *arg)
|
|||||||
if (time_clock.tv_sec % 60 == 0 || time_clock.tv_sec - old_sec > 60 || (time1_format && !buf_time[0]) || (time2_format && !buf_date[0]))
|
if (time_clock.tv_sec % 60 == 0 || time_clock.tv_sec - old_sec > 60 || (time1_format && !buf_time[0]) || (time2_format && !buf_date[0]))
|
||||||
update_clocks();
|
update_clocks();
|
||||||
old_sec = time_clock.tv_sec;
|
old_sec = time_clock.tv_sec;
|
||||||
clock_timeout = add_timeout(ms_until_second_change(&time_clock), 0, update_clocks_min, 0, &clock_timeout);
|
change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_min, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean time_format_needs_sec_ticks(char *time_format)
|
gboolean time_format_needs_sec_ticks(char *time_format)
|
||||||
{
|
{
|
||||||
if (!time_format)
|
if (!time_format)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (strchr(time_format, 'S') || strchr(time_format, 'T') || strchr(time_format, 'r'))
|
if (strchr(time_format, 'c') ||
|
||||||
|
strchr(time_format, 'r') ||
|
||||||
|
strchr(time_format, 's') ||
|
||||||
|
strchr(time_format, 'S') ||
|
||||||
|
strchr(time_format, 'T') ||
|
||||||
|
strchr(time_format, 'X') ||
|
||||||
|
strchr(time_format, '+'))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -216,7 +221,7 @@ void init_clock_panel(void *p)
|
|||||||
strftime(buf_tooltip, sizeof(buf_tooltip), time_tooltip_format, clock_gettime_for_tz(time_tooltip_timezone));
|
strftime(buf_tooltip, sizeof(buf_tooltip), time_tooltip_format, clock_gettime_for_tz(time_tooltip_timezone));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clock_timeout) {
|
if (!clock_timer.enabled_) {
|
||||||
if (time_format_needs_sec_ticks(time1_format) || time_format_needs_sec_ticks(time2_format)) {
|
if (time_format_needs_sec_ticks(time1_format) || time_format_needs_sec_ticks(time2_format)) {
|
||||||
update_clocks_sec(NULL);
|
update_clocks_sec(NULL);
|
||||||
} else {
|
} else {
|
||||||
@@ -262,10 +267,8 @@ void clock_default_font_changed()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void clock_compute_text_geometry(Clock *clock,
|
void clock_compute_text_geometry(Clock *clock,
|
||||||
int *time_height_ink,
|
|
||||||
int *time_height,
|
int *time_height,
|
||||||
int *time_width,
|
int *time_width,
|
||||||
int *date_height_ink,
|
|
||||||
int *date_height,
|
int *date_height,
|
||||||
int *date_width)
|
int *date_width)
|
||||||
{
|
{
|
||||||
@@ -274,10 +277,8 @@ void clock_compute_text_geometry(Clock *clock,
|
|||||||
time2_format ? buf_date : NULL,
|
time2_format ? buf_date : NULL,
|
||||||
time1_font_desc,
|
time1_font_desc,
|
||||||
time2_font_desc,
|
time2_font_desc,
|
||||||
time_height_ink,
|
|
||||||
time_height,
|
time_height,
|
||||||
time_width,
|
time_width,
|
||||||
date_height_ink,
|
|
||||||
date_height,
|
date_height,
|
||||||
date_width);
|
date_width);
|
||||||
}
|
}
|
||||||
@@ -307,6 +308,7 @@ gboolean resize_clock(void *obj)
|
|||||||
void draw_clock(void *obj, cairo_t *c)
|
void draw_clock(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Clock *clock = (Clock *)obj;
|
Clock *clock = (Clock *)obj;
|
||||||
|
Panel *panel = (Panel *)clock->area.panel;
|
||||||
draw_text_area(&clock->area,
|
draw_text_area(&clock->area,
|
||||||
c,
|
c,
|
||||||
buf_time,
|
buf_time,
|
||||||
@@ -315,7 +317,8 @@ void draw_clock(void *obj, cairo_t *c)
|
|||||||
time2_font_desc,
|
time2_font_desc,
|
||||||
clock->time1_posy,
|
clock->time1_posy,
|
||||||
clock->time2_posy,
|
clock->time2_posy,
|
||||||
&clock->font);
|
&clock->font,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clock_dump_geometry(void *obj, int indent)
|
void clock_dump_geometry(void *obj, int indent)
|
||||||
|
|||||||
+24
-2
@@ -244,7 +244,11 @@ void add_entry(char *key, char *value)
|
|||||||
char *value1 = 0, *value2 = 0, *value3 = 0;
|
char *value1 = 0, *value2 = 0, *value3 = 0;
|
||||||
|
|
||||||
/* Background and border */
|
/* Background and border */
|
||||||
if (strcmp(key, "rounded") == 0) {
|
if (strcmp(key, "scale_relative_to_dpi") == 0) {
|
||||||
|
ui_scale_dpi_ref = atof(value);
|
||||||
|
} else if (strcmp(key, "scale_relative_to_screen_height") == 0) {
|
||||||
|
ui_scale_monitor_size_ref = atof(value);
|
||||||
|
} else if (strcmp(key, "rounded") == 0) {
|
||||||
// 'rounded' is the first parameter => alloc a new background
|
// 'rounded' is the first parameter => alloc a new background
|
||||||
if (backgrounds->len > 0) {
|
if (backgrounds->len > 0) {
|
||||||
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
||||||
@@ -350,6 +354,12 @@ void add_entry(char *key, char *value)
|
|||||||
id = (id < gradients->len && id >= 0) ? id : -1;
|
id = (id < gradients->len && id >= 0) ? id : -1;
|
||||||
if (id >= 0)
|
if (id >= 0)
|
||||||
bg->gradients[MOUSE_DOWN] = &g_array_index(gradients, GradientClass, id);
|
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 */
|
/* Gradients */
|
||||||
@@ -1006,6 +1016,8 @@ void add_entry(char *key, char *value)
|
|||||||
taskbar_sort_method = TASKBAR_SORT_CENTER;
|
taskbar_sort_method = TASKBAR_SORT_CENTER;
|
||||||
} else if (strcmp(value, "title") == 0) {
|
} else if (strcmp(value, "title") == 0) {
|
||||||
taskbar_sort_method = TASKBAR_SORT_TITLE;
|
taskbar_sort_method = TASKBAR_SORT_TITLE;
|
||||||
|
} else if (strcmp(value, "application") == 0) {
|
||||||
|
taskbar_sort_method = TASKBAR_SORT_APPLICATION;
|
||||||
} else if (strcmp(value, "lru") == 0) {
|
} else if (strcmp(value, "lru") == 0) {
|
||||||
taskbar_sort_method = TASKBAR_SORT_LRU;
|
taskbar_sort_method = TASKBAR_SORT_LRU;
|
||||||
} else if (strcmp(value, "mru") == 0) {
|
} else if (strcmp(value, "mru") == 0) {
|
||||||
@@ -1086,11 +1098,18 @@ void add_entry(char *key, char *value)
|
|||||||
panel_config.g_task.config_background_mask |= (1 << status);
|
panel_config.g_task.config_background_mask |= (1 << status);
|
||||||
if (status == TASK_NORMAL)
|
if (status == TASK_NORMAL)
|
||||||
panel_config.g_task.area.bg = panel_config.g_task.background[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
|
// "tooltip" is deprecated but here for backwards compatibility
|
||||||
else if (strcmp(key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0)
|
else if (strcmp(key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0)
|
||||||
panel_config.g_task.tooltip_enabled = atoi(value);
|
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 */
|
/* Systray */
|
||||||
else if (strcmp(key, "systray_padding") == 0) {
|
else if (strcmp(key, "systray_padding") == 0) {
|
||||||
@@ -1133,8 +1152,11 @@ void add_entry(char *key, char *value)
|
|||||||
} else if (strcmp(key, "systray_monitor") == 0) {
|
} else if (strcmp(key, "systray_monitor") == 0) {
|
||||||
systray_monitor = MAX(0, config_get_monitor(value));
|
systray_monitor = MAX(0, config_get_monitor(value));
|
||||||
} else if (strcmp(key, "systray_name_filter") == 0) {
|
} 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);
|
free(systray_hide_name_filter);
|
||||||
|
}
|
||||||
systray_hide_name_filter = strdup(value);
|
systray_hide_name_filter = strdup(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef default_icon_h
|
||||||
|
#define default_icon_h
|
||||||
|
|
||||||
|
#include <Imlib2.h>
|
||||||
|
|
||||||
|
extern int default_icon_width;
|
||||||
|
extern int default_icon_height;
|
||||||
|
extern DATA32 default_icon_data[];
|
||||||
|
|
||||||
|
#endif
|
||||||
+91
-53
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#define MAX_TOOLTIP_LEN 4096
|
#define MAX_TOOLTIP_LEN 4096
|
||||||
|
|
||||||
|
bool debug_executors = false;
|
||||||
|
|
||||||
void execp_timer_callback(void *arg);
|
void execp_timer_callback(void *arg);
|
||||||
char *execp_get_tooltip(void *obj);
|
char *execp_get_tooltip(void *obj);
|
||||||
void execp_init_fonts();
|
void execp_init_fonts();
|
||||||
@@ -41,6 +43,7 @@ Execp *create_execp()
|
|||||||
execp->backend->cache_icon = TRUE;
|
execp->backend->cache_icon = TRUE;
|
||||||
execp->backend->centered = TRUE;
|
execp->backend->centered = TRUE;
|
||||||
execp->backend->font_color.alpha = 0.5;
|
execp->backend->font_color.alpha = 0.5;
|
||||||
|
INIT_TIMER(execp->backend->timer);
|
||||||
return execp;
|
return execp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,14 +70,9 @@ void destroy_execp(void *obj)
|
|||||||
free_and_null(execp);
|
free_and_null(execp);
|
||||||
} else {
|
} else {
|
||||||
// This is a backend element
|
// This is a backend element
|
||||||
stop_timeout(execp->backend->timer);
|
destroy_timer(&execp->backend->timer);
|
||||||
execp->backend->timer = NULL;
|
|
||||||
|
|
||||||
if (execp->backend->icon) {
|
free_icon(execp->backend->icon);
|
||||||
imlib_context_set_image(execp->backend->icon);
|
|
||||||
imlib_free_image();
|
|
||||||
execp->backend->icon = NULL;
|
|
||||||
}
|
|
||||||
free_and_null(execp->backend->buf_stdout);
|
free_and_null(execp->backend->buf_stdout);
|
||||||
free_and_null(execp->backend->buf_stderr);
|
free_and_null(execp->backend->buf_stderr);
|
||||||
free_and_null(execp->backend->text);
|
free_and_null(execp->backend->text);
|
||||||
@@ -109,7 +107,7 @@ void destroy_execp(void *obj)
|
|||||||
|
|
||||||
if (execp->backend->instances) {
|
if (execp->backend->instances) {
|
||||||
fprintf(stderr, "tint2: Error: Attempt to destroy backend while there are still frontend instances!\n");
|
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->backend);
|
||||||
free(execp);
|
free(execp);
|
||||||
@@ -196,7 +194,7 @@ void init_execp_panel(void *p)
|
|||||||
execp->area.on_screen = TRUE;
|
execp->area.on_screen = TRUE;
|
||||||
instantiate_area_gradients(&execp->area);
|
instantiate_area_gradients(&execp->area);
|
||||||
|
|
||||||
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
change_timer(&execp->backend->timer, true, 10, 0, execp_timer_callback, execp);
|
||||||
|
|
||||||
execp_update_post_read(execp);
|
execp_update_post_read(execp);
|
||||||
}
|
}
|
||||||
@@ -308,7 +306,6 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
int *icon_w,
|
int *icon_w,
|
||||||
int *icon_h,
|
int *icon_h,
|
||||||
gboolean *text_next_line,
|
gboolean *text_next_line,
|
||||||
int *txt_height_ink,
|
|
||||||
int *txt_height,
|
int *txt_height,
|
||||||
int *txt_width,
|
int *txt_width,
|
||||||
int *new_size,
|
int *new_size,
|
||||||
@@ -316,9 +313,9 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
{
|
{
|
||||||
Panel *panel = (Panel *)execp->area.panel;
|
Panel *panel = (Panel *)execp->area.panel;
|
||||||
Area *area = &execp->area;
|
Area *area = &execp->area;
|
||||||
*horiz_padding = (panel_horizontal ? area->paddingxlr : area->paddingy);
|
*horiz_padding = (panel_horizontal ? area->paddingxlr : area->paddingy) * panel->scale;
|
||||||
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr);
|
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr) * panel->scale;
|
||||||
*interior_padding = area->paddingx;
|
*interior_padding = area->paddingx * panel->scale;
|
||||||
|
|
||||||
if (reload_icon(execp)) {
|
if (reload_icon(execp)) {
|
||||||
if (execp->backend->icon) {
|
if (execp->backend->icon) {
|
||||||
@@ -337,7 +334,7 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
int available_w, available_h;
|
int available_w, available_h;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
available_w = panel->area.width;
|
available_w = panel->area.width;
|
||||||
available_h = area->height - 2 * area->paddingy - left_right_border_width(area);
|
available_h = area->height - 2 * *vert_padding - left_right_border_width(area);
|
||||||
} else {
|
} else {
|
||||||
available_w = !text_next_line
|
available_w = !text_next_line
|
||||||
? area->width - *icon_w - (*icon_w ? *interior_padding : 0) - 2 * *horiz_padding -
|
? area->width - *icon_w - (*icon_w ? *interior_padding : 0) - 2 * *horiz_padding -
|
||||||
@@ -346,7 +343,6 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
available_h = panel->area.height;
|
available_h = panel->area.height;
|
||||||
}
|
}
|
||||||
get_text_size2(execp->backend->font_desc,
|
get_text_size2(execp->backend->font_desc,
|
||||||
txt_height_ink,
|
|
||||||
txt_height,
|
txt_height,
|
||||||
txt_width,
|
txt_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -355,7 +351,9 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
strlen(execp->backend->text),
|
strlen(execp->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
execp->backend->has_markup);
|
execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
execp->backend->has_markup,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
*resized = FALSE;
|
*resized = FALSE;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -375,7 +373,11 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
*new_size = *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
*new_size = *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
||||||
*new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area));
|
*new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area));
|
||||||
} else {
|
} else {
|
||||||
|
if (strlen(execp->backend->text)) {
|
||||||
*new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
*new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
||||||
|
} else {
|
||||||
|
*new_size = *icon_h + 2 * *vert_padding + top_bottom_border_width(area);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (*new_size != area->height) {
|
if (*new_size != area->height) {
|
||||||
*resized = TRUE;
|
*resized = TRUE;
|
||||||
@@ -389,7 +391,7 @@ int execp_compute_desired_size(void *obj)
|
|||||||
int horiz_padding, vert_padding, interior_padding;
|
int horiz_padding, vert_padding, interior_padding;
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
gboolean text_next_line;
|
gboolean text_next_line;
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
int new_size;
|
int new_size;
|
||||||
gboolean resized;
|
gboolean resized;
|
||||||
execp_compute_icon_text_geometry(execp,
|
execp_compute_icon_text_geometry(execp,
|
||||||
@@ -399,7 +401,6 @@ int execp_compute_desired_size(void *obj)
|
|||||||
&icon_w,
|
&icon_w,
|
||||||
&icon_h,
|
&icon_h,
|
||||||
&text_next_line,
|
&text_next_line,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
&new_size,
|
&new_size,
|
||||||
@@ -414,7 +415,7 @@ gboolean resize_execp(void *obj)
|
|||||||
int horiz_padding, vert_padding, interior_padding;
|
int horiz_padding, vert_padding, interior_padding;
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
gboolean text_next_line;
|
gboolean text_next_line;
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
int new_size;
|
int new_size;
|
||||||
gboolean resized;
|
gboolean resized;
|
||||||
execp_compute_icon_text_geometry(execp,
|
execp_compute_icon_text_geometry(execp,
|
||||||
@@ -424,7 +425,6 @@ gboolean resize_execp(void *obj)
|
|||||||
&icon_w,
|
&icon_w,
|
||||||
&icon_h,
|
&icon_h,
|
||||||
&text_next_line,
|
&text_next_line,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
&new_size,
|
&new_size,
|
||||||
@@ -445,10 +445,17 @@ gboolean resize_execp(void *obj)
|
|||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
||||||
} else {
|
} else {
|
||||||
|
if (strlen(execp->backend->text)) {
|
||||||
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
||||||
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
||||||
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
execp->frontend->textx = (execp->area.width - txt_width) / 2;
|
execp->frontend->textx = (execp->area.width - txt_width) / 2;
|
||||||
|
} else {
|
||||||
|
execp->frontend->icony = (execp->area.height - icon_h) / 2;
|
||||||
|
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
||||||
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
|
execp->frontend->textx = (execp->area.width - txt_width) / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
@@ -462,10 +469,17 @@ gboolean resize_execp(void *obj)
|
|||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
||||||
} else {
|
} else {
|
||||||
|
if (strlen(execp->backend->text)) {
|
||||||
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
||||||
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
||||||
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
execp->frontend->textx = execp->frontend->iconx;
|
execp->frontend->textx = execp->frontend->iconx;
|
||||||
|
} else {
|
||||||
|
execp->frontend->icony = (execp->area.height - icon_h) / 2;
|
||||||
|
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
||||||
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
|
execp->frontend->textx = execp->frontend->iconx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
@@ -477,10 +491,27 @@ gboolean resize_execp(void *obj)
|
|||||||
return resized;
|
return resized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PangoLayout *create_execp_text_layout(Execp *execp, PangoContext *context)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
pango_layout_set_font_description(layout, execp->backend->font_desc);
|
||||||
|
pango_layout_set_width(layout, (execp->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
|
pango_layout_set_height(layout, (execp->frontend->texth + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
|
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
||||||
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
void draw_execp(void *obj, cairo_t *c)
|
void draw_execp(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Execp *execp = (Execp *)obj;
|
Execp *execp = (Execp *)obj;
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
Panel *panel = (Panel *)execp->area.panel;
|
||||||
|
|
||||||
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = create_execp_text_layout(execp, context);
|
||||||
|
PangoLayout *shadow_layout = NULL;
|
||||||
|
|
||||||
if (execp->backend->has_icon && execp->backend->icon) {
|
if (execp->backend->has_icon && execp->backend->icon) {
|
||||||
imlib_context_set_image(execp->backend->icon);
|
imlib_context_set_image(execp->backend->icon);
|
||||||
@@ -489,15 +520,18 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw layout
|
// draw layout
|
||||||
pango_layout_set_font_description(layout, execp->backend->font_desc);
|
if (!execp->backend->has_markup) {
|
||||||
pango_layout_set_width(layout, execp->frontend->textw * PANGO_SCALE);
|
|
||||||
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
|
||||||
if (!execp->backend->has_markup)
|
|
||||||
pango_layout_set_text(layout, execp->backend->text, strlen(execp->backend->text));
|
pango_layout_set_text(layout, execp->backend->text, strlen(execp->backend->text));
|
||||||
else
|
} else {
|
||||||
pango_layout_set_markup(layout, execp->backend->text, strlen(execp->backend->text));
|
pango_layout_set_markup(layout, execp->backend->text, strlen(execp->backend->text));
|
||||||
|
if (panel_config.font_shadow) {
|
||||||
|
shadow_layout = create_execp_text_layout(execp, context);
|
||||||
|
if (!layout_set_markup_strip_colors(shadow_layout, execp->backend->text)) {
|
||||||
|
g_object_unref(shadow_layout);
|
||||||
|
shadow_layout = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
draw_text(layout,
|
draw_text(layout,
|
||||||
@@ -505,9 +539,10 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
execp->frontend->textx,
|
execp->frontend->textx,
|
||||||
execp->frontend->texty,
|
execp->frontend->texty,
|
||||||
&execp->backend->font_color,
|
&execp->backend->font_color,
|
||||||
panel_config.font_shadow);
|
shadow_layout);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execp_dump_geometry(void *obj, int indent)
|
void execp_dump_geometry(void *obj, int indent)
|
||||||
@@ -518,7 +553,7 @@ void execp_dump_geometry(void *obj, int indent)
|
|||||||
Imlib_Image tmp = imlib_context_get_image();
|
Imlib_Image tmp = imlib_context_get_image();
|
||||||
imlib_context_set_image(execp->backend->icon);
|
imlib_context_set_image(execp->backend->icon);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%*sIcon: x = %d, y = %d, w = %d, h = %d\n",
|
"tint2: %*sIcon: x = %d, y = %d, w = %d, h = %d\n",
|
||||||
indent,
|
indent,
|
||||||
"",
|
"",
|
||||||
execp->frontend->iconx,
|
execp->frontend->iconx,
|
||||||
@@ -529,12 +564,13 @@ void execp_dump_geometry(void *obj, int indent)
|
|||||||
imlib_context_set_image(tmp);
|
imlib_context_set_image(tmp);
|
||||||
}
|
}
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n",
|
"tint2: %*sText: x = %d, y = %d, w = %d, h = %d, align = %s, text = %s\n",
|
||||||
indent,
|
indent,
|
||||||
"",
|
"",
|
||||||
execp->frontend->textx,
|
execp->frontend->textx,
|
||||||
execp->frontend->texty,
|
execp->frontend->texty,
|
||||||
execp->frontend->textw,
|
execp->frontend->textw,
|
||||||
|
execp->frontend->texth,
|
||||||
execp->backend->centered ? "center" : "left",
|
execp->backend->centered ? "center" : "left",
|
||||||
execp->backend->text);
|
execp->backend->text);
|
||||||
}
|
}
|
||||||
@@ -544,10 +580,8 @@ void execp_force_update(Execp *execp)
|
|||||||
if (execp->backend->child_pipe_stdout > 0) {
|
if (execp->backend->child_pipe_stdout > 0) {
|
||||||
// Command currently running, nothing to do
|
// Command currently running, nothing to do
|
||||||
} else {
|
} else {
|
||||||
if (execp->backend->timer)
|
|
||||||
stop_timeout(execp->backend->timer);
|
|
||||||
// Run command right away
|
// Run command right away
|
||||||
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
change_timer(&execp->backend->timer, true, 10, 0, execp_timer_callback, execp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,6 +671,7 @@ void execp_timer_callback(void *arg)
|
|||||||
close(pipe_fd_stderr[0]);
|
close(pipe_fd_stderr[0]);
|
||||||
return;
|
return;
|
||||||
} else if (child == 0) {
|
} else if (child == 0) {
|
||||||
|
if (debug_executors)
|
||||||
fprintf(stderr, "tint2: Executing: %s\n", execp->backend->command);
|
fprintf(stderr, "tint2: Executing: %s\n", execp->backend->command);
|
||||||
// We are in the child
|
// We are in the child
|
||||||
close(pipe_fd_stdout[0]);
|
close(pipe_fd_stdout[0]);
|
||||||
@@ -761,8 +796,7 @@ gboolean read_execp(void *obj)
|
|||||||
close(execp->backend->child_pipe_stderr);
|
close(execp->backend->child_pipe_stderr);
|
||||||
execp->backend->child_pipe_stderr = -1;
|
execp->backend->child_pipe_stderr = -1;
|
||||||
if (execp->backend->interval)
|
if (execp->backend->interval)
|
||||||
execp->backend->timer =
|
change_timer(&execp->backend->timer, true, execp->backend->interval * 1000, 0, execp_timer_callback, execp);
|
||||||
add_timeout(execp->backend->interval * 1000, 0, execp_timer_callback, execp, &execp->backend->timer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ansi_clear_screen = (char*)"\x1b[2J";
|
char *ansi_clear_screen = (char*)"\x1b[2J";
|
||||||
@@ -886,22 +920,22 @@ gboolean read_execp(void *obj)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *time_to_string(int seconds, char *buffer)
|
const char *time_to_string(int seconds, char *buffer, size_t buffer_size)
|
||||||
{
|
{
|
||||||
if (seconds < 60) {
|
if (seconds < 60) {
|
||||||
sprintf(buffer, "%ds", seconds);
|
snprintf(buffer, buffer_size, "%ds", seconds);
|
||||||
} else if (seconds < 60 * 60) {
|
} else if (seconds < 60 * 60) {
|
||||||
int m = seconds / 60;
|
int m = seconds / 60;
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
int s = seconds;
|
int s = seconds;
|
||||||
sprintf(buffer, "%d:%ds", m, s);
|
snprintf(buffer, buffer_size, "%d:%ds", m, s);
|
||||||
} else {
|
} else {
|
||||||
int h = seconds / (60 * 60);
|
int h = seconds / (60 * 60);
|
||||||
seconds = seconds % (60 * 60);
|
seconds = seconds % (60 * 60);
|
||||||
int m = seconds / 60;
|
int m = seconds / 60;
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
int s = seconds;
|
int s = seconds;
|
||||||
sprintf(buffer, "%d:%d:%ds", h, m, s);
|
snprintf(buffer, buffer_size, "%d:%d:%ds", h, m, s);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@@ -927,35 +961,39 @@ char *execp_get_tooltip(void *obj)
|
|||||||
if (execp->backend->last_update_finish_time) {
|
if (execp->backend->last_update_finish_time) {
|
||||||
// We updated at least once
|
// We updated at least once
|
||||||
if (execp->backend->interval > 0) {
|
if (execp->backend->interval > 0) {
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
|
sizeof(execp->backend->tooltip_text),
|
||||||
"Last update finished %s ago (took %s). Next update starting in %s.",
|
"Last update finished %s ago (took %s). Next update starting in %s.",
|
||||||
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1, sizeof(tmp_buf1)),
|
||||||
time_to_string((int)execp->backend->last_update_duration, tmp_buf2),
|
time_to_string((int)execp->backend->last_update_duration, tmp_buf2, sizeof(tmp_buf2)),
|
||||||
time_to_string((int)(execp->backend->interval - (now - execp->backend->last_update_finish_time)),
|
time_to_string((int)(execp->backend->interval - (now - execp->backend->last_update_finish_time)),
|
||||||
tmp_buf3));
|
tmp_buf3, sizeof(tmp_buf3)));
|
||||||
} else {
|
} else {
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
|
sizeof(execp->backend->tooltip_text),
|
||||||
"Last update finished %s ago (took %s).",
|
"Last update finished %s ago (took %s).",
|
||||||
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1, sizeof(tmp_buf1)),
|
||||||
time_to_string((int)execp->backend->last_update_duration, tmp_buf2));
|
time_to_string((int)execp->backend->last_update_duration, tmp_buf2, sizeof(tmp_buf2)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we never requested an update
|
// we never requested an update
|
||||||
sprintf(execp->backend->tooltip_text, "Never updated. No update scheduled.");
|
snprintf(execp->backend->tooltip_text, sizeof(execp->backend->tooltip_text), "Never updated. No update scheduled.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Currently executing command
|
// Currently executing command
|
||||||
if (execp->backend->last_update_finish_time) {
|
if (execp->backend->last_update_finish_time) {
|
||||||
// we finished updating at least once
|
// we finished updating at least once
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
|
sizeof(execp->backend->tooltip_text),
|
||||||
"Last update finished %s ago. Update in progress (started %s ago).",
|
"Last update finished %s ago. Update in progress (started %s ago).",
|
||||||
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1, sizeof(tmp_buf1)),
|
||||||
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf3));
|
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf3, sizeof(tmp_buf3)));
|
||||||
} else {
|
} else {
|
||||||
// we never finished an update
|
// we never finished an update
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
|
sizeof(execp->backend->tooltip_text),
|
||||||
"First update in progress (started %s seconds ago).",
|
"First update in progress (started %s seconds ago).",
|
||||||
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf1));
|
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf1, sizeof(tmp_buf1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strdup(execp->backend->tooltip_text);
|
return strdup(execp->backend->tooltip_text);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
extern bool debug_executors;
|
||||||
|
|
||||||
// Architecture:
|
// Architecture:
|
||||||
// Panel panel_config contains an array of Execp, each storing all config options and all the state variables.
|
// Panel panel_config contains an array of Execp, each storing all config options and all the state variables.
|
||||||
// Only these run commands.
|
// Only these run commands.
|
||||||
@@ -46,7 +48,7 @@ typedef struct ExecpBackend {
|
|||||||
Background *bg;
|
Background *bg;
|
||||||
|
|
||||||
// Backend state:
|
// Backend state:
|
||||||
timeout *timer;
|
Timer timer;
|
||||||
int child_pipe_stdout;
|
int child_pipe_stdout;
|
||||||
int child_pipe_stderr;
|
int child_pipe_stderr;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
|
|||||||
@@ -65,14 +65,14 @@ void cleanup_freespace(Panel *panel)
|
|||||||
panel->freespace_list = NULL;
|
panel->freespace_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int freespace_get_max_size(Panel *p)
|
int freespace_get_max_size(Panel *panel)
|
||||||
{
|
{
|
||||||
if (panel_shrink)
|
if (panel_shrink)
|
||||||
return 0;
|
return 0;
|
||||||
// Get space used by every element except the freespace
|
// Get space used by every element except the freespace
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int spacers = 0;
|
int spacers = 0;
|
||||||
for (GList *walk = p->area.children; walk; walk = g_list_next(walk)) {
|
for (GList *walk = panel->area.children; walk; walk = g_list_next(walk)) {
|
||||||
Area *a = (Area *)walk->data;
|
Area *a = (Area *)walk->data;
|
||||||
|
|
||||||
if (!a->on_screen)
|
if (!a->on_screen)
|
||||||
@@ -83,15 +83,15 @@ int freespace_get_max_size(Panel *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size += a->width + p->area.paddingx;
|
size += a->width + panel->area.paddingx * panel->scale;
|
||||||
else
|
else
|
||||||
size += a->height + p->area.paddingy;
|
size += a->height + panel->area.paddingy * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size = p->area.width - size - left_right_border_width(&p->area) - p->area.paddingxlr;
|
size = panel->area.width - size - left_right_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
||||||
else
|
else
|
||||||
size = p->area.height - size - top_bottom_border_width(&p->area) - p->area.paddingxlr;
|
size = panel->area.height - size - top_bottom_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
||||||
|
|
||||||
return size / spacers;
|
return size / spacers;
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-28
@@ -6,12 +6,19 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.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 "config.h"
|
||||||
|
#include "default_icon.h"
|
||||||
#include "drag_and_drop.h"
|
#include "drag_and_drop.h"
|
||||||
#include "fps_distribution.h"
|
#include "fps_distribution.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
|
#include "test.h"
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "tracing.h"
|
#include "tracing.h"
|
||||||
#include "uevent.h"
|
#include "uevent.h"
|
||||||
@@ -43,6 +50,15 @@ void handle_cli_arguments(int argc, char **argv)
|
|||||||
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
|
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
|
||||||
fprintf(stdout, "tint2 version %s\n", VERSION_STRING);
|
fprintf(stdout, "tint2 version %s\n", VERSION_STRING);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
} else if (strcmp(argv[i], "--test") == 0) {
|
||||||
|
run_all_tests(false);
|
||||||
|
exit(0);
|
||||||
|
} else if (strcmp(argv[i], "--test-verbose") == 0) {
|
||||||
|
run_all_tests(true);
|
||||||
|
exit(0);
|
||||||
|
} else if (strcmp(argv[i], "--dump-image-data") == 0) {
|
||||||
|
dump_image_data(argv[i+1], argv[i+2]);
|
||||||
|
exit(0);
|
||||||
} else if (strcmp(argv[i], "-c") == 0) {
|
} else if (strcmp(argv[i], "-c") == 0) {
|
||||||
if (i + 1 < argc) {
|
if (i + 1 < argc) {
|
||||||
i++;
|
i++;
|
||||||
@@ -75,7 +91,7 @@ void handle_cli_arguments(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
print_usage();
|
print_usage();
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,6 +104,9 @@ void handle_env_vars()
|
|||||||
debug_fps = getenv("DEBUG_FPS") != NULL;
|
debug_fps = getenv("DEBUG_FPS") != NULL;
|
||||||
debug_frames = getenv("DEBUG_FRAMES") != NULL;
|
debug_frames = getenv("DEBUG_FRAMES") != NULL;
|
||||||
debug_dnd = getenv("DEBUG_DND") != NULL;
|
debug_dnd = getenv("DEBUG_DND") != NULL;
|
||||||
|
debug_thumbnails = getenv("DEBUG_THUMBNAILS") != NULL;
|
||||||
|
debug_timers = getenv("DEBUG_TIMERS") != NULL;
|
||||||
|
debug_executors = getenv("DEBUG_EXECUTORS") != NULL;
|
||||||
if (debug_fps) {
|
if (debug_fps) {
|
||||||
init_fps_distribution();
|
init_fps_distribution();
|
||||||
char *s = getenv("TRACING_FPS_THRESHOLD");
|
char *s = getenv("TRACING_FPS_THRESHOLD");
|
||||||
@@ -97,25 +116,25 @@ void handle_env_vars()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static timeout *detect_compositor_timer = NULL;
|
static Timer detect_compositor_timer = DEFAULT_TIMER;
|
||||||
static int detect_compositor_timer_counter = 0;
|
static int detect_compositor_timer_counter = 0;
|
||||||
|
|
||||||
void detect_compositor(void *arg)
|
void detect_compositor(void *arg)
|
||||||
{
|
{
|
||||||
if (server.composite_manager) {
|
if (server.composite_manager) {
|
||||||
stop_timeout(detect_compositor_timer);
|
stop_timer(&detect_compositor_timer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
detect_compositor_timer_counter--;
|
detect_compositor_timer_counter--;
|
||||||
if (detect_compositor_timer_counter < 0) {
|
if (detect_compositor_timer_counter < 0) {
|
||||||
stop_timeout(detect_compositor_timer);
|
stop_timer(&detect_compositor_timer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No compositor, check for one
|
// No compositor, check for one
|
||||||
if (XGetSelectionOwner(server.display, server.atom._NET_WM_CM_S0) != None) {
|
if (XGetSelectionOwner(server.display, server.atom._NET_WM_CM_S0) != None) {
|
||||||
stop_timeout(detect_compositor_timer);
|
stop_timer(&detect_compositor_timer);
|
||||||
// Restart tint2
|
// Restart tint2
|
||||||
fprintf(stderr, "tint2: Detected compositor, restarting tint2...\n");
|
fprintf(stderr, "tint2: Detected compositor, restarting tint2...\n");
|
||||||
kill(getpid(), SIGUSR1);
|
kill(getpid(), SIGUSR1);
|
||||||
@@ -128,15 +147,15 @@ void start_detect_compositor()
|
|||||||
if (server.composite_manager)
|
if (server.composite_manager)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stop_timeout(detect_compositor_timer);
|
|
||||||
// Check every 0.5 seconds for up to 30 seconds
|
// Check every 0.5 seconds for up to 30 seconds
|
||||||
detect_compositor_timer_counter = 60;
|
detect_compositor_timer_counter = 60;
|
||||||
detect_compositor_timer = add_timeout(500, 500, detect_compositor, 0, &detect_compositor_timer);
|
INIT_TIMER(detect_compositor_timer);
|
||||||
|
change_timer(&detect_compositor_timer, true, 500, 500, detect_compositor, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_default_elements()
|
void create_default_elements()
|
||||||
{
|
{
|
||||||
default_timeout();
|
default_timers();
|
||||||
default_systray();
|
default_systray();
|
||||||
memset(&server, 0, sizeof(server));
|
memset(&server, 0, sizeof(server));
|
||||||
#ifdef ENABLE_BATTERY
|
#ifdef ENABLE_BATTERY
|
||||||
@@ -151,6 +170,22 @@ void create_default_elements()
|
|||||||
default_panel();
|
default_panel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load_default_task_icon()
|
||||||
|
{
|
||||||
|
const gchar *const *data_dirs = g_get_system_data_dirs();
|
||||||
|
for (int i = 0; data_dirs[i] != NULL; i++) {
|
||||||
|
gchar *path = g_build_filename(data_dirs[i], "tint2", "default_icon.png", NULL);
|
||||||
|
if (g_file_test(path, G_FILE_TEST_EXISTS))
|
||||||
|
default_icon = load_image(path, TRUE);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
if (!default_icon) {
|
||||||
|
default_icon = imlib_create_image_using_data(default_icon_width,
|
||||||
|
default_icon_height,
|
||||||
|
default_icon_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init_post_config()
|
void init_post_config()
|
||||||
{
|
{
|
||||||
server_init_visual();
|
server_init_visual();
|
||||||
@@ -161,20 +196,7 @@ void init_post_config()
|
|||||||
imlib_context_set_colormap(server.colormap);
|
imlib_context_set_colormap(server.colormap);
|
||||||
|
|
||||||
init_signals_postconfig();
|
init_signals_postconfig();
|
||||||
|
load_default_task_icon();
|
||||||
// load default icon
|
|
||||||
const gchar *const *data_dirs = g_get_system_data_dirs();
|
|
||||||
for (int i = 0; data_dirs[i] != NULL; i++) {
|
|
||||||
gchar *path = g_build_filename(data_dirs[i], "tint2", "default_icon.png", NULL);
|
|
||||||
if (g_file_test(path, G_FILE_TEST_EXISTS))
|
|
||||||
default_icon = load_image(path, TRUE);
|
|
||||||
g_free(path);
|
|
||||||
}
|
|
||||||
if (!default_icon) {
|
|
||||||
fprintf(stderr,
|
|
||||||
RED "Could not load default_icon.png. Please check that tint2 has been installed correctly!" RESET
|
|
||||||
"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
XSync(server.display, False);
|
XSync(server.display, False);
|
||||||
}
|
}
|
||||||
@@ -184,15 +206,16 @@ void init_X11_pre_config()
|
|||||||
server.display = XOpenDisplay(NULL);
|
server.display = XOpenDisplay(NULL);
|
||||||
if (!server.display) {
|
if (!server.display) {
|
||||||
fprintf(stderr, "tint2: could not open display!\n");
|
fprintf(stderr, "tint2: could not open display!\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
server.x11_fd = ConnectionNumber(server.display);
|
server.x11_fd = ConnectionNumber(server.display);
|
||||||
XSetErrorHandler((XErrorHandler)server_catch_error);
|
XSetErrorHandler(server_catch_error);
|
||||||
XSetIOErrorHandler((XIOErrorHandler)x11_io_error);
|
XSetIOErrorHandler(x11_io_error);
|
||||||
server_init_atoms();
|
server_init_atoms();
|
||||||
server.screen = DefaultScreen(server.display);
|
server.screen = DefaultScreen(server.display);
|
||||||
server.root_win = RootWindow(server.display, server.screen);
|
server.root_win = RootWindow(server.display, server.screen);
|
||||||
server.desktop = get_current_desktop();
|
server.desktop = get_current_desktop();
|
||||||
|
server.has_shm = XShmQueryExtension(server.display);
|
||||||
|
|
||||||
// Needed since the config file uses '.' as decimal separator
|
// Needed since the config file uses '.' as decimal separator
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
@@ -215,17 +238,18 @@ void init(int argc, char **argv)
|
|||||||
setlinebuf(stdout);
|
setlinebuf(stdout);
|
||||||
setlinebuf(stderr);
|
setlinebuf(stderr);
|
||||||
default_config();
|
default_config();
|
||||||
|
handle_env_vars();
|
||||||
handle_cli_arguments(argc, argv);
|
handle_cli_arguments(argc, argv);
|
||||||
create_default_elements();
|
create_default_elements();
|
||||||
init_signals();
|
init_signals();
|
||||||
handle_env_vars();
|
|
||||||
|
|
||||||
init_X11_pre_config();
|
init_X11_pre_config();
|
||||||
if (!config_read()) {
|
if (!config_read()) {
|
||||||
fprintf(stderr, "tint2: Could not read config file.\n");
|
fprintf(stderr, "tint2: Could not read config file.\n");
|
||||||
print_usage();
|
print_usage();
|
||||||
|
warnings_for_timers = false;
|
||||||
cleanup();
|
cleanup();
|
||||||
return;
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_post_config();
|
init_post_config();
|
||||||
@@ -251,6 +275,8 @@ void cleanup()
|
|||||||
#ifdef ENABLE_BATTERY
|
#ifdef ENABLE_BATTERY
|
||||||
cleanup_battery();
|
cleanup_battery();
|
||||||
#endif
|
#endif
|
||||||
|
cleanup_separator();
|
||||||
|
cleanup_taskbar();
|
||||||
cleanup_panel();
|
cleanup_panel();
|
||||||
cleanup_config();
|
cleanup_config();
|
||||||
|
|
||||||
@@ -265,7 +291,7 @@ void cleanup()
|
|||||||
xsettings_client = NULL;
|
xsettings_client = NULL;
|
||||||
|
|
||||||
cleanup_server();
|
cleanup_server();
|
||||||
cleanup_timeout();
|
cleanup_timers();
|
||||||
|
|
||||||
if (server.display)
|
if (server.display)
|
||||||
XCloseDisplay(server.display);
|
XCloseDisplay(server.display);
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ void expand_exec(DesktopEntry *entry, const char *path)
|
|||||||
// %c -> Name
|
// %c -> Name
|
||||||
// %k -> path
|
// %k -> path
|
||||||
if (entry->exec) {
|
if (entry->exec) {
|
||||||
char *exec2 = calloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
|
size_t buf_size = strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
|
||||||
(entry->icon ? strlen(entry->icon) : 1) + 100,
|
(entry->icon ? strlen(entry->icon) : 1) + 100;
|
||||||
1);
|
char *exec2 = calloc(buf_size, 1);
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
// p will never point to an escaped char
|
// p will never point to an escaped char
|
||||||
for (p = entry->exec, q = exec2; *p; p++, q++) {
|
for (p = entry->exec, q = exec2; *p; p++, q++) {
|
||||||
@@ -82,23 +82,30 @@ void expand_exec(DesktopEntry *entry, const char *path)
|
|||||||
if (!*p)
|
if (!*p)
|
||||||
break;
|
break;
|
||||||
if (*p == 'i' && entry->icon != NULL) {
|
if (*p == 'i' && entry->icon != NULL) {
|
||||||
sprintf(q, "--icon '%s'", entry->icon);
|
snprintf(q, buf_size, "--icon '%s'", entry->icon);
|
||||||
|
char *old = q;
|
||||||
q += strlen("--icon ''");
|
q += strlen("--icon ''");
|
||||||
q += strlen(entry->icon);
|
q += strlen(entry->icon);
|
||||||
|
buf_size -= (size_t)(q - old);
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else if (*p == 'c' && entry->name != NULL) {
|
} else if (*p == 'c' && entry->name != NULL) {
|
||||||
sprintf(q, "'%s'", entry->name);
|
snprintf(q, buf_size, "'%s'", entry->name);
|
||||||
|
char *old = q;
|
||||||
q += strlen("''");
|
q += strlen("''");
|
||||||
q += strlen(entry->name);
|
q += strlen(entry->name);
|
||||||
|
buf_size -= (size_t)(q - old);
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else if (*p == 'c') {
|
} else if (*p == 'c') {
|
||||||
sprintf(q, "'%s'", path);
|
snprintf(q, buf_size, "'%s'", path);
|
||||||
|
char *old = q;
|
||||||
q += strlen("''");
|
q += strlen("''");
|
||||||
q += strlen(path);
|
q += strlen(path);
|
||||||
|
buf_size -= (size_t)(q - old);
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else if (*p == 'f' || *p == 'F') {
|
} else if (*p == 'f' || *p == 'F') {
|
||||||
sprintf(q, "%c%c", '%', *p);
|
snprintf(q, buf_size, "%c%c", '%', *p);
|
||||||
q += 2;
|
q += 2;
|
||||||
|
buf_size -= 2;
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else {
|
} else {
|
||||||
// We don't care about other expansions
|
// We don't care about other expansions
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ int parse_theme_line(char *line, char **key, char **value)
|
|||||||
return parse_dektop_line(line, key, value);
|
return parse_dektop_line(line, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList *icon_locations = NULL;
|
static GSList *icon_locations = NULL;
|
||||||
// Do not free the result.
|
// Do not free the result.
|
||||||
const GSList *get_icon_locations()
|
const GSList *get_icon_locations()
|
||||||
{
|
{
|
||||||
@@ -74,6 +74,21 @@ const GSList *get_icon_locations()
|
|||||||
return icon_locations;
|
return icon_locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GSList *icon_extensions = NULL;
|
||||||
|
const GSList *get_icon_extensions()
|
||||||
|
{
|
||||||
|
if (icon_extensions)
|
||||||
|
return icon_extensions;
|
||||||
|
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, ".png");
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, ".xpm");
|
||||||
|
#ifdef HAVE_RSVG
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, ".svg");
|
||||||
|
#endif
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, "");
|
||||||
|
return icon_extensions;
|
||||||
|
}
|
||||||
|
|
||||||
IconTheme *make_theme(const char *name)
|
IconTheme *make_theme(const char *name)
|
||||||
{
|
{
|
||||||
IconTheme *theme = calloc(1, sizeof(IconTheme));
|
IconTheme *theme = calloc(1, sizeof(IconTheme));
|
||||||
@@ -535,41 +550,42 @@ gint compare_theme_directories(gconstpointer a, gconstpointer b, gpointer size_q
|
|||||||
return abs(da->size - size) - abs(db->size - size);
|
return abs(da->size - size) - abs(db->size - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool is_full_path(const char *s)
|
||||||
|
{
|
||||||
|
if (!s)
|
||||||
|
return FALSE;
|
||||||
|
return s[0] == '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool file_exists(const char *path)
|
||||||
|
{
|
||||||
|
return g_file_test(path, G_FILE_TEST_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *icon_path_from_full_path(const char *s)
|
||||||
|
{
|
||||||
|
if (is_full_path(s) && file_exists(s))
|
||||||
|
return strdup(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
||||||
{
|
{
|
||||||
if (icon_name == NULL)
|
if (!icon_name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// If the icon_name is already a path and the file exists, return it
|
char *result = icon_path_from_full_path(icon_name);
|
||||||
if (strstr(icon_name, "/") == icon_name) {
|
if (result)
|
||||||
if (g_file_test(icon_name, G_FILE_TEST_EXISTS))
|
return result;
|
||||||
return strdup(icon_name);
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GSList *basenames = get_icon_locations();
|
const GSList *basenames = get_icon_locations();
|
||||||
GSList *extensions = NULL;
|
const GSList *extensions = get_icon_extensions();
|
||||||
extensions = g_slist_append(extensions, ".png");
|
|
||||||
extensions = g_slist_append(extensions, ".xpm");
|
|
||||||
#ifdef HAVE_RSVG
|
|
||||||
extensions = g_slist_append(extensions, ".svg");
|
|
||||||
#endif
|
|
||||||
// if the icon name already contains one of the extensions (e.g. vlc.png instead of vlc) add a special entry
|
|
||||||
for (GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
|
||||||
char *extension = (char *)ext->data;
|
|
||||||
if (strlen(icon_name) > strlen(extension) &&
|
|
||||||
strcmp(extension, icon_name + strlen(icon_name) - strlen(extension)) == 0) {
|
|
||||||
extensions = g_slist_append(extensions, "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList *theme;
|
GSList *theme;
|
||||||
|
|
||||||
// Best size match
|
// Best size match
|
||||||
// Contrary to the freedesktop spec, we are not choosing the closest icon in size, but the next larger icon
|
// Contrary to the freedesktop spec, we are not choosing the closest icon in size, but the next larger icon
|
||||||
// otherwise the quality is usually crap (for size 22, if you can choose 16 or 32, you're better with 32)
|
// otherwise the quality is worse when scaling up (for size 22, if you can choose 16 or 32, you're better with 32)
|
||||||
// We do fallback to the closest size if we cannot find a larger or equal icon
|
// We do fallback to the closest size if we cannot find a larger or equal icon
|
||||||
|
|
||||||
// These 3 variables are used for keeping the closest size match
|
// These 3 variables are used for keeping the closest size match
|
||||||
@@ -582,7 +598,7 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
char *next_larger = NULL;
|
char *next_larger = NULL;
|
||||||
GSList *next_larger_theme = NULL;
|
GSList *next_larger_theme = NULL;
|
||||||
|
|
||||||
int file_name_size = 4096;
|
size_t file_name_size = 4096;
|
||||||
char *file_name = calloc(file_name_size, 1);
|
char *file_name = calloc(file_name_size, 1);
|
||||||
|
|
||||||
for (theme = themes; theme; theme = g_slist_next(theme)) {
|
for (theme = themes; theme; theme = g_slist_next(theme)) {
|
||||||
@@ -607,7 +623,7 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
fprintf(stderr, "tint2: Searching directory: %s\n", ((IconThemeDir *)dir->data)->name);
|
fprintf(stderr, "tint2: Searching directory: %s\n", ((IconThemeDir *)dir->data)->name);
|
||||||
const GSList *base;
|
const GSList *base;
|
||||||
for (base = basenames; base; base = g_slist_next(base)) {
|
for (base = basenames; base; base = g_slist_next(base)) {
|
||||||
for (GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
for (const GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
||||||
char *base_name = (char *)base->data;
|
char *base_name = (char *)base->data;
|
||||||
char *theme_name = ((IconTheme *)theme->data)->name;
|
char *theme_name = ((IconTheme *)theme->data)->name;
|
||||||
char *dir_name = ((IconThemeDir *)dir->data)->name;
|
char *dir_name = ((IconThemeDir *)dir->data)->name;
|
||||||
@@ -621,7 +637,7 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
}
|
}
|
||||||
file_name[0] = 0;
|
file_name[0] = 0;
|
||||||
// filename = directory/$(themename)/subdirectory/iconname.extension
|
// filename = directory/$(themename)/subdirectory/iconname.extension
|
||||||
sprintf(file_name, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
snprintf(file_name, (size_t)file_name_size, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
||||||
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
@@ -662,12 +678,10 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
free(file_name);
|
free(file_name);
|
||||||
file_name = NULL;
|
file_name = NULL;
|
||||||
if (next_larger) {
|
if (next_larger) {
|
||||||
g_slist_free(extensions);
|
|
||||||
free(best_file_name);
|
free(best_file_name);
|
||||||
return next_larger;
|
return next_larger;
|
||||||
}
|
}
|
||||||
if (best_file_name) {
|
if (best_file_name) {
|
||||||
g_slist_free(extensions);
|
|
||||||
return best_file_name;
|
return best_file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,18 +690,18 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Searching unthemed icons\n");
|
fprintf(stderr, "tint2: Searching unthemed icons\n");
|
||||||
for (const GSList *base = basenames; base; base = g_slist_next(base)) {
|
for (const GSList *base = basenames; base; base = g_slist_next(base)) {
|
||||||
for (GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
for (const GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
||||||
char *base_name = (char *)base->data;
|
char *base_name = (char *)base->data;
|
||||||
char *extension = (char *)ext->data;
|
char *extension = (char *)ext->data;
|
||||||
file_name = calloc(strlen(base_name) + strlen(icon_name) + strlen(extension) + 100, 1);
|
size_t file_name_size2 = strlen(base_name) + strlen(icon_name) + strlen(extension) + 100;
|
||||||
|
file_name = calloc(file_name_size2, 1);
|
||||||
// filename = directory/iconname.extension
|
// filename = directory/iconname.extension
|
||||||
sprintf(file_name, "%s/%s%s", base_name, icon_name, extension);
|
snprintf(file_name, file_name_size2, "%s/%s%s", base_name, icon_name, extension);
|
||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
||||||
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Found %s\n", file_name);
|
fprintf(stderr, "tint2: Found %s\n", file_name);
|
||||||
g_slist_free(extensions);
|
|
||||||
return file_name;
|
return file_name;
|
||||||
} else {
|
} else {
|
||||||
free(file_name);
|
free(file_name);
|
||||||
@@ -697,7 +711,6 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_slist_free(extensions);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+32
-24
@@ -112,7 +112,7 @@ void init_launcher_panel(void *p)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// This will be recomputed on resize, we just initialize to a non-zero value
|
// This will be recomputed on resize, we just initialize to a non-zero value
|
||||||
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size : 24;
|
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size * panel->scale : 24;
|
||||||
|
|
||||||
launcher->area.on_screen = TRUE;
|
launcher->area.on_screen = TRUE;
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
@@ -174,11 +174,12 @@ void cleanup_launcher_theme(Launcher *launcher)
|
|||||||
|
|
||||||
int launcher_compute_icon_size(Launcher *launcher)
|
int launcher_compute_icon_size(Launcher *launcher)
|
||||||
{
|
{
|
||||||
|
Panel *panel = launcher->area.panel;
|
||||||
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
|
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
|
||||||
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
|
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
|
||||||
(2 * launcher->area.paddingy);
|
(2 * launcher->area.paddingy * panel->scale);
|
||||||
if (launcher_max_icon_size > 0 && icon_size > launcher_max_icon_size)
|
if (launcher_max_icon_size)
|
||||||
icon_size = launcher_max_icon_size;
|
icon_size = MIN(icon_size, launcher_max_icon_size * panel->scale);
|
||||||
return icon_size;
|
return icon_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ void launcher_compute_geometry(Launcher *launcher,
|
|||||||
int *icons_per_row,
|
int *icons_per_row,
|
||||||
int *margin)
|
int *margin)
|
||||||
{
|
{
|
||||||
|
Panel *panel = (Panel*)launcher->area.panel;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (GSList *l = launcher->list_icons; l; l = l->next) {
|
for (GSList *l = launcher->list_icons; l; l = l->next) {
|
||||||
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
||||||
@@ -204,25 +206,25 @@ void launcher_compute_geometry(Launcher *launcher,
|
|||||||
if (!count) {
|
if (!count) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
} else {
|
} else {
|
||||||
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy * panel->scale;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
*icons_per_column = (height + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
*icons_per_column = (height + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
||||||
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
|
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
||||||
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
|
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
|
||||||
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr * panel->scale +
|
||||||
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx);
|
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!count) {
|
if (!count) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
} else {
|
} else {
|
||||||
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy * panel->scale;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
*icons_per_row = (width + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
*icons_per_row = (width + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
||||||
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
|
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
||||||
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
|
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
|
||||||
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr * panel->scale +
|
||||||
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx);
|
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,6 +241,7 @@ int launcher_compute_desired_size(void *obj)
|
|||||||
gboolean resize_launcher(void *obj)
|
gboolean resize_launcher(void *obj)
|
||||||
{
|
{
|
||||||
Launcher *launcher = (Launcher *)obj;
|
Launcher *launcher = (Launcher *)obj;
|
||||||
|
Panel *panel = (Panel*)launcher->area.panel;
|
||||||
|
|
||||||
int size, icons_per_column, icons_per_row, margin;
|
int size, icons_per_column, icons_per_row, margin;
|
||||||
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
|
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
|
||||||
@@ -281,11 +284,11 @@ gboolean resize_launcher(void *obj)
|
|||||||
int posx, posy;
|
int posx, posy;
|
||||||
int start;
|
int start;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy * panel->scale + margin / 2;
|
||||||
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr;
|
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy * panel->scale + margin / 2;
|
||||||
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
|
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -300,17 +303,17 @@ gboolean resize_launcher(void *obj)
|
|||||||
// fprintf(stderr, "tint2: launcher %d : %d,%d\n", i, posx, posy);
|
// fprintf(stderr, "tint2: launcher %d : %d,%d\n", i, posx, posy);
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (i % icons_per_column) {
|
if (i % icons_per_column) {
|
||||||
posy += launcher->icon_size + launcher->area.paddingx;
|
posy += launcher->icon_size + launcher->area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (launcher->icon_size + launcher->area.paddingx);
|
posx += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % icons_per_row) {
|
if (i % icons_per_row) {
|
||||||
posx += launcher->icon_size + launcher->area.paddingx;
|
posx += launcher->icon_size + launcher->area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (launcher->icon_size + launcher->area.paddingx);
|
posy += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,7 +399,12 @@ void launcher_icon_dump_geometry(void *obj, int indent)
|
|||||||
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
|
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
|
||||||
{
|
{
|
||||||
Imlib_Image icon_scaled;
|
Imlib_Image icon_scaled;
|
||||||
if (original) {
|
if (!icon_size) {
|
||||||
|
icon_scaled = imlib_create_image(1, 1);
|
||||||
|
imlib_context_set_image(icon_scaled);
|
||||||
|
imlib_context_set_color(255, 255, 255, 255);
|
||||||
|
imlib_image_fill_rectangle(0, 0, icon_size, icon_size);
|
||||||
|
} else if (original) {
|
||||||
imlib_context_set_image(original);
|
imlib_context_set_image(original);
|
||||||
icon_scaled = imlib_create_cropped_scaled_image(0,
|
icon_scaled = imlib_create_cropped_scaled_image(0,
|
||||||
0,
|
0,
|
||||||
@@ -470,7 +478,7 @@ void launcher_load_icons(Launcher *launcher)
|
|||||||
launcherIcon->area.size_mode = LAYOUT_FIXED;
|
launcherIcon->area.size_mode = LAYOUT_FIXED;
|
||||||
launcherIcon->area._resize = NULL;
|
launcherIcon->area._resize = NULL;
|
||||||
launcherIcon->area._compute_desired_size = launcher_icon_compute_desired_size;
|
launcherIcon->area._compute_desired_size = launcher_icon_compute_desired_size;
|
||||||
sprintf(launcherIcon->area.name, "LauncherIcon %d", index);
|
snprintf(launcherIcon->area.name, sizeof(launcherIcon->area.name), "LauncherIcon %d", index);
|
||||||
launcherIcon->area.resize_needed = 0;
|
launcherIcon->area.resize_needed = 0;
|
||||||
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
|
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
|
||||||
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
|
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
|
||||||
|
|||||||
+20
-20
@@ -104,7 +104,7 @@ void handle_event_property_notify(XEvent *e)
|
|||||||
// Change name of desktops
|
// Change name of desktops
|
||||||
else if (at == server.atom._NET_DESKTOP_NAMES) {
|
else if (at == server.atom._NET_DESKTOP_NAMES) {
|
||||||
if (debug)
|
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();
|
update_desktop_names();
|
||||||
}
|
}
|
||||||
// Change desktops
|
// 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_DESKTOP_VIEWPORT || at == server.atom._NET_WORKAREA ||
|
||||||
at == server.atom._NET_CURRENT_DESKTOP) {
|
at == server.atom._NET_CURRENT_DESKTOP) {
|
||||||
if (debug)
|
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)
|
if (!taskbar_enabled)
|
||||||
return;
|
return;
|
||||||
int old_num_desktops = server.num_desktops;
|
int old_num_desktops = server.num_desktops;
|
||||||
@@ -202,7 +202,7 @@ void handle_event_property_notify(XEvent *e)
|
|||||||
// Window list
|
// Window list
|
||||||
else if (at == server.atom._NET_CLIENT_LIST) {
|
else if (at == server.atom._NET_CLIENT_LIST) {
|
||||||
if (debug)
|
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();
|
taskbar_refresh_tasklist();
|
||||||
update_all_taskbars_visibility();
|
update_all_taskbars_visibility();
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
@@ -210,12 +210,12 @@ void handle_event_property_notify(XEvent *e)
|
|||||||
// Change active
|
// Change active
|
||||||
else if (at == server.atom._NET_ACTIVE_WINDOW) {
|
else if (at == server.atom._NET_ACTIVE_WINDOW) {
|
||||||
if (debug)
|
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();
|
reset_active_task();
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
} else if (at == server.atom._XROOTPMAP_ID || at == server.atom._XROOTMAP_ID) {
|
} else if (at == server.atom._XROOTPMAP_ID || at == server.atom._XROOTMAP_ID) {
|
||||||
if (debug)
|
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
|
// change Wallpaper
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
set_panel_background(&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);
|
char *atom_name = XGetAtomName(server.display, at);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s %d: win = %ld, task = %s, atom = %s\n",
|
"%s %d: win = %ld, task = %s, atom = %s\n",
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
win,
|
win,
|
||||||
task ? (task->title ? task->title : "??") : "null",
|
task ? (task->title ? task->title : "??") : "null",
|
||||||
@@ -243,7 +243,7 @@ void handle_event_property_notify(XEvent *e)
|
|||||||
}
|
}
|
||||||
if (!task) {
|
if (!task) {
|
||||||
if (debug)
|
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) {
|
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
|
// 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
|
// 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 (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) {
|
||||||
if (task_update_title(task)) {
|
if (task_update_title(task)) {
|
||||||
if (g_tooltip.mapped && (g_tooltip.area == (Area *)task)) {
|
if (g_tooltip.mapped && (g_tooltip.area == (Area *)task)) {
|
||||||
tooltip_copy_text((Area *)task);
|
tooltip_update_contents_for((Area *)task);
|
||||||
tooltip_update();
|
tooltip_update();
|
||||||
}
|
}
|
||||||
if (taskbar_sort_method == TASKBAR_SORT_TITLE)
|
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);
|
Atom *atom_state = server_get_property(win, server.atom._NET_WM_STATE, XA_ATOM, &count);
|
||||||
for (int j = 0; j < count; j++) {
|
for (int j = 0; j < count; j++) {
|
||||||
char *atom_state_name = XGetAtomName(server.display, atom_state[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_name);
|
||||||
}
|
}
|
||||||
XFree(atom_state);
|
XFree(atom_state);
|
||||||
@@ -576,30 +576,30 @@ void handle_x_events()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare_fd_set(fd_set *fd_set, int *max_fd)
|
void prepare_fd_set(fd_set *set, int *max_fd)
|
||||||
{
|
{
|
||||||
FD_ZERO(fd_set);
|
FD_ZERO(set);
|
||||||
FD_SET(server.x11_fd, fd_set);
|
FD_SET(server.x11_fd, set);
|
||||||
*max_fd = server.x11_fd;
|
*max_fd = server.x11_fd;
|
||||||
if (sigchild_pipe_valid) {
|
if (sigchild_pipe_valid) {
|
||||||
FD_SET(sigchild_pipe[0], fd_set);
|
FD_SET(sigchild_pipe[0], set);
|
||||||
*max_fd = MAX(*max_fd, sigchild_pipe[0]);
|
*max_fd = MAX(*max_fd, sigchild_pipe[0]);
|
||||||
}
|
}
|
||||||
for (GList *l = panel_config.execp_list; l; l = l->next) {
|
for (GList *l = panel_config.execp_list; l; l = l->next) {
|
||||||
Execp *execp = (Execp *)l->data;
|
Execp *execp = (Execp *)l->data;
|
||||||
int fd = execp->backend->child_pipe_stdout;
|
int fd = execp->backend->child_pipe_stdout;
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
FD_SET(fd, fd_set);
|
FD_SET(fd, set);
|
||||||
*max_fd = MAX(*max_fd, fd);
|
*max_fd = MAX(*max_fd, fd);
|
||||||
}
|
}
|
||||||
fd = execp->backend->child_pipe_stderr;
|
fd = execp->backend->child_pipe_stderr;
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
FD_SET(fd, fd_set);
|
FD_SET(fd, set);
|
||||||
*max_fd = MAX(*max_fd, fd);
|
*max_fd = MAX(*max_fd, fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uevent_fd > 0) {
|
if (uevent_fd > 0) {
|
||||||
FD_SET(uevent_fd, fd_set);
|
FD_SET(uevent_fd, set);
|
||||||
*max_fd = MAX(*max_fd, uevent_fd);
|
*max_fd = MAX(*max_fd, uevent_fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -723,7 +723,7 @@ void handle_panel_refresh()
|
|||||||
if (debug_frames) {
|
if (debug_frames) {
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
char path[256];
|
char path[256];
|
||||||
sprintf(path, "tint2-%d-panel-%d-frame-%d.png", getpid(), i, frame);
|
snprintf(path, sizeof(path), "tint2-%d-panel-%d-frame-%d.png", getpid(), i, frame);
|
||||||
save_panel_screenshot(&panels[i], path);
|
save_panel_screenshot(&panels[i], path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -742,13 +742,13 @@ void run_tint2_event_loop()
|
|||||||
if (panel_refresh)
|
if (panel_refresh)
|
||||||
handle_panel_refresh();
|
handle_panel_refresh();
|
||||||
|
|
||||||
fd_set fd_set;
|
fd_set fds;
|
||||||
int max_fd;
|
int max_fd;
|
||||||
prepare_fd_set(&fd_set, &max_fd);
|
prepare_fd_set(&fds, &max_fd);
|
||||||
|
|
||||||
// Wait for an event and handle it
|
// Wait for an event and handle it
|
||||||
ts_event_read = 0;
|
ts_event_read = 0;
|
||||||
if (XPending(server.display) > 0 || select(max_fd + 1, &fd_set, 0, 0, get_next_timeout()) >= 0) {
|
if (XPending(server.display) > 0 || select(max_fd + 1, &fds, 0, 0, get_duration_to_next_timer_expiration()) >= 0) {
|
||||||
#ifdef HAVE_TRACING
|
#ifdef HAVE_TRACING
|
||||||
start_tracing((void*)run_tint2_event_loop);
|
start_tracing((void*)run_tint2_event_loop);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+88
-14
@@ -58,6 +58,7 @@ char *panel_window_name = NULL;
|
|||||||
gboolean debug_geometry;
|
gboolean debug_geometry;
|
||||||
gboolean debug_gradients;
|
gboolean debug_gradients;
|
||||||
gboolean startup_notifications;
|
gboolean startup_notifications;
|
||||||
|
gboolean debug_thumbnails;
|
||||||
|
|
||||||
gboolean panel_autohide;
|
gboolean panel_autohide;
|
||||||
int panel_autohide_show_timeout;
|
int panel_autohide_show_timeout;
|
||||||
@@ -78,11 +79,16 @@ int num_panels;
|
|||||||
GArray *backgrounds;
|
GArray *backgrounds;
|
||||||
GArray *gradients;
|
GArray *gradients;
|
||||||
|
|
||||||
|
double ui_scale_dpi_ref;
|
||||||
|
double ui_scale_monitor_size_ref;
|
||||||
|
|
||||||
Imlib_Image default_icon;
|
Imlib_Image default_icon;
|
||||||
char *default_font = NULL;
|
char *default_font = NULL;
|
||||||
|
|
||||||
void default_panel()
|
void default_panel()
|
||||||
{
|
{
|
||||||
|
ui_scale_dpi_ref = 0;
|
||||||
|
ui_scale_monitor_size_ref = 0;
|
||||||
panels = NULL;
|
panels = NULL;
|
||||||
num_panels = 0;
|
num_panels = 0;
|
||||||
default_icon = NULL;
|
default_icon = NULL;
|
||||||
@@ -129,8 +135,6 @@ void cleanup_panel()
|
|||||||
if (!panels)
|
if (!panels)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cleanup_taskbar();
|
|
||||||
|
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
Panel *p = &panels[i];
|
Panel *p = &panels[i];
|
||||||
|
|
||||||
@@ -144,7 +148,7 @@ void cleanup_panel()
|
|||||||
if (p->main_win)
|
if (p->main_win)
|
||||||
XDestroyWindow(server.display, p->main_win);
|
XDestroyWindow(server.display, p->main_win);
|
||||||
p->main_win = 0;
|
p->main_win = 0;
|
||||||
stop_timeout(p->autohide_timeout);
|
destroy_timer(&p->autohide_timer);
|
||||||
cleanup_freespace(p);
|
cleanup_freespace(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +210,7 @@ void init_panel()
|
|||||||
panels = calloc(num_panels, sizeof(Panel));
|
panels = calloc(num_panels, sizeof(Panel));
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
memcpy(&panels[i], &panel_config, sizeof(Panel));
|
memcpy(&panels[i], &panel_config, sizeof(Panel));
|
||||||
|
INIT_TIMER(panels[i].autohide_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -218,6 +223,17 @@ void init_panel()
|
|||||||
|
|
||||||
if (panel_config.monitor < 0)
|
if (panel_config.monitor < 0)
|
||||||
p->monitor = i;
|
p->monitor = i;
|
||||||
|
if (ui_scale_dpi_ref > 0 && server.monitors[p->monitor].dpi > 0)
|
||||||
|
p->scale = server.monitors[p->monitor].dpi / ui_scale_dpi_ref;
|
||||||
|
else
|
||||||
|
p->scale = 1;
|
||||||
|
if (ui_scale_monitor_size_ref > 0)
|
||||||
|
p->scale *= server.monitors[p->monitor].height / ui_scale_monitor_size_ref;
|
||||||
|
if (p->scale > 8 || p->scale < 1./8) {
|
||||||
|
fprintf(stderr, RED "tint2: panel %d having scale %g outside bounds, resetting to 1.0" RESET "\n", i + 1, p->scale);
|
||||||
|
p->scale = 1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, BLUE "tint2: panel %d uses scale %g " RESET "\n", i + 1, p->scale);
|
||||||
if (!p->area.bg)
|
if (!p->area.bg)
|
||||||
p->area.bg = &g_array_index(backgrounds, Background, 0);
|
p->area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
p->area.parent = p;
|
p->area.parent = p;
|
||||||
@@ -355,6 +371,19 @@ void panel_compute_size(Panel *panel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!panel->fractional_width) {
|
||||||
|
if (panel_horizontal)
|
||||||
|
panel->area.width *= panel->scale;
|
||||||
|
else
|
||||||
|
panel->area.height *= panel->scale;
|
||||||
|
}
|
||||||
|
if (!panel->fractional_height) {
|
||||||
|
if (panel_horizontal)
|
||||||
|
panel->area.height *= panel->scale;
|
||||||
|
else
|
||||||
|
panel->area.width *= panel->scale;
|
||||||
|
}
|
||||||
|
|
||||||
if (panel->area.width + panel->marginx > server.monitors[panel->monitor].width)
|
if (panel->area.width + panel->marginx > server.monitors[panel->monitor].width)
|
||||||
panel->area.width = server.monitors[panel->monitor].width - panel->marginx;
|
panel->area.width = server.monitors[panel->monitor].width - panel->marginx;
|
||||||
if (panel->area.height + panel->marginy > server.monitors[panel->monitor].height)
|
if (panel->area.height + panel->marginy > server.monitors[panel->monitor].height)
|
||||||
@@ -449,9 +478,9 @@ gboolean resize_panel(void *obj)
|
|||||||
if (!taskbar->area.on_screen)
|
if (!taskbar->area.on_screen)
|
||||||
continue;
|
continue;
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
taskbar->area.width = 2 * taskbar->area.paddingxlr;
|
taskbar->area.width = 2 * taskbar->area.paddingxlr * panel->scale;
|
||||||
else
|
else
|
||||||
taskbar->area.height = 2 * taskbar->area.paddingxlr;
|
taskbar->area.height = 2 * taskbar->area.paddingxlr * panel->scale;
|
||||||
if (taskbarname_enabled && taskbar->area.children) {
|
if (taskbarname_enabled && taskbar->area.children) {
|
||||||
Area *name = (Area *)taskbar->area.children->data;
|
Area *name = (Area *)taskbar->area.children->data;
|
||||||
if (name->on_screen) {
|
if (name->on_screen) {
|
||||||
@@ -468,9 +497,9 @@ gboolean resize_panel(void *obj)
|
|||||||
continue;
|
continue;
|
||||||
if (!first_child) {
|
if (!first_child) {
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
taskbar->area.width += taskbar->area.paddingx;
|
taskbar->area.width += taskbar->area.paddingx * panel->scale;
|
||||||
else
|
else
|
||||||
taskbar->area.height += taskbar->area.paddingy;
|
taskbar->area.height += taskbar->area.paddingy * panel->scale;
|
||||||
}
|
}
|
||||||
first_child = FALSE;
|
first_child = FALSE;
|
||||||
}
|
}
|
||||||
@@ -493,9 +522,11 @@ gboolean resize_panel(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distribute the remaining size between tasks
|
// Distribute the remaining size between taskbars
|
||||||
if (num_tasks > 0) {
|
if (num_tasks > 0) {
|
||||||
int task_size = total_size / num_tasks;
|
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++) {
|
for (int i = 0; i < panel->num_desktops; i++) {
|
||||||
Taskbar *taskbar = &panel->taskbar[i];
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
if (!taskbar->area.on_screen)
|
if (!taskbar->area.on_screen)
|
||||||
@@ -512,6 +543,49 @@ gboolean resize_panel(void *obj)
|
|||||||
taskbar->area.height += task_size;
|
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;
|
||||||
|
Taskbar *left_taskbar = NULL;
|
||||||
|
Taskbar *right_taskbar = NULL;
|
||||||
|
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;
|
||||||
|
left_taskbar = taskbar;
|
||||||
|
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;
|
||||||
|
right_taskbar = taskbar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (left_taskbar == right_taskbar)
|
||||||
|
left_taskbar->area.alignment = ALIGN_CENTER;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// No tasks => expand the first visible taskbar
|
// No tasks => expand the first visible taskbar
|
||||||
for (int i = 0; i < panel->num_desktops; i++) {
|
for (int i = 0; i < panel->num_desktops; i++) {
|
||||||
@@ -1020,15 +1094,15 @@ Button *click_button(Panel *panel, int x, int y)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_autohide_timeout(Panel *p)
|
void stop_autohide_timer(Panel *p)
|
||||||
{
|
{
|
||||||
stop_timeout(p->autohide_timeout);
|
stop_timer(&p->autohide_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void autohide_show(void *p)
|
void autohide_show(void *p)
|
||||||
{
|
{
|
||||||
Panel *panel = (Panel *)p;
|
Panel *panel = (Panel *)p;
|
||||||
stop_autohide_timeout(panel);
|
stop_autohide_timer(panel);
|
||||||
panel->is_hidden = 0;
|
panel->is_hidden = 0;
|
||||||
XMapSubwindows(server.display, panel->main_win); // systray windows
|
XMapSubwindows(server.display, panel->main_win); // systray windows
|
||||||
set_panel_window_geometry(panel);
|
set_panel_window_geometry(panel);
|
||||||
@@ -1040,7 +1114,7 @@ void autohide_show(void *p)
|
|||||||
void autohide_hide(void *p)
|
void autohide_hide(void *p)
|
||||||
{
|
{
|
||||||
Panel *panel = (Panel *)p;
|
Panel *panel = (Panel *)p;
|
||||||
stop_autohide_timeout(panel);
|
stop_autohide_timer(panel);
|
||||||
set_panel_layer(panel, panel_layer);
|
set_panel_layer(panel, panel_layer);
|
||||||
panel->is_hidden = TRUE;
|
panel->is_hidden = TRUE;
|
||||||
XUnmapSubwindows(server.display, panel->main_win); // systray windows
|
XUnmapSubwindows(server.display, panel->main_win); // systray windows
|
||||||
@@ -1052,7 +1126,7 @@ void autohide_trigger_show(Panel *p)
|
|||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
return;
|
return;
|
||||||
change_timeout(&p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p);
|
change_timer(&p->autohide_timer, true, panel_autohide_show_timeout, 0, autohide_show, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void autohide_trigger_hide(Panel *p)
|
void autohide_trigger_hide(Panel *p)
|
||||||
@@ -1067,7 +1141,7 @@ void autohide_trigger_hide(Panel *p)
|
|||||||
if (child)
|
if (child)
|
||||||
return; // mouse over one of the system tray icons
|
return; // mouse over one of the system tray icons
|
||||||
|
|
||||||
change_timeout(&p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
change_timer(&p->autohide_timer, true, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shrink_panel(Panel *panel)
|
void shrink_panel(Panel *panel)
|
||||||
|
|||||||
+6
-2
@@ -94,6 +94,9 @@ extern gboolean debug_geometry;
|
|||||||
extern gboolean debug_fps;
|
extern gboolean debug_fps;
|
||||||
extern double tracing_fps_threshold;
|
extern double tracing_fps_threshold;
|
||||||
extern gboolean debug_frames;
|
extern gboolean debug_frames;
|
||||||
|
extern gboolean debug_thumbnails;
|
||||||
|
extern double ui_scale_dpi_ref;
|
||||||
|
extern double ui_scale_monitor_size_ref;
|
||||||
|
|
||||||
typedef struct Panel {
|
typedef struct Panel {
|
||||||
Area area;
|
Area area;
|
||||||
@@ -116,6 +119,7 @@ typedef struct Panel {
|
|||||||
int mouse_pressed_alpha;
|
int mouse_pressed_alpha;
|
||||||
int mouse_pressed_saturation;
|
int mouse_pressed_saturation;
|
||||||
int mouse_pressed_brightness;
|
int mouse_pressed_brightness;
|
||||||
|
double scale;
|
||||||
|
|
||||||
// Per-panel parameters and states for Taskbar and Task
|
// Per-panel parameters and states for Taskbar and Task
|
||||||
GlobalTaskbar g_taskbar;
|
GlobalTaskbar g_taskbar;
|
||||||
@@ -143,7 +147,7 @@ typedef struct Panel {
|
|||||||
gboolean is_hidden;
|
gboolean is_hidden;
|
||||||
int hidden_width, hidden_height;
|
int hidden_width, hidden_height;
|
||||||
Pixmap hidden_pixmap;
|
Pixmap hidden_pixmap;
|
||||||
timeout *autohide_timeout;
|
Timer autohide_timer;
|
||||||
} Panel;
|
} Panel;
|
||||||
|
|
||||||
extern Panel panel_config;
|
extern Panel panel_config;
|
||||||
@@ -165,7 +169,7 @@ gboolean resize_panel(void *obj);
|
|||||||
void render_panel(Panel *panel);
|
void render_panel(Panel *panel);
|
||||||
void shrink_panel(Panel *panel);
|
void shrink_panel(Panel *panel);
|
||||||
void _schedule_panel_redraw(const char *file, const char *function, const int line);
|
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 set_panel_items_order(Panel *p);
|
||||||
void place_panel_all_desktops(Panel *p);
|
void place_panel_all_desktops(Panel *p);
|
||||||
|
|||||||
@@ -115,31 +115,33 @@ void cleanup_separator()
|
|||||||
int separator_compute_desired_size(void *obj)
|
int separator_compute_desired_size(void *obj)
|
||||||
{
|
{
|
||||||
Separator *separator = (Separator *)obj;
|
Separator *separator = (Separator *)obj;
|
||||||
|
Panel *panel = (Panel*)separator->area.panel;
|
||||||
if (!separator->area.on_screen)
|
if (!separator->area.on_screen)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
return separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr * panel->scale + left_right_border_width(&separator->area);
|
||||||
else
|
else
|
||||||
return separator->thickness + 2 * separator->area.paddingxlr + top_bottom_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean resize_separator(void *obj)
|
gboolean resize_separator(void *obj)
|
||||||
{
|
{
|
||||||
Separator *separator = (Separator *)obj;
|
Separator *separator = (Separator *)obj;
|
||||||
|
Panel *panel = (Panel*)separator->area.panel;
|
||||||
if (!separator->area.on_screen)
|
if (!separator->area.on_screen)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
separator->area.width =
|
separator->area.width =
|
||||||
separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr * panel->scale + left_right_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.height - 2 * separator->area.paddingy - top_bottom_border_width(&separator->area);
|
separator->area.height - 2 * separator->area.paddingy * panel->scale - top_bottom_border_width(&separator->area);
|
||||||
} else {
|
} else {
|
||||||
separator->area.height =
|
separator->area.height =
|
||||||
separator->thickness + 2 * separator->area.paddingxlr + top_bottom_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.width - 2 * separator->area.paddingy - left_right_border_width(&separator->area);
|
separator->area.width - 2 * separator->area.paddingy * panel->scale - left_right_border_width(&separator->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule_redraw(&separator->area);
|
schedule_redraw(&separator->area);
|
||||||
|
|||||||
+74
-88
@@ -141,11 +141,12 @@ void init_systray_panel(void *p)
|
|||||||
|
|
||||||
void systray_compute_geometry(int *size)
|
void systray_compute_geometry(int *size)
|
||||||
{
|
{
|
||||||
|
Panel *panel = (Panel*)systray.area.panel;
|
||||||
systray.icon_size = panel_horizontal ? systray.area.height : systray.area.width;
|
systray.icon_size = panel_horizontal ? systray.area.height : systray.area.width;
|
||||||
systray.icon_size -=
|
systray.icon_size -=
|
||||||
MAX(left_right_border_width(&systray.area), top_bottom_border_width(&systray.area)) + 2 * systray.area.paddingy;
|
MAX(left_right_border_width(&systray.area), top_bottom_border_width(&systray.area)) + 2 * systray.area.paddingy * panel->scale;
|
||||||
if (systray_max_icon_size > 0)
|
if (systray_max_icon_size > 0)
|
||||||
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size);
|
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size * panel->scale);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (GSList *l = systray.list_icons; l; l = l->next) {
|
for (GSList *l = systray.list_icons; l; l = l->next) {
|
||||||
@@ -153,24 +154,24 @@ void systray_compute_geometry(int *size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
int height = systray.area.height - top_bottom_border_width(&systray.area) - 2 * systray.area.paddingy;
|
int height = systray.area.height - top_bottom_border_width(&systray.area) - 2 * systray.area.paddingy * panel->scale;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
systray.icons_per_column = (height + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
systray.icons_per_column = (height + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx) - systray.icon_size;
|
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
||||||
systray.icons_per_row = count / systray.icons_per_column + (count % systray.icons_per_column != 0);
|
systray.icons_per_row = count / systray.icons_per_column + (count % systray.icons_per_column != 0);
|
||||||
*size = left_right_border_width(&systray.area) + 2 * systray.area.paddingxlr +
|
*size = left_right_border_width(&systray.area) + 2 * systray.area.paddingxlr * panel->scale +
|
||||||
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx);
|
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx * panel->scale);
|
||||||
} else {
|
} else {
|
||||||
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy;
|
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy * panel->scale;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
systray.icons_per_row = (width + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
systray.icons_per_row = (width + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx) - systray.icon_size;
|
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
||||||
systray.icons_per_column = count / systray.icons_per_row + (count % systray.icons_per_row != 0);
|
systray.icons_per_column = count / systray.icons_per_row + (count % systray.icons_per_row != 0);
|
||||||
*size = top_bottom_border_width(&systray.area) + (2 * systray.area.paddingxlr) +
|
*size = top_bottom_border_width(&systray.area) + (2 * systray.area.paddingxlr * panel->scale) +
|
||||||
(systray.icon_size * systray.icons_per_column) +
|
(systray.icon_size * systray.icons_per_column) +
|
||||||
((systray.icons_per_column - 1) * systray.area.paddingx);
|
((systray.icons_per_column - 1) * systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +185,7 @@ int systray_compute_desired_size(void *obj)
|
|||||||
gboolean resize_systray(void *obj)
|
gboolean resize_systray(void *obj)
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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;
|
int size;
|
||||||
systray_compute_geometry(&size);
|
systray_compute_geometry(&size);
|
||||||
@@ -227,7 +228,7 @@ gboolean resize_systray(void *obj)
|
|||||||
void draw_systray(void *obj, cairo_t *c)
|
void draw_systray(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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 (systray_composited) {
|
||||||
if (render_background)
|
if (render_background)
|
||||||
XFreePixmap(server.display, render_background);
|
XFreePixmap(server.display, render_background);
|
||||||
@@ -257,7 +258,7 @@ void systray_dump_geometry(void *obj, int indent)
|
|||||||
for (GSList *l = tray->list_icons; l; l = l->next) {
|
for (GSList *l = tray->list_icons; l; l = l->next) {
|
||||||
TrayWindow *traywin = (TrayWindow *)l->data;
|
TrayWindow *traywin = (TrayWindow *)l->data;
|
||||||
fprintf(stderr,
|
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,
|
indent,
|
||||||
"",
|
"",
|
||||||
traywin->x,
|
traywin->x,
|
||||||
@@ -271,7 +272,7 @@ void systray_dump_geometry(void *obj, int indent)
|
|||||||
void on_change_systray(void *obj)
|
void on_change_systray(void *obj)
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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)
|
if (systray.icons_per_column == 0 || systray.icons_per_row == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -281,13 +282,13 @@ void on_change_systray(void *obj)
|
|||||||
int posx, posy;
|
int posx, posy;
|
||||||
int start;
|
int start;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
posy = start = top_border_width(&panel->area) + panel->area.paddingy + top_border_width(&systray.area) +
|
posy = start = top_border_width(&panel->area) + panel->area.paddingy * panel->scale + top_border_width(&systray.area) +
|
||||||
systray.area.paddingy + systray.margin / 2;
|
systray.area.paddingy * panel->scale + systray.margin / 2;
|
||||||
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr;
|
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&panel->area) + panel->area.paddingy + left_border_width(&systray.area) +
|
posx = start = left_border_width(&panel->area) + panel->area.paddingy * panel->scale + left_border_width(&systray.area) +
|
||||||
systray.area.paddingy + systray.margin / 2;
|
systray.area.paddingy * panel->scale + systray.margin / 2;
|
||||||
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr;
|
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrayWindow *traywin;
|
TrayWindow *traywin;
|
||||||
@@ -301,7 +302,7 @@ void on_change_systray(void *obj)
|
|||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s:%d win = %lu (%s), parent = %lu, x = %d, y = %d\n",
|
"%s:%d win = %lu (%s), parent = %lu, x = %d, y = %d\n",
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name,
|
traywin->name,
|
||||||
@@ -312,17 +313,17 @@ void on_change_systray(void *obj)
|
|||||||
traywin->height = systray.icon_size;
|
traywin->height = systray.icon_size;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (i % systray.icons_per_column) {
|
if (i % systray.icons_per_column) {
|
||||||
posy += systray.icon_size + systray.area.paddingx;
|
posy += systray.icon_size + systray.area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (systray.icon_size + systray.area.paddingx);
|
posx += (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % systray.icons_per_row) {
|
if (i % systray.icons_per_row) {
|
||||||
posx += systray.icon_size + systray.area.paddingx;
|
posx += systray.icon_size + systray.area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (systray.icon_size + systray.area.paddingx);
|
posy += (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +359,7 @@ void on_change_systray(void *obj)
|
|||||||
void start_net()
|
void start_net()
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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) {
|
if (net_sel_win) {
|
||||||
// protocol already started
|
// protocol already started
|
||||||
if (!systray_enabled)
|
if (!systray_enabled)
|
||||||
@@ -464,7 +465,7 @@ void start_net()
|
|||||||
|
|
||||||
fprintf(stderr, GREEN "tint2: systray started" RESET "\n");
|
fprintf(stderr, GREEN "tint2: systray started" RESET "\n");
|
||||||
if (systray_profile)
|
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;
|
XClientMessageEvent ev;
|
||||||
ev.type = ClientMessage;
|
ev.type = ClientMessage;
|
||||||
ev.window = server.root_win;
|
ev.window = server.root_win;
|
||||||
@@ -481,7 +482,7 @@ void start_net()
|
|||||||
void handle_systray_event(XClientMessageEvent *e)
|
void handle_systray_event(XClientMessageEvent *e)
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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;
|
Window win;
|
||||||
unsigned long opcode = e->data.l[1];
|
unsigned long opcode = e->data.l[1];
|
||||||
@@ -509,7 +510,7 @@ void handle_systray_event(XClientMessageEvent *e)
|
|||||||
void stop_net()
|
void stop_net()
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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) {
|
if (systray.list_icons) {
|
||||||
// remove_icon change systray.list_icons
|
// remove_icon change systray.list_icons
|
||||||
while (systray.list_icons)
|
while (systray.list_icons)
|
||||||
@@ -529,7 +530,7 @@ gboolean error;
|
|||||||
int window_error_handler(Display *d, XErrorEvent *e)
|
int window_error_handler(Display *d, XErrorEvent *e)
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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;
|
error = TRUE;
|
||||||
if (e->error_code != BadWindow) {
|
if (e->error_code != BadWindow) {
|
||||||
fprintf(stderr, RED "tint2: systray: error code %d" RESET "\n", e->error_code);
|
fprintf(stderr, RED "tint2: systray: error code %d" RESET "\n", e->error_code);
|
||||||
@@ -623,7 +624,7 @@ gboolean add_icon(Window win)
|
|||||||
|
|
||||||
char *name = get_window_name(win);
|
char *name = get_window_name(win);
|
||||||
if (systray_profile)
|
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;
|
Panel *panel = systray.area.panel;
|
||||||
|
|
||||||
// Get the process ID of the application that created the window
|
// Get the process ID of the application that created the window
|
||||||
@@ -679,7 +680,7 @@ gboolean add_icon(Window win)
|
|||||||
win,
|
win,
|
||||||
name,
|
name,
|
||||||
pid,
|
pid,
|
||||||
attr.visual,
|
(void*)attr.visual,
|
||||||
attr.colormap,
|
attr.colormap,
|
||||||
attr.depth,
|
attr.depth,
|
||||||
attr.width,
|
attr.width,
|
||||||
@@ -730,6 +731,8 @@ gboolean add_icon(Window win)
|
|||||||
traywin->pid = pid;
|
traywin->pid = pid;
|
||||||
traywin->name = name;
|
traywin->name = name;
|
||||||
traywin->chrono = chrono;
|
traywin->chrono = chrono;
|
||||||
|
INIT_TIMER(traywin->render_timer);
|
||||||
|
INIT_TIMER(traywin->resize_timer);
|
||||||
chrono++;
|
chrono++;
|
||||||
|
|
||||||
show(&systray.area);
|
show(&systray.area);
|
||||||
@@ -748,14 +751,14 @@ gboolean add_icon(Window win)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (systray_profile)
|
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
|
// Resize and redraw the systray
|
||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
systray.area.resize_needed = TRUE;
|
systray.area.resize_needed = TRUE;
|
||||||
panel->area.resize_needed = TRUE;
|
panel->area.resize_needed = TRUE;
|
||||||
@@ -770,7 +773,7 @@ gboolean reparent_icon(TrayWindow *traywin)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -832,7 +835,7 @@ gboolean reparent_icon(TrayWindow *traywin)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -846,7 +849,7 @@ gboolean embed_icon(TrayWindow *traywin)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -903,7 +906,7 @@ gboolean embed_icon(TrayWindow *traywin)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -917,7 +920,7 @@ void remove_icon(TrayWindow *traywin)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -940,8 +943,8 @@ void remove_icon(TrayWindow *traywin)
|
|||||||
XDestroyWindow(server.display, traywin->parent);
|
XDestroyWindow(server.display, traywin->parent);
|
||||||
XSync(server.display, False);
|
XSync(server.display, False);
|
||||||
XSetErrorHandler(old);
|
XSetErrorHandler(old);
|
||||||
stop_timeout(traywin->render_timeout);
|
destroy_timer(&traywin->render_timer);
|
||||||
stop_timeout(traywin->resize_timeout);
|
destroy_timer(&traywin->resize_timer);
|
||||||
free(traywin->name);
|
free(traywin->name);
|
||||||
if (traywin->image) {
|
if (traywin->image) {
|
||||||
imlib_context_set_image(traywin->image);
|
imlib_context_set_image(traywin->image);
|
||||||
@@ -963,7 +966,7 @@ void remove_icon(TrayWindow *traywin)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
systray.area.resize_needed = TRUE;
|
systray.area.resize_needed = TRUE;
|
||||||
panel->area.resize_needed = TRUE;
|
panel->area.resize_needed = TRUE;
|
||||||
@@ -1055,9 +1058,8 @@ void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
|
|||||||
if (traywin->bad_size_counter < min_bad_resize_events) {
|
if (traywin->bad_size_counter < min_bad_resize_events) {
|
||||||
systray_resize_icon(traywin);
|
systray_resize_icon(traywin);
|
||||||
} else {
|
} else {
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, fast_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(fast_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (traywin->bad_size_counter == max_bad_resize_events) {
|
if (traywin->bad_size_counter == max_bad_resize_events) {
|
||||||
@@ -1071,14 +1073,13 @@ void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
|
|||||||
// FIXME Normally we should force the icon to resize fill_color to the size we resized it to when we
|
// FIXME Normally we should force the icon to resize fill_color to the size we resized it to when we
|
||||||
// embedded it.
|
// embedded it.
|
||||||
// However this triggers a resize loop in new versions of GTK, which we must avoid.
|
// However this triggers a resize loop in new versions of GTK, which we must avoid.
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, slow_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Correct size
|
// Correct size
|
||||||
stop_timeout(traywin->resize_timeout);
|
stop_timer(&traywin->resize_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize and redraw the systray
|
// Resize and redraw the systray
|
||||||
@@ -1086,7 +1087,7 @@ void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
refresh_systray = TRUE;
|
refresh_systray = TRUE;
|
||||||
@@ -1135,9 +1136,8 @@ void systray_resize_request_event(TrayWindow *traywin, XEvent *e)
|
|||||||
if (traywin->bad_size_counter < min_bad_resize_events) {
|
if (traywin->bad_size_counter < min_bad_resize_events) {
|
||||||
systray_resize_icon(traywin);
|
systray_resize_icon(traywin);
|
||||||
} else {
|
} else {
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, fast_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(fast_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (traywin->bad_size_counter == max_bad_resize_events) {
|
if (traywin->bad_size_counter == max_bad_resize_events) {
|
||||||
@@ -1150,14 +1150,13 @@ void systray_resize_request_event(TrayWindow *traywin, XEvent *e)
|
|||||||
// Delayed resize
|
// Delayed resize
|
||||||
// FIXME Normally we should force the icon to resize to the size we resized it to when we embedded it.
|
// FIXME Normally we should force the icon to resize to the size we resized it to when we embedded it.
|
||||||
// However this triggers a resize loop in some versions of GTK, which we must avoid.
|
// However this triggers a resize loop in some versions of GTK, which we must avoid.
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, slow_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Correct size
|
// Correct size
|
||||||
stop_timeout(traywin->resize_timeout);
|
stop_timer(&traywin->resize_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize and redraw the systray
|
// Resize and redraw the systray
|
||||||
@@ -1165,7 +1164,7 @@ void systray_resize_request_event(TrayWindow *traywin, XEvent *e)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
refresh_systray = TRUE;
|
refresh_systray = TRUE;
|
||||||
@@ -1177,7 +1176,7 @@ void systray_destroy_event(TrayWindow *traywin)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -1212,7 +1211,7 @@ void systray_render_icon_composited(void *t)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -1224,13 +1223,12 @@ void systray_render_icon_composited(void *t)
|
|||||||
if (compare_timespecs(&earliest_render, &now) > 0) {
|
if (compare_timespecs(&earliest_render, &now) > 0) {
|
||||||
traywin->num_fast_renders++;
|
traywin->num_fast_renders++;
|
||||||
if (traywin->num_fast_renders > max_fast_refreshes) {
|
if (traywin->num_fast_renders > max_fast_refreshes) {
|
||||||
traywin->render_timeout =
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon_composited, traywin);
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
|
||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -1244,23 +1242,19 @@ void systray_render_icon_composited(void *t)
|
|||||||
|
|
||||||
if (traywin->width == 0 || traywin->height == 0) {
|
if (traywin->width == 0 || traywin->height == 0) {
|
||||||
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
|
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
|
||||||
traywin->render_timeout =
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon_composited, traywin);
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
|
||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traywin->render_timeout) {
|
stop_timer(&traywin->render_timer);
|
||||||
stop_timeout(traywin->render_timeout);
|
|
||||||
traywin->render_timeout = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// good systray icons support 32 bit depth, but some icons are still 24 bit.
|
// good systray icons support 32 bit depth, but some icons are still 24 bit.
|
||||||
// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
|
// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
|
||||||
@@ -1381,7 +1375,7 @@ void systray_render_icon_composited(void *t)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -1419,13 +1413,11 @@ void systray_render_icon(void *t)
|
|||||||
// fprintf(stderr,
|
// fprintf(stderr,
|
||||||
// YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
// YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
||||||
// profiling_get_time(),
|
// profiling_get_time(),
|
||||||
// __FUNCTION__,
|
// __func__,
|
||||||
// __LINE__,
|
// __LINE__,
|
||||||
// traywin->win,
|
// traywin->win,
|
||||||
// traywin->name);
|
// traywin->name);
|
||||||
stop_timeout(traywin->render_timeout);
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
||||||
traywin->render_timeout =
|
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1433,7 +1425,7 @@ void systray_render_icon(void *t)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[%f] %s:%d win = %lu (%s)\n",
|
"[%f] %s:%d win = %lu (%s)\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -1448,25 +1440,19 @@ void systray_render_icon(void *t)
|
|||||||
unsigned int width, height, depth;
|
unsigned int width, height, depth;
|
||||||
Window root;
|
Window root;
|
||||||
if (!XGetGeometry(server.display, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
if (!XGetGeometry(server.display, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
||||||
stop_timeout(traywin->render_timeout);
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
||||||
if (!traywin->render_timeout)
|
|
||||||
traywin->render_timeout =
|
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
|
||||||
systray_render_icon_from_image(traywin);
|
systray_render_icon_from_image(traywin);
|
||||||
XSetErrorHandler(old);
|
XSetErrorHandler(old);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (xpos != 0 || ypos != 0 || width != traywin->width || height != traywin->height) {
|
if (xpos != 0 || ypos != 0 || width != traywin->width || height != traywin->height) {
|
||||||
stop_timeout(traywin->render_timeout);
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
||||||
if (!traywin->render_timeout)
|
|
||||||
traywin->render_timeout =
|
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
|
||||||
systray_render_icon_from_image(traywin);
|
systray_render_icon_from_image(traywin);
|
||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
||||||
profiling_get_time(),
|
profiling_get_time(),
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
__LINE__,
|
__LINE__,
|
||||||
traywin->win,
|
traywin->win,
|
||||||
traywin->name);
|
traywin->name);
|
||||||
@@ -1500,7 +1486,7 @@ void systray_render_icon(void *t)
|
|||||||
void refresh_systray_icons()
|
void refresh_systray_icons()
|
||||||
{
|
{
|
||||||
if (systray_profile)
|
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;
|
TrayWindow *traywin;
|
||||||
GSList *l;
|
GSList *l;
|
||||||
for (l = systray.list_icons; l; l = l->next) {
|
for (l = systray.list_icons; l; l = l->next) {
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ typedef struct {
|
|||||||
// Members used for rendering
|
// Members used for rendering
|
||||||
struct timespec time_last_render;
|
struct timespec time_last_render;
|
||||||
int num_fast_renders;
|
int num_fast_renders;
|
||||||
timeout *render_timeout;
|
Timer render_timer;
|
||||||
// Members used for resizing
|
// Members used for resizing
|
||||||
int bad_size_counter;
|
int bad_size_counter;
|
||||||
struct timespec time_last_resize;
|
struct timespec time_last_resize;
|
||||||
timeout *resize_timeout;
|
Timer resize_timer;
|
||||||
// Icon contents if we are compositing the icon, otherwise null
|
// Icon contents if we are compositing the icon, otherwise null
|
||||||
Imlib_Image image;
|
Imlib_Image image;
|
||||||
// XDamage
|
// XDamage
|
||||||
|
|||||||
+167
-67
@@ -35,11 +35,13 @@
|
|||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
timeout *urgent_timeout;
|
Timer urgent_timer;
|
||||||
GSList *urgent_list;
|
GSList *urgent_list;
|
||||||
|
|
||||||
void task_dump_geometry(void *obj, int indent);
|
void task_dump_geometry(void *obj, int indent);
|
||||||
int task_compute_desired_size(void *obj);
|
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)
|
char *task_get_tooltip(void *obj)
|
||||||
{
|
{
|
||||||
@@ -47,6 +49,17 @@ char *task_get_tooltip(void *obj)
|
|||||||
return strdup(t->title);
|
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)
|
Task *add_task(Window win)
|
||||||
{
|
{
|
||||||
if (!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.has_mouse_press_effect = panel_config.mouse_effects;
|
||||||
task_template.area._dump_geometry = task_dump_geometry;
|
task_template.area._dump_geometry = task_dump_geometry;
|
||||||
task_template.area._is_under_mouse = full_width_area_is_under_mouse;
|
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.win = win;
|
||||||
task_template.desktop = get_window_desktop(win);
|
task_template.desktop = get_window_desktop(win);
|
||||||
task_template.area.panel = &panels[monitor];
|
task_template.area.panel = &panels[monitor];
|
||||||
@@ -93,9 +107,20 @@ Task *add_task(Window win)
|
|||||||
(int)win,
|
(int)win,
|
||||||
task_template.title ? task_template.title : "null");
|
task_template.title ? task_template.title : "null");
|
||||||
|
|
||||||
// fprintf(stderr, "tint2: %s %d: win = %ld, task = %s\n", __FUNCTION__, __LINE__, win, task_template.title ?
|
// get application name
|
||||||
// task_template.title : "??");
|
// use res_class property of WM_CLASS as res_name is easily overridable by user
|
||||||
// fprintf(stderr, "tint2: new task %s win %u: desktop %d, monitor %d\n", new_task.title, win, new_task.desktop, monitor);
|
XClassHint *classhint = XAllocClassHint();
|
||||||
|
if (classhint && XGetClassHint(server.display, win, classhint))
|
||||||
|
task_template.application = strdup(classhint->res_class);
|
||||||
|
else
|
||||||
|
task_template.application = strdup("Untitled");
|
||||||
|
if (classhint) {
|
||||||
|
if (classhint->res_name)
|
||||||
|
XFree(classhint->res_name);
|
||||||
|
if (classhint->res_class)
|
||||||
|
XFree(classhint->res_class);
|
||||||
|
XFree(classhint);
|
||||||
|
}
|
||||||
|
|
||||||
GPtrArray *task_buttons = g_ptr_array_new();
|
GPtrArray *task_buttons = g_ptr_array_new();
|
||||||
for (int j = 0; j < panels[monitor].num_desktops; j++) {
|
for (int j = 0; j < panels[monitor].num_desktops; j++) {
|
||||||
@@ -110,6 +135,7 @@ Task *add_task(Window win)
|
|||||||
task_instance->area._dump_geometry = task_dump_geometry;
|
task_instance->area._dump_geometry = task_dump_geometry;
|
||||||
task_instance->area._is_under_mouse = full_width_area_is_under_mouse;
|
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._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->win = task_template.win;
|
||||||
task_instance->desktop = task_template.desktop;
|
task_instance->desktop = task_template.desktop;
|
||||||
task_instance->win_x = task_template.win_x;
|
task_instance->win_x = task_template.win_x;
|
||||||
@@ -118,12 +144,17 @@ Task *add_task(Window win)
|
|||||||
task_instance->win_h = task_template.win_h;
|
task_instance->win_h = task_template.win_h;
|
||||||
task_instance->current_state = TASK_UNDEFINED; // to update the current state later in set_task_state...
|
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) {
|
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->area.on_screen = always_show_all_desktop_tasks;
|
||||||
}
|
}
|
||||||
task_instance->title = task_template.title;
|
task_instance->title = task_template.title;
|
||||||
if (panels[monitor].g_task.tooltip_enabled)
|
task_instance->application = task_template.application;
|
||||||
|
if (panels[monitor].g_task.tooltip_enabled) {
|
||||||
task_instance->area._get_tooltip_text = task_get_tooltip;
|
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) {
|
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
|
||||||
task_instance->icon[k] = task_template.icon[k];
|
task_instance->icon[k] = task_template.icon[k];
|
||||||
task_instance->icon_hover[k] = task_template.icon_hover[k];
|
task_instance->icon_hover[k] = task_template.icon_hover[k];
|
||||||
@@ -186,9 +217,6 @@ void remove_task(Task *task)
|
|||||||
if (!task)
|
if (!task)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// fprintf(stderr, "tint2: %s %d: win = %ld, task = %s\n", __FUNCTION__, __LINE__, task->win, task->title ? task->title :
|
|
||||||
// "??");
|
|
||||||
|
|
||||||
if (taskbar_mode == MULTI_DESKTOP) {
|
if (taskbar_mode == MULTI_DESKTOP) {
|
||||||
Panel *panel = task->area.panel;
|
Panel *panel = task->area.panel;
|
||||||
panel->area.resize_needed = 1;
|
panel->area.resize_needed = 1;
|
||||||
@@ -196,11 +224,14 @@ void remove_task(Task *task)
|
|||||||
|
|
||||||
Window win = task->win;
|
Window win = task->win;
|
||||||
|
|
||||||
// free title and icon just for the first task
|
// free title, icon and application name just for the first task
|
||||||
// even with task_on_all_desktop and with task_on_all_panel
|
// 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)
|
if (task->title)
|
||||||
free(task->title);
|
free(task->title);
|
||||||
|
if (task->thumbnail)
|
||||||
|
cairo_surface_destroy(task->thumbnail);
|
||||||
|
if (task->application)
|
||||||
|
free(task->application);
|
||||||
task_remove_icon(task);
|
task_remove_icon(task);
|
||||||
|
|
||||||
GPtrArray *task_buttons = g_hash_table_lookup(win_to_task, &win);
|
GPtrArray *task_buttons = g_hash_table_lookup(win_to_task, &win);
|
||||||
@@ -212,6 +243,8 @@ void remove_task(Task *task)
|
|||||||
task_drag = 0;
|
task_drag = 0;
|
||||||
if (g_slist_find(urgent_list, task2))
|
if (g_slist_find(urgent_list, task2))
|
||||||
del_urgent(task2);
|
del_urgent(task2);
|
||||||
|
if (g_tooltip.area == &task2->area)
|
||||||
|
tooltip_hide(NULL);
|
||||||
remove_area((Area *)task2);
|
remove_area((Area *)task2);
|
||||||
free(task2);
|
free(task2);
|
||||||
}
|
}
|
||||||
@@ -266,36 +299,23 @@ gboolean task_update_title(Task *task)
|
|||||||
return TRUE;
|
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;
|
Imlib_Image img = NULL;
|
||||||
|
|
||||||
if (!img) {
|
if (!img) {
|
||||||
int len;
|
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 (data) {
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
// get ARGB icon
|
// get ARGB icon
|
||||||
int w, h;
|
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) {
|
if (tmp_data) {
|
||||||
DATA32 icon_data[w * h];
|
DATA32 icon_data[w * h];
|
||||||
for (int j = 0; j < w * h; ++j)
|
for (int j = 0; j < w * h; ++j)
|
||||||
icon_data[j] = tmp_data[j];
|
icon_data[j] = tmp_data[j];
|
||||||
img = imlib_create_image_using_copied_data(w, h, icon_data);
|
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);
|
XFree(data);
|
||||||
@@ -303,7 +323,7 @@ void task_update_icon(Task *task)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!img) {
|
if (!img) {
|
||||||
XWMHints *hints = XGetWMHints(server.display, task->win);
|
XWMHints *hints = XGetWMHints(server.display, win);
|
||||||
if (hints) {
|
if (hints) {
|
||||||
if (hints->flags & IconPixmapHint && hints->icon_pixmap != 0) {
|
if (hints->flags & IconPixmapHint && hints->icon_pixmap != 0) {
|
||||||
// get width, height and depth for the pixmap
|
// get width, height and depth for the pixmap
|
||||||
@@ -315,13 +335,6 @@ void task_update_icon(Task *task)
|
|||||||
XGetGeometry(server.display, hints->icon_pixmap, &root, &icon_x, &icon_y, &w, &h, &border_width, &bpp);
|
XGetGeometry(server.display, hints->icon_pixmap, &root, &icon_x, &icon_y, &w, &h, &border_width, &bpp);
|
||||||
imlib_context_set_drawable(hints->icon_pixmap);
|
imlib_context_set_drawable(hints->icon_pixmap);
|
||||||
img = imlib_create_image_from_drawable(hints->icon_mask, 0, 0, w, h, 0);
|
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);
|
XFree(hints);
|
||||||
}
|
}
|
||||||
@@ -332,6 +345,44 @@ void task_update_icon(Task *task)
|
|||||||
img = imlib_clone_image();
|
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
|
// transform icons
|
||||||
imlib_context_set_image(img);
|
imlib_context_set_image(img);
|
||||||
imlib_image_set_has_alpha(1);
|
imlib_image_set_has_alpha(1);
|
||||||
@@ -345,20 +396,10 @@ void task_update_icon(Task *task)
|
|||||||
task->icon_width = imlib_image_get_width();
|
task->icon_width = imlib_image_get_width();
|
||||||
task->icon_height = imlib_image_get_height();
|
task->icon_height = imlib_image_get_height();
|
||||||
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
|
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
|
||||||
imlib_context_set_image(orig_image);
|
task->icon[k] = adjust_icon(orig_image,
|
||||||
task->icon[k] = imlib_clone_image();
|
panel->g_task.alpha[k],
|
||||||
imlib_context_set_image(task->icon[k]);
|
panel->g_task.saturation[k],
|
||||||
DATA32 *data32;
|
panel->g_task.brightness[k]);
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (panel_config.mouse_effects) {
|
if (panel_config.mouse_effects) {
|
||||||
task->icon_hover[k] = adjust_icon(task->icon[k],
|
task->icon_hover[k] = adjust_icon(task->icon[k],
|
||||||
panel_config.mouse_over_alpha,
|
panel_config.mouse_over_alpha,
|
||||||
@@ -376,9 +417,12 @@ void task_update_icon(Task *task)
|
|||||||
GPtrArray *task_buttons = get_task_buttons(task->win);
|
GPtrArray *task_buttons = get_task_buttons(task->win);
|
||||||
if (task_buttons) {
|
if (task_buttons) {
|
||||||
for (int i = 0; i < task_buttons->len; ++i) {
|
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_width = task->icon_width;
|
||||||
task2->icon_height = task->icon_height;
|
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) {
|
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
|
||||||
task2->icon[k] = task->icon[k];
|
task2->icon[k] = task->icon[k];
|
||||||
task2->icon_hover[k] = task->icon_hover[k];
|
task2->icon_hover[k] = task->icon_hover[k];
|
||||||
@@ -403,7 +447,7 @@ void draw_task_icon(Task *task, int text_width)
|
|||||||
else
|
else
|
||||||
task->_icon_x = (task->area.width - panel->g_task.icon_size1) / 2;
|
task->_icon_x = (task->area.width - panel->g_task.icon_size1) / 2;
|
||||||
} else {
|
} else {
|
||||||
task->_icon_x = left_border_width(&task->area) + task->area.paddingxlr;
|
task->_icon_x = left_border_width(&task->area) + task->area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
@@ -433,11 +477,13 @@ void draw_task(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
task->_text_width = 0;
|
task->_text_width = 0;
|
||||||
if (panel->g_task.has_text) {
|
if (panel->g_task.has_text) {
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, panel->g_task.font_desc);
|
pango_layout_set_font_description(layout, panel->g_task.font_desc);
|
||||||
pango_layout_set_text(layout, task->title, -1);
|
pango_layout_set_text(layout, task->title, -1);
|
||||||
|
|
||||||
pango_layout_set_width(layout, ((Taskbar *)task->area.parent)->text_width * PANGO_SCALE);
|
pango_layout_set_width(layout, (((Taskbar *)task->area.parent)->text_width + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE);
|
pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
@@ -451,9 +497,10 @@ void draw_task(void *obj, cairo_t *c)
|
|||||||
task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0;
|
task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0;
|
||||||
|
|
||||||
Color *config_text = &panel->g_task.font[task->current_state];
|
Color *config_text = &panel->g_task.font[task->current_state];
|
||||||
draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow);
|
draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow ? layout : NULL);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel->g_task.has_icon)
|
if (panel->g_task.has_icon)
|
||||||
@@ -466,7 +513,7 @@ void task_dump_geometry(void *obj, int indent)
|
|||||||
Panel *panel = (Panel *)task->area.panel;
|
Panel *panel = (Panel *)task->area.panel;
|
||||||
|
|
||||||
fprintf(stderr,
|
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,
|
indent,
|
||||||
"",
|
"",
|
||||||
(int)panel->g_task.text_posx,
|
(int)panel->g_task.text_posx,
|
||||||
@@ -476,7 +523,7 @@ void task_dump_geometry(void *obj, int indent)
|
|||||||
panel->g_task.centered ? "center" : "left",
|
panel->g_task.centered ? "center" : "left",
|
||||||
task->title);
|
task->title);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%*sIcon: x = %d, y = %d, w = h = %d\n",
|
"tint2: %*sIcon: x = %d, y = %d, w = h = %d\n",
|
||||||
indent,
|
indent,
|
||||||
"",
|
"",
|
||||||
task->_icon_x,
|
task->_icon_x,
|
||||||
@@ -484,11 +531,29 @@ void task_dump_geometry(void *obj, int indent)
|
|||||||
panel->g_task.icon_size1);
|
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)
|
int task_compute_desired_size(void *obj)
|
||||||
{
|
{
|
||||||
Task *task = (Task *)obj;
|
Task *task = (Task *)obj;
|
||||||
Panel *panel = (Panel *)task->area.panel;
|
Panel *panel = (Panel *)task->area.panel;
|
||||||
int size = panel_horizontal ? panel->g_task.maximum_width : panel->g_task.maximum_height;
|
int size = (panel_horizontal ? panel->g_task.maximum_width : panel->g_task.maximum_height) * panel->scale;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,7 +656,6 @@ void reset_active_task()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Window w1 = get_active_window();
|
Window w1 = get_active_window();
|
||||||
// fprintf(stderr, "tint2: Change active task %ld\n", w1);
|
|
||||||
|
|
||||||
if (w1) {
|
if (w1) {
|
||||||
if (!get_task_buttons(w1)) {
|
if (!get_task_buttons(w1)) {
|
||||||
@@ -603,11 +667,50 @@ 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;
|
||||||
|
Panel *panel = (Panel*)task->area.panel;
|
||||||
|
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 * panel->scale);
|
||||||
|
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)
|
void set_task_state(Task *task, TaskState state)
|
||||||
{
|
{
|
||||||
if (!task || state == TASK_UNDEFINED || state >= TASK_STATE_COUNT)
|
if (!task || state == TASK_UNDEFINED || state >= TASK_STATE_COUNT)
|
||||||
return;
|
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) {
|
if (state == TASK_ACTIVE && task->current_state != state) {
|
||||||
clock_gettime(CLOCK_MONOTONIC, &task->last_activation_time);
|
clock_gettime(CLOCK_MONOTONIC, &task->last_activation_time);
|
||||||
if (taskbar_sort_method == TASKBAR_SORT_LRU || taskbar_sort_method == TASKBAR_SORT_MRU) {
|
if (taskbar_sort_method == TASKBAR_SORT_LRU || taskbar_sort_method == TASKBAR_SORT_MRU) {
|
||||||
@@ -673,8 +776,8 @@ void blink_urgent(void *arg)
|
|||||||
GSList *urgent_task = urgent_list;
|
GSList *urgent_task = urgent_list;
|
||||||
while (urgent_task) {
|
while (urgent_task) {
|
||||||
Task *t = urgent_task->data;
|
Task *t = urgent_task->data;
|
||||||
if (t->urgent_tick < max_tick_urgent) {
|
if (t->urgent_tick <= max_tick_urgent) {
|
||||||
if (t->urgent_tick++ % 2)
|
if (++t->urgent_tick % 2)
|
||||||
set_task_state(t, TASK_URGENT);
|
set_task_state(t, TASK_URGENT);
|
||||||
else
|
else
|
||||||
set_task_state(t, window_is_iconified(t->win) ? TASK_ICONIFIED : TASK_NORMAL);
|
set_task_state(t, window_is_iconified(t->win) ? TASK_ICONIFIED : TASK_NORMAL);
|
||||||
@@ -701,8 +804,8 @@ void add_urgent(Task *task)
|
|||||||
// not yet in the list, so we have to add it
|
// not yet in the list, so we have to add it
|
||||||
urgent_list = g_slist_prepend(urgent_list, task);
|
urgent_list = g_slist_prepend(urgent_list, task);
|
||||||
|
|
||||||
if (!urgent_timeout)
|
if (!urgent_timer.enabled_)
|
||||||
urgent_timeout = add_timeout(10, 1000, blink_urgent, 0, &urgent_timeout);
|
change_timer(&urgent_timer, true, 10, 1000, blink_urgent, 0);
|
||||||
|
|
||||||
Panel *panel = task->area.panel;
|
Panel *panel = task->area.panel;
|
||||||
if (panel->is_hidden)
|
if (panel->is_hidden)
|
||||||
@@ -712,10 +815,8 @@ void add_urgent(Task *task)
|
|||||||
void del_urgent(Task *task)
|
void del_urgent(Task *task)
|
||||||
{
|
{
|
||||||
urgent_list = g_slist_remove(urgent_list, task);
|
urgent_list = g_slist_remove(urgent_list, task);
|
||||||
if (!urgent_list) {
|
if (!urgent_list)
|
||||||
stop_timeout(urgent_timeout);
|
stop_timer(&urgent_timer);
|
||||||
urgent_timeout = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_handle_mouse_event(Task *task, MouseAction action)
|
void task_handle_mouse_event(Task *task, MouseAction action)
|
||||||
@@ -783,7 +884,6 @@ void task_handle_mouse_event(Task *task, MouseAction action)
|
|||||||
|
|
||||||
void task_update_desktop(Task *task)
|
void task_update_desktop(Task *task)
|
||||||
{
|
{
|
||||||
// fprintf(stderr, "tint2: %s %d:\n", __FUNCTION__, __LINE__);
|
|
||||||
Window win = task->win;
|
Window win = task->win;
|
||||||
remove_task(task);
|
remove_task(task);
|
||||||
task = add_task(win);
|
task = add_task(win);
|
||||||
|
|||||||
+11
-1
@@ -42,10 +42,13 @@ typedef struct GlobalTask {
|
|||||||
// starting position for text ~ task_padding + task_border + icon_size
|
// starting position for text ~ task_padding + task_border + icon_size
|
||||||
double text_posx, text_height;
|
double text_posx, text_height;
|
||||||
gboolean has_font;
|
gboolean has_font;
|
||||||
|
gboolean has_content_tint;
|
||||||
PangoFontDescription *font_desc;
|
PangoFontDescription *font_desc;
|
||||||
Color font[TASK_STATE_COUNT];
|
Color font[TASK_STATE_COUNT];
|
||||||
int config_font_mask;
|
int config_font_mask;
|
||||||
gboolean tooltip_enabled;
|
gboolean tooltip_enabled;
|
||||||
|
gboolean thumbnail_enabled;
|
||||||
|
int thumbnail_width;
|
||||||
} GlobalTask;
|
} GlobalTask;
|
||||||
|
|
||||||
// Stores information about a task.
|
// Stores information about a task.
|
||||||
@@ -61,7 +64,11 @@ typedef struct Task {
|
|||||||
Imlib_Image icon_press[TASK_STATE_COUNT];
|
Imlib_Image icon_press[TASK_STATE_COUNT];
|
||||||
unsigned int icon_width;
|
unsigned int icon_width;
|
||||||
unsigned int icon_height;
|
unsigned int icon_height;
|
||||||
|
Color icon_color;
|
||||||
|
Color icon_color_hover;
|
||||||
|
Color icon_color_press;
|
||||||
char *title;
|
char *title;
|
||||||
|
char *application;
|
||||||
int urgent_tick;
|
int urgent_tick;
|
||||||
// These may not be up-to-date
|
// These may not be up-to-date
|
||||||
int win_x;
|
int win_x;
|
||||||
@@ -74,9 +81,11 @@ typedef struct Task {
|
|||||||
double _text_posy;
|
double _text_posy;
|
||||||
int _icon_x;
|
int _icon_x;
|
||||||
int _icon_y;
|
int _icon_y;
|
||||||
|
cairo_surface_t *thumbnail;
|
||||||
|
double thumbnail_last_update;
|
||||||
} Task;
|
} Task;
|
||||||
|
|
||||||
extern timeout *urgent_timeout;
|
extern Timer urgent_timer;
|
||||||
extern GSList *urgent_list;
|
extern GSList *urgent_list;
|
||||||
|
|
||||||
Task *add_task(Window win);
|
Task *add_task(Window win);
|
||||||
@@ -91,6 +100,7 @@ gboolean task_update_title(Task *task);
|
|||||||
void reset_active_task();
|
void reset_active_task();
|
||||||
void set_task_state(Task *task, TaskState state);
|
void set_task_state(Task *task, TaskState state);
|
||||||
void task_handle_mouse_event(Task *task, MouseAction action);
|
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),
|
// 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.
|
// returns a pointer to the Task for the active window on the same taskbar.
|
||||||
|
|||||||
+212
-29
@@ -32,6 +32,7 @@
|
|||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
#include "strnatcmp.h"
|
#include "strnatcmp.h"
|
||||||
|
#include "tooltip.h"
|
||||||
|
|
||||||
GHashTable *win_to_task;
|
GHashTable *win_to_task;
|
||||||
|
|
||||||
@@ -46,6 +47,12 @@ gboolean hide_taskbar_if_empty;
|
|||||||
gboolean always_show_all_desktop_tasks;
|
gboolean always_show_all_desktop_tasks;
|
||||||
TaskbarSortMethod taskbar_sort_method;
|
TaskbarSortMethod taskbar_sort_method;
|
||||||
Alignment taskbar_alignment;
|
Alignment taskbar_alignment;
|
||||||
|
static Timer thumbnail_update_timer_all;
|
||||||
|
static Timer thumbnail_update_timer_active;
|
||||||
|
static Timer thumbnail_update_timer_tooltip;
|
||||||
|
|
||||||
|
static GList *taskbar_task_orderings = NULL;
|
||||||
|
static GList *taskbar_thumbnail_jobs_done = NULL;
|
||||||
|
|
||||||
void taskbar_init_fonts();
|
void taskbar_init_fonts();
|
||||||
int taskbar_compute_desired_size(void *obj);
|
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.
|
// Removes the task with &win = key. The other args are ignored.
|
||||||
void taskbar_remove_task(Window *win);
|
void taskbar_remove_task(Window *win);
|
||||||
|
|
||||||
|
void taskbar_update_thumbnails(void *arg);
|
||||||
|
|
||||||
guint win_hash(gconstpointer key)
|
guint win_hash(gconstpointer key)
|
||||||
{
|
{
|
||||||
return *((const Window *)key);
|
return *((const Window *)key);
|
||||||
@@ -71,7 +80,6 @@ void free_ptr_array(gpointer data)
|
|||||||
void default_taskbar()
|
void default_taskbar()
|
||||||
{
|
{
|
||||||
win_to_task = NULL;
|
win_to_task = NULL;
|
||||||
urgent_timeout = NULL;
|
|
||||||
urgent_list = NULL;
|
urgent_list = NULL;
|
||||||
taskbar_enabled = FALSE;
|
taskbar_enabled = FALSE;
|
||||||
taskbar_distribute_size = FALSE;
|
taskbar_distribute_size = FALSE;
|
||||||
@@ -80,13 +88,53 @@ void default_taskbar()
|
|||||||
hide_task_diff_monitor = FALSE;
|
hide_task_diff_monitor = FALSE;
|
||||||
hide_taskbar_if_empty = FALSE;
|
hide_taskbar_if_empty = FALSE;
|
||||||
always_show_all_desktop_tasks = FALSE;
|
always_show_all_desktop_tasks = FALSE;
|
||||||
|
taskbar_thumbnail_jobs_done = NULL;
|
||||||
taskbar_sort_method = TASKBAR_NOSORT;
|
taskbar_sort_method = TASKBAR_NOSORT;
|
||||||
taskbar_alignment = ALIGN_LEFT;
|
taskbar_alignment = ALIGN_LEFT;
|
||||||
default_taskbarname();
|
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()
|
void cleanup_taskbar()
|
||||||
{
|
{
|
||||||
|
destroy_timer(&thumbnail_update_timer_all);
|
||||||
|
destroy_timer(&thumbnail_update_timer_active);
|
||||||
|
destroy_timer(&thumbnail_update_timer_tooltip);
|
||||||
|
g_list_free(taskbar_thumbnail_jobs_done);
|
||||||
|
taskbar_save_orderings();
|
||||||
if (win_to_task) {
|
if (win_to_task) {
|
||||||
while (g_hash_table_size(win_to_task)) {
|
while (g_hash_table_size(win_to_task)) {
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
@@ -118,7 +166,7 @@ void cleanup_taskbar()
|
|||||||
g_slist_free(urgent_list);
|
g_slist_free(urgent_list);
|
||||||
urgent_list = NULL;
|
urgent_list = NULL;
|
||||||
|
|
||||||
stop_timeout(urgent_timeout);
|
destroy_timer(&urgent_timer);
|
||||||
|
|
||||||
for (int state = 0; state < TASK_STATE_COUNT; state++) {
|
for (int state = 0; state < TASK_STATE_COUNT; state++) {
|
||||||
g_list_free(panel_config.g_task.gradient[state]);
|
g_list_free(panel_config.g_task.gradient[state]);
|
||||||
@@ -132,10 +180,18 @@ void cleanup_taskbar()
|
|||||||
|
|
||||||
void init_taskbar()
|
void init_taskbar()
|
||||||
{
|
{
|
||||||
|
INIT_TIMER(urgent_timer);
|
||||||
|
INIT_TIMER(thumbnail_update_timer_all);
|
||||||
|
INIT_TIMER(thumbnail_update_timer_active);
|
||||||
|
INIT_TIMER(thumbnail_update_timer_tooltip);
|
||||||
|
|
||||||
if (!panel_config.g_task.has_text && !panel_config.g_task.has_icon) {
|
if (!panel_config.g_task.has_text && !panel_config.g_task.has_icon) {
|
||||||
panel_config.g_task.has_text = panel_config.g_task.has_icon = 1;
|
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)
|
if (!win_to_task)
|
||||||
win_to_task = g_hash_table_new_full(win_hash, win_compare, free, free_ptr_array);
|
win_to_task = g_hash_table_new_full(win_hash, win_compare, free, free_ptr_array);
|
||||||
|
|
||||||
@@ -182,15 +238,15 @@ void init_taskbar_panel(void *p)
|
|||||||
panel->g_taskbar.area.resize_needed = 1;
|
panel->g_taskbar.area.resize_needed = 1;
|
||||||
panel->g_taskbar.area.on_screen = TRUE;
|
panel->g_taskbar.area.on_screen = TRUE;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy;
|
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area.height =
|
panel->g_taskbar.area.height =
|
||||||
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy;
|
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
||||||
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
||||||
} else {
|
} else {
|
||||||
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy;
|
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area.width =
|
panel->g_taskbar.area.width =
|
||||||
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy;
|
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
|
panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
|
||||||
panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
|
panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
|
||||||
}
|
}
|
||||||
@@ -248,26 +304,27 @@ void init_taskbar_panel(void *p)
|
|||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
panel->g_task.area.posy = panel->g_taskbar.area.posy +
|
panel->g_task.area.posy = panel->g_taskbar.area.posy +
|
||||||
top_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
top_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
||||||
panel->g_taskbar.area.paddingy;
|
panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.width = panel->g_task.maximum_width;
|
panel->g_task.area.width = panel->g_task.maximum_width;
|
||||||
panel->g_task.area.height = panel->g_taskbar.area.height -
|
panel->g_task.area.height = panel->g_taskbar.area.height -
|
||||||
top_bottom_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
top_bottom_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
||||||
2 * panel->g_taskbar.area.paddingy;
|
2 * panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
panel->g_task.area.posx = panel->g_taskbar.area.posx +
|
panel->g_task.area.posx = panel->g_taskbar.area.posx +
|
||||||
left_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
left_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
||||||
panel->g_taskbar.area.paddingy;
|
panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.width = panel->g_taskbar.area.width -
|
panel->g_task.area.width = panel->g_taskbar.area.width -
|
||||||
left_right_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
left_right_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
||||||
2 * panel->g_taskbar.area.paddingy;
|
2 * panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.height = panel->g_task.maximum_height;
|
panel->g_task.area.height = panel->g_task.maximum_height * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
||||||
if (!panel->g_task.background[j])
|
if (!panel->g_task.background[j])
|
||||||
panel->g_task.background[j] = &g_array_index(backgrounds, Background, 0);
|
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) {
|
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",
|
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_");
|
j == 0 ? "_" : j == 1 ? "_active_" : j == 2 ? "_iconified_" : "_urgent_");
|
||||||
g_array_append_val(backgrounds, *panel->g_task.background[j]);
|
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] = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
||||||
@@ -276,9 +333,8 @@ void init_taskbar_panel(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute vertical position : text and icon
|
// compute vertical position : text and icon
|
||||||
int height_ink, height, width;
|
int height, width;
|
||||||
get_text_size2(panel->g_task.font_desc,
|
get_text_size2(panel->g_task.font_desc,
|
||||||
&height_ink,
|
|
||||||
&height,
|
&height,
|
||||||
&width,
|
&width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -287,17 +343,19 @@ void init_taskbar_panel(void *p)
|
|||||||
5,
|
5,
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_END,
|
PANGO_ELLIPSIZE_END,
|
||||||
FALSE);
|
panel->g_task.centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
panel->g_task.text_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr;
|
panel->g_task.text_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr * panel->scale;
|
||||||
panel->g_task.text_height =
|
panel->g_task.text_height =
|
||||||
panel->g_task.area.height - (2 * panel->g_task.area.paddingy) - top_bottom_border_width(&panel->g_task.area);
|
panel->g_task.area.height - (2 * panel->g_task.area.paddingy * panel->scale) - top_bottom_border_width(&panel->g_task.area);
|
||||||
if (panel->g_task.has_icon) {
|
if (panel->g_task.has_icon) {
|
||||||
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width, panel->g_task.maximum_height),
|
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width * panel->scale, panel->g_task.maximum_height * panel->scale),
|
||||||
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
|
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
|
||||||
2 * panel->g_task.area.paddingy - MAX(left_right_border_width(&panel->g_task.area),
|
2 * panel->g_task.area.paddingy * panel->scale - MAX(left_right_border_width(&panel->g_task.area),
|
||||||
top_bottom_border_width(&panel->g_task.area));
|
top_bottom_border_width(&panel->g_task.area));
|
||||||
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx;
|
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx * panel->scale;
|
||||||
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,6 +377,22 @@ void init_taskbar_panel(void *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
init_taskbarname_panel(panel);
|
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_timer(mode == THUMB_MODE_ALL ? &thumbnail_update_timer_all :
|
||||||
|
mode == THUMB_MODE_ACTIVE_WINDOW ? &thumbnail_update_timer_active : &thumbnail_update_timer_tooltip,
|
||||||
|
true,
|
||||||
|
mode == THUMB_MODE_TOOLTIP_WINDOW ? 1000 : 500,
|
||||||
|
mode == THUMB_MODE_ALL ? 10 * 1000 : 0,
|
||||||
|
taskbar_update_thumbnails,
|
||||||
|
(void *)(long)mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void taskbar_init_fonts()
|
void taskbar_init_fonts()
|
||||||
@@ -381,14 +455,67 @@ GPtrArray *get_task_buttons(Window win)
|
|||||||
return NULL;
|
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()
|
void taskbar_refresh_tasklist()
|
||||||
{
|
{
|
||||||
if (!taskbar_enabled)
|
if (!taskbar_enabled)
|
||||||
return;
|
return;
|
||||||
// fprintf(stderr, "tint2: %s %d:\n", __FUNCTION__, __LINE__);
|
|
||||||
|
|
||||||
int num_results;
|
int num_results;
|
||||||
Window *win = server_get_property(server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &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)
|
if (!win)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -396,7 +523,7 @@ void taskbar_refresh_tasklist()
|
|||||||
for (GList *it = win_list; it; it = it->next) {
|
for (GList *it = win_list; it; it = it->next) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < num_results; i++)
|
for (i = 0; i < num_results; i++)
|
||||||
if (*((Window *)it->data) == win[i])
|
if (*((Window *)it->data) == sorted[i])
|
||||||
break;
|
break;
|
||||||
if (i == num_results)
|
if (i == num_results)
|
||||||
taskbar_remove_task(it->data);
|
taskbar_remove_task(it->data);
|
||||||
@@ -405,10 +532,11 @@ void taskbar_refresh_tasklist()
|
|||||||
|
|
||||||
// Add any new
|
// Add any new
|
||||||
for (int i = 0; i < num_results; i++)
|
for (int i = 0; i < num_results; i++)
|
||||||
if (!get_task(win[i]))
|
if (!get_task(sorted[i]))
|
||||||
add_task(win[i]);
|
add_task(sorted[i]);
|
||||||
|
|
||||||
XFree(win);
|
XFree(win);
|
||||||
|
free(sorted);
|
||||||
}
|
}
|
||||||
|
|
||||||
int taskbar_compute_desired_size(void *obj)
|
int taskbar_compute_desired_size(void *obj)
|
||||||
@@ -432,7 +560,6 @@ gboolean resize_taskbar(void *obj)
|
|||||||
Taskbar *taskbar = (Taskbar *)obj;
|
Taskbar *taskbar = (Taskbar *)obj;
|
||||||
Panel *panel = (Panel *)taskbar->area.panel;
|
Panel *panel = (Panel *)taskbar->area.panel;
|
||||||
|
|
||||||
// fprintf(stderr, "tint2: resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy);
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_width);
|
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_width);
|
||||||
|
|
||||||
@@ -447,12 +574,12 @@ gboolean resize_taskbar(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
taskbar->text_width = text_width - panel->g_task.text_posx - right_border_width(&panel->g_task.area) -
|
taskbar->text_width = text_width - panel->g_task.text_posx - right_border_width(&panel->g_task.area) -
|
||||||
panel->g_task.area.paddingxlr;
|
panel->g_task.area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height);
|
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height * panel->scale);
|
||||||
|
|
||||||
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy) - panel->g_task.text_posx -
|
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy * panel->scale) - panel->g_task.text_posx -
|
||||||
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr;
|
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -608,6 +735,14 @@ gint compare_task_titles(Task *a, Task *b, Taskbar *taskbar)
|
|||||||
return strnatcasecmp(a->title ? a->title : "", b->title ? b->title : "");
|
return strnatcasecmp(a->title ? a->title : "", b->title ? b->title : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gint compare_task_applications(Task *a, Task *b, Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
||||||
|
if (trivial != NONTRIVIAL)
|
||||||
|
return trivial;
|
||||||
|
return strnatcasecmp(a->application ? a->application : "", b->application ? b->application : "");
|
||||||
|
}
|
||||||
|
|
||||||
gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
||||||
{
|
{
|
||||||
int trivial = compare_tasks_trivial(a, b, taskbar);
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
||||||
@@ -619,6 +754,8 @@ gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
|||||||
return compare_task_centers(a, b, taskbar);
|
return compare_task_centers(a, b, taskbar);
|
||||||
} else if (taskbar_sort_method == TASKBAR_SORT_TITLE) {
|
} else if (taskbar_sort_method == TASKBAR_SORT_TITLE) {
|
||||||
return compare_task_titles(a, b, taskbar);
|
return compare_task_titles(a, b, taskbar);
|
||||||
|
} else if (taskbar_sort_method == TASKBAR_SORT_APPLICATION) {
|
||||||
|
return compare_task_applications(a, b, taskbar);
|
||||||
} else if (taskbar_sort_method == TASKBAR_SORT_LRU) {
|
} else if (taskbar_sort_method == TASKBAR_SORT_LRU) {
|
||||||
return compare_timespecs(&a->last_activation_time, &b->last_activation_time);
|
return compare_timespecs(&a->last_activation_time, &b->last_activation_time);
|
||||||
} else if (taskbar_sort_method == TASKBAR_SORT_MRU) {
|
} else if (taskbar_sort_method == TASKBAR_SORT_MRU) {
|
||||||
@@ -690,3 +827,49 @@ 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_timer(&thumbnail_update_timer_all, true, 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_timer(&thumbnail_update_timer_all, true, 10 * 1000, 10 * 1000, taskbar_update_thumbnails, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,10 +21,17 @@ typedef enum TaskbarSortMethod {
|
|||||||
TASKBAR_NOSORT = 0,
|
TASKBAR_NOSORT = 0,
|
||||||
TASKBAR_SORT_CENTER,
|
TASKBAR_SORT_CENTER,
|
||||||
TASKBAR_SORT_TITLE,
|
TASKBAR_SORT_TITLE,
|
||||||
|
TASKBAR_SORT_APPLICATION,
|
||||||
TASKBAR_SORT_LRU,
|
TASKBAR_SORT_LRU,
|
||||||
TASKBAR_SORT_MRU,
|
TASKBAR_SORT_MRU,
|
||||||
} TaskbarSortMethod;
|
} TaskbarSortMethod;
|
||||||
|
|
||||||
|
typedef enum ThumbnailUpdateMode {
|
||||||
|
THUMB_MODE_ACTIVE_WINDOW = 0,
|
||||||
|
THUMB_MODE_TOOLTIP_WINDOW,
|
||||||
|
THUMB_MODE_ALL
|
||||||
|
} ThumbnailUpdateMode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Area area;
|
Area area;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
@@ -72,6 +79,7 @@ void init_taskbar_panel(void *p);
|
|||||||
|
|
||||||
gboolean resize_taskbar(void *obj);
|
gboolean resize_taskbar(void *obj);
|
||||||
void taskbar_default_font_changed();
|
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.
|
// Reloads the entire list of tasks from the window manager and recreates the task buttons.
|
||||||
void taskbar_refresh_tasklist();
|
void taskbar_refresh_tasklist();
|
||||||
|
|||||||
+16
-10
@@ -134,9 +134,8 @@ int taskbarname_compute_desired_size(void *obj)
|
|||||||
{
|
{
|
||||||
TaskbarName *taskbar_name = (TaskbarName *)obj;
|
TaskbarName *taskbar_name = (TaskbarName *)obj;
|
||||||
Panel *panel = (Panel *)taskbar_name->area.panel;
|
Panel *panel = (Panel *)taskbar_name->area.panel;
|
||||||
int name_height, name_width, name_height_ink;
|
int name_height, name_width;
|
||||||
get_text_size2(panel_config.taskbarname_font_desc,
|
get_text_size2(panel_config.taskbarname_font_desc,
|
||||||
&name_height_ink,
|
|
||||||
&name_height,
|
&name_height,
|
||||||
&name_width,
|
&name_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -145,12 +144,14 @@ int taskbarname_compute_desired_size(void *obj)
|
|||||||
strlen(taskbar_name->name),
|
strlen(taskbar_name->name),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
return name_width + 2 * taskbar_name->area.paddingxlr + left_right_border_width(&taskbar_name->area);
|
return name_width + 2 * taskbar_name->area.paddingxlr * panel->scale + left_right_border_width(&taskbar_name->area);
|
||||||
} else {
|
} else {
|
||||||
return name_height + 2 * taskbar_name->area.paddingxlr + top_bottom_border_width(&taskbar_name->area);
|
return name_height + 2 * taskbar_name->area.paddingxlr * panel->scale + top_bottom_border_width(&taskbar_name->area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,9 +162,8 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
|
|
||||||
schedule_redraw(&taskbar_name->area);
|
schedule_redraw(&taskbar_name->area);
|
||||||
|
|
||||||
int name_height, name_width, name_height_ink;
|
int name_height, name_width;
|
||||||
get_text_size2(panel_config.taskbarname_font_desc,
|
get_text_size2(panel_config.taskbarname_font_desc,
|
||||||
&name_height_ink,
|
|
||||||
&name_height,
|
&name_height,
|
||||||
&name_width,
|
&name_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -172,7 +172,9 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
strlen(taskbar_name->name),
|
strlen(taskbar_name->name),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
int new_size = taskbarname_compute_desired_size(obj);
|
int new_size = taskbarname_compute_desired_size(obj);
|
||||||
@@ -195,11 +197,14 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
void draw_taskbarname(void *obj, cairo_t *c)
|
void draw_taskbarname(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
TaskbarName *taskbar_name = obj;
|
TaskbarName *taskbar_name = obj;
|
||||||
|
Panel *panel = (Panel *)taskbar_name->area.panel;
|
||||||
Taskbar *taskbar = taskbar_name->area.parent;
|
Taskbar *taskbar = taskbar_name->area.parent;
|
||||||
Color *config_text = (taskbar->desktop == server.desktop) ? &taskbarname_active_font : &taskbarname_font;
|
Color *config_text = (taskbar->desktop == server.desktop) ? &taskbarname_active_font : &taskbarname_font;
|
||||||
|
|
||||||
// draw content
|
// draw content
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, panel_config.taskbarname_font_desc);
|
pango_layout_set_font_description(layout, panel_config.taskbarname_font_desc);
|
||||||
pango_layout_set_width(layout, taskbar_name->area.width * PANGO_SCALE);
|
pango_layout_set_width(layout, taskbar_name->area.width * PANGO_SCALE);
|
||||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||||
@@ -210,9 +215,10 @@ void draw_taskbarname(void *obj, cairo_t *c)
|
|||||||
cairo_set_source_rgba(c, config_text->rgb[0], config_text->rgb[1], config_text->rgb[2], config_text->alpha);
|
cairo_set_source_rgba(c, config_text->rgb[0], config_text->rgb[1], config_text->rgb[2], config_text->alpha);
|
||||||
|
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel *)taskbar_name->area.panel)->font_shadow);
|
draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel *)taskbar_name->area.panel)->font_shadow ? layout : NULL);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_desktop_names()
|
void update_desktop_names()
|
||||||
|
|||||||
@@ -20,11 +20,16 @@ include_directories( ../util
|
|||||||
${RSVG_INCLUDE_DIRS} )
|
${RSVG_INCLUDE_DIRS} )
|
||||||
|
|
||||||
set(SOURCES ../util/common.c
|
set(SOURCES ../util/common.c
|
||||||
|
../util/bt.c
|
||||||
../util/strnatcmp.c
|
../util/strnatcmp.c
|
||||||
../util/cache.c
|
../util/cache.c
|
||||||
../util/timer.c
|
../util/timer.c
|
||||||
|
../util/test.c
|
||||||
|
../util/print.c
|
||||||
|
../util/signals.c
|
||||||
../config.c
|
../config.c
|
||||||
../server.c
|
../util/server.c
|
||||||
|
../util/strlcat.c
|
||||||
../launcher/apps-common.c
|
../launcher/apps-common.c
|
||||||
../launcher/icon-theme-common.c
|
../launcher/icon-theme-common.c
|
||||||
md4.c
|
md4.c
|
||||||
|
|||||||
@@ -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_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_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_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)
|
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_BOOL,
|
||||||
GTK_TYPE_BOOL);
|
GTK_TYPE_BOOL,
|
||||||
|
GTK_TYPE_DOUBLE,
|
||||||
|
GTK_TYPE_DOUBLE);
|
||||||
|
|
||||||
GtkWidget *table, *label, *button;
|
GtkWidget *table, *label, *button;
|
||||||
int row, col;
|
int row, col;
|
||||||
@@ -175,6 +177,19 @@ void create_background(GtkWidget *parent)
|
|||||||
col++;
|
col++;
|
||||||
gtk_tooltips_set_tip(tooltips, background_fill_color, _("The fill color of the current background"), NULL);
|
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;
|
row++, col = 2;
|
||||||
label = gtk_label_new(_("Border color"));
|
label = gtk_label_new(_("Border color"));
|
||||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||||
@@ -189,6 +204,19 @@ void create_background(GtkWidget *parent)
|
|||||||
col++;
|
col++;
|
||||||
gtk_tooltips_set_tip(tooltips, background_border_color, _("The border color of the current background"), NULL);
|
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;
|
row++, col = 2;
|
||||||
label = gtk_label_new(_("Gradient"));
|
label = gtk_label_new(_("Gradient"));
|
||||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
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_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_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_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);
|
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));
|
r = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_corner_radius));
|
||||||
b = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_border_width));
|
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 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 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));
|
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,
|
sideLeft,
|
||||||
bgColBorderSidesRight,
|
bgColBorderSidesRight,
|
||||||
sideRight,
|
sideRight,
|
||||||
|
bgColFillWeight,
|
||||||
|
fill_weight,
|
||||||
|
bgColBorderWeight,
|
||||||
|
border_weight,
|
||||||
-1);
|
-1);
|
||||||
background_update_image(index);
|
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_left, index > 0);
|
||||||
gtk_widget_set_sensitive(background_border_sides_right, 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_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;
|
background_updates_disabled = TRUE;
|
||||||
|
|
||||||
@@ -875,6 +914,9 @@ void current_background_changed(GtkWidget *widget, gpointer data)
|
|||||||
int r;
|
int r;
|
||||||
int b;
|
int b;
|
||||||
|
|
||||||
|
double fill_weight;
|
||||||
|
double border_weight;
|
||||||
|
|
||||||
gboolean sideTop;
|
gboolean sideTop;
|
||||||
gboolean sideBottom;
|
gboolean sideBottom;
|
||||||
gboolean sideLeft;
|
gboolean sideLeft;
|
||||||
@@ -938,6 +980,10 @@ void current_background_changed(GtkWidget *widget, gpointer data)
|
|||||||
&sideLeft,
|
&sideLeft,
|
||||||
bgColBorderSidesRight,
|
bgColBorderSidesRight,
|
||||||
&sideRight,
|
&sideRight,
|
||||||
|
bgColFillWeight,
|
||||||
|
&fill_weight,
|
||||||
|
bgColBorderWeight,
|
||||||
|
&border_weight,
|
||||||
-1);
|
-1);
|
||||||
|
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(background_border_sides_top), sideTop);
|
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_border_width), b);
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_corner_radius), r);
|
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, fillColor);
|
||||||
g_boxed_free(GDK_TYPE_COLOR, borderColor);
|
g_boxed_free(GDK_TYPE_COLOR, borderColor);
|
||||||
g_boxed_free(GDK_TYPE_COLOR, fillColorOver);
|
g_boxed_free(GDK_TYPE_COLOR, fillColorOver);
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ char *file_name_from_path(const char *filepath)
|
|||||||
|
|
||||||
void make_backup(const char *filepath)
|
void make_backup(const char *filepath)
|
||||||
{
|
{
|
||||||
gchar *backup_path = g_strdup_printf("%s.backup.%ld", filepath, time(NULL));
|
gchar *backup_path = g_strdup_printf("%s.backup.%lld", filepath, (long long)time(NULL));
|
||||||
copy_file(filepath, backup_path);
|
copy_file(filepath, backup_path);
|
||||||
g_free(backup_path);
|
g_free(backup_path);
|
||||||
}
|
}
|
||||||
@@ -383,6 +383,11 @@ static void menuAbout()
|
|||||||
|
|
||||||
// ====== Theme import/copy/delete ======
|
// ====== Theme import/copy/delete ======
|
||||||
|
|
||||||
|
static void free_data(gpointer data, gpointer userdata)
|
||||||
|
{
|
||||||
|
g_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
// Shows open dialog and copies the selected files to ~ without overwrite.
|
// Shows open dialog and copies the selected files to ~ without overwrite.
|
||||||
static void menuImportFile()
|
static void menuImportFile()
|
||||||
{
|
{
|
||||||
@@ -407,7 +412,7 @@ static void menuImportFile()
|
|||||||
gchar *newpath = import_no_overwrite(l->data);
|
gchar *newpath = import_no_overwrite(l->data);
|
||||||
g_free(newpath);
|
g_free(newpath);
|
||||||
}
|
}
|
||||||
g_slist_foreach(list, (GFunc)g_free, NULL);
|
g_slist_foreach(list, free_data, NULL);
|
||||||
g_slist_free(list);
|
g_slist_free(list);
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
}
|
||||||
|
|||||||
+495
-451
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+495
-469
File diff suppressed because it is too large
Load Diff
+495
-451
File diff suppressed because it is too large
Load Diff
+495
-451
File diff suppressed because it is too large
Load Diff
+495
-451
File diff suppressed because it is too large
Load Diff
+495
-451
File diff suppressed because it is too large
Load Diff
+491
-452
File diff suppressed because it is too large
Load Diff
@@ -15,3 +15,22 @@ do
|
|||||||
cat ${lang}.pox > ${lang}.po
|
cat ${lang}.pox > ${lang}.po
|
||||||
rm ${lang}.pox
|
rm ${lang}.pox
|
||||||
done
|
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
|
||||||
|
|||||||
+79
-18
@@ -20,7 +20,9 @@
|
|||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "background_gui.h"
|
#include "background_gui.h"
|
||||||
#include "gradient_gui.h"
|
#include "gradient_gui.h"
|
||||||
|
#include "strlcat.h"
|
||||||
|
|
||||||
|
GtkWidget *scale_relative_to_dpi, *scale_relative_to_screen_height;
|
||||||
GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
||||||
*panel_spacing;
|
*panel_spacing;
|
||||||
GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
||||||
@@ -97,7 +99,7 @@ GtkWidget *systray_background, *systray_monitor, *systray_name_filter;
|
|||||||
|
|
||||||
// tooltip
|
// tooltip
|
||||||
GtkWidget *tooltip_padding_x, *tooltip_padding_y, *tooltip_font, *tooltip_font_set, *tooltip_font_color;
|
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 *clock_format_tooltip, *clock_tmz_tooltip;
|
||||||
GtkWidget *tooltip_background;
|
GtkWidget *tooltip_background;
|
||||||
|
|
||||||
@@ -180,7 +182,7 @@ void applyClicked(GtkWidget *widget, gpointer data)
|
|||||||
gchar *filepath = get_current_theme_path();
|
gchar *filepath = get_current_theme_path();
|
||||||
if (filepath) {
|
if (filepath) {
|
||||||
if (config_is_manual(filepath)) {
|
if (config_is_manual(filepath)) {
|
||||||
gchar *backup_path = g_strdup_printf("%s.backup.%ld", filepath, time(NULL));
|
gchar *backup_path = g_strdup_printf("%s.backup.%lld", filepath, (long long)time(NULL));
|
||||||
copy_file(filepath, backup_path);
|
copy_file(filepath, backup_path);
|
||||||
g_free(backup_path);
|
g_free(backup_path);
|
||||||
}
|
}
|
||||||
@@ -599,6 +601,32 @@ void create_panel(GtkWidget *parent)
|
|||||||
"for centered panels, it is evenly distributed on both sides of the panel."),
|
"for centered panels, it is evenly distributed on both sides of the panel."),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
row++;
|
||||||
|
col = 2;
|
||||||
|
label = gtk_label_new(_("Scale relative to DPI"));
|
||||||
|
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++;
|
||||||
|
|
||||||
|
scale_relative_to_dpi = gtk_spin_button_new_with_range(0, 9000, 1);
|
||||||
|
gtk_widget_show(scale_relative_to_dpi);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), scale_relative_to_dpi, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
row++;
|
||||||
|
col = 2;
|
||||||
|
label = gtk_label_new(_("Scale relative to screen height"));
|
||||||
|
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++;
|
||||||
|
|
||||||
|
scale_relative_to_screen_height = gtk_spin_button_new_with_range(0, 9000, 1);
|
||||||
|
gtk_widget_show(scale_relative_to_screen_height);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), scale_relative_to_screen_height, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
change_paragraph(parent);
|
change_paragraph(parent);
|
||||||
|
|
||||||
label = gtk_label_new(_("<b>Appearance</b>"));
|
label = gtk_label_new(_("<b>Appearance</b>"));
|
||||||
@@ -1256,7 +1284,8 @@ gboolean panel_contains(const char *value)
|
|||||||
|
|
||||||
char *get_panel_items()
|
char *get_panel_items()
|
||||||
{
|
{
|
||||||
char *result = calloc(1, 256 * sizeof(char));
|
size_t buf_size = 256;
|
||||||
|
char *result = calloc(buf_size, 1);
|
||||||
GtkTreeModel *model = GTK_TREE_MODEL(panel_items);
|
GtkTreeModel *model = GTK_TREE_MODEL(panel_items);
|
||||||
|
|
||||||
GtkTreeIter i;
|
GtkTreeIter i;
|
||||||
@@ -1267,7 +1296,7 @@ char *get_panel_items()
|
|||||||
while (1) {
|
while (1) {
|
||||||
gchar *v;
|
gchar *v;
|
||||||
gtk_tree_model_get(model, &i, itemsColValue, &v, -1);
|
gtk_tree_model_get(model, &i, itemsColValue, &v, -1);
|
||||||
strcat(result, v);
|
strlcat(result, v, buf_size);
|
||||||
|
|
||||||
if (!gtk_tree_model_iter_next(model, &i)) {
|
if (!gtk_tree_model_iter_next(model, &i)) {
|
||||||
break;
|
break;
|
||||||
@@ -1312,19 +1341,19 @@ void set_panel_items(const char *items)
|
|||||||
} else if (v == ':') {
|
} else if (v == ':') {
|
||||||
separator_index++;
|
separator_index++;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Separator"), separator_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Separator"), separator_index + 1);
|
||||||
name = buffer;
|
name = buffer;
|
||||||
value = ":";
|
value = ":";
|
||||||
} else if (v == 'E') {
|
} else if (v == 'E') {
|
||||||
execp_index++;
|
execp_index++;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Executor"), execp_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Executor"), execp_index + 1);
|
||||||
name = buffer;
|
name = buffer;
|
||||||
value = "E";
|
value = "E";
|
||||||
} else if (v == 'P') {
|
} else if (v == 'P') {
|
||||||
button_index++;
|
button_index++;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Button"), button_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Button"), button_index + 1);
|
||||||
name = buffer;
|
name = buffer;
|
||||||
value = "P";
|
value = "P";
|
||||||
} else {
|
} else {
|
||||||
@@ -2689,6 +2718,7 @@ void create_taskbar(GtkWidget *parent)
|
|||||||
col++;
|
col++;
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("None"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("None"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By title"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By title"));
|
||||||
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By application"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By center"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By center"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used first"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used first"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used last"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used last"));
|
||||||
@@ -2699,6 +2729,7 @@ void create_taskbar(GtkWidget *parent)
|
|||||||
"'None' means that new tasks are added to the end, and the user can also reorder task "
|
"'None' means that new tasks are added to the end, and the user can also reorder task "
|
||||||
"buttons by mouse dragging. \n"
|
"buttons by mouse dragging. \n"
|
||||||
"'By title' means that tasks are sorted by their window titles. \n"
|
"'By title' means that tasks are sorted by their window titles. \n"
|
||||||
|
"'By application' means that tasks are sorted by their application names. \n"
|
||||||
"'By center' means that tasks are sorted geometrically by their window centers."),
|
"'By center' means that tasks are sorted geometrically by their window centers."),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
@@ -3288,6 +3319,36 @@ void create_task(GtkWidget *parent)
|
|||||||
"over task buttons."),
|
"over task buttons."),
|
||||||
NULL);
|
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;
|
row++, col = 2;
|
||||||
label = gtk_label_new(_("Maximum width"));
|
label = gtk_label_new(_("Maximum width"));
|
||||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||||
@@ -4067,7 +4128,7 @@ void create_separator(GtkWidget *notebook, int i)
|
|||||||
Separator *separator = &g_array_index(separators, Separator, i);
|
Separator *separator = &g_array_index(separators, Separator, i);
|
||||||
|
|
||||||
separator->name[0] = 0;
|
separator->name[0] = 0;
|
||||||
sprintf(separator->name, "%s %d", _("Separator"), i + 1);
|
snprintf(separator->name, sizeof(separator->name), "%s %d", _("Separator"), i + 1);
|
||||||
separator->page_label = gtk_label_new(separator->name);
|
separator->page_label = gtk_label_new(separator->name);
|
||||||
gtk_widget_show(separator->page_label);
|
gtk_widget_show(separator->page_label);
|
||||||
separator->page_separator = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
separator->page_separator = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
||||||
@@ -4193,7 +4254,7 @@ void create_execp(GtkWidget *notebook, int i)
|
|||||||
Executor *executor = &g_array_index(executors, Executor, i);
|
Executor *executor = &g_array_index(executors, Executor, i);
|
||||||
|
|
||||||
executor->name[0] = 0;
|
executor->name[0] = 0;
|
||||||
sprintf(executor->name, "%s %d", _("Executor"), i + 1);
|
snprintf(executor->name, sizeof(executor->name), "%s %d", _("Executor"), i + 1);
|
||||||
executor->page_label = gtk_label_new(executor->name);
|
executor->page_label = gtk_label_new(executor->name);
|
||||||
gtk_widget_show(executor->page_label);
|
gtk_widget_show(executor->page_label);
|
||||||
executor->page_execp = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
executor->page_execp = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
||||||
@@ -4614,7 +4675,7 @@ void create_button(GtkWidget *notebook, int i)
|
|||||||
Button *button = &g_array_index(buttons, Button, i);
|
Button *button = &g_array_index(buttons, Button, i);
|
||||||
|
|
||||||
button->name[0] = 0;
|
button->name[0] = 0;
|
||||||
sprintf(button->name, "%s %d", _("Button"), i + 1);
|
snprintf(button->name, sizeof(button->name), "%s %d", _("Button"), i + 1);
|
||||||
button->page_label = gtk_label_new(button->name);
|
button->page_label = gtk_label_new(button->name);
|
||||||
gtk_widget_show(button->page_label);
|
gtk_widget_show(button->page_label);
|
||||||
button->page_button = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
button->page_button = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
||||||
@@ -5003,7 +5064,7 @@ void separator_update_indices()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < separators->len; i++) {
|
for (int i = 0; i < separators->len; i++) {
|
||||||
Separator *separator = &g_array_index(separators, Separator, i);
|
Separator *separator = &g_array_index(separators, Separator, i);
|
||||||
sprintf(separator->name, "%s %d", _("Separator"), i + 1);
|
snprintf(separator->name, sizeof(separator->name), "%s %d", _("Separator"), i + 1);
|
||||||
gtk_label_set_text(GTK_LABEL(separator->page_label), separator->name);
|
gtk_label_set_text(GTK_LABEL(separator->page_label), separator->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5021,7 +5082,7 @@ void separator_update_indices()
|
|||||||
separator_index++;
|
separator_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Separator"), separator_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Separator"), separator_index + 1);
|
||||||
|
|
||||||
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
||||||
}
|
}
|
||||||
@@ -5035,7 +5096,7 @@ void execp_update_indices()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < executors->len; i++) {
|
for (int i = 0; i < executors->len; i++) {
|
||||||
Executor *executor = &g_array_index(executors, Executor, i);
|
Executor *executor = &g_array_index(executors, Executor, i);
|
||||||
sprintf(executor->name, "%s %d", _("Executor"), i + 1);
|
snprintf(executor->name, sizeof(executor->name), "%s %d", _("Executor"), i + 1);
|
||||||
gtk_label_set_text(GTK_LABEL(executor->page_label), executor->name);
|
gtk_label_set_text(GTK_LABEL(executor->page_label), executor->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5053,7 +5114,7 @@ void execp_update_indices()
|
|||||||
execp_index++;
|
execp_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Executor"), execp_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Executor"), execp_index + 1);
|
||||||
|
|
||||||
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
||||||
}
|
}
|
||||||
@@ -5067,7 +5128,7 @@ void button_update_indices()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < buttons->len; i++) {
|
for (int i = 0; i < buttons->len; i++) {
|
||||||
Button *button = &g_array_index(buttons, Button, i);
|
Button *button = &g_array_index(buttons, Button, i);
|
||||||
sprintf(button->name, "%s %d", _("Button"), i + 1);
|
snprintf(button->name, sizeof(button->name), "%s %d", _("Button"), i + 1);
|
||||||
gtk_label_set_text(GTK_LABEL(button->page_label), button->name);
|
gtk_label_set_text(GTK_LABEL(button->page_label), button->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5085,7 +5146,7 @@ void button_update_indices()
|
|||||||
button_index++;
|
button_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Button"), button_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Button"), button_index + 1);
|
||||||
|
|
||||||
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
||||||
}
|
}
|
||||||
@@ -5136,8 +5197,8 @@ void create_systemtray(GtkWidget *parent)
|
|||||||
_("Specifies the order used to arrange the system tray icons. \n"
|
_("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"
|
"'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"
|
"'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"
|
"'Left to right' means that icons are always added to the right. \n"
|
||||||
"'Right to left' means that icons are always added to the right."),
|
"'Right to left' means that icons are always added to the left."),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
row++;
|
row++;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "../launcher/icon-theme-common.h"
|
#include "../launcher/icon-theme-common.h"
|
||||||
|
|
||||||
// panel
|
// panel
|
||||||
|
extern GtkWidget *scale_relative_to_dpi, *scale_relative_to_screen_height;
|
||||||
extern GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
extern GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
||||||
*panel_spacing;
|
*panel_spacing;
|
||||||
extern GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
extern GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
||||||
@@ -105,7 +106,7 @@ extern GtkWidget *systray_background, *systray_monitor, *systray_name_filter;
|
|||||||
|
|
||||||
// tooltip
|
// tooltip
|
||||||
extern GtkWidget *tooltip_padding_x, *tooltip_padding_y, *tooltip_font, *tooltip_font_set, *tooltip_font_color;
|
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 *clock_format_tooltip, *clock_tmz_tooltip;
|
||||||
extern GtkWidget *tooltip_background;
|
extern GtkWidget *tooltip_background;
|
||||||
|
|
||||||
@@ -203,6 +204,8 @@ enum {
|
|||||||
bgColBorderSidesBottom,
|
bgColBorderSidesBottom,
|
||||||
bgColBorderSidesLeft,
|
bgColBorderSidesLeft,
|
||||||
bgColBorderSidesRight,
|
bgColBorderSidesRight,
|
||||||
|
bgColFillWeight,
|
||||||
|
bgColBorderWeight,
|
||||||
bgNumCols
|
bgNumCols
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -211,7 +214,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_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_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_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
|
// gradients
|
||||||
enum { grColPixbuf = 0, grColId, grColText, grNumCols };
|
enum { grColPixbuf = 0, grColId, grColText, grNumCols };
|
||||||
|
|||||||
@@ -69,23 +69,23 @@ void config_read_file(const char *path)
|
|||||||
if (!config_has_panel_items) {
|
if (!config_has_panel_items) {
|
||||||
char panel_items[256];
|
char panel_items[256];
|
||||||
panel_items[0] = 0;
|
panel_items[0] = 0;
|
||||||
strcat(panel_items, "T");
|
strlcat(panel_items, "T", sizeof(panel_items));
|
||||||
if (config_has_battery) {
|
if (config_has_battery) {
|
||||||
if (config_battery_enabled)
|
if (config_battery_enabled)
|
||||||
strcat(panel_items, "B");
|
strlcat(panel_items, "B", sizeof(panel_items));
|
||||||
} else {
|
} else {
|
||||||
if (no_items_battery_enabled)
|
if (no_items_battery_enabled)
|
||||||
strcat(panel_items, "B");
|
strlcat(panel_items, "B", sizeof(panel_items));
|
||||||
}
|
}
|
||||||
if (config_has_systray) {
|
if (config_has_systray) {
|
||||||
if (config_systray_enabled)
|
if (config_systray_enabled)
|
||||||
strcat(panel_items, "S");
|
strlcat(panel_items, "S", sizeof(panel_items));
|
||||||
} else {
|
} else {
|
||||||
if (no_items_systray_enabled)
|
if (no_items_systray_enabled)
|
||||||
strcat(panel_items, "S");
|
strlcat(panel_items, "S", sizeof(panel_items));
|
||||||
}
|
}
|
||||||
if (no_items_clock_enabled)
|
if (no_items_clock_enabled)
|
||||||
strcat(panel_items, "C");
|
strlcat(panel_items, "C", sizeof(panel_items));
|
||||||
set_panel_items(panel_items);
|
set_panel_items(panel_items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,6 +161,8 @@ void config_write_backgrounds(FILE *fp)
|
|||||||
|
|
||||||
int r;
|
int r;
|
||||||
int b;
|
int b;
|
||||||
|
double fill_weight;
|
||||||
|
double border_weight;
|
||||||
gboolean sideTop;
|
gboolean sideTop;
|
||||||
gboolean sideBottom;
|
gboolean sideBottom;
|
||||||
gboolean sideLeft;
|
gboolean sideLeft;
|
||||||
@@ -228,6 +230,10 @@ void config_write_backgrounds(FILE *fp)
|
|||||||
&sideLeft,
|
&sideLeft,
|
||||||
bgColBorderSidesRight,
|
bgColBorderSidesRight,
|
||||||
&sideRight,
|
&sideRight,
|
||||||
|
bgColFillWeight,
|
||||||
|
&fill_weight,
|
||||||
|
bgColBorderWeight,
|
||||||
|
&border_weight,
|
||||||
-1);
|
-1);
|
||||||
fprintf(fp, "# Background %d: %s\n", index, text ? text : "");
|
fprintf(fp, "# Background %d: %s\n", index, text ? text : "");
|
||||||
fprintf(fp, "rounded = %d\n", r);
|
fprintf(fp, "rounded = %d\n", r);
|
||||||
@@ -236,15 +242,18 @@ void config_write_backgrounds(FILE *fp)
|
|||||||
char sides[10];
|
char sides[10];
|
||||||
sides[0] = '\0';
|
sides[0] = '\0';
|
||||||
if (sideTop)
|
if (sideTop)
|
||||||
strcat(sides, "T");
|
strlcat(sides, "T", sizeof(sides));
|
||||||
if (sideBottom)
|
if (sideBottom)
|
||||||
strcat(sides, "B");
|
strlcat(sides, "B", sizeof(sides));
|
||||||
if (sideLeft)
|
if (sideLeft)
|
||||||
strcat(sides, "L");
|
strlcat(sides, "L", sizeof(sides));
|
||||||
if (sideRight)
|
if (sideRight)
|
||||||
strcat(sides, "R");
|
strlcat(sides, "R", sizeof(sides));
|
||||||
fprintf(fp, "border_sides = %s\n", sides);
|
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, "background_color", *fillColor, fillOpacity);
|
||||||
config_write_color(fp, "border_color", *borderColor, borderOpacity);
|
config_write_color(fp, "border_color", *borderColor, borderOpacity);
|
||||||
if (gradient_id >= 0)
|
if (gradient_id >= 0)
|
||||||
@@ -369,6 +378,13 @@ void config_write_panel(FILE *fp)
|
|||||||
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_saturation)),
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_saturation)),
|
||||||
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_brightness)));
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_brightness)));
|
||||||
|
|
||||||
|
fprintf(fp,
|
||||||
|
"scale_relative_to_dpi = %d\n",
|
||||||
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scale_relative_to_dpi)));
|
||||||
|
fprintf(fp,
|
||||||
|
"scale_relative_to_screen_height = %d\n",
|
||||||
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scale_relative_to_screen_height)));
|
||||||
|
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,10 +457,12 @@ void config_write_taskbar(FILE *fp)
|
|||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 1) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 1) {
|
||||||
fprintf(fp, "title");
|
fprintf(fp, "title");
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 2) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 2) {
|
||||||
fprintf(fp, "center");
|
fprintf(fp, "application");
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 3) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 3) {
|
||||||
fprintf(fp, "mru");
|
fprintf(fp, "center");
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 4) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 4) {
|
||||||
|
fprintf(fp, "mru");
|
||||||
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 5) {
|
||||||
fprintf(fp, "lru");
|
fprintf(fp, "lru");
|
||||||
} else {
|
} else {
|
||||||
fprintf(fp, "none");
|
fprintf(fp, "none");
|
||||||
@@ -469,7 +487,7 @@ void config_write_task_font_color(FILE *fp, char *name, GtkWidget *task_color)
|
|||||||
GdkColor color;
|
GdkColor color;
|
||||||
gtk_color_button_get_color(GTK_COLOR_BUTTON(task_color), &color);
|
gtk_color_button_get_color(GTK_COLOR_BUTTON(task_color), &color);
|
||||||
char full_name[128];
|
char full_name[128];
|
||||||
sprintf(full_name, "task%s_font_color", name);
|
snprintf(full_name, sizeof(full_name), "task%s_font_color", name);
|
||||||
config_write_color(fp, full_name, color, gtk_color_button_get_alpha(GTK_COLOR_BUTTON(task_color)) * 100 / 0xffff);
|
config_write_color(fp, full_name, color, gtk_color_button_get_alpha(GTK_COLOR_BUTTON(task_color)) * 100 / 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,7 +498,7 @@ void config_write_task_icon_osb(FILE *fp,
|
|||||||
GtkWidget *widget_brightness)
|
GtkWidget *widget_brightness)
|
||||||
{
|
{
|
||||||
char full_name[128];
|
char full_name[128];
|
||||||
sprintf(full_name, "task%s_icon_asb", name);
|
snprintf(full_name, sizeof(full_name), "task%s_icon_asb", name);
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
"%s = %d %d %d\n",
|
"%s = %d %d %d\n",
|
||||||
full_name,
|
full_name,
|
||||||
@@ -492,7 +510,7 @@ void config_write_task_icon_osb(FILE *fp,
|
|||||||
void config_write_task_background(FILE *fp, char *name, GtkWidget *task_background)
|
void config_write_task_background(FILE *fp, char *name, GtkWidget *task_background)
|
||||||
{
|
{
|
||||||
char full_name[128];
|
char full_name[128];
|
||||||
sprintf(full_name, "task%s_background_id", name);
|
snprintf(full_name, sizeof(full_name), "task%s_background_id", name);
|
||||||
fprintf(fp, "%s = %d\n", full_name, gtk_combo_box_get_active(GTK_COMBO_BOX(task_background)));
|
fprintf(fp, "%s = %d\n", full_name, gtk_combo_box_get_active(GTK_COMBO_BOX(task_background)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,6 +535,11 @@ void config_write_task(FILE *fp)
|
|||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(task_font_set)))
|
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_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_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
|
// same for: "" _normal _active _urgent _iconified
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(task_default_color_set))) {
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(task_default_color_set))) {
|
||||||
@@ -1094,7 +1117,13 @@ void add_entry(char *key, char *value)
|
|||||||
char *value1 = 0, *value2 = 0, *value3 = 0;
|
char *value1 = 0, *value2 = 0, *value3 = 0;
|
||||||
|
|
||||||
/* Gradients */
|
/* Gradients */
|
||||||
if (strcmp(key, "gradient") == 0) {
|
if (strcmp(key, "scale_relative_to_dpi") == 0) {
|
||||||
|
extract_values(value, &value1, &value2, &value3);
|
||||||
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(scale_relative_to_dpi), atoi(value1));
|
||||||
|
} else if (strcmp(key, "scale_relative_to_screen_height") == 0) {
|
||||||
|
extract_values(value, &value1, &value2, &value3);
|
||||||
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(scale_relative_to_screen_height), atoi(value1));
|
||||||
|
} else if (strcmp(key, "gradient") == 0) {
|
||||||
finalize_gradient();
|
finalize_gradient();
|
||||||
GradientConfigType t;
|
GradientConfigType t;
|
||||||
if (g_str_equal(value, "horizontal"))
|
if (g_str_equal(value, "horizontal"))
|
||||||
@@ -1225,6 +1254,12 @@ void add_entry(char *key, char *value)
|
|||||||
int id = gradient_index_safe(atoi(value));
|
int id = gradient_index_safe(atoi(value));
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(background_gradient_press), id);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(background_gradient_press), id);
|
||||||
background_force_update();
|
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 */
|
/* Panel */
|
||||||
@@ -1526,12 +1561,14 @@ void add_entry(char *key, char *value)
|
|||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
||||||
else if (strcmp(value, "title") == 0)
|
else if (strcmp(value, "title") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 1);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 1);
|
||||||
else if (strcmp(value, "center") == 0)
|
else if (strcmp(value, "application") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 2);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 2);
|
||||||
else if (strcmp(value, "mru") == 0)
|
else if (strcmp(value, "center") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 3);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 3);
|
||||||
else if (strcmp(value, "lru") == 0)
|
else if (strcmp(value, "mru") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 4);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 4);
|
||||||
|
else if (strcmp(value, "lru") == 0)
|
||||||
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 5);
|
||||||
else
|
else
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
||||||
} else if (strcmp(key, "task_align") == 0) {
|
} else if (strcmp(key, "task_align") == 0) {
|
||||||
@@ -1732,6 +1769,10 @@ void add_entry(char *key, char *value)
|
|||||||
else if (strcmp(key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0) {
|
else if (strcmp(key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0) {
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltip_task_show), atoi(value));
|
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 */
|
/* Systray */
|
||||||
else if (strcmp(key, "systray") == 0) {
|
else if (strcmp(key, "systray") == 0) {
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ gboolean update_snapshot(gpointer ignored)
|
|||||||
|
|
||||||
char hash[MD4_HEX_SIZE + 4];
|
char hash[MD4_HEX_SIZE + 4];
|
||||||
md4hexf(path, hash);
|
md4hexf(path, hash);
|
||||||
strcat(hash, ".png");
|
strlcat(hash, ".png", sizeof(hash));
|
||||||
|
|
||||||
gchar *snap = g_build_filename(g_get_user_cache_dir(), "tint2", hash, NULL);
|
gchar *snap = g_build_filename(g_get_user_cache_dir(), "tint2", hash, NULL);
|
||||||
pixbuf = force_refresh ? NULL : gdk_pixbuf_new_from_file(snap, NULL);
|
pixbuf = force_refresh ? NULL : gdk_pixbuf_new_from_file(snap, NULL);
|
||||||
|
|||||||
+76
-33
@@ -31,9 +31,9 @@ static int x, y, width, height;
|
|||||||
static gboolean just_shown;
|
static gboolean just_shown;
|
||||||
|
|
||||||
// the next functions are helper functions for tooltip handling
|
// the next functions are helper functions for tooltip handling
|
||||||
void start_show_timeout();
|
void start_show_timer();
|
||||||
void start_hide_timeout();
|
void start_hide_timer();
|
||||||
void stop_tooltip_timeout();
|
void stop_tooltip_timer();
|
||||||
|
|
||||||
void tooltip_init_fonts();
|
void tooltip_init_fonts();
|
||||||
|
|
||||||
@@ -44,6 +44,9 @@ void default_tooltip()
|
|||||||
// give the tooltip some reasonable default values
|
// give the tooltip some reasonable default values
|
||||||
memset(&g_tooltip, 0, sizeof(Tooltip));
|
memset(&g_tooltip, 0, sizeof(Tooltip));
|
||||||
|
|
||||||
|
INIT_TIMER(g_tooltip.visibility_timer);
|
||||||
|
INIT_TIMER(g_tooltip.update_timer);
|
||||||
|
|
||||||
g_tooltip.font_color.rgb[0] = 1;
|
g_tooltip.font_color.rgb[0] = 1;
|
||||||
g_tooltip.font_color.rgb[1] = 1;
|
g_tooltip.font_color.rgb[1] = 1;
|
||||||
g_tooltip.font_color.rgb[2] = 1;
|
g_tooltip.font_color.rgb[2] = 1;
|
||||||
@@ -53,9 +56,11 @@ void default_tooltip()
|
|||||||
|
|
||||||
void cleanup_tooltip()
|
void cleanup_tooltip()
|
||||||
{
|
{
|
||||||
stop_tooltip_timeout();
|
stop_tooltip_timer();
|
||||||
|
destroy_timer(&g_tooltip.visibility_timer);
|
||||||
|
destroy_timer(&g_tooltip.update_timer);
|
||||||
tooltip_hide(NULL);
|
tooltip_hide(NULL);
|
||||||
tooltip_copy_text(NULL);
|
tooltip_update_contents_for(NULL);
|
||||||
if (g_tooltip.window)
|
if (g_tooltip.window)
|
||||||
XDestroyWindow(server.display, g_tooltip.window);
|
XDestroyWindow(server.display, g_tooltip.window);
|
||||||
g_tooltip.window = 0;
|
g_tooltip.window = 0;
|
||||||
@@ -118,11 +123,11 @@ void tooltip_trigger_show(Area *area, Panel *p, XEvent *e)
|
|||||||
just_shown = TRUE;
|
just_shown = TRUE;
|
||||||
g_tooltip.panel = p;
|
g_tooltip.panel = p;
|
||||||
if (g_tooltip.mapped && g_tooltip.area != area) {
|
if (g_tooltip.mapped && g_tooltip.area != area) {
|
||||||
tooltip_copy_text(area);
|
tooltip_update_contents_for(area);
|
||||||
tooltip_update();
|
tooltip_update();
|
||||||
stop_tooltip_timeout();
|
stop_tooltip_timer();
|
||||||
} else if (!g_tooltip.mapped) {
|
} else if (!g_tooltip.mapped) {
|
||||||
start_show_timeout();
|
start_show_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +138,7 @@ void tooltip_show(void *arg)
|
|||||||
XTranslateCoordinates(server.display, server.root_win, g_tooltip.panel->main_win, x, y, &mx, &my, &w);
|
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);
|
Area *area = find_area_under_mouse(g_tooltip.panel, mx, my);
|
||||||
if (!g_tooltip.mapped && area->_get_tooltip_text) {
|
if (!g_tooltip.mapped && area->_get_tooltip_text) {
|
||||||
tooltip_copy_text(area);
|
tooltip_update_contents_for(area);
|
||||||
g_tooltip.mapped = True;
|
g_tooltip.mapped = True;
|
||||||
XMapWindow(server.display, g_tooltip.window);
|
XMapWindow(server.display, g_tooltip.window);
|
||||||
tooltip_update();
|
tooltip_update();
|
||||||
@@ -144,24 +149,35 @@ void tooltip_show(void *arg)
|
|||||||
void tooltip_update_geometry()
|
void tooltip_update_geometry()
|
||||||
{
|
{
|
||||||
Panel *panel = g_tooltip.panel;
|
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_surface_t *cs = cairo_xlib_surface_create(server.display, g_tooltip.window, server.visual, width, height);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
||||||
PangoRectangle r1, r2;
|
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);
|
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 * panel->scale +
|
||||||
|
cairo_image_surface_get_width(g_tooltip.image);
|
||||||
|
}
|
||||||
pango_layout_set_width(layout, max_width * PANGO_SCALE);
|
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_set_wrap(layout, PANGO_WRAP_WORD);
|
||||||
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
||||||
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx + r2.width;
|
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx * panel->scale + r2.width;
|
||||||
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy + r2.height;
|
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy * panel->scale + 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 * panel->scale +
|
||||||
|
cairo_image_surface_get_width(g_tooltip.image);
|
||||||
|
height += g_tooltip.paddingy * panel->scale + cairo_image_surface_get_height(g_tooltip.image);
|
||||||
|
}
|
||||||
|
|
||||||
if (panel_horizontal && panel_position & BOTTOM)
|
if (panel_horizontal && panel_position & BOTTOM)
|
||||||
y = panel->posy - height;
|
y = panel->posy - height;
|
||||||
@@ -173,6 +189,7 @@ void tooltip_update_geometry()
|
|||||||
x = panel->posx - width;
|
x = panel->posx - width;
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
}
|
}
|
||||||
@@ -229,6 +246,7 @@ void tooltip_update()
|
|||||||
tooltip_hide(0);
|
tooltip_hide(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Panel *panel = g_tooltip.panel;
|
||||||
|
|
||||||
tooltip_update_geometry();
|
tooltip_update_geometry();
|
||||||
if (just_shown) {
|
if (just_shown) {
|
||||||
@@ -263,7 +281,9 @@ void tooltip_update()
|
|||||||
|
|
||||||
Color fc = g_tooltip.font_color;
|
Color fc = g_tooltip.font_color;
|
||||||
cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha);
|
cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha);
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
||||||
pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
|
pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
|
||||||
@@ -275,11 +295,20 @@ void tooltip_update()
|
|||||||
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and
|
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and
|
||||||
// vert.)
|
// vert.)
|
||||||
cairo_move_to(c,
|
cairo_move_to(c,
|
||||||
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
|
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx * panel->scale,
|
||||||
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy);
|
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy * panel->scale);
|
||||||
pango_cairo_show_layout(c, layout);
|
pango_cairo_show_layout(c, layout);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
|
|
||||||
|
if (g_tooltip.image) {
|
||||||
|
cairo_translate(c,
|
||||||
|
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx * panel->scale,
|
||||||
|
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy * panel->scale - 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_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
}
|
}
|
||||||
@@ -287,11 +316,11 @@ void tooltip_update()
|
|||||||
void tooltip_trigger_hide()
|
void tooltip_trigger_hide()
|
||||||
{
|
{
|
||||||
if (g_tooltip.mapped) {
|
if (g_tooltip.mapped) {
|
||||||
tooltip_copy_text(0);
|
tooltip_update_contents_for(NULL);
|
||||||
start_hide_timeout();
|
start_hide_timer();
|
||||||
} else {
|
} else {
|
||||||
// tooltip not visible yet, but maybe a timeout is still pending
|
// tooltip not visible yet, but maybe a timer is still pending
|
||||||
stop_tooltip_timeout();
|
stop_tooltip_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,29 +331,43 @@ void tooltip_hide(void *arg)
|
|||||||
XUnmapWindow(server.display, g_tooltip.window);
|
XUnmapWindow(server.display, g_tooltip.window);
|
||||||
XFlush(server.display);
|
XFlush(server.display);
|
||||||
}
|
}
|
||||||
|
g_tooltip.area = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_show_timeout()
|
void start_show_timer()
|
||||||
{
|
{
|
||||||
change_timeout(&g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
change_timer(&g_tooltip.visibility_timer, true, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_hide_timeout()
|
void start_hide_timer()
|
||||||
{
|
{
|
||||||
change_timeout(&g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
change_timer(&g_tooltip.visibility_timer, true, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_tooltip_timeout()
|
void stop_tooltip_timer()
|
||||||
{
|
{
|
||||||
stop_timeout(g_tooltip.timeout);
|
stop_timer(&g_tooltip.visibility_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (area && area->_get_tooltip_text)
|
||||||
g_tooltip.tooltip_text = area->_get_tooltip_text(area);
|
g_tooltip.tooltip_text = area->_get_tooltip_text(area);
|
||||||
|
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
|
else
|
||||||
g_tooltip.tooltip_text = NULL;
|
change_timer(&g_tooltip.update_timer, true, 300, 0, tooltip_update_contents_timeout, NULL);
|
||||||
|
}
|
||||||
g_tooltip.area = area;
|
g_tooltip.area = area;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ typedef struct {
|
|||||||
PangoFontDescription *font_desc;
|
PangoFontDescription *font_desc;
|
||||||
Color font_color;
|
Color font_color;
|
||||||
Background *bg;
|
Background *bg;
|
||||||
timeout *timeout;
|
Timer visibility_timer;
|
||||||
|
Timer update_timer;
|
||||||
|
cairo_surface_t *image;
|
||||||
} Tooltip;
|
} Tooltip;
|
||||||
|
|
||||||
extern Tooltip g_tooltip;
|
extern Tooltip g_tooltip;
|
||||||
@@ -53,7 +55,7 @@ void tooltip_show(void * /*arg*/);
|
|||||||
void tooltip_update();
|
void tooltip_update();
|
||||||
void tooltip_trigger_hide();
|
void tooltip_trigger_hide();
|
||||||
void tooltip_hide(void * /*arg*/);
|
void tooltip_hide(void * /*arg*/);
|
||||||
void tooltip_copy_text(Area *area);
|
void tooltip_update_contents_for(Area *area);
|
||||||
void tooltip_default_font_changed();
|
void tooltip_default_font_changed();
|
||||||
|
|
||||||
#endif // TOOLTIP_H
|
#endif // TOOLTIP_H
|
||||||
|
|||||||
+111
-72
@@ -478,40 +478,71 @@ void draw(Area *a)
|
|||||||
a->_clear(a);
|
a->_clear(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t *cs = cairo_xlib_surface_create(server.display, a->pix, server.visual, a->width, a->height);
|
cairo_surface_t *cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, a->width, a->height);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
|
|
||||||
draw_background(a, c);
|
draw_background(a, c);
|
||||||
|
|
||||||
if (a->_draw_foreground)
|
if (a->_draw_foreground)
|
||||||
a->_draw_foreground(a, c);
|
a->_draw_foreground(a, c);
|
||||||
|
|
||||||
|
draw_cairo_surface_to_xpixmap(cs, a->pix);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void draw_background(Area *a, cairo_t *c)
|
||||||
{
|
{
|
||||||
if ((a->bg->fill_color.alpha > 0.0) ||
|
if ((a->bg->fill_color.alpha > 0.0) ||
|
||||||
(panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect))) {
|
(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
|
// Not sure about this
|
||||||
draw_rect(c,
|
draw_rect(c,
|
||||||
left_border_width(a),
|
left_border_width(a),
|
||||||
@@ -519,7 +550,7 @@ void draw_background(Area *a, cairo_t *c)
|
|||||||
a->width - left_right_border_width(a),
|
a->width - left_right_border_width(a),
|
||||||
a->height - top_bottom_border_width(a),
|
a->height - top_bottom_border_width(a),
|
||||||
a->bg->border.radius - a->bg->border.width / 1.571);
|
a->bg->border.radius - a->bg->border.width / 1.571);
|
||||||
|
set_cairo_source_bg_color(a, c);
|
||||||
cairo_fill(c);
|
cairo_fill(c);
|
||||||
}
|
}
|
||||||
for (GList *l = a->gradient_instances_by_state[a->mouse_state]; l; l = l->next) {
|
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);
|
cairo_set_line_width(c, a->bg->border.width);
|
||||||
|
|
||||||
// draw border inside (x, y, width, height)
|
// draw border inside (x, y, width, height)
|
||||||
if (a->mouse_state == MOUSE_OVER)
|
set_cairo_source_border_color(a, c);
|
||||||
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);
|
|
||||||
draw_rect_on_sides(c,
|
draw_rect_on_sides(c,
|
||||||
left_border_width(a) / 2.,
|
left_border_width(a) / 2.,
|
||||||
top_border_width(a) / 2.,
|
top_border_width(a) / 2.,
|
||||||
@@ -850,7 +864,7 @@ void area_dump_geometry(Area *area, int indent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fprintf(stderr,
|
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,
|
indent,
|
||||||
"",
|
"",
|
||||||
area->posx,
|
area->posx,
|
||||||
@@ -859,7 +873,7 @@ void area_dump_geometry(Area *area, int indent)
|
|||||||
area->height,
|
area->height,
|
||||||
compute_desired_size(area));
|
compute_desired_size(area));
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%*sBorder: left = %d, right = %d, top = %d, bottom = %d\n",
|
"tint2: %*sBorder: left = %d, right = %d, top = %d, bottom = %d\n",
|
||||||
indent,
|
indent,
|
||||||
"",
|
"",
|
||||||
left_border_width(area),
|
left_border_width(area),
|
||||||
@@ -867,7 +881,7 @@ void area_dump_geometry(Area *area, int indent)
|
|||||||
top_border_width(area),
|
top_border_width(area),
|
||||||
bottom_border_width(area));
|
bottom_border_width(area));
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%*sPadding: left = right = %d, top = bottom = %d, spacing = %d\n",
|
"tint2: %*sPadding: left = right = %d, top = bottom = %d, spacing = %d\n",
|
||||||
indent,
|
indent,
|
||||||
"",
|
"",
|
||||||
area->paddingxlr,
|
area->paddingxlr,
|
||||||
@@ -883,31 +897,48 @@ 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,
|
void area_compute_text_geometry(Area *area,
|
||||||
const char *line1,
|
const char *line1,
|
||||||
const char *line2,
|
const char *line2,
|
||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int *line1_height_ink,
|
|
||||||
int *line1_height,
|
int *line1_height,
|
||||||
int *line1_width,
|
int *line1_width,
|
||||||
int *line2_height_ink,
|
|
||||||
int *line2_height,
|
int *line2_height,
|
||||||
int *line2_width)
|
int *line2_width)
|
||||||
{
|
{
|
||||||
Panel *panel = (Panel *)area->panel;
|
|
||||||
int available_w, available_h;
|
int available_w, available_h;
|
||||||
if (panel_horizontal) {
|
area_compute_available_size(area, &available_w, &available_h);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line1 && line1[0])
|
if (line1 && line1[0])
|
||||||
get_text_size2(line1_font_desc,
|
get_text_size2(line1_font_desc,
|
||||||
line1_height_ink,
|
|
||||||
line1_height,
|
line1_height,
|
||||||
line1_width,
|
line1_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -916,13 +947,14 @@ void area_compute_text_geometry(Area *area,
|
|||||||
strlen(line1),
|
strlen(line1),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
((Panel*)area->panel)->scale);
|
||||||
else
|
else
|
||||||
*line1_width = *line1_height_ink = *line1_height = 0;
|
*line1_width = *line1_height = 0;
|
||||||
|
|
||||||
if (line2 && line2[0])
|
if (line2 && line2[0])
|
||||||
get_text_size2(line2_font_desc,
|
get_text_size2(line2_font_desc,
|
||||||
line2_height_ink,
|
|
||||||
line2_height,
|
line2_height,
|
||||||
line2_width,
|
line2_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -931,9 +963,11 @@ void area_compute_text_geometry(Area *area,
|
|||||||
strlen(line2),
|
strlen(line2),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
((Panel*)area->panel)->scale);
|
||||||
else
|
else
|
||||||
*line2_width = *line2_height_ink = *line2_height = 0;
|
*line2_width = *line2_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int text_area_compute_desired_size(Area *area,
|
int text_area_compute_desired_size(Area *area,
|
||||||
@@ -942,16 +976,14 @@ int text_area_compute_desired_size(Area *area,
|
|||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc)
|
PangoFontDescription *line2_font_desc)
|
||||||
{
|
{
|
||||||
int line1_height_ink, line1_height, line1_width, line2_height_ink, line2_height, line2_width;
|
int line1_height, line1_width, line2_height, line2_width;
|
||||||
area_compute_text_geometry(area,
|
area_compute_text_geometry(area,
|
||||||
line1,
|
line1,
|
||||||
line2,
|
line2,
|
||||||
line1_font_desc,
|
line1_font_desc,
|
||||||
line2_font_desc,
|
line2_font_desc,
|
||||||
&line1_height_ink,
|
|
||||||
&line1_height,
|
&line1_height,
|
||||||
&line1_width,
|
&line1_width,
|
||||||
&line2_height_ink,
|
|
||||||
&line2_height,
|
&line2_height,
|
||||||
&line2_width);
|
&line2_width);
|
||||||
|
|
||||||
@@ -959,7 +991,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);
|
int new_size = MAX(line1_width, line2_width) + 2 * area->paddingxlr + left_right_border_width(area);
|
||||||
return new_size;
|
return new_size;
|
||||||
} else {
|
} 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;
|
return new_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -976,17 +1008,15 @@ gboolean resize_text_area(Area *area,
|
|||||||
|
|
||||||
schedule_redraw(area);
|
schedule_redraw(area);
|
||||||
|
|
||||||
int line1_height_ink, line1_height, line1_width;
|
int line1_height, line1_width;
|
||||||
int line2_height_ink, line2_height, line2_width;
|
int line2_height, line2_width;
|
||||||
area_compute_text_geometry(area,
|
area_compute_text_geometry(area,
|
||||||
line1,
|
line1,
|
||||||
line2,
|
line2,
|
||||||
line1_font_desc,
|
line1_font_desc,
|
||||||
line2_font_desc,
|
line2_font_desc,
|
||||||
&line1_height_ink,
|
|
||||||
&line1_height,
|
&line1_height,
|
||||||
&line1_width,
|
&line1_width,
|
||||||
&line2_height_ink,
|
|
||||||
&line2_height,
|
&line2_height,
|
||||||
&line2_width);
|
&line2_width);
|
||||||
|
|
||||||
@@ -1033,20 +1063,28 @@ void draw_text_area(Area *area,
|
|||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int line1_posy,
|
int line1_posy,
|
||||||
int line2_posy,
|
int line2_posy,
|
||||||
Color *color)
|
Color *color,
|
||||||
|
double scale)
|
||||||
{
|
{
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
int inner_w, inner_h;
|
||||||
|
area_compute_inner_size(area, &inner_w, &inner_h);
|
||||||
|
|
||||||
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
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);
|
cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha);
|
||||||
|
|
||||||
if (line1 && line1[0]) {
|
if (line1 && line1[0]) {
|
||||||
pango_layout_set_font_description(layout, line1_font_desc);
|
pango_layout_set_font_description(layout, line1_font_desc);
|
||||||
pango_layout_set_text(layout, line1, strlen(line1));
|
pango_layout_set_text(layout, line1, strlen(line1));
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
draw_text(layout, c, 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 ? layout : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line2 && line2[0]) {
|
if (line2 && line2[0]) {
|
||||||
@@ -1054,10 +1092,11 @@ void draw_text_area(Area *area,
|
|||||||
pango_layout_set_indent(layout, 0);
|
pango_layout_set_indent(layout, 0);
|
||||||
pango_layout_set_text(layout, line2, strlen(line2));
|
pango_layout_set_text(layout, line2, strlen(line2));
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
draw_text(layout, c, 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 ? layout : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Area *compute_element_area(Area *area, Element element)
|
Area *compute_element_area(Area *area, Element element)
|
||||||
@@ -1173,7 +1212,7 @@ double compute_control_point_offset(Area *area, Offset *offset)
|
|||||||
double height = element_area->height;
|
double height = element_area->height;
|
||||||
double radius = sqrt(element_area->width * element_area->width + element_area->height * element_area->height) / 2.0;
|
double radius = sqrt(element_area->width * element_area->width + element_area->height * element_area->height) / 2.0;
|
||||||
|
|
||||||
double left, top;
|
double left = 0, top = 0;
|
||||||
if (offset->element == ELEMENT_SELF) {
|
if (offset->element == ELEMENT_SELF) {
|
||||||
left = 0;
|
left = 0;
|
||||||
top = 0;
|
top = 0;
|
||||||
|
|||||||
+7
-3
@@ -154,6 +154,8 @@ typedef struct Background {
|
|||||||
Color border_color_pressed;
|
Color border_color_pressed;
|
||||||
// Pointer to a GradientClass or NULL, no ownership
|
// Pointer to a GradientClass or NULL, no ownership
|
||||||
GradientClass *gradients[MOUSE_STATE_COUNT];
|
GradientClass *gradients[MOUSE_STATE_COUNT];
|
||||||
|
double fill_content_tint_weight;
|
||||||
|
double border_content_tint_weight;
|
||||||
} Background;
|
} Background;
|
||||||
|
|
||||||
typedef enum Layout {
|
typedef enum Layout {
|
||||||
@@ -233,6 +235,7 @@ typedef struct Area {
|
|||||||
// Returns a copy of the tooltip to be displayed for this widget.
|
// Returns a copy of the tooltip to be displayed for this widget.
|
||||||
// The caller takes ownership of the pointer.
|
// The caller takes ownership of the pointer.
|
||||||
char *(*_get_tooltip_text)(void *obj);
|
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.
|
// 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.
|
// 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.
|
// Prints the geometry of the object on stderr, with left indentation of indent spaces.
|
||||||
void (*_dump_geometry)(void *obj, int indent);
|
void (*_dump_geometry)(void *obj, int indent);
|
||||||
|
|
||||||
|
void (*_get_content_color)(void *obj, Color *color);
|
||||||
} Area;
|
} Area;
|
||||||
|
|
||||||
// Initializes the Background member to default values.
|
// Initializes the Background member to default values.
|
||||||
@@ -268,10 +273,8 @@ void area_compute_text_geometry(Area *area,
|
|||||||
const char *line2,
|
const char *line2,
|
||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int *line1_height_ink,
|
|
||||||
int *line1_height,
|
int *line1_height,
|
||||||
int *line1_width,
|
int *line1_width,
|
||||||
int *line2_height_ink,
|
|
||||||
int *line2_height,
|
int *line2_height,
|
||||||
int *line2_width);
|
int *line2_width);
|
||||||
int text_area_compute_desired_size(Area *area,
|
int text_area_compute_desired_size(Area *area,
|
||||||
@@ -294,7 +297,8 @@ void draw_text_area(Area *area,
|
|||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int line1_posy,
|
int line1_posy,
|
||||||
int line2_posy,
|
int line2_posy,
|
||||||
Color *color);
|
Color *color,
|
||||||
|
double scale);
|
||||||
|
|
||||||
int left_border_width(Area *a);
|
int left_border_width(Area *a);
|
||||||
int right_border_width(Area *a);
|
int right_border_width(Area *a);
|
||||||
|
|||||||
@@ -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
|
||||||
+268
@@ -0,0 +1,268 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Tint2 : backtrace
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Pål Staurland (staura@gmail.com)
|
||||||
|
* Modified (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr) from Omega distribution
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "bt.h"
|
||||||
|
#include "bool.h"
|
||||||
|
|
||||||
|
#if defined(HAS_BACKTRACE) || defined(HAS_LIBUNWIND) || defined(HAS_EXECINFO)
|
||||||
|
|
||||||
|
static void bt_add_frame(struct backtrace *bt, const char *fname)
|
||||||
|
{
|
||||||
|
if (bt->frame_count >= BT_MAX_FRAMES)
|
||||||
|
return;
|
||||||
|
struct backtrace_frame *frame = &bt->frames[bt->frame_count];
|
||||||
|
if (fname && *fname) {
|
||||||
|
strncpy(frame->name, fname, BT_FRAME_SIZE);
|
||||||
|
} else {
|
||||||
|
strncpy(frame->name, "??", BT_FRAME_SIZE);
|
||||||
|
}
|
||||||
|
bt->frame_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_BACKTRACE
|
||||||
|
|
||||||
|
#include <backtrace.h>
|
||||||
|
|
||||||
|
static const char *get_exe()
|
||||||
|
{
|
||||||
|
static char buf[256] = {0};
|
||||||
|
ssize_t ret = readlink("/proc/self/exe", buf, sizeof(buf)-1);
|
||||||
|
if (ret > 0)
|
||||||
|
return buf;
|
||||||
|
ret = readlink("/proc/curproc/file", buf, sizeof(buf)-1);
|
||||||
|
if (ret > 0)
|
||||||
|
return buf;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bt_error_callback(void *data, const char *msg, int errnum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bt_full_callback(void *data, uintptr_t pc,
|
||||||
|
const char *filename, int lineno,
|
||||||
|
const char *function)
|
||||||
|
{
|
||||||
|
struct backtrace *bt = (struct backtrace *)data;
|
||||||
|
bt_add_frame(bt, function);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
static struct backtrace_state *state = NULL;
|
||||||
|
|
||||||
|
if (!state) {
|
||||||
|
const char *exe = get_exe();
|
||||||
|
if (exe)
|
||||||
|
state = backtrace_create_state(exe, 1, bt_error_callback, NULL);
|
||||||
|
}
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
if (state) {
|
||||||
|
backtrace_full(state, skip + 1, bt_full_callback, bt_error_callback, bt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif HAS_LIBUNWIND
|
||||||
|
|
||||||
|
#define UNW_LOCAL_ONLY
|
||||||
|
#include <libunwind.h>
|
||||||
|
|
||||||
|
struct bt_mapping {
|
||||||
|
unw_word_t ip;
|
||||||
|
char fname[BT_FRAME_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BT_BUCKET_SIZE 3
|
||||||
|
struct bt_bucket {
|
||||||
|
struct bt_mapping mappings[BT_BUCKET_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bt_cache {
|
||||||
|
struct bt_bucket *buckets;
|
||||||
|
size_t count;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned oat_hash(void *key, int len)
|
||||||
|
{
|
||||||
|
unsigned char *p = key;
|
||||||
|
unsigned h = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
h += p[i];
|
||||||
|
h += (h << 10);
|
||||||
|
h ^= (h >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
h += (h << 3);
|
||||||
|
h ^= (h >> 11);
|
||||||
|
h += (h << 15);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_bucket *cached_proc_name_bucket(struct bt_cache *cache, unw_word_t ip)
|
||||||
|
{
|
||||||
|
if (!cache->size)
|
||||||
|
return NULL;
|
||||||
|
unsigned h = oat_hash(&ip, sizeof(ip));
|
||||||
|
return &cache->buckets[h % cache->size];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bt_cache_init(struct bt_cache *cache)
|
||||||
|
{
|
||||||
|
if (!cache->size) {
|
||||||
|
cache->size = 119;
|
||||||
|
cache->buckets = calloc(cache->size, sizeof(*cache->buckets));
|
||||||
|
if (!cache->buckets)
|
||||||
|
cache->size = 0;
|
||||||
|
cache->count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cached_proc_name_store(struct bt_cache *cache, unw_word_t ip, const char *fname);
|
||||||
|
|
||||||
|
static void bt_cache_rebalance(struct bt_cache *cache)
|
||||||
|
{
|
||||||
|
struct bt_cache bigger = {};
|
||||||
|
bigger.size = cache->size * 2 + 1337;
|
||||||
|
bigger.buckets = calloc(bigger.size, sizeof(*bigger.buckets));
|
||||||
|
bigger.count = 0;
|
||||||
|
for (size_t b = 0; b < cache->size; b++) {
|
||||||
|
for (size_t i = 0; i < BT_BUCKET_SIZE; i++) {
|
||||||
|
struct bt_mapping *map = &cache->buckets[b].mappings[i];
|
||||||
|
if (map->ip) {
|
||||||
|
cached_proc_name_store(&bigger, map->ip, map->fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(cache->buckets);
|
||||||
|
*cache = bigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cached_proc_name_store(struct bt_cache *cache, unw_word_t ip, const char *fname)
|
||||||
|
{
|
||||||
|
bt_cache_init(cache);
|
||||||
|
if (!cache->size)
|
||||||
|
return;
|
||||||
|
struct bt_bucket *bucket = cached_proc_name_bucket(cache, ip);
|
||||||
|
bool stored = false;
|
||||||
|
for (size_t i = 0; i < BT_BUCKET_SIZE; i++) {
|
||||||
|
if (bucket->mappings[i].ip == ip)
|
||||||
|
return;
|
||||||
|
if (bucket->mappings[i].ip != 0)
|
||||||
|
continue;
|
||||||
|
bucket->mappings[i].ip = ip;
|
||||||
|
strncpy(bucket->mappings[i].fname, fname, sizeof(bucket->mappings[i].fname));
|
||||||
|
cache->count++;
|
||||||
|
stored = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cache->count > cache->size / 4 || !stored) {
|
||||||
|
bt_cache_rebalance(cache);
|
||||||
|
fprintf(stderr, "tint2: proc_name cache: ratio %f, count %lu, size %lu, (%lu bytes)\n",
|
||||||
|
cache->count / (double)cache->size,
|
||||||
|
cache->count, (size_t)cache->size, cache->size * sizeof(*cache->buckets));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cached_proc_name_get(struct bt_cache *cache, unw_word_t ip)
|
||||||
|
{
|
||||||
|
struct bt_bucket *bucket = cached_proc_name_bucket(cache, ip);
|
||||||
|
if (!bucket)
|
||||||
|
return NULL;
|
||||||
|
for (size_t i = 0; i < BT_BUCKET_SIZE; i++) {
|
||||||
|
if (bucket->mappings[i].ip != ip)
|
||||||
|
continue;
|
||||||
|
return bucket->mappings[i].fname;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
static struct bt_cache bt_cache = {};
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
|
||||||
|
unw_cursor_t cursor;
|
||||||
|
unw_context_t context;
|
||||||
|
unw_getcontext(&context);
|
||||||
|
unw_init_local(&cursor, &context);
|
||||||
|
|
||||||
|
while (unw_step(&cursor) > 0) {
|
||||||
|
if (skip > 0) {
|
||||||
|
skip--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unw_word_t offset;
|
||||||
|
char fname[BT_FRAME_SIZE] = {0};
|
||||||
|
unw_word_t ip;
|
||||||
|
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||||
|
const char *fname_cached = cached_proc_name_get(&bt_cache, ip);
|
||||||
|
if (fname_cached) {
|
||||||
|
bt_add_frame(bt, fname_cached);
|
||||||
|
} else {
|
||||||
|
unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
|
||||||
|
cached_proc_name_store(&bt_cache, ip, fname);
|
||||||
|
bt_add_frame(bt, fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif HAS_EXECINFO
|
||||||
|
|
||||||
|
#include <execinfo.h>
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
|
||||||
|
void *array[BT_MAX_FRAMES];
|
||||||
|
int size = backtrace(array, BT_MAX_FRAMES);
|
||||||
|
char **strings = backtrace_symbols(array, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
bt_add_frame(bt, strings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef BT_H
|
||||||
|
#define BT_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define BT_FRAME_SIZE 64
|
||||||
|
#define BT_MAX_FRAMES 64
|
||||||
|
|
||||||
|
struct backtrace_frame {
|
||||||
|
char name[BT_FRAME_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct backtrace {
|
||||||
|
struct backtrace_frame frames[BT_MAX_FRAMES];
|
||||||
|
size_t frame_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip);
|
||||||
|
|
||||||
|
#endif // BT_H
|
||||||
@@ -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
|
||||||
+274
-80
@@ -31,7 +31,7 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib/gstdio.h>
|
#include <glib/gstdio.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "../server.h"
|
#include "server.h"
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@@ -40,23 +40,18 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#if !defined(__OpenBSD__)
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_RSVG
|
#ifdef HAVE_RSVG
|
||||||
#include <librsvg/rsvg.h>
|
#include <librsvg/rsvg.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_LIBUNWIND
|
|
||||||
#define UNW_LOCAL_ONLY
|
|
||||||
#include <libunwind.h>
|
|
||||||
#else
|
|
||||||
#ifdef ENABLE_EXECINFO
|
|
||||||
#include <execinfo.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../panel.h"
|
#include "../panel.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include "bt.h"
|
||||||
|
|
||||||
void write_string(int fd, const char *s)
|
void write_string(int fd, const char *s)
|
||||||
{
|
{
|
||||||
@@ -80,39 +75,13 @@ void log_string(int fd, const char *s)
|
|||||||
|
|
||||||
void dump_backtrace(int log_fd)
|
void dump_backtrace(int log_fd)
|
||||||
{
|
{
|
||||||
#ifndef DISABLE_BACKTRACE
|
struct backtrace bt;
|
||||||
|
get_backtrace(&bt, 1);
|
||||||
log_string(log_fd, "\n" YELLOW "Backtrace:" RESET "\n");
|
log_string(log_fd, "\n" YELLOW "Backtrace:" RESET "\n");
|
||||||
|
for (size_t i = 0; i < bt.frame_count; i++) {
|
||||||
#ifdef ENABLE_LIBUNWIND
|
log_string(log_fd, bt.frames[i].name);
|
||||||
unw_cursor_t cursor;
|
|
||||||
unw_context_t context;
|
|
||||||
unw_getcontext(&context);
|
|
||||||
unw_init_local(&cursor, &context);
|
|
||||||
|
|
||||||
while (unw_step(&cursor) > 0) {
|
|
||||||
unw_word_t offset;
|
|
||||||
char fname[128];
|
|
||||||
fname[0] = '\0';
|
|
||||||
(void)unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
|
|
||||||
log_string(log_fd, fname);
|
|
||||||
log_string(log_fd, "\n");
|
log_string(log_fd, "\n");
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#ifdef ENABLE_EXECINFO
|
|
||||||
#define MAX_TRACE_SIZE 128
|
|
||||||
void *array[MAX_TRACE_SIZE];
|
|
||||||
size_t size = backtrace(array, MAX_TRACE_SIZE);
|
|
||||||
char **strings = backtrace_symbols(array, size);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
log_string(log_fd, strings[i]);
|
|
||||||
log_string(log_fd, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(strings);
|
|
||||||
#endif // ENABLE_EXECINFO
|
|
||||||
#endif // ENABLE_LIBUNWIND
|
|
||||||
#endif // DISABLE_BACKTRACE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep() returns early when signals arrive. This function does not.
|
// sleep() returns early when signals arrive. This function does not.
|
||||||
@@ -188,7 +157,7 @@ const char *signal_name(int sig)
|
|||||||
return "SIGSYS: Bad system call.";
|
return "SIGSYS: Bad system call.";
|
||||||
}
|
}
|
||||||
static char s[64];
|
static char s[64];
|
||||||
sprintf(s, "SIG=%d: Unknown", sig);
|
snprintf(s, sizeof(s), "SIG=%d: Unknown", sig);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +232,7 @@ extern char *config_path;
|
|||||||
int setenvd(const char *name, const int value)
|
int setenvd(const char *name, const int value)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
sprintf(buf, "%d", value);
|
snprintf(buf, sizeof(buf), "%d", value);
|
||||||
return setenv(name, buf, 1);
|
return setenv(name, buf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,19 +362,28 @@ pid_t tint_exec(const char *command,
|
|||||||
// Allow children to exist after parent destruction
|
// Allow children to exist after parent destruction
|
||||||
setsid();
|
setsid();
|
||||||
// Run the command
|
// Run the command
|
||||||
if (dir)
|
if (dir) {
|
||||||
chdir(dir);
|
int ret = chdir(dir);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "tint2: failed to chdir to %s\n", dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
close_all_fds();
|
close_all_fds();
|
||||||
|
reset_signals();
|
||||||
if (terminal) {
|
if (terminal) {
|
||||||
|
#if !defined(__OpenBSD__)
|
||||||
fprintf(stderr, "tint2: executing in x-terminal-emulator: %s\n", command);
|
fprintf(stderr, "tint2: executing in x-terminal-emulator: %s\n", command);
|
||||||
wordexp_t words;
|
wordexp_t words;
|
||||||
words.we_offs = 2;
|
words.we_offs = 2;
|
||||||
if (wordexp(command, &words, WRDE_DOOFFS | WRDE_SHOWERR) == 0) {
|
if (wordexp(command, &words, WRDE_DOOFFS | WRDE_SHOWERR) == 0) {
|
||||||
words.we_wordv[0] = (char*)"x-terminal-emulator";
|
words.we_wordv[0] = (char *)"x-terminal-emulator";
|
||||||
words.we_wordv[1] = (char*)"-e";
|
words.we_wordv[1] = (char *)"-e";
|
||||||
execvp("x-terminal-emulator", words.we_wordv);
|
execvp("x-terminal-emulator", words.we_wordv);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "tint2: could not execute command in x-terminal-emulator: %s, executting in shell\n", command);
|
#endif
|
||||||
|
fprintf(stderr,
|
||||||
|
"tint2: could not execute command in x-terminal-emulator: %s, executting in shell\n",
|
||||||
|
command);
|
||||||
}
|
}
|
||||||
execlp("sh", "sh", "-c", command, NULL);
|
execlp("sh", "sh", "-c", command, NULL);
|
||||||
fprintf(stderr, "tint2: Failed to execute %s\n", command);
|
fprintf(stderr, "tint2: Failed to execute %s\n", command);
|
||||||
@@ -453,9 +431,10 @@ char *expand_tilde(const char *s)
|
|||||||
{
|
{
|
||||||
const gchar *home = g_get_home_dir();
|
const gchar *home = g_get_home_dir();
|
||||||
if (home && (strcmp(s, "~") == 0 || strstr(s, "~/") == s)) {
|
if (home && (strcmp(s, "~") == 0 || strstr(s, "~/") == s)) {
|
||||||
char *result = calloc(strlen(home) + strlen(s), 1);
|
size_t buf_size = strlen(home) + strlen(s);
|
||||||
strcat(result, home);
|
char *result = calloc(buf_size, 1);
|
||||||
strcat(result, s + 1);
|
strlcat(result, home, buf_size);
|
||||||
|
strlcat(result, s + 1, buf_size);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return strdup(s);
|
return strdup(s);
|
||||||
@@ -468,14 +447,16 @@ char *contract_tilde(const char *s)
|
|||||||
if (!home)
|
if (!home)
|
||||||
return strdup(s);
|
return strdup(s);
|
||||||
|
|
||||||
char *home_slash = calloc(strlen(home) + 2, 1);
|
size_t buf_size = strlen(home) + 2;
|
||||||
strcat(home_slash, home);
|
char *home_slash = calloc(buf_size, 1);
|
||||||
strcat(home_slash, "/");
|
strlcat(home_slash, home, buf_size);
|
||||||
|
strlcat(home_slash, "/", buf_size);
|
||||||
|
|
||||||
if ((strcmp(s, home) == 0 || strstr(s, home_slash) == s)) {
|
if ((strcmp(s, home) == 0 || strstr(s, home_slash) == s)) {
|
||||||
char *result = calloc(strlen(s) - strlen(home) + 2, 1);
|
size_t buf_size2 = strlen(s) - strlen(home) + 2;
|
||||||
strcat(result, "~");
|
char *result = calloc(buf_size2, 1);
|
||||||
strcat(result, s + strlen(home));
|
strlcat(result, "~", buf_size2);
|
||||||
|
strlcat(result, s + strlen(home), buf_size2);
|
||||||
free(home_slash);
|
free(home_slash);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@@ -747,9 +728,37 @@ void render_image(Drawable d, int x, int y)
|
|||||||
XFreePixmap(server.display, pixmap);
|
XFreePixmap(server.display, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow)
|
gboolean is_color_attribute(PangoAttribute *attr, gpointer user_data)
|
||||||
|
{
|
||||||
|
return attr->klass->type == PANGO_ATTR_FOREGROUND ||
|
||||||
|
attr->klass->type == PANGO_ATTR_BACKGROUND ||
|
||||||
|
attr->klass->type == PANGO_ATTR_UNDERLINE_COLOR ||
|
||||||
|
attr->klass->type == PANGO_ATTR_STRIKETHROUGH_COLOR ||
|
||||||
|
attr->klass->type == PANGO_ATTR_FOREGROUND_ALPHA ||
|
||||||
|
attr->klass->type == PANGO_ATTR_BACKGROUND_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup)
|
||||||
|
{
|
||||||
|
PangoAttrList *attrs = NULL;
|
||||||
|
char *text = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
if (!pango_parse_markup(markup, -1, 0, &attrs, &text, NULL, &error)) {
|
||||||
|
g_error_free(error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pango_layout_set_text(layout, text, -1);
|
||||||
|
g_free(text);
|
||||||
|
|
||||||
|
pango_attr_list_filter(attrs, is_color_attribute, NULL);
|
||||||
|
pango_layout_set_attributes(layout, attrs);
|
||||||
|
pango_attr_list_unref(attrs);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_shadow(cairo_t *c, int posx, int posy, PangoLayout *shadow_layout)
|
||||||
{
|
{
|
||||||
if (font_shadow) {
|
|
||||||
const int shadow_size = 3;
|
const int shadow_size = 3;
|
||||||
const double shadow_edge_alpha = 0.0;
|
const double shadow_edge_alpha = 0.0;
|
||||||
int i, j;
|
int i, j;
|
||||||
@@ -762,12 +771,17 @@ void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color
|
|||||||
1.0 -
|
1.0 -
|
||||||
(1.0 - shadow_edge_alpha) *
|
(1.0 - shadow_edge_alpha) *
|
||||||
sqrt((i * i + j * j) / (double)(shadow_size * shadow_size)));
|
sqrt((i * i + j * j) / (double)(shadow_size * shadow_size)));
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, shadow_layout);
|
||||||
cairo_move_to(c, posx + i, posy + j);
|
cairo_move_to(c, posx + i, posy + j);
|
||||||
pango_cairo_show_layout(c, layout);
|
pango_cairo_show_layout(c, shadow_layout);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, PangoLayout *shadow_layout)
|
||||||
|
{
|
||||||
|
if (shadow_layout)
|
||||||
|
draw_shadow(c, posx, posy, shadow_layout);
|
||||||
cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha);
|
cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha);
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
cairo_move_to(c, posx, posy);
|
cairo_move_to(c, posx, posy);
|
||||||
@@ -777,15 +791,15 @@ void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color
|
|||||||
Imlib_Image load_image(const char *path, int cached)
|
Imlib_Image load_image(const char *path, int cached)
|
||||||
{
|
{
|
||||||
Imlib_Image image;
|
Imlib_Image image;
|
||||||
|
static unsigned long counter = 0;
|
||||||
|
if (debug_icons)
|
||||||
|
fprintf(stderr, "tint2: loading icon %s\n", path);
|
||||||
#ifdef HAVE_RSVG
|
#ifdef HAVE_RSVG
|
||||||
if (cached) {
|
image = imlib_load_image(path);
|
||||||
image = imlib_load_image_immediately(path);
|
|
||||||
} else {
|
|
||||||
image = imlib_load_image_immediately_without_cache(path);
|
|
||||||
}
|
|
||||||
if (!image && g_str_has_suffix(path, ".svg")) {
|
if (!image && g_str_has_suffix(path, ".svg")) {
|
||||||
char tmp_filename[128];
|
char tmp_filename[128];
|
||||||
sprintf(tmp_filename, "/tmp/tint2-%d.png", (int)getpid());
|
snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d-%lu.png", (int)getpid(), counter);
|
||||||
|
counter++;
|
||||||
int fd = open(tmp_filename, O_CREAT | O_EXCL, 0600);
|
int fd = open(tmp_filename, O_CREAT | O_EXCL, 0600);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
// We fork here because librsvg allocates memory like crazy
|
// We fork here because librsvg allocates memory like crazy
|
||||||
@@ -802,24 +816,22 @@ Imlib_Image load_image(const char *path, int cached)
|
|||||||
GdkPixbuf *pixbuf = rsvg_handle_get_pixbuf(svg);
|
GdkPixbuf *pixbuf = rsvg_handle_get_pixbuf(svg);
|
||||||
gdk_pixbuf_save(pixbuf, tmp_filename, "png", NULL, NULL);
|
gdk_pixbuf_save(pixbuf, tmp_filename, "png", NULL, NULL);
|
||||||
}
|
}
|
||||||
exit(0);
|
_exit(0);
|
||||||
} else {
|
} else {
|
||||||
// Parent
|
// Parent
|
||||||
close(fd);
|
close(fd);
|
||||||
waitpid(pid, 0, 0);
|
waitpid(pid, 0, 0);
|
||||||
image = imlib_load_image_immediately_without_cache(tmp_filename);
|
image = imlib_load_image_immediately(tmp_filename);
|
||||||
unlink(tmp_filename);
|
unlink(tmp_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (cached) {
|
image = imlib_load_image(path);
|
||||||
image = imlib_load_image_immediately(path);
|
|
||||||
} else {
|
|
||||||
image = imlib_load_image_immediately_without_cache(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
imlib_context_set_image(image);
|
||||||
|
imlib_image_set_changes_on_disk();
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -913,8 +925,7 @@ void clear_pixmap(Pixmap p, int x, int y, int w, int h)
|
|||||||
XRenderFreePicture(server.display, pict);
|
XRenderFreePicture(server.display, pict);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_text_size2(const PangoFontDescription *font,
|
void get_text_size(const PangoFontDescription *font,
|
||||||
int *height_ink,
|
|
||||||
int *height,
|
int *height,
|
||||||
int *width,
|
int *width,
|
||||||
int available_height,
|
int available_height,
|
||||||
@@ -923,21 +934,26 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
int text_len,
|
int text_len,
|
||||||
PangoWrapMode wrap,
|
PangoWrapMode wrap,
|
||||||
PangoEllipsizeMode ellipsis,
|
PangoEllipsizeMode ellipsis,
|
||||||
gboolean markup)
|
PangoAlignment alignment,
|
||||||
|
gboolean markup,
|
||||||
|
double scale)
|
||||||
{
|
{
|
||||||
PangoRectangle rect_ink, rect;
|
PangoRectangle rect_ink, rect;
|
||||||
|
|
||||||
available_width = MAX(0, available_width);
|
available_width = MAX(0, available_width);
|
||||||
available_height = MAX(0, available_height);
|
available_height = MAX(0, available_height);
|
||||||
Pixmap pmap = XCreatePixmap(server.display, server.root_win, available_height, available_width, server.depth);
|
|
||||||
|
|
||||||
|
Pixmap pmap = XCreatePixmap(server.display, server.root_win, available_height, available_width, server.depth);
|
||||||
cairo_surface_t *cs =
|
cairo_surface_t *cs =
|
||||||
cairo_xlib_surface_create(server.display, pmap, server.visual, available_height, available_width);
|
cairo_xlib_surface_create(server.display, pmap, server.visual, available_height, available_width);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
|
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_width(layout, available_width * PANGO_SCALE);
|
pango_layout_set_width(layout, available_width * PANGO_SCALE);
|
||||||
pango_layout_set_height(layout, available_height * PANGO_SCALE);
|
pango_layout_set_height(layout, available_height * PANGO_SCALE);
|
||||||
|
pango_layout_set_alignment(layout, alignment);
|
||||||
pango_layout_set_wrap(layout, wrap);
|
pango_layout_set_wrap(layout, wrap);
|
||||||
pango_layout_set_ellipsize(layout, ellipsis);
|
pango_layout_set_ellipsize(layout, ellipsis);
|
||||||
pango_layout_set_font_description(layout, font);
|
pango_layout_set_font_description(layout, font);
|
||||||
@@ -948,17 +964,65 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
pango_layout_set_markup(layout, text, text_len);
|
pango_layout_set_markup(layout, text, text_len);
|
||||||
|
|
||||||
pango_layout_get_pixel_extents(layout, &rect_ink, &rect);
|
pango_layout_get_pixel_extents(layout, &rect_ink, &rect);
|
||||||
*height_ink = rect_ink.height;
|
|
||||||
*height = rect.height;
|
*height = rect.height;
|
||||||
*width = rect.width;
|
*width = rect.width;
|
||||||
|
|
||||||
// fprintf(stderr, "tint2: dimension : %d - %d\n", rect_ink.height, rect.height);
|
// fprintf(stderr, "tint2: dimension : %d - %d\n", rect_ink.height, rect.height);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
XFreePixmap(server.display, pmap);
|
XFreePixmap(server.display, pmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_text_size2(const PangoFontDescription *font,
|
||||||
|
int *height,
|
||||||
|
int *width,
|
||||||
|
int available_height,
|
||||||
|
int available_width,
|
||||||
|
const char *text,
|
||||||
|
int text_len,
|
||||||
|
PangoWrapMode wrap,
|
||||||
|
PangoEllipsizeMode ellipsis,
|
||||||
|
PangoAlignment alignment,
|
||||||
|
gboolean markup,
|
||||||
|
double scale)
|
||||||
|
{
|
||||||
|
get_text_size(font, height, width, available_height, available_width, text, text_len, wrap, ellipsis, alignment, markup, scale);
|
||||||
|
|
||||||
|
// We do multiple passes, because pango sucks
|
||||||
|
int actual_height, actual_width, overflow = 0;
|
||||||
|
while (true) {
|
||||||
|
get_text_size(font, &actual_height, &actual_width, *height, *width, text, text_len, wrap, ellipsis, alignment, markup, scale);
|
||||||
|
if (actual_height <= *height)
|
||||||
|
break;
|
||||||
|
if (*width >= available_width)
|
||||||
|
break;
|
||||||
|
overflow = 1;
|
||||||
|
fprintf(stderr, "tint2: text overflows, recomputing: available %dx%d, computed %dx%d, actual %dx%d: %s\n",
|
||||||
|
available_width,
|
||||||
|
available_height,
|
||||||
|
*width,
|
||||||
|
*height,
|
||||||
|
actual_width,
|
||||||
|
actual_height,
|
||||||
|
text);
|
||||||
|
(*width)++;
|
||||||
|
}
|
||||||
|
if (overflow) {
|
||||||
|
*height = actual_height;
|
||||||
|
fprintf(stderr, "tint2: text final size computed as: available %dx%d, computed %dx%d, actual %dx%d: %s\n",
|
||||||
|
available_width,
|
||||||
|
available_height,
|
||||||
|
*width,
|
||||||
|
*height,
|
||||||
|
actual_width,
|
||||||
|
actual_height,
|
||||||
|
text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if !GLIB_CHECK_VERSION(2, 34, 0)
|
#if !GLIB_CHECK_VERSION(2, 34, 0)
|
||||||
GList *g_list_copy_deep(GList *list, GCopyFunc func, gpointer user_data)
|
GList *g_list_copy_deep(GList *list, GCopyFunc func, gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -1051,3 +1115,133 @@ GString *tint2_g_string_replace(GString *s, const char *from, const char *to)
|
|||||||
g_string_free(result, TRUE);
|
g_string_free(result, TRUE);
|
||||||
return s;
|
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.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_image_data(const char *file_name, const char *name)
|
||||||
|
{
|
||||||
|
Imlib_Image image = load_image(file_name, false);
|
||||||
|
if (!image) {
|
||||||
|
fprintf(stderr, "tint2: Could not load image from file\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *header_name = g_strdup_printf("%s.h", name);
|
||||||
|
gchar *guard = g_strdup_printf("%s_h", name);
|
||||||
|
FILE *header = fopen(header_name, "wt");
|
||||||
|
fprintf(header,
|
||||||
|
"#ifndef %s\n"
|
||||||
|
"#define %s\n"
|
||||||
|
"\n"
|
||||||
|
"#include <Imlib2.h>\n"
|
||||||
|
"\n"
|
||||||
|
"extern int %s_width;\n"
|
||||||
|
"extern int %s_height;\n"
|
||||||
|
"extern DATA32 %s_data[];\n"
|
||||||
|
"\n"
|
||||||
|
"#endif\n",
|
||||||
|
guard,
|
||||||
|
guard,
|
||||||
|
name,
|
||||||
|
name,
|
||||||
|
name);
|
||||||
|
fclose(header);
|
||||||
|
g_free(guard);
|
||||||
|
g_free(header_name);
|
||||||
|
|
||||||
|
imlib_context_set_image(image);
|
||||||
|
|
||||||
|
gchar *source_name = g_strdup_printf("%s.c", name);
|
||||||
|
FILE *source = fopen(source_name, "wt");
|
||||||
|
fprintf(source,
|
||||||
|
"#include <%s.h>\n"
|
||||||
|
"\n"
|
||||||
|
"int %s_width = %d;\n"
|
||||||
|
"int %s_height = %d;\n"
|
||||||
|
"DATA32 %s_data[] = {",
|
||||||
|
name,
|
||||||
|
name,
|
||||||
|
imlib_image_get_width(),
|
||||||
|
name,
|
||||||
|
imlib_image_get_height(),
|
||||||
|
name);
|
||||||
|
|
||||||
|
size_t size = (size_t)imlib_image_get_width() * (size_t)imlib_image_get_height();
|
||||||
|
DATA32 *data = imlib_image_get_data_for_reading_only();
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
fprintf(source, "%s%u", i == 0 ? "" : ", ", data[i]);
|
||||||
|
}
|
||||||
|
fprintf(source, "};\n");
|
||||||
|
fclose(source);
|
||||||
|
g_free(source_name);
|
||||||
|
|
||||||
|
imlib_free_image();
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_cairo_surface_to_xpixmap(cairo_surface_t *cs, Pixmap pix)
|
||||||
|
{
|
||||||
|
int w = cairo_image_surface_get_width(cs);
|
||||||
|
int h = cairo_image_surface_get_height(cs);
|
||||||
|
cairo_surface_t *cs_xlib = cairo_xlib_surface_create(server.display, pix, server.visual, w, h);
|
||||||
|
cairo_xlib_surface_set_size(cs_xlib, w, h);
|
||||||
|
cairo_t *c_xlib = cairo_create(cs_xlib);
|
||||||
|
|
||||||
|
cairo_set_source_surface(c_xlib, cs, 0, 0);
|
||||||
|
cairo_paint(c_xlib);
|
||||||
|
cairo_surface_flush(cs_xlib);
|
||||||
|
|
||||||
|
cairo_destroy(c_xlib);
|
||||||
|
cairo_surface_destroy(cs_xlib);
|
||||||
|
}
|
||||||
|
|||||||
+15
-9
@@ -7,17 +7,14 @@
|
|||||||
#define COMMON_H
|
#define COMMON_H
|
||||||
|
|
||||||
#define WM_CLASS_TINT "panel"
|
#define WM_CLASS_TINT "panel"
|
||||||
|
#define TINT2_PANGO_SLACK 0
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
|
#include "colors.h"
|
||||||
#define GREEN "\033[1;32m"
|
#include "strlcat.h"
|
||||||
#define YELLOW "\033[1;33m"
|
|
||||||
#define RED "\033[1;31m"
|
|
||||||
#define BLUE "\033[1;34m"
|
|
||||||
#define RESET "\033[0m"
|
|
||||||
|
|
||||||
#define MAX3(a, b, c) MAX(MAX(a, b), c)
|
#define MAX3(a, b, c) MAX(MAX(a, b), c)
|
||||||
#define MIN3(a, b, c) MIN(MIN(a, b), c)
|
#define MIN3(a, b, c) MIN(MIN(a, b), c)
|
||||||
@@ -109,6 +106,7 @@ Imlib_Image load_image(const char *path, int cached);
|
|||||||
// * 1 = white
|
// * 1 = white
|
||||||
void adjust_asb(DATA32 *data, int w, int h, float alpha_adjust, float satur_adjust, float bright_adjust);
|
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);
|
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);
|
void create_heuristic_mask(DATA32 *data, int w, int h);
|
||||||
|
|
||||||
@@ -116,7 +114,6 @@ void create_heuristic_mask(DATA32 *data, int w, int h);
|
|||||||
void render_image(Drawable d, int x, int y);
|
void render_image(Drawable d, int x, int y);
|
||||||
|
|
||||||
void get_text_size2(const PangoFontDescription *font,
|
void get_text_size2(const PangoFontDescription *font,
|
||||||
int *height_ink,
|
|
||||||
int *height,
|
int *height,
|
||||||
int *width,
|
int *width,
|
||||||
int available_height,
|
int available_height,
|
||||||
@@ -125,9 +122,12 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
int text_len,
|
int text_len,
|
||||||
PangoWrapMode wrap,
|
PangoWrapMode wrap,
|
||||||
PangoEllipsizeMode ellipsis,
|
PangoEllipsizeMode ellipsis,
|
||||||
gboolean markup);
|
PangoAlignment alignment,
|
||||||
|
gboolean markup,
|
||||||
|
double scale);
|
||||||
|
|
||||||
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
|
gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup);
|
||||||
|
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, PangoLayout *shadow_layout);
|
||||||
|
|
||||||
// Draws a rounded rectangle
|
// Draws a rounded rectangle
|
||||||
void draw_rect(cairo_t *c, double x, double y, double w, double h, double r);
|
void draw_rect(cairo_t *c, double x, double y, double w, double h, double r);
|
||||||
@@ -150,6 +150,12 @@ gint cmp_ptr(gconstpointer a, gconstpointer b);
|
|||||||
|
|
||||||
GString *tint2_g_string_replace(GString *s, const char *from, const char *to);
|
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);
|
||||||
|
|
||||||
|
void dump_image_data(const char *file_name, const char *name);
|
||||||
|
|
||||||
|
void draw_cairo_surface_to_xpixmap(cairo_surface_t *cs, Pixmap pix);
|
||||||
|
|
||||||
#define free_and_null(p) \
|
#define free_and_null(p) \
|
||||||
{ \
|
{ \
|
||||||
free(p); \
|
free(p); \
|
||||||
|
|||||||
+1
-2
@@ -67,11 +67,10 @@ void cleanup_gradient(GradientClass *g);
|
|||||||
// Gradient instances associated to Areas
|
// Gradient instances associated to Areas
|
||||||
|
|
||||||
struct Area;
|
struct Area;
|
||||||
typedef struct Area Area;
|
|
||||||
|
|
||||||
typedef struct GradientInstance {
|
typedef struct GradientInstance {
|
||||||
GradientClass *gradient_class;
|
GradientClass *gradient_class;
|
||||||
Area *area;
|
struct Area *area;
|
||||||
cairo_pattern_t *pattern;
|
cairo_pattern_t *pattern;
|
||||||
} GradientInstance;
|
} GradientInstance;
|
||||||
|
|
||||||
|
|||||||
+331
@@ -0,0 +1,331 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <endian.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "bt.h"
|
||||||
|
#include "bool.h"
|
||||||
|
|
||||||
|
#define UNUSED(x) ((void)x)
|
||||||
|
|
||||||
|
void ERR(const char *s)
|
||||||
|
{
|
||||||
|
if (!s) {
|
||||||
|
ERR("(null)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ssize_t ret = write(STDERR_FILENO, s, strlen(s));
|
||||||
|
UNUSED(ret);
|
||||||
|
ret = fsync(STDERR_FILENO);
|
||||||
|
UNUSED(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void utoa(unsigned long n, char *s)
|
||||||
|
{
|
||||||
|
if (n == 0) {
|
||||||
|
*s++ = '0';
|
||||||
|
*s = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buffer[128] = {0};
|
||||||
|
char *digit;
|
||||||
|
for (digit = buffer; n; digit++, n/=10) {
|
||||||
|
*digit = '0' + (n % 10);
|
||||||
|
}
|
||||||
|
digit--;
|
||||||
|
while (digit >= buffer) {
|
||||||
|
*s++ = *digit--;
|
||||||
|
}
|
||||||
|
*s = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long uabs(long n)
|
||||||
|
{
|
||||||
|
if (n == LONG_MIN)
|
||||||
|
return ((unsigned long)LONG_MAX) + 1;
|
||||||
|
return (unsigned long)labs(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void itoa(long n, char *s)
|
||||||
|
{
|
||||||
|
if (n < 0) {
|
||||||
|
*s++ = '-';
|
||||||
|
}
|
||||||
|
utoa(uabs(n), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
static void crash(char *file, int line, char *msg)
|
||||||
|
{
|
||||||
|
ERR(file);
|
||||||
|
ERR(":");
|
||||||
|
char buf[256];
|
||||||
|
itoa(line, buf);
|
||||||
|
ERR(buf);
|
||||||
|
ERR(" ");
|
||||||
|
ERR(msg);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_OK(call) if (0 != (call)) crash(__FILE__, __LINE__, #call)
|
||||||
|
#define ASSERT_FD(fd) if ((fd) == -1) crash(__FILE__, __LINE__, "bad file descriptor")
|
||||||
|
#define ASSERT_PID(pid) if ((pid) == -1) crash(__FILE__, __LINE__, "bad PID")
|
||||||
|
#define ASSERT(b) if (!(b)) crash(__FILE__, __LINE__, "assert failed")
|
||||||
|
|
||||||
|
void *return_null(void *x, void *y)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_func_or_crash(void **result, const char *name)
|
||||||
|
{
|
||||||
|
static int inside_loader = 0;
|
||||||
|
if (inside_loader) {
|
||||||
|
*result = (void*)return_null;
|
||||||
|
return;
|
||||||
|
} else if (*result == (void*)return_null) {
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
if (*result)
|
||||||
|
return;
|
||||||
|
dlerror();
|
||||||
|
inside_loader++;
|
||||||
|
*result = dlsym(RTLD_NEXT, name);
|
||||||
|
inside_loader--;
|
||||||
|
char *err = dlerror();
|
||||||
|
if (err) {
|
||||||
|
ERR("Failed to load ");
|
||||||
|
ERR(name);
|
||||||
|
ERR(" error: ");
|
||||||
|
ERR(err);
|
||||||
|
ERR("\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd = -1;
|
||||||
|
static u_int64_t tstart = 0;
|
||||||
|
static bool stop_alloc_log = false;
|
||||||
|
|
||||||
|
static void write_char(char c)
|
||||||
|
{
|
||||||
|
static char buffer[4096] = {0};
|
||||||
|
static size_t count = 0;
|
||||||
|
if (c) {
|
||||||
|
buffer[count++] = c;
|
||||||
|
}
|
||||||
|
if (!count)
|
||||||
|
return;
|
||||||
|
if (c == '\n' || c == 0 || count >= sizeof(buffer)) {
|
||||||
|
ssize_t ret = write(fd, buffer, count);
|
||||||
|
ASSERT(ret > 0);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_string(const char *s)
|
||||||
|
{
|
||||||
|
for (; *s; s++)
|
||||||
|
write_char(*s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_word(const char *s)
|
||||||
|
{
|
||||||
|
write_string(s);
|
||||||
|
write_string(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static char hex(u_int8_t value)
|
||||||
|
{
|
||||||
|
if (value < 10)
|
||||||
|
return '0' + (char)value;
|
||||||
|
return 'a' + (char)(value - 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_hex(u_int64_t v)
|
||||||
|
{
|
||||||
|
write_string("0x");
|
||||||
|
if (!v) {
|
||||||
|
write_string("0 ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
v = htobe64(v);
|
||||||
|
int leading_zero = 1;
|
||||||
|
while (v) {
|
||||||
|
u_int8_t byte = v & 0xff;
|
||||||
|
if (byte)
|
||||||
|
leading_zero = 0;
|
||||||
|
if (!leading_zero) {
|
||||||
|
write_char(hex(byte >> 4));
|
||||||
|
write_char(hex(byte & 0xf));
|
||||||
|
}
|
||||||
|
v = v >> 8;
|
||||||
|
}
|
||||||
|
write_string(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_backtrace(int skip)
|
||||||
|
{
|
||||||
|
struct backtrace bt;
|
||||||
|
get_backtrace(&bt, skip + 1);
|
||||||
|
for (size_t i = 0; i < bt.frame_count; i++) {
|
||||||
|
write_word(bt.frames[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_finish(void);
|
||||||
|
|
||||||
|
static u_int64_t current_time_ms()
|
||||||
|
{
|
||||||
|
struct timespec t = {0, 0};
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||||
|
u_int64_t result = t.tv_sec * 1000 + t.tv_nsec / 1000 / 1000;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_init(u_int64_t t)
|
||||||
|
{
|
||||||
|
if (stop_alloc_log)
|
||||||
|
return;
|
||||||
|
if (fd == -1) {
|
||||||
|
int pfd[2] = {-1, -1};
|
||||||
|
ASSERT_OK(pipe(pfd));
|
||||||
|
pid_t child = fork();
|
||||||
|
ASSERT_PID(child);
|
||||||
|
if (child == 0) {
|
||||||
|
// child
|
||||||
|
close(pfd[1]);
|
||||||
|
ASSERT_FD(dup2(pfd[0], STDIN_FILENO));
|
||||||
|
ASSERT_OK(close(pfd[0]));
|
||||||
|
int out = open("mem.log.gz", O_APPEND | O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0600);
|
||||||
|
ASSERT_FD(out);
|
||||||
|
ASSERT_FD(dup2(out, STDOUT_FILENO));
|
||||||
|
sigset_t mask;
|
||||||
|
sigfillset(&mask);
|
||||||
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
|
ASSERT_OK(execlp("gzip", "gzip", "-c", NULL));
|
||||||
|
_exit(1);
|
||||||
|
} else {
|
||||||
|
// parent
|
||||||
|
close(pfd[0]);
|
||||||
|
fd = pfd[1];
|
||||||
|
}
|
||||||
|
atexit(log_alloc_finish);
|
||||||
|
tstart = t;
|
||||||
|
write_string("# function time_ms result ptr size count backtrace\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_locked(const char *func_name, void *result, void *ptr, size_t size, size_t count)
|
||||||
|
{
|
||||||
|
if (stop_alloc_log)
|
||||||
|
return;
|
||||||
|
u_int64_t t = current_time_ms();
|
||||||
|
if (fd == -1)
|
||||||
|
log_alloc_init(t);
|
||||||
|
if (fd == -1)
|
||||||
|
return;
|
||||||
|
if (func_name) {
|
||||||
|
write_word(func_name);
|
||||||
|
write_hex((u_int64_t)(t - tstart));
|
||||||
|
write_hex((u_int64_t)result);
|
||||||
|
write_hex((u_int64_t)ptr);
|
||||||
|
write_hex((u_int64_t)size);
|
||||||
|
write_hex((u_int64_t)count);
|
||||||
|
write_backtrace(2);
|
||||||
|
write_string("\n");
|
||||||
|
} else {
|
||||||
|
write_string("# done\n");
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
stop_alloc_log = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pid = -1;
|
||||||
|
static void log_alloc(const char *func_name, void *result, void *ptr, size_t size, size_t count)
|
||||||
|
{
|
||||||
|
static pthread_mutex_t mutex_global = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_mutex_t mutex_recursive;
|
||||||
|
static pthread_mutex_t mutex_nonrecursive = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static bool mutexes_initialized = false;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mutex_global);
|
||||||
|
{
|
||||||
|
if (!mutexes_initialized) {
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&mutex_recursive, &attr);
|
||||||
|
mutexes_initialized = true;
|
||||||
|
pid = getpid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex_global);
|
||||||
|
|
||||||
|
// Do not log from forked processes.
|
||||||
|
if (pid != getpid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mutex_recursive);
|
||||||
|
int ret = pthread_mutex_trylock(&mutex_nonrecursive);
|
||||||
|
if (ret == 0) {
|
||||||
|
log_alloc_locked(func_name, result, ptr, size, count);
|
||||||
|
pthread_mutex_unlock(&mutex_nonrecursive);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex_recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_finish()
|
||||||
|
{
|
||||||
|
log_alloc(0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *malloc(size_t size)
|
||||||
|
{
|
||||||
|
static void *(*original)(size_t size) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
void *result = original(size);
|
||||||
|
log_alloc(__FUNCTION__, result, 0, size, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *realloc(void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
static void *(*original)(void *p, size_t size) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
void *result = original(ptr, size);
|
||||||
|
log_alloc(__FUNCTION__, result, ptr, size, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *calloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
static void *(*original)(size_t nmemb, size_t size) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
void *result = original(nmemb, size);
|
||||||
|
log_alloc(__FUNCTION__, result, 0, size, nmemb);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void *ptr)
|
||||||
|
{
|
||||||
|
static void *(*original)(void *p) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
if (!original) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
original(ptr);
|
||||||
|
log_alloc(__FUNCTION__, 0, ptr, 0, 0);
|
||||||
|
}
|
||||||
@@ -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)");
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xrender.h>
|
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -36,8 +36,9 @@
|
|||||||
|
|
||||||
Server server;
|
Server server;
|
||||||
|
|
||||||
void server_catch_error(Display *d, XErrorEvent *ev)
|
int server_catch_error(Display *d, XErrorEvent *ev)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_init_atoms()
|
void server_init_atoms()
|
||||||
@@ -311,6 +312,21 @@ void sort_monitors()
|
|||||||
qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos);
|
qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compute_dpi(XRRCrtcInfo *crtc, XRROutputInfo *output)
|
||||||
|
{
|
||||||
|
double width = output->mm_width;
|
||||||
|
double height = output->mm_height;
|
||||||
|
double x_res = crtc->width;
|
||||||
|
double y_res = crtc->height;
|
||||||
|
|
||||||
|
if (width > 0 && height > 0) {
|
||||||
|
int dpi_x = x_res / width * 25.4;
|
||||||
|
int dpi_y = y_res / height * 25.4;
|
||||||
|
return MAX(dpi_x, dpi_y);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void get_monitors()
|
void get_monitors()
|
||||||
{
|
{
|
||||||
if (XineramaIsActive(server.display)) {
|
if (XineramaIsActive(server.display)) {
|
||||||
@@ -339,12 +355,22 @@ void get_monitors()
|
|||||||
server.monitors[i_monitor].width = crtc_info->width;
|
server.monitors[i_monitor].width = crtc_info->width;
|
||||||
server.monitors[i_monitor].height = crtc_info->height;
|
server.monitors[i_monitor].height = crtc_info->height;
|
||||||
server.monitors[i_monitor].names = calloc((crtc_info->noutput + 1), sizeof(gchar *));
|
server.monitors[i_monitor].names = calloc((crtc_info->noutput + 1), sizeof(gchar *));
|
||||||
|
server.monitors[i_monitor].dpi = 96;
|
||||||
for (int j = 0; j < crtc_info->noutput; ++j) {
|
for (int j = 0; j < crtc_info->noutput; ++j) {
|
||||||
XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]);
|
XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]);
|
||||||
fprintf(stderr, "tint2: xRandr: Linking output %s with crtc %d\n", output_info->name, i);
|
|
||||||
server.monitors[i_monitor].names[j] = g_strdup(output_info->name);
|
server.monitors[i_monitor].names[j] = g_strdup(output_info->name);
|
||||||
XRRFreeOutputInfo(output_info);
|
|
||||||
server.monitors[i_monitor].primary = crtc_info->outputs[j] == primary_output;
|
server.monitors[i_monitor].primary = crtc_info->outputs[j] == primary_output;
|
||||||
|
int dpi = compute_dpi(crtc_info, output_info);
|
||||||
|
if (dpi)
|
||||||
|
server.monitors[i_monitor].dpi = dpi;
|
||||||
|
fprintf(stderr,
|
||||||
|
BLUE "tint2: xRandr: Linking output %s with crtc %d, resolution %dx%d, DPI %d" RESET "\n",
|
||||||
|
output_info->name,
|
||||||
|
i,
|
||||||
|
server.monitors[i_monitor].width,
|
||||||
|
server.monitors[i_monitor].height,
|
||||||
|
server.monitors[i_monitor].dpi);
|
||||||
|
XRRFreeOutputInfo(output_info);
|
||||||
}
|
}
|
||||||
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
||||||
XRRFreeCrtcInfo(crtc_info);
|
XRRFreeCrtcInfo(crtc_info);
|
||||||
@@ -357,6 +383,7 @@ void get_monitors()
|
|||||||
server.monitors[i].width = info[i].width;
|
server.monitors[i].width = info[i].width;
|
||||||
server.monitors[i].height = info[i].height;
|
server.monitors[i].height = info[i].height;
|
||||||
server.monitors[i].names = NULL;
|
server.monitors[i].names = NULL;
|
||||||
|
server.monitors[i].dpi = 96;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,6 +420,7 @@ void get_monitors()
|
|||||||
server.monitors[0].width = DisplayWidth(server.display, server.screen);
|
server.monitors[0].width = DisplayWidth(server.display, server.screen);
|
||||||
server.monitors[0].height = DisplayHeight(server.display, server.screen);
|
server.monitors[0].height = DisplayHeight(server.display, server.screen);
|
||||||
server.monitors[0].names = 0;
|
server.monitors[0].names = 0;
|
||||||
|
server.monitors[0].dpi = 96;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +551,8 @@ int get_current_desktop()
|
|||||||
// fprintf(stderr, "tint2: \n");
|
// fprintf(stderr, "tint2: \n");
|
||||||
// fprintf(stderr, "tint2: Work area size: %d x %d\n", work_area_width, work_area_height);
|
// fprintf(stderr, "tint2: Work area size: %d x %d\n", work_area_width, work_area_height);
|
||||||
// fprintf(stderr, "tint2: Viewport pos: %d x %d\n", viewport_x, viewport_y);
|
// fprintf(stderr, "tint2: Viewport pos: %d x %d\n", viewport_x, viewport_y);
|
||||||
// fprintf(stderr, "tint2: Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x / work_area_width);
|
// fprintf(stderr, "tint2: Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x /
|
||||||
|
//work_area_width);
|
||||||
|
|
||||||
int result = (viewport_y / work_area_height) * ncols + viewport_x / work_area_width;
|
int result = (viewport_y / work_area_height) * ncols + viewport_x / work_area_width;
|
||||||
return MAX(0, MIN(server.num_desktops - 1, result));
|
return MAX(0, MIN(server.num_desktops - 1, result));
|
||||||
@@ -648,9 +677,10 @@ void handle_crash(const char *reason)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void x11_io_error(Display *display)
|
int x11_io_error(Display *display)
|
||||||
{
|
{
|
||||||
handle_crash("X11 I/O error");
|
handle_crash("X11 I/O error");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
@@ -107,6 +107,7 @@ typedef struct Monitor {
|
|||||||
int y;
|
int y;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
int dpi;
|
||||||
gboolean primary;
|
gboolean primary;
|
||||||
gchar **names;
|
gchar **names;
|
||||||
} Monitor;
|
} Monitor;
|
||||||
@@ -147,6 +148,7 @@ typedef struct Server {
|
|||||||
Global_atom atom;
|
Global_atom atom;
|
||||||
int xdamage_event_type;
|
int xdamage_event_type;
|
||||||
int xdamage_event_error_type;
|
int xdamage_event_error_type;
|
||||||
|
gboolean has_shm;
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
SnDisplay *sn_display;
|
SnDisplay *sn_display;
|
||||||
GTree *pids;
|
GTree *pids;
|
||||||
@@ -162,12 +164,12 @@ void send_event32(Window win, Atom at, long data1, long data2, long data3);
|
|||||||
int get_property32(Window win, Atom at, Atom type);
|
int get_property32(Window win, Atom at, Atom type);
|
||||||
void *server_get_property(Window win, Atom at, Atom type, int *num_results);
|
void *server_get_property(Window win, Atom at, Atom type, int *num_results);
|
||||||
Atom server_get_atom(char *atom_name);
|
Atom server_get_atom(char *atom_name);
|
||||||
void server_catch_error(Display *d, XErrorEvent *ev);
|
int server_catch_error(Display *d, XErrorEvent *ev);
|
||||||
void server_init_atoms();
|
void server_init_atoms();
|
||||||
void server_init_visual();
|
void server_init_visual();
|
||||||
void server_init_xdamage();
|
void server_init_xdamage();
|
||||||
|
|
||||||
void x11_io_error(Display *display);
|
int x11_io_error(Display *display);
|
||||||
void handle_crash(const char *reason);
|
void handle_crash(const char *reason);
|
||||||
|
|
||||||
// detect root background
|
// detect root background
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#ifndef TINT2CONF
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -24,12 +26,25 @@ void signal_handler(int sig)
|
|||||||
signal_pending = 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef TINT2CONF
|
||||||
void init_signals()
|
void init_signals()
|
||||||
{
|
{
|
||||||
// Set signal handlers
|
// Set signal handlers
|
||||||
signal_pending = 0;
|
signal_pending = 0;
|
||||||
|
|
||||||
struct sigaction sa_chld = {.sa_handler = SIG_DFL, .sa_flags = SA_NOCLDWAIT | SA_RESTART};
|
reset_signals();
|
||||||
|
|
||||||
|
struct sigaction sa_chld = {.sa_handler = SIG_IGN};
|
||||||
sigaction(SIGCHLD, &sa_chld, 0);
|
sigaction(SIGCHLD, &sa_chld, 0);
|
||||||
|
|
||||||
struct sigaction sa = {.sa_handler = signal_handler, .sa_flags = SA_RESTART};
|
struct sigaction sa = {.sa_handler = signal_handler, .sa_flags = SA_RESTART};
|
||||||
@@ -152,3 +167,4 @@ int get_signal_pending()
|
|||||||
{
|
{
|
||||||
return signal_pending;
|
return signal_pending;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -5,6 +5,7 @@ void init_signals();
|
|||||||
void init_signals_postconfig();
|
void init_signals_postconfig();
|
||||||
void emit_self_restart(const char *reason);
|
void emit_self_restart(const char *reason);
|
||||||
int get_signal_pending();
|
int get_signal_pending();
|
||||||
|
void reset_signals();
|
||||||
|
|
||||||
void handle_sigchld_events();
|
void handle_sigchld_events();
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/* $NetBSD: strlcat.c,v 1.4 2005/05/16 06:55:48 lukem Exp $ */
|
||||||
|
/* from NetBSD: strlcat.c,v 1.16 2003/10/27 00:12:42 lukem Exp */
|
||||||
|
/* from OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
|
||||||
|
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "strlcat.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||||
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
|
* If retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcat(char *dst, const char *src, size_t siz)
|
||||||
|
{
|
||||||
|
char *d = dst;
|
||||||
|
const char *s = src;
|
||||||
|
size_t n = siz;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||||
|
while (n-- != 0 && *d != '\0')
|
||||||
|
d++;
|
||||||
|
dlen = d - dst;
|
||||||
|
n = siz - dlen;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return(dlen + strlen(s));
|
||||||
|
while (*s != '\0') {
|
||||||
|
if (n != 1) {
|
||||||
|
*d++ = *s;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
|
return(dlen + (s - src)); /* count does not include NUL */
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef STRLCAT_H
|
||||||
|
#define STRLCAT_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||||
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
|
* If retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||||
|
|
||||||
|
#endif
|
||||||
+183
@@ -0,0 +1,183 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crash(int sig)
|
||||||
|
{
|
||||||
|
kill(getpid(), SIGSEGV);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
static void run_test_child(TestListItem *item)
|
||||||
|
{
|
||||||
|
reset_signals();
|
||||||
|
struct sigaction sa = {.sa_handler = crash};
|
||||||
|
sigaction(SIGINT, &sa, 0);
|
||||||
|
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);
|
||||||
|
struct sigaction sa = {.sa_handler = SIG_IGN};
|
||||||
|
sigaction(SIGINT, &sa, 0);
|
||||||
|
return run_test_parent(item, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_all_tests(bool verbose)
|
||||||
|
{
|
||||||
|
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 (verbose) {
|
||||||
|
char *log_name = test_log_name_from_test_name(item->name);
|
||||||
|
FILE *log = fopen(log_name, "rt");
|
||||||
|
if (log) {
|
||||||
|
char buffer[4096];
|
||||||
|
size_t num_read;
|
||||||
|
while ((num_read = fread(buffer, 1, sizeof(buffer), log)) > 0) {
|
||||||
|
fwrite(buffer, 1, num_read, stdout);
|
||||||
|
}
|
||||||
|
fclose(log);
|
||||||
|
}
|
||||||
|
free(log_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
TEST(dummy) {
|
||||||
|
int x = 2;
|
||||||
|
int y = 2;
|
||||||
|
ASSERT_EQUAL(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(dummy_bad) {
|
||||||
|
int x = 2;
|
||||||
|
int y = 3;
|
||||||
|
ASSERT_EQUAL(x, y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -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(bool verbose);
|
||||||
|
|
||||||
|
#define FAIL_TEST_ \
|
||||||
|
*test_result_ = FAILURE; \
|
||||||
|
return;
|
||||||
|
|
||||||
|
#define ASSERT(value) \
|
||||||
|
if (!(value)) { \
|
||||||
|
FAIL_TEST_ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_EQUAL(a, b) \
|
||||||
|
if (!(a == b)) { \
|
||||||
|
printf("%s:%d: Assertion failed: %s == %s: ", __FILE__, __LINE__, #a, #b); \
|
||||||
|
print(a); \
|
||||||
|
printf(" != "); \
|
||||||
|
print(b); \
|
||||||
|
FAIL_TEST_ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_DIFFERENT(a, b) \
|
||||||
|
if (a == b) { \
|
||||||
|
printf("%s:%d: Assertion failed: %s != %s: ", __FILE__, __LINE__, #a, #b); \
|
||||||
|
print(a); \
|
||||||
|
printf(" == "); \
|
||||||
|
print(b); \
|
||||||
|
FAIL_TEST_ \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define ASSERT_STR_EQUAL(a, b) \
|
||||||
|
if (strcmp(a, b) != 0) { \
|
||||||
|
printf("%s:%d: Assertion failed: %s == %s: ", __FILE__, __LINE__, #a, #b); \
|
||||||
|
print(a); \
|
||||||
|
printf(" != "); \
|
||||||
|
print(b); \
|
||||||
|
FAIL_TEST_ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_STR_DIFFERENT(a, b) \
|
||||||
|
if (strcmp(a, b) == 0) { \
|
||||||
|
printf("%s:%d: Assertion failed: %s != %s: ", __FILE__, __LINE__, #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
|
||||||
+1613
-380
File diff suppressed because it is too large
Load Diff
+37
-28
@@ -21,45 +21,53 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include "bool.h"
|
||||||
|
|
||||||
// Single shot timers (i.e. timers with interval_msec == 0) are deleted automatically as soon as they expire,
|
extern bool warnings_for_timers;
|
||||||
// i.e. you do not need to stop them, however it is safe to call stop_timeout for these timers.
|
extern bool debug_timers;
|
||||||
// You can pass the address of the variable storing the pointer to the timer as 'self' in add_timeout, in which
|
|
||||||
// case it is used to clear the pointer if the timer is destroyed automatically. This enforces the timeout pointers
|
|
||||||
// to be either valid or NULL.
|
|
||||||
// Periodic timeouts are aligned to each other whenever possible, i.e. one interval_msec is an
|
|
||||||
// integral multiple of the other.
|
|
||||||
|
|
||||||
typedef struct _timeout timeout;
|
typedef void TimerCallback(void *arg);
|
||||||
|
|
||||||
// Initializes default global data.
|
typedef struct {
|
||||||
void default_timeout();
|
char name_[64];
|
||||||
|
bool enabled_;
|
||||||
|
long long expiration_time_ms_;
|
||||||
|
int period_ms_;
|
||||||
|
TimerCallback *callback_;
|
||||||
|
void *arg_;
|
||||||
|
bool handled_;
|
||||||
|
} Timer;
|
||||||
|
|
||||||
// Cleans up: stops all timers and frees memory.
|
#define DEFAULT_TIMER {"", 0, 0, 0, 0, 0, 0}
|
||||||
void cleanup_timeout();
|
|
||||||
|
|
||||||
// Installs a timer with the first timeout after 'value_msec' and then an optional periodic timeout every
|
#define INIT_TIMER(t) init_timer(&t, #t)
|
||||||
// 'interval_msec' (set it to 0 to prevent periodic timeouts).
|
|
||||||
// '_callback' is the function called when the timer reaches the timeout.
|
|
||||||
// 'arg' is the argument passed to the callback function.
|
|
||||||
// 'self' is an optional pointer to a timeout* variable. If non-NULL, the variable is set to NULL when the timer
|
|
||||||
// is destroyed (with stop_timeout, cleanup_timeout or when the timer expires and it is single-shot).
|
|
||||||
// Returns a pointer to the timer, which is needed for stopping/changing it.
|
|
||||||
timeout *add_timeout(int value_msec, int interval_msec, void (*_callback)(void *), void *arg, timeout **self);
|
|
||||||
|
|
||||||
// Changes timer 't'. If it does not exist, a new timer is created, with self set to 't'.
|
// Initialize the timer module.
|
||||||
void change_timeout(timeout **t, int value_msec, int interval_msec, void (*_callback)(void *), void *arg);
|
void default_timers();
|
||||||
|
|
||||||
// Stops the timer 't'
|
// Destroy the timer module.
|
||||||
void stop_timeout(timeout *t);
|
void cleanup_timers();
|
||||||
|
|
||||||
// Get the time when the next installed timer will expire, or NULL if there is no timer.
|
// Initialize a timer. Caller keeps ownership.
|
||||||
// Do not free the pointer; but it is safe to change its contents.
|
void init_timer(Timer *timer, const char *name);
|
||||||
struct timeval *get_next_timeout();
|
|
||||||
|
|
||||||
// Callback of all expired timeouts
|
// Destroy a timer. Does not free() the pointer.
|
||||||
|
void destroy_timer(Timer *timer);
|
||||||
|
|
||||||
|
// Modify a timer.
|
||||||
|
void change_timer(Timer *timer, bool enabled, int delay_ms, int period_ms, TimerCallback *callback, void *arg);
|
||||||
|
|
||||||
|
void stop_timer(Timer *timer);
|
||||||
|
|
||||||
|
// Get the time duration to the next expiration time, or NULL if there is no active timer.
|
||||||
|
// Do not free the pointer; it is harmless to change its contents.
|
||||||
|
struct timeval *get_duration_to_next_timer_expiration();
|
||||||
|
|
||||||
|
// Trigger all expired timers, and reschedule them if they are periodic timers
|
||||||
void handle_expired_timers();
|
void handle_expired_timers();
|
||||||
|
|
||||||
|
// Time helper functions.
|
||||||
|
|
||||||
// Returns -1 if t1 < t2, 0 if t1 == t2, 1 if t1 > t2
|
// Returns -1 if t1 < t2, 0 if t1 == t2, 1 if t1 > t2
|
||||||
gint compare_timespecs(const struct timespec *t1, const struct timespec *t2);
|
gint compare_timespecs(const struct timespec *t1, const struct timespec *t2);
|
||||||
|
|
||||||
@@ -69,6 +77,7 @@ struct timespec add_msec_to_timespec(struct timespec ts, int msec);
|
|||||||
// At the first call returns zero.
|
// At the first call returns zero.
|
||||||
double profiling_get_time();
|
double profiling_get_time();
|
||||||
|
|
||||||
|
// Get current time in seconds, from an unspecified origin.
|
||||||
double get_time();
|
double get_time();
|
||||||
|
|
||||||
#endif // TIMER_H
|
#endif // TIMER_H
|
||||||
|
|||||||
@@ -49,8 +49,9 @@ char *addr2name(void *func)
|
|||||||
free(strings);
|
free(strings);
|
||||||
return result;
|
return result;
|
||||||
#else
|
#else
|
||||||
char *result = (char*) calloc(32, 1);
|
const size_t buf_size = 32;
|
||||||
sprintf(result, "%p", func);
|
char *result = (char*) calloc(buf_size, 1);
|
||||||
|
snprintf(result, buf_size, "%p", func);
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
+258
-5
@@ -21,14 +21,21 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <cairo-xlib.h>
|
#include <cairo-xlib.h>
|
||||||
|
|
||||||
|
#include <X11/extensions/XShm.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
@@ -157,7 +164,8 @@ int get_window_desktop(Window win)
|
|||||||
|
|
||||||
if (best_match < 0)
|
if (best_match < 0)
|
||||||
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);
|
// best_match+1, x, y);
|
||||||
return best_match;
|
return best_match;
|
||||||
}
|
}
|
||||||
@@ -190,15 +198,18 @@ int get_window_monitor(Window win)
|
|||||||
return best_match;
|
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;
|
int dummy_int;
|
||||||
unsigned ww, wh, bw, bh;
|
unsigned ww, wh, bw, bh;
|
||||||
Window src;
|
Window src;
|
||||||
XTranslateCoordinates(server.display, win, server.root_win, 0, 0, x, y, &src);
|
if (!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);
|
return FALSE;
|
||||||
|
if (!XGetGeometry(server.display, win, &src, &dummy_int, &dummy_int, &ww, &wh, &bw, &bh))
|
||||||
|
return FALSE;
|
||||||
*w = ww + bw;
|
*w = ww + bw;
|
||||||
*h = wh + bh;
|
*h = wh + bw;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean window_is_iconified(Window win)
|
gboolean window_is_iconified(Window win)
|
||||||
@@ -352,3 +363,245 @@ char *get_window_name(Window win)
|
|||||||
XFree(text_property.value);
|
XFree(text_property.value);
|
||||||
return result;
|
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 than XGetPixel.
|
||||||
|
static u_int32_t GetPixel(XImage *ximg, unsigned x, unsigned y)
|
||||||
|
{
|
||||||
|
if (x >= ximg->width || y >= ximg->height) {
|
||||||
|
fprintf(stderr, RED "GetPixel read overflow: %u %u %d %d\n",
|
||||||
|
x, y, ximg->width, ximg->height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ((u_int32_t *)&(ximg->data[y * ximg->bytes_per_line]))[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: the xrender method only works well if there is a compositor running
|
||||||
|
cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm)
|
||||||
|
{
|
||||||
|
fprintf(stderr, GREEN "tint2: win=%u: getting thumbnail of size %u" RESET "\n", win, size);
|
||||||
|
cairo_surface_t *result = NULL;
|
||||||
|
XWindowAttributes wa;
|
||||||
|
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 ||
|
||||||
|
wa.map_state != IsViewable) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no win attributes" RESET "\n", win);
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_is_iconified(win)) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for minimized window" RESET "\n", win);
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t w, h;
|
||||||
|
w = (size_t)wa.width + wa.x;
|
||||||
|
h = (size_t)wa.height + wa.y;
|
||||||
|
size_t tw, th, fw;
|
||||||
|
size_t ox, oy;
|
||||||
|
tw = size;
|
||||||
|
th = h * tw / w;
|
||||||
|
double scale = th / (double)h;
|
||||||
|
if (th > tw * 0.618) {
|
||||||
|
th = (size_t)(tw * 0.618);
|
||||||
|
fw = w * th / h;
|
||||||
|
ox = (tw - fw) / 2;
|
||||||
|
oy = 0;
|
||||||
|
} else {
|
||||||
|
fw = tw;
|
||||||
|
ox = oy = 0;
|
||||||
|
}
|
||||||
|
if (!w || !h || !tw || !th || !fw) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for size 0x0" RESET "\n", win);
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XImage *ximg = NULL;
|
||||||
|
|
||||||
|
XGetWindowAttributes(server.display, win, &wa);
|
||||||
|
if (wa.map_state != IsViewable) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for non-viewable window" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pixmap pix = XCreatePixmap(server.display, win, tw, th, wa.depth);
|
||||||
|
if (!pix) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no pixmap" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
XRenderPictureAttributes attrs = {
|
||||||
|
.repeat = RepeatNone
|
||||||
|
};
|
||||||
|
XRenderPictFormat *fmt = XRenderFindVisualFormat(server.display, wa.visual);
|
||||||
|
if (!fmt) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no XRender format" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
Picture src_pic = XRenderCreatePicture(server.display, win, fmt, CPRepeat, &attrs);
|
||||||
|
if (!src_pic) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no src picture" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
Picture dst_pic = XRenderCreatePicture(server.display, pix, fmt, CPRepeat, &attrs);
|
||||||
|
if (!dst_pic) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no src picture" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
fprintf(stderr, GREEN "tint2: win=%u: transformation %u %u %f xy %d %d" RESET "\n", win, ox, oy, scale,
|
||||||
|
wa.x, wa.y);
|
||||||
|
XTransform transform = {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
XDoubleToFixed(1./scale),
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(ox-wa.x/scale)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(1./scale),
|
||||||
|
XDoubleToFixed(oy-wa.y/scale)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
XRenderSetPictureTransform(server.display, src_pic, &transform);
|
||||||
|
XRenderSetPictureFilter(server.display, src_pic, FilterBilinear, NULL, 0);
|
||||||
|
XRenderComposite(server.display, PictOpSrc, src_pic, None, dst_pic, 0, 0, 0, 0, 0, 0, w, h);
|
||||||
|
XSync(server.display, False);
|
||||||
|
|
||||||
|
ximg = XGetImage(server.display, pix, 0, 0, (unsigned)tw, (unsigned)th, AllPlanes, ZPixmap);
|
||||||
|
if (!ximg) {
|
||||||
|
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
if (ximg->bits_per_pixel != 24 && ximg->bits_per_pixel != 32) {
|
||||||
|
fprintf(stderr, RED "tint2: unusual bits_per_pixel" RESET "\n");
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, GREEN "tint2: creating image surface %ux%u" RESET "\n", tw, th);
|
||||||
|
result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, (int)tw, (int)th);
|
||||||
|
u_int32_t *data = (u_int32_t *)cairo_image_surface_get_data(result);
|
||||||
|
memset(data, 0, tw * th);
|
||||||
|
|
||||||
|
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 y = 0; y < th; y++) {
|
||||||
|
for (size_t x = 0; x < tw; x++) {
|
||||||
|
u_int32_t c = (u_int32_t)XGetPixel(ximg, x, y);
|
||||||
|
data[y * tw + x] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imlib_context_set_drawable(pix);
|
||||||
|
Imlib_Image img = imlib_create_image_from_drawable(0, 0, 0, tw, th, 1);
|
||||||
|
//Imlib_Image img = imlib_create_image_using_data(tw, th, data);
|
||||||
|
imlib_context_set_image(img);
|
||||||
|
char path[256];
|
||||||
|
static unsigned count = 0;
|
||||||
|
sprintf(path, "thumb-%u-%u.png", win, count++);
|
||||||
|
imlib_save_image(path);
|
||||||
|
imlib_free_image();
|
||||||
|
|
||||||
|
// Convert to argb32
|
||||||
|
if (rmask & 0xff0000) {
|
||||||
|
// argb32 or rgb24 => Nothing to do
|
||||||
|
} 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);
|
||||||
|
cairo_surface_flush(result);
|
||||||
|
|
||||||
|
if (ximg) {
|
||||||
|
XDestroyImage(ximg);
|
||||||
|
ximg = NULL;
|
||||||
|
}
|
||||||
|
err1:
|
||||||
|
err4:
|
||||||
|
if (ximg)
|
||||||
|
XDestroyImage(ximg);
|
||||||
|
if (src_pic)
|
||||||
|
XRenderFreePicture(server.display, src_pic);
|
||||||
|
if (dst_pic)
|
||||||
|
XRenderFreePicture(server.display, dst_pic);
|
||||||
|
if (pix)
|
||||||
|
XFreePixmap(server.display, pix);
|
||||||
|
err0:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!image_surface) {
|
||||||
|
image_surface = get_window_thumbnail_ximage(win, (size_t)size, FALSE);
|
||||||
|
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
||||||
|
fprintf(stderr, RED "tint2: captured blank thumbnail" RESET "\n");
|
||||||
|
cairo_surface_destroy(image_surface);
|
||||||
|
image_surface = NULL;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|||||||
+2
-1
@@ -25,7 +25,7 @@ int get_window_monitor(Window win);
|
|||||||
|
|
||||||
void activate_window(Window win);
|
void activate_window(Window win);
|
||||||
void close_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_maximized(Window win);
|
||||||
void toggle_window_shade(Window win);
|
void toggle_window_shade(Window win);
|
||||||
void change_window_desktop(Window win, int desktop);
|
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);
|
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);
|
char *get_window_name(Window win);
|
||||||
|
cairo_surface_t *get_window_thumbnail(Window win, int size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
1
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
disabled
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
auto
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
disabled
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
unsupported
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
enabled
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
4
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
4
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user