Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b810bad93f | ||
|
|
b85362b5c7 | ||
|
|
03675b152d | ||
|
|
c3fdd76b58 | ||
|
|
04ba5a6617 | ||
|
|
f5f8792d42 | ||
|
|
965a2665b0 | ||
|
|
b2b0119f4d | ||
|
|
41e49ef4e6 | ||
|
|
25dd623618 | ||
|
|
28b1174c0f | ||
|
|
b70edc437c | ||
|
|
bf58e16b83 | ||
|
|
3190c5b7de | ||
|
|
5db0dceec2 | ||
|
|
5c5f507e54 | ||
|
|
d301ada47a | ||
|
|
b3f9834313 | ||
|
|
c7b23ee94a | ||
|
|
12f04e3055 | ||
|
|
7f62594cf6 | ||
|
|
405c2c9286 | ||
|
|
90a445868c | ||
|
|
427afc61b5 | ||
|
|
ee92fac10e | ||
|
|
95eea350fe | ||
|
|
8242b494bc | ||
|
|
1c6377f570 | ||
|
|
dd1fd28114 | ||
|
|
b4610fcb6e | ||
|
|
eb0e6765f9 | ||
|
|
5ee278d3ca | ||
|
|
fb438031c3 | ||
|
|
e5380f8e29 | ||
|
|
c064ec70ed | ||
|
|
a9a9a753bc | ||
|
|
38bee65b58 | ||
|
|
f64cf199e4 | ||
|
|
0911dcaed1 | ||
|
|
c41d75e54e | ||
|
|
8e0bdcaedd | ||
|
|
be4554b89d | ||
|
|
82d7fdc8f9 | ||
|
|
e046cb88ab | ||
|
|
300ef518cb | ||
|
|
457d51e267 | ||
|
|
1b48efe738 | ||
|
|
40e01e2abf | ||
|
|
a7ca1b739b | ||
|
|
750cbd572c | ||
|
|
75c2a2084d | ||
|
|
9b17461f74 | ||
|
|
a185f625f9 | ||
|
|
3a9181eff5 | ||
|
|
5cea67171b | ||
|
|
328a35f949 | ||
|
|
cab9c3bddd | ||
|
|
5dd814773a | ||
|
|
f4384b786c | ||
|
|
5bc83561e0 | ||
|
|
375e965a3a | ||
|
|
67e25b8102 | ||
|
|
c96201930b | ||
|
|
6bf72a030a | ||
|
|
63d0d98a5c | ||
|
|
e739023529 | ||
|
|
a7a9c5cdae | ||
|
|
50822bd2fd | ||
|
|
00c79073f0 | ||
|
|
f5b36b37b6 | ||
|
|
c635f46439 | ||
|
|
16a359f944 | ||
|
|
9a972f4c25 | ||
|
|
9d06ac0157 | ||
|
|
cfac6a645d | ||
|
|
648c7c109f | ||
|
|
8946f93254 | ||
|
|
58e030de5d | ||
|
|
c2f8c210f8 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,5 +1,7 @@
|
|||||||
build
|
build
|
||||||
*.user
|
*.user
|
||||||
version.h
|
version.h
|
||||||
*.todo
|
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.todo
|
||||||
|
packaging/make_ubuntu2.sh
|
||||||
|
test_*.log
|
||||||
|
|||||||
@@ -62,6 +62,17 @@ else()
|
|||||||
set(BACKTRACE_L_FLAGS "")
|
set(BACKTRACE_L_FLAGS "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
check_c_source_compiles(
|
||||||
|
"#define print(x) _Generic((x), default : print_unknown)(x) \n void print_unknown(){} \n int main () { print(0); }"
|
||||||
|
HAS_GENERIC)
|
||||||
|
|
||||||
|
if(HAS_GENERIC)
|
||||||
|
add_definitions(-DHAS_GENERIC)
|
||||||
|
set(CSTD "c11")
|
||||||
|
else()
|
||||||
|
set(CSTD "c99")
|
||||||
|
endif(HAS_GENERIC)
|
||||||
|
|
||||||
if( ENABLE_RSVG )
|
if( ENABLE_RSVG )
|
||||||
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
|
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
|
||||||
endif( ENABLE_RSVG )
|
endif( ENABLE_RSVG )
|
||||||
@@ -116,13 +127,14 @@ include_directories( ${PROJECT_BINARY_DIR}
|
|||||||
|
|
||||||
set( SOURCES src/config.c
|
set( SOURCES src/config.c
|
||||||
src/panel.c
|
src/panel.c
|
||||||
src/server.c
|
src/util/server.c
|
||||||
src/main.c
|
src/main.c
|
||||||
src/init.c
|
src/init.c
|
||||||
src/signals.c
|
src/util/signals.c
|
||||||
src/tracing.c
|
src/util/tracing.c
|
||||||
src/mouse_actions.c
|
src/mouse_actions.c
|
||||||
src/drag_and_drop.c
|
src/drag_and_drop.c
|
||||||
|
src/default_icon.c
|
||||||
src/clock/clock.c
|
src/clock/clock.c
|
||||||
src/systray/systraybar.c
|
src/systray/systraybar.c
|
||||||
src/launcher/launcher.c
|
src/launcher/launcher.c
|
||||||
@@ -146,10 +158,10 @@ set( SOURCES src/config.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/gradient.c
|
src/util/strlcat.c
|
||||||
src/util/addr2line.c
|
|
||||||
src/util/print.c
|
src/util/print.c
|
||||||
src/util/mem.c
|
src/util/gradient.c
|
||||||
|
src/util/test.c
|
||||||
src/util/uevent.c
|
src/util/uevent.c
|
||||||
src/util/window.c )
|
src/util/window.c )
|
||||||
|
|
||||||
@@ -236,7 +248,7 @@ else()
|
|||||||
SET(TRACING_L_FLAGS "")
|
SET(TRACING_L_FLAGS "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" -- "\"${PROJECT_SOURCE_DIR}/\"" )
|
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" )
|
||||||
|
|
||||||
link_directories( ${X11_LIBRARY_DIRS}
|
link_directories( ${X11_LIBRARY_DIRS}
|
||||||
${PANGOCAIRO_LIBRARY_DIRS}
|
${PANGOCAIRO_LIBRARY_DIRS}
|
||||||
@@ -268,14 +280,9 @@ 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=c11 ${ASAN_C_FLAGS} ${TRACING_C_FLAGS}" )
|
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=${CSTD} ${ASAN_C_FLAGS} ${TRACING_C_FLAGS}" )
|
||||||
set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS} ${BACKTRACE_L_FLAGS} ${TRACING_L_FLAGS}" )
|
set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS} ${BACKTRACE_L_FLAGS} ${TRACING_L_FLAGS}" )
|
||||||
|
|
||||||
install( TARGETS tint2 DESTINATION bin )
|
install( TARGETS tint2 DESTINATION bin )
|
||||||
|
|||||||
24
ChangeLog
24
ChangeLog
@@ -1,8 +1,27 @@
|
|||||||
2017-11-10 master
|
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:
|
||||||
@@ -971,3 +990,6 @@ released tint-0.2
|
|||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -1,5 +1,5 @@
|
|||||||
# Latest stable release: 15.3
|
# Latest stable release: 16.2
|
||||||
Changes: https://gitlab.com/o9000/tint2/blob/15.3/ChangeLog
|
Changes: https://gitlab.com/o9000/tint2/blob/16.2/ChangeLog
|
||||||
|
|
||||||
Documentation: [doc/tint2.md](doc/tint2.md)
|
Documentation: [doc/tint2.md](doc/tint2.md)
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ Compile it with (after you install the [dependencies](https://gitlab.com/o9000/t
|
|||||||
```
|
```
|
||||||
git clone https://gitlab.com/o9000/tint2.git
|
git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 15.3
|
git checkout 16.2
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
@@ -61,9 +61,9 @@ tint2 is a simple panel/taskbar made for modern X window managers. It was specif
|
|||||||
|
|
||||||
# Known issues
|
# Known issues
|
||||||
|
|
||||||
* Graphic glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA ([issue 595](https://gitlab.com/o9000/tint2/issues/595))
|
* Graphical glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA ([issue 595](https://gitlab.com/o9000/tint2/issues/595))
|
||||||
* Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (known issues for [awesome](https://gitlab.com/o9000/tint2/issues/385), [bspwm](https://gitlab.com/o9000/tint2/issues/524). [openbox-multihead](https://gitlab.com/o9000/tint2/issues/456))
|
* Window managers that do not follow exactly the EWMH specification might not interact well with tint2 ([issue 627](https://gitlab.com/o9000/tint2/issues/627)).
|
||||||
* Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE)
|
* Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE).
|
||||||
|
|
||||||
# How can I help out?
|
# How can I help out?
|
||||||
|
|
||||||
|
|||||||
@@ -386,6 +386,8 @@ gradient_id_pressed = 2
|
|||||||
<li><code>width</code> and <code>height</code> can be specified without units (e.g. <code>123</code>) as pixels, or followed by <code>%</code> as percentages of the monitor size (e.g. <code>50%</code>). Use <code>100%</code> for full monitor width/height.
|
<li><code>width</code> and <code>height</code> can be specified without units (e.g. <code>123</code>) as pixels, or followed by <code>%</code> as percentages of the monitor size (e.g. <code>50%</code>). Use <code>100%</code> for full monitor width/height.
|
||||||
Example:</li>
|
Example:</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
<li><p><code>scale_relative_to_dpi = integer</code> : If set to a non-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI - this is the DPI for which exising user configs looked normal, for backward compatibility.</p></li>
|
||||||
|
<li><p><code>scale_relative_to_screen_height = integer</code> : Similar to <code>scale_relative_to_dpi</code>, except the scaling factor is computed as the ratio between the monitor height and <code>scale_relative_to_screen_height</code>. The effect is cumulative with <code>scale_relative_to_dpi</code>, i.e. if both options are present, the factors are multiplied.</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
<pre class="highlight plaintext"><code># The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
<pre class="highlight plaintext"><code># The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
||||||
panel_size = 94% 30
|
panel_size = 94% 30
|
||||||
@@ -605,7 +607,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>
|
||||||
|
|||||||
@@ -199,9 +199,9 @@ pre {
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<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
|
<h1 id="latest-stable-release-16-2"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.2</span><a name="latest-stable-release-16-2" href="#latest-stable-release-16-2" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.2/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.2/ChangeLog</a></p><p>Documentation: <a href="manual.html">manual.html</a></p><p>Compile it with (after you install the <a href="https://gitlab.com/o9000/tint2/wikis/Install#dependencies">dependencies</a>):</p><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 15.3
|
git checkout 16.2
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
@@ -239,9 +239,9 @@ update-mime-database /usr/local/share/mime
|
|||||||
</ul>
|
</ul>
|
||||||
<h1 id="known-issues">Known issues<a name="known-issues" href="#known-issues" class="md2man-permalink" title="permalink"></a></h1>
|
<h1 id="known-issues">Known issues<a name="known-issues" href="#known-issues" class="md2man-permalink" title="permalink"></a></h1>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Graphic glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA (<a href="https://gitlab.com/o9000/tint2/issues/595">issue 595</a>)</li>
|
<li>Graphical glitches on Intel graphics cards can be avoided by changing the acceleration method to UXA (<a href="https://gitlab.com/o9000/tint2/issues/595">issue 595</a>)</li>
|
||||||
<li>Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (known issues for <a href="https://gitlab.com/o9000/tint2/issues/385">awesome</a>, <a href="https://gitlab.com/o9000/tint2/issues/524">bspwm</a>. <a href="https://gitlab.com/o9000/tint2/issues/456">openbox-multihead</a>)</li>
|
<li>Window managers that do not follow exactly the EWMH specification might not interact well with tint2 (<a href="https://gitlab.com/o9000/tint2/issues/627">issue 627</a>).</li>
|
||||||
<li>Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE)</li>
|
<li>Full transparency requires a compositor such as Compton (if not provided already by the window manager, as in Compiz/Unity, KDE or XFCE).</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h1 id="how-can-i-help-out">How can I help out?<a name="how-can-i-help-out" href="#how-can-i-help-out" class="md2man-permalink" title="permalink"></a></h1>
|
<h1 id="how-can-i-help-out">How can I help out?<a name="how-can-i-help-out" href="#how-can-i-help-out" class="md2man-permalink" title="permalink"></a></h1>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.TH TINT2 1 "2017\-11\-05" 15.3
|
.TH TINT2 1 "2018\-01\-21" 16.2
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
tint2 \- lightweight panel/taskbar
|
tint2 \- lightweight panel/taskbar
|
||||||
@@ -343,6 +343,10 @@ Use \fB\fCpanel_monitor = all\fR to get a separate panel per monitor
|
|||||||
\fB\fCwidth\fR and \fB\fCheight\fR can be specified without units (e.g. \fB\fC123\fR) as pixels, or followed by \fB\fC%\fR as percentages of the monitor size (e.g. \fB\fC50%\fR). Use \fB\fC100%\fR for full monitor width/height.
|
\fB\fCwidth\fR and \fB\fCheight\fR can be specified without units (e.g. \fB\fC123\fR) as pixels, or followed by \fB\fC%\fR as percentages of the monitor size (e.g. \fB\fC50%\fR). Use \fB\fC100%\fR for full monitor width/height.
|
||||||
Example:
|
Example:
|
||||||
.RE
|
.RE
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fCscale_relative_to_dpi = integer\fR : If set to a non\-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI \- this is the DPI for which exising user configs looked normal, for backward compatibility.
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fCscale_relative_to_screen_height = integer\fR : Similar to \fB\fCscale_relative_to_dpi\fR, except the scaling factor is computed as the ratio between the monitor height and \fB\fCscale_relative_to_screen_height\fR\&. The effect is cumulative with \fB\fCscale_relative_to_dpi\fR, i.e. if both options are present, the factors are multiplied.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# TINT2 1 "2017-11-05" 15.3
|
# TINT2 1 "2018-01-21" 16.2
|
||||||
|
|
||||||
## NAME
|
## NAME
|
||||||
tint2 - lightweight panel/taskbar
|
tint2 - lightweight panel/taskbar
|
||||||
@@ -279,6 +279,10 @@ gradient_id_pressed = 2
|
|||||||
* `width` and `height` can be specified without units (e.g. `123`) as pixels, or followed by `%` as percentages of the monitor size (e.g. `50%`). Use `100%` for full monitor width/height.
|
* `width` and `height` can be specified without units (e.g. `123`) as pixels, or followed by `%` as percentages of the monitor size (e.g. `50%`). Use `100%` for full monitor width/height.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
* `scale_relative_to_dpi = integer` : If set to a non-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI - this is the DPI for which exising user configs looked normal, for backward compatibility.
|
||||||
|
|
||||||
|
* `scale_relative_to_screen_height = integer` : Similar to `scale_relative_to_dpi`, except the scaling factor is computed as the ratio between the monitor height and `scale_relative_to_screen_height`. The effect is cumulative with `scale_relative_to_dpi`, i.e. if both options are present, the factors are multiplied.
|
||||||
|
|
||||||
```
|
```
|
||||||
# The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
# The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
||||||
panel_size = 94% 30
|
panel_size = 94% 30
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ SCRIPT_DIR=$(dirname "$0")
|
|||||||
DIRTY=""
|
DIRTY=""
|
||||||
VERSION=""
|
VERSION=""
|
||||||
|
|
||||||
if [ -d ${SCRIPT_DIR}/.git ] && git status 1>/dev/null 2>/dev/null
|
OLD_DIR=$(pwd)
|
||||||
|
cd ${SCRIPT_DIR}
|
||||||
|
|
||||||
|
if [ -d .git ] && git status 1>/dev/null 2>/dev/null
|
||||||
then
|
then
|
||||||
git update-index -q --ignore-submodules --refresh
|
git update-index -q --ignore-submodules --refresh
|
||||||
# Disallow unstaged changes in the working tree
|
# Disallow unstaged changes in the working tree
|
||||||
@@ -37,10 +40,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 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 2)
|
VERSION=$(head -n 1 "ChangeLog" | cut -d ' ' -f 2)
|
||||||
if [ "$VERSION" = "master" ]
|
if [ "$VERSION" = "master" ]
|
||||||
then
|
then
|
||||||
PREVIOUS=$(grep '^2' "${SCRIPT_DIR}/ChangeLog" | head -n 2 | tail -n 1 | cut -d ' ' -f 2)
|
PREVIOUS=$(grep '^2' "ChangeLog" | head -n 2 | tail -n 1 | cut -d ' ' -f 2)
|
||||||
HASH=$(git log -n 1 --pretty=format:%cI.%ct.%h | tr -d ':' | tr -d '-' | tr '.' '-' | sed 's/T[0-9\+]*//g' 2>/dev/null)
|
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
|
||||||
@@ -49,13 +52,15 @@ fi
|
|||||||
|
|
||||||
if [ -z "$VERSION" ]
|
if [ -z "$VERSION" ]
|
||||||
then
|
then
|
||||||
VERSION=$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 2)
|
VERSION=$(head -n 1 "ChangeLog" | cut -d ' ' -f 2)
|
||||||
if [ "$VERSION" = "master" ]
|
if [ "$VERSION" = "master" ]
|
||||||
then
|
then
|
||||||
VERSION=$VERSION-$(head -n 1 "${SCRIPT_DIR}/ChangeLog" | cut -d ' ' -f 1)
|
VERSION=$VERSION-$(head -n 1 "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
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm -f version.h
|
rm -f version.h
|
||||||
VERSION=$(git describe --exact-match 2>/dev/null)
|
VERSION=$(false 2>/dev/null)
|
||||||
if [ $? -eq 0 ]
|
if [ $? -eq 0 ]
|
||||||
then
|
then
|
||||||
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
VERSION=$(echo "$VERSION" | sed 's/^v//')
|
||||||
@@ -49,7 +49,7 @@ echo "echo \"#define VERSION_STRING \\\"$VERSION\\\"\" > version.h" > $DIR/get_v
|
|||||||
# Copy the debian files into the source directory
|
# Copy the debian files into the source directory
|
||||||
cp -r debian $DIR/debian
|
cp -r debian $DIR/debian
|
||||||
|
|
||||||
for DISTRO in trusty xenial zesty artful
|
for DISTRO in trusty xenial artful bionic
|
||||||
do
|
do
|
||||||
# Cleanup from previous builds
|
# Cleanup from previous builds
|
||||||
rm -rf tint2_$VERSION-*
|
rm -rf tint2_$VERSION-*
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ git reset --hard
|
|||||||
git pull
|
git pull
|
||||||
|
|
||||||
|
|
||||||
~/tint2/packaging/version_status.py > packaging.tmp.md
|
timeout -k 10 600 ~/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
|
||||||
|
|
||||||
|
|||||||
@@ -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?rev=1.5&content-type=text/plain")
|
makefile = http_download_txt("http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/ports/x11/tint2/Makefile?content-type=text/plain")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
for line in makefile.split("\n"):
|
for line in makefile.split("\n"):
|
||||||
|
|||||||
@@ -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 timeout *battery_timeout;
|
static Timer battery_timer;
|
||||||
|
|
||||||
#define BATTERY_BUF_SIZE 256
|
#define BATTERY_BUF_SIZE 256
|
||||||
static char buf_bat_line1[BATTERY_BUF_SIZE];
|
static char buf_bat_line1[BATTERY_BUF_SIZE];
|
||||||
@@ -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;
|
||||||
battery_timeout = NULL;
|
INIT_TIMER(battery_timer);
|
||||||
bat1_has_font = FALSE;
|
bat1_has_font = FALSE;
|
||||||
bat1_font_desc = NULL;
|
bat1_font_desc = NULL;
|
||||||
bat1_format = NULL;
|
bat1_format = NULL;
|
||||||
@@ -127,8 +127,7 @@ void cleanup_battery()
|
|||||||
ac_connected_cmd = NULL;
|
ac_connected_cmd = NULL;
|
||||||
free(ac_disconnected_cmd);
|
free(ac_disconnected_cmd);
|
||||||
ac_disconnected_cmd = NULL;
|
ac_disconnected_cmd = NULL;
|
||||||
stop_timeout(battery_timeout);
|
destroy_timer(&battery_timer);
|
||||||
battery_timeout = NULL;
|
|
||||||
battery_found = FALSE;
|
battery_found = FALSE;
|
||||||
|
|
||||||
battery_os_free();
|
battery_os_free();
|
||||||
@@ -226,7 +225,8 @@ void init_battery()
|
|||||||
|
|
||||||
battery_found = battery_os_init();
|
battery_found = battery_os_init();
|
||||||
|
|
||||||
battery_timeout = add_timeout(10, 30000, update_battery_tick, 0, &battery_timeout);
|
if (!battery_timer.enabled_)
|
||||||
|
change_timer(&battery_timer, true, 30000, 30000, update_battery_tick, 0);
|
||||||
|
|
||||||
update_battery();
|
update_battery();
|
||||||
}
|
}
|
||||||
@@ -273,6 +273,7 @@ void init_battery_panel(void *p)
|
|||||||
bat1_format = strdup("%p");
|
bat1_format = strdup("%p");
|
||||||
bat2_format = strdup("%t");
|
bat2_format = strdup("%t");
|
||||||
}
|
}
|
||||||
|
update_battery_tick(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_init_fonts()
|
void battery_init_fonts()
|
||||||
@@ -421,6 +422,7 @@ gboolean resize_battery(void *obj)
|
|||||||
void draw_battery(void *obj, cairo_t *c)
|
void draw_battery(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Battery *battery = (Battery *)obj;
|
Battery *battery = (Battery *)obj;
|
||||||
|
Panel *panel = (Panel *)battery->area.panel;
|
||||||
draw_text_area(&battery->area,
|
draw_text_area(&battery->area,
|
||||||
c,
|
c,
|
||||||
buf_bat_line1,
|
buf_bat_line1,
|
||||||
@@ -429,7 +431,8 @@ void draw_battery(void *obj, cairo_t *c)
|
|||||||
bat2_font_desc,
|
bat2_font_desc,
|
||||||
battery->bat1_posy,
|
battery->bat1_posy,
|
||||||
battery->bat2_posy,
|
battery->bat2_posy,
|
||||||
&battery->font_color);
|
&battery->font_color,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_dump_geometry(void *obj, int indent)
|
void battery_dump_geometry(void *obj, int indent)
|
||||||
|
|||||||
@@ -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);
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy) * panel->scale;
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
||||||
int interior_padding = button->area.paddingx;
|
int interior_padding = button->area.paddingx * panel->scale;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -280,18 +280,17 @@ int button_compute_desired_size(void *obj)
|
|||||||
else
|
else
|
||||||
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
||||||
if (button->backend->max_icon_size) {
|
if (button->backend->max_icon_size) {
|
||||||
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
icon_w = MIN(icon_w, button->backend->max_icon_size * panel->scale);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -300,10 +299,11 @@ int button_compute_desired_size(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
} else {
|
} else {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -313,10 +313,12 @@ int button_compute_desired_size(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
txt_height_ink = txt_height = txt_width = 0;
|
txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -336,9 +338,9 @@ gboolean resize_button(void *obj)
|
|||||||
Button *button = (Button *)obj;
|
Button *button = (Button *)obj;
|
||||||
Panel *panel = (Panel *)button->area.panel;
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
Area *area = &button->area;
|
Area *area = &button->area;
|
||||||
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy);
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy) * panel->scale;
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
||||||
int interior_padding = button->area.paddingx;
|
int interior_padding = button->area.paddingx * panel->scale;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -347,8 +349,8 @@ gboolean resize_button(void *obj)
|
|||||||
else
|
else
|
||||||
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
||||||
if (button->backend->max_icon_size) {
|
if (button->backend->max_icon_size) {
|
||||||
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
icon_w = MIN(icon_w, button->backend->max_icon_size * panel->scale);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
@@ -369,10 +371,9 @@ gboolean resize_button(void *obj)
|
|||||||
available_h = panel->area.height;
|
available_h = panel->area.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -381,9 +382,11 @@ gboolean resize_button(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
} else {
|
} else {
|
||||||
txt_height_ink = txt_height = txt_width = 0;
|
txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
@@ -436,6 +439,7 @@ gboolean resize_button(void *obj)
|
|||||||
void draw_button(void *obj, cairo_t *c)
|
void draw_button(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Button *button = obj;
|
Button *button = obj;
|
||||||
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
|
|
||||||
if (button->frontend->icon) {
|
if (button->frontend->icon) {
|
||||||
// Render icon
|
// Render icon
|
||||||
@@ -457,10 +461,12 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
// Render text
|
// Render text
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_font_description(layout, button->backend->font_desc);
|
pango_layout_set_font_description(layout, button->backend->font_desc);
|
||||||
pango_layout_set_width(layout, button->frontend->textw * PANGO_SCALE);
|
pango_layout_set_width(layout, (button->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
pango_layout_set_alignment(layout, button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
pango_layout_set_alignment(layout, button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
||||||
@@ -475,6 +481,7 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ static char buf_time[256];
|
|||||||
static char buf_date[256];
|
static char buf_date[256];
|
||||||
static char buf_tooltip[512];
|
static char buf_tooltip[512];
|
||||||
int clock_enabled;
|
int clock_enabled;
|
||||||
static timeout *clock_timeout;
|
static Timer clock_timer;
|
||||||
|
|
||||||
void clock_init_fonts();
|
void clock_init_fonts();
|
||||||
char *clock_get_tooltip(void *obj);
|
char *clock_get_tooltip(void *obj);
|
||||||
@@ -61,11 +61,11 @@ void clock_dump_geometry(void *obj, int indent);
|
|||||||
void default_clock()
|
void default_clock()
|
||||||
{
|
{
|
||||||
clock_enabled = 0;
|
clock_enabled = 0;
|
||||||
clock_timeout = NULL;
|
|
||||||
time1_format = NULL;
|
time1_format = NULL;
|
||||||
time1_timezone = NULL;
|
time1_timezone = NULL;
|
||||||
time2_format = NULL;
|
time2_format = NULL;
|
||||||
time2_timezone = NULL;
|
time2_timezone = NULL;
|
||||||
|
INIT_TIMER(clock_timer);
|
||||||
time_tooltip_format = NULL;
|
time_tooltip_format = NULL;
|
||||||
time_tooltip_timezone = NULL;
|
time_tooltip_timezone = NULL;
|
||||||
clock_lclick_command = NULL;
|
clock_lclick_command = NULL;
|
||||||
@@ -110,8 +110,7 @@ void cleanup_clock()
|
|||||||
clock_uwheel_command = NULL;
|
clock_uwheel_command = NULL;
|
||||||
free(clock_dwheel_command);
|
free(clock_dwheel_command);
|
||||||
clock_dwheel_command = NULL;
|
clock_dwheel_command = NULL;
|
||||||
stop_timeout(clock_timeout);
|
destroy_timer(&clock_timer);
|
||||||
clock_timeout = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tm *clock_gettime_for_tz(const char *timezone)
|
struct tm *clock_gettime_for_tz(const char *timezone)
|
||||||
@@ -155,7 +154,7 @@ void update_clocks_sec(void *arg)
|
|||||||
{
|
{
|
||||||
gettimeofday(&time_clock, 0);
|
gettimeofday(&time_clock, 0);
|
||||||
update_clocks();
|
update_clocks();
|
||||||
clock_timeout = add_timeout(ms_until_second_change(&time_clock), 0, update_clocks_sec, 0, &clock_timeout);
|
change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_sec, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_clocks_min(void *arg)
|
void update_clocks_min(void *arg)
|
||||||
@@ -167,7 +166,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;
|
||||||
clock_timeout = add_timeout(ms_until_second_change(&time_clock), 0, update_clocks_min, 0, &clock_timeout);
|
change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_min, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean time_format_needs_sec_ticks(char *time_format)
|
gboolean time_format_needs_sec_ticks(char *time_format)
|
||||||
@@ -216,7 +215,7 @@ void init_clock_panel(void *p)
|
|||||||
strftime(buf_tooltip, sizeof(buf_tooltip), time_tooltip_format, clock_gettime_for_tz(time_tooltip_timezone));
|
strftime(buf_tooltip, sizeof(buf_tooltip), time_tooltip_format, clock_gettime_for_tz(time_tooltip_timezone));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clock_timeout) {
|
if (!clock_timer.enabled_) {
|
||||||
if (time_format_needs_sec_ticks(time1_format) || time_format_needs_sec_ticks(time2_format)) {
|
if (time_format_needs_sec_ticks(time1_format) || time_format_needs_sec_ticks(time2_format)) {
|
||||||
update_clocks_sec(NULL);
|
update_clocks_sec(NULL);
|
||||||
} else {
|
} else {
|
||||||
@@ -262,10 +261,8 @@ void clock_default_font_changed()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void clock_compute_text_geometry(Clock *clock,
|
void clock_compute_text_geometry(Clock *clock,
|
||||||
int *time_height_ink,
|
|
||||||
int *time_height,
|
int *time_height,
|
||||||
int *time_width,
|
int *time_width,
|
||||||
int *date_height_ink,
|
|
||||||
int *date_height,
|
int *date_height,
|
||||||
int *date_width)
|
int *date_width)
|
||||||
{
|
{
|
||||||
@@ -274,10 +271,8 @@ void clock_compute_text_geometry(Clock *clock,
|
|||||||
time2_format ? buf_date : NULL,
|
time2_format ? buf_date : NULL,
|
||||||
time1_font_desc,
|
time1_font_desc,
|
||||||
time2_font_desc,
|
time2_font_desc,
|
||||||
time_height_ink,
|
|
||||||
time_height,
|
time_height,
|
||||||
time_width,
|
time_width,
|
||||||
date_height_ink,
|
|
||||||
date_height,
|
date_height,
|
||||||
date_width);
|
date_width);
|
||||||
}
|
}
|
||||||
@@ -307,6 +302,7 @@ gboolean resize_clock(void *obj)
|
|||||||
void draw_clock(void *obj, cairo_t *c)
|
void draw_clock(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Clock *clock = (Clock *)obj;
|
Clock *clock = (Clock *)obj;
|
||||||
|
Panel *panel = (Panel *)clock->area.panel;
|
||||||
draw_text_area(&clock->area,
|
draw_text_area(&clock->area,
|
||||||
c,
|
c,
|
||||||
buf_time,
|
buf_time,
|
||||||
@@ -315,7 +311,8 @@ void draw_clock(void *obj, cairo_t *c)
|
|||||||
time2_font_desc,
|
time2_font_desc,
|
||||||
clock->time1_posy,
|
clock->time1_posy,
|
||||||
clock->time2_posy,
|
clock->time2_posy,
|
||||||
&clock->font);
|
&clock->font,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clock_dump_geometry(void *obj, int indent)
|
void clock_dump_geometry(void *obj, int indent)
|
||||||
|
|||||||
@@ -244,7 +244,11 @@ void add_entry(char *key, char *value)
|
|||||||
char *value1 = 0, *value2 = 0, *value3 = 0;
|
char *value1 = 0, *value2 = 0, *value3 = 0;
|
||||||
|
|
||||||
/* Background and border */
|
/* Background and border */
|
||||||
if (strcmp(key, "rounded") == 0) {
|
if (strcmp(key, "scale_relative_to_dpi") == 0) {
|
||||||
|
ui_scale_dpi_ref = atof(value);
|
||||||
|
} else if (strcmp(key, "scale_relative_to_screen_height") == 0) {
|
||||||
|
ui_scale_monitor_size_ref = atof(value);
|
||||||
|
} else if (strcmp(key, "rounded") == 0) {
|
||||||
// 'rounded' is the first parameter => alloc a new background
|
// 'rounded' is the first parameter => alloc a new background
|
||||||
if (backgrounds->len > 0) {
|
if (backgrounds->len > 0) {
|
||||||
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
||||||
|
|||||||
5
src/default_icon.c
Normal file
5
src/default_icon.c
Normal file
File diff suppressed because one or more lines are too long
10
src/default_icon.h
Normal file
10
src/default_icon.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef default_icon_h
|
||||||
|
#define default_icon_h
|
||||||
|
|
||||||
|
#include <Imlib2.h>
|
||||||
|
|
||||||
|
extern int default_icon_width;
|
||||||
|
extern int default_icon_height;
|
||||||
|
extern DATA32 default_icon_data[];
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -41,6 +41,7 @@ Execp *create_execp()
|
|||||||
execp->backend->cache_icon = TRUE;
|
execp->backend->cache_icon = TRUE;
|
||||||
execp->backend->centered = TRUE;
|
execp->backend->centered = TRUE;
|
||||||
execp->backend->font_color.alpha = 0.5;
|
execp->backend->font_color.alpha = 0.5;
|
||||||
|
INIT_TIMER(execp->backend->timer);
|
||||||
return execp;
|
return execp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,8 +68,7 @@ void destroy_execp(void *obj)
|
|||||||
free_and_null(execp);
|
free_and_null(execp);
|
||||||
} else {
|
} else {
|
||||||
// This is a backend element
|
// This is a backend element
|
||||||
stop_timeout(execp->backend->timer);
|
destroy_timer(&execp->backend->timer);
|
||||||
execp->backend->timer = NULL;
|
|
||||||
|
|
||||||
free_icon(execp->backend->icon);
|
free_icon(execp->backend->icon);
|
||||||
free_and_null(execp->backend->buf_stdout);
|
free_and_null(execp->backend->buf_stdout);
|
||||||
@@ -192,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);
|
||||||
|
|
||||||
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
change_timer(&execp->backend->timer, true, 10, 0, execp_timer_callback, execp);
|
||||||
|
|
||||||
execp_update_post_read(execp);
|
execp_update_post_read(execp);
|
||||||
}
|
}
|
||||||
@@ -304,7 +304,6 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
int *icon_w,
|
int *icon_w,
|
||||||
int *icon_h,
|
int *icon_h,
|
||||||
gboolean *text_next_line,
|
gboolean *text_next_line,
|
||||||
int *txt_height_ink,
|
|
||||||
int *txt_height,
|
int *txt_height,
|
||||||
int *txt_width,
|
int *txt_width,
|
||||||
int *new_size,
|
int *new_size,
|
||||||
@@ -312,9 +311,9 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
{
|
{
|
||||||
Panel *panel = (Panel *)execp->area.panel;
|
Panel *panel = (Panel *)execp->area.panel;
|
||||||
Area *area = &execp->area;
|
Area *area = &execp->area;
|
||||||
*horiz_padding = (panel_horizontal ? area->paddingxlr : area->paddingy);
|
*horiz_padding = (panel_horizontal ? area->paddingxlr : area->paddingy) * panel->scale;
|
||||||
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr);
|
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr) * panel->scale;
|
||||||
*interior_padding = area->paddingx;
|
*interior_padding = area->paddingx * panel->scale;
|
||||||
|
|
||||||
if (reload_icon(execp)) {
|
if (reload_icon(execp)) {
|
||||||
if (execp->backend->icon) {
|
if (execp->backend->icon) {
|
||||||
@@ -333,7 +332,7 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
int available_w, available_h;
|
int available_w, available_h;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
available_w = panel->area.width;
|
available_w = panel->area.width;
|
||||||
available_h = area->height - 2 * area->paddingy - left_right_border_width(area);
|
available_h = area->height - 2 * *horiz_padding - left_right_border_width(area);
|
||||||
} else {
|
} else {
|
||||||
available_w = !text_next_line
|
available_w = !text_next_line
|
||||||
? area->width - *icon_w - (*icon_w ? *interior_padding : 0) - 2 * *horiz_padding -
|
? area->width - *icon_w - (*icon_w ? *interior_padding : 0) - 2 * *horiz_padding -
|
||||||
@@ -342,7 +341,6 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
available_h = panel->area.height;
|
available_h = panel->area.height;
|
||||||
}
|
}
|
||||||
get_text_size2(execp->backend->font_desc,
|
get_text_size2(execp->backend->font_desc,
|
||||||
txt_height_ink,
|
|
||||||
txt_height,
|
txt_height,
|
||||||
txt_width,
|
txt_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -351,7 +349,9 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
strlen(execp->backend->text),
|
strlen(execp->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
execp->backend->has_markup);
|
execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
execp->backend->has_markup,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
*resized = FALSE;
|
*resized = FALSE;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -385,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_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
int new_size;
|
int new_size;
|
||||||
gboolean resized;
|
gboolean resized;
|
||||||
execp_compute_icon_text_geometry(execp,
|
execp_compute_icon_text_geometry(execp,
|
||||||
@@ -395,7 +395,6 @@ int execp_compute_desired_size(void *obj)
|
|||||||
&icon_w,
|
&icon_w,
|
||||||
&icon_h,
|
&icon_h,
|
||||||
&text_next_line,
|
&text_next_line,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
&new_size,
|
&new_size,
|
||||||
@@ -410,7 +409,7 @@ gboolean resize_execp(void *obj)
|
|||||||
int horiz_padding, vert_padding, interior_padding;
|
int horiz_padding, vert_padding, interior_padding;
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
gboolean text_next_line;
|
gboolean text_next_line;
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
int new_size;
|
int new_size;
|
||||||
gboolean resized;
|
gboolean resized;
|
||||||
execp_compute_icon_text_geometry(execp,
|
execp_compute_icon_text_geometry(execp,
|
||||||
@@ -420,7 +419,6 @@ gboolean resize_execp(void *obj)
|
|||||||
&icon_w,
|
&icon_w,
|
||||||
&icon_h,
|
&icon_h,
|
||||||
&text_next_line,
|
&text_next_line,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
&new_size,
|
&new_size,
|
||||||
@@ -476,7 +474,11 @@ 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;
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
Panel *panel = (Panel *)execp->area.panel;
|
||||||
|
|
||||||
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = 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);
|
||||||
@@ -486,7 +488,8 @@ 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 * PANGO_SCALE);
|
pango_layout_set_width(layout, (execp->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
|
pango_layout_set_height(layout, (execp->frontend->texth + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
pango_layout_set_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);
|
||||||
@@ -504,6 +507,7 @@ 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)
|
||||||
@@ -540,10 +544,8 @@ void execp_force_update(Execp *execp)
|
|||||||
if (execp->backend->child_pipe_stdout > 0) {
|
if (execp->backend->child_pipe_stdout > 0) {
|
||||||
// Command currently running, nothing to do
|
// Command currently running, nothing to do
|
||||||
} else {
|
} else {
|
||||||
if (execp->backend->timer)
|
|
||||||
stop_timeout(execp->backend->timer);
|
|
||||||
// Run command right away
|
// Run command right away
|
||||||
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
change_timer(&execp->backend->timer, true, 10, 0, execp_timer_callback, execp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,8 +759,7 @@ gboolean read_execp(void *obj)
|
|||||||
close(execp->backend->child_pipe_stderr);
|
close(execp->backend->child_pipe_stderr);
|
||||||
execp->backend->child_pipe_stderr = -1;
|
execp->backend->child_pipe_stderr = -1;
|
||||||
if (execp->backend->interval)
|
if (execp->backend->interval)
|
||||||
execp->backend->timer =
|
change_timer(&execp->backend->timer, true, execp->backend->interval * 1000, 0, execp_timer_callback, execp);
|
||||||
add_timeout(execp->backend->interval * 1000, 0, execp_timer_callback, execp, &execp->backend->timer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ansi_clear_screen = (char*)"\x1b[2J";
|
char *ansi_clear_screen = (char*)"\x1b[2J";
|
||||||
@@ -882,22 +883,22 @@ gboolean read_execp(void *obj)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *time_to_string(int seconds, char *buffer)
|
const char *time_to_string(int seconds, char *buffer, size_t buffer_size)
|
||||||
{
|
{
|
||||||
if (seconds < 60) {
|
if (seconds < 60) {
|
||||||
sprintf(buffer, "%ds", seconds);
|
snprintf(buffer, buffer_size, "%ds", seconds);
|
||||||
} else if (seconds < 60 * 60) {
|
} else if (seconds < 60 * 60) {
|
||||||
int m = seconds / 60;
|
int m = seconds / 60;
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
int s = seconds;
|
int s = seconds;
|
||||||
sprintf(buffer, "%d:%ds", m, s);
|
snprintf(buffer, buffer_size, "%d:%ds", m, s);
|
||||||
} else {
|
} else {
|
||||||
int h = seconds / (60 * 60);
|
int h = seconds / (60 * 60);
|
||||||
seconds = seconds % (60 * 60);
|
seconds = seconds % (60 * 60);
|
||||||
int m = seconds / 60;
|
int m = seconds / 60;
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
int s = seconds;
|
int s = seconds;
|
||||||
sprintf(buffer, "%d:%d:%ds", h, m, s);
|
snprintf(buffer, buffer_size, "%d:%d:%ds", h, m, s);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@@ -923,35 +924,39 @@ char *execp_get_tooltip(void *obj)
|
|||||||
if (execp->backend->last_update_finish_time) {
|
if (execp->backend->last_update_finish_time) {
|
||||||
// We updated at least once
|
// We updated at least once
|
||||||
if (execp->backend->interval > 0) {
|
if (execp->backend->interval > 0) {
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
"Last update finished %s ago (took %s). Next update starting in %s.",
|
sizeof(execp->backend->tooltip_text),
|
||||||
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
"Last update finished %s ago (took %s). Next update starting in %s.",
|
||||||
time_to_string((int)execp->backend->last_update_duration, tmp_buf2),
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1, sizeof(tmp_buf1)),
|
||||||
time_to_string((int)(execp->backend->interval - (now - execp->backend->last_update_finish_time)),
|
time_to_string((int)execp->backend->last_update_duration, tmp_buf2, sizeof(tmp_buf2)),
|
||||||
tmp_buf3));
|
time_to_string((int)(execp->backend->interval - (now - execp->backend->last_update_finish_time)),
|
||||||
|
tmp_buf3, sizeof(tmp_buf3)));
|
||||||
} else {
|
} else {
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
"Last update finished %s ago (took %s).",
|
sizeof(execp->backend->tooltip_text),
|
||||||
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
"Last update finished %s ago (took %s).",
|
||||||
time_to_string((int)execp->backend->last_update_duration, tmp_buf2));
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1, sizeof(tmp_buf1)),
|
||||||
|
time_to_string((int)execp->backend->last_update_duration, tmp_buf2, sizeof(tmp_buf2)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we never requested an update
|
// we never requested an update
|
||||||
sprintf(execp->backend->tooltip_text, "Never updated. No update scheduled.");
|
snprintf(execp->backend->tooltip_text, sizeof(execp->backend->tooltip_text), "Never updated. No update scheduled.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Currently executing command
|
// Currently executing command
|
||||||
if (execp->backend->last_update_finish_time) {
|
if (execp->backend->last_update_finish_time) {
|
||||||
// we finished updating at least once
|
// we finished updating at least once
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
"Last update finished %s ago. Update in progress (started %s ago).",
|
sizeof(execp->backend->tooltip_text),
|
||||||
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1),
|
"Last update finished %s ago. Update in progress (started %s ago).",
|
||||||
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf3));
|
time_to_string((int)(now - execp->backend->last_update_finish_time), tmp_buf1, sizeof(tmp_buf1)),
|
||||||
|
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf3, sizeof(tmp_buf3)));
|
||||||
} else {
|
} else {
|
||||||
// we never finished an update
|
// we never finished an update
|
||||||
sprintf(execp->backend->tooltip_text,
|
snprintf(execp->backend->tooltip_text,
|
||||||
"First update in progress (started %s seconds ago).",
|
sizeof(execp->backend->tooltip_text),
|
||||||
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf1));
|
"First update in progress (started %s seconds ago).",
|
||||||
|
time_to_string((int)(now - execp->backend->last_update_start_time), tmp_buf1, sizeof(tmp_buf1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strdup(execp->backend->tooltip_text);
|
return strdup(execp->backend->tooltip_text);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ typedef struct ExecpBackend {
|
|||||||
Background *bg;
|
Background *bg;
|
||||||
|
|
||||||
// Backend state:
|
// Backend state:
|
||||||
timeout *timer;
|
Timer timer;
|
||||||
int child_pipe_stdout;
|
int child_pipe_stdout;
|
||||||
int child_pipe_stderr;
|
int child_pipe_stderr;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
|
|||||||
@@ -65,14 +65,14 @@ void cleanup_freespace(Panel *panel)
|
|||||||
panel->freespace_list = NULL;
|
panel->freespace_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int freespace_get_max_size(Panel *p)
|
int freespace_get_max_size(Panel *panel)
|
||||||
{
|
{
|
||||||
if (panel_shrink)
|
if (panel_shrink)
|
||||||
return 0;
|
return 0;
|
||||||
// Get space used by every element except the freespace
|
// Get space used by every element except the freespace
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int spacers = 0;
|
int spacers = 0;
|
||||||
for (GList *walk = p->area.children; walk; walk = g_list_next(walk)) {
|
for (GList *walk = panel->area.children; walk; walk = g_list_next(walk)) {
|
||||||
Area *a = (Area *)walk->data;
|
Area *a = (Area *)walk->data;
|
||||||
|
|
||||||
if (!a->on_screen)
|
if (!a->on_screen)
|
||||||
@@ -83,15 +83,15 @@ int freespace_get_max_size(Panel *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size += a->width + p->area.paddingx;
|
size += a->width + panel->area.paddingx * panel->scale;
|
||||||
else
|
else
|
||||||
size += a->height + p->area.paddingy;
|
size += a->height + panel->area.paddingy * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size = p->area.width - size - left_right_border_width(&p->area) - p->area.paddingxlr;
|
size = panel->area.width - size - left_right_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
||||||
else
|
else
|
||||||
size = p->area.height - size - top_bottom_border_width(&p->area) - p->area.paddingxlr;
|
size = panel->area.height - size - top_bottom_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
||||||
|
|
||||||
return size / spacers;
|
return size / spacers;
|
||||||
}
|
}
|
||||||
|
|||||||
62
src/init.c
62
src/init.c
@@ -12,11 +12,13 @@
|
|||||||
#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"
|
||||||
@@ -48,6 +50,15 @@ void handle_cli_arguments(int argc, char **argv)
|
|||||||
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
|
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
|
||||||
fprintf(stdout, "tint2 version %s\n", VERSION_STRING);
|
fprintf(stdout, "tint2 version %s\n", VERSION_STRING);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
} else if (strcmp(argv[i], "--test") == 0) {
|
||||||
|
run_all_tests(false);
|
||||||
|
exit(0);
|
||||||
|
} else if (strcmp(argv[i], "--test-verbose") == 0) {
|
||||||
|
run_all_tests(true);
|
||||||
|
exit(0);
|
||||||
|
} else if (strcmp(argv[i], "--dump-image-data") == 0) {
|
||||||
|
dump_image_data(argv[i+1], argv[i+2]);
|
||||||
|
exit(0);
|
||||||
} else if (strcmp(argv[i], "-c") == 0) {
|
} else if (strcmp(argv[i], "-c") == 0) {
|
||||||
if (i + 1 < argc) {
|
if (i + 1 < argc) {
|
||||||
i++;
|
i++;
|
||||||
@@ -94,6 +105,7 @@ 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;
|
||||||
if (debug_fps) {
|
if (debug_fps) {
|
||||||
init_fps_distribution();
|
init_fps_distribution();
|
||||||
char *s = getenv("TRACING_FPS_THRESHOLD");
|
char *s = getenv("TRACING_FPS_THRESHOLD");
|
||||||
@@ -103,25 +115,25 @@ void handle_env_vars()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static timeout *detect_compositor_timer = NULL;
|
static Timer detect_compositor_timer = DEFAULT_TIMER;
|
||||||
static int detect_compositor_timer_counter = 0;
|
static int detect_compositor_timer_counter = 0;
|
||||||
|
|
||||||
void detect_compositor(void *arg)
|
void detect_compositor(void *arg)
|
||||||
{
|
{
|
||||||
if (server.composite_manager) {
|
if (server.composite_manager) {
|
||||||
stop_timeout(detect_compositor_timer);
|
stop_timer(&detect_compositor_timer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
detect_compositor_timer_counter--;
|
detect_compositor_timer_counter--;
|
||||||
if (detect_compositor_timer_counter < 0) {
|
if (detect_compositor_timer_counter < 0) {
|
||||||
stop_timeout(detect_compositor_timer);
|
stop_timer(&detect_compositor_timer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No compositor, check for one
|
// No compositor, check for one
|
||||||
if (XGetSelectionOwner(server.display, server.atom._NET_WM_CM_S0) != None) {
|
if (XGetSelectionOwner(server.display, server.atom._NET_WM_CM_S0) != None) {
|
||||||
stop_timeout(detect_compositor_timer);
|
stop_timer(&detect_compositor_timer);
|
||||||
// Restart tint2
|
// Restart tint2
|
||||||
fprintf(stderr, "tint2: Detected compositor, restarting tint2...\n");
|
fprintf(stderr, "tint2: Detected compositor, restarting tint2...\n");
|
||||||
kill(getpid(), SIGUSR1);
|
kill(getpid(), SIGUSR1);
|
||||||
@@ -134,15 +146,15 @@ void start_detect_compositor()
|
|||||||
if (server.composite_manager)
|
if (server.composite_manager)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stop_timeout(detect_compositor_timer);
|
|
||||||
// Check every 0.5 seconds for up to 30 seconds
|
// Check every 0.5 seconds for up to 30 seconds
|
||||||
detect_compositor_timer_counter = 60;
|
detect_compositor_timer_counter = 60;
|
||||||
detect_compositor_timer = add_timeout(500, 500, detect_compositor, 0, &detect_compositor_timer);
|
INIT_TIMER(detect_compositor_timer);
|
||||||
|
change_timer(&detect_compositor_timer, true, 500, 500, detect_compositor, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_default_elements()
|
void create_default_elements()
|
||||||
{
|
{
|
||||||
default_timeout();
|
default_timers();
|
||||||
default_systray();
|
default_systray();
|
||||||
memset(&server, 0, sizeof(server));
|
memset(&server, 0, sizeof(server));
|
||||||
#ifdef ENABLE_BATTERY
|
#ifdef ENABLE_BATTERY
|
||||||
@@ -157,6 +169,22 @@ void create_default_elements()
|
|||||||
default_panel();
|
default_panel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load_default_task_icon()
|
||||||
|
{
|
||||||
|
const gchar *const *data_dirs = g_get_system_data_dirs();
|
||||||
|
for (int i = 0; data_dirs[i] != NULL; i++) {
|
||||||
|
gchar *path = g_build_filename(data_dirs[i], "tint2", "default_icon.png", NULL);
|
||||||
|
if (g_file_test(path, G_FILE_TEST_EXISTS))
|
||||||
|
default_icon = load_image(path, TRUE);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
if (!default_icon) {
|
||||||
|
default_icon = imlib_create_image_using_data(default_icon_width,
|
||||||
|
default_icon_height,
|
||||||
|
default_icon_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init_post_config()
|
void init_post_config()
|
||||||
{
|
{
|
||||||
server_init_visual();
|
server_init_visual();
|
||||||
@@ -167,20 +195,7 @@ void init_post_config()
|
|||||||
imlib_context_set_colormap(server.colormap);
|
imlib_context_set_colormap(server.colormap);
|
||||||
|
|
||||||
init_signals_postconfig();
|
init_signals_postconfig();
|
||||||
|
load_default_task_icon();
|
||||||
// load default icon
|
|
||||||
const gchar *const *data_dirs = g_get_system_data_dirs();
|
|
||||||
for (int i = 0; data_dirs[i] != NULL; i++) {
|
|
||||||
gchar *path = g_build_filename(data_dirs[i], "tint2", "default_icon.png", NULL);
|
|
||||||
if (g_file_test(path, G_FILE_TEST_EXISTS))
|
|
||||||
default_icon = load_image(path, TRUE);
|
|
||||||
g_free(path);
|
|
||||||
}
|
|
||||||
if (!default_icon) {
|
|
||||||
fprintf(stderr,
|
|
||||||
RED "Could not load default_icon.png. Please check that tint2 has been installed correctly!" RESET
|
|
||||||
"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
XSync(server.display, False);
|
XSync(server.display, False);
|
||||||
}
|
}
|
||||||
@@ -222,10 +237,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()) {
|
||||||
@@ -259,6 +274,7 @@ void cleanup()
|
|||||||
cleanup_battery();
|
cleanup_battery();
|
||||||
#endif
|
#endif
|
||||||
cleanup_separator();
|
cleanup_separator();
|
||||||
|
cleanup_taskbar();
|
||||||
cleanup_panel();
|
cleanup_panel();
|
||||||
cleanup_config();
|
cleanup_config();
|
||||||
|
|
||||||
@@ -273,7 +289,7 @@ void cleanup()
|
|||||||
xsettings_client = NULL;
|
xsettings_client = NULL;
|
||||||
|
|
||||||
cleanup_server();
|
cleanup_server();
|
||||||
cleanup_timeout();
|
cleanup_timers();
|
||||||
|
|
||||||
if (server.display)
|
if (server.display)
|
||||||
XCloseDisplay(server.display);
|
XCloseDisplay(server.display);
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ void expand_exec(DesktopEntry *entry, const char *path)
|
|||||||
// %c -> Name
|
// %c -> Name
|
||||||
// %k -> path
|
// %k -> path
|
||||||
if (entry->exec) {
|
if (entry->exec) {
|
||||||
char *exec2 = calloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
|
size_t buf_size = strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
|
||||||
(entry->icon ? strlen(entry->icon) : 1) + 100,
|
(entry->icon ? strlen(entry->icon) : 1) + 100;
|
||||||
1);
|
char *exec2 = calloc(buf_size, 1);
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
// p will never point to an escaped char
|
// p will never point to an escaped char
|
||||||
for (p = entry->exec, q = exec2; *p; p++, q++) {
|
for (p = entry->exec, q = exec2; *p; p++, q++) {
|
||||||
@@ -82,23 +82,30 @@ void expand_exec(DesktopEntry *entry, const char *path)
|
|||||||
if (!*p)
|
if (!*p)
|
||||||
break;
|
break;
|
||||||
if (*p == 'i' && entry->icon != NULL) {
|
if (*p == 'i' && entry->icon != NULL) {
|
||||||
sprintf(q, "--icon '%s'", entry->icon);
|
snprintf(q, buf_size, "--icon '%s'", entry->icon);
|
||||||
|
char *old = q;
|
||||||
q += strlen("--icon ''");
|
q += strlen("--icon ''");
|
||||||
q += strlen(entry->icon);
|
q += strlen(entry->icon);
|
||||||
|
buf_size -= (size_t)(q - old);
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else if (*p == 'c' && entry->name != NULL) {
|
} else if (*p == 'c' && entry->name != NULL) {
|
||||||
sprintf(q, "'%s'", entry->name);
|
snprintf(q, buf_size, "'%s'", entry->name);
|
||||||
|
char *old = q;
|
||||||
q += strlen("''");
|
q += strlen("''");
|
||||||
q += strlen(entry->name);
|
q += strlen(entry->name);
|
||||||
|
buf_size -= (size_t)(q - old);
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else if (*p == 'c') {
|
} else if (*p == 'c') {
|
||||||
sprintf(q, "'%s'", path);
|
snprintf(q, buf_size, "'%s'", path);
|
||||||
|
char *old = q;
|
||||||
q += strlen("''");
|
q += strlen("''");
|
||||||
q += strlen(path);
|
q += strlen(path);
|
||||||
|
buf_size -= (size_t)(q - old);
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else if (*p == 'f' || *p == 'F') {
|
} else if (*p == 'f' || *p == 'F') {
|
||||||
sprintf(q, "%c%c", '%', *p);
|
snprintf(q, buf_size, "%c%c", '%', *p);
|
||||||
q += 2;
|
q += 2;
|
||||||
|
buf_size -= 2;
|
||||||
q--; // To balance the q++ in the for
|
q--; // To balance the q++ in the for
|
||||||
} else {
|
} else {
|
||||||
// We don't care about other expansions
|
// We don't care about other expansions
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ int parse_theme_line(char *line, char **key, char **value)
|
|||||||
return parse_dektop_line(line, key, value);
|
return parse_dektop_line(line, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList *icon_locations = NULL;
|
static GSList *icon_locations = NULL;
|
||||||
// Do not free the result.
|
// Do not free the result.
|
||||||
const GSList *get_icon_locations()
|
const GSList *get_icon_locations()
|
||||||
{
|
{
|
||||||
@@ -74,6 +74,21 @@ const GSList *get_icon_locations()
|
|||||||
return icon_locations;
|
return icon_locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GSList *icon_extensions = NULL;
|
||||||
|
const GSList *get_icon_extensions()
|
||||||
|
{
|
||||||
|
if (icon_extensions)
|
||||||
|
return icon_extensions;
|
||||||
|
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, ".png");
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, ".xpm");
|
||||||
|
#ifdef HAVE_RSVG
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, ".svg");
|
||||||
|
#endif
|
||||||
|
icon_extensions = g_slist_append(icon_extensions, "");
|
||||||
|
return icon_extensions;
|
||||||
|
}
|
||||||
|
|
||||||
IconTheme *make_theme(const char *name)
|
IconTheme *make_theme(const char *name)
|
||||||
{
|
{
|
||||||
IconTheme *theme = calloc(1, sizeof(IconTheme));
|
IconTheme *theme = calloc(1, sizeof(IconTheme));
|
||||||
@@ -535,41 +550,42 @@ gint compare_theme_directories(gconstpointer a, gconstpointer b, gpointer size_q
|
|||||||
return abs(da->size - size) - abs(db->size - size);
|
return abs(da->size - size) - abs(db->size - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool is_full_path(const char *s)
|
||||||
|
{
|
||||||
|
if (!s)
|
||||||
|
return FALSE;
|
||||||
|
return s[0] == '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool file_exists(const char *path)
|
||||||
|
{
|
||||||
|
return g_file_test(path, G_FILE_TEST_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *icon_path_from_full_path(const char *s)
|
||||||
|
{
|
||||||
|
if (is_full_path(s) && file_exists(s))
|
||||||
|
return strdup(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
||||||
{
|
{
|
||||||
if (icon_name == NULL)
|
if (!icon_name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// If the icon_name is already a path and the file exists, return it
|
char *result = icon_path_from_full_path(icon_name);
|
||||||
if (strstr(icon_name, "/") == icon_name) {
|
if (result)
|
||||||
if (g_file_test(icon_name, G_FILE_TEST_EXISTS))
|
return result;
|
||||||
return strdup(icon_name);
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GSList *basenames = get_icon_locations();
|
const GSList *basenames = get_icon_locations();
|
||||||
GSList *extensions = NULL;
|
const GSList *extensions = get_icon_extensions();
|
||||||
extensions = g_slist_append(extensions, ".png");
|
|
||||||
extensions = g_slist_append(extensions, ".xpm");
|
|
||||||
#ifdef HAVE_RSVG
|
|
||||||
extensions = g_slist_append(extensions, ".svg");
|
|
||||||
#endif
|
|
||||||
// if the icon name already contains one of the extensions (e.g. vlc.png instead of vlc) add a special entry
|
|
||||||
for (GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
|
||||||
char *extension = (char *)ext->data;
|
|
||||||
if (strlen(icon_name) > strlen(extension) &&
|
|
||||||
strcmp(extension, icon_name + strlen(icon_name) - strlen(extension)) == 0) {
|
|
||||||
extensions = g_slist_append(extensions, "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList *theme;
|
GSList *theme;
|
||||||
|
|
||||||
// Best size match
|
// Best size match
|
||||||
// Contrary to the freedesktop spec, we are not choosing the closest icon in size, but the next larger icon
|
// Contrary to the freedesktop spec, we are not choosing the closest icon in size, but the next larger icon
|
||||||
// otherwise the quality is usually crap (for size 22, if you can choose 16 or 32, you're better with 32)
|
// otherwise the quality is worse when scaling up (for size 22, if you can choose 16 or 32, you're better with 32)
|
||||||
// We do fallback to the closest size if we cannot find a larger or equal icon
|
// We do fallback to the closest size if we cannot find a larger or equal icon
|
||||||
|
|
||||||
// These 3 variables are used for keeping the closest size match
|
// These 3 variables are used for keeping the closest size match
|
||||||
@@ -582,7 +598,7 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
char *next_larger = NULL;
|
char *next_larger = NULL;
|
||||||
GSList *next_larger_theme = NULL;
|
GSList *next_larger_theme = NULL;
|
||||||
|
|
||||||
int file_name_size = 4096;
|
size_t file_name_size = 4096;
|
||||||
char *file_name = calloc(file_name_size, 1);
|
char *file_name = calloc(file_name_size, 1);
|
||||||
|
|
||||||
for (theme = themes; theme; theme = g_slist_next(theme)) {
|
for (theme = themes; theme; theme = g_slist_next(theme)) {
|
||||||
@@ -607,7 +623,7 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
fprintf(stderr, "tint2: Searching directory: %s\n", ((IconThemeDir *)dir->data)->name);
|
fprintf(stderr, "tint2: Searching directory: %s\n", ((IconThemeDir *)dir->data)->name);
|
||||||
const GSList *base;
|
const GSList *base;
|
||||||
for (base = basenames; base; base = g_slist_next(base)) {
|
for (base = basenames; base; base = g_slist_next(base)) {
|
||||||
for (GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
for (const GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
||||||
char *base_name = (char *)base->data;
|
char *base_name = (char *)base->data;
|
||||||
char *theme_name = ((IconTheme *)theme->data)->name;
|
char *theme_name = ((IconTheme *)theme->data)->name;
|
||||||
char *dir_name = ((IconThemeDir *)dir->data)->name;
|
char *dir_name = ((IconThemeDir *)dir->data)->name;
|
||||||
@@ -621,7 +637,7 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
}
|
}
|
||||||
file_name[0] = 0;
|
file_name[0] = 0;
|
||||||
// filename = directory/$(themename)/subdirectory/iconname.extension
|
// filename = directory/$(themename)/subdirectory/iconname.extension
|
||||||
sprintf(file_name, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
snprintf(file_name, (size_t)file_name_size, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
||||||
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
@@ -662,12 +678,10 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
free(file_name);
|
free(file_name);
|
||||||
file_name = NULL;
|
file_name = NULL;
|
||||||
if (next_larger) {
|
if (next_larger) {
|
||||||
g_slist_free(extensions);
|
|
||||||
free(best_file_name);
|
free(best_file_name);
|
||||||
return next_larger;
|
return next_larger;
|
||||||
}
|
}
|
||||||
if (best_file_name) {
|
if (best_file_name) {
|
||||||
g_slist_free(extensions);
|
|
||||||
return best_file_name;
|
return best_file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,18 +690,18 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Searching unthemed icons\n");
|
fprintf(stderr, "tint2: Searching unthemed icons\n");
|
||||||
for (const GSList *base = basenames; base; base = g_slist_next(base)) {
|
for (const GSList *base = basenames; base; base = g_slist_next(base)) {
|
||||||
for (GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
for (const GSList *ext = extensions; ext; ext = g_slist_next(ext)) {
|
||||||
char *base_name = (char *)base->data;
|
char *base_name = (char *)base->data;
|
||||||
char *extension = (char *)ext->data;
|
char *extension = (char *)ext->data;
|
||||||
file_name = calloc(strlen(base_name) + strlen(icon_name) + strlen(extension) + 100, 1);
|
size_t file_name_size2 = strlen(base_name) + strlen(icon_name) + strlen(extension) + 100;
|
||||||
|
file_name = calloc(file_name_size2, 1);
|
||||||
// filename = directory/iconname.extension
|
// filename = directory/iconname.extension
|
||||||
sprintf(file_name, "%s/%s%s", base_name, icon_name, extension);
|
snprintf(file_name, file_name_size2, "%s/%s%s", base_name, icon_name, extension);
|
||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
fprintf(stderr, "tint2: Checking %s\n", file_name);
|
||||||
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
if (debug_icons)
|
if (debug_icons)
|
||||||
fprintf(stderr, "tint2: Found %s\n", file_name);
|
fprintf(stderr, "tint2: Found %s\n", file_name);
|
||||||
g_slist_free(extensions);
|
|
||||||
return file_name;
|
return file_name;
|
||||||
} else {
|
} else {
|
||||||
free(file_name);
|
free(file_name);
|
||||||
@@ -697,7 +711,6 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_slist_free(extensions);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ void init_launcher_panel(void *p)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// This will be recomputed on resize, we just initialize to a non-zero value
|
// This will be recomputed on resize, we just initialize to a non-zero value
|
||||||
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size : 24;
|
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size * panel->scale : 24;
|
||||||
|
|
||||||
launcher->area.on_screen = TRUE;
|
launcher->area.on_screen = TRUE;
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
@@ -174,11 +174,12 @@ void cleanup_launcher_theme(Launcher *launcher)
|
|||||||
|
|
||||||
int launcher_compute_icon_size(Launcher *launcher)
|
int launcher_compute_icon_size(Launcher *launcher)
|
||||||
{
|
{
|
||||||
|
Panel *panel = launcher->area.panel;
|
||||||
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
|
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
|
||||||
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
|
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
|
||||||
(2 * launcher->area.paddingy);
|
(2 * launcher->area.paddingy * panel->scale);
|
||||||
if (launcher_max_icon_size > 0 && icon_size > launcher_max_icon_size)
|
if (launcher_max_icon_size)
|
||||||
icon_size = launcher_max_icon_size;
|
icon_size = MIN(icon_size, launcher_max_icon_size * panel->scale);
|
||||||
return icon_size;
|
return icon_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ void launcher_compute_geometry(Launcher *launcher,
|
|||||||
int *icons_per_row,
|
int *icons_per_row,
|
||||||
int *margin)
|
int *margin)
|
||||||
{
|
{
|
||||||
|
Panel *panel = (Panel*)launcher->area.panel;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (GSList *l = launcher->list_icons; l; l = l->next) {
|
for (GSList *l = launcher->list_icons; l; l = l->next) {
|
||||||
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
||||||
@@ -204,25 +206,25 @@ void launcher_compute_geometry(Launcher *launcher,
|
|||||||
if (!count) {
|
if (!count) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
} else {
|
} else {
|
||||||
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy * panel->scale;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
*icons_per_column = (height + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
*icons_per_column = (height + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
||||||
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
|
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
||||||
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
|
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
|
||||||
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr * panel->scale +
|
||||||
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx);
|
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!count) {
|
if (!count) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
} else {
|
} else {
|
||||||
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy * panel->scale;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
*icons_per_row = (width + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
*icons_per_row = (width + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
||||||
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
|
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
||||||
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
|
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
|
||||||
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr * panel->scale +
|
||||||
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx);
|
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,6 +241,7 @@ int launcher_compute_desired_size(void *obj)
|
|||||||
gboolean resize_launcher(void *obj)
|
gboolean resize_launcher(void *obj)
|
||||||
{
|
{
|
||||||
Launcher *launcher = (Launcher *)obj;
|
Launcher *launcher = (Launcher *)obj;
|
||||||
|
Panel *panel = (Panel*)launcher->area.panel;
|
||||||
|
|
||||||
int size, icons_per_column, icons_per_row, margin;
|
int size, icons_per_column, icons_per_row, margin;
|
||||||
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
|
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
|
||||||
@@ -281,11 +284,11 @@ gboolean resize_launcher(void *obj)
|
|||||||
int posx, posy;
|
int posx, posy;
|
||||||
int start;
|
int start;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy * panel->scale + margin / 2;
|
||||||
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr;
|
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy * panel->scale + margin / 2;
|
||||||
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
|
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -300,17 +303,17 @@ gboolean resize_launcher(void *obj)
|
|||||||
// fprintf(stderr, "tint2: launcher %d : %d,%d\n", i, posx, posy);
|
// fprintf(stderr, "tint2: launcher %d : %d,%d\n", i, posx, posy);
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (i % icons_per_column) {
|
if (i % icons_per_column) {
|
||||||
posy += launcher->icon_size + launcher->area.paddingx;
|
posy += launcher->icon_size + launcher->area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (launcher->icon_size + launcher->area.paddingx);
|
posx += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % icons_per_row) {
|
if (i % icons_per_row) {
|
||||||
posx += launcher->icon_size + launcher->area.paddingx;
|
posx += launcher->icon_size + launcher->area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (launcher->icon_size + launcher->area.paddingx);
|
posy += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,7 +473,7 @@ void launcher_load_icons(Launcher *launcher)
|
|||||||
launcherIcon->area.size_mode = LAYOUT_FIXED;
|
launcherIcon->area.size_mode = LAYOUT_FIXED;
|
||||||
launcherIcon->area._resize = NULL;
|
launcherIcon->area._resize = NULL;
|
||||||
launcherIcon->area._compute_desired_size = launcher_icon_compute_desired_size;
|
launcherIcon->area._compute_desired_size = launcher_icon_compute_desired_size;
|
||||||
sprintf(launcherIcon->area.name, "LauncherIcon %d", index);
|
snprintf(launcherIcon->area.name, sizeof(launcherIcon->area.name), "LauncherIcon %d", index);
|
||||||
launcherIcon->area.resize_needed = 0;
|
launcherIcon->area.resize_needed = 0;
|
||||||
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
|
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
|
||||||
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
|
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
|
||||||
|
|||||||
@@ -723,7 +723,7 @@ void handle_panel_refresh()
|
|||||||
if (debug_frames) {
|
if (debug_frames) {
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
char path[256];
|
char path[256];
|
||||||
sprintf(path, "tint2-%d-panel-%d-frame-%d.png", getpid(), i, frame);
|
snprintf(path, sizeof(path), "tint2-%d-panel-%d-frame-%d.png", getpid(), i, frame);
|
||||||
save_panel_screenshot(&panels[i], path);
|
save_panel_screenshot(&panels[i], path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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_next_timeout()) >= 0) {
|
if (XPending(server.display) > 0 || select(max_fd + 1, &fds, 0, 0, get_duration_to_next_timer_expiration()) >= 0) {
|
||||||
#ifdef HAVE_TRACING
|
#ifdef HAVE_TRACING
|
||||||
start_tracing((void*)run_tint2_event_loop);
|
start_tracing((void*)run_tint2_event_loop);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
97
src/panel.c
97
src/panel.c
@@ -79,11 +79,16 @@ int num_panels;
|
|||||||
GArray *backgrounds;
|
GArray *backgrounds;
|
||||||
GArray *gradients;
|
GArray *gradients;
|
||||||
|
|
||||||
|
double ui_scale_dpi_ref;
|
||||||
|
double ui_scale_monitor_size_ref;
|
||||||
|
|
||||||
Imlib_Image default_icon;
|
Imlib_Image default_icon;
|
||||||
char *default_font = NULL;
|
char *default_font = NULL;
|
||||||
|
|
||||||
void default_panel()
|
void default_panel()
|
||||||
{
|
{
|
||||||
|
ui_scale_dpi_ref = 0;
|
||||||
|
ui_scale_monitor_size_ref = 0;
|
||||||
panels = NULL;
|
panels = NULL;
|
||||||
num_panels = 0;
|
num_panels = 0;
|
||||||
default_icon = NULL;
|
default_icon = NULL;
|
||||||
@@ -130,8 +135,6 @@ void cleanup_panel()
|
|||||||
if (!panels)
|
if (!panels)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cleanup_taskbar();
|
|
||||||
|
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
Panel *p = &panels[i];
|
Panel *p = &panels[i];
|
||||||
|
|
||||||
@@ -145,7 +148,7 @@ void cleanup_panel()
|
|||||||
if (p->main_win)
|
if (p->main_win)
|
||||||
XDestroyWindow(server.display, p->main_win);
|
XDestroyWindow(server.display, p->main_win);
|
||||||
p->main_win = 0;
|
p->main_win = 0;
|
||||||
stop_timeout(p->autohide_timeout);
|
destroy_timer(&p->autohide_timer);
|
||||||
cleanup_freespace(p);
|
cleanup_freespace(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,6 +210,7 @@ void init_panel()
|
|||||||
panels = calloc(num_panels, sizeof(Panel));
|
panels = calloc(num_panels, sizeof(Panel));
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
memcpy(&panels[i], &panel_config, sizeof(Panel));
|
memcpy(&panels[i], &panel_config, sizeof(Panel));
|
||||||
|
INIT_TIMER(panels[i].autohide_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -219,6 +223,13 @@ 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;
|
||||||
|
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;
|
||||||
@@ -356,6 +367,19 @@ void panel_compute_size(Panel *panel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!panel->fractional_width) {
|
||||||
|
if (panel_horizontal)
|
||||||
|
panel->area.width *= panel->scale;
|
||||||
|
else
|
||||||
|
panel->area.height *= panel->scale;
|
||||||
|
}
|
||||||
|
if (!panel->fractional_height) {
|
||||||
|
if (panel_horizontal)
|
||||||
|
panel->area.height *= panel->scale;
|
||||||
|
else
|
||||||
|
panel->area.width *= panel->scale;
|
||||||
|
}
|
||||||
|
|
||||||
if (panel->area.width + panel->marginx > server.monitors[panel->monitor].width)
|
if (panel->area.width + panel->marginx > server.monitors[panel->monitor].width)
|
||||||
panel->area.width = server.monitors[panel->monitor].width - panel->marginx;
|
panel->area.width = server.monitors[panel->monitor].width - panel->marginx;
|
||||||
if (panel->area.height + panel->marginy > server.monitors[panel->monitor].height)
|
if (panel->area.height + panel->marginy > server.monitors[panel->monitor].height)
|
||||||
@@ -450,9 +474,9 @@ gboolean resize_panel(void *obj)
|
|||||||
if (!taskbar->area.on_screen)
|
if (!taskbar->area.on_screen)
|
||||||
continue;
|
continue;
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
taskbar->area.width = 2 * taskbar->area.paddingxlr;
|
taskbar->area.width = 2 * taskbar->area.paddingxlr * panel->scale;
|
||||||
else
|
else
|
||||||
taskbar->area.height = 2 * taskbar->area.paddingxlr;
|
taskbar->area.height = 2 * taskbar->area.paddingxlr * panel->scale;
|
||||||
if (taskbarname_enabled && taskbar->area.children) {
|
if (taskbarname_enabled && taskbar->area.children) {
|
||||||
Area *name = (Area *)taskbar->area.children->data;
|
Area *name = (Area *)taskbar->area.children->data;
|
||||||
if (name->on_screen) {
|
if (name->on_screen) {
|
||||||
@@ -469,9 +493,9 @@ gboolean resize_panel(void *obj)
|
|||||||
continue;
|
continue;
|
||||||
if (!first_child) {
|
if (!first_child) {
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
taskbar->area.width += taskbar->area.paddingx;
|
taskbar->area.width += taskbar->area.paddingx * panel->scale;
|
||||||
else
|
else
|
||||||
taskbar->area.height += taskbar->area.paddingy;
|
taskbar->area.height += taskbar->area.paddingy * panel->scale;
|
||||||
}
|
}
|
||||||
first_child = FALSE;
|
first_child = FALSE;
|
||||||
}
|
}
|
||||||
@@ -494,9 +518,11 @@ gboolean resize_panel(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distribute the remaining size between tasks
|
// Distribute the remaining size between taskbars
|
||||||
if (num_tasks > 0) {
|
if (num_tasks > 0) {
|
||||||
int task_size = total_size / num_tasks;
|
int task_size = total_size / num_tasks;
|
||||||
|
if (taskbar_alignment != ALIGN_LEFT)
|
||||||
|
task_size = MIN(task_size, panel_horizontal ? panel_config.g_task.maximum_width : panel_config.g_task.maximum_height);
|
||||||
for (int i = 0; i < panel->num_desktops; i++) {
|
for (int i = 0; i < panel->num_desktops; i++) {
|
||||||
Taskbar *taskbar = &panel->taskbar[i];
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
if (!taskbar->area.on_screen)
|
if (!taskbar->area.on_screen)
|
||||||
@@ -513,6 +539,49 @@ gboolean resize_panel(void *obj)
|
|||||||
taskbar->area.height += task_size;
|
taskbar->area.height += task_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int slack = total_size - task_size * num_tasks;
|
||||||
|
if (taskbar_alignment == ALIGN_RIGHT) {
|
||||||
|
for (int i = 0; i < panel->num_desktops; i++) {
|
||||||
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
|
if (!taskbar->area.on_screen)
|
||||||
|
continue;
|
||||||
|
if (panel_horizontal)
|
||||||
|
taskbar->area.width += slack;
|
||||||
|
else
|
||||||
|
taskbar->area.height += slack;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (taskbar_alignment == ALIGN_CENTER) {
|
||||||
|
slack /= 2;
|
||||||
|
Taskbar *left_taskbar = NULL;
|
||||||
|
Taskbar *right_taskbar = NULL;
|
||||||
|
for (int i = 0; i < panel->num_desktops; i++) {
|
||||||
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
|
if (!taskbar->area.on_screen)
|
||||||
|
continue;
|
||||||
|
if (panel_horizontal)
|
||||||
|
taskbar->area.width += slack;
|
||||||
|
else
|
||||||
|
taskbar->area.height += slack;
|
||||||
|
taskbar->area.alignment = ALIGN_RIGHT;
|
||||||
|
left_taskbar = taskbar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int i = panel->num_desktops - 1; i >= 0; i--) {
|
||||||
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
|
if (!taskbar->area.on_screen)
|
||||||
|
continue;
|
||||||
|
if (panel_horizontal)
|
||||||
|
taskbar->area.width += slack;
|
||||||
|
else
|
||||||
|
taskbar->area.height += slack;
|
||||||
|
taskbar->area.alignment = ALIGN_LEFT;
|
||||||
|
right_taskbar = taskbar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (left_taskbar == right_taskbar)
|
||||||
|
left_taskbar->area.alignment = ALIGN_CENTER;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// No tasks => expand the first visible taskbar
|
// No tasks => expand the first visible taskbar
|
||||||
for (int i = 0; i < panel->num_desktops; i++) {
|
for (int i = 0; i < panel->num_desktops; i++) {
|
||||||
@@ -1021,15 +1090,15 @@ Button *click_button(Panel *panel, int x, int y)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_autohide_timeout(Panel *p)
|
void stop_autohide_timer(Panel *p)
|
||||||
{
|
{
|
||||||
stop_timeout(p->autohide_timeout);
|
stop_timer(&p->autohide_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void autohide_show(void *p)
|
void autohide_show(void *p)
|
||||||
{
|
{
|
||||||
Panel *panel = (Panel *)p;
|
Panel *panel = (Panel *)p;
|
||||||
stop_autohide_timeout(panel);
|
stop_autohide_timer(panel);
|
||||||
panel->is_hidden = 0;
|
panel->is_hidden = 0;
|
||||||
XMapSubwindows(server.display, panel->main_win); // systray windows
|
XMapSubwindows(server.display, panel->main_win); // systray windows
|
||||||
set_panel_window_geometry(panel);
|
set_panel_window_geometry(panel);
|
||||||
@@ -1041,7 +1110,7 @@ void autohide_show(void *p)
|
|||||||
void autohide_hide(void *p)
|
void autohide_hide(void *p)
|
||||||
{
|
{
|
||||||
Panel *panel = (Panel *)p;
|
Panel *panel = (Panel *)p;
|
||||||
stop_autohide_timeout(panel);
|
stop_autohide_timer(panel);
|
||||||
set_panel_layer(panel, panel_layer);
|
set_panel_layer(panel, panel_layer);
|
||||||
panel->is_hidden = TRUE;
|
panel->is_hidden = TRUE;
|
||||||
XUnmapSubwindows(server.display, panel->main_win); // systray windows
|
XUnmapSubwindows(server.display, panel->main_win); // systray windows
|
||||||
@@ -1053,7 +1122,7 @@ void autohide_trigger_show(Panel *p)
|
|||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
return;
|
return;
|
||||||
change_timeout(&p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p);
|
change_timer(&p->autohide_timer, true, panel_autohide_show_timeout, 0, autohide_show, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void autohide_trigger_hide(Panel *p)
|
void autohide_trigger_hide(Panel *p)
|
||||||
@@ -1068,7 +1137,7 @@ void autohide_trigger_hide(Panel *p)
|
|||||||
if (child)
|
if (child)
|
||||||
return; // mouse over one of the system tray icons
|
return; // mouse over one of the system tray icons
|
||||||
|
|
||||||
change_timeout(&p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
change_timer(&p->autohide_timer, true, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shrink_panel(Panel *panel)
|
void shrink_panel(Panel *panel)
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ 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;
|
||||||
@@ -117,6 +119,7 @@ typedef struct Panel {
|
|||||||
int mouse_pressed_alpha;
|
int mouse_pressed_alpha;
|
||||||
int mouse_pressed_saturation;
|
int mouse_pressed_saturation;
|
||||||
int mouse_pressed_brightness;
|
int mouse_pressed_brightness;
|
||||||
|
double scale;
|
||||||
|
|
||||||
// Per-panel parameters and states for Taskbar and Task
|
// Per-panel parameters and states for Taskbar and Task
|
||||||
GlobalTaskbar g_taskbar;
|
GlobalTaskbar g_taskbar;
|
||||||
@@ -144,7 +147,7 @@ typedef struct Panel {
|
|||||||
gboolean is_hidden;
|
gboolean is_hidden;
|
||||||
int hidden_width, hidden_height;
|
int hidden_width, hidden_height;
|
||||||
Pixmap hidden_pixmap;
|
Pixmap hidden_pixmap;
|
||||||
timeout *autohide_timeout;
|
Timer autohide_timer;
|
||||||
} Panel;
|
} Panel;
|
||||||
|
|
||||||
extern Panel panel_config;
|
extern Panel panel_config;
|
||||||
|
|||||||
@@ -115,31 +115,33 @@ void cleanup_separator()
|
|||||||
int separator_compute_desired_size(void *obj)
|
int separator_compute_desired_size(void *obj)
|
||||||
{
|
{
|
||||||
Separator *separator = (Separator *)obj;
|
Separator *separator = (Separator *)obj;
|
||||||
|
Panel *panel = (Panel*)separator->area.panel;
|
||||||
if (!separator->area.on_screen)
|
if (!separator->area.on_screen)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
return separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr * panel->scale + left_right_border_width(&separator->area);
|
||||||
else
|
else
|
||||||
return separator->thickness + 2 * separator->area.paddingxlr + top_bottom_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean resize_separator(void *obj)
|
gboolean resize_separator(void *obj)
|
||||||
{
|
{
|
||||||
Separator *separator = (Separator *)obj;
|
Separator *separator = (Separator *)obj;
|
||||||
|
Panel *panel = (Panel*)separator->area.panel;
|
||||||
if (!separator->area.on_screen)
|
if (!separator->area.on_screen)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
separator->area.width =
|
separator->area.width =
|
||||||
separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr * panel->scale + left_right_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.height - 2 * separator->area.paddingy - top_bottom_border_width(&separator->area);
|
separator->area.height - 2 * separator->area.paddingy * panel->scale - top_bottom_border_width(&separator->area);
|
||||||
} else {
|
} else {
|
||||||
separator->area.height =
|
separator->area.height =
|
||||||
separator->thickness + 2 * separator->area.paddingxlr + top_bottom_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.width - 2 * separator->area.paddingy - left_right_border_width(&separator->area);
|
separator->area.width - 2 * separator->area.paddingy * panel->scale - left_right_border_width(&separator->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule_redraw(&separator->area);
|
schedule_redraw(&separator->area);
|
||||||
|
|||||||
@@ -141,11 +141,12 @@ void init_systray_panel(void *p)
|
|||||||
|
|
||||||
void systray_compute_geometry(int *size)
|
void systray_compute_geometry(int *size)
|
||||||
{
|
{
|
||||||
|
Panel *panel = (Panel*)systray.area.panel;
|
||||||
systray.icon_size = panel_horizontal ? systray.area.height : systray.area.width;
|
systray.icon_size = panel_horizontal ? systray.area.height : systray.area.width;
|
||||||
systray.icon_size -=
|
systray.icon_size -=
|
||||||
MAX(left_right_border_width(&systray.area), top_bottom_border_width(&systray.area)) + 2 * systray.area.paddingy;
|
MAX(left_right_border_width(&systray.area), top_bottom_border_width(&systray.area)) + 2 * systray.area.paddingy * panel->scale;
|
||||||
if (systray_max_icon_size > 0)
|
if (systray_max_icon_size > 0)
|
||||||
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size);
|
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size * panel->scale);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (GSList *l = systray.list_icons; l; l = l->next) {
|
for (GSList *l = systray.list_icons; l; l = l->next) {
|
||||||
@@ -153,24 +154,24 @@ void systray_compute_geometry(int *size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
int height = systray.area.height - top_bottom_border_width(&systray.area) - 2 * systray.area.paddingy;
|
int height = systray.area.height - top_bottom_border_width(&systray.area) - 2 * systray.area.paddingy * panel->scale;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
systray.icons_per_column = (height + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
systray.icons_per_column = (height + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx) - systray.icon_size;
|
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
||||||
systray.icons_per_row = count / systray.icons_per_column + (count % systray.icons_per_column != 0);
|
systray.icons_per_row = count / systray.icons_per_column + (count % systray.icons_per_column != 0);
|
||||||
*size = left_right_border_width(&systray.area) + 2 * systray.area.paddingxlr +
|
*size = left_right_border_width(&systray.area) + 2 * systray.area.paddingxlr * panel->scale +
|
||||||
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx);
|
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx * panel->scale);
|
||||||
} else {
|
} else {
|
||||||
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy;
|
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy * panel->scale;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
systray.icons_per_row = (width + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
systray.icons_per_row = (width + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx) - systray.icon_size;
|
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
||||||
systray.icons_per_column = count / systray.icons_per_row + (count % systray.icons_per_row != 0);
|
systray.icons_per_column = count / systray.icons_per_row + (count % systray.icons_per_row != 0);
|
||||||
*size = top_bottom_border_width(&systray.area) + (2 * systray.area.paddingxlr) +
|
*size = top_bottom_border_width(&systray.area) + (2 * systray.area.paddingxlr * panel->scale) +
|
||||||
(systray.icon_size * systray.icons_per_column) +
|
(systray.icon_size * systray.icons_per_column) +
|
||||||
((systray.icons_per_column - 1) * systray.area.paddingx);
|
((systray.icons_per_column - 1) * systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,13 +282,13 @@ void on_change_systray(void *obj)
|
|||||||
int posx, posy;
|
int posx, posy;
|
||||||
int start;
|
int start;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
posy = start = top_border_width(&panel->area) + panel->area.paddingy + top_border_width(&systray.area) +
|
posy = start = top_border_width(&panel->area) + panel->area.paddingy * panel->scale + top_border_width(&systray.area) +
|
||||||
systray.area.paddingy + systray.margin / 2;
|
systray.area.paddingy * panel->scale + systray.margin / 2;
|
||||||
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr;
|
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&panel->area) + panel->area.paddingy + left_border_width(&systray.area) +
|
posx = start = left_border_width(&panel->area) + panel->area.paddingy * panel->scale + left_border_width(&systray.area) +
|
||||||
systray.area.paddingy + systray.margin / 2;
|
systray.area.paddingy * panel->scale + systray.margin / 2;
|
||||||
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr;
|
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrayWindow *traywin;
|
TrayWindow *traywin;
|
||||||
@@ -312,17 +313,17 @@ void on_change_systray(void *obj)
|
|||||||
traywin->height = systray.icon_size;
|
traywin->height = systray.icon_size;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (i % systray.icons_per_column) {
|
if (i % systray.icons_per_column) {
|
||||||
posy += systray.icon_size + systray.area.paddingx;
|
posy += systray.icon_size + systray.area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (systray.icon_size + systray.area.paddingx);
|
posx += (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % systray.icons_per_row) {
|
if (i % systray.icons_per_row) {
|
||||||
posx += systray.icon_size + systray.area.paddingx;
|
posx += systray.icon_size + systray.area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (systray.icon_size + systray.area.paddingx);
|
posy += (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,11 +544,11 @@ static gint compare_traywindows(gconstpointer a, gconstpointer b)
|
|||||||
const TrayWindow *traywin_b = (const TrayWindow *)b;
|
const TrayWindow *traywin_b = (const TrayWindow *)b;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// This breaks pygtk2 StatusIcon with blinking activated
|
// This breaks pygtk2 StatusIcon with blinking activated
|
||||||
if (traywin_a->empty && !traywin_b->empty)
|
if (traywin_a->empty && !traywin_b->empty)
|
||||||
return 1 * (systray.sort == SYSTRAY_SORT_RIGHT2LEFT ? -1 : 1);
|
return 1 * (systray.sort == SYSTRAY_SORT_RIGHT2LEFT ? -1 : 1);
|
||||||
if (!traywin_a->empty && traywin_b->empty)
|
if (!traywin_a->empty && traywin_b->empty)
|
||||||
return -1 * (systray.sort == SYSTRAY_SORT_RIGHT2LEFT ? -1 : 1);
|
return -1 * (systray.sort == SYSTRAY_SORT_RIGHT2LEFT ? -1 : 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (systray.sort == SYSTRAY_SORT_ASCENDING || systray.sort == SYSTRAY_SORT_DESCENDING) {
|
if (systray.sort == SYSTRAY_SORT_ASCENDING || systray.sort == SYSTRAY_SORT_DESCENDING) {
|
||||||
@@ -730,6 +731,8 @@ gboolean add_icon(Window win)
|
|||||||
traywin->pid = pid;
|
traywin->pid = pid;
|
||||||
traywin->name = name;
|
traywin->name = name;
|
||||||
traywin->chrono = chrono;
|
traywin->chrono = chrono;
|
||||||
|
INIT_TIMER(traywin->render_timer);
|
||||||
|
INIT_TIMER(traywin->resize_timer);
|
||||||
chrono++;
|
chrono++;
|
||||||
|
|
||||||
show(&systray.area);
|
show(&systray.area);
|
||||||
@@ -940,8 +943,8 @@ void remove_icon(TrayWindow *traywin)
|
|||||||
XDestroyWindow(server.display, traywin->parent);
|
XDestroyWindow(server.display, traywin->parent);
|
||||||
XSync(server.display, False);
|
XSync(server.display, False);
|
||||||
XSetErrorHandler(old);
|
XSetErrorHandler(old);
|
||||||
stop_timeout(traywin->render_timeout);
|
destroy_timer(&traywin->render_timer);
|
||||||
stop_timeout(traywin->resize_timeout);
|
destroy_timer(&traywin->resize_timer);
|
||||||
free(traywin->name);
|
free(traywin->name);
|
||||||
if (traywin->image) {
|
if (traywin->image) {
|
||||||
imlib_context_set_image(traywin->image);
|
imlib_context_set_image(traywin->image);
|
||||||
@@ -1055,9 +1058,8 @@ void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
|
|||||||
if (traywin->bad_size_counter < min_bad_resize_events) {
|
if (traywin->bad_size_counter < min_bad_resize_events) {
|
||||||
systray_resize_icon(traywin);
|
systray_resize_icon(traywin);
|
||||||
} else {
|
} else {
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, fast_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(fast_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (traywin->bad_size_counter == max_bad_resize_events) {
|
if (traywin->bad_size_counter == max_bad_resize_events) {
|
||||||
@@ -1071,14 +1073,13 @@ void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
|
|||||||
// FIXME Normally we should force the icon to resize fill_color to the size we resized it to when we
|
// FIXME Normally we should force the icon to resize fill_color to the size we resized it to when we
|
||||||
// embedded it.
|
// embedded it.
|
||||||
// However this triggers a resize loop in new versions of GTK, which we must avoid.
|
// However this triggers a resize loop in new versions of GTK, which we must avoid.
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, slow_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Correct size
|
// Correct size
|
||||||
stop_timeout(traywin->resize_timeout);
|
stop_timer(&traywin->resize_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize and redraw the systray
|
// Resize and redraw the systray
|
||||||
@@ -1135,9 +1136,8 @@ void systray_resize_request_event(TrayWindow *traywin, XEvent *e)
|
|||||||
if (traywin->bad_size_counter < min_bad_resize_events) {
|
if (traywin->bad_size_counter < min_bad_resize_events) {
|
||||||
systray_resize_icon(traywin);
|
systray_resize_icon(traywin);
|
||||||
} else {
|
} else {
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, fast_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(fast_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (traywin->bad_size_counter == max_bad_resize_events) {
|
if (traywin->bad_size_counter == max_bad_resize_events) {
|
||||||
@@ -1150,14 +1150,13 @@ void systray_resize_request_event(TrayWindow *traywin, XEvent *e)
|
|||||||
// Delayed resize
|
// Delayed resize
|
||||||
// FIXME Normally we should force the icon to resize to the size we resized it to when we embedded it.
|
// FIXME Normally we should force the icon to resize to the size we resized it to when we embedded it.
|
||||||
// However this triggers a resize loop in some versions of GTK, which we must avoid.
|
// However this triggers a resize loop in some versions of GTK, which we must avoid.
|
||||||
if (!traywin->resize_timeout)
|
if (!traywin->resize_timer.enabled_)
|
||||||
traywin->resize_timeout =
|
change_timer(&traywin->resize_timer, true, slow_resize_period, 0, systray_resize_icon, traywin);
|
||||||
add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Correct size
|
// Correct size
|
||||||
stop_timeout(traywin->resize_timeout);
|
stop_timer(&traywin->resize_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize and redraw the systray
|
// Resize and redraw the systray
|
||||||
@@ -1224,8 +1223,7 @@ void systray_render_icon_composited(void *t)
|
|||||||
if (compare_timespecs(&earliest_render, &now) > 0) {
|
if (compare_timespecs(&earliest_render, &now) > 0) {
|
||||||
traywin->num_fast_renders++;
|
traywin->num_fast_renders++;
|
||||||
if (traywin->num_fast_renders > max_fast_refreshes) {
|
if (traywin->num_fast_renders > max_fast_refreshes) {
|
||||||
traywin->render_timeout =
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon_composited, traywin);
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
|
||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
||||||
@@ -1244,8 +1242,7 @@ void systray_render_icon_composited(void *t)
|
|||||||
|
|
||||||
if (traywin->width == 0 || traywin->height == 0) {
|
if (traywin->width == 0 || traywin->height == 0) {
|
||||||
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
|
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
|
||||||
traywin->render_timeout =
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon_composited, traywin);
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
|
||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
|
||||||
@@ -1257,10 +1254,7 @@ void systray_render_icon_composited(void *t)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traywin->render_timeout) {
|
stop_timer(&traywin->render_timer);
|
||||||
stop_timeout(traywin->render_timeout);
|
|
||||||
traywin->render_timeout = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// good systray icons support 32 bit depth, but some icons are still 24 bit.
|
// good systray icons support 32 bit depth, but some icons are still 24 bit.
|
||||||
// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
|
// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
|
||||||
@@ -1423,9 +1417,7 @@ void systray_render_icon(void *t)
|
|||||||
// __LINE__,
|
// __LINE__,
|
||||||
// traywin->win,
|
// traywin->win,
|
||||||
// traywin->name);
|
// traywin->name);
|
||||||
stop_timeout(traywin->render_timeout);
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
||||||
traywin->render_timeout =
|
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1448,19 +1440,13 @@ void systray_render_icon(void *t)
|
|||||||
unsigned int width, height, depth;
|
unsigned int width, height, depth;
|
||||||
Window root;
|
Window root;
|
||||||
if (!XGetGeometry(server.display, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
if (!XGetGeometry(server.display, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
||||||
stop_timeout(traywin->render_timeout);
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
||||||
if (!traywin->render_timeout)
|
|
||||||
traywin->render_timeout =
|
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
|
||||||
systray_render_icon_from_image(traywin);
|
systray_render_icon_from_image(traywin);
|
||||||
XSetErrorHandler(old);
|
XSetErrorHandler(old);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (xpos != 0 || ypos != 0 || width != traywin->width || height != traywin->height) {
|
if (xpos != 0 || ypos != 0 || width != traywin->width || height != traywin->height) {
|
||||||
stop_timeout(traywin->render_timeout);
|
change_timer(&traywin->render_timer, true, min_refresh_period, 0, systray_render_icon, traywin);
|
||||||
if (!traywin->render_timeout)
|
|
||||||
traywin->render_timeout =
|
|
||||||
add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
|
||||||
systray_render_icon_from_image(traywin);
|
systray_render_icon_from_image(traywin);
|
||||||
if (systray_profile)
|
if (systray_profile)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ typedef struct {
|
|||||||
// Members used for rendering
|
// Members used for rendering
|
||||||
struct timespec time_last_render;
|
struct timespec time_last_render;
|
||||||
int num_fast_renders;
|
int num_fast_renders;
|
||||||
timeout *render_timeout;
|
Timer render_timer;
|
||||||
// Members used for resizing
|
// Members used for resizing
|
||||||
int bad_size_counter;
|
int bad_size_counter;
|
||||||
struct timespec time_last_resize;
|
struct timespec time_last_resize;
|
||||||
timeout *resize_timeout;
|
Timer resize_timer;
|
||||||
// Icon contents if we are compositing the icon, otherwise null
|
// Icon contents if we are compositing the icon, otherwise null
|
||||||
Imlib_Image image;
|
Imlib_Image image;
|
||||||
// XDamage
|
// XDamage
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
timeout *urgent_timeout;
|
Timer urgent_timer;
|
||||||
GSList *urgent_list;
|
GSList *urgent_list;
|
||||||
|
|
||||||
void task_dump_geometry(void *obj, int indent);
|
void task_dump_geometry(void *obj, int indent);
|
||||||
@@ -429,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;
|
task->_icon_x = left_border_width(&task->area) + task->area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
@@ -459,11 +459,13 @@ void draw_task(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
task->_text_width = 0;
|
task->_text_width = 0;
|
||||||
if (panel->g_task.has_text) {
|
if (panel->g_task.has_text) {
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, panel->g_task.font_desc);
|
pango_layout_set_font_description(layout, panel->g_task.font_desc);
|
||||||
pango_layout_set_text(layout, task->title, -1);
|
pango_layout_set_text(layout, task->title, -1);
|
||||||
|
|
||||||
pango_layout_set_width(layout, ((Taskbar *)task->area.parent)->text_width * PANGO_SCALE);
|
pango_layout_set_width(layout, (((Taskbar *)task->area.parent)->text_width + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE);
|
pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
@@ -480,6 +482,7 @@ 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)
|
||||||
@@ -532,7 +535,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;
|
int size = (panel_horizontal ? panel->g_task.maximum_width : panel->g_task.maximum_height) * panel->scale;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,12 +655,13 @@ 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);
|
cairo_surface_t *thumbnail = get_window_thumbnail(task->win, panel_config.g_task.thumbnail_width * panel->scale);
|
||||||
if (!thumbnail)
|
if (!thumbnail)
|
||||||
return;
|
return;
|
||||||
if (task->thumbnail)
|
if (task->thumbnail)
|
||||||
@@ -782,8 +786,8 @@ void add_urgent(Task *task)
|
|||||||
// not yet in the list, so we have to add it
|
// not yet in the list, so we have to add it
|
||||||
urgent_list = g_slist_prepend(urgent_list, task);
|
urgent_list = g_slist_prepend(urgent_list, task);
|
||||||
|
|
||||||
if (!urgent_timeout)
|
if (!urgent_timer.enabled_)
|
||||||
urgent_timeout = add_timeout(10, 1000, blink_urgent, 0, &urgent_timeout);
|
change_timer(&urgent_timer, true, 10, 1000, blink_urgent, 0);
|
||||||
|
|
||||||
Panel *panel = task->area.panel;
|
Panel *panel = task->area.panel;
|
||||||
if (panel->is_hidden)
|
if (panel->is_hidden)
|
||||||
@@ -793,10 +797,8 @@ void add_urgent(Task *task)
|
|||||||
void del_urgent(Task *task)
|
void del_urgent(Task *task)
|
||||||
{
|
{
|
||||||
urgent_list = g_slist_remove(urgent_list, task);
|
urgent_list = g_slist_remove(urgent_list, task);
|
||||||
if (!urgent_list) {
|
if (!urgent_list)
|
||||||
stop_timeout(urgent_timeout);
|
stop_timer(&urgent_timer);
|
||||||
urgent_timeout = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_handle_mouse_event(Task *task, MouseAction action)
|
void task_handle_mouse_event(Task *task, MouseAction action)
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ typedef struct Task {
|
|||||||
double thumbnail_last_update;
|
double thumbnail_last_update;
|
||||||
} Task;
|
} Task;
|
||||||
|
|
||||||
extern timeout *urgent_timeout;
|
extern Timer urgent_timer;
|
||||||
extern GSList *urgent_list;
|
extern GSList *urgent_list;
|
||||||
|
|
||||||
Task *add_task(Window win);
|
Task *add_task(Window win);
|
||||||
|
|||||||
@@ -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 timeout *thumbnail_update_timer_all;
|
static Timer thumbnail_update_timer_all;
|
||||||
static timeout *thumbnail_update_timer_active;
|
static Timer thumbnail_update_timer_active;
|
||||||
static timeout *thumbnail_update_timer_tooltip;
|
static Timer 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,7 +80,6 @@ void free_ptr_array(gpointer data)
|
|||||||
void default_taskbar()
|
void default_taskbar()
|
||||||
{
|
{
|
||||||
win_to_task = NULL;
|
win_to_task = NULL;
|
||||||
urgent_timeout = NULL;
|
|
||||||
urgent_list = NULL;
|
urgent_list = NULL;
|
||||||
taskbar_enabled = FALSE;
|
taskbar_enabled = FALSE;
|
||||||
taskbar_distribute_size = FALSE;
|
taskbar_distribute_size = FALSE;
|
||||||
@@ -89,9 +88,6 @@ 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;
|
||||||
@@ -134,9 +130,9 @@ void taskbar_save_orderings()
|
|||||||
|
|
||||||
void cleanup_taskbar()
|
void cleanup_taskbar()
|
||||||
{
|
{
|
||||||
stop_timeout(thumbnail_update_timer_all);
|
destroy_timer(&thumbnail_update_timer_all);
|
||||||
stop_timeout(thumbnail_update_timer_active);
|
destroy_timer(&thumbnail_update_timer_active);
|
||||||
stop_timeout(thumbnail_update_timer_tooltip);
|
destroy_timer(&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) {
|
||||||
@@ -170,7 +166,7 @@ void cleanup_taskbar()
|
|||||||
g_slist_free(urgent_list);
|
g_slist_free(urgent_list);
|
||||||
urgent_list = NULL;
|
urgent_list = NULL;
|
||||||
|
|
||||||
stop_timeout(urgent_timeout);
|
destroy_timer(&urgent_timer);
|
||||||
|
|
||||||
for (int state = 0; state < TASK_STATE_COUNT; state++) {
|
for (int state = 0; state < TASK_STATE_COUNT; state++) {
|
||||||
g_list_free(panel_config.g_task.gradient[state]);
|
g_list_free(panel_config.g_task.gradient[state]);
|
||||||
@@ -184,6 +180,11 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -237,15 +238,15 @@ void init_taskbar_panel(void *p)
|
|||||||
panel->g_taskbar.area.resize_needed = 1;
|
panel->g_taskbar.area.resize_needed = 1;
|
||||||
panel->g_taskbar.area.on_screen = TRUE;
|
panel->g_taskbar.area.on_screen = TRUE;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy;
|
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area.height =
|
panel->g_taskbar.area.height =
|
||||||
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy;
|
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
||||||
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
||||||
} else {
|
} else {
|
||||||
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy;
|
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area.width =
|
panel->g_taskbar.area.width =
|
||||||
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy;
|
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
|
panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
|
||||||
panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
|
panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
|
||||||
}
|
}
|
||||||
@@ -303,19 +304,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->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.width = panel->g_task.maximum_width;
|
panel->g_task.area.width = panel->g_task.maximum_width;
|
||||||
panel->g_task.area.height = panel->g_taskbar.area.height -
|
panel->g_task.area.height = panel->g_taskbar.area.height -
|
||||||
top_bottom_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
top_bottom_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
||||||
2 * panel->g_taskbar.area.paddingy;
|
2 * panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
panel->g_task.area.posx = panel->g_taskbar.area.posx +
|
panel->g_task.area.posx = panel->g_taskbar.area.posx +
|
||||||
left_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
left_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
||||||
panel->g_taskbar.area.paddingy;
|
panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.width = panel->g_taskbar.area.width -
|
panel->g_task.area.width = panel->g_taskbar.area.width -
|
||||||
left_right_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
left_right_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
||||||
2 * panel->g_taskbar.area.paddingy;
|
2 * panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.height = panel->g_task.maximum_height;
|
panel->g_task.area.height = panel->g_task.maximum_height * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
||||||
@@ -332,9 +333,8 @@ void init_taskbar_panel(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute vertical position : text and icon
|
// compute vertical position : text and icon
|
||||||
int height_ink, height, width;
|
int height, width;
|
||||||
get_text_size2(panel->g_task.font_desc,
|
get_text_size2(panel->g_task.font_desc,
|
||||||
&height_ink,
|
|
||||||
&height,
|
&height,
|
||||||
&width,
|
&width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -343,17 +343,19 @@ void init_taskbar_panel(void *p)
|
|||||||
5,
|
5,
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_END,
|
PANGO_ELLIPSIZE_END,
|
||||||
FALSE);
|
panel->g_task.centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
panel->g_task.text_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr;
|
panel->g_task.text_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr * panel->scale;
|
||||||
panel->g_task.text_height =
|
panel->g_task.text_height =
|
||||||
panel->g_task.area.height - (2 * panel->g_task.area.paddingy) - top_bottom_border_width(&panel->g_task.area);
|
panel->g_task.area.height - (2 * panel->g_task.area.paddingy * panel->scale) - top_bottom_border_width(&panel->g_task.area);
|
||||||
if (panel->g_task.has_icon) {
|
if (panel->g_task.has_icon) {
|
||||||
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width, panel->g_task.maximum_height),
|
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width * panel->scale, panel->g_task.maximum_height * panel->scale),
|
||||||
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
|
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
|
||||||
2 * panel->g_task.area.paddingy - MAX(left_right_border_width(&panel->g_task.area),
|
2 * panel->g_task.area.paddingy * panel->scale - MAX(left_right_border_width(&panel->g_task.area),
|
||||||
top_bottom_border_width(&panel->g_task.area));
|
top_bottom_border_width(&panel->g_task.area));
|
||||||
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx;
|
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx * panel->scale;
|
||||||
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,12 +386,13 @@ 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_timeout(mode == THUMB_MODE_ALL ? &thumbnail_update_timer_all :
|
change_timer(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,
|
||||||
mode == THUMB_MODE_TOOLTIP_WINDOW ? 1000 : 500,
|
true,
|
||||||
mode == THUMB_MODE_ALL ? 10 * 1000 : 0,
|
mode == THUMB_MODE_TOOLTIP_WINDOW ? 1000 : 500,
|
||||||
taskbar_update_thumbnails,
|
mode == THUMB_MODE_ALL ? 10 * 1000 : 0,
|
||||||
(void *)(long)mode);
|
taskbar_update_thumbnails,
|
||||||
|
(void *)(long)mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void taskbar_init_fonts()
|
void taskbar_init_fonts()
|
||||||
@@ -571,12 +574,12 @@ gboolean resize_taskbar(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
taskbar->text_width = text_width - panel->g_task.text_posx - right_border_width(&panel->g_task.area) -
|
taskbar->text_width = text_width - panel->g_task.text_posx - right_border_width(&panel->g_task.area) -
|
||||||
panel->g_task.area.paddingxlr;
|
panel->g_task.area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height);
|
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height * panel->scale);
|
||||||
|
|
||||||
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy) - panel->g_task.text_posx -
|
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy * panel->scale) - panel->g_task.text_posx -
|
||||||
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr;
|
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -844,7 +847,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_timeout(&thumbnail_update_timer_all, 50, 10 * 1000, taskbar_update_thumbnails, arg);
|
change_timer(&thumbnail_update_timer_all, true, 50, 10 * 1000, taskbar_update_thumbnails, arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -855,7 +858,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_timeout(&thumbnail_update_timer_all, 10 * 1000, 10 * 1000, taskbar_update_thumbnails, arg);
|
change_timer(&thumbnail_update_timer_all, true, 10 * 1000, 10 * 1000, taskbar_update_thumbnails, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,9 +134,8 @@ int taskbarname_compute_desired_size(void *obj)
|
|||||||
{
|
{
|
||||||
TaskbarName *taskbar_name = (TaskbarName *)obj;
|
TaskbarName *taskbar_name = (TaskbarName *)obj;
|
||||||
Panel *panel = (Panel *)taskbar_name->area.panel;
|
Panel *panel = (Panel *)taskbar_name->area.panel;
|
||||||
int name_height, name_width, name_height_ink;
|
int name_height, name_width;
|
||||||
get_text_size2(panel_config.taskbarname_font_desc,
|
get_text_size2(panel_config.taskbarname_font_desc,
|
||||||
&name_height_ink,
|
|
||||||
&name_height,
|
&name_height,
|
||||||
&name_width,
|
&name_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -145,12 +144,14 @@ int taskbarname_compute_desired_size(void *obj)
|
|||||||
strlen(taskbar_name->name),
|
strlen(taskbar_name->name),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
return name_width + 2 * taskbar_name->area.paddingxlr + left_right_border_width(&taskbar_name->area);
|
return name_width + 2 * taskbar_name->area.paddingxlr * panel->scale + left_right_border_width(&taskbar_name->area);
|
||||||
} else {
|
} else {
|
||||||
return name_height + 2 * taskbar_name->area.paddingxlr + top_bottom_border_width(&taskbar_name->area);
|
return name_height + 2 * taskbar_name->area.paddingxlr * panel->scale + top_bottom_border_width(&taskbar_name->area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,9 +162,8 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
|
|
||||||
schedule_redraw(&taskbar_name->area);
|
schedule_redraw(&taskbar_name->area);
|
||||||
|
|
||||||
int name_height, name_width, name_height_ink;
|
int name_height, name_width;
|
||||||
get_text_size2(panel_config.taskbarname_font_desc,
|
get_text_size2(panel_config.taskbarname_font_desc,
|
||||||
&name_height_ink,
|
|
||||||
&name_height,
|
&name_height,
|
||||||
&name_width,
|
&name_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -172,7 +172,9 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
strlen(taskbar_name->name),
|
strlen(taskbar_name->name),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
int new_size = taskbarname_compute_desired_size(obj);
|
int new_size = taskbarname_compute_desired_size(obj);
|
||||||
@@ -195,11 +197,14 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
void draw_taskbarname(void *obj, cairo_t *c)
|
void draw_taskbarname(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
TaskbarName *taskbar_name = obj;
|
TaskbarName *taskbar_name = obj;
|
||||||
|
Panel *panel = (Panel *)taskbar_name->area.panel;
|
||||||
Taskbar *taskbar = taskbar_name->area.parent;
|
Taskbar *taskbar = taskbar_name->area.parent;
|
||||||
Color *config_text = (taskbar->desktop == server.desktop) ? &taskbarname_active_font : &taskbarname_font;
|
Color *config_text = (taskbar->desktop == server.desktop) ? &taskbarname_active_font : &taskbarname_font;
|
||||||
|
|
||||||
// draw content
|
// draw content
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, panel_config.taskbarname_font_desc);
|
pango_layout_set_font_description(layout, panel_config.taskbarname_font_desc);
|
||||||
pango_layout_set_width(layout, taskbar_name->area.width * PANGO_SCALE);
|
pango_layout_set_width(layout, taskbar_name->area.width * PANGO_SCALE);
|
||||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||||
@@ -213,6 +218,7 @@ 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()
|
||||||
|
|||||||
@@ -23,8 +23,12 @@ set(SOURCES ../util/common.c
|
|||||||
../util/strnatcmp.c
|
../util/strnatcmp.c
|
||||||
../util/cache.c
|
../util/cache.c
|
||||||
../util/timer.c
|
../util/timer.c
|
||||||
|
../util/test.c
|
||||||
|
../util/print.c
|
||||||
|
../util/signals.c
|
||||||
../config.c
|
../config.c
|
||||||
../server.c
|
../util/server.c
|
||||||
|
../util/strlcat.c
|
||||||
../launcher/apps-common.c
|
../launcher/apps-common.c
|
||||||
../launcher/icon-theme-common.c
|
../launcher/icon-theme-common.c
|
||||||
md4.c
|
md4.c
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ char *file_name_from_path(const char *filepath)
|
|||||||
|
|
||||||
void make_backup(const char *filepath)
|
void make_backup(const char *filepath)
|
||||||
{
|
{
|
||||||
gchar *backup_path = g_strdup_printf("%s.backup.%ld", filepath, time(NULL));
|
gchar *backup_path = g_strdup_printf("%s.backup.%lld", filepath, (long long)time(NULL));
|
||||||
copy_file(filepath, backup_path);
|
copy_file(filepath, backup_path);
|
||||||
g_free(backup_path);
|
g_free(backup_path);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,9 @@
|
|||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "background_gui.h"
|
#include "background_gui.h"
|
||||||
#include "gradient_gui.h"
|
#include "gradient_gui.h"
|
||||||
|
#include "strlcat.h"
|
||||||
|
|
||||||
|
GtkWidget *scale_relative_to_dpi, *scale_relative_to_screen_height;
|
||||||
GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
||||||
*panel_spacing;
|
*panel_spacing;
|
||||||
GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
||||||
@@ -180,7 +182,7 @@ void applyClicked(GtkWidget *widget, gpointer data)
|
|||||||
gchar *filepath = get_current_theme_path();
|
gchar *filepath = get_current_theme_path();
|
||||||
if (filepath) {
|
if (filepath) {
|
||||||
if (config_is_manual(filepath)) {
|
if (config_is_manual(filepath)) {
|
||||||
gchar *backup_path = g_strdup_printf("%s.backup.%ld", filepath, time(NULL));
|
gchar *backup_path = g_strdup_printf("%s.backup.%lld", filepath, (long long)time(NULL));
|
||||||
copy_file(filepath, backup_path);
|
copy_file(filepath, backup_path);
|
||||||
g_free(backup_path);
|
g_free(backup_path);
|
||||||
}
|
}
|
||||||
@@ -599,6 +601,32 @@ void create_panel(GtkWidget *parent)
|
|||||||
"for centered panels, it is evenly distributed on both sides of the panel."),
|
"for centered panels, it is evenly distributed on both sides of the panel."),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
row++;
|
||||||
|
col = 2;
|
||||||
|
label = gtk_label_new(_("Scale relative to DPI"));
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||||
|
gtk_widget_show(label);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
scale_relative_to_dpi = gtk_spin_button_new_with_range(0, 9000, 1);
|
||||||
|
gtk_widget_show(scale_relative_to_dpi);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), scale_relative_to_dpi, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
row++;
|
||||||
|
col = 2;
|
||||||
|
label = gtk_label_new(_("Scale relative to screen height"));
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||||
|
gtk_widget_show(label);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
scale_relative_to_screen_height = gtk_spin_button_new_with_range(0, 9000, 1);
|
||||||
|
gtk_widget_show(scale_relative_to_screen_height);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), scale_relative_to_screen_height, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
change_paragraph(parent);
|
change_paragraph(parent);
|
||||||
|
|
||||||
label = gtk_label_new(_("<b>Appearance</b>"));
|
label = gtk_label_new(_("<b>Appearance</b>"));
|
||||||
@@ -1256,7 +1284,8 @@ gboolean panel_contains(const char *value)
|
|||||||
|
|
||||||
char *get_panel_items()
|
char *get_panel_items()
|
||||||
{
|
{
|
||||||
char *result = calloc(1, 256 * sizeof(char));
|
size_t buf_size = 256;
|
||||||
|
char *result = calloc(buf_size, 1);
|
||||||
GtkTreeModel *model = GTK_TREE_MODEL(panel_items);
|
GtkTreeModel *model = GTK_TREE_MODEL(panel_items);
|
||||||
|
|
||||||
GtkTreeIter i;
|
GtkTreeIter i;
|
||||||
@@ -1267,7 +1296,7 @@ char *get_panel_items()
|
|||||||
while (1) {
|
while (1) {
|
||||||
gchar *v;
|
gchar *v;
|
||||||
gtk_tree_model_get(model, &i, itemsColValue, &v, -1);
|
gtk_tree_model_get(model, &i, itemsColValue, &v, -1);
|
||||||
strcat(result, v);
|
strlcat(result, v, buf_size);
|
||||||
|
|
||||||
if (!gtk_tree_model_iter_next(model, &i)) {
|
if (!gtk_tree_model_iter_next(model, &i)) {
|
||||||
break;
|
break;
|
||||||
@@ -1312,19 +1341,19 @@ void set_panel_items(const char *items)
|
|||||||
} else if (v == ':') {
|
} else if (v == ':') {
|
||||||
separator_index++;
|
separator_index++;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Separator"), separator_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Separator"), separator_index + 1);
|
||||||
name = buffer;
|
name = buffer;
|
||||||
value = ":";
|
value = ":";
|
||||||
} else if (v == 'E') {
|
} else if (v == 'E') {
|
||||||
execp_index++;
|
execp_index++;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Executor"), execp_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Executor"), execp_index + 1);
|
||||||
name = buffer;
|
name = buffer;
|
||||||
value = "E";
|
value = "E";
|
||||||
} else if (v == 'P') {
|
} else if (v == 'P') {
|
||||||
button_index++;
|
button_index++;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Button"), button_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Button"), button_index + 1);
|
||||||
name = buffer;
|
name = buffer;
|
||||||
value = "P";
|
value = "P";
|
||||||
} else {
|
} else {
|
||||||
@@ -4097,7 +4126,7 @@ void create_separator(GtkWidget *notebook, int i)
|
|||||||
Separator *separator = &g_array_index(separators, Separator, i);
|
Separator *separator = &g_array_index(separators, Separator, i);
|
||||||
|
|
||||||
separator->name[0] = 0;
|
separator->name[0] = 0;
|
||||||
sprintf(separator->name, "%s %d", _("Separator"), i + 1);
|
snprintf(separator->name, sizeof(separator->name), "%s %d", _("Separator"), i + 1);
|
||||||
separator->page_label = gtk_label_new(separator->name);
|
separator->page_label = gtk_label_new(separator->name);
|
||||||
gtk_widget_show(separator->page_label);
|
gtk_widget_show(separator->page_label);
|
||||||
separator->page_separator = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
separator->page_separator = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
||||||
@@ -4223,7 +4252,7 @@ void create_execp(GtkWidget *notebook, int i)
|
|||||||
Executor *executor = &g_array_index(executors, Executor, i);
|
Executor *executor = &g_array_index(executors, Executor, i);
|
||||||
|
|
||||||
executor->name[0] = 0;
|
executor->name[0] = 0;
|
||||||
sprintf(executor->name, "%s %d", _("Executor"), i + 1);
|
snprintf(executor->name, sizeof(executor->name), "%s %d", _("Executor"), i + 1);
|
||||||
executor->page_label = gtk_label_new(executor->name);
|
executor->page_label = gtk_label_new(executor->name);
|
||||||
gtk_widget_show(executor->page_label);
|
gtk_widget_show(executor->page_label);
|
||||||
executor->page_execp = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
executor->page_execp = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
||||||
@@ -4644,7 +4673,7 @@ void create_button(GtkWidget *notebook, int i)
|
|||||||
Button *button = &g_array_index(buttons, Button, i);
|
Button *button = &g_array_index(buttons, Button, i);
|
||||||
|
|
||||||
button->name[0] = 0;
|
button->name[0] = 0;
|
||||||
sprintf(button->name, "%s %d", _("Button"), i + 1);
|
snprintf(button->name, sizeof(button->name), "%s %d", _("Button"), i + 1);
|
||||||
button->page_label = gtk_label_new(button->name);
|
button->page_label = gtk_label_new(button->name);
|
||||||
gtk_widget_show(button->page_label);
|
gtk_widget_show(button->page_label);
|
||||||
button->page_button = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
button->page_button = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
|
||||||
@@ -5033,7 +5062,7 @@ void separator_update_indices()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < separators->len; i++) {
|
for (int i = 0; i < separators->len; i++) {
|
||||||
Separator *separator = &g_array_index(separators, Separator, i);
|
Separator *separator = &g_array_index(separators, Separator, i);
|
||||||
sprintf(separator->name, "%s %d", _("Separator"), i + 1);
|
snprintf(separator->name, sizeof(separator->name), "%s %d", _("Separator"), i + 1);
|
||||||
gtk_label_set_text(GTK_LABEL(separator->page_label), separator->name);
|
gtk_label_set_text(GTK_LABEL(separator->page_label), separator->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5051,7 +5080,7 @@ void separator_update_indices()
|
|||||||
separator_index++;
|
separator_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Separator"), separator_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Separator"), separator_index + 1);
|
||||||
|
|
||||||
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
||||||
}
|
}
|
||||||
@@ -5065,7 +5094,7 @@ void execp_update_indices()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < executors->len; i++) {
|
for (int i = 0; i < executors->len; i++) {
|
||||||
Executor *executor = &g_array_index(executors, Executor, i);
|
Executor *executor = &g_array_index(executors, Executor, i);
|
||||||
sprintf(executor->name, "%s %d", _("Executor"), i + 1);
|
snprintf(executor->name, sizeof(executor->name), "%s %d", _("Executor"), i + 1);
|
||||||
gtk_label_set_text(GTK_LABEL(executor->page_label), executor->name);
|
gtk_label_set_text(GTK_LABEL(executor->page_label), executor->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5083,7 +5112,7 @@ void execp_update_indices()
|
|||||||
execp_index++;
|
execp_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Executor"), execp_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Executor"), execp_index + 1);
|
||||||
|
|
||||||
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
||||||
}
|
}
|
||||||
@@ -5097,7 +5126,7 @@ void button_update_indices()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < buttons->len; i++) {
|
for (int i = 0; i < buttons->len; i++) {
|
||||||
Button *button = &g_array_index(buttons, Button, i);
|
Button *button = &g_array_index(buttons, Button, i);
|
||||||
sprintf(button->name, "%s %d", _("Button"), i + 1);
|
snprintf(button->name, sizeof(button->name), "%s %d", _("Button"), i + 1);
|
||||||
gtk_label_set_text(GTK_LABEL(button->page_label), button->name);
|
gtk_label_set_text(GTK_LABEL(button->page_label), button->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5115,7 +5144,7 @@ void button_update_indices()
|
|||||||
button_index++;
|
button_index++;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
sprintf(buffer, "%s %d", _("Button"), button_index + 1);
|
snprintf(buffer, sizeof(buffer), "%s %d", _("Button"), button_index + 1);
|
||||||
|
|
||||||
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
gtk_list_store_set(panel_items, &iter, itemsColName, buffer, -1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "../launcher/icon-theme-common.h"
|
#include "../launcher/icon-theme-common.h"
|
||||||
|
|
||||||
// panel
|
// panel
|
||||||
|
extern GtkWidget *scale_relative_to_dpi, *scale_relative_to_screen_height;
|
||||||
extern GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
extern GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
||||||
*panel_spacing;
|
*panel_spacing;
|
||||||
extern GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
extern GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
||||||
|
|||||||
@@ -69,23 +69,23 @@ void config_read_file(const char *path)
|
|||||||
if (!config_has_panel_items) {
|
if (!config_has_panel_items) {
|
||||||
char panel_items[256];
|
char panel_items[256];
|
||||||
panel_items[0] = 0;
|
panel_items[0] = 0;
|
||||||
strcat(panel_items, "T");
|
strlcat(panel_items, "T", sizeof(panel_items));
|
||||||
if (config_has_battery) {
|
if (config_has_battery) {
|
||||||
if (config_battery_enabled)
|
if (config_battery_enabled)
|
||||||
strcat(panel_items, "B");
|
strlcat(panel_items, "B", sizeof(panel_items));
|
||||||
} else {
|
} else {
|
||||||
if (no_items_battery_enabled)
|
if (no_items_battery_enabled)
|
||||||
strcat(panel_items, "B");
|
strlcat(panel_items, "B", sizeof(panel_items));
|
||||||
}
|
}
|
||||||
if (config_has_systray) {
|
if (config_has_systray) {
|
||||||
if (config_systray_enabled)
|
if (config_systray_enabled)
|
||||||
strcat(panel_items, "S");
|
strlcat(panel_items, "S", sizeof(panel_items));
|
||||||
} else {
|
} else {
|
||||||
if (no_items_systray_enabled)
|
if (no_items_systray_enabled)
|
||||||
strcat(panel_items, "S");
|
strlcat(panel_items, "S", sizeof(panel_items));
|
||||||
}
|
}
|
||||||
if (no_items_clock_enabled)
|
if (no_items_clock_enabled)
|
||||||
strcat(panel_items, "C");
|
strlcat(panel_items, "C", sizeof(panel_items));
|
||||||
set_panel_items(panel_items);
|
set_panel_items(panel_items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
strcat(sides, "T");
|
strlcat(sides, "T", sizeof(sides));
|
||||||
if (sideBottom)
|
if (sideBottom)
|
||||||
strcat(sides, "B");
|
strlcat(sides, "B", sizeof(sides));
|
||||||
if (sideLeft)
|
if (sideLeft)
|
||||||
strcat(sides, "L");
|
strlcat(sides, "L", sizeof(sides));
|
||||||
if (sideRight)
|
if (sideRight)
|
||||||
strcat(sides, "R");
|
strlcat(sides, "R", sizeof(sides));
|
||||||
fprintf(fp, "border_sides = %s\n", sides);
|
fprintf(fp, "border_sides = %s\n", sides);
|
||||||
|
|
||||||
fprintf(fp, "border_content_tint_weight = %d\n", (int)(border_weight));
|
fprintf(fp, "border_content_tint_weight = %d\n", (int)(border_weight));
|
||||||
@@ -378,6 +378,13 @@ void config_write_panel(FILE *fp)
|
|||||||
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_saturation)),
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_saturation)),
|
||||||
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_brightness)));
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_brightness)));
|
||||||
|
|
||||||
|
fprintf(fp,
|
||||||
|
"scale_relative_to_dpi = %d\n",
|
||||||
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scale_relative_to_dpi)));
|
||||||
|
fprintf(fp,
|
||||||
|
"scale_relative_to_screen_height = %d\n",
|
||||||
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scale_relative_to_screen_height)));
|
||||||
|
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,7 +485,7 @@ void config_write_task_font_color(FILE *fp, char *name, GtkWidget *task_color)
|
|||||||
GdkColor color;
|
GdkColor color;
|
||||||
gtk_color_button_get_color(GTK_COLOR_BUTTON(task_color), &color);
|
gtk_color_button_get_color(GTK_COLOR_BUTTON(task_color), &color);
|
||||||
char full_name[128];
|
char full_name[128];
|
||||||
sprintf(full_name, "task%s_font_color", name);
|
snprintf(full_name, sizeof(full_name), "task%s_font_color", name);
|
||||||
config_write_color(fp, full_name, color, gtk_color_button_get_alpha(GTK_COLOR_BUTTON(task_color)) * 100 / 0xffff);
|
config_write_color(fp, full_name, color, gtk_color_button_get_alpha(GTK_COLOR_BUTTON(task_color)) * 100 / 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +496,7 @@ void config_write_task_icon_osb(FILE *fp,
|
|||||||
GtkWidget *widget_brightness)
|
GtkWidget *widget_brightness)
|
||||||
{
|
{
|
||||||
char full_name[128];
|
char full_name[128];
|
||||||
sprintf(full_name, "task%s_icon_asb", name);
|
snprintf(full_name, sizeof(full_name), "task%s_icon_asb", name);
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
"%s = %d %d %d\n",
|
"%s = %d %d %d\n",
|
||||||
full_name,
|
full_name,
|
||||||
@@ -501,7 +508,7 @@ void config_write_task_icon_osb(FILE *fp,
|
|||||||
void config_write_task_background(FILE *fp, char *name, GtkWidget *task_background)
|
void config_write_task_background(FILE *fp, char *name, GtkWidget *task_background)
|
||||||
{
|
{
|
||||||
char full_name[128];
|
char full_name[128];
|
||||||
sprintf(full_name, "task%s_background_id", name);
|
snprintf(full_name, sizeof(full_name), "task%s_background_id", name);
|
||||||
fprintf(fp, "%s = %d\n", full_name, gtk_combo_box_get_active(GTK_COMBO_BOX(task_background)));
|
fprintf(fp, "%s = %d\n", full_name, gtk_combo_box_get_active(GTK_COMBO_BOX(task_background)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,7 +1115,13 @@ void add_entry(char *key, char *value)
|
|||||||
char *value1 = 0, *value2 = 0, *value3 = 0;
|
char *value1 = 0, *value2 = 0, *value3 = 0;
|
||||||
|
|
||||||
/* Gradients */
|
/* Gradients */
|
||||||
if (strcmp(key, "gradient") == 0) {
|
if (strcmp(key, "scale_relative_to_dpi") == 0) {
|
||||||
|
extract_values(value, &value1, &value2, &value3);
|
||||||
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(scale_relative_to_dpi), atoi(value1));
|
||||||
|
} else if (strcmp(key, "scale_relative_to_screen_height") == 0) {
|
||||||
|
extract_values(value, &value1, &value2, &value3);
|
||||||
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(scale_relative_to_screen_height), atoi(value1));
|
||||||
|
} else if (strcmp(key, "gradient") == 0) {
|
||||||
finalize_gradient();
|
finalize_gradient();
|
||||||
GradientConfigType t;
|
GradientConfigType t;
|
||||||
if (g_str_equal(value, "horizontal"))
|
if (g_str_equal(value, "horizontal"))
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ gboolean update_snapshot(gpointer ignored)
|
|||||||
|
|
||||||
char hash[MD4_HEX_SIZE + 4];
|
char hash[MD4_HEX_SIZE + 4];
|
||||||
md4hexf(path, hash);
|
md4hexf(path, hash);
|
||||||
strcat(hash, ".png");
|
strlcat(hash, ".png", sizeof(hash));
|
||||||
|
|
||||||
gchar *snap = g_build_filename(g_get_user_cache_dir(), "tint2", hash, NULL);
|
gchar *snap = g_build_filename(g_get_user_cache_dir(), "tint2", hash, NULL);
|
||||||
pixbuf = force_refresh ? NULL : gdk_pixbuf_new_from_file(snap, NULL);
|
pixbuf = force_refresh ? NULL : gdk_pixbuf_new_from_file(snap, NULL);
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ static int x, y, width, height;
|
|||||||
static gboolean just_shown;
|
static gboolean just_shown;
|
||||||
|
|
||||||
// the next functions are helper functions for tooltip handling
|
// the next functions are helper functions for tooltip handling
|
||||||
void start_show_timeout();
|
void start_show_timer();
|
||||||
void start_hide_timeout();
|
void start_hide_timer();
|
||||||
void stop_tooltip_timeout();
|
void stop_tooltip_timer();
|
||||||
|
|
||||||
void tooltip_init_fonts();
|
void tooltip_init_fonts();
|
||||||
|
|
||||||
@@ -44,6 +44,9 @@ void default_tooltip()
|
|||||||
// give the tooltip some reasonable default values
|
// give the tooltip some reasonable default values
|
||||||
memset(&g_tooltip, 0, sizeof(Tooltip));
|
memset(&g_tooltip, 0, sizeof(Tooltip));
|
||||||
|
|
||||||
|
INIT_TIMER(g_tooltip.visibility_timer);
|
||||||
|
INIT_TIMER(g_tooltip.update_timer);
|
||||||
|
|
||||||
g_tooltip.font_color.rgb[0] = 1;
|
g_tooltip.font_color.rgb[0] = 1;
|
||||||
g_tooltip.font_color.rgb[1] = 1;
|
g_tooltip.font_color.rgb[1] = 1;
|
||||||
g_tooltip.font_color.rgb[2] = 1;
|
g_tooltip.font_color.rgb[2] = 1;
|
||||||
@@ -53,8 +56,9 @@ void default_tooltip()
|
|||||||
|
|
||||||
void cleanup_tooltip()
|
void cleanup_tooltip()
|
||||||
{
|
{
|
||||||
stop_tooltip_timeout();
|
stop_tooltip_timer();
|
||||||
stop_timeout(g_tooltip.update_timeout);
|
destroy_timer(&g_tooltip.visibility_timer);
|
||||||
|
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)
|
||||||
@@ -121,9 +125,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_timeout();
|
stop_tooltip_timer();
|
||||||
} else if (!g_tooltip.mapped) {
|
} else if (!g_tooltip.mapped) {
|
||||||
start_show_timeout();
|
start_show_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +153,9 @@ 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);
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
||||||
PangoRectangle r1, r2;
|
PangoRectangle r1, r2;
|
||||||
@@ -157,7 +163,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 +
|
max_width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx * panel->scale +
|
||||||
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);
|
||||||
@@ -165,12 +171,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 + r2.width;
|
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx * panel->scale + r2.width;
|
||||||
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy + r2.height;
|
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy * panel->scale + r2.height;
|
||||||
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
|
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 +
|
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx * panel->scale +
|
||||||
cairo_image_surface_get_width(g_tooltip.image);
|
cairo_image_surface_get_width(g_tooltip.image);
|
||||||
height += g_tooltip.paddingy + cairo_image_surface_get_height(g_tooltip.image);
|
height += g_tooltip.paddingy * panel->scale + cairo_image_surface_get_height(g_tooltip.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal && panel_position & BOTTOM)
|
if (panel_horizontal && panel_position & BOTTOM)
|
||||||
@@ -183,6 +189,7 @@ void tooltip_update_geometry()
|
|||||||
x = panel->posx - width;
|
x = panel->posx - width;
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
}
|
}
|
||||||
@@ -239,6 +246,7 @@ void tooltip_update()
|
|||||||
tooltip_hide(0);
|
tooltip_hide(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Panel *panel = g_tooltip.panel;
|
||||||
|
|
||||||
tooltip_update_geometry();
|
tooltip_update_geometry();
|
||||||
if (just_shown) {
|
if (just_shown) {
|
||||||
@@ -273,7 +281,9 @@ void tooltip_update()
|
|||||||
|
|
||||||
Color fc = g_tooltip.font_color;
|
Color fc = g_tooltip.font_color;
|
||||||
cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha);
|
cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha);
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
||||||
pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
|
pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
|
||||||
@@ -285,15 +295,16 @@ void tooltip_update()
|
|||||||
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and
|
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and
|
||||||
// vert.)
|
// vert.)
|
||||||
cairo_move_to(c,
|
cairo_move_to(c,
|
||||||
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
|
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx * panel->scale,
|
||||||
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy);
|
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy * panel->scale);
|
||||||
pango_cairo_show_layout(c, layout);
|
pango_cairo_show_layout(c, layout);
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
|
|
||||||
if (g_tooltip.image) {
|
if (g_tooltip.image) {
|
||||||
cairo_translate(c,
|
cairo_translate(c,
|
||||||
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
|
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx * panel->scale,
|
||||||
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy - cairo_image_surface_get_height(g_tooltip.image));
|
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy * panel->scale - cairo_image_surface_get_height(g_tooltip.image));
|
||||||
cairo_set_source_surface(c, g_tooltip.image, 0, 0);
|
cairo_set_source_surface(c, g_tooltip.image, 0, 0);
|
||||||
cairo_paint(c);
|
cairo_paint(c);
|
||||||
}
|
}
|
||||||
@@ -306,10 +317,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_timeout();
|
start_hide_timer();
|
||||||
} else {
|
} else {
|
||||||
// tooltip not visible yet, but maybe a timeout is still pending
|
// tooltip not visible yet, but maybe a timer is still pending
|
||||||
stop_tooltip_timeout();
|
stop_tooltip_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,19 +334,19 @@ void tooltip_hide(void *arg)
|
|||||||
g_tooltip.area = NULL;
|
g_tooltip.area = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_show_timeout()
|
void start_show_timer()
|
||||||
{
|
{
|
||||||
change_timeout(&g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
change_timer(&g_tooltip.visibility_timer, true, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_hide_timeout()
|
void start_hide_timer()
|
||||||
{
|
{
|
||||||
change_timeout(&g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
change_timer(&g_tooltip.visibility_timer, true, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_tooltip_timeout()
|
void stop_tooltip_timer()
|
||||||
{
|
{
|
||||||
stop_timeout(g_tooltip.timeout);
|
stop_timer(&g_tooltip.visibility_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tooltip_update_contents_timeout(void *arg)
|
void tooltip_update_contents_timeout(void *arg)
|
||||||
@@ -356,7 +367,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_timeout(&g_tooltip.update_timeout, 300, 0, tooltip_update_contents_timeout, NULL);
|
change_timer(&g_tooltip.update_timer, true, 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;
|
||||||
timeout *timeout;
|
Timer visibility_timer;
|
||||||
timeout *update_timeout;
|
Timer update_timer;
|
||||||
cairo_surface_t *image;
|
cairo_surface_t *image;
|
||||||
} Tooltip;
|
} Tooltip;
|
||||||
|
|
||||||
|
|||||||
@@ -1,238 +0,0 @@
|
|||||||
/* 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
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#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
|
|
||||||
@@ -929,10 +929,8 @@ void area_compute_text_geometry(Area *area,
|
|||||||
const char *line2,
|
const char *line2,
|
||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int *line1_height_ink,
|
|
||||||
int *line1_height,
|
int *line1_height,
|
||||||
int *line1_width,
|
int *line1_width,
|
||||||
int *line2_height_ink,
|
|
||||||
int *line2_height,
|
int *line2_height,
|
||||||
int *line2_width)
|
int *line2_width)
|
||||||
{
|
{
|
||||||
@@ -941,7 +939,6 @@ 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,
|
||||||
@@ -950,13 +947,14 @@ void area_compute_text_geometry(Area *area,
|
|||||||
strlen(line1),
|
strlen(line1),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
((Panel*)area->panel)->scale);
|
||||||
else
|
else
|
||||||
*line1_width = *line1_height_ink = *line1_height = 0;
|
*line1_width = *line1_height = 0;
|
||||||
|
|
||||||
if (line2 && line2[0])
|
if (line2 && line2[0])
|
||||||
get_text_size2(line2_font_desc,
|
get_text_size2(line2_font_desc,
|
||||||
line2_height_ink,
|
|
||||||
line2_height,
|
line2_height,
|
||||||
line2_width,
|
line2_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -965,9 +963,11 @@ void area_compute_text_geometry(Area *area,
|
|||||||
strlen(line2),
|
strlen(line2),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
((Panel*)area->panel)->scale);
|
||||||
else
|
else
|
||||||
*line2_width = *line2_height_ink = *line2_height = 0;
|
*line2_width = *line2_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int text_area_compute_desired_size(Area *area,
|
int text_area_compute_desired_size(Area *area,
|
||||||
@@ -976,16 +976,14 @@ int text_area_compute_desired_size(Area *area,
|
|||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc)
|
PangoFontDescription *line2_font_desc)
|
||||||
{
|
{
|
||||||
int line1_height_ink, line1_height, line1_width, line2_height_ink, line2_height, line2_width;
|
int line1_height, line1_width, line2_height, line2_width;
|
||||||
area_compute_text_geometry(area,
|
area_compute_text_geometry(area,
|
||||||
line1,
|
line1,
|
||||||
line2,
|
line2,
|
||||||
line1_font_desc,
|
line1_font_desc,
|
||||||
line2_font_desc,
|
line2_font_desc,
|
||||||
&line1_height_ink,
|
|
||||||
&line1_height,
|
&line1_height,
|
||||||
&line1_width,
|
&line1_width,
|
||||||
&line2_height_ink,
|
|
||||||
&line2_height,
|
&line2_height,
|
||||||
&line2_width);
|
&line2_width);
|
||||||
|
|
||||||
@@ -1010,17 +1008,15 @@ gboolean resize_text_area(Area *area,
|
|||||||
|
|
||||||
schedule_redraw(area);
|
schedule_redraw(area);
|
||||||
|
|
||||||
int line1_height_ink, line1_height, line1_width;
|
int line1_height, line1_width;
|
||||||
int line2_height_ink, line2_height, line2_width;
|
int line2_height, line2_width;
|
||||||
area_compute_text_geometry(area,
|
area_compute_text_geometry(area,
|
||||||
line1,
|
line1,
|
||||||
line2,
|
line2,
|
||||||
line1_font_desc,
|
line1_font_desc,
|
||||||
line2_font_desc,
|
line2_font_desc,
|
||||||
&line1_height_ink,
|
|
||||||
&line1_height,
|
&line1_height,
|
||||||
&line1_width,
|
&line1_width,
|
||||||
&line2_height_ink,
|
|
||||||
&line2_height,
|
&line2_height,
|
||||||
&line2_width);
|
&line2_width);
|
||||||
|
|
||||||
@@ -1067,12 +1063,16 @@ 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);
|
||||||
|
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_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,6 +1096,7 @@ 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)
|
||||||
|
|||||||
@@ -273,10 +273,8 @@ void area_compute_text_geometry(Area *area,
|
|||||||
const char *line2,
|
const char *line2,
|
||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int *line1_height_ink,
|
|
||||||
int *line1_height,
|
int *line1_height,
|
||||||
int *line1_width,
|
int *line1_width,
|
||||||
int *line2_height_ink,
|
|
||||||
int *line2_height,
|
int *line2_height,
|
||||||
int *line2_width);
|
int *line2_width);
|
||||||
int text_area_compute_desired_size(Area *area,
|
int text_area_compute_desired_size(Area *area,
|
||||||
@@ -299,7 +297,8 @@ void draw_text_area(Area *area,
|
|||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int line1_posy,
|
int line1_posy,
|
||||||
int line2_posy,
|
int line2_posy,
|
||||||
Color *color);
|
Color *color,
|
||||||
|
double scale);
|
||||||
|
|
||||||
int left_border_width(Area *a);
|
int left_border_width(Area *a);
|
||||||
int right_border_width(Area *a);
|
int right_border_width(Area *a);
|
||||||
|
|||||||
17
src/util/bool.h
Normal file
17
src/util/bool.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef BOOL_H
|
||||||
|
#define BOOL_H
|
||||||
|
|
||||||
|
#ifndef bool
|
||||||
|
#define bool int
|
||||||
|
#define false 0
|
||||||
|
#define true 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SUCCESS true
|
||||||
|
#define FAILURE false
|
||||||
|
|
||||||
|
#ifndef Status
|
||||||
|
typedef int Status;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
10
src/util/colors.h
Normal file
10
src/util/colors.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef COLORS_H
|
||||||
|
#define COLORS_H
|
||||||
|
|
||||||
|
#define GREEN "\033[1;32m"
|
||||||
|
#define YELLOW "\033[1;33m"
|
||||||
|
#define RED "\033[1;31m"
|
||||||
|
#define BLUE "\033[1;34m"
|
||||||
|
#define RESET "\033[0m"
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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>
|
||||||
@@ -191,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];
|
||||||
sprintf(s, "SIG=%d: Unknown", sig);
|
snprintf(s, sizeof(s), "SIG=%d: Unknown", sig);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,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];
|
||||||
sprintf(buf, "%d", value);
|
snprintf(buf, sizeof(buf), "%d", value);
|
||||||
return setenv(name, buf, 1);
|
return setenv(name, buf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,9 +461,10 @@ char *expand_tilde(const char *s)
|
|||||||
{
|
{
|
||||||
const gchar *home = g_get_home_dir();
|
const gchar *home = g_get_home_dir();
|
||||||
if (home && (strcmp(s, "~") == 0 || strstr(s, "~/") == s)) {
|
if (home && (strcmp(s, "~") == 0 || strstr(s, "~/") == s)) {
|
||||||
char *result = calloc(strlen(home) + strlen(s), 1);
|
size_t buf_size = strlen(home) + strlen(s);
|
||||||
strcat(result, home);
|
char *result = calloc(buf_size, 1);
|
||||||
strcat(result, s + 1);
|
strlcat(result, home, buf_size);
|
||||||
|
strlcat(result, s + 1, buf_size);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return strdup(s);
|
return strdup(s);
|
||||||
@@ -476,14 +477,16 @@ char *contract_tilde(const char *s)
|
|||||||
if (!home)
|
if (!home)
|
||||||
return strdup(s);
|
return strdup(s);
|
||||||
|
|
||||||
char *home_slash = calloc(strlen(home) + 2, 1);
|
size_t buf_size = strlen(home) + 2;
|
||||||
strcat(home_slash, home);
|
char *home_slash = calloc(buf_size, 1);
|
||||||
strcat(home_slash, "/");
|
strlcat(home_slash, home, buf_size);
|
||||||
|
strlcat(home_slash, "/", buf_size);
|
||||||
|
|
||||||
if ((strcmp(s, home) == 0 || strstr(s, home_slash) == s)) {
|
if ((strcmp(s, home) == 0 || strstr(s, home_slash) == s)) {
|
||||||
char *result = calloc(strlen(s) - strlen(home) + 2, 1);
|
size_t buf_size2 = strlen(s) - strlen(home) + 2;
|
||||||
strcat(result, "~");
|
char *result = calloc(buf_size2, 1);
|
||||||
strcat(result, s + strlen(home));
|
strlcat(result, "~", buf_size2);
|
||||||
|
strlcat(result, s + strlen(home), buf_size2);
|
||||||
free(home_slash);
|
free(home_slash);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@@ -793,7 +796,7 @@ Imlib_Image load_image(const char *path, int cached)
|
|||||||
}
|
}
|
||||||
if (!image && g_str_has_suffix(path, ".svg")) {
|
if (!image && g_str_has_suffix(path, ".svg")) {
|
||||||
char tmp_filename[128];
|
char tmp_filename[128];
|
||||||
sprintf(tmp_filename, "/tmp/tint2-%d.png", (int)getpid());
|
snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d.png", (int)getpid());
|
||||||
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
|
||||||
@@ -921,30 +924,35 @@ void clear_pixmap(Pixmap p, int x, int y, int w, int h)
|
|||||||
XRenderFreePicture(server.display, pict);
|
XRenderFreePicture(server.display, pict);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_text_size2(const PangoFontDescription *font,
|
void get_text_size(const PangoFontDescription *font,
|
||||||
int *height_ink,
|
int *height,
|
||||||
int *height,
|
int *width,
|
||||||
int *width,
|
int available_height,
|
||||||
int available_height,
|
int available_width,
|
||||||
int available_width,
|
const char *text,
|
||||||
const char *text,
|
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_image_surface_create(CAIRO_FORMAT_ARGB32, available_height, available_width);
|
cairo_xlib_surface_create(server.display, pmap, server.visual, available_height, available_width);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
|
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_width(layout, available_width * PANGO_SCALE);
|
pango_layout_set_width(layout, available_width * PANGO_SCALE);
|
||||||
pango_layout_set_height(layout, available_height * PANGO_SCALE);
|
pango_layout_set_height(layout, available_height * PANGO_SCALE);
|
||||||
|
pango_layout_set_alignment(layout, alignment);
|
||||||
pango_layout_set_wrap(layout, wrap);
|
pango_layout_set_wrap(layout, wrap);
|
||||||
pango_layout_set_ellipsize(layout, ellipsis);
|
pango_layout_set_ellipsize(layout, ellipsis);
|
||||||
pango_layout_set_font_description(layout, font);
|
pango_layout_set_font_description(layout, font);
|
||||||
@@ -955,14 +963,63 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
pango_layout_set_markup(layout, text, text_len);
|
pango_layout_set_markup(layout, text, text_len);
|
||||||
|
|
||||||
pango_layout_get_pixel_extents(layout, &rect_ink, &rect);
|
pango_layout_get_pixel_extents(layout, &rect_ink, &rect);
|
||||||
*height_ink = rect_ink.height;
|
|
||||||
*height = rect.height;
|
*height = rect.height;
|
||||||
*width = rect.width;
|
*width = rect.width;
|
||||||
|
|
||||||
// fprintf(stderr, "tint2: dimension : %d - %d\n", rect_ink.height, rect.height);
|
// fprintf(stderr, "tint2: dimension : %d - %d\n", rect_ink.height, rect.height);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
|
XFreePixmap(server.display, pmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
@@ -1111,3 +1168,63 @@ 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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,17 +7,14 @@
|
|||||||
#define COMMON_H
|
#define COMMON_H
|
||||||
|
|
||||||
#define WM_CLASS_TINT "panel"
|
#define WM_CLASS_TINT "panel"
|
||||||
|
#define TINT2_PANGO_SLACK 0
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
|
#include "colors.h"
|
||||||
#define GREEN "\033[1;32m"
|
#include "strlcat.h"
|
||||||
#define YELLOW "\033[1;33m"
|
|
||||||
#define RED "\033[1;31m"
|
|
||||||
#define BLUE "\033[1;34m"
|
|
||||||
#define RESET "\033[0m"
|
|
||||||
|
|
||||||
#define MAX3(a, b, c) MAX(MAX(a, b), c)
|
#define MAX3(a, b, c) MAX(MAX(a, b), c)
|
||||||
#define MIN3(a, b, c) MIN(MIN(a, b), c)
|
#define MIN3(a, b, c) MIN(MIN(a, b), c)
|
||||||
@@ -117,7 +114,6 @@ void create_heuristic_mask(DATA32 *data, int w, int h);
|
|||||||
void render_image(Drawable d, int x, int y);
|
void render_image(Drawable d, int x, int y);
|
||||||
|
|
||||||
void get_text_size2(const PangoFontDescription *font,
|
void get_text_size2(const PangoFontDescription *font,
|
||||||
int *height_ink,
|
|
||||||
int *height,
|
int *height,
|
||||||
int *width,
|
int *width,
|
||||||
int available_height,
|
int available_height,
|
||||||
@@ -126,7 +122,9 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
int text_len,
|
int text_len,
|
||||||
PangoWrapMode wrap,
|
PangoWrapMode wrap,
|
||||||
PangoEllipsizeMode ellipsis,
|
PangoEllipsizeMode ellipsis,
|
||||||
gboolean markup);
|
PangoAlignment alignment,
|
||||||
|
gboolean markup,
|
||||||
|
double scale);
|
||||||
|
|
||||||
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
|
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
|
||||||
|
|
||||||
@@ -153,6 +151,8 @@ 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); \
|
||||||
|
|||||||
471
src/util/mem.c
471
src/util/mem.c
@@ -1,471 +0,0 @@
|
|||||||
#ifdef ENABLE_EXECINFO
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <execinfo.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdc-predef.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
#include "addr2line.h"
|
|
||||||
#include "mem.h"
|
|
||||||
#include "print.h"
|
|
||||||
|
|
||||||
#ifndef RTLD_NEXT
|
|
||||||
# define RTLD_NEXT ((void *) -1l)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
ListItem *n = (ListItem*)calloc(1, sizeof(ListItem));
|
|
||||||
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;
|
|
||||||
if (num_buckets < 1)
|
|
||||||
num_buckets = 4096;
|
|
||||||
table->num_buckets = num_buckets;
|
|
||||||
table->buckets = (List*)calloc(table->num_buckets, sizeof(List));
|
|
||||||
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 *hash_table_add(HashTable *table, void *data)
|
|
||||||
{
|
|
||||||
size_t hash = table->hash_func(data);
|
|
||||||
size_t bucket = hash % table->num_buckets;
|
|
||||||
for (ListItem *existing = table->buckets[bucket].head; existing; existing = existing->next) {
|
|
||||||
if (table->equal_func(existing->data, data))
|
|
||||||
return existing->data;
|
|
||||||
}
|
|
||||||
list_append(&table->buckets[bucket], table->copy_func(data));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_TRACE_SIZE 120
|
|
||||||
|
|
||||||
typedef struct Trace {
|
|
||||||
void *entries[MAX_TRACE_SIZE+8];
|
|
||||||
size_t id;
|
|
||||||
} Trace;
|
|
||||||
|
|
||||||
#define LARGE_THRESH (10 * 1024 * 1024)
|
|
||||||
|
|
||||||
static void *(*calloc_original)(size_t count, size_t size) = NULL;
|
|
||||||
static void *(*realloc_original)(void *p, size_t size) = NULL;
|
|
||||||
static void *(*malloc_original)(size_t size) = NULL;
|
|
||||||
static void *(*free_original)(void *p) = NULL;
|
|
||||||
static gzFile mem_log = NULL;
|
|
||||||
static pid_t mem_log_owner = 0;
|
|
||||||
pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
static HashTable traces;
|
|
||||||
static size_t next_trace_id = 0;
|
|
||||||
pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
static HashTable addr2lines;
|
|
||||||
pthread_mutex_t addr2lines_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
thread_local int paused = 0;
|
|
||||||
|
|
||||||
static double get_unix_time()
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
if (gettimeofday(&tv, NULL) != 0)
|
|
||||||
return 0;
|
|
||||||
return tv.tv_sec + 1.0e-6 * tv.tv_usec;
|
|
||||||
}
|
|
||||||
|
|
||||||
__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)
|
|
||||||
{
|
|
||||||
int size = 0;
|
|
||||||
for (void **p = trace->entries; *p; p++) {
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct FilenameLookup {
|
|
||||||
char *file_name;
|
|
||||||
Lookup *lookup;
|
|
||||||
} FilenameLookup;
|
|
||||||
|
|
||||||
size_t hash_lookup(void *data)
|
|
||||||
{
|
|
||||||
FilenameLookup *lookup = (FilenameLookup *)data;
|
|
||||||
size_t seed = 14695981039346656037ULL;
|
|
||||||
size_t hash = seed;
|
|
||||||
for (char *p = lookup->file_name; *p; p++) {
|
|
||||||
hash = (hash ^ (size_t)(*p)) * 1099511628211ULL;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
int equal_lookup(void *data1, void *data2)
|
|
||||||
{
|
|
||||||
FilenameLookup *lookup1 = (FilenameLookup *)data1;
|
|
||||||
FilenameLookup *lookup2 = (FilenameLookup *)data2;
|
|
||||||
return strcmp(lookup1->file_name, lookup2->file_name) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *resolve_symbol(char *file_name, void *address)
|
|
||||||
{
|
|
||||||
FilenameLookup *lookup = (FilenameLookup *)calloc(1, sizeof(FilenameLookup));
|
|
||||||
lookup->file_name = strdup(file_name);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&addr2lines_mutex);
|
|
||||||
hash_table_init(&addr2lines, 0, hash_lookup, equal_lookup, NULL);
|
|
||||||
FilenameLookup *existing = (FilenameLookup *)hash_table_add(&addr2lines, lookup);
|
|
||||||
if (existing == lookup) {
|
|
||||||
lookup->lookup = addr2line_init(lookup->file_name);
|
|
||||||
} else {
|
|
||||||
free(lookup->file_name);
|
|
||||||
free(lookup);
|
|
||||||
}
|
|
||||||
char *result = addr2line_lookup(existing->lookup, address);
|
|
||||||
pthread_mutex_unlock(&addr2lines_mutex);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *backtrace_to_string(Trace *trace)
|
|
||||||
{
|
|
||||||
int size = trace_size(trace);
|
|
||||||
char **strings = backtrace_symbols(trace->entries, size);
|
|
||||||
if (!strings)
|
|
||||||
return NULL;
|
|
||||||
Buffer *buffer = NULL;
|
|
||||||
buffer = buffer_printf(buffer, "t %lu ", trace->id);
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
buffer = buffer_printf(buffer, "%s", strings[i]);
|
|
||||||
// /lib/x86_64-linux-gnu/libglib-2.0.so.0(g_realloc+0xf) [0x7efda85c96af]
|
|
||||||
char *func_start = strstr(strings[i], "(");
|
|
||||||
if (func_start) {
|
|
||||||
*func_start = 0;
|
|
||||||
char *file_name = strings[i];
|
|
||||||
char *resolved = resolve_symbol(file_name, trace->entries[i]);
|
|
||||||
if (resolved) {
|
|
||||||
buffer = buffer_printf(buffer, " %s", resolved);
|
|
||||||
free(resolved);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
trace->id = existing->id;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&trace_mutex);
|
|
||||||
return created;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_flush();
|
|
||||||
|
|
||||||
static void log_init()
|
|
||||||
{
|
|
||||||
char path[256];
|
|
||||||
sprintf(path, "/tmp/tint2.%lu.memtrace", (size_t)getpid());
|
|
||||||
pthread_mutex_lock(&log_mutex);
|
|
||||||
if (!mem_log) {
|
|
||||||
mem_log = gzopen(path, "w");
|
|
||||||
mem_log_owner = getpid();
|
|
||||||
atexit(log_flush);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&log_mutex);
|
|
||||||
if (mem_log)
|
|
||||||
fprintf(stderr, "Writing memory log to %s\n", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_write(char *buffer)
|
|
||||||
{
|
|
||||||
if (mem_log) {
|
|
||||||
pthread_mutex_lock(&log_mutex);
|
|
||||||
if (getpid() == mem_log_owner)
|
|
||||||
gzwrite(mem_log, buffer, (unsigned)strlen(buffer));
|
|
||||||
pthread_mutex_unlock(&log_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_flush()
|
|
||||||
{
|
|
||||||
if (mem_log) {
|
|
||||||
pthread_mutex_lock(&log_mutex);
|
|
||||||
if (getpid() == mem_log_owner)
|
|
||||||
gzflush(mem_log, Z_SYNC_FLUSH);
|
|
||||||
pthread_mutex_unlock(&log_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void malloc_profile_load_pointers()
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (paused)
|
|
||||||
return malloc_original ? malloc_original(size) : 0;
|
|
||||||
paused = 1;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free(void *p)
|
|
||||||
{
|
|
||||||
if (paused) {
|
|
||||||
if (free_original)
|
|
||||||
free_original(p);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
paused = 1;
|
|
||||||
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
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#ifndef MEM_H
|
|
||||||
#define MEM_H
|
|
||||||
|
|
||||||
#endif
|
|
||||||
107
src/util/print.c
107
src/util/print.c
@@ -1,40 +1,83 @@
|
|||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
Buffer *vbuffer_printf(Buffer *buffer, const char *fmt, va_list ap)
|
int print_uchar(unsigned char v)
|
||||||
{
|
{
|
||||||
va_list ap1;
|
return printf("%u", v);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
vsnprintf(buffer->data + strlen(buffer->data), size, fmt, ap);
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer *buffer_printf(Buffer *buffer, const char *fmt, ...)
|
int print_char(char v)
|
||||||
{
|
{
|
||||||
va_list ap;
|
return printf("%c", v);
|
||||||
|
}
|
||||||
va_start(ap, fmt);
|
|
||||||
buffer = vbuffer_printf(buffer, fmt, ap);
|
int print_short(short v)
|
||||||
va_end(ap);
|
{
|
||||||
|
return printf("%d", v);
|
||||||
return buffer;
|
}
|
||||||
|
|
||||||
|
int print_ushort(unsigned short v)
|
||||||
|
{
|
||||||
|
return printf("%u", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_int(int v)
|
||||||
|
{
|
||||||
|
return printf("%d", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_uint(unsigned v)
|
||||||
|
{
|
||||||
|
return printf("%u", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_long(long v)
|
||||||
|
{
|
||||||
|
return printf("%ld", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_ulong(unsigned long v)
|
||||||
|
{
|
||||||
|
return printf("%lu", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_long_long(long long v)
|
||||||
|
{
|
||||||
|
return printf("%lld", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_ulong_long(unsigned long long v)
|
||||||
|
{
|
||||||
|
return printf("%llu", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_float(float v)
|
||||||
|
{
|
||||||
|
return printf("%f", (double)v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_double(double v)
|
||||||
|
{
|
||||||
|
return printf("%f", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_long_double(long double v)
|
||||||
|
{
|
||||||
|
return printf("%Lf", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_string(char *s)
|
||||||
|
{
|
||||||
|
return printf("%s", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_pointer(void *v)
|
||||||
|
{
|
||||||
|
return printf("%p", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_unknown()
|
||||||
|
{
|
||||||
|
return printf("(variable of unknown type)");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,61 @@
|
|||||||
#ifndef PRINT_H
|
#ifndef PRINT_H
|
||||||
#define PRINT_H
|
#define PRINT_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#ifdef HAS_GENERIC
|
||||||
#include <stddef.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
typedef struct Buffer {
|
int print_uchar(unsigned char v);
|
||||||
char *data;
|
|
||||||
size_t size;
|
|
||||||
} Buffer;
|
|
||||||
|
|
||||||
Buffer *vbuffer_printf(Buffer *buffer, const char *fmt, va_list ap);
|
int print_char(char v);
|
||||||
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
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xrender.h>
|
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -311,6 +311,21 @@ void sort_monitors()
|
|||||||
qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos);
|
qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compute_dpi(XRRCrtcInfo *crtc, XRROutputInfo *output)
|
||||||
|
{
|
||||||
|
double width = output->mm_width;
|
||||||
|
double height = output->mm_height;
|
||||||
|
double x_res = crtc->width;
|
||||||
|
double y_res = crtc->height;
|
||||||
|
|
||||||
|
if (width > 0 && height > 0) {
|
||||||
|
int dpi_x = x_res / width * 25.4;
|
||||||
|
int dpi_y = y_res / height * 25.4;
|
||||||
|
return MAX(dpi_x, dpi_y);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void get_monitors()
|
void get_monitors()
|
||||||
{
|
{
|
||||||
if (XineramaIsActive(server.display)) {
|
if (XineramaIsActive(server.display)) {
|
||||||
@@ -339,12 +354,22 @@ void get_monitors()
|
|||||||
server.monitors[i_monitor].width = crtc_info->width;
|
server.monitors[i_monitor].width = crtc_info->width;
|
||||||
server.monitors[i_monitor].height = crtc_info->height;
|
server.monitors[i_monitor].height = crtc_info->height;
|
||||||
server.monitors[i_monitor].names = calloc((crtc_info->noutput + 1), sizeof(gchar *));
|
server.monitors[i_monitor].names = calloc((crtc_info->noutput + 1), sizeof(gchar *));
|
||||||
|
server.monitors[i_monitor].dpi = 96;
|
||||||
for (int j = 0; j < crtc_info->noutput; ++j) {
|
for (int j = 0; j < crtc_info->noutput; ++j) {
|
||||||
XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]);
|
XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]);
|
||||||
fprintf(stderr, "tint2: xRandr: Linking output %s with crtc %d\n", output_info->name, i);
|
|
||||||
server.monitors[i_monitor].names[j] = g_strdup(output_info->name);
|
server.monitors[i_monitor].names[j] = g_strdup(output_info->name);
|
||||||
XRRFreeOutputInfo(output_info);
|
|
||||||
server.monitors[i_monitor].primary = crtc_info->outputs[j] == primary_output;
|
server.monitors[i_monitor].primary = crtc_info->outputs[j] == primary_output;
|
||||||
|
int dpi = compute_dpi(crtc_info, output_info);
|
||||||
|
if (dpi)
|
||||||
|
server.monitors[i_monitor].dpi = dpi;
|
||||||
|
fprintf(stderr,
|
||||||
|
BLUE "tint2: xRandr: Linking output %s with crtc %d, resolution %dx%d, DPI %d" RESET "\n",
|
||||||
|
output_info->name,
|
||||||
|
i,
|
||||||
|
server.monitors[i_monitor].width,
|
||||||
|
server.monitors[i_monitor].height,
|
||||||
|
server.monitors[i_monitor].dpi);
|
||||||
|
XRRFreeOutputInfo(output_info);
|
||||||
}
|
}
|
||||||
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
||||||
XRRFreeCrtcInfo(crtc_info);
|
XRRFreeCrtcInfo(crtc_info);
|
||||||
@@ -357,6 +382,7 @@ void get_monitors()
|
|||||||
server.monitors[i].width = info[i].width;
|
server.monitors[i].width = info[i].width;
|
||||||
server.monitors[i].height = info[i].height;
|
server.monitors[i].height = info[i].height;
|
||||||
server.monitors[i].names = NULL;
|
server.monitors[i].names = NULL;
|
||||||
|
server.monitors[i].dpi = 96;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,6 +419,7 @@ void get_monitors()
|
|||||||
server.monitors[0].width = DisplayWidth(server.display, server.screen);
|
server.monitors[0].width = DisplayWidth(server.display, server.screen);
|
||||||
server.monitors[0].height = DisplayHeight(server.display, server.screen);
|
server.monitors[0].height = DisplayHeight(server.display, server.screen);
|
||||||
server.monitors[0].names = 0;
|
server.monitors[0].names = 0;
|
||||||
|
server.monitors[0].dpi = 96;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +550,8 @@ int get_current_desktop()
|
|||||||
// fprintf(stderr, "tint2: \n");
|
// fprintf(stderr, "tint2: \n");
|
||||||
// fprintf(stderr, "tint2: Work area size: %d x %d\n", work_area_width, work_area_height);
|
// fprintf(stderr, "tint2: Work area size: %d x %d\n", work_area_width, work_area_height);
|
||||||
// fprintf(stderr, "tint2: Viewport pos: %d x %d\n", viewport_x, viewport_y);
|
// fprintf(stderr, "tint2: Viewport pos: %d x %d\n", viewport_x, viewport_y);
|
||||||
// fprintf(stderr, "tint2: Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x / work_area_width);
|
// fprintf(stderr, "tint2: Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x /
|
||||||
|
//work_area_width);
|
||||||
|
|
||||||
int result = (viewport_y / work_area_height) * ncols + viewport_x / work_area_width;
|
int result = (viewport_y / work_area_height) * ncols + viewport_x / work_area_width;
|
||||||
return MAX(0, MIN(server.num_desktops - 1, result));
|
return MAX(0, MIN(server.num_desktops - 1, result));
|
||||||
@@ -107,6 +107,7 @@ typedef struct Monitor {
|
|||||||
int y;
|
int y;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
int dpi;
|
||||||
gboolean primary;
|
gboolean primary;
|
||||||
gchar **names;
|
gchar **names;
|
||||||
} Monitor;
|
} Monitor;
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#ifndef TINT2CONF
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -34,6 +36,7 @@ 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
|
||||||
@@ -164,3 +167,4 @@ int get_signal_pending()
|
|||||||
{
|
{
|
||||||
return signal_pending;
|
return signal_pending;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
60
src/util/strlcat.c
Normal file
60
src/util/strlcat.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* $NetBSD: strlcat.c,v 1.4 2005/05/16 06:55:48 lukem Exp $ */
|
||||||
|
/* from NetBSD: strlcat.c,v 1.16 2003/10/27 00:12:42 lukem Exp */
|
||||||
|
/* from OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
|
||||||
|
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "strlcat.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||||
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
|
* If retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcat(char *dst, const char *src, size_t siz)
|
||||||
|
{
|
||||||
|
char *d = dst;
|
||||||
|
const char *s = src;
|
||||||
|
size_t n = siz;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||||
|
while (n-- != 0 && *d != '\0')
|
||||||
|
d++;
|
||||||
|
dlen = d - dst;
|
||||||
|
n = siz - dlen;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return(dlen + strlen(s));
|
||||||
|
while (*s != '\0') {
|
||||||
|
if (n != 1) {
|
||||||
|
*d++ = *s;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
|
return(dlen + (s - src)); /* count does not include NUL */
|
||||||
|
}
|
||||||
16
src/util/strlcat.h
Normal file
16
src/util/strlcat.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef STRLCAT_H
|
||||||
|
#define STRLCAT_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||||
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
|
* If retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||||
|
|
||||||
|
#endif
|
||||||
183
src/util/test.c
Normal file
183
src/util/test.c
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "colors.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
typedef struct TestListItem {
|
||||||
|
Test *test;
|
||||||
|
const char *name;
|
||||||
|
} TestListItem;
|
||||||
|
|
||||||
|
static GList *all_tests = NULL;
|
||||||
|
|
||||||
|
void register_test_(Test *test, const char *name)
|
||||||
|
{
|
||||||
|
TestListItem *item = (TestListItem *)calloc(sizeof(TestListItem), 1);
|
||||||
|
item->test = test;
|
||||||
|
item->name = name;
|
||||||
|
all_tests = g_list_append(all_tests, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *test_log_name_from_test_name(const char *test_name)
|
||||||
|
{
|
||||||
|
char *output_name = g_strdup_printf("test_%s.log", test_name);
|
||||||
|
char *result = strdup(output_name);
|
||||||
|
g_free(output_name);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void redirect_test_output(const char *test_name)
|
||||||
|
{
|
||||||
|
char *output_name = test_log_name_from_test_name(test_name);
|
||||||
|
int fd = open(output_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||||
|
if (fd == -1)
|
||||||
|
goto err;
|
||||||
|
if (dup2(fd, STDOUT_FILENO) == -1)
|
||||||
|
goto err;
|
||||||
|
if (dup2(fd, STDERR_FILENO) == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
free(output_name);
|
||||||
|
return;
|
||||||
|
err:
|
||||||
|
fprintf(stderr, "tint2: Could not redirect test output to file name: %s\n", output_name);
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
free(output_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crash(int sig)
|
||||||
|
{
|
||||||
|
kill(getpid(), SIGSEGV);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
static void run_test_child(TestListItem *item)
|
||||||
|
{
|
||||||
|
reset_signals();
|
||||||
|
struct sigaction sa = {.sa_handler = crash};
|
||||||
|
sigaction(SIGINT, &sa, 0);
|
||||||
|
redirect_test_output(item->name);
|
||||||
|
bool result = true;
|
||||||
|
item->test(&result);
|
||||||
|
exit(result ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE *open_test_log(const char *test_name)
|
||||||
|
{
|
||||||
|
char *output_name = test_log_name_from_test_name(test_name);
|
||||||
|
FILE *log = fopen(output_name, "a");
|
||||||
|
free(output_name);
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Status run_test_parent(TestListItem *item, pid_t child)
|
||||||
|
{
|
||||||
|
FILE *log = open_test_log(item->name);
|
||||||
|
if (child == -1) {
|
||||||
|
fprintf(log, "\n" "Test failed, fork failed\n");
|
||||||
|
fclose(log);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int child_status;
|
||||||
|
pid_t ret_pid = waitpid(child, &child_status, 0);
|
||||||
|
if (ret_pid != child) {
|
||||||
|
fprintf(log, "\n" "Test failed, waitpid failed\n");
|
||||||
|
fclose(log);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
if (WIFEXITED(child_status)) {
|
||||||
|
int exit_status = WEXITSTATUS(child_status);
|
||||||
|
if (exit_status == EXIT_SUCCESS) {
|
||||||
|
fprintf(log, "\n" "Test succeeded.\n");
|
||||||
|
fclose(log);
|
||||||
|
return SUCCESS;
|
||||||
|
} else {
|
||||||
|
fprintf(log, "\n" "Test failed, exit status: %d.\n", exit_status);
|
||||||
|
fclose(log);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
} else if (WIFSIGNALED(child_status)) {
|
||||||
|
int signal = WTERMSIG(child_status);
|
||||||
|
fprintf(log, "\n" "Test failed, child killed by signal: %d.\n", signal);
|
||||||
|
fclose(log);
|
||||||
|
return FAILURE;
|
||||||
|
} else {
|
||||||
|
fprintf(log, "\n" "Test failed, waitpid failed.\n");
|
||||||
|
fclose(log);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Status run_test(TestListItem *item)
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0)
|
||||||
|
run_test_child(item);
|
||||||
|
struct sigaction sa = {.sa_handler = SIG_IGN};
|
||||||
|
sigaction(SIGINT, &sa, 0);
|
||||||
|
return run_test_parent(item, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_all_tests(bool verbose)
|
||||||
|
{
|
||||||
|
fprintf(stdout, BLUE "tint2: Running %d tests..." RESET "\n", g_list_length(all_tests));
|
||||||
|
size_t count = 0, succeeded = 0, failed = 0;
|
||||||
|
for (GList *l = all_tests; l; l = l->next) {
|
||||||
|
TestListItem *item = (TestListItem *)l->data;
|
||||||
|
Status status = run_test(item);
|
||||||
|
count++;
|
||||||
|
fprintf(stdout, BLUE "tint2: Test " YELLOW "%s" BLUE ": ", item->name);
|
||||||
|
if (status == SUCCESS) {
|
||||||
|
fprintf(stdout, GREEN "succeeded" RESET "\n");
|
||||||
|
succeeded++;
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, RED "failed" RESET "\n");
|
||||||
|
failed++;
|
||||||
|
if (verbose) {
|
||||||
|
char *log_name = test_log_name_from_test_name(item->name);
|
||||||
|
FILE *log = fopen(log_name, "rt");
|
||||||
|
if (log) {
|
||||||
|
char buffer[4096];
|
||||||
|
size_t num_read;
|
||||||
|
while ((num_read = fread(buffer, 1, sizeof(buffer), log)) > 0) {
|
||||||
|
fwrite(buffer, 1, num_read, stdout);
|
||||||
|
}
|
||||||
|
fclose(log);
|
||||||
|
}
|
||||||
|
free(log_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (failed == 0)
|
||||||
|
fprintf(stdout, BLUE "tint2: " GREEN "all %lu tests succeeded." RESET "\n", count);
|
||||||
|
else
|
||||||
|
fprintf(stdout, BLUE "tint2: " RED "%lu" BLUE " out of %lu tests " RED "failed." RESET "\n", failed, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
TEST(dummy) {
|
||||||
|
int x = 2;
|
||||||
|
int y = 2;
|
||||||
|
ASSERT_EQUAL(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(dummy_bad) {
|
||||||
|
int x = 2;
|
||||||
|
int y = 3;
|
||||||
|
ASSERT_EQUAL(x, y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
72
src/util/test.h
Normal file
72
src/util/test.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#ifndef TEST_H
|
||||||
|
#define TEST_H
|
||||||
|
|
||||||
|
#include "bool.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
typedef void Test(Status *test_result_);
|
||||||
|
|
||||||
|
void register_test_(Test *test, const char *name);
|
||||||
|
|
||||||
|
#define TEST(name) \
|
||||||
|
void test_##name(Status *test_result_); \
|
||||||
|
__attribute__((constructor)) void test_register_##name() \
|
||||||
|
{ \
|
||||||
|
register_test_(test_##name, #name); \
|
||||||
|
} \
|
||||||
|
void test_##name(Status *test_result_)
|
||||||
|
|
||||||
|
void run_all_tests(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
|
||||||
1999
src/util/timer.c
1999
src/util/timer.c
File diff suppressed because it is too large
Load Diff
@@ -21,45 +21,52 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include "bool.h"
|
||||||
|
|
||||||
// Single shot timers (i.e. timers with interval_msec == 0) are deleted automatically as soon as they expire,
|
extern bool debug_timers;
|
||||||
// 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 struct _timeout timeout;
|
typedef void TimerCallback(void *arg);
|
||||||
|
|
||||||
// Initializes default global data.
|
typedef struct {
|
||||||
void default_timeout();
|
char name_[64];
|
||||||
|
bool enabled_;
|
||||||
|
long long expiration_time_ms_;
|
||||||
|
int period_ms_;
|
||||||
|
TimerCallback *callback_;
|
||||||
|
void *arg_;
|
||||||
|
bool handled_;
|
||||||
|
} Timer;
|
||||||
|
|
||||||
// Cleans up: stops all timers and frees memory.
|
#define DEFAULT_TIMER {"", 0, 0, 0, 0, 0, 0}
|
||||||
void cleanup_timeout();
|
|
||||||
|
|
||||||
// Installs a timer with the first timeout after 'value_msec' and then an optional periodic timeout every
|
#define INIT_TIMER(t) init_timer(&t, #t)
|
||||||
// 'interval_msec' (set it to 0 to prevent periodic timeouts).
|
|
||||||
// '_callback' is the function called when the timer reaches the timeout.
|
|
||||||
// 'arg' is the argument passed to the callback function.
|
|
||||||
// 'self' is an optional pointer to a timeout* variable. If non-NULL, the variable is set to NULL when the timer
|
|
||||||
// is destroyed (with stop_timeout, cleanup_timeout or when the timer expires and it is single-shot).
|
|
||||||
// Returns a pointer to the timer, which is needed for stopping/changing it.
|
|
||||||
timeout *add_timeout(int value_msec, int interval_msec, void (*_callback)(void *), void *arg, timeout **self);
|
|
||||||
|
|
||||||
// Changes timer 't'. If it does not exist, a new timer is created, with self set to 't'.
|
// Initialize the timer module.
|
||||||
void change_timeout(timeout **t, int value_msec, int interval_msec, void (*_callback)(void *), void *arg);
|
void default_timers();
|
||||||
|
|
||||||
// Stops the timer 't'
|
// Destroy the timer module.
|
||||||
void stop_timeout(timeout *t);
|
void cleanup_timers();
|
||||||
|
|
||||||
// Get the time when the next installed timer will expire, or NULL if there is no timer.
|
// Initialize a timer. Caller keeps ownership.
|
||||||
// Do not free the pointer; but it is safe to change its contents.
|
void init_timer(Timer *timer, const char *name);
|
||||||
struct timeval *get_next_timeout();
|
|
||||||
|
|
||||||
// Callback of all expired timeouts
|
// Destroy a timer. Does not free() the pointer.
|
||||||
|
void destroy_timer(Timer *timer);
|
||||||
|
|
||||||
|
// Modify a timer.
|
||||||
|
void change_timer(Timer *timer, bool enabled, int delay_ms, int period_ms, TimerCallback *callback, void *arg);
|
||||||
|
|
||||||
|
void stop_timer(Timer *timer);
|
||||||
|
|
||||||
|
// Get the time duration to the next expiration time, or NULL if there is no active timer.
|
||||||
|
// Do not free the pointer; it is harmless to change its contents.
|
||||||
|
struct timeval *get_duration_to_next_timer_expiration();
|
||||||
|
|
||||||
|
// Trigger all expired timers, and reschedule them if they are periodic timers
|
||||||
void handle_expired_timers();
|
void handle_expired_timers();
|
||||||
|
|
||||||
|
// Time helper functions.
|
||||||
|
|
||||||
// Returns -1 if t1 < t2, 0 if t1 == t2, 1 if t1 > t2
|
// Returns -1 if t1 < t2, 0 if t1 == t2, 1 if t1 > t2
|
||||||
gint compare_timespecs(const struct timespec *t1, const struct timespec *t2);
|
gint compare_timespecs(const struct timespec *t1, const struct timespec *t2);
|
||||||
|
|
||||||
@@ -69,6 +76,7 @@ struct timespec add_msec_to_timespec(struct timespec ts, int msec);
|
|||||||
// At the first call returns zero.
|
// At the first call returns zero.
|
||||||
double profiling_get_time();
|
double profiling_get_time();
|
||||||
|
|
||||||
|
// Get current time in seconds, from an unspecified origin.
|
||||||
double get_time();
|
double get_time();
|
||||||
|
|
||||||
#endif // TIMER_H
|
#endif // TIMER_H
|
||||||
|
|||||||
@@ -49,8 +49,9 @@ char *addr2name(void *func)
|
|||||||
free(strings);
|
free(strings);
|
||||||
return result;
|
return result;
|
||||||
#else
|
#else
|
||||||
char *result = (char*) calloc(32, 1);
|
const size_t buf_size = 32;
|
||||||
sprintf(result, "%p", func);
|
char *result = (char*) calloc(buf_size, 1);
|
||||||
|
snprintf(result, buf_size, "%p", func);
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
#!/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,6 +10,7 @@ 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
|
||||||
@@ -39,6 +40,10 @@ 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,
|
||||||
@@ -188,6 +193,7 @@ 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))
|
||||||
@@ -222,6 +228,41 @@ 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"))
|
||||||
@@ -285,6 +326,29 @@ 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 "")
|
||||||
@@ -350,8 +414,11 @@ 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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
18
tint2.config
18
tint2.config
@@ -1,8 +1,16 @@
|
|||||||
// ADD PREDEFINED MACROS HERE!
|
// ADD PREDEFINED MACROS HERE!
|
||||||
#define HAVE_RSVG 1
|
#define DISABLE_BACKTRACE 1
|
||||||
#define HAVE_SN 1
|
|
||||||
#define ENABLE_BATTERY 1
|
#define ENABLE_BATTERY 1
|
||||||
#define ENABLE_UEVENT 1
|
#define ENABLE_UEVENT 1
|
||||||
#define GETTEXT_PACKAGE
|
#define GETTEXT_PACKAGE "tint2conf"
|
||||||
#define HAVE_TRACING
|
#define HAS_GENERIC 1
|
||||||
#define ENABLE_EXECINFO
|
#define HAVE_RSVG 1
|
||||||
|
#define HAVE_SN 1
|
||||||
|
#define HAVE_VERSION_H 1
|
||||||
|
#define INSTALL_PREFIX "/usr/local"
|
||||||
|
#define LOCALEDIR "/usr/local/share/locale"
|
||||||
|
#define SN_API_NOT_YET_FROZEN
|
||||||
|
#define _BSD_SOURCE
|
||||||
|
#define _DEFAULT_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE=200809L
|
||||||
|
#define _WITH_GETLINE
|
||||||
|
|||||||
23
tint2.files
23
tint2.files
@@ -20,6 +20,9 @@ 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
|
||||||
@@ -58,6 +61,10 @@ src/util/blur.c
|
|||||||
src/util/blur.h
|
src/util/blur.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
|
||||||
@@ -237,9 +244,15 @@ src/signals.c
|
|||||||
src/signals.h
|
src/signals.h
|
||||||
src/tracing.c
|
src/tracing.c
|
||||||
src/tracing.h
|
src/tracing.h
|
||||||
src/util/mem.c
|
src/util/test.c
|
||||||
src/util/mem.h
|
src/util/test.h
|
||||||
src/util/addr2line.c
|
src/util/bool.h
|
||||||
src/util/addr2line.h
|
src/util/colors.h
|
||||||
src/util/print.h
|
|
||||||
src/util/print.c
|
src/util/print.c
|
||||||
|
src/util/print.h
|
||||||
|
src/util/test.c
|
||||||
|
src/util/test.h
|
||||||
|
src/util/tracing.h
|
||||||
|
src/util/tracing.c
|
||||||
|
src/util/signals.h
|
||||||
|
src/util/signals.c
|
||||||
|
|||||||
@@ -1,22 +1,33 @@
|
|||||||
.
|
.
|
||||||
|
./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/tint2conf
|
./src/launcher
|
||||||
./src/tooltip
|
./src/tooltip
|
||||||
./src/util
|
./src/util
|
||||||
/usr/include
|
./src/execplugin
|
||||||
/usr/include/gtk-2.0
|
./src/button
|
||||||
/usr/include/glib-2.0
|
./src/freespace
|
||||||
/usr/include/gdk-pixbuf-2.0
|
./src/separator
|
||||||
/usr/include/cairo
|
|
||||||
/usr/include/pango-1.0
|
/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/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
|
||||||
po
|
po
|
||||||
src/tint2conf/po
|
src/tint2conf/po
|
||||||
src/freespace
|
src/freespace
|
||||||
|
|||||||
Reference in New Issue
Block a user