Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01f823cf79 |
+1
-3
@@ -1,7 +1,5 @@
|
|||||||
build
|
build
|
||||||
*.user
|
*.user
|
||||||
version.h
|
version.h
|
||||||
*.pyc
|
|
||||||
*.todo
|
*.todo
|
||||||
packaging/make_ubuntu2.sh
|
*.pyc
|
||||||
test_*.log
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ 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>
|
||||||
@@ -33,7 +32,6 @@ Contributors:
|
|||||||
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
|
heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color
|
||||||
Fabian Carlström : taskbar sort order by app name
|
|
||||||
|
|
||||||
Translations:
|
Translations:
|
||||||
Bosnian:
|
Bosnian:
|
||||||
|
|||||||
+13
-21
@@ -62,17 +62,6 @@ 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 )
|
||||||
@@ -127,14 +116,13 @@ include_directories( ${PROJECT_BINARY_DIR}
|
|||||||
|
|
||||||
set( SOURCES src/config.c
|
set( SOURCES src/config.c
|
||||||
src/panel.c
|
src/panel.c
|
||||||
src/util/server.c
|
src/server.c
|
||||||
src/main.c
|
src/main.c
|
||||||
src/init.c
|
src/init.c
|
||||||
src/util/signals.c
|
src/signals.c
|
||||||
src/util/tracing.c
|
src/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
|
||||||
@@ -152,17 +140,16 @@ 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/addr2line.c
|
||||||
|
src/util/print.c
|
||||||
|
src/util/mem.c
|
||||||
src/util/uevent.c
|
src/util/uevent.c
|
||||||
src/util/window.c )
|
src/util/window.c )
|
||||||
|
|
||||||
@@ -249,7 +236,7 @@ else()
|
|||||||
SET(TRACING_L_FLAGS "")
|
SET(TRACING_L_FLAGS "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" )
|
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" -- "\"${PROJECT_SOURCE_DIR}/\"" )
|
||||||
|
|
||||||
link_directories( ${X11_LIBRARY_DIRS}
|
link_directories( ${X11_LIBRARY_DIRS}
|
||||||
${PANGOCAIRO_LIBRARY_DIRS}
|
${PANGOCAIRO_LIBRARY_DIRS}
|
||||||
@@ -281,9 +268,14 @@ if( RT_LIBRARY )
|
|||||||
endif( RT_LIBRARY )
|
endif( RT_LIBRARY )
|
||||||
|
|
||||||
target_link_libraries( tint2 m )
|
target_link_libraries( tint2 m )
|
||||||
|
if(ENABLE_BACKTRACE)
|
||||||
|
target_link_libraries( tint2 dl )
|
||||||
|
target_link_libraries( tint2 z )
|
||||||
|
target_link_libraries( tint2 bfd )
|
||||||
|
endif(ENABLE_BACKTRACE)
|
||||||
|
|
||||||
add_dependencies( tint2 version )
|
add_dependencies( tint2 version )
|
||||||
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 COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=c11 ${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 )
|
||||||
|
|||||||
@@ -1,49 +1,8 @@
|
|||||||
2018-08-05 16.6.1
|
2017-11-10 master
|
||||||
- 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:
|
- Enhancements:
|
||||||
- Added Spanish translation (contributed by Vicmz)
|
- Added Spanish translation (contributed by Vicmz)
|
||||||
- Executor: updated tooltip documentation (issue #676)
|
- Executor: updated tooltip documentation (issue #676)
|
||||||
- Systray: warn on duplicate config option systray_name_filter (issue #652)
|
- 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
|
2017-11-05 15.3
|
||||||
- Fixes:
|
- Fixes:
|
||||||
@@ -1012,10 +971,3 @@ released tint-0.2
|
|||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Latest stable release: 16.6.1
|
# Latest stable release: 15.3
|
||||||
Changes: https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog
|
Changes: https://gitlab.com/o9000/tint2/blob/15.3/ChangeLog
|
||||||
|
|
||||||
Documentation: [doc/tint2.md](doc/tint2.md)
|
Documentation: [doc/tint2.md](doc/tint2.md)
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ Compile it with (after you install the [dependencies](https://gitlab.com/o9000/t
|
|||||||
```
|
```
|
||||||
git clone https://gitlab.com/o9000/tint2.git
|
git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 16.6.1
|
git checkout 15.3
|
||||||
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
|
||||||
|
|
||||||
* 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))
|
* Graphic glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA ([issue 595](https://gitlab.com/o9000/tint2/issues/595))
|
||||||
* Window managers that do not follow exactly the EWMH specification might not interact well with tint2 ([issue 627](https://gitlab.com/o9000/tint2/issues/627)).
|
* Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (known issues for [awesome](https://gitlab.com/o9000/tint2/issues/385), [bspwm](https://gitlab.com/o9000/tint2/issues/524). [openbox-multihead](https://gitlab.com/o9000/tint2/issues/456))
|
||||||
* Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE).
|
* 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,3 +97,4 @@ 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)
|
||||||
|
|||||||
+2
-5
@@ -386,8 +386,6 @@ 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
|
||||||
@@ -466,7 +464,6 @@ 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>
|
||||||
@@ -573,7 +570,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 = xmessage 'tint2: Battery low!'</code> : Command to execute when the battery is low.</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_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>
|
||||||
@@ -608,7 +605,7 @@ panel_size = 94% 30
|
|||||||
<li><p><code>execp_cache_icon = boolean (0 or 1)</code> : If <code>execp_cache_icon = 0</code>, the image is reloaded each time the command is executed (useful if the image file is changed on disk by the program executed by <code>execp_command</code>). <em>(since 0.12.4)</em></p></li>
|
<li><p><code>execp_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. 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_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>
|
||||||
|
|||||||
+7
-6
@@ -199,9 +199,9 @@ pre {
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<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
|
<h1 id="latest-stable-release-15-3"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">15.3</span><a name="latest-stable-release-15-3" href="#latest-stable-release-15-3" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/15.3/ChangeLog">https://gitlab.com/o9000/tint2/blob/15.3/ChangeLog</a></p><p>Documentation: <a href="manual.html">manual.html</a></p><p>Compile it with (after you install the <a href="https://gitlab.com/o9000/tint2/wikis/Install#dependencies">dependencies</a>):</p><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 16.6.1
|
git checkout 15.3
|
||||||
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>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>Graphic glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA (<a href="https://gitlab.com/o9000/tint2/issues/595">issue 595</a>)</li>
|
||||||
<li>Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (<a href="https://gitlab.com/o9000/tint2/issues/627">issue 627</a>).</li>
|
<li>Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (known issues for <a href="https://gitlab.com/o9000/tint2/issues/385">awesome</a>, <a href="https://gitlab.com/o9000/tint2/issues/524">bspwm</a>. <a href="https://gitlab.com/o9000/tint2/issues/456">openbox-multihead</a>)</li>
|
||||||
<li>Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE).</li>
|
<li>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,7 +269,8 @@ 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>
|
<li><a href="https://gitlab.com/o9000/tint2/wikis/Home">Tint2 wiki</a>
|
||||||
|
Home)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+2
-8
@@ -1,4 +1,4 @@
|
|||||||
.TH TINT2 1 "2018\-08\-05" 16.6.1
|
.TH TINT2 1 "2017\-11\-05" 15.3
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
tint2 \- lightweight panel/taskbar
|
tint2 \- lightweight panel/taskbar
|
||||||
@@ -343,10 +343,6 @@ 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
|
||||||
@@ -480,8 +476,6 @@ 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
|
||||||
@@ -665,7 +659,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 = xmessage 'tint2: Battery low!'\fR : Command to execute when the battery is low.
|
\fB\fCbattery_low_cmd = notify\-send "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
|
||||||
|
|||||||
+2
-7
@@ -1,4 +1,4 @@
|
|||||||
# TINT2 1 "2018-08-05" 16.6.1
|
# TINT2 1 "2017-11-05" 15.3
|
||||||
|
|
||||||
## NAME
|
## NAME
|
||||||
tint2 - lightweight panel/taskbar
|
tint2 - lightweight panel/taskbar
|
||||||
@@ -279,10 +279,6 @@ 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
|
||||||
@@ -385,7 +381,6 @@ 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)*
|
||||||
@@ -547,7 +542,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 = xmessage 'tint2: Battery low!'` : Command to execute when the battery is low.
|
* `battery_low_cmd = notify-send "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.
|
||||||
|
|
||||||
|
|||||||
+5
-10
@@ -4,10 +4,7 @@ SCRIPT_DIR=$(dirname "$0")
|
|||||||
DIRTY=""
|
DIRTY=""
|
||||||
VERSION=""
|
VERSION=""
|
||||||
|
|
||||||
OLD_DIR=$(pwd)
|
if [ -d ${SCRIPT_DIR}/.git ] && git status 1>/dev/null 2>/dev/null
|
||||||
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
|
||||||
@@ -40,10 +37,10 @@ then
|
|||||||
VERSION=$(git describe 2>/dev/null)$DIRTY
|
VERSION=$(git describe 2>/dev/null)$DIRTY
|
||||||
elif git log -n 1 1>/dev/null 2>/dev/null
|
elif git log -n 1 1>/dev/null 2>/dev/null
|
||||||
then
|
then
|
||||||
VERSION=$(head -n 1 "ChangeLog" | cut -d ' ' -f 2)
|
VERSION=$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 2)
|
||||||
if [ "$VERSION" = "master" ]
|
if [ "$VERSION" = "master" ]
|
||||||
then
|
then
|
||||||
PREVIOUS=$(grep '^2' "ChangeLog" | head -n 2 | tail -n 1 | cut -d ' ' -f 2)
|
PREVIOUS=$(grep '^2' "${SCRIPT_DIR}/ChangeLog" | head -n 2 | tail -n 1 | cut -d ' ' -f 2)
|
||||||
HASH=$(git log -n 1 --pretty=format:%cI.%ct.%h | tr -d ':' | tr -d '-' | tr '.' '-' | sed 's/T[0-9\+]*//g' 2>/dev/null)
|
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
|
VERSION=$PREVIOUS-next-$HASH
|
||||||
fi
|
fi
|
||||||
@@ -52,15 +49,13 @@ fi
|
|||||||
|
|
||||||
if [ -z "$VERSION" ]
|
if [ -z "$VERSION" ]
|
||||||
then
|
then
|
||||||
VERSION=$(head -n 1 "ChangeLog" | cut -d ' ' -f 2)
|
VERSION=$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 2)
|
||||||
if [ "$VERSION" = "master" ]
|
if [ "$VERSION" = "master" ]
|
||||||
then
|
then
|
||||||
VERSION=$VERSION-$(head -n 1 "ChangeLog" | cut -d ' ' -f 1)
|
VERSION=$VERSION-$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 1)
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "${OLD_DIR}"
|
|
||||||
|
|
||||||
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
||||||
|
|
||||||
echo '#define VERSION_STRING "'$VERSION'"' > version.h
|
echo '#define VERSION_STRING "'$VERSION'"' > version.h
|
||||||
|
|||||||
+15
-16
@@ -76,23 +76,19 @@ def get_last_version():
|
|||||||
return tags[-1]
|
return tags[-1]
|
||||||
|
|
||||||
|
|
||||||
def inc_version(v, feature=False, tiny=False):
|
def inc_version(v, feature=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 or v4.11.1
|
# v4.11 -> v4.12 or v5.0
|
||||||
parts = v.split(".")
|
parts = v.split(".")
|
||||||
while len(parts) < 3:
|
while len(parts) < 2:
|
||||||
parts.append("0")
|
parts.append("0")
|
||||||
assert len(parts) == 3
|
assert len(parts) == 2
|
||||||
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])
|
||||||
|
|
||||||
@@ -157,14 +153,23 @@ 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("--tiny", action="store_true")
|
parser.add_argument("--undo", 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, args.tiny)
|
version = inc_version(old_version, args.feature)
|
||||||
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)
|
||||||
@@ -189,9 +194,3 @@ if __name__ == '__main__':
|
|||||||
choice = raw_input().lower()
|
choice = raw_input().lower()
|
||||||
if choice != "y":
|
if choice != "y":
|
||||||
run("git reset --hard HEAD~ ; git tag -d %s ; git tag -d %s" % (version, readable_version))
|
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")
|
|
||||||
|
|||||||
Vendored
-543
@@ -1,543 +0,0 @@
|
|||||||
#!/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']
|
|
||||||
|
|
||||||
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)
|
|
||||||
@@ -21,7 +21,7 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm -f version.h
|
rm -f version.h
|
||||||
VERSION=$(false 2>/dev/null)
|
VERSION=$(git describe --exact-match 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 artful bionic
|
for DISTRO in trusty xenial zesty artful
|
||||||
do
|
do
|
||||||
# Cleanup from previous builds
|
# Cleanup from previous builds
|
||||||
rm -rf tint2_$VERSION-*
|
rm -rf tint2_$VERSION-*
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ git reset --hard
|
|||||||
git pull
|
git pull
|
||||||
|
|
||||||
|
|
||||||
timeout -k 10 600 ~/tint2/packaging/version_status.py > packaging.tmp.md
|
~/tint2/packaging/version_status.py > packaging.tmp.md
|
||||||
cat packaging.tmp.md > packaging.md
|
cat packaging.tmp.md > packaging.md
|
||||||
rm packaging.tmp.md
|
rm packaging.tmp.md
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ def get_gentoo_versions():
|
|||||||
|
|
||||||
def get_void_versions():
|
def get_void_versions():
|
||||||
print >> sys.stderr, "Void ..."
|
print >> sys.stderr, "Void ..."
|
||||||
template = http_download_txt("https://raw.githubusercontent.com/void-linux/void-packages/master/srcpkgs/tint2/template")
|
template = http_download_txt("https://raw.githubusercontent.com/voidlinux/void-packages/master/srcpkgs/tint2/template")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
maintainer = None
|
maintainer = None
|
||||||
@@ -367,7 +367,7 @@ def get_freebsd_versions():
|
|||||||
|
|
||||||
def get_openbsd_versions():
|
def get_openbsd_versions():
|
||||||
print >> sys.stderr, "OpenBSD ..."
|
print >> sys.stderr, "OpenBSD ..."
|
||||||
makefile = http_download_txt("http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/ports/x11/tint2/Makefile?content-type=text/plain")
|
makefile = http_download_txt("http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/ports/x11/tint2/Makefile?rev=1.5&content-type=text/plain")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
for line in makefile.split("\n"):
|
for line in makefile.split("\n"):
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ 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 Timer battery_timer;
|
static timeout *battery_timeout;
|
||||||
|
|
||||||
#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];
|
||||||
@@ -76,7 +76,7 @@ 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;
|
||||||
INIT_TIMER(battery_timer);
|
battery_timeout = NULL;
|
||||||
bat1_has_font = FALSE;
|
bat1_has_font = FALSE;
|
||||||
bat1_font_desc = NULL;
|
bat1_font_desc = NULL;
|
||||||
bat1_format = NULL;
|
bat1_format = NULL;
|
||||||
@@ -127,7 +127,8 @@ 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;
|
||||||
destroy_timer(&battery_timer);
|
stop_timeout(battery_timeout);
|
||||||
|
battery_timeout = NULL;
|
||||||
battery_found = FALSE;
|
battery_found = FALSE;
|
||||||
|
|
||||||
battery_os_free();
|
battery_os_free();
|
||||||
@@ -225,8 +226,7 @@ void init_battery()
|
|||||||
|
|
||||||
battery_found = battery_os_init();
|
battery_found = battery_os_init();
|
||||||
|
|
||||||
if (!battery_timer.enabled_)
|
battery_timeout = add_timeout(10, 30000, update_battery_tick, 0, &battery_timeout);
|
||||||
change_timer(&battery_timer, true, 30000, 30000, update_battery_tick, 0);
|
|
||||||
|
|
||||||
update_battery();
|
update_battery();
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,6 @@ 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()
|
||||||
@@ -422,7 +421,6 @@ 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,
|
||||||
@@ -431,8 +429,7 @@ 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)
|
||||||
|
|||||||
+22
-29
@@ -269,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) * panel->scale;
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy);
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
||||||
int interior_padding = button->area.paddingx * panel->scale;
|
int interior_padding = button->area.paddingx;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -280,17 +280,18 @@ 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 * panel->scale);
|
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height, txt_width;
|
int txt_height_ink, 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,
|
||||||
@@ -299,11 +300,10 @@ 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,
|
||||||
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
FALSE);
|
||||||
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,
|
||||||
@@ -313,12 +313,10 @@ 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,
|
||||||
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
FALSE);
|
||||||
FALSE,
|
|
||||||
panel->scale);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
txt_height = txt_width = 0;
|
txt_height_ink = txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -338,9 +336,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) * panel->scale;
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy);
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
||||||
int interior_padding = button->area.paddingx * panel->scale;
|
int interior_padding = button->area.paddingx;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -349,8 +347,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 * panel->scale);
|
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
@@ -371,9 +369,10 @@ gboolean resize_button(void *obj)
|
|||||||
available_h = panel->area.height;
|
available_h = panel->area.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height, txt_width;
|
int txt_height_ink, 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,
|
||||||
@@ -382,11 +381,9 @@ 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,
|
||||||
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
FALSE);
|
||||||
FALSE,
|
|
||||||
panel->scale);
|
|
||||||
} else {
|
} else {
|
||||||
txt_height = txt_width = 0;
|
txt_height_ink = txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
@@ -439,7 +436,6 @@ 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
|
||||||
@@ -461,12 +457,10 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
// Render text
|
// Render text
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoLayout *layout = pango_cairo_create_layout(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 + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
pango_layout_set_width(layout, button->frontend->textw * 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);
|
||||||
@@ -481,7 +475,6 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
panel_config.font_shadow);
|
panel_config.font_shadow);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
g_object_unref(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-9
@@ -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 Timer clock_timer;
|
static timeout *clock_timeout;
|
||||||
|
|
||||||
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,7 +110,8 @@ 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;
|
||||||
destroy_timer(&clock_timer);
|
stop_timeout(clock_timeout);
|
||||||
|
clock_timeout = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tm *clock_gettime_for_tz(const char *timezone)
|
struct tm *clock_gettime_for_tz(const char *timezone)
|
||||||
@@ -154,7 +155,7 @@ void update_clocks_sec(void *arg)
|
|||||||
{
|
{
|
||||||
gettimeofday(&time_clock, 0);
|
gettimeofday(&time_clock, 0);
|
||||||
update_clocks();
|
update_clocks();
|
||||||
change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_sec, 0);
|
clock_timeout = add_timeout(ms_until_second_change(&time_clock), 0, update_clocks_sec, 0, &clock_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_clocks_min(void *arg)
|
void update_clocks_min(void *arg)
|
||||||
@@ -166,7 +167,7 @@ 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;
|
||||||
change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_min, 0);
|
clock_timeout = add_timeout(ms_until_second_change(&time_clock), 0, update_clocks_min, 0, &clock_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean time_format_needs_sec_ticks(char *time_format)
|
gboolean time_format_needs_sec_ticks(char *time_format)
|
||||||
@@ -215,7 +216,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_timer.enabled_) {
|
if (!clock_timeout) {
|
||||||
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 {
|
||||||
@@ -261,8 +262,10 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -271,8 +274,10 @@ 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);
|
||||||
}
|
}
|
||||||
@@ -302,7 +307,6 @@ 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,
|
||||||
@@ -311,8 +315,7 @@ 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)
|
||||||
|
|||||||
+1
-7
@@ -244,11 +244,7 @@ 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, "scale_relative_to_dpi") == 0) {
|
if (strcmp(key, "rounded") == 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);
|
||||||
@@ -1016,8 +1012,6 @@ 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) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,10 +0,0 @@
|
|||||||
#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
|
|
||||||
+38
-46
@@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
#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();
|
||||||
@@ -43,7 +41,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +67,8 @@ 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
|
||||||
destroy_timer(&execp->backend->timer);
|
stop_timeout(execp->backend->timer);
|
||||||
|
execp->backend->timer = NULL;
|
||||||
|
|
||||||
free_icon(execp->backend->icon);
|
free_icon(execp->backend->icon);
|
||||||
free_and_null(execp->backend->buf_stdout);
|
free_and_null(execp->backend->buf_stdout);
|
||||||
@@ -194,7 +192,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);
|
||||||
|
|
||||||
change_timer(&execp->backend->timer, true, 10, 0, execp_timer_callback, execp);
|
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
||||||
|
|
||||||
execp_update_post_read(execp);
|
execp_update_post_read(execp);
|
||||||
}
|
}
|
||||||
@@ -306,6 +304,7 @@ 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,
|
||||||
@@ -313,9 +312,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) * panel->scale;
|
*horiz_padding = (panel_horizontal ? area->paddingxlr : area->paddingy);
|
||||||
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr) * panel->scale;
|
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr);
|
||||||
*interior_padding = area->paddingx * panel->scale;
|
*interior_padding = area->paddingx;
|
||||||
|
|
||||||
if (reload_icon(execp)) {
|
if (reload_icon(execp)) {
|
||||||
if (execp->backend->icon) {
|
if (execp->backend->icon) {
|
||||||
@@ -334,7 +333,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 * *vert_padding - left_right_border_width(area);
|
available_h = area->height - 2 * area->paddingy - 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 -
|
||||||
@@ -343,6 +342,7 @@ 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,
|
||||||
@@ -351,9 +351,7 @@ 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->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
execp->backend->has_markup);
|
||||||
execp->backend->has_markup,
|
|
||||||
panel->scale);
|
|
||||||
|
|
||||||
*resized = FALSE;
|
*resized = FALSE;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -387,7 +385,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, txt_width;
|
int txt_height_ink, 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,
|
||||||
@@ -397,6 +395,7 @@ 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,
|
||||||
@@ -411,7 +410,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, txt_width;
|
int txt_height_ink, 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,
|
||||||
@@ -421,6 +420,7 @@ 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,
|
||||||
@@ -476,11 +476,7 @@ gboolean resize_execp(void *obj)
|
|||||||
void draw_execp(void *obj, cairo_t *c)
|
void draw_execp(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Execp *execp = (Execp *)obj;
|
Execp *execp = (Execp *)obj;
|
||||||
Panel *panel = (Panel *)execp->area.panel;
|
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);
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -490,8 +486,7 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
// draw layout
|
// draw layout
|
||||||
pango_layout_set_font_description(layout, execp->backend->font_desc);
|
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_width(layout, execp->frontend->textw * 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_alignment(layout, execp->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);
|
||||||
@@ -509,7 +504,6 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
panel_config.font_shadow);
|
panel_config.font_shadow);
|
||||||
|
|
||||||
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)
|
||||||
@@ -546,8 +540,10 @@ 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
|
||||||
change_timer(&execp->backend->timer, true, 10, 0, execp_timer_callback, execp);
|
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +633,6 @@ 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]);
|
||||||
@@ -762,7 +757,8 @@ 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)
|
||||||
change_timer(&execp->backend->timer, true, execp->backend->interval * 1000, 0, execp_timer_callback, execp);
|
execp->backend->timer =
|
||||||
|
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 +882,22 @@ gboolean read_execp(void *obj)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *time_to_string(int seconds, char *buffer, size_t buffer_size)
|
const char *time_to_string(int seconds, char *buffer)
|
||||||
{
|
{
|
||||||
if (seconds < 60) {
|
if (seconds < 60) {
|
||||||
snprintf(buffer, buffer_size, "%ds", seconds);
|
sprintf(buffer, "%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;
|
||||||
snprintf(buffer, buffer_size, "%d:%ds", m, s);
|
sprintf(buffer, "%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;
|
||||||
snprintf(buffer, buffer_size, "%d:%d:%ds", h, m, s);
|
sprintf(buffer, "%d:%d:%ds", h, m, s);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@@ -927,39 +923,35 @@ 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) {
|
||||||
snprintf(execp->backend->tooltip_text,
|
sprintf(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, sizeof(tmp_buf1)),
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
||||||
time_to_string((int)execp->backend->last_update_duration, tmp_buf2, sizeof(tmp_buf2)),
|
time_to_string((int)execp->backend->last_update_duration, 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, sizeof(tmp_buf3)));
|
tmp_buf3));
|
||||||
} else {
|
} else {
|
||||||
snprintf(execp->backend->tooltip_text,
|
sprintf(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, sizeof(tmp_buf1)),
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
||||||
time_to_string((int)execp->backend->last_update_duration, tmp_buf2, sizeof(tmp_buf2)));
|
time_to_string((int)execp->backend->last_update_duration, tmp_buf2));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we never requested an update
|
// we never requested an update
|
||||||
snprintf(execp->backend->tooltip_text, sizeof(execp->backend->tooltip_text), "Never updated. No update scheduled.");
|
sprintf(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
|
||||||
snprintf(execp->backend->tooltip_text,
|
sprintf(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, sizeof(tmp_buf1)),
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
||||||
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf3, sizeof(tmp_buf3)));
|
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf3));
|
||||||
} else {
|
} else {
|
||||||
// we never finished an update
|
// we never finished an update
|
||||||
snprintf(execp->backend->tooltip_text,
|
sprintf(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, sizeof(tmp_buf1)));
|
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strdup(execp->backend->tooltip_text);
|
return strdup(execp->backend->tooltip_text);
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
#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.
|
||||||
@@ -48,7 +46,7 @@ typedef struct ExecpBackend {
|
|||||||
Background *bg;
|
Background *bg;
|
||||||
|
|
||||||
// Backend state:
|
// Backend state:
|
||||||
Timer timer;
|
timeout *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 *panel)
|
int freespace_get_max_size(Panel *p)
|
||||||
{
|
{
|
||||||
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 = panel->area.children; walk; walk = g_list_next(walk)) {
|
for (GList *walk = p->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 *panel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size += a->width + panel->area.paddingx * panel->scale;
|
size += a->width + p->area.paddingx;
|
||||||
else
|
else
|
||||||
size += a->height + panel->area.paddingy * panel->scale;
|
size += a->height + p->area.paddingy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size = panel->area.width - size - left_right_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
size = p->area.width - size - left_right_border_width(&p->area) - p->area.paddingxlr;
|
||||||
else
|
else
|
||||||
size = panel->area.height - size - top_bottom_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
size = p->area.height - size - top_bottom_border_width(&p->area) - p->area.paddingxlr;
|
||||||
|
|
||||||
return size / spacers;
|
return size / spacers;
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-40
@@ -12,13 +12,11 @@
|
|||||||
#include <X11/extensions/XShm.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"
|
||||||
@@ -50,15 +48,6 @@ 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++;
|
||||||
@@ -105,8 +94,6 @@ void handle_env_vars()
|
|||||||
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_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");
|
||||||
@@ -116,25 +103,25 @@ void handle_env_vars()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Timer detect_compositor_timer = DEFAULT_TIMER;
|
static timeout *detect_compositor_timer = NULL;
|
||||||
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_timer(&detect_compositor_timer);
|
stop_timeout(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_timer(&detect_compositor_timer);
|
stop_timeout(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_timer(&detect_compositor_timer);
|
stop_timeout(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);
|
||||||
@@ -147,15 +134,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;
|
||||||
INIT_TIMER(detect_compositor_timer);
|
detect_compositor_timer = add_timeout(500, 500, detect_compositor, 0, &detect_compositor_timer);
|
||||||
change_timer(&detect_compositor_timer, true, 500, 500, detect_compositor, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_default_elements()
|
void create_default_elements()
|
||||||
{
|
{
|
||||||
default_timers();
|
default_timeout();
|
||||||
default_systray();
|
default_systray();
|
||||||
memset(&server, 0, sizeof(server));
|
memset(&server, 0, sizeof(server));
|
||||||
#ifdef ENABLE_BATTERY
|
#ifdef ENABLE_BATTERY
|
||||||
@@ -170,22 +157,6 @@ 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();
|
||||||
@@ -196,7 +167,20 @@ 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);
|
||||||
}
|
}
|
||||||
@@ -238,10 +222,10 @@ 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()) {
|
||||||
@@ -275,7 +259,6 @@ void cleanup()
|
|||||||
cleanup_battery();
|
cleanup_battery();
|
||||||
#endif
|
#endif
|
||||||
cleanup_separator();
|
cleanup_separator();
|
||||||
cleanup_taskbar();
|
|
||||||
cleanup_panel();
|
cleanup_panel();
|
||||||
cleanup_config();
|
cleanup_config();
|
||||||
|
|
||||||
@@ -290,7 +273,7 @@ void cleanup()
|
|||||||
xsettings_client = NULL;
|
xsettings_client = NULL;
|
||||||
|
|
||||||
cleanup_server();
|
cleanup_server();
|
||||||
cleanup_timers();
|
cleanup_timeout();
|
||||||
|
|
||||||
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) {
|
||||||
size_t buf_size = strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
|
char *exec2 = calloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
|
||||||
(entry->icon ? strlen(entry->icon) : 1) + 100;
|
(entry->icon ? strlen(entry->icon) : 1) + 100,
|
||||||
char *exec2 = calloc(buf_size, 1);
|
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,30 +82,23 @@ 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) {
|
||||||
snprintf(q, buf_size, "--icon '%s'", entry->icon);
|
sprintf(q, "--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) {
|
||||||
snprintf(q, buf_size, "'%s'", entry->name);
|
sprintf(q, "'%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') {
|
||||||
snprintf(q, buf_size, "'%s'", path);
|
sprintf(q, "'%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') {
|
||||||
snprintf(q, buf_size, "%c%c", '%', *p);
|
sprintf(q, "%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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSList *icon_locations = NULL;
|
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,21 +74,6 @@ 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));
|
||||||
@@ -550,42 +535,41 @@ 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)
|
if (icon_name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
char *result = icon_path_from_full_path(icon_name);
|
// If the icon_name is already a path and the file exists, return it
|
||||||
if (result)
|
if (strstr(icon_name, "/") == icon_name) {
|
||||||
return result;
|
if (g_file_test(icon_name, G_FILE_TEST_EXISTS))
|
||||||
|
return strdup(icon_name);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const GSList *basenames = get_icon_locations();
|
const GSList *basenames = get_icon_locations();
|
||||||
const GSList *extensions = get_icon_extensions();
|
GSList *extensions = NULL;
|
||||||
|
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 worse when scaling up (for size 22, if you can choose 16 or 32, you're better with 32)
|
// otherwise the quality is usually crap (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
|
||||||
@@ -598,7 +582,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;
|
||||||
|
|
||||||
size_t file_name_size = 4096;
|
int 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)) {
|
||||||
@@ -623,7 +607,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 (const GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
for (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;
|
||||||
@@ -637,7 +621,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
|
||||||
snprintf(file_name, (size_t)file_name_size, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
sprintf(file_name, "%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)) {
|
||||||
@@ -678,10 +662,12 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,18 +676,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 (const GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
for (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;
|
||||||
size_t file_name_size2 = strlen(base_name) + strlen(icon_name) + strlen(extension) + 100;
|
file_name = calloc(strlen(base_name) + strlen(icon_name) + strlen(extension) + 100, 1);
|
||||||
file_name = calloc(file_name_size2, 1);
|
|
||||||
// filename = directory/iconname.extension
|
// filename = directory/iconname.extension
|
||||||
snprintf(file_name, file_name_size2, "%s/%s%s", base_name, icon_name, extension);
|
sprintf(file_name, "%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);
|
||||||
@@ -711,6 +697,7 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_slist_free(extensions);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-26
@@ -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 * panel->scale : 24;
|
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size : 24;
|
||||||
|
|
||||||
launcher->area.on_screen = TRUE;
|
launcher->area.on_screen = TRUE;
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
@@ -174,12 +174,11 @@ 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 * panel->scale);
|
(2 * launcher->area.paddingy);
|
||||||
if (launcher_max_icon_size)
|
if (launcher_max_icon_size > 0 && icon_size > launcher_max_icon_size)
|
||||||
icon_size = MIN(icon_size, launcher_max_icon_size * panel->scale);
|
icon_size = launcher_max_icon_size;
|
||||||
return icon_size;
|
return icon_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +189,6 @@ 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;
|
||||||
@@ -206,25 +204,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 * panel->scale;
|
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
*icons_per_column = (height + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
*icons_per_column = (height + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
||||||
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx) - *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 * panel->scale +
|
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
||||||
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx * panel->scale);
|
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx);
|
||||||
}
|
}
|
||||||
} 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 * panel->scale;
|
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
*icons_per_row = (width + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
*icons_per_row = (width + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
||||||
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx) - *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 * panel->scale +
|
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
||||||
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx * panel->scale);
|
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +239,6 @@ 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);
|
||||||
@@ -284,11 +281,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 * panel->scale + margin / 2;
|
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
||||||
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy * panel->scale + margin / 2;
|
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
||||||
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -303,17 +300,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 * panel->scale;
|
posy += launcher->icon_size + launcher->area.paddingx;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
posx += (launcher->icon_size + launcher->area.paddingx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % icons_per_row) {
|
if (i % icons_per_row) {
|
||||||
posx += launcher->icon_size + launcher->area.paddingx * panel->scale;
|
posx += launcher->icon_size + launcher->area.paddingx;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
posy += (launcher->icon_size + launcher->area.paddingx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -473,7 +470,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;
|
||||||
snprintf(launcherIcon->area.name, sizeof(launcherIcon->area.name), "LauncherIcon %d", index);
|
sprintf(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;
|
||||||
|
|||||||
+2
-2
@@ -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];
|
||||||
snprintf(path, sizeof(path), "tint2-%d-panel-%d-frame-%d.png", getpid(), i, frame);
|
sprintf(path, "tint2-%d-panel-%d-frame-%d.png", getpid(), i, frame);
|
||||||
save_panel_screenshot(&panels[i], path);
|
save_panel_screenshot(&panels[i], path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -748,7 +748,7 @@ void run_tint2_event_loop()
|
|||||||
|
|
||||||
// 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, &fds, 0, 0, get_duration_to_next_timer_expiration()) >= 0) {
|
if (XPending(server.display) > 0 || select(max_fd + 1, &fds, 0, 0, get_next_timeout()) >= 0) {
|
||||||
#ifdef HAVE_TRACING
|
#ifdef HAVE_TRACING
|
||||||
start_tracing((void*)run_tint2_event_loop);
|
start_tracing((void*)run_tint2_event_loop);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+14
-87
@@ -79,16 +79,11 @@ 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;
|
||||||
@@ -135,6 +130,8 @@ 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];
|
||||||
|
|
||||||
@@ -148,7 +145,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;
|
||||||
destroy_timer(&p->autohide_timer);
|
stop_timeout(p->autohide_timeout);
|
||||||
cleanup_freespace(p);
|
cleanup_freespace(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +207,6 @@ 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,
|
||||||
@@ -223,17 +219,6 @@ 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;
|
||||||
@@ -371,19 +356,6 @@ 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)
|
||||||
@@ -478,9 +450,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 * panel->scale;
|
taskbar->area.width = 2 * taskbar->area.paddingxlr;
|
||||||
else
|
else
|
||||||
taskbar->area.height = 2 * taskbar->area.paddingxlr * panel->scale;
|
taskbar->area.height = 2 * taskbar->area.paddingxlr;
|
||||||
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) {
|
||||||
@@ -497,9 +469,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 * panel->scale;
|
taskbar->area.width += taskbar->area.paddingx;
|
||||||
else
|
else
|
||||||
taskbar->area.height += taskbar->area.paddingy * panel->scale;
|
taskbar->area.height += taskbar->area.paddingy;
|
||||||
}
|
}
|
||||||
first_child = FALSE;
|
first_child = FALSE;
|
||||||
}
|
}
|
||||||
@@ -522,11 +494,9 @@ gboolean resize_panel(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distribute the remaining size between taskbars
|
// Distribute the remaining size between tasks
|
||||||
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)
|
||||||
@@ -543,49 +513,6 @@ 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++) {
|
||||||
@@ -1094,15 +1021,15 @@ Button *click_button(Panel *panel, int x, int y)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_autohide_timer(Panel *p)
|
void stop_autohide_timeout(Panel *p)
|
||||||
{
|
{
|
||||||
stop_timer(&p->autohide_timer);
|
stop_timeout(p->autohide_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void autohide_show(void *p)
|
void autohide_show(void *p)
|
||||||
{
|
{
|
||||||
Panel *panel = (Panel *)p;
|
Panel *panel = (Panel *)p;
|
||||||
stop_autohide_timer(panel);
|
stop_autohide_timeout(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);
|
||||||
@@ -1114,7 +1041,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_timer(panel);
|
stop_autohide_timeout(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
|
||||||
@@ -1126,7 +1053,7 @@ void autohide_trigger_show(Panel *p)
|
|||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
return;
|
return;
|
||||||
change_timer(&p->autohide_timer, true, panel_autohide_show_timeout, 0, autohide_show, p);
|
change_timeout(&p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void autohide_trigger_hide(Panel *p)
|
void autohide_trigger_hide(Panel *p)
|
||||||
@@ -1141,7 +1068,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_timer(&p->autohide_timer, true, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
change_timeout(&p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shrink_panel(Panel *panel)
|
void shrink_panel(Panel *panel)
|
||||||
|
|||||||
+1
-4
@@ -95,8 +95,6 @@ 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 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;
|
||||||
@@ -119,7 +117,6 @@ 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;
|
||||||
@@ -147,7 +144,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;
|
||||||
Timer autohide_timer;
|
timeout *autohide_timeout;
|
||||||
} Panel;
|
} Panel;
|
||||||
|
|
||||||
extern Panel panel_config;
|
extern Panel panel_config;
|
||||||
|
|||||||
@@ -115,33 +115,31 @@ 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 * panel->scale + left_right_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
||||||
else
|
else
|
||||||
return separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr + 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 * panel->scale + left_right_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.height - 2 * separator->area.paddingy * panel->scale - top_bottom_border_width(&separator->area);
|
separator->area.height - 2 * separator->area.paddingy - top_bottom_border_width(&separator->area);
|
||||||
} else {
|
} else {
|
||||||
separator->area.height =
|
separator->area.height =
|
||||||
separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr + top_bottom_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.width - 2 * separator->area.paddingy * panel->scale - left_right_border_width(&separator->area);
|
separator->area.width - 2 * separator->area.paddingy - left_right_border_width(&separator->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule_redraw(&separator->area);
|
schedule_redraw(&separator->area);
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xrandr.h>
|
|
||||||
#include <X11/extensions/Xrender.h>
|
#include <X11/extensions/Xrender.h>
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -311,21 +311,6 @@ 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)) {
|
||||||
@@ -354,22 +339,12 @@ 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);
|
||||||
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);
|
XRRFreeOutputInfo(output_info);
|
||||||
|
server.monitors[i_monitor].primary = crtc_info->outputs[j] == primary_output;
|
||||||
}
|
}
|
||||||
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
||||||
XRRFreeCrtcInfo(crtc_info);
|
XRRFreeCrtcInfo(crtc_info);
|
||||||
@@ -382,7 +357,6 @@ 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,7 +393,6 @@ 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,8 +523,7 @@ 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 /
|
// fprintf(stderr, "tint2: Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x / work_area_width);
|
||||||
//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));
|
||||||
@@ -107,7 +107,6 @@ 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;
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
#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>
|
||||||
@@ -36,7 +34,6 @@ void reset_signals()
|
|||||||
sigprocmask(SIG_SETMASK, &signal_set, NULL);
|
sigprocmask(SIG_SETMASK, &signal_set, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TINT2CONF
|
|
||||||
void init_signals()
|
void init_signals()
|
||||||
{
|
{
|
||||||
// Set signal handlers
|
// Set signal handlers
|
||||||
@@ -167,4 +164,3 @@ int get_signal_pending()
|
|||||||
{
|
{
|
||||||
return signal_pending;
|
return signal_pending;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
+57
-43
@@ -141,12 +141,11 @@ 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 * panel->scale;
|
MAX(left_right_border_width(&systray.area), top_bottom_border_width(&systray.area)) + 2 * systray.area.paddingy;
|
||||||
if (systray_max_icon_size > 0)
|
if (systray_max_icon_size > 0)
|
||||||
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size * panel->scale);
|
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size);
|
||||||
|
|
||||||
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) {
|
||||||
@@ -154,24 +153,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 * panel->scale;
|
int height = systray.area.height - top_bottom_border_width(&systray.area) - 2 * systray.area.paddingy;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
systray.icons_per_column = (height + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
systray.icons_per_column = (height + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx) - 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 * panel->scale +
|
*size = left_right_border_width(&systray.area) + 2 * systray.area.paddingxlr +
|
||||||
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx * panel->scale);
|
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx);
|
||||||
} else {
|
} else {
|
||||||
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy * panel->scale;
|
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
systray.icons_per_row = (width + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
systray.icons_per_row = (width + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx) - 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 * panel->scale) +
|
*size = top_bottom_border_width(&systray.area) + (2 * systray.area.paddingxlr) +
|
||||||
(systray.icon_size * systray.icons_per_column) +
|
(systray.icon_size * systray.icons_per_column) +
|
||||||
((systray.icons_per_column - 1) * systray.area.paddingx * panel->scale);
|
((systray.icons_per_column - 1) * systray.area.paddingx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,13 +281,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 * panel->scale + top_border_width(&systray.area) +
|
posy = start = top_border_width(&panel->area) + panel->area.paddingy + top_border_width(&systray.area) +
|
||||||
systray.area.paddingy * panel->scale + systray.margin / 2;
|
systray.area.paddingy + systray.margin / 2;
|
||||||
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&panel->area) + panel->area.paddingy * panel->scale + left_border_width(&systray.area) +
|
posx = start = left_border_width(&panel->area) + panel->area.paddingy + left_border_width(&systray.area) +
|
||||||
systray.area.paddingy * panel->scale + systray.margin / 2;
|
systray.area.paddingy + systray.margin / 2;
|
||||||
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrayWindow *traywin;
|
TrayWindow *traywin;
|
||||||
@@ -313,17 +312,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 * panel->scale;
|
posy += systray.icon_size + systray.area.paddingx;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (systray.icon_size + systray.area.paddingx * panel->scale);
|
posx += (systray.icon_size + systray.area.paddingx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % systray.icons_per_row) {
|
if (i % systray.icons_per_row) {
|
||||||
posx += systray.icon_size + systray.area.paddingx * panel->scale;
|
posx += systray.icon_size + systray.area.paddingx;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (systray.icon_size + systray.area.paddingx * panel->scale);
|
posy += (systray.icon_size + systray.area.paddingx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,8 +730,6 @@ 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);
|
||||||
@@ -943,8 +940,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);
|
||||||
destroy_timer(&traywin->render_timer);
|
stop_timeout(traywin->render_timeout);
|
||||||
destroy_timer(&traywin->resize_timer);
|
stop_timeout(traywin->resize_timeout);
|
||||||
free(traywin->name);
|
free(traywin->name);
|
||||||
if (traywin->image) {
|
if (traywin->image) {
|
||||||
imlib_context_set_image(traywin->image);
|
imlib_context_set_image(traywin->image);
|
||||||
@@ -1058,8 +1055,9 @@ 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_timer.enabled_)
|
if (!traywin->resize_timeout)
|
||||||
change_timer(&traywin->resize_timer, true, fast_resize_period, 0, systray_resize_icon, traywin);
|
traywin->resize_timeout =
|
||||||
|
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) {
|
||||||
@@ -1073,13 +1071,14 @@ 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_timer.enabled_)
|
if (!traywin->resize_timeout)
|
||||||
change_timer(&traywin->resize_timer, true, slow_resize_period, 0, systray_resize_icon, traywin);
|
traywin->resize_timeout =
|
||||||
|
add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Correct size
|
// Correct size
|
||||||
stop_timer(&traywin->resize_timer);
|
stop_timeout(traywin->resize_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize and redraw the systray
|
// Resize and redraw the systray
|
||||||
@@ -1136,8 +1135,9 @@ 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_timer.enabled_)
|
if (!traywin->resize_timeout)
|
||||||
change_timer(&traywin->resize_timer, true, fast_resize_period, 0, systray_resize_icon, traywin);
|
traywin->resize_timeout =
|
||||||
|
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,13 +1150,14 @@ 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_timer.enabled_)
|
if (!traywin->resize_timeout)
|
||||||
change_timer(&traywin->resize_timer, true, slow_resize_period, 0, systray_resize_icon, traywin);
|
traywin->resize_timeout =
|
||||||
|
add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Correct size
|
// Correct size
|
||||||
stop_timer(&traywin->resize_timer);
|
stop_timeout(traywin->resize_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize and redraw the systray
|
// Resize and redraw the systray
|
||||||
@@ -1223,7 +1224,8 @@ 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) {
|
||||||
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon_composited, traywin);
|
traywin->render_timeout =
|
||||||
|
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",
|
||||||
@@ -1242,7 +1244,8 @@ 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)
|
||||||
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon_composited, traywin);
|
traywin->render_timeout =
|
||||||
|
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",
|
||||||
@@ -1254,7 +1257,10 @@ void systray_render_icon_composited(void *t)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_timer(&traywin->render_timer);
|
if (traywin->render_timeout) {
|
||||||
|
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
|
||||||
@@ -1417,7 +1423,9 @@ void systray_render_icon(void *t)
|
|||||||
// __LINE__,
|
// __LINE__,
|
||||||
// traywin->win,
|
// traywin->win,
|
||||||
// traywin->name);
|
// traywin->name);
|
||||||
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
stop_timeout(traywin->render_timeout);
|
||||||
|
traywin->render_timeout =
|
||||||
|
add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1440,13 +1448,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)) {
|
||||||
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
stop_timeout(traywin->render_timeout);
|
||||||
|
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) {
|
||||||
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
stop_timeout(traywin->render_timeout);
|
||||||
|
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,
|
||||||
|
|||||||
@@ -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;
|
||||||
Timer render_timer;
|
timeout *render_timeout;
|
||||||
// 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;
|
||||||
Timer resize_timer;
|
timeout *resize_timeout;
|
||||||
// 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
|
||||||
|
|||||||
+16
-36
@@ -35,7 +35,7 @@
|
|||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
Timer urgent_timer;
|
timeout *urgent_timeout;
|
||||||
GSList *urgent_list;
|
GSList *urgent_list;
|
||||||
|
|
||||||
void task_dump_geometry(void *obj, int indent);
|
void task_dump_geometry(void *obj, int indent);
|
||||||
@@ -107,21 +107,6 @@ Task *add_task(Window win)
|
|||||||
(int)win,
|
(int)win,
|
||||||
task_template.title ? task_template.title : "null");
|
task_template.title ? task_template.title : "null");
|
||||||
|
|
||||||
// get application name
|
|
||||||
// use res_class property of WM_CLASS as res_name is easily overridable by user
|
|
||||||
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++) {
|
||||||
if (task_template.desktop != ALL_DESKTOPS && task_template.desktop != j)
|
if (task_template.desktop != ALL_DESKTOPS && task_template.desktop != j)
|
||||||
@@ -147,7 +132,6 @@ Task *add_task(Window 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;
|
||||||
task_instance->application = task_template.application;
|
|
||||||
if (panels[monitor].g_task.tooltip_enabled) {
|
if (panels[monitor].g_task.tooltip_enabled) {
|
||||||
task_instance->area._get_tooltip_text = task_get_tooltip;
|
task_instance->area._get_tooltip_text = task_get_tooltip;
|
||||||
task_instance->area._get_tooltip_image = task_get_thumbnail;
|
task_instance->area._get_tooltip_image = task_get_thumbnail;
|
||||||
@@ -224,14 +208,12 @@ void remove_task(Task *task)
|
|||||||
|
|
||||||
Window win = task->win;
|
Window win = task->win;
|
||||||
|
|
||||||
// free title, icon and application name just for the first task
|
// free title and icon 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
|
||||||
if (task->title)
|
if (task->title)
|
||||||
free(task->title);
|
free(task->title);
|
||||||
if (task->thumbnail)
|
if (task->thumbnail)
|
||||||
cairo_surface_destroy(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);
|
||||||
@@ -399,7 +381,7 @@ void task_update_icon(Task *task)
|
|||||||
task->icon[k] = adjust_icon(orig_image,
|
task->icon[k] = adjust_icon(orig_image,
|
||||||
panel->g_task.alpha[k],
|
panel->g_task.alpha[k],
|
||||||
panel->g_task.saturation[k],
|
panel->g_task.saturation[k],
|
||||||
panel->g_task.brightness[k]);
|
panel->g_task.brightness[k] != 0);
|
||||||
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,
|
||||||
@@ -447,7 +429,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 * panel->scale;
|
task->_icon_x = left_border_width(&task->area) + task->area.paddingxlr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
@@ -477,13 +459,11 @@ 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) {
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoLayout *layout = pango_cairo_create_layout(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 + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
pango_layout_set_width(layout, ((Taskbar *)task->area.parent)->text_width * 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);
|
||||||
@@ -500,7 +480,6 @@ void draw_task(void *obj, cairo_t *c)
|
|||||||
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);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
g_object_unref(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel->g_task.has_icon)
|
if (panel->g_task.has_icon)
|
||||||
@@ -553,7 +532,7 @@ 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) * panel->scale;
|
int size = panel_horizontal ? panel->g_task.maximum_width : panel->g_task.maximum_height;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,13 +652,12 @@ void task_refresh_thumbnail(Task *task)
|
|||||||
return;
|
return;
|
||||||
if (task->current_state == TASK_ICONIFIED)
|
if (task->current_state == TASK_ICONIFIED)
|
||||||
return;
|
return;
|
||||||
Panel *panel = (Panel*)task->area.panel;
|
|
||||||
double now = get_time();
|
double now = get_time();
|
||||||
if (now - task->thumbnail_last_update < 0.1)
|
if (now - task->thumbnail_last_update < 0.1)
|
||||||
return;
|
return;
|
||||||
if (debug_thumbnails)
|
if (debug_thumbnails)
|
||||||
fprintf(stderr, "tint2: thumbnail for window: %s" RESET "\n", task->title ? task->title : "");
|
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);
|
cairo_surface_t *thumbnail = get_window_thumbnail(task->win, panel_config.g_task.thumbnail_width);
|
||||||
if (!thumbnail)
|
if (!thumbnail)
|
||||||
return;
|
return;
|
||||||
if (task->thumbnail)
|
if (task->thumbnail)
|
||||||
@@ -776,8 +754,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);
|
||||||
@@ -804,8 +782,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_timer.enabled_)
|
if (!urgent_timeout)
|
||||||
change_timer(&urgent_timer, true, 10, 1000, blink_urgent, 0);
|
urgent_timeout = add_timeout(10, 1000, blink_urgent, 0, &urgent_timeout);
|
||||||
|
|
||||||
Panel *panel = task->area.panel;
|
Panel *panel = task->area.panel;
|
||||||
if (panel->is_hidden)
|
if (panel->is_hidden)
|
||||||
@@ -815,8 +793,10 @@ 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_timer(&urgent_timer);
|
stop_timeout(urgent_timeout);
|
||||||
|
urgent_timeout = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_handle_mouse_event(Task *task, MouseAction action)
|
void task_handle_mouse_event(Task *task, MouseAction action)
|
||||||
|
|||||||
+1
-2
@@ -68,7 +68,6 @@ typedef struct Task {
|
|||||||
Color icon_color_hover;
|
Color icon_color_hover;
|
||||||
Color icon_color_press;
|
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;
|
||||||
@@ -85,7 +84,7 @@ typedef struct Task {
|
|||||||
double thumbnail_last_update;
|
double thumbnail_last_update;
|
||||||
} Task;
|
} Task;
|
||||||
|
|
||||||
extern Timer urgent_timer;
|
extern timeout *urgent_timeout;
|
||||||
extern GSList *urgent_list;
|
extern GSList *urgent_list;
|
||||||
|
|
||||||
Task *add_task(Window win);
|
Task *add_task(Window win);
|
||||||
|
|||||||
+35
-48
@@ -47,9 +47,9 @@ 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 timeout *thumbnail_update_timer_all;
|
||||||
static Timer thumbnail_update_timer_active;
|
static timeout *thumbnail_update_timer_active;
|
||||||
static Timer thumbnail_update_timer_tooltip;
|
static timeout *thumbnail_update_timer_tooltip;
|
||||||
|
|
||||||
static GList *taskbar_task_orderings = NULL;
|
static GList *taskbar_task_orderings = NULL;
|
||||||
static GList *taskbar_thumbnail_jobs_done = NULL;
|
static GList *taskbar_thumbnail_jobs_done = NULL;
|
||||||
@@ -80,6 +80,7 @@ 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;
|
||||||
@@ -88,6 +89,9 @@ 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;
|
||||||
|
thumbnail_update_timer_all = NULL;
|
||||||
|
thumbnail_update_timer_active = NULL;
|
||||||
|
thumbnail_update_timer_tooltip = NULL;
|
||||||
taskbar_thumbnail_jobs_done = NULL;
|
taskbar_thumbnail_jobs_done = NULL;
|
||||||
taskbar_sort_method = TASKBAR_NOSORT;
|
taskbar_sort_method = TASKBAR_NOSORT;
|
||||||
taskbar_alignment = ALIGN_LEFT;
|
taskbar_alignment = ALIGN_LEFT;
|
||||||
@@ -130,9 +134,9 @@ void taskbar_save_orderings()
|
|||||||
|
|
||||||
void cleanup_taskbar()
|
void cleanup_taskbar()
|
||||||
{
|
{
|
||||||
destroy_timer(&thumbnail_update_timer_all);
|
stop_timeout(thumbnail_update_timer_all);
|
||||||
destroy_timer(&thumbnail_update_timer_active);
|
stop_timeout(thumbnail_update_timer_active);
|
||||||
destroy_timer(&thumbnail_update_timer_tooltip);
|
stop_timeout(thumbnail_update_timer_tooltip);
|
||||||
g_list_free(taskbar_thumbnail_jobs_done);
|
g_list_free(taskbar_thumbnail_jobs_done);
|
||||||
taskbar_save_orderings();
|
taskbar_save_orderings();
|
||||||
if (win_to_task) {
|
if (win_to_task) {
|
||||||
@@ -166,7 +170,7 @@ void cleanup_taskbar()
|
|||||||
g_slist_free(urgent_list);
|
g_slist_free(urgent_list);
|
||||||
urgent_list = NULL;
|
urgent_list = NULL;
|
||||||
|
|
||||||
destroy_timer(&urgent_timer);
|
stop_timeout(urgent_timeout);
|
||||||
|
|
||||||
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]);
|
||||||
@@ -180,11 +184,6 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -238,15 +237,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->scale;
|
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy;
|
||||||
panel->g_taskbar.area.height =
|
panel->g_taskbar.area.height =
|
||||||
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy;
|
||||||
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->scale;
|
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy;
|
||||||
panel->g_taskbar.area.width =
|
panel->g_taskbar.area.width =
|
||||||
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy;
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -304,19 +303,19 @@ 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->scale;
|
panel->g_taskbar.area.paddingy;
|
||||||
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 * panel->scale;
|
2 * panel->g_taskbar.area.paddingy;
|
||||||
} 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->scale;
|
panel->g_taskbar.area.paddingy;
|
||||||
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 * panel->scale;
|
2 * panel->g_taskbar.area.paddingy;
|
||||||
panel->g_task.area.height = panel->g_task.maximum_height * panel->scale;
|
panel->g_task.area.height = panel->g_task.maximum_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
||||||
@@ -333,8 +332,9 @@ void init_taskbar_panel(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute vertical position : text and icon
|
// compute vertical position : text and icon
|
||||||
int height, width;
|
int height_ink, 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,
|
||||||
@@ -343,19 +343,17 @@ void init_taskbar_panel(void *p)
|
|||||||
5,
|
5,
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_END,
|
PANGO_ELLIPSIZE_END,
|
||||||
panel->g_task.centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
FALSE);
|
||||||
FALSE,
|
|
||||||
panel->scale);
|
|
||||||
|
|
||||||
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_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr;
|
||||||
panel->g_task.text_height =
|
panel->g_task.text_height =
|
||||||
panel->g_task.area.height - (2 * panel->g_task.area.paddingy * panel->scale) - top_bottom_border_width(&panel->g_task.area);
|
panel->g_task.area.height - (2 * panel->g_task.area.paddingy) - 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->scale, panel->g_task.maximum_height * panel->scale),
|
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width, panel->g_task.maximum_height),
|
||||||
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 * panel->scale - MAX(left_right_border_width(&panel->g_task.area),
|
2 * panel->g_task.area.paddingy - 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->scale;
|
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx;
|
||||||
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,9 +384,8 @@ void taskbar_start_thumbnail_timer(ThumbnailUpdateMode mode)
|
|||||||
return;
|
return;
|
||||||
if (debug_thumbnails)
|
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");
|
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 :
|
change_timeout(mode == THUMB_MODE_ALL ? &thumbnail_update_timer_all :
|
||||||
mode == THUMB_MODE_ACTIVE_WINDOW ? &thumbnail_update_timer_active : &thumbnail_update_timer_tooltip,
|
mode == THUMB_MODE_ACTIVE_WINDOW ? &thumbnail_update_timer_active : &thumbnail_update_timer_tooltip,
|
||||||
true,
|
|
||||||
mode == THUMB_MODE_TOOLTIP_WINDOW ? 1000 : 500,
|
mode == THUMB_MODE_TOOLTIP_WINDOW ? 1000 : 500,
|
||||||
mode == THUMB_MODE_ALL ? 10 * 1000 : 0,
|
mode == THUMB_MODE_ALL ? 10 * 1000 : 0,
|
||||||
taskbar_update_thumbnails,
|
taskbar_update_thumbnails,
|
||||||
@@ -574,12 +571,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->scale;
|
panel->g_task.area.paddingxlr;
|
||||||
} else {
|
} else {
|
||||||
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height * panel->scale);
|
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height);
|
||||||
|
|
||||||
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy * panel->scale) - panel->g_task.text_posx -
|
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy) - panel->g_task.text_posx -
|
||||||
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr * panel->scale;
|
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -735,14 +732,6 @@ 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);
|
||||||
@@ -754,8 +743,6 @@ 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) {
|
||||||
@@ -857,7 +844,7 @@ void taskbar_update_thumbnails(void *arg)
|
|||||||
if (mode == THUMB_MODE_ALL) {
|
if (mode == THUMB_MODE_ALL) {
|
||||||
double now = get_time();
|
double now = get_time();
|
||||||
if (now - start_time > 0.030) {
|
if (now - start_time > 0.030) {
|
||||||
change_timer(&thumbnail_update_timer_all, true, 50, 10 * 1000, taskbar_update_thumbnails, arg);
|
change_timeout(&thumbnail_update_timer_all, 50, 10 * 1000, taskbar_update_thumbnails, arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -868,7 +855,7 @@ void taskbar_update_thumbnails(void *arg)
|
|||||||
if (taskbar_thumbnail_jobs_done) {
|
if (taskbar_thumbnail_jobs_done) {
|
||||||
g_list_free(taskbar_thumbnail_jobs_done);
|
g_list_free(taskbar_thumbnail_jobs_done);
|
||||||
taskbar_thumbnail_jobs_done = NULL;
|
taskbar_thumbnail_jobs_done = NULL;
|
||||||
change_timer(&thumbnail_update_timer_all, true, 10 * 1000, 10 * 1000, taskbar_update_thumbnails, arg);
|
change_timeout(&thumbnail_update_timer_all, 10 * 1000, 10 * 1000, taskbar_update_thumbnails, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ 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;
|
||||||
|
|||||||
@@ -134,8 +134,9 @@ 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;
|
int name_height, name_width, name_height_ink;
|
||||||
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,
|
||||||
@@ -144,14 +145,12 @@ 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,
|
||||||
PANGO_ALIGN_CENTER,
|
FALSE);
|
||||||
FALSE,
|
|
||||||
panel->scale);
|
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
return name_width + 2 * taskbar_name->area.paddingxlr * panel->scale + left_right_border_width(&taskbar_name->area);
|
return name_width + 2 * taskbar_name->area.paddingxlr + left_right_border_width(&taskbar_name->area);
|
||||||
} else {
|
} else {
|
||||||
return name_height + 2 * taskbar_name->area.paddingxlr * panel->scale + top_bottom_border_width(&taskbar_name->area);
|
return name_height + 2 * taskbar_name->area.paddingxlr + top_bottom_border_width(&taskbar_name->area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +161,9 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
|
|
||||||
schedule_redraw(&taskbar_name->area);
|
schedule_redraw(&taskbar_name->area);
|
||||||
|
|
||||||
int name_height, name_width;
|
int name_height, name_width, name_height_ink;
|
||||||
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,9 +172,7 @@ 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,
|
||||||
PANGO_ALIGN_CENTER,
|
FALSE);
|
||||||
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);
|
||||||
@@ -197,14 +195,11 @@ 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
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoLayout *layout = pango_cairo_create_layout(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);
|
||||||
@@ -218,7 +213,6 @@ void draw_taskbarname(void *obj, cairo_t *c)
|
|||||||
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);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
g_object_unref(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_desktop_names()
|
void update_desktop_names()
|
||||||
|
|||||||
@@ -20,16 +20,11 @@ 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
|
||||||
../util/server.c
|
../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
|
||||||
|
|||||||
@@ -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.%lld", filepath, (long long)time(NULL));
|
gchar *backup_path = g_strdup_printf("%s.backup.%ld", filepath, time(NULL));
|
||||||
copy_file(filepath, backup_path);
|
copy_file(filepath, backup_path);
|
||||||
g_free(backup_path);
|
g_free(backup_path);
|
||||||
}
|
}
|
||||||
|
|||||||
+428
-443
File diff suppressed because it is too large
Load Diff
+428
-443
File diff suppressed because it is too large
Load Diff
+428
-443
File diff suppressed because it is too large
Load Diff
+428
-443
File diff suppressed because it is too large
Load Diff
+428
-443
File diff suppressed because it is too large
Load Diff
+428
-443
File diff suppressed because it is too large
Load Diff
+428
-443
File diff suppressed because it is too large
Load Diff
+429
-442
File diff suppressed because it is too large
Load Diff
+15
-46
@@ -20,9 +20,7 @@
|
|||||||
#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,
|
||||||
@@ -182,7 +180,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.%lld", filepath, (long long)time(NULL));
|
gchar *backup_path = g_strdup_printf("%s.backup.%ld", filepath, time(NULL));
|
||||||
copy_file(filepath, backup_path);
|
copy_file(filepath, backup_path);
|
||||||
g_free(backup_path);
|
g_free(backup_path);
|
||||||
}
|
}
|
||||||
@@ -601,32 +599,6 @@ 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>"));
|
||||||
@@ -1284,8 +1256,7 @@ gboolean panel_contains(const char *value)
|
|||||||
|
|
||||||
char *get_panel_items()
|
char *get_panel_items()
|
||||||
{
|
{
|
||||||
size_t buf_size = 256;
|
char *result = calloc(1, 256 * sizeof(char));
|
||||||
char *result = calloc(buf_size, 1);
|
|
||||||
GtkTreeModel *model = GTK_TREE_MODEL(panel_items);
|
GtkTreeModel *model = GTK_TREE_MODEL(panel_items);
|
||||||
|
|
||||||
GtkTreeIter i;
|
GtkTreeIter i;
|
||||||
@@ -1296,7 +1267,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);
|
||||||
strlcat(result, v, buf_size);
|
strcat(result, v);
|
||||||
|
|
||||||
if (!gtk_tree_model_iter_next(model, &i)) {
|
if (!gtk_tree_model_iter_next(model, &i)) {
|
||||||
break;
|
break;
|
||||||
@@ -1341,19 +1312,19 @@ void set_panel_items(const char *items)
|
|||||||
} else if (v == ':') {
|
} else if (v == ':') {
|
||||||
separator_index++;
|
separator_index++;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
snprintf(buffer, sizeof(buffer), "%s %d", _("Separator"), separator_index + 1);
|
sprintf(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;
|
||||||
snprintf(buffer, sizeof(buffer), "%s %d", _("Executor"), execp_index + 1);
|
sprintf(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;
|
||||||
snprintf(buffer, sizeof(buffer), "%s %d", _("Button"), button_index + 1);
|
sprintf(buffer, "%s %d", _("Button"), button_index + 1);
|
||||||
name = buffer;
|
name = buffer;
|
||||||
value = "P";
|
value = "P";
|
||||||
} else {
|
} else {
|
||||||
@@ -2718,7 +2689,6 @@ 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"));
|
||||||
@@ -2729,7 +2699,6 @@ 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);
|
||||||
|
|
||||||
@@ -4128,7 +4097,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;
|
||||||
snprintf(separator->name, sizeof(separator->name), "%s %d", _("Separator"), i + 1);
|
sprintf(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);
|
||||||
@@ -4254,7 +4223,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;
|
||||||
snprintf(executor->name, sizeof(executor->name), "%s %d", _("Executor"), i + 1);
|
sprintf(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);
|
||||||
@@ -4675,7 +4644,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;
|
||||||
snprintf(button->name, sizeof(button->name), "%s %d", _("Button"), i + 1);
|
sprintf(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);
|
||||||
@@ -5064,7 +5033,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);
|
||||||
snprintf(separator->name, sizeof(separator->name), "%s %d", _("Separator"), i + 1);
|
sprintf(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5082,7 +5051,7 @@ void separator_update_indices()
|
|||||||
separator_index++;
|
separator_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
snprintf(buffer, sizeof(buffer), "%s %d", _("Separator"), separator_index + 1);
|
sprintf(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);
|
||||||
}
|
}
|
||||||
@@ -5096,7 +5065,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);
|
||||||
snprintf(executor->name, sizeof(executor->name), "%s %d", _("Executor"), i + 1);
|
sprintf(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5114,7 +5083,7 @@ void execp_update_indices()
|
|||||||
execp_index++;
|
execp_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
snprintf(buffer, sizeof(buffer), "%s %d", _("Executor"), execp_index + 1);
|
sprintf(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);
|
||||||
}
|
}
|
||||||
@@ -5128,7 +5097,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);
|
||||||
snprintf(button->name, sizeof(button->name), "%s %d", _("Button"), i + 1);
|
sprintf(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5146,7 +5115,7 @@ void button_update_indices()
|
|||||||
button_index++;
|
button_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
snprintf(buffer, sizeof(buffer), "%s %d", _("Button"), button_index + 1);
|
sprintf(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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#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,
|
||||||
|
|||||||
@@ -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;
|
||||||
strlcat(panel_items, "T", sizeof(panel_items));
|
strcat(panel_items, "T");
|
||||||
if (config_has_battery) {
|
if (config_has_battery) {
|
||||||
if (config_battery_enabled)
|
if (config_battery_enabled)
|
||||||
strlcat(panel_items, "B", sizeof(panel_items));
|
strcat(panel_items, "B");
|
||||||
} else {
|
} else {
|
||||||
if (no_items_battery_enabled)
|
if (no_items_battery_enabled)
|
||||||
strlcat(panel_items, "B", sizeof(panel_items));
|
strcat(panel_items, "B");
|
||||||
}
|
}
|
||||||
if (config_has_systray) {
|
if (config_has_systray) {
|
||||||
if (config_systray_enabled)
|
if (config_systray_enabled)
|
||||||
strlcat(panel_items, "S", sizeof(panel_items));
|
strcat(panel_items, "S");
|
||||||
} else {
|
} else {
|
||||||
if (no_items_systray_enabled)
|
if (no_items_systray_enabled)
|
||||||
strlcat(panel_items, "S", sizeof(panel_items));
|
strcat(panel_items, "S");
|
||||||
}
|
}
|
||||||
if (no_items_clock_enabled)
|
if (no_items_clock_enabled)
|
||||||
strlcat(panel_items, "C", sizeof(panel_items));
|
strcat(panel_items, "C");
|
||||||
set_panel_items(panel_items);
|
set_panel_items(panel_items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,13 +242,13 @@ void config_write_backgrounds(FILE *fp)
|
|||||||
char sides[10];
|
char sides[10];
|
||||||
sides[0] = '\0';
|
sides[0] = '\0';
|
||||||
if (sideTop)
|
if (sideTop)
|
||||||
strlcat(sides, "T", sizeof(sides));
|
strcat(sides, "T");
|
||||||
if (sideBottom)
|
if (sideBottom)
|
||||||
strlcat(sides, "B", sizeof(sides));
|
strcat(sides, "B");
|
||||||
if (sideLeft)
|
if (sideLeft)
|
||||||
strlcat(sides, "L", sizeof(sides));
|
strcat(sides, "L");
|
||||||
if (sideRight)
|
if (sideRight)
|
||||||
strlcat(sides, "R", sizeof(sides));
|
strcat(sides, "R");
|
||||||
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, "border_content_tint_weight = %d\n", (int)(border_weight));
|
||||||
@@ -378,13 +378,6 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,12 +450,10 @@ 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, "application");
|
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 3) {
|
|
||||||
fprintf(fp, "center");
|
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)) == 3) {
|
||||||
fprintf(fp, "mru");
|
fprintf(fp, "mru");
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 5) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 4) {
|
||||||
fprintf(fp, "lru");
|
fprintf(fp, "lru");
|
||||||
} else {
|
} else {
|
||||||
fprintf(fp, "none");
|
fprintf(fp, "none");
|
||||||
@@ -487,7 +478,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];
|
||||||
snprintf(full_name, sizeof(full_name), "task%s_font_color", name);
|
sprintf(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +489,7 @@ void config_write_task_icon_osb(FILE *fp,
|
|||||||
GtkWidget *widget_brightness)
|
GtkWidget *widget_brightness)
|
||||||
{
|
{
|
||||||
char full_name[128];
|
char full_name[128];
|
||||||
snprintf(full_name, sizeof(full_name), "task%s_icon_asb", name);
|
sprintf(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,
|
||||||
@@ -510,7 +501,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];
|
||||||
snprintf(full_name, sizeof(full_name), "task%s_background_id", name);
|
sprintf(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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,13 +1108,7 @@ 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, "scale_relative_to_dpi") == 0) {
|
if (strcmp(key, "gradient") == 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"))
|
||||||
@@ -1561,14 +1546,12 @@ 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, "application") == 0)
|
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 2);
|
|
||||||
else if (strcmp(value, "center") == 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), 2);
|
||||||
else if (strcmp(value, "mru") == 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), 3);
|
||||||
else if (strcmp(value, "lru") == 0)
|
else if (strcmp(value, "lru") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 5);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 4);
|
||||||
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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
strlcat(hash, ".png", sizeof(hash));
|
strcat(hash, ".png");
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
+28
-39
@@ -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_timer();
|
void start_show_timeout();
|
||||||
void start_hide_timer();
|
void start_hide_timeout();
|
||||||
void stop_tooltip_timer();
|
void stop_tooltip_timeout();
|
||||||
|
|
||||||
void tooltip_init_fonts();
|
void tooltip_init_fonts();
|
||||||
|
|
||||||
@@ -44,9 +44,6 @@ 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;
|
||||||
@@ -56,9 +53,8 @@ void default_tooltip()
|
|||||||
|
|
||||||
void cleanup_tooltip()
|
void cleanup_tooltip()
|
||||||
{
|
{
|
||||||
stop_tooltip_timer();
|
stop_tooltip_timeout();
|
||||||
destroy_timer(&g_tooltip.visibility_timer);
|
stop_timeout(g_tooltip.update_timeout);
|
||||||
destroy_timer(&g_tooltip.update_timer);
|
|
||||||
tooltip_hide(NULL);
|
tooltip_hide(NULL);
|
||||||
tooltip_update_contents_for(NULL);
|
tooltip_update_contents_for(NULL);
|
||||||
if (g_tooltip.window)
|
if (g_tooltip.window)
|
||||||
@@ -125,9 +121,9 @@ void tooltip_trigger_show(Area *area, Panel *p, XEvent *e)
|
|||||||
if (g_tooltip.mapped && g_tooltip.area != area) {
|
if (g_tooltip.mapped && g_tooltip.area != area) {
|
||||||
tooltip_update_contents_for(area);
|
tooltip_update_contents_for(area);
|
||||||
tooltip_update();
|
tooltip_update();
|
||||||
stop_tooltip_timer();
|
stop_tooltip_timeout();
|
||||||
} else if (!g_tooltip.mapped) {
|
} else if (!g_tooltip.mapped) {
|
||||||
start_show_timer();
|
start_show_timeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,9 +149,7 @@ void tooltip_update_geometry()
|
|||||||
|
|
||||||
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);
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoLayout *layout = pango_cairo_create_layout(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;
|
||||||
@@ -163,7 +157,7 @@ void tooltip_update_geometry()
|
|||||||
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
||||||
int max_width = MIN(r2.width * 5, 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) {
|
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 +
|
max_width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx +
|
||||||
cairo_image_surface_get_width(g_tooltip.image);
|
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);
|
||||||
@@ -171,12 +165,12 @@ void tooltip_update_geometry()
|
|||||||
pango_layout_set_text(layout, g_tooltip.tooltip_text ? g_tooltip.tooltip_text : "1234567890abcdef", -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 * panel->scale + r2.width;
|
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx + r2.width;
|
||||||
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy * panel->scale + r2.height;
|
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy + r2.height;
|
||||||
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
|
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 +
|
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx +
|
||||||
cairo_image_surface_get_width(g_tooltip.image);
|
cairo_image_surface_get_width(g_tooltip.image);
|
||||||
height += g_tooltip.paddingy * panel->scale + cairo_image_surface_get_height(g_tooltip.image);
|
height += g_tooltip.paddingy + cairo_image_surface_get_height(g_tooltip.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal && panel_position & BOTTOM)
|
if (panel_horizontal && panel_position & BOTTOM)
|
||||||
@@ -189,7 +183,6 @@ 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);
|
||||||
}
|
}
|
||||||
@@ -246,7 +239,6 @@ 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) {
|
||||||
@@ -281,9 +273,7 @@ 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);
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoLayout *layout = pango_cairo_create_layout(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);
|
||||||
@@ -295,16 +285,15 @@ 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 * panel->scale,
|
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
|
||||||
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy * panel->scale);
|
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy);
|
||||||
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) {
|
if (g_tooltip.image) {
|
||||||
cairo_translate(c,
|
cairo_translate(c,
|
||||||
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx * panel->scale,
|
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
|
||||||
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy * panel->scale - cairo_image_surface_get_height(g_tooltip.image));
|
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy - cairo_image_surface_get_height(g_tooltip.image));
|
||||||
cairo_set_source_surface(c, g_tooltip.image, 0, 0);
|
cairo_set_source_surface(c, g_tooltip.image, 0, 0);
|
||||||
cairo_paint(c);
|
cairo_paint(c);
|
||||||
}
|
}
|
||||||
@@ -317,10 +306,10 @@ void tooltip_trigger_hide()
|
|||||||
{
|
{
|
||||||
if (g_tooltip.mapped) {
|
if (g_tooltip.mapped) {
|
||||||
tooltip_update_contents_for(NULL);
|
tooltip_update_contents_for(NULL);
|
||||||
start_hide_timer();
|
start_hide_timeout();
|
||||||
} else {
|
} else {
|
||||||
// tooltip not visible yet, but maybe a timer is still pending
|
// tooltip not visible yet, but maybe a timeout is still pending
|
||||||
stop_tooltip_timer();
|
stop_tooltip_timeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,19 +323,19 @@ void tooltip_hide(void *arg)
|
|||||||
g_tooltip.area = NULL;
|
g_tooltip.area = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_show_timer()
|
void start_show_timeout()
|
||||||
{
|
{
|
||||||
change_timer(&g_tooltip.visibility_timer, true, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
change_timeout(&g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_hide_timer()
|
void start_hide_timeout()
|
||||||
{
|
{
|
||||||
change_timer(&g_tooltip.visibility_timer, true, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
change_timeout(&g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_tooltip_timer()
|
void stop_tooltip_timeout()
|
||||||
{
|
{
|
||||||
stop_timer(&g_tooltip.visibility_timer);
|
stop_timeout(g_tooltip.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tooltip_update_contents_timeout(void *arg)
|
void tooltip_update_contents_timeout(void *arg)
|
||||||
@@ -367,7 +356,7 @@ void tooltip_update_contents_for(Area *area)
|
|||||||
if (g_tooltip.image)
|
if (g_tooltip.image)
|
||||||
cairo_surface_reference(g_tooltip.image);
|
cairo_surface_reference(g_tooltip.image);
|
||||||
else
|
else
|
||||||
change_timer(&g_tooltip.update_timer, true, 300, 0, tooltip_update_contents_timeout, NULL);
|
change_timeout(&g_tooltip.update_timeout, 300, 0, tooltip_update_contents_timeout, NULL);
|
||||||
}
|
}
|
||||||
g_tooltip.area = area;
|
g_tooltip.area = area;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ typedef struct {
|
|||||||
PangoFontDescription *font_desc;
|
PangoFontDescription *font_desc;
|
||||||
Color font_color;
|
Color font_color;
|
||||||
Background *bg;
|
Background *bg;
|
||||||
Timer visibility_timer;
|
timeout *timeout;
|
||||||
Timer update_timer;
|
timeout *update_timeout;
|
||||||
cairo_surface_t *image;
|
cairo_surface_t *image;
|
||||||
} Tooltip;
|
} Tooltip;
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,8 @@ char *addr2name(void *func)
|
|||||||
free(strings);
|
free(strings);
|
||||||
return result;
|
return result;
|
||||||
#else
|
#else
|
||||||
const size_t buf_size = 32;
|
char *result = (char*) calloc(32, 1);
|
||||||
char *result = (char*) calloc(buf_size, 1);
|
sprintf(result, "%p", func);
|
||||||
snprintf(result, buf_size, "%p", func);
|
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
/* addr2line.c -- convert addresses to line number and function name
|
||||||
|
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||||
|
2007, 2009 Free Software Foundation, Inc.
|
||||||
|
Contributed by Ulrich Lauther <Ulrich.Lauther@mchp.siemens.de>
|
||||||
|
|
||||||
|
This file is part of GNU Binutils.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
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, 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
/* Derived from objdump.c and nm.c by Ulrich.Lauther@mchp.siemens.de */
|
||||||
|
|
||||||
|
#ifdef ENABLE_EXECINFO
|
||||||
|
|
||||||
|
#include <bfd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "addr2line.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
static bfd_boolean unwind_inlines = 1; /* -i, unwind inlined functions. */
|
||||||
|
static bfd_boolean with_addresses = 0; /* -a, show addresses. */
|
||||||
|
static bfd_boolean with_functions = 1; /* -f, show function names. */
|
||||||
|
static bfd_boolean do_demangle = 1; /* -C, demangle names. */
|
||||||
|
static bfd_boolean base_names = 1; /* -s, strip directory names. */
|
||||||
|
|
||||||
|
typedef struct Lookup {
|
||||||
|
char *exe_file_name;
|
||||||
|
void *address;
|
||||||
|
char *result;
|
||||||
|
bfd *abfd;
|
||||||
|
asymbol **syms;
|
||||||
|
bfd_vma pc;
|
||||||
|
const char *filename;
|
||||||
|
const char *functionname;
|
||||||
|
unsigned int line;
|
||||||
|
unsigned int discriminator;
|
||||||
|
bfd_boolean found;
|
||||||
|
} Lookup;
|
||||||
|
|
||||||
|
static asymbol **slurp_symtab(bfd *);
|
||||||
|
static void find_address_in_section(bfd *, asection *, void *unused);
|
||||||
|
static void translate_address(Lookup *lookup);
|
||||||
|
|
||||||
|
static asymbol **slurp_symtab(bfd *abfd)
|
||||||
|
{
|
||||||
|
if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
long storage = bfd_get_symtab_upper_bound(abfd);
|
||||||
|
bfd_boolean dynamic = FALSE;
|
||||||
|
if (storage == 0) {
|
||||||
|
storage = bfd_get_dynamic_symtab_upper_bound(abfd);
|
||||||
|
dynamic = TRUE;
|
||||||
|
}
|
||||||
|
if (storage < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
asymbol **syms = (asymbol **)malloc(storage);
|
||||||
|
long symcount;
|
||||||
|
if (dynamic)
|
||||||
|
symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
|
||||||
|
else
|
||||||
|
symcount = bfd_canonicalize_symtab(abfd, syms);
|
||||||
|
if (symcount < 0)
|
||||||
|
return syms;
|
||||||
|
|
||||||
|
// If there are no symbols left after canonicalization and
|
||||||
|
// we have not tried the dynamic symbols then give them a go.
|
||||||
|
if (symcount == 0 && !dynamic && (storage = bfd_get_dynamic_symtab_upper_bound(abfd)) > 0) {
|
||||||
|
free(syms);
|
||||||
|
syms = (asymbol **)malloc(storage);
|
||||||
|
symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
|
||||||
|
}
|
||||||
|
return syms;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void find_address_in_section(bfd *abfd, asection *section, void *unused)
|
||||||
|
{
|
||||||
|
Lookup *lookup = (Lookup *)abfd->usrdata;
|
||||||
|
|
||||||
|
bfd_vma vma;
|
||||||
|
bfd_size_type size;
|
||||||
|
|
||||||
|
if (lookup->found)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vma = bfd_get_section_vma(abfd, section);
|
||||||
|
if (lookup->pc < vma)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size = bfd_get_section_size(section);
|
||||||
|
if (lookup->pc >= vma + size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lookup->found = bfd_find_nearest_line_discriminator(abfd,
|
||||||
|
section,
|
||||||
|
lookup->syms,
|
||||||
|
lookup->pc - vma,
|
||||||
|
&lookup->filename,
|
||||||
|
&lookup->functionname,
|
||||||
|
&lookup->line,
|
||||||
|
&lookup->discriminator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void translate_address(Lookup *lookup)
|
||||||
|
{
|
||||||
|
Buffer *buffer = NULL;
|
||||||
|
lookup->pc = (bfd_vma)lookup->address;
|
||||||
|
|
||||||
|
if (with_addresses) {
|
||||||
|
char tmp[256];
|
||||||
|
bfd_sprintf_vma(lookup->abfd, tmp, lookup->pc);
|
||||||
|
buffer = buffer_printf(buffer, "0x%s: ", tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup->found = FALSE;
|
||||||
|
bfd_map_over_sections(lookup->abfd, find_address_in_section, NULL);
|
||||||
|
|
||||||
|
if (!lookup->found) {
|
||||||
|
if (with_functions)
|
||||||
|
buffer = buffer_printf(buffer, "?? ");
|
||||||
|
buffer = buffer_printf(buffer, "??:0");
|
||||||
|
} else {
|
||||||
|
while (1) {
|
||||||
|
if (with_functions) {
|
||||||
|
const char *name;
|
||||||
|
char *alloc = NULL;
|
||||||
|
|
||||||
|
name = lookup->functionname;
|
||||||
|
if (name == NULL || *name == '\0')
|
||||||
|
name = "??";
|
||||||
|
else if (do_demangle) {
|
||||||
|
alloc = bfd_demangle(lookup->abfd, name, 3);
|
||||||
|
if (alloc != NULL)
|
||||||
|
name = alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = buffer_printf(buffer, "%s", name);
|
||||||
|
buffer = buffer_printf(buffer, " at ");
|
||||||
|
|
||||||
|
if (alloc != NULL)
|
||||||
|
free(alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base_names && lookup->filename != NULL) {
|
||||||
|
const char *h = strrchr(lookup->filename, '/');
|
||||||
|
if (h != NULL)
|
||||||
|
lookup->filename = h + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = buffer_printf(buffer, "%s:", lookup->filename ? lookup->filename : "??");
|
||||||
|
if (lookup->line != 0) {
|
||||||
|
if (lookup->discriminator != 0)
|
||||||
|
buffer = buffer_printf(buffer, "%u (discriminator %u)", lookup->line, lookup->discriminator);
|
||||||
|
else
|
||||||
|
buffer = buffer_printf(buffer, "%u", lookup->line);
|
||||||
|
} else {
|
||||||
|
buffer = buffer_printf(buffer, "??");
|
||||||
|
}
|
||||||
|
if (!unwind_inlines)
|
||||||
|
lookup->found = FALSE;
|
||||||
|
else
|
||||||
|
lookup->found =
|
||||||
|
bfd_find_inliner_info(lookup->abfd, &lookup->filename, &lookup->functionname, &lookup->line);
|
||||||
|
if (!lookup->found)
|
||||||
|
break;
|
||||||
|
buffer = buffer_printf(buffer, " (inlined by) ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buffer)
|
||||||
|
lookup->result = buffer->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lookup *addr2line_init(const char *file_name)
|
||||||
|
{
|
||||||
|
bfd *abfd = bfd_openr(file_name, NULL);
|
||||||
|
if (abfd == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Decompress sections.
|
||||||
|
abfd->flags |= BFD_DECOMPRESS;
|
||||||
|
|
||||||
|
if (bfd_check_format(abfd, bfd_archive))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
char **matching = NULL;
|
||||||
|
if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
|
||||||
|
free(matching);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lookup *lookup = (Lookup *)calloc(1, sizeof(Lookup));
|
||||||
|
lookup->abfd = abfd;
|
||||||
|
lookup->abfd->usrdata = lookup;
|
||||||
|
lookup->syms = slurp_symtab(abfd);
|
||||||
|
lookup->exe_file_name = strdup(file_name);
|
||||||
|
return lookup;
|
||||||
|
|
||||||
|
err:
|
||||||
|
bfd_close(abfd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addr2line_destroy(Lookup *lookup)
|
||||||
|
{
|
||||||
|
free(lookup->syms);
|
||||||
|
bfd_close(lookup->abfd);
|
||||||
|
free(lookup->exe_file_name);
|
||||||
|
free(lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *addr2line_lookup(Lookup *lookup, void *address)
|
||||||
|
{
|
||||||
|
lookup->address = address;
|
||||||
|
lookup->result = NULL;
|
||||||
|
translate_address(lookup);
|
||||||
|
return lookup->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef ADDR2LINE
|
||||||
|
#define ADDR2LINE
|
||||||
|
|
||||||
|
#ifdef ENABLE_EXECINFO
|
||||||
|
|
||||||
|
typedef struct Lookup Lookup;
|
||||||
|
|
||||||
|
Lookup *addr2line_init(const char *file_name);
|
||||||
|
void addr2line_destroy(Lookup *lookup);
|
||||||
|
char *addr2line_lookup(Lookup *lookup, void *address);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
+17
-18
@@ -929,8 +929,10 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -939,6 +941,7 @@ void area_compute_text_geometry(Area *area,
|
|||||||
|
|
||||||
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,
|
||||||
@@ -947,14 +950,13 @@ 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,
|
||||||
PANGO_ALIGN_CENTER,
|
FALSE);
|
||||||
FALSE,
|
|
||||||
((Panel*)area->panel)->scale);
|
|
||||||
else
|
else
|
||||||
*line1_width = *line1_height = 0;
|
*line1_width = *line1_height_ink = *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,
|
||||||
@@ -963,11 +965,9 @@ 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,
|
||||||
PANGO_ALIGN_CENTER,
|
FALSE);
|
||||||
FALSE,
|
|
||||||
((Panel*)area->panel)->scale);
|
|
||||||
else
|
else
|
||||||
*line2_width = *line2_height = 0;
|
*line2_width = *line2_height_ink = *line2_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int text_area_compute_desired_size(Area *area,
|
int text_area_compute_desired_size(Area *area,
|
||||||
@@ -976,14 +976,16 @@ 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, line1_width, line2_height, line2_width;
|
int line1_height_ink, line1_height, line1_width, line2_height_ink, 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);
|
||||||
|
|
||||||
@@ -1008,15 +1010,17 @@ gboolean resize_text_area(Area *area,
|
|||||||
|
|
||||||
schedule_redraw(area);
|
schedule_redraw(area);
|
||||||
|
|
||||||
int line1_height, line1_width;
|
int line1_height_ink, line1_height, line1_width;
|
||||||
int line2_height, line2_width;
|
int line2_height_ink, 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);
|
||||||
|
|
||||||
@@ -1063,16 +1067,12 @@ 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 inner_w, inner_h;
|
int inner_w, inner_h;
|
||||||
area_compute_inner_size(area, &inner_w, &inner_h);
|
area_compute_inner_size(area, &inner_w, &inner_h);
|
||||||
|
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoLayout *layout = pango_cairo_create_layout(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);
|
||||||
@@ -1096,7 +1096,6 @@ void draw_text_area(Area *area,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
+3
-2
@@ -273,8 +273,10 @@ 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,
|
||||||
@@ -297,8 +299,7 @@ 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);
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#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
@@ -1,268 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#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
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#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
|
|
||||||
+69
-150
@@ -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>
|
||||||
@@ -48,10 +48,18 @@
|
|||||||
#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 "signals.h"
|
||||||
#include "bt.h"
|
|
||||||
|
|
||||||
void write_string(int fd, const char *s)
|
void write_string(int fd, const char *s)
|
||||||
{
|
{
|
||||||
@@ -75,13 +83,39 @@ void log_string(int fd, const char *s)
|
|||||||
|
|
||||||
void dump_backtrace(int log_fd)
|
void dump_backtrace(int log_fd)
|
||||||
{
|
{
|
||||||
struct backtrace bt;
|
#ifndef DISABLE_BACKTRACE
|
||||||
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++) {
|
|
||||||
log_string(log_fd, bt.frames[i].name);
|
#ifdef ENABLE_LIBUNWIND
|
||||||
|
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.
|
||||||
@@ -157,7 +191,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];
|
||||||
snprintf(s, sizeof(s), "SIG=%d: Unknown", sig);
|
sprintf(s, "SIG=%d: Unknown", sig);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +266,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];
|
||||||
snprintf(buf, sizeof(buf), "%d", value);
|
sprintf(buf, "%d", value);
|
||||||
return setenv(name, buf, 1);
|
return setenv(name, buf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,10 +461,9 @@ 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)) {
|
||||||
size_t buf_size = strlen(home) + strlen(s);
|
char *result = calloc(strlen(home) + strlen(s), 1);
|
||||||
char *result = calloc(buf_size, 1);
|
strcat(result, home);
|
||||||
strlcat(result, home, buf_size);
|
strcat(result, s + 1);
|
||||||
strlcat(result, s + 1, buf_size);
|
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return strdup(s);
|
return strdup(s);
|
||||||
@@ -443,16 +476,14 @@ char *contract_tilde(const char *s)
|
|||||||
if (!home)
|
if (!home)
|
||||||
return strdup(s);
|
return strdup(s);
|
||||||
|
|
||||||
size_t buf_size = strlen(home) + 2;
|
char *home_slash = calloc(strlen(home) + 2, 1);
|
||||||
char *home_slash = calloc(buf_size, 1);
|
strcat(home_slash, home);
|
||||||
strlcat(home_slash, home, buf_size);
|
strcat(home_slash, "/");
|
||||||
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)) {
|
||||||
size_t buf_size2 = strlen(s) - strlen(home) + 2;
|
char *result = calloc(strlen(s) - strlen(home) + 2, 1);
|
||||||
char *result = calloc(buf_size2, 1);
|
strcat(result, "~");
|
||||||
strlcat(result, "~", buf_size2);
|
strcat(result, s + strlen(home));
|
||||||
strlcat(result, s + strlen(home), buf_size2);
|
|
||||||
free(home_slash);
|
free(home_slash);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@@ -754,15 +785,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
|
||||||
image = imlib_load_image(path);
|
if (cached) {
|
||||||
|
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];
|
||||||
snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d-%lu.png", (int)getpid(), counter);
|
sprintf(tmp_filename, "/tmp/tint2-%d.png", (int)getpid());
|
||||||
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
|
||||||
@@ -784,17 +815,19 @@ Imlib_Image load_image(const char *path, int cached)
|
|||||||
// Parent
|
// Parent
|
||||||
close(fd);
|
close(fd);
|
||||||
waitpid(pid, 0, 0);
|
waitpid(pid, 0, 0);
|
||||||
image = imlib_load_image_immediately(tmp_filename);
|
image = imlib_load_image_immediately_without_cache(tmp_filename);
|
||||||
unlink(tmp_filename);
|
unlink(tmp_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
image = imlib_load_image(path);
|
if (cached) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,7 +921,8 @@ void clear_pixmap(Pixmap p, int x, int y, int w, int h)
|
|||||||
XRenderFreePicture(server.display, pict);
|
XRenderFreePicture(server.display, pict);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_text_size(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,
|
||||||
@@ -897,26 +931,20 @@ void get_text_size(const PangoFontDescription *font,
|
|||||||
int text_len,
|
int text_len,
|
||||||
PangoWrapMode wrap,
|
PangoWrapMode wrap,
|
||||||
PangoEllipsizeMode ellipsis,
|
PangoEllipsizeMode ellipsis,
|
||||||
PangoAlignment alignment,
|
gboolean markup)
|
||||||
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);
|
|
||||||
cairo_surface_t *cs =
|
cairo_surface_t *cs =
|
||||||
cairo_xlib_surface_create(server.display, pmap, server.visual, available_height, available_width);
|
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, available_height, available_width);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
|
|
||||||
PangoContext *context = pango_cairo_create_context(c);
|
PangoLayout *layout = pango_cairo_create_layout(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);
|
||||||
@@ -927,63 +955,14 @@ void get_text_size(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
@@ -1132,63 +1111,3 @@ void adjust_color(Color *color, int alpha, int saturation, int brightness)
|
|||||||
color->rgb[1] = g / 255.;
|
color->rgb[1] = g / 255.;
|
||||||
color->rgb[2] = b / 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();
|
|
||||||
}
|
|
||||||
|
|||||||
+8
-8
@@ -7,14 +7,17 @@
|
|||||||
#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"
|
|
||||||
#include "strlcat.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"
|
||||||
|
|
||||||
#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)
|
||||||
@@ -114,6 +117,7 @@ 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,
|
||||||
@@ -122,9 +126,7 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
int text_len,
|
int text_len,
|
||||||
PangoWrapMode wrap,
|
PangoWrapMode wrap,
|
||||||
PangoEllipsizeMode ellipsis,
|
PangoEllipsizeMode ellipsis,
|
||||||
PangoAlignment alignment,
|
gboolean markup);
|
||||||
gboolean markup,
|
|
||||||
double scale);
|
|
||||||
|
|
||||||
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
|
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
|
||||||
|
|
||||||
@@ -151,8 +153,6 @@ 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 get_image_mean_color(const Imlib_Image image, Color *mean_color);
|
||||||
|
|
||||||
void dump_image_data(const char *file_name, const char *name);
|
|
||||||
|
|
||||||
#define free_and_null(p) \
|
#define free_and_null(p) \
|
||||||
{ \
|
{ \
|
||||||
free(p); \
|
free(p); \
|
||||||
|
|||||||
+405
-265
@@ -1,331 +1,471 @@
|
|||||||
#define _GNU_SOURCE
|
#ifdef ENABLE_EXECINFO
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <endian.h>
|
#include <execinfo.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <stdc-predef.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <zlib.h>
|
||||||
#include <limits.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "bt.h"
|
#include "addr2line.h"
|
||||||
#include "bool.h"
|
#include "mem.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
#define UNUSED(x) ((void)x)
|
#ifndef RTLD_NEXT
|
||||||
|
# define RTLD_NEXT ((void *) -1l)
|
||||||
|
#endif
|
||||||
|
|
||||||
void ERR(const char *s)
|
#ifndef thread_local
|
||||||
|
# if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
|
||||||
|
# define thread_local _Thread_local
|
||||||
|
# elif defined _WIN32 && ( \
|
||||||
|
defined _MSC_VER || \
|
||||||
|
defined __ICL || \
|
||||||
|
defined __DMC__ || \
|
||||||
|
defined __BORLANDC__ )
|
||||||
|
# define thread_local __declspec(thread)
|
||||||
|
/* note that ICC (linux) and Clang are covered by __GNUC__ */
|
||||||
|
# elif defined __GNUC__ || \
|
||||||
|
defined __SUNPRO_C || \
|
||||||
|
defined __xlC__
|
||||||
|
# define thread_local __thread
|
||||||
|
# else
|
||||||
|
# error "Cannot define thread_local"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define get_caller() __builtin_extract_return_addr(__builtin_return_address(0))
|
||||||
|
|
||||||
|
#define size_t_mul_overflow(a, b) (a > 0 && b > SIZE_MAX / a)
|
||||||
|
|
||||||
|
typedef struct ListItem {
|
||||||
|
struct ListItem *next;
|
||||||
|
struct ListItem *prev;
|
||||||
|
void *data;
|
||||||
|
} ListItem;
|
||||||
|
|
||||||
|
typedef struct List {
|
||||||
|
ListItem *head;
|
||||||
|
ListItem *tail;
|
||||||
|
} List;
|
||||||
|
|
||||||
|
void list_append(List *list, void *data)
|
||||||
{
|
{
|
||||||
if (!s) {
|
ListItem *n = (ListItem*)calloc(1, sizeof(ListItem));
|
||||||
ERR("(null)");
|
n->data = data;
|
||||||
|
if (!list->tail) {
|
||||||
|
list->head = list->tail = n;
|
||||||
|
} else {
|
||||||
|
list->tail->next = n;
|
||||||
|
n->prev = list->tail;
|
||||||
|
list->tail = list->tail->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef size_t (*HashFunc)(void *data);
|
||||||
|
typedef int (*EqualFunc)(void *data1, void *data2);
|
||||||
|
typedef void *(*CopyFunc)(void *data);
|
||||||
|
|
||||||
|
typedef struct HashTable {
|
||||||
|
List *buckets;
|
||||||
|
size_t num_buckets;
|
||||||
|
size_t (*hash_func)(void *data);
|
||||||
|
int (*equal_func)(void *data1, void *data2);
|
||||||
|
void *(*copy_func)(void *data);
|
||||||
|
} HashTable;
|
||||||
|
|
||||||
|
size_t hash_void(void *data)
|
||||||
|
{
|
||||||
|
return (size_t)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int equal_void(void *data1, void *data2)
|
||||||
|
{
|
||||||
|
return data1 == data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *copy_void(void *data)
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash_table_init(HashTable *table, size_t num_buckets, HashFunc hash_func, EqualFunc equal_func, CopyFunc copy_func)
|
||||||
|
{
|
||||||
|
if (table->buckets)
|
||||||
return;
|
return;
|
||||||
}
|
if (num_buckets < 1)
|
||||||
ssize_t ret = write(STDERR_FILENO, s, strlen(s));
|
num_buckets = 4096;
|
||||||
UNUSED(ret);
|
table->num_buckets = num_buckets;
|
||||||
ret = fsync(STDERR_FILENO);
|
table->buckets = (List*)calloc(table->num_buckets, sizeof(List));
|
||||||
UNUSED(ret);
|
table->hash_func = hash_func ? hash_func : hash_void;
|
||||||
|
table->equal_func = equal_func ? equal_func : equal_void;
|
||||||
|
table->copy_func = copy_func ? copy_func : copy_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
void utoa(unsigned long n, char *s)
|
void *hash_table_add(HashTable *table, void *data)
|
||||||
{
|
{
|
||||||
if (n == 0) {
|
size_t hash = table->hash_func(data);
|
||||||
*s++ = '0';
|
size_t bucket = hash % table->num_buckets;
|
||||||
*s = 0;
|
for (ListItem *existing = table->buckets[bucket].head; existing; existing = existing->next) {
|
||||||
return;
|
if (table->equal_func(existing->data, data))
|
||||||
|
return existing->data;
|
||||||
}
|
}
|
||||||
char buffer[128] = {0};
|
list_append(&table->buckets[bucket], table->copy_func(data));
|
||||||
char *digit;
|
return data;
|
||||||
for (digit = buffer; n; digit++, n/=10) {
|
|
||||||
*digit = '0' + (n % 10);
|
|
||||||
}
|
|
||||||
digit--;
|
|
||||||
while (digit >= buffer) {
|
|
||||||
*s++ = *digit--;
|
|
||||||
}
|
|
||||||
*s = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long uabs(long n)
|
#define MAX_TRACE_SIZE 120
|
||||||
{
|
|
||||||
if (n == LONG_MIN)
|
typedef struct Trace {
|
||||||
return ((unsigned long)LONG_MAX) + 1;
|
void *entries[MAX_TRACE_SIZE+8];
|
||||||
return (unsigned long)labs(n);
|
size_t id;
|
||||||
}
|
} Trace;
|
||||||
|
|
||||||
void itoa(long n, char *s)
|
#define LARGE_THRESH (10 * 1024 * 1024)
|
||||||
{
|
|
||||||
if (n < 0) {
|
static void *(*calloc_original)(size_t count, size_t size) = NULL;
|
||||||
*s++ = '-';
|
static void *(*realloc_original)(void *p, size_t size) = NULL;
|
||||||
}
|
static void *(*malloc_original)(size_t size) = NULL;
|
||||||
utoa(uabs(n), s);
|
static void *(*free_original)(void *p) = NULL;
|
||||||
}
|
static gzFile mem_log = NULL;
|
||||||
|
static pid_t mem_log_owner = 0;
|
||||||
__attribute__((noreturn))
|
pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static void crash(char *file, int line, char *msg)
|
|
||||||
{
|
static HashTable traces;
|
||||||
ERR(file);
|
static size_t next_trace_id = 0;
|
||||||
ERR(":");
|
pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
char buf[256];
|
|
||||||
itoa(line, buf);
|
static HashTable addr2lines;
|
||||||
ERR(buf);
|
pthread_mutex_t addr2lines_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
ERR(" ");
|
|
||||||
ERR(msg);
|
thread_local int paused = 0;
|
||||||
_exit(1);
|
|
||||||
}
|
static double get_unix_time()
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
if (gettimeofday(&tv, NULL) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
return tv.tv_sec + 1.0e-6 * tv.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_func_or_crash(void **result, const char *name)
|
__attribute__ ((noinline))
|
||||||
|
static void get_backtrace(Trace *trace) {
|
||||||
|
int size = backtrace(trace->entries, MAX_TRACE_SIZE);
|
||||||
|
trace->entries[size] = NULL;
|
||||||
|
for (void **p = trace->entries; *p; p++) {
|
||||||
|
*p = *(p+2);
|
||||||
|
}
|
||||||
|
trace->id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int trace_size(Trace *trace)
|
||||||
{
|
{
|
||||||
static int inside_loader = 0;
|
int size = 0;
|
||||||
if (inside_loader) {
|
for (void **p = trace->entries; *p; p++) {
|
||||||
*result = (void*)return_null;
|
size++;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fd = -1;
|
typedef struct FilenameLookup {
|
||||||
static u_int64_t tstart = 0;
|
char *file_name;
|
||||||
static bool stop_alloc_log = false;
|
Lookup *lookup;
|
||||||
|
} FilenameLookup;
|
||||||
|
|
||||||
static void write_char(char c)
|
size_t hash_lookup(void *data)
|
||||||
{
|
{
|
||||||
static char buffer[4096] = {0};
|
FilenameLookup *lookup = (FilenameLookup *)data;
|
||||||
static size_t count = 0;
|
size_t seed = 14695981039346656037ULL;
|
||||||
if (c) {
|
size_t hash = seed;
|
||||||
buffer[count++] = c;
|
for (char *p = lookup->file_name; *p; p++) {
|
||||||
}
|
hash = (hash ^ (size_t)(*p)) * 1099511628211ULL;
|
||||||
if (!count)
|
|
||||||
return;
|
|
||||||
if (c == '\n' || c == 0 || count >= sizeof(buffer)) {
|
|
||||||
ssize_t ret = write(fd, buffer, count);
|
|
||||||
ASSERT(ret > 0);
|
|
||||||
count = 0;
|
|
||||||
}
|
}
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_string(const char *s)
|
int equal_lookup(void *data1, void *data2)
|
||||||
{
|
{
|
||||||
for (; *s; s++)
|
FilenameLookup *lookup1 = (FilenameLookup *)data1;
|
||||||
write_char(*s);
|
FilenameLookup *lookup2 = (FilenameLookup *)data2;
|
||||||
|
return strcmp(lookup1->file_name, lookup2->file_name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_word(const char *s)
|
char *resolve_symbol(char *file_name, void *address)
|
||||||
{
|
{
|
||||||
write_string(s);
|
FilenameLookup *lookup = (FilenameLookup *)calloc(1, sizeof(FilenameLookup));
|
||||||
write_string(" ");
|
lookup->file_name = strdup(file_name);
|
||||||
}
|
|
||||||
|
|
||||||
static char hex(u_int8_t value)
|
pthread_mutex_lock(&addr2lines_mutex);
|
||||||
{
|
hash_table_init(&addr2lines, 0, hash_lookup, equal_lookup, NULL);
|
||||||
if (value < 10)
|
FilenameLookup *existing = (FilenameLookup *)hash_table_add(&addr2lines, lookup);
|
||||||
return '0' + (char)value;
|
if (existing == lookup) {
|
||||||
return 'a' + (char)(value - 10);
|
lookup->lookup = addr2line_init(lookup->file_name);
|
||||||
|
} else {
|
||||||
|
free(lookup->file_name);
|
||||||
|
free(lookup);
|
||||||
}
|
}
|
||||||
|
char *result = addr2line_lookup(existing->lookup, address);
|
||||||
static void write_hex(u_int64_t v)
|
pthread_mutex_unlock(&addr2lines_mutex);
|
||||||
{
|
|
||||||
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_alloc_init(u_int64_t t)
|
char *backtrace_to_string(Trace *trace)
|
||||||
{
|
{
|
||||||
if (stop_alloc_log)
|
int size = trace_size(trace);
|
||||||
return;
|
char **strings = backtrace_symbols(trace->entries, size);
|
||||||
if (fd == -1) {
|
if (!strings)
|
||||||
int pfd[2] = {-1, -1};
|
return NULL;
|
||||||
ASSERT_OK(pipe(pfd));
|
Buffer *buffer = NULL;
|
||||||
pid_t child = fork();
|
buffer = buffer_printf(buffer, "t %lu ", trace->id);
|
||||||
ASSERT_PID(child);
|
for (int i = 0; i < size; i++) {
|
||||||
if (child == 0) {
|
buffer = buffer_printf(buffer, "%s", strings[i]);
|
||||||
// child
|
// /lib/x86_64-linux-gnu/libglib-2.0.so.0(g_realloc+0xf) [0x7efda85c96af]
|
||||||
close(pfd[1]);
|
char *func_start = strstr(strings[i], "(");
|
||||||
ASSERT_FD(dup2(pfd[0], STDIN_FILENO));
|
if (func_start) {
|
||||||
ASSERT_OK(close(pfd[0]));
|
*func_start = 0;
|
||||||
int out = open("mem.log.gz", O_APPEND | O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0600);
|
char *file_name = strings[i];
|
||||||
ASSERT_FD(out);
|
char *resolved = resolve_symbol(file_name, trace->entries[i]);
|
||||||
ASSERT_FD(dup2(out, STDOUT_FILENO));
|
if (resolved) {
|
||||||
sigset_t mask;
|
buffer = buffer_printf(buffer, " %s", resolved);
|
||||||
sigfillset(&mask);
|
free(resolved);
|
||||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
}
|
||||||
ASSERT_OK(execlp("gzip", "gzip", "-c", NULL));
|
}
|
||||||
_exit(1);
|
buffer = buffer_printf(buffer, "|");
|
||||||
|
}
|
||||||
|
free(strings);
|
||||||
|
buffer = buffer_printf(buffer, "\n");
|
||||||
|
return buffer->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t hash_trace(Trace *trace)
|
||||||
|
{
|
||||||
|
size_t seed = 14695981039346656037ULL;
|
||||||
|
size_t hash = seed;
|
||||||
|
for (void **p = trace->entries; *p; p++) {
|
||||||
|
hash = (hash ^ (size_t)(*p)) * 1099511628211ULL;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int equal_traces(Trace *a, Trace *b)
|
||||||
|
{
|
||||||
|
void **pa, **pb;
|
||||||
|
for (pa = a->entries, pb = b->entries; *pa && *pb; pa++, pb++) {
|
||||||
|
if (*pa != *pb)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (*pa || *pb)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Trace *copy_trace(Trace *trace)
|
||||||
|
{
|
||||||
|
Trace *result = (Trace*)calloc(1, sizeof(Trace));
|
||||||
|
*result = *trace;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int trace_assign_id(Trace *trace)
|
||||||
|
{
|
||||||
|
int created = 0;
|
||||||
|
pthread_mutex_lock(&trace_mutex);
|
||||||
|
hash_table_init(&traces, 1024 * 1024, (HashFunc)hash_trace, (EqualFunc)equal_traces, (CopyFunc)copy_trace);
|
||||||
|
trace->id = 0;
|
||||||
|
Trace *existing = (Trace*)hash_table_add(&traces, trace);
|
||||||
|
if (!existing->id) {
|
||||||
|
next_trace_id++;
|
||||||
|
existing->id = trace->id = next_trace_id;
|
||||||
|
created = 1;
|
||||||
} else {
|
} else {
|
||||||
// parent
|
trace->id = existing->id;
|
||||||
close(pfd[0]);
|
|
||||||
fd = pfd[1];
|
|
||||||
}
|
|
||||||
atexit(log_alloc_finish);
|
|
||||||
tstart = t;
|
|
||||||
write_string("# function time_ms result ptr size count backtrace\n");
|
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&trace_mutex);
|
||||||
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_alloc_locked(const char *func_name, void *result, void *ptr, size_t size, size_t count)
|
static void log_flush();
|
||||||
|
|
||||||
|
static void log_init()
|
||||||
{
|
{
|
||||||
if (stop_alloc_log)
|
char path[256];
|
||||||
return;
|
sprintf(path, "/tmp/tint2.%lu.memtrace", (size_t)getpid());
|
||||||
u_int64_t t = current_time_ms();
|
pthread_mutex_lock(&log_mutex);
|
||||||
if (fd == -1)
|
if (!mem_log) {
|
||||||
log_alloc_init(t);
|
mem_log = gzopen(path, "w");
|
||||||
if (fd == -1)
|
mem_log_owner = getpid();
|
||||||
return;
|
atexit(log_flush);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&log_mutex);
|
||||||
|
if (mem_log)
|
||||||
|
fprintf(stderr, "Writing memory log to %s\n", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pid = -1;
|
static void log_write(char *buffer)
|
||||||
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;
|
if (mem_log) {
|
||||||
static pthread_mutex_t mutex_recursive;
|
pthread_mutex_lock(&log_mutex);
|
||||||
static pthread_mutex_t mutex_nonrecursive = PTHREAD_MUTEX_INITIALIZER;
|
if (getpid() == mem_log_owner)
|
||||||
static bool mutexes_initialized = false;
|
gzwrite(mem_log, buffer, (unsigned)strlen(buffer));
|
||||||
|
pthread_mutex_unlock(&log_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&mutex_global);
|
static void log_flush()
|
||||||
{
|
{
|
||||||
if (!mutexes_initialized) {
|
if (mem_log) {
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutex_lock(&log_mutex);
|
||||||
pthread_mutexattr_init(&attr);
|
if (getpid() == mem_log_owner)
|
||||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
gzflush(mem_log, Z_SYNC_FLUSH);
|
||||||
pthread_mutex_init(&mutex_recursive, &attr);
|
pthread_mutex_unlock(&log_mutex);
|
||||||
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()
|
static void malloc_profile_load_pointers()
|
||||||
{
|
{
|
||||||
log_alloc(0, 0, 0, 0, 0);
|
realloc_original = dlsym(RTLD_NEXT, "realloc");
|
||||||
|
malloc_original = dlsym(RTLD_NEXT, "malloc");
|
||||||
|
calloc_original = dlsym(RTLD_NEXT, "calloc");
|
||||||
|
free_original = dlsym(RTLD_NEXT, "free");
|
||||||
|
int trace_mem = getenv("TRACE_MEM") != NULL;
|
||||||
|
if (trace_mem)
|
||||||
|
log_init();
|
||||||
|
else
|
||||||
|
paused = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *calloc(size_t count, size_t size)
|
||||||
|
{
|
||||||
|
if (paused)
|
||||||
|
return calloc_original ? calloc_original(count, size) : 0;
|
||||||
|
paused = 1;
|
||||||
|
if (!calloc_original) {
|
||||||
|
malloc_profile_load_pointers();
|
||||||
|
if (!calloc_original)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *result = calloc_original(count, size);
|
||||||
|
if (mem_log) {
|
||||||
|
Trace trace;
|
||||||
|
get_backtrace(&trace);
|
||||||
|
int created = trace_assign_id(&trace);
|
||||||
|
if (created) {
|
||||||
|
char *str = backtrace_to_string(&trace);
|
||||||
|
if (str) {
|
||||||
|
log_write(str);
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char buffer[1024];
|
||||||
|
sprintf(buffer, "[%f] t %lu : %p = c %lu %lu\n", get_unix_time(), trace.id, result, count, size);
|
||||||
|
log_write(buffer);
|
||||||
|
if (size_t_mul_overflow(count, size) || (count * size) > LARGE_THRESH)
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
|
paused = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *realloc(void *p, size_t size)
|
||||||
|
{
|
||||||
|
if (paused)
|
||||||
|
return realloc_original ? realloc_original(p, size) : 0;
|
||||||
|
paused = 1;
|
||||||
|
if (!realloc_original) {
|
||||||
|
malloc_profile_load_pointers();
|
||||||
|
if (!realloc_original)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *result = realloc_original(p, size);
|
||||||
|
if (mem_log) {
|
||||||
|
Trace trace;
|
||||||
|
get_backtrace(&trace);
|
||||||
|
int created = trace_assign_id(&trace);
|
||||||
|
if (created) {
|
||||||
|
char *str = backtrace_to_string(&trace);
|
||||||
|
if (str) {
|
||||||
|
log_write(str);
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char buffer[1024];
|
||||||
|
sprintf(buffer, "[%f] t %lu : %p = r %p %lu\n", get_unix_time(), trace.id, result, p, size);
|
||||||
|
log_write(buffer);
|
||||||
|
if (size > LARGE_THRESH)
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
|
paused = 0;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *malloc(size_t size)
|
void *malloc(size_t size)
|
||||||
{
|
{
|
||||||
static void *(*original)(size_t size) = 0;
|
if (paused)
|
||||||
load_func_or_crash((void *)&original, __FUNCTION__);
|
return malloc_original ? malloc_original(size) : 0;
|
||||||
void *result = original(size);
|
paused = 1;
|
||||||
log_alloc(__FUNCTION__, result, 0, size, 0);
|
if (!malloc_original) {
|
||||||
|
malloc_profile_load_pointers();
|
||||||
|
if (!malloc_original)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *result = malloc_original(size);
|
||||||
|
if (mem_log) {
|
||||||
|
Trace trace;
|
||||||
|
get_backtrace(&trace);
|
||||||
|
int created = trace_assign_id(&trace);
|
||||||
|
if (created) {
|
||||||
|
char *str = backtrace_to_string(&trace);
|
||||||
|
if (str) {
|
||||||
|
log_write(str);
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char buffer[1024];
|
||||||
|
sprintf(buffer, "[%f] t %lu : %p = m %lu\n", get_unix_time(), trace.id, result, size);
|
||||||
|
log_write(buffer);
|
||||||
|
if (size > LARGE_THRESH)
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
|
paused = 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *realloc(void *ptr, size_t size)
|
void free(void *p)
|
||||||
{
|
{
|
||||||
static void *(*original)(void *p, size_t size) = 0;
|
if (paused) {
|
||||||
load_func_or_crash((void *)&original, __FUNCTION__);
|
if (free_original)
|
||||||
void *result = original(ptr, size);
|
free_original(p);
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
original(ptr);
|
paused = 1;
|
||||||
log_alloc(__FUNCTION__, 0, ptr, 0, 0);
|
if (!free_original) {
|
||||||
|
malloc_profile_load_pointers();
|
||||||
|
if (!free_original)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
free_original(p);
|
||||||
|
if (mem_log) {
|
||||||
|
Trace trace;
|
||||||
|
get_backtrace(&trace);
|
||||||
|
int created = trace_assign_id(&trace);
|
||||||
|
if (created) {
|
||||||
|
char *str = backtrace_to_string(&trace);
|
||||||
|
if (str) {
|
||||||
|
log_write(str);
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char buffer[1024];
|
||||||
|
sprintf(buffer, "[%f] t %lu : 0 = f %p\n", get_unix_time(), trace.id, p);
|
||||||
|
log_write(buffer);
|
||||||
|
}
|
||||||
|
paused = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef MEM_H
|
||||||
|
#define MEM_H
|
||||||
|
|
||||||
|
#endif
|
||||||
+28
-71
@@ -1,83 +1,40 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
int print_uchar(unsigned char v)
|
Buffer *vbuffer_printf(Buffer *buffer, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
return printf("%u", v);
|
va_list ap1;
|
||||||
|
va_copy(ap1, ap);
|
||||||
|
int ret = vsnprintf(NULL, 0, fmt, ap1) + 1;
|
||||||
|
va_end(ap1);
|
||||||
|
if (ret < 1)
|
||||||
|
return buffer;
|
||||||
|
|
||||||
|
size_t size = (size_t)ret;
|
||||||
|
if (!buffer)
|
||||||
|
buffer = (Buffer*)calloc(1, sizeof(Buffer));
|
||||||
|
if (!buffer->data) {
|
||||||
|
buffer->size = 2 * size + 128;
|
||||||
|
buffer->data = (char*) calloc(buffer->size, 1);
|
||||||
|
} else if (strlen(buffer->data) + size >= buffer->size + 1) {
|
||||||
|
buffer->size = 2 * (size + buffer->size) + 128;
|
||||||
|
buffer->data = (char*) realloc(buffer->data, buffer->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_char(char v)
|
vsnprintf(buffer->data + strlen(buffer->data), size, fmt, ap);
|
||||||
{
|
return buffer;
|
||||||
return printf("%c", v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_short(short v)
|
Buffer *buffer_printf(Buffer *buffer, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
return printf("%d", v);
|
va_list ap;
|
||||||
}
|
|
||||||
|
|
||||||
int print_ushort(unsigned short v)
|
va_start(ap, fmt);
|
||||||
{
|
buffer = vbuffer_printf(buffer, fmt, ap);
|
||||||
return printf("%u", v);
|
va_end(ap);
|
||||||
}
|
|
||||||
|
|
||||||
int print_int(int v)
|
return buffer;
|
||||||
{
|
|
||||||
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)");
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-54
@@ -1,61 +1,16 @@
|
|||||||
#ifndef PRINT_H
|
#ifndef PRINT_H
|
||||||
#define PRINT_H
|
#define PRINT_H
|
||||||
|
|
||||||
#ifdef HAS_GENERIC
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
int print_uchar(unsigned char v);
|
typedef struct Buffer {
|
||||||
|
char *data;
|
||||||
|
size_t size;
|
||||||
|
} Buffer;
|
||||||
|
|
||||||
int print_char(char v);
|
Buffer *vbuffer_printf(Buffer *buffer, const char *fmt, va_list ap);
|
||||||
|
Buffer *buffer_printf(Buffer *buffer, const char *fmt, ...);
|
||||||
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
|
#endif
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
/* $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 */
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#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
@@ -1,183 +0,0 @@
|
|||||||
#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
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#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
|
|
||||||
+386
-1611
File diff suppressed because it is too large
Load Diff
+28
-36
@@ -21,52 +21,45 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "bool.h"
|
|
||||||
|
|
||||||
extern bool debug_timers;
|
// Single shot timers (i.e. timers with interval_msec == 0) are deleted automatically as soon as they expire,
|
||||||
|
// i.e. you do not need to stop them, however it is safe to call stop_timeout for these 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 void TimerCallback(void *arg);
|
typedef struct _timeout timeout;
|
||||||
|
|
||||||
typedef struct {
|
// Initializes default global data.
|
||||||
char name_[64];
|
void default_timeout();
|
||||||
bool enabled_;
|
|
||||||
long long expiration_time_ms_;
|
|
||||||
int period_ms_;
|
|
||||||
TimerCallback *callback_;
|
|
||||||
void *arg_;
|
|
||||||
bool handled_;
|
|
||||||
} Timer;
|
|
||||||
|
|
||||||
#define DEFAULT_TIMER {"", 0, 0, 0, 0, 0, 0}
|
// Cleans up: stops all timers and frees memory.
|
||||||
|
void cleanup_timeout();
|
||||||
|
|
||||||
#define INIT_TIMER(t) init_timer(&t, #t)
|
// Installs a timer with the first timeout after 'value_msec' and then an optional periodic timeout every
|
||||||
|
// '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);
|
||||||
|
|
||||||
// Initialize the timer module.
|
// Changes timer 't'. If it does not exist, a new timer is created, with self set to 't'.
|
||||||
void default_timers();
|
void change_timeout(timeout **t, int value_msec, int interval_msec, void (*_callback)(void *), void *arg);
|
||||||
|
|
||||||
// Destroy the timer module.
|
// Stops the timer 't'
|
||||||
void cleanup_timers();
|
void stop_timeout(timeout *t);
|
||||||
|
|
||||||
// Initialize a timer. Caller keeps ownership.
|
// Get the time when the next installed timer will expire, or NULL if there is no timer.
|
||||||
void init_timer(Timer *timer, const char *name);
|
// Do not free the pointer; but it is safe to change its contents.
|
||||||
|
struct timeval *get_next_timeout();
|
||||||
|
|
||||||
// Destroy a timer. Does not free() the pointer.
|
// Callback of all expired timeouts
|
||||||
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);
|
||||||
|
|
||||||
@@ -76,7 +69,6 @@ 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
|
||||||
|
|||||||
Executable
+165
@@ -0,0 +1,165 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
|
import gzip
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def commas(v):
|
||||||
|
return "{:12,}".format(v)
|
||||||
|
|
||||||
|
|
||||||
|
class Event:
|
||||||
|
def __init__(self):
|
||||||
|
self.alloc = False
|
||||||
|
self.free = False
|
||||||
|
self.ts = None
|
||||||
|
self.size = None
|
||||||
|
self.addr = None
|
||||||
|
self.trace_name = None
|
||||||
|
|
||||||
|
|
||||||
|
class Analyzer:
|
||||||
|
def __init__(self):
|
||||||
|
self.traces = {}
|
||||||
|
self.events = []
|
||||||
|
self.all_allocations = {}
|
||||||
|
self.new_allocations = {}
|
||||||
|
self.all_mem = 0
|
||||||
|
self.old_mem = 0
|
||||||
|
|
||||||
|
def read(self, path):
|
||||||
|
with gzip.open(path, "rb") as f:
|
||||||
|
try:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("t"):
|
||||||
|
self.add_trace(line)
|
||||||
|
elif line.startswith("["):
|
||||||
|
self.add_call(line)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add_trace(self, line):
|
||||||
|
t, name, content = line.split(" ", 2)
|
||||||
|
name = int(name)
|
||||||
|
assert(name > 0)
|
||||||
|
assert(name not in self.traces)
|
||||||
|
self.traces[name] = content.split("|")
|
||||||
|
|
||||||
|
def add_call(self, line):
|
||||||
|
first, second = line.split(":", 1)
|
||||||
|
first = first.strip()
|
||||||
|
ts, t, tname = first.split(" ")
|
||||||
|
ts = float(ts.replace("[", "").replace("]", ""))
|
||||||
|
assert(t == "t")
|
||||||
|
tname = int(tname)
|
||||||
|
assert(tname in self.traces)
|
||||||
|
second = second.strip()
|
||||||
|
result, eq, func, params = second.split(" ", 3)
|
||||||
|
assert(eq == "=")
|
||||||
|
params = params.split(" ")
|
||||||
|
e = Event()
|
||||||
|
e.ts = ts
|
||||||
|
e.trace_name = tname
|
||||||
|
if func == "m" and result != "(nil)":
|
||||||
|
e.alloc = True
|
||||||
|
e.addr = int(result, 16)
|
||||||
|
e.size = int(params[0])
|
||||||
|
elif func == "c" and result != "(nil)":
|
||||||
|
e.alloc = True
|
||||||
|
e.addr = int(result, 16)
|
||||||
|
e.size = int(params[0]) * int(params[1])
|
||||||
|
elif func == "r":
|
||||||
|
old_addr = params[0]
|
||||||
|
size = int(params[1])
|
||||||
|
if old_addr == "(nil)":
|
||||||
|
if result != "(nil)":
|
||||||
|
e.alloc = True
|
||||||
|
e.addr = int(result, 16)
|
||||||
|
e.size = size
|
||||||
|
elif old_addr != "(nil)":
|
||||||
|
if result != "(nil)":
|
||||||
|
e.free = True
|
||||||
|
e.addr = int(old_addr, 16)
|
||||||
|
self.events.append(e)
|
||||||
|
e = Event()
|
||||||
|
e.ts = ts
|
||||||
|
e.trace_name = tname
|
||||||
|
e.alloc = True
|
||||||
|
e.addr = int(result, 16)
|
||||||
|
e.size = size
|
||||||
|
elif func == "f":
|
||||||
|
addr = params[0]
|
||||||
|
if addr != "(nil)":
|
||||||
|
e.free = True
|
||||||
|
e.addr = int(addr, 16)
|
||||||
|
if e.alloc or e.free:
|
||||||
|
self.events.append(e)
|
||||||
|
|
||||||
|
|
||||||
|
def analyze(self):
|
||||||
|
self.all_allocations = {}
|
||||||
|
self.new_allocations = {}
|
||||||
|
self.all_mem = 0
|
||||||
|
self.old_mem = 0
|
||||||
|
self.peak_mem = 0
|
||||||
|
period = 1
|
||||||
|
next_ts_print = self.events[0].ts
|
||||||
|
for e in self.events:
|
||||||
|
if e.ts >= next_ts_print:
|
||||||
|
self.print_allocations()
|
||||||
|
next_ts_print += period
|
||||||
|
self.process_event(e)
|
||||||
|
self.print_allocations()
|
||||||
|
self.print_leaks()
|
||||||
|
|
||||||
|
|
||||||
|
def print_allocations(self):
|
||||||
|
print "Memory usage: current:", commas(self.all_mem), " | delta:", commas(self.all_mem - self.old_mem), " | peak:", commas(self.peak_mem)
|
||||||
|
self.old_mem = self.all_mem
|
||||||
|
self.new_alllocations = {}
|
||||||
|
|
||||||
|
|
||||||
|
def print_leaks(self):
|
||||||
|
if not self.all_allocations:
|
||||||
|
return
|
||||||
|
print "Memory leaked:", commas(self.all_mem)
|
||||||
|
leaks = [e for addr, e in self.all_allocations.iteritems()]
|
||||||
|
leaks.sort(key=lambda e: e.size)
|
||||||
|
for e in leaks:
|
||||||
|
print "Leak:", commas(e.size)
|
||||||
|
print "Allocated in:\n ", "\n ".join(self.traces[e.trace_name])
|
||||||
|
|
||||||
|
def process_event(self, e):
|
||||||
|
if e.alloc:
|
||||||
|
assert(e.addr not in self.all_allocations)
|
||||||
|
self.all_allocations[e.addr] = e
|
||||||
|
assert(e.addr not in self.new_allocations)
|
||||||
|
self.new_allocations[e.addr] = e
|
||||||
|
self.all_mem += e.size
|
||||||
|
self.peak_mem = max(self.peak_mem, self.all_mem)
|
||||||
|
else:
|
||||||
|
assert(e.addr in self.all_allocations)
|
||||||
|
e_alloc = self.all_allocations[e.addr]
|
||||||
|
if e.ts - e_alloc.ts > 1. and e_alloc.size > 1e3 and False:
|
||||||
|
print "Long-lived alloc:", commas(e_alloc.size), "freed after", commas(e.ts - e_alloc.ts) + "s"
|
||||||
|
print "Allocated in:\n ", "\n ".join(self.traces[e_alloc.trace_name])
|
||||||
|
print "Freed in:\n ", "\n ".join(self.traces[e.trace_name])
|
||||||
|
if e_alloc.addr in self.new_allocations:
|
||||||
|
if e_alloc.size > 1e7 and False:
|
||||||
|
print "Large alloc:", commas(e_alloc.size), "freed after", commas(e.ts - e_alloc.ts) + "s"
|
||||||
|
print "Allocated in:\n ", "\n ".join(self.traces[e_alloc.trace_name])
|
||||||
|
print "Freed in:\n ", "\n ".join(self.traces[e.trace_name])
|
||||||
|
del self.new_allocations[e_alloc.addr]
|
||||||
|
del self.all_allocations[e_alloc.addr]
|
||||||
|
self.all_mem -= e_alloc.size
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
a = Analyzer()
|
||||||
|
a.read(sys.argv[1])
|
||||||
|
a.analyze()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -10,7 +10,6 @@ sys.setdefaultencoding('utf8')
|
|||||||
import argparse
|
import argparse
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
@@ -40,10 +39,6 @@ def print_err(*args, **kwargs):
|
|||||||
print(*args, file=sys.stderr, **kwargs)
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def clear_ansi_codes(s):
|
|
||||||
return re.sub(r"\x1B\[[0-9;]*[a-zA-Z]", "", s)
|
|
||||||
|
|
||||||
|
|
||||||
def run(cmd, output=False):
|
def run(cmd, output=False):
|
||||||
return subprocess.Popen(cmd,
|
return subprocess.Popen(cmd,
|
||||||
stdin=devnull,
|
stdin=devnull,
|
||||||
@@ -193,7 +188,6 @@ def test(tint2path, config, use_asan):
|
|||||||
mem, mem_detail = get_mem_usage(tint2.pid)
|
mem, mem_detail = get_mem_usage(tint2.pid)
|
||||||
stop(tint2)
|
stop(tint2)
|
||||||
out, _ = tint2.communicate()
|
out, _ = tint2.communicate()
|
||||||
out = clear_ansi_codes(out)
|
|
||||||
exitcode = tint2.returncode
|
exitcode = tint2.returncode
|
||||||
if exitcode != 0 and exitcode != 23:
|
if exitcode != 0 and exitcode != 23:
|
||||||
print("tint2 crashed with exit code {0}!".format(exitcode))
|
print("tint2 crashed with exit code {0}!".format(exitcode))
|
||||||
@@ -228,41 +222,6 @@ def test(tint2path, config, use_asan):
|
|||||||
stop_xvfb()
|
stop_xvfb()
|
||||||
|
|
||||||
|
|
||||||
def run_unit_tests(tint2path, use_asan):
|
|
||||||
print("# Unit tests", "(ASAN on)" if use_asan else "")
|
|
||||||
start_xvfb()
|
|
||||||
sleep(1)
|
|
||||||
start_xsettings()
|
|
||||||
start_wm()
|
|
||||||
sleep(1)
|
|
||||||
compton = start_compositor()
|
|
||||||
sleep(1)
|
|
||||||
os.environ["DEBUG_FPS"] = "1"
|
|
||||||
os.environ["ASAN_OPTIONS"] = "detect_leaks=1:exitcode=0"
|
|
||||||
tint2 = run([tint2path, "--test-verbose"], True)
|
|
||||||
time_limit = time.time() + 60
|
|
||||||
while tint2.poll() == None:
|
|
||||||
if time.time() < time_limit:
|
|
||||||
time.sleep(1)
|
|
||||||
continue
|
|
||||||
tint2.stop()
|
|
||||||
out, _ = tint2.communicate()
|
|
||||||
out = clear_ansi_codes(out)
|
|
||||||
exitcode = tint2.returncode
|
|
||||||
if exitcode != 0 and exitcode != 23:
|
|
||||||
print("tint2 crashed with exit code {0}!".format(exitcode))
|
|
||||||
print("Output:")
|
|
||||||
print("```\n" + out.strip() + "\n```")
|
|
||||||
return
|
|
||||||
if "tests succeeded" in out:
|
|
||||||
num_tests = [line for line in out.split("\n") if "tint2: Running" in line][0]
|
|
||||||
print("All {0} tests succeeded.".format(num_tests))
|
|
||||||
return
|
|
||||||
if "tests failed" in out:
|
|
||||||
print("```\n" + out.strip() + "\n```")
|
|
||||||
stop_xvfb()
|
|
||||||
|
|
||||||
|
|
||||||
def show_timestamp():
|
def show_timestamp():
|
||||||
utc_datetime = datetime.datetime.utcnow()
|
utc_datetime = datetime.datetime.utcnow()
|
||||||
print("Last updated:", utc_datetime.strftime("%Y-%m-%d %H:%M UTC"))
|
print("Last updated:", utc_datetime.strftime("%Y-%m-%d %H:%M UTC"))
|
||||||
@@ -326,29 +285,6 @@ def compile_and_report(src_dir, use_asan):
|
|||||||
print("Status: Succeeded in %.1f seconds" % (duration,), ok)
|
print("Status: Succeeded in %.1f seconds" % (duration,), ok)
|
||||||
|
|
||||||
|
|
||||||
def compile_remotely_and_report(host):
|
|
||||||
print_err("Compiling on {0}...".format(host))
|
|
||||||
print("# Compilation on {0}".format(host))
|
|
||||||
start = time.time()
|
|
||||||
c = run("ssh worker@{0} 'cd tint2 && git pull && mkdir -p build && rm -rf build && mkdir -p build && cd build && cmake .. && make && ./tint2 --version'".format(host), True)
|
|
||||||
out, _ = c.communicate()
|
|
||||||
duration = time.time() - start
|
|
||||||
if c.returncode != 0:
|
|
||||||
print("Status: Failed!", error)
|
|
||||||
print("Output:")
|
|
||||||
print("```\n" + out.strip() + "\n```")
|
|
||||||
warnings = [ line for line in out.split("\n") if "warning:" in line and ".so." not in line.split(":", 1)[0] ]
|
|
||||||
if warnings:
|
|
||||||
print("Status: Succeeded with warnings!", warning)
|
|
||||||
print("Warnings:")
|
|
||||||
print("```", end="")
|
|
||||||
for line in warnings:
|
|
||||||
print(line, end="")
|
|
||||||
print("```", end="")
|
|
||||||
else:
|
|
||||||
print("Status: Succeeded in %.1f seconds" % (duration,), ok)
|
|
||||||
|
|
||||||
|
|
||||||
def run_test(config, index, use_asan):
|
def run_test(config, index, use_asan):
|
||||||
print_err("Running test", index, "for config", config)
|
print_err("Running test", index, "for config", config)
|
||||||
print("# Test", index, "(ASAN on)" if use_asan else "")
|
print("# Test", index, "(ASAN on)" if use_asan else "")
|
||||||
@@ -414,11 +350,8 @@ def main():
|
|||||||
show_timestamp()
|
show_timestamp()
|
||||||
show_git_info(args.src_dir)
|
show_git_info(args.src_dir)
|
||||||
show_system_info()
|
show_system_info()
|
||||||
compile_remotely_and_report("FreeBSD")
|
|
||||||
compile_remotely_and_report("OpenBSD")
|
|
||||||
for use_asan in [True, False]:
|
for use_asan in [True, False]:
|
||||||
compile_and_report(args.src_dir, use_asan)
|
compile_and_report(args.src_dir, use_asan)
|
||||||
run_unit_tests("./build/tint2", use_asan)
|
|
||||||
run_tests(use_asan)
|
run_tests(use_asan)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
+1
-1
@@ -175,7 +175,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
battery_font_color = #ffffff 100
|
battery_font_color = #ffffff 100
|
||||||
bat1_format =
|
bat1_format =
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = xmessage 'tint2: Battery low!'
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
+5
-13
@@ -1,16 +1,8 @@
|
|||||||
// ADD PREDEFINED MACROS HERE!
|
// ADD PREDEFINED MACROS HERE!
|
||||||
#define DISABLE_BACKTRACE 1
|
|
||||||
#define ENABLE_BATTERY 1
|
|
||||||
#define ENABLE_UEVENT 1
|
|
||||||
#define GETTEXT_PACKAGE "tint2conf"
|
|
||||||
#define HAS_GENERIC 1
|
|
||||||
#define HAVE_RSVG 1
|
#define HAVE_RSVG 1
|
||||||
#define HAVE_SN 1
|
#define HAVE_SN 1
|
||||||
#define HAVE_VERSION_H 1
|
#define ENABLE_BATTERY 1
|
||||||
#define INSTALL_PREFIX "/usr/local"
|
#define ENABLE_UEVENT 1
|
||||||
#define LOCALEDIR "/usr/local/share/locale"
|
#define GETTEXT_PACKAGE
|
||||||
#define SN_API_NOT_YET_FROZEN
|
#define HAVE_TRACING
|
||||||
#define _BSD_SOURCE
|
#define ENABLE_EXECINFO
|
||||||
#define _DEFAULT_SOURCE
|
|
||||||
#define _POSIX_C_SOURCE=200809L
|
|
||||||
#define _WITH_GETLINE
|
|
||||||
|
|||||||
+5
-21
@@ -1,4 +1,3 @@
|
|||||||
configure
|
|
||||||
doc/tint2.1
|
doc/tint2.1
|
||||||
sample/icon_and_text_1.tint2rc
|
sample/icon_and_text_1.tint2rc
|
||||||
sample/icon_and_text_2.tint2rc
|
sample/icon_and_text_2.tint2rc
|
||||||
@@ -21,9 +20,6 @@ src/battery/battery.c
|
|||||||
src/battery/battery.h
|
src/battery/battery.h
|
||||||
src/clock/clock.c
|
src/clock/clock.c
|
||||||
src/clock/clock.h
|
src/clock/clock.h
|
||||||
src/default_icon.c
|
|
||||||
src/default_icon.c
|
|
||||||
src/default_icon.h
|
|
||||||
src/execplugin/execplugin.c
|
src/execplugin/execplugin.c
|
||||||
src/execplugin/execplugin.h
|
src/execplugin/execplugin.h
|
||||||
src/launcher/launcher.c
|
src/launcher/launcher.c
|
||||||
@@ -60,14 +56,8 @@ src/util/area.c
|
|||||||
src/util/area.h
|
src/util/area.h
|
||||||
src/util/blur.c
|
src/util/blur.c
|
||||||
src/util/blur.h
|
src/util/blur.h
|
||||||
src/util/bt.c
|
|
||||||
src/util/bt.h
|
|
||||||
src/util/common.c
|
src/util/common.c
|
||||||
src/util/common.h
|
src/util/common.h
|
||||||
src/util/server.c
|
|
||||||
src/util/server.h
|
|
||||||
src/util/strlcat.c
|
|
||||||
src/util/strlcat.h
|
|
||||||
src/util/timer.c
|
src/util/timer.c
|
||||||
src/util/timer.h
|
src/util/timer.h
|
||||||
src/util/window.c
|
src/util/window.c
|
||||||
@@ -247,15 +237,9 @@ src/signals.c
|
|||||||
src/signals.h
|
src/signals.h
|
||||||
src/tracing.c
|
src/tracing.c
|
||||||
src/tracing.h
|
src/tracing.h
|
||||||
src/util/test.c
|
src/util/mem.c
|
||||||
src/util/test.h
|
src/util/mem.h
|
||||||
src/util/bool.h
|
src/util/addr2line.c
|
||||||
src/util/colors.h
|
src/util/addr2line.h
|
||||||
src/util/print.c
|
|
||||||
src/util/print.h
|
src/util/print.h
|
||||||
src/util/test.c
|
src/util/print.c
|
||||||
src/util/test.h
|
|
||||||
src/util/tracing.h
|
|
||||||
src/util/tracing.c
|
|
||||||
src/util/signals.h
|
|
||||||
src/util/signals.c
|
|
||||||
|
|||||||
+10
-21
@@ -1,33 +1,22 @@
|
|||||||
.
|
.
|
||||||
./build
|
|
||||||
./src
|
./src
|
||||||
./src/battery
|
./src/battery
|
||||||
./src/clock
|
./src/clock
|
||||||
|
./src/execplugin
|
||||||
|
./src/launcher
|
||||||
|
./src/sysmon
|
||||||
./src/systray
|
./src/systray
|
||||||
./src/taskbar
|
./src/taskbar
|
||||||
./src/launcher
|
./src/tint2conf
|
||||||
./src/tooltip
|
./src/tooltip
|
||||||
./src/util
|
./src/util
|
||||||
./src/execplugin
|
|
||||||
./src/button
|
|
||||||
./src/freespace
|
|
||||||
./src/separator
|
|
||||||
/usr/include/pango-1.0
|
|
||||||
/usr/include/cairo
|
|
||||||
/usr/include/glib-2.0
|
|
||||||
/usr/lib/x86_64-linux-gnu/glib-2.0/include
|
|
||||||
/usr/include/pixman-1
|
|
||||||
/usr/include/freetype2
|
|
||||||
/usr/include/libpng12
|
|
||||||
/usr/include/librsvg-2.0
|
|
||||||
/usr/include/gdk-pixbuf-2.0
|
|
||||||
/usr/include/startup-notification-1.0
|
|
||||||
/usr/include/gtk-2.0
|
|
||||||
/usr/lib/x86_64-linux-gnu/gtk-2.0/include
|
|
||||||
/usr/include/atk-1.0
|
|
||||||
/usr/include/gio-unix-2.0
|
|
||||||
/usr/include/harfbuzz
|
|
||||||
/usr/include
|
/usr/include
|
||||||
|
/usr/include/gtk-2.0
|
||||||
|
/usr/include/glib-2.0
|
||||||
|
/usr/include/gdk-pixbuf-2.0
|
||||||
|
/usr/include/cairo
|
||||||
|
/usr/include/pango-1.0
|
||||||
|
/usr/include/startup-notification-1.0
|
||||||
po
|
po
|
||||||
src/tint2conf/po
|
src/tint2conf/po
|
||||||
src/freespace
|
src/freespace
|
||||||
|
|||||||
Reference in New Issue
Block a user