Compare commits

...

59 Commits

Author SHA1 Message Date
Chris Lee
f8f9c18cef Release 17.0.2 2021-12-04 10:46:45 +01:00
Chris Lee
56bccf2b4f Update changelog 2021-12-04 10:45:36 +01:00
Chris Lee
ec4eccd769 Add tint2-send to cmake 2021-11-21 01:23:39 +01:00
Chris Lee
2ed026ba32 Attempt to fix get window monitor 2021-11-14 10:24:14 +01:00
Chris
a4996c84bd Update .gitlab-ci.yml file 2021-06-27 23:47:21 +00:00
Chris Lee
7b42055a20 add ci pipeline 2021-06-28 01:25:46 +02:00
Chris Lee
f628cba966 Release 17.0.1 2021-05-29 11:24:56 +02:00
Chris Lee
a922884485 update changelog 2021-05-01 19:16:51 +02:00
Chris Lee
66a6238014 fix crash in single-monitor execp 2021-05-01 19:15:38 +02:00
Chris Lee
5e8c65b87e remove useless fsync 2021-05-01 19:12:28 +02:00
Chris Lee
7737edff47 Release 17.0 2021-04-18 19:43:11 -07:00
Chris Lee
b7e7743b21 update changelog 2021-04-18 19:42:58 -07:00
Chris Lee
7232feee5a fix incorrect timeout microsecond computation 2021-04-14 23:38:36 +02:00
Chris
6b127f9661 Merge branch 'imlib-leak' into 'master'
Fix imlib image leak

Closes #704

See merge request o9000/tint2!39
2021-03-23 23:00:58 +00:00
Adam M. Trofa
e2641092b8 Fix imlib image leak
Double-adding the image caused imlib's reference count to increment
twice, requiring us to free it twice to actually release the cached
image, but we only ever free it once.

Fixes #704, likely #721 (leak is not present with -DENABLE_RSVG=OFF),
possibly #650 based on connection to execp, maybe others since this was
introduced nearly 6 years ago in 1d02b858 in launcher-specific code.
2021-03-19 19:44:25 -04:00
Chris Lee
49e7f54d2f preserve item order when skipping executors #799 2021-02-25 00:01:39 +01:00
Chris Lee
0f00212c58 add execp_monitor config #799 2021-02-24 22:08:20 +01:00
Chris Lee
dba0e66646 add scrollbars to fix issue #796 2021-01-26 23:15:51 +01:00
Chris Lee
2ed7ecb08d revert change to cmakefile 2021-01-04 22:21:50 +01:00
Chris Lee
f9cb16a0f0 attempt to port to gtk3 2021-01-04 22:06:31 +01:00
Chris Lee
06bcb3f2da attempt to fix #786 2021-01-02 23:22:22 +01:00
Chris
03b86f5f2c Merge branch 'big_icon_crash' into 'master'
Fix crashing when a window icon is large

See merge request o9000/tint2!35
2020-12-24 18:14:26 +00:00
Chris
b56147efb7 Merge branch 'executor-example-memusage' into 'master'
Enhanced example for memusage executor

Closes #787

See merge request o9000/tint2!38
2020-12-24 18:10:22 +00:00
Nikita Zlobin
ca3588cab0 Improve network bandwidth executor example too (stdbuf -oL)
If memusage example got stdbuf -oL awk, why further examples
can't use same?
2020-12-24 00:25:41 +05:00
Nikita Zlobin
795302fbaf More reasonable comment about stdbuf -oL 2020-12-24 00:22:48 +05:00
Nikita Zlobin
60ee870ae5 Oops, avoid gawk coprocess extension 2020-12-24 00:16:00 +05:00
Nikita Zlobin
975149642f Use numfmt to get back human output in memory usage executor 2020-12-05 23:48:33 +05:00
Nikita Zlobin
bba945b3b9 Enhanced example for memory usage executor, sync for all docs
It seems, html help already had one free instance with -s option for persistance,
though still used inner non-persistant chain for humanized output.
2020-11-30 13:00:21 +05:00
Chris Lee
5b3f9c4662 fix help message 2020-06-27 13:55:55 +00:00
Chris Lee
3bdb0e03f2 #643 Hide/unhide programatically 2020-06-27 12:02:00 +00:00
santouits
27a8ea013e Fix crashing when a window icon is large
If an icon of a window is large tint2 crashes with segmentation fault, I guess because of stack overflow. This changes the allocation of icon_data from stack to heap.
2019-10-29 21:22:23 +02:00
Chris Lee
78313502d3 Release 16.7 2019-07-14 23:15:40 -07:00
Chris Lee
3eae1ba912 fix release script 2019-07-14 23:15:01 -07:00
Chris Lee
22ce7c5427 Remove debug code from release mode 2019-07-12 22:47:07 -07:00
Chris Lee
784edaccd2 Expand leading tilde in icon paths (fixes #743) 2019-06-02 22:08:20 +02:00
Chris Lee
b9c313cd18 add script to compile dependencies 2019-04-28 19:24:51 +02:00
Chris Lee
10723b1db5 workaround broken battery blink with intel gpu 2019-03-09 12:51:33 +01:00
Chris Lee
89c02d3912 use simpler battery blink method 2019-03-09 12:33:52 +01:00
Chris Lee
da75999832 add env var to debug battery blink 2019-03-09 12:29:31 +01:00
Chris Lee
bff1a337f3 Revert "do not draw text with cairo directly on xlib pixmap (workaround for intel graphics bug, see emacs implementation) (issue #731, issue #732)"
This reverts commit e1211a929f.
2019-03-09 12:23:41 +01:00
Chris Lee
2f372364f0 disable glib slice allocator 2019-03-04 03:42:53 +01:00
Chris Lee
a83e057414 update changelog 2019-03-03 23:16:33 +01:00
Chris Lee
7f070b4f45 Battery percentage without % sign (#730) 2019-03-03 23:13:40 +01:00
Chris Lee
a859727ff3 more detailed logging for thumbnails 2019-03-03 22:48:47 +01:00
Chris Lee
6c36f79aae enable shared memory method of getting window screenshot 2019-03-03 01:46:59 +01:00
Chris Lee
d682756012 safety measures in thumbnail code 2019-03-03 01:40:12 +01:00
Chris Lee
b6c19da36c update authors and changelog 2019-02-24 23:13:17 +01:00
Chris Lee
372b51a4fa use named constants in struts 2019-02-24 23:09:55 +01:00
Chris
86dcaa7a83 Merge branch 'master' into 'master'
Allow pivoting STRUTs for panels in the middle of virtual screens on some WMs

See merge request o9000/tint2!31
2019-02-24 21:58:35 +00:00
Chris Billington
2b0f6a9869 Allow pivoting STRUTs for panels in the middle of virtual screens on some WMs 2019-02-24 21:58:35 +00:00
Chris Lee
4dafea185f thumbnails: do not crash if window size is 0x0 2019-02-23 22:49:58 +01:00
Chris Lee
77890d463a blink battery between two colors (issue #723) 2019-02-23 20:06:47 +01:00
Chris Lee
e1211a929f do not draw text with cairo directly on xlib pixmap (workaround for intel graphics bug, see emacs implementation) 2019-02-23 20:06:06 +01:00
Chris Lee
00f0bbd354 blink battery when low (issue #723) 2019-02-20 23:38:17 +01:00
Chris Lee
15d2570a3e Silence warnings 2018-12-31 18:23:41 +01:00
Chris Lee
c76f056746 Fix markup drawing when font shadow enabled (fixes issue #709) 2018-12-31 18:22:50 +01:00
Chris Lee
cacd4b8dad Fix: Bug: Clock Only Updates Every Minute With Format %s (issue #724) 2018-12-27 08:01:11 +01:00
Chris Lee
b539c0a1c0 fix crash if bad config path given #719 2018-09-25 19:55:55 +00:00
Chris Lee
970c597796 #716 fix executor spacing 2018-09-15 05:46:14 +00:00
57 changed files with 4228 additions and 3514 deletions

34
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,34 @@
stages:
- build
- test
- release
variables:
DEBIAN_FRONTEND: 'noninteractive'
job-build:
stage: build
image: ubuntu:rolling
script:
- sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list
- apt-get update
- apt-get build-dep -y tint2
- apt-get install -y libgtk-3-dev git
- git clean -ffdx
- mkdir build
- cd build
- cmake ..
- make -j
job-release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG =~ /^v.*/
script:
- echo 'running release_job'
release:
name: 'Release $CI_COMMIT_TAG'
description: 'Release $CI_COMMIT_TAG / $CI_COMMIT_SHA'
tag_name: '$CI_COMMIT_TAG'
ref: '$CI_COMMIT_SHA'

View File

@@ -34,6 +34,7 @@ Contributors:
aaaz (https://gitlab.com/aaaz) : clock fixes aaaz (https://gitlab.com/aaaz) : clock fixes
heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color
Fabian Carlström : taskbar sort order by app name Fabian Carlström : taskbar sort order by app name
Chris Billington (https://gitlab.com/chrisjbillington) : panel struts pivoting
Translations: Translations:
Bosnian: Bosnian:

View File

@@ -286,6 +286,9 @@ add_dependencies( tint2 version )
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=${CSTD} ${ASAN_C_FLAGS} ${TRACING_C_FLAGS}" ) set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=${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}" )
add_executable(tint2-send src/tint2-send/tint2-send.c)
target_link_libraries(tint2-send ${X11_LIBRARIES})
install( TARGETS tint2 DESTINATION bin ) install( TARGETS tint2 DESTINATION bin )
install( FILES tint2.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps ) install( FILES tint2.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps )
install( FILES tint2.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications ) install( FILES tint2.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )

View File

@@ -1,3 +1,32 @@
2021-12-04 17.0.2
- Fixes:
- On dual monitor, when minimizing Chrome window it minimizes on the wrong monitor panel (issue #818)
2021-05-29 17.0.1
- Fixes:
- Crash on panel cleanup in single-monitor execp (issue #801)
2021-04-18 17.0
- Fixes:
- Crash when a window icon is large (issue #786) (santouits)
- Minute clock doesn't update (issue #786)
- Scrollbars in tint2conf (issue #796)
- Preserve item order when skipping executors (issue #799)
- Image memory leak (issues #704, #721) (Adam M. Trofa)
- Incorrect timeout microsecond computation leading to high CPU usage (issue #800)
- Enhancements:
- Port tint2conf to gtk3 (issue #380)
- execp_monitor config (issue #799)
- Improved executor examples (Nikita Zlobin)
2019-07-14 16.7
- Fixes:
- Fix spacing around icons in executor without text in vertical panels (issue #716)
- Fix Bug: Clock Only Updates Every Minute With Format %s (issue #724)
- Fix markup drawing when font shadow enabled (issue #709)
- Struts pivoting: workaround for panel positioning between monitors in mutter (Chris Billington)
- Enhancements:
- Blink battery when discharging and low (issue #723)
- Add support for battery percentage without % sign (issue #730)
- Expand leading ~ in icon paths
2018-08-05 16.6.1 2018-08-05 16.6.1
- Fix packaging regression for debian (issue #715) - Fix packaging regression for debian (issue #715)
@@ -1019,3 +1048,5 @@ released tint-0.2
. .
. .
. .
.
.

View File

@@ -1,5 +1,5 @@
# Latest stable release: 16.6.1 # Latest stable release: 17.0.2
Changes: https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog Changes: https://gitlab.com/o9000/tint2/blob/17.0.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 16.6.1 git checkout 17.0.2
mkdir build mkdir build
cd build cd build
cmake .. cmake ..
@@ -97,3 +97,4 @@ tint2 is a simple panel/taskbar made for modern X window managers. It was specif
## More ## More
* [Tint2 wiki](https://gitlab.com/o9000/tint2/wikis/Home) * [Tint2 wiki](https://gitlab.com/o9000/tint2/wikis/Home)
Home)

View File

@@ -273,7 +273,7 @@ Try to respect as much as possible the order of the options as given below.</p><
<li><p><code>border_content_tint_weight = integer</code> : Mixes the border color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). <em>(since 16.0)</em></p></li> <li><p><code>border_content_tint_weight = integer</code> : Mixes the border color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). <em>(since 16.0)</em></p></li>
<li><p><code>background_content_tint_weight = integer</code> : Mixes the background color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). <em>(since 16.0)</em></p></li> <li><p><code>background_content_tint_weight = integer</code> : Mixes the background color with the content color (for tasks, this is the average color of the window icon). Values must be between 0 (no mixing) and 100 (fully replaces the color). <em>(since 16.0)</em></p></li>
</ul> </ul>
<p>You can define as many backgrounds as you want. For example, the following config defines two backgrounds:</p><pre class="highlight plaintext"><code>rounded = 1 <p>You can define as many backgrounds as you want. For example, the following config defines two backgrounds:</p><div class="highlight"><pre class="highlight plaintext"><code>rounded = 1
border_width = 0 border_width = 0
background_color = #282828 100 background_color = #282828 100
border_color = #000000 0 border_color = #000000 0
@@ -282,16 +282,14 @@ rounded = 1
border_width = 0 border_width = 0
background_color = #f6b655 90 background_color = #f6b655 90
border_color = #cccccc 40 border_color = #cccccc 40
</code></pre> </code></pre></div><p>tint2 automatically identifies each background with a number starting from 1 (1, 2, ...).
<p>tint2 automatically identifies each background with a number starting from 1 (1, 2, ...). Afterwards, you can apply a background to objects (panel, taskbar, task, clock, systray) using the background id, for example:</p><div class="highlight"><pre class="highlight plaintext"><code>panel_background_id = 1
Afterwards, you can apply a background to objects (panel, taskbar, task, clock, systray) using the background id, for example:</p><pre class="highlight plaintext"><code>panel_background_id = 1
taskbar_background_id = 0 taskbar_background_id = 0
task_background_id = 0 task_background_id = 0
task_active_background_id = 2 task_active_background_id = 2
systray_background_id = 0 systray_background_id = 0
clock_background_id = 0 clock_background_id = 0
</code></pre> </code></pre></div><p>Identifier 0 refers to a special background which is fully transparent, identifier 1 applies the first background defined in the config file etc.</p><h3 id="gradients">Gradients<a name="gradients" href="#gradients" class="md2man-permalink" title="permalink"></a></h3><p>(Available since 0.13.0)</p><p>Backgrounds also allow specifying gradient layers
<p>Identifier 0 refers to a special background which is fully transparent, identifier 1 applies the first background defined in the config file etc.</p><h3 id="gradients">Gradients<a name="gradients" href="#gradients" class="md2man-permalink" title="permalink"></a></h3><p>(Available since 0.13.0)</p><p>Backgrounds also allow specifying gradient layers
that are drawn on top of the solid color background.</p><p>First the user must define one or more gradients in the config file, that are drawn on top of the solid color background.</p><p>First the user must define one or more gradients in the config file,
each starting with <code>gradient = TYPE</code>. These must be added before backgrounds.</p><p>Then gradients can be added by index to backgrounds, each starting with <code>gradient = TYPE</code>. These must be added before backgrounds.</p><p>Then gradients can be added by index to backgrounds,
using the <code>gradient_id = INDEX</code>, <code>gradient_id_hover = INDEX</code> and using the <code>gradient_id = INDEX</code>, <code>gradient_id_hover = INDEX</code> and
@@ -300,21 +298,17 @@ the gradient index, starting from 1.</p><h4 id="gradient-types">Gradient types<a
* vertical gradients: top-to-bottom; * vertical gradients: top-to-bottom;
* horizontal gradients: left-to-right; * horizontal gradients: left-to-right;
* radial gradients: center-to-corners.</p><p>The user must specify the start and end colors, and can optionally add extra color stops in between * radial gradients: center-to-corners.</p><p>The user must specify the start and end colors, and can optionally add extra color stops in between
using the <code>color_stop</code> option, as explained below.</p><h5 id="vertical-gradient-with-color-varying-from-the-top-edge-to-the-bottom-edge-two-colors">Vertical gradient, with color varying from the top edge to the bottom edge, two colors<a name="vertical-gradient-with-color-varying-from-the-top-edge-to-the-bottom-edge-two-colors" href="#vertical-gradient-with-color-varying-from-the-top-edge-to-the-bottom-edge-two-colors" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>gradient = vertical using the <code>color_stop</code> option, as explained below.</p><h5 id="vertical-gradient-with-color-varying-from-the-top-edge-to-the-bottom-edge-two-colors">Vertical gradient, with color varying from the top edge to the bottom edge, two colors<a name="vertical-gradient-with-color-varying-from-the-top-edge-to-the-bottom-edge-two-colors" href="#vertical-gradient-with-color-varying-from-the-top-edge-to-the-bottom-edge-two-colors" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>gradient = vertical
start_color = #rrggbb opacity start_color = #rrggbb opacity
end_color = #rrggbb opacity end_color = #rrggbb opacity
</code></pre> </code></pre></div><h5 id="horizontal-gradient-with-color-varying-from-the-left-edge-to-the-right-edge-two-colors">Horizontal gradient, with color varying from the left edge to the right edge, two colors<a name="horizontal-gradient-with-color-varying-from-the-left-edge-to-the-right-edge-two-colors" href="#horizontal-gradient-with-color-varying-from-the-left-edge-to-the-right-edge-two-colors" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>gradient = horizontal
<h5 id="horizontal-gradient-with-color-varying-from-the-left-edge-to-the-right-edge-two-colors">Horizontal gradient, with color varying from the left edge to the right edge, two colors<a name="horizontal-gradient-with-color-varying-from-the-left-edge-to-the-right-edge-two-colors" href="#horizontal-gradient-with-color-varying-from-the-left-edge-to-the-right-edge-two-colors" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>gradient = horizontal
start_color = #rrggbb opacity start_color = #rrggbb opacity
end_color = #rrggbb opacity end_color = #rrggbb opacity
</code></pre> </code></pre></div><h5 id="radial-gradient-with-color-varying-from-the-center-to-the-corner-two-colors">Radial gradient, with color varying from the center to the corner, two colors:<a name="radial-gradient-with-color-varying-from-the-center-to-the-corner-two-colors" href="#radial-gradient-with-color-varying-from-the-center-to-the-corner-two-colors" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>gradient = radial
<h5 id="radial-gradient-with-color-varying-from-the-center-to-the-corner-two-colors">Radial gradient, with color varying from the center to the corner, two colors:<a name="radial-gradient-with-color-varying-from-the-center-to-the-corner-two-colors" href="#radial-gradient-with-color-varying-from-the-center-to-the-corner-two-colors" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>gradient = radial
start_color = #rrggbb opacity start_color = #rrggbb opacity
end_color = #rrggbb opacity end_color = #rrggbb opacity
</code></pre> </code></pre></div><h5 id="adding-extra-color-stops-0-and-100-remain-fixed-more-colors-at-x-between-the-start-and-end-control-points">Adding extra color stops (0% and 100% remain fixed, more colors at x% between the start and end control points)<a name="adding-extra-color-stops-0-and-100-remain-fixed-more-colors-at-x-between-the-start-and-end-control-points" href="#adding-extra-color-stops-0-and-100-remain-fixed-more-colors-at-x-between-the-start-and-end-control-points" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>color_stop = percentage #rrggbb opacity
<h5 id="adding-extra-color-stops-0-and-100-remain-fixed-more-colors-at-x-between-the-start-and-end-control-points">Adding extra color stops (0% and 100% remain fixed, more colors at x% between the start and end control points)<a name="adding-extra-color-stops-0-and-100-remain-fixed-more-colors-at-x-between-the-start-and-end-control-points" href="#adding-extra-color-stops-0-and-100-remain-fixed-more-colors-at-x-between-the-start-and-end-control-points" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>color_stop = percentage #rrggbb opacity </code></pre></div><h4 id="gradient-examples">Gradient examples<a name="gradient-examples" href="#gradient-examples" class="md2man-permalink" title="permalink"></a></h4><div class="highlight"><pre class="highlight plaintext"><code># Gradient 1: thin film effect
</code></pre>
<h4 id="gradient-examples">Gradient examples<a name="gradient-examples" href="#gradient-examples" class="md2man-permalink" title="permalink"></a></h4><pre class="highlight plaintext"><code># Gradient 1: thin film effect
gradient = horizontal gradient = horizontal
start_color = #111122 30 start_color = #111122 30
end_color = #112211 30 end_color = #112211 30
@@ -350,8 +344,7 @@ gradient_id_hover = 4
gradient_id_pressed = 2 gradient_id_pressed = 2
[...] [...]
</code></pre> </code></pre></div><h3 id="panel">Panel<a name="panel" href="#panel" class="md2man-permalink" title="permalink"></a></h3>
<h3 id="panel">Panel<a name="panel" href="#panel" class="md2man-permalink" title="permalink"></a></h3>
<ul> <ul>
<li><p><code>panel_items = LTSBC</code> defines the items tint2 will show and the order of those items. Each letter refers to an item, defined as:</p> <li><p><code>panel_items = LTSBC</code> defines the items tint2 will show and the order of those items. Each letter refers to an item, defined as:</p>
<ul> <ul>
@@ -389,10 +382,9 @@ Example:</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_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> <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: <div class="highlight"><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
</code></pre> </code></pre></div>
<ul> <ul>
<li><p><code>panel_shrink = boolean (0 or 1)</code> : If set to 1, the panel will shrink to a compact size dynamically. <em>(since 0.13)</em></p></li> <li><p><code>panel_shrink = boolean (0 or 1)</code> : If set to 1, the panel will shrink to a compact size dynamically. <em>(since 0.13)</em></p></li>
<li><p><code>panel_margin = horizontal_margin vertical_margin</code> : The margins define the distance between the panel and the horizontal/vertical monitor edge. Use <code>0</code> to obtain a panel with the same size as the edge of the monitor (no margin).</p></li> <li><p><code>panel_margin = horizontal_margin vertical_margin</code> : The margins define the distance between the panel and the horizontal/vertical monitor edge. Use <code>0</code> to obtain a panel with the same size as the edge of the monitor (no margin).</p></li>
@@ -407,8 +399,9 @@ panel_size = 94% 30
<li><p><code>panel_background_id = integer</code> : Which background to use for the panel.</p></li> <li><p><code>panel_background_id = integer</code> : Which background to use for the panel.</p></li>
<li><p><code>wm_menu = boolean (0 or 1)</code> : Defines if tint2 forwards unhandled mouse events to your window manager. Useful for window managers such as openbox, which display the start menu if you right click on the desktop.</p></li> <li><p><code>wm_menu = boolean (0 or 1)</code> : Defines if tint2 forwards unhandled mouse events to your window manager. Useful for window managers such as openbox, which display the start menu if you right click on the desktop.</p></li>
<li><p><code>panel_dock = boolean (0 or 1)</code> : Defines if tint2 is placed into the window manager&#39;s dock. For the openbox window manager it is advised to also use a modifier for the moveButton option, otherwise the mouse click is not forwarded to tint2 (in ~/.config/openbox/rc.xml).</p></li> <li><p><code>panel_dock = boolean (0 or 1)</code> : Defines if tint2 is placed into the window manager&#39;s dock. For the openbox window manager it is advised to also use a modifier for the moveButton option, otherwise the mouse click is not forwarded to tint2 (in ~/.config/openbox/rc.xml).</p></li>
<li><p><code>panel_pivot_struts = boolean (0 or 1)</code> : Defines if tint2 lies to the window manager about its orientation (horizontal vs vertical) when requesting reserved space with STRUTs (see <code>strut_policy</code> below). On some window managers, this allows placing a panel in the middle of the virtual screen, e.g. on the bottom edge of the top monitor in a vertical dual-monitor setup. </p></li>
<li><p><code>panel_layer = bottom/normal/top</code> : Places tint2 into the bottom/normal/top layer. This is helpful for specifying if the panel can be covered by other windows or not. The default is the bottom layer, but with real transparency normal or top layer may be a nice alternative.</p></li> <li><p><code>panel_layer = bottom/normal/top</code> : Places tint2 into the bottom/normal/top layer. This is helpful for specifying if the panel can be covered by other windows or not. The default is the bottom layer, but with real transparency normal or top layer may be a nice alternative.</p></li>
<li><p><code>strut_policy = follow_size/minimum/none</code> : STRUTs are used by the window manager to decide the size of maximized windows. Note: on multi-monitor (Xinerama) setups, the panel must be placed at the edge (not in the middle) of the virtual screen for this to work correctly.</p> <li><p><code>strut_policy = follow_size/minimum/none</code> : STRUTs are used by the window manager to decide the size of maximized windows. Note: on multi-monitor (Xinerama) setups, the panel generally must be placed at the edge (not in the middle) of the virtual screen for this to work correctly (though on some window managers, setting <code>panel_pivot_struts</code> may work around this limitation). </p>
<ul> <ul>
<li><code>follow_size</code> means that the maximized windows always resize to have a common edge with tint2.</li> <li><code>follow_size</code> means that the maximized windows always resize to have a common edge with tint2.</li>
<li><code>minimum</code> means that the maximized windows always expand to have a common edge with the hidden panel. This is useful if the <code>autohide</code> option is enabled.</li> <li><code>minimum</code> means that the maximized windows always expand to have a common edge with the hidden panel. This is useful if the <code>autohide</code> option is enabled.</li>
@@ -585,6 +578,7 @@ panel_size = 94% 30
<li>%h: Hours left until completely charged/discharged (estimated).</li> <li>%h: Hours left until completely charged/discharged (estimated).</li>
<li>%t: Time left. Shows &quot;hrs:mins&quot; when charging/discharging, or &quot;Ful\&quot; when full.</li> <li>%t: Time left. Shows &quot;hrs:mins&quot; when charging/discharging, or &quot;Ful\&quot; when full.</li>
<li>%p: Percentage. Includes the % sign.</li> <li>%p: Percentage. Includes the % sign.</li>
<li>%P: Percentage. Without the % sign.</li>
</ul></li> </ul></li>
<li><p><code>bat2_format = FORMAT_STRING</code> : Format for battery line 2. Default: %t. <em>(since 1.0)</em></p></li> <li><p><code>bat2_format = FORMAT_STRING</code> : Format for battery line 2. Default: %t. <em>(since 1.0)</em></p></li>
<li><p><code>battery_padding = horizontal_padding vertical_padding</code></p></li> <li><p><code>battery_padding = horizontal_padding vertical_padding</code></p></li>
@@ -615,21 +609,20 @@ panel_size = 94% 30
<li><p><code>execp_background_id = integer</code> : Which background to use. <em>(since 0.12.4)</em></p></li> <li><p><code>execp_background_id = integer</code> : Which background to use. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_centered = boolean (0 or 1)</code> : Whether to center the text. <em>(since 0.12.4)</em></p></li> <li><p><code>execp_centered = boolean (0 or 1)</code> : Whether to center the text. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_padding = horizontal_padding vertical_padding spacing_between_icon_and_text</code> <em>(since 0.12.4)</em></p></li> <li><p><code>execp_padding = horizontal_padding vertical_padding spacing_between_icon_and_text</code> <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_monitor = integer (1, 2, ...), primary or all</code> : On which monitor to draw the executor. The first monitor is <code>1</code>. <em>(since 17.0)</em></p></li>
<li><p><code>execp_lclick_command = text</code> : Command to execute on left click. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li> <li><p><code>execp_lclick_command = text</code> : Command to execute on left click. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_mclick_command = text</code> : Command to execute on right click. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li> <li><p><code>execp_mclick_command = text</code> : Command to execute on right click. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_rclick_command = text</code> : Command to execute on middle click. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li> <li><p><code>execp_rclick_command = text</code> : Command to execute on middle click. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_uwheel_command = text</code> : Command to execute on wheel scroll up. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li> <li><p><code>execp_uwheel_command = text</code> : Command to execute on wheel scroll up. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_dwheel_command = text</code> : Command to execute on wheel scroll down. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li> <li><p><code>execp_dwheel_command = text</code> : Command to execute on wheel scroll down. If not defined, <code>execp_command</code> is executed immediately, unless it is currently running. <em>(since 0.12.4)</em></p></li>
</ul> </ul>
<h4 id="executor-samples">Executor samples<a name="executor-samples" href="#executor-samples" class="md2man-permalink" title="permalink"></a></h4><h5 id="print-the-hostname">Print the hostname<a name="print-the-hostname" href="#print-the-hostname" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new <h4 id="executor-samples">Executor samples<a name="executor-samples" href="#executor-samples" class="md2man-permalink" title="permalink"></a></h4><h5 id="print-the-hostname">Print the hostname<a name="print-the-hostname" href="#print-the-hostname" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>execp = new
execp_command = hostname execp_command = hostname
execp_interval = 0 execp_interval = 0
</code></pre> </code></pre></div><h5 id="print-disk-usage-for-the-root-partition-every-10-seconds">Print disk usage for the root partition every 10 seconds<a name="print-disk-usage-for-the-root-partition-every-10-seconds" href="#print-disk-usage-for-the-root-partition-every-10-seconds" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>execp = new
<h5 id="print-disk-usage-for-the-root-partition-every-10-seconds">Print disk usage for the root partition every 10 seconds<a name="print-disk-usage-for-the-root-partition-every-10-seconds" href="#print-disk-usage-for-the-root-partition-every-10-seconds" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new
execp_command = df -h | awk '/\/$/ { print $6 ": " $2 " " $5}' execp_command = df -h | awk '/\/$/ { print $6 ": " $2 " " $5}'
execp_interval = 10 execp_interval = 10
</code></pre> </code></pre></div><h5 id="button-with-icon-and-rich-text-executes-command-when-clicked">Button with icon and rich text, executes command when clicked<a name="button-with-icon-and-rich-text-executes-command-when-clicked" href="#button-with-icon-and-rich-text-executes-command-when-clicked" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>execp = new
<h5 id="button-with-icon-and-rich-text-executes-command-when-clicked">Button with icon and rich text, executes command when clicked<a name="button-with-icon-and-rich-text-executes-command-when-clicked" href="#button-with-icon-and-rich-text-executes-command-when-clicked" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new
execp_command = echo /usr/share/icons/elementary-xfce/emblems/24/emblem-colors-blue.png; echo '&lt;span foreground="#7f7"&gt;Click&lt;/span&gt; &lt;span foreground="#77f"&gt;me&lt;/span&gt; &lt;span foreground="#f77"&gt;pls&lt;/span&gt;' execp_command = echo /usr/share/icons/elementary-xfce/emblems/24/emblem-colors-blue.png; echo '&lt;span foreground="#7f7"&gt;Click&lt;/span&gt; &lt;span foreground="#77f"&gt;me&lt;/span&gt; &lt;span foreground="#f77"&gt;pls&lt;/span&gt;'
execp_has_icon = 1 execp_has_icon = 1
execp_interval = 0 execp_interval = 0
@@ -641,36 +634,30 @@ execp_padding = 2 0
execp_tooltip = I will tell you a secret... execp_tooltip = I will tell you a secret...
execp_lclick_command = zenity --info "--text=$(uname -sr)" execp_lclick_command = zenity --info "--text=$(uname -sr)"
execp_background_id = 2 execp_background_id = 2
</code></pre> </code></pre></div><h5 id="desktop-pager-with-text">Desktop pager with text<a name="desktop-pager-with-text" href="#desktop-pager-with-text" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>execp = new
<h5 id="desktop-pager-with-text">Desktop pager with text<a name="desktop-pager-with-text" href="#desktop-pager-with-text" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new
execp_command = xprop -root -spy | awk '/^_NET_CURRENT_DESKTOP/ { print "Workspace " ($3 + 1) ; fflush(); }' execp_command = xprop -root -spy | awk '/^_NET_CURRENT_DESKTOP/ { print "Workspace " ($3 + 1) ; fflush(); }'
execp_interval = 1 execp_interval = 1
execp_continuous = 1 execp_continuous = 1
</code></pre> </code></pre></div><h5 id="desktop-pager-with-icon">Desktop pager with icon<a name="desktop-pager-with-icon" href="#desktop-pager-with-icon" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>execp_command = xprop -root -spy | awk -v home="$HOME" '/^_NET_CURRENT_DESKTOP/ { print home "/.config/myPager/" ($3 + 1) ".png\n" ; fflush(); }'
<h5 id="desktop-pager-with-icon">Desktop pager with icon<a name="desktop-pager-with-icon" href="#desktop-pager-with-icon" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp_command = xprop -root -spy | awk -v home="$HOME" '/^_NET_CURRENT_DESKTOP/ { print home "/.config/myPager/" ($3 + 1) ".png\n" ; fflush(); }'
execp_interval = 1 execp_interval = 1
execp_has_icon = 1 execp_has_icon = 1
execp_cache_icon = 1 execp_cache_icon = 1
execp_continuous = 2 execp_continuous = 2
</code></pre> </code></pre></div><h5 id="round-trip-time-to-the-gateway-refreshed-every-second">Round-trip time to the gateway, refreshed every second<a name="round-trip-time-to-the-gateway-refreshed-every-second" href="#round-trip-time-to-the-gateway-refreshed-every-second" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>execp = new
<h5 id="round-trip-time-to-the-gateway-refreshed-every-second">Round-trip time to the gateway, refreshed every second<a name="round-trip-time-to-the-gateway-refreshed-every-second" href="#round-trip-time-to-the-gateway-refreshed-every-second" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new
execp_command = ping -i 1 -c 1 -W 1 -O -D -n $(ip route | grep default | grep via | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*') | awk '/no/ { print "&lt;span foreground=\"#faa\"&gt;timeout&lt;/span&gt;"; fflush(); }; /time=/ { gsub(/time=/, "", $8); printf "&lt;span foreground=\"#7af\"&gt;%3.0f %s&lt;/span&gt;\n", $8, $9; fflush(); } ' execp_command = ping -i 1 -c 1 -W 1 -O -D -n $(ip route | grep default | grep via | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*') | awk '/no/ { print "&lt;span foreground=\"#faa\"&gt;timeout&lt;/span&gt;"; fflush(); }; /time=/ { gsub(/time=/, "", $8); printf "&lt;span foreground=\"#7af\"&gt;%3.0f %s&lt;/span&gt;\n", $8, $9; fflush(); } '
execp_continuous = 0 execp_continuous = 0
execp_interval = 1 execp_interval = 1
execp_markup = 1 execp_markup = 1
</code></pre> </code></pre></div><h5 id="memory-usage">Memory usage<a name="memory-usage" href="#memory-usage" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code># Note the use of "stdbuf -oL" to force the program to flush the output line by line.
<h5 id="memory-usage">Memory usage<a name="memory-usage" href="#memory-usage" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new
execp_command = free | awk '/^-/ { printf "Mem: '$(free -h | awk '/^Mem:/ { print $2 }')' %.0f%%\n", 100*$3/($3+$4); fflush(stdout) }'
execp_interval = 5
execp_continuous = 0
</code></pre>
<h5 id="network-load">Network load<a name="network-load" href="#network-load" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code># Note the use of "stdbuf -oL" to force the program to flush the output line by line.
execp = new execp = new
execp_command = stdbuf -oL bwm-ng -o csv -t 1000 | awk -F ';' '/total/ { printf "Net: %.0f Mb/s\n", ($5*8/1.0e6) }; fflush(stdout)' execp_command = free -b -s1 | stdbuf -oL awk '/^Mem:/ { printf "Mem: %s %.0f%%\n", $2, 100 * ($2 - $7) / $2 }' | stdbuf -oL numfmt --to=iec-i --field=2 -d' '
execp_interval = 1
execp_continuous = 1
</code></pre></div><h5 id="network-load">Network load<a name="network-load" href="#network-load" class="md2man-permalink" title="permalink"></a></h5><div class="highlight"><pre class="highlight plaintext"><code>execp = new
execp_command = stdbuf -oL bwm-ng -o csv -t 1000 | stdbuf -oL awk -F ';' '/total/ { printf "Net: %.0f Mb/s\n", ($5*8/1.0e6) }'
execp_continuous = 1 execp_continuous = 1
execp_interval = 1 execp_interval = 1
</code></pre> </code></pre></div><h3 id="button">Button<a name="button" href="#button" class="md2man-permalink" title="permalink"></a></h3>
<h3 id="button">Button<a name="button" href="#button" class="md2man-permalink" title="permalink"></a></h3>
<ul> <ul>
<li><p><code>button = new</code> : Begins the configuration of a new button. Multiple such plugins are supported; just use multiple <code>P</code>s in <code>panel_items</code>. <em>(since 0.14)</em></p></li> <li><p><code>button = new</code> : Begins the configuration of a new button. Multiple such plugins are supported; just use multiple <code>P</code>s in <code>panel_items</code>. <em>(since 0.14)</em></p></li>
<li><p><code>button_icon = text</code> : Name or path of icon (or empty). <em>(since 0.14)</em></p></li> <li><p><code>button_icon = text</code> : Name or path of icon (or empty). <em>(since 0.14)</em></p></li>
@@ -702,6 +689,7 @@ It is based on ttm, originally written by Pål Staurland <a href="mailto:staura@
It was adopted from the tint2 docs.</p><h2 id="see-also">SEE ALSO<a name="see-also" href="#see-also" class="md2man-permalink" title="permalink"></a></h2><p>The main website <a href="https://gitlab.com/o9000/tint2">https://gitlab.com/o9000/tint2</a> It was adopted from the tint2 docs.</p><h2 id="see-also">SEE ALSO<a name="see-also" href="#see-also" class="md2man-permalink" title="permalink"></a></h2><p>The main website <a href="https://gitlab.com/o9000/tint2">https://gitlab.com/o9000/tint2</a>
and the wiki page at <a href="https://gitlab.com/o9000/tint2/wikis/home">https://gitlab.com/o9000/tint2/wikis/home</a>.</p><p>This documentation is also provided in HTML and Markdown format in the system&#39;s default location and the wiki page at <a href="https://gitlab.com/o9000/tint2/wikis/home">https://gitlab.com/o9000/tint2/wikis/home</a>.</p><p>This documentation is also provided in HTML and Markdown format in the system&#39;s default location
for documentation files, usually <code>/usr/share/doc/tint2</code> or <code>/usr/local/share/doc/tint2</code>. for documentation files, usually <code>/usr/share/doc/tint2</code> or <code>/usr/local/share/doc/tint2</code>.
.
.</p> .</p>
</body> </body>
</html> </html>

View File

@@ -199,19 +199,17 @@ pre {
</style> </style>
</head> </head>
<body> <body>
<h1 id="latest-stable-release-16-6-1"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.6.1</span><a name="latest-stable-release-16-6-1" href="#latest-stable-release-16-6-1" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog</a></p><p>Documentation: <a href="manual.html">manual.html</a></p><p>Compile it with (after you install the <a href="https://gitlab.com/o9000/tint2/wikis/Install#dependencies">dependencies</a>):</p><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git <h1 id="latest-stable-release-17-0-2"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">17.0.2</span><a name="latest-stable-release-17-0-2" href="#latest-stable-release-17-0-2" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/17.0.2/ChangeLog">https://gitlab.com/o9000/tint2/blob/17.0.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><div class="highlight"><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git
cd tint2 cd tint2
git checkout 16.6.1 git checkout 17.0.2
mkdir build mkdir build
cd build cd build
cmake .. cmake ..
make -j4 make -j4
</code></pre> </code></pre></div><p>To install, run (as root):</p><div class="highlight"><pre class="highlight plaintext"><code>make install
<p>To install, run (as root):</p><pre class="highlight plaintext"><code>make install
update-icon-caches /usr/local/share/icons/hicolor update-icon-caches /usr/local/share/icons/hicolor
update-mime-database /usr/local/share/mime update-mime-database /usr/local/share/mime
</code></pre> </code></pre></div><p>And then you can run the panel <code>tint2</code> and the configuration program <code>tint2conf</code>.</p><p>Please report any problems to <a href="https://gitlab.com/o9000/tint2/issues">https://gitlab.com/o9000/tint2/issues</a>. Your feedback is much appreciated.</p><p>P.S. GitLab is now the official location of the tint2 project, migrated from Google Code, which is shutting down. In case you are wondering why not GitHub, BitBucket etc., we chose GitLab because it is open source, it is mature and works well, looks cool and has a very nice team.</p><h1 id="what-is-tint2">What is tint2?<a name="what-is-tint2" href="#what-is-tint2" class="md2man-permalink" title="permalink"></a></h1><p>tint2 is a simple panel/taskbar made for modern X window managers. It was specifically made for Openbox but it should also work with other window managers (GNOME, KDE, XFCE etc.). It is based on ttm <a href="https://code.google.com/p/ttm/">https://code.google.com/p/ttm/</a>.</p><h1 id="features">Features<a name="features" href="#features" class="md2man-permalink" title="permalink"></a></h1>
<p>And then you can run the panel <code>tint2</code> and the configuration program <code>tint2conf</code>.</p><p>Please report any problems to <a href="https://gitlab.com/o9000/tint2/issues">https://gitlab.com/o9000/tint2/issues</a>. Your feedback is much appreciated.</p><p>P.S. GitLab is now the official location of the tint2 project, migrated from Google Code, which is shutting down. In case you are wondering why not GitHub, BitBucket etc., we chose GitLab because it is open source, it is mature and works well, looks cool and has a very nice team.</p><h1 id="what-is-tint2">What is tint2?<a name="what-is-tint2" href="#what-is-tint2" class="md2man-permalink" title="permalink"></a></h1><p>tint2 is a simple panel/taskbar made for modern X window managers. It was specifically made for Openbox but it should also work with other window managers (GNOME, KDE, XFCE etc.). It is based on ttm <a href="https://code.google.com/p/ttm/">https://code.google.com/p/ttm/</a>.</p><h1 id="features">Features<a name="features" href="#features" class="md2man-permalink" title="permalink"></a></h1>
<ul> <ul>
<li>Panel with taskbar, system tray, clock and launcher icons;</li> <li>Panel with taskbar, system tray, clock and launcher icons;</li>
<li>Easy to customize: color/transparency on fonts, icons, borders and backgrounds;</li> <li>Easy to customize: color/transparency on fonts, icons, borders and backgrounds;</li>
@@ -269,7 +267,8 @@ update-mime-database /usr/local/share/mime
</ul> </ul>
<h2 id="more">More<a name="more" href="#more" class="md2man-permalink" title="permalink"></a></h2> <h2 id="more">More<a name="more" href="#more" class="md2man-permalink" title="permalink"></a></h2>
<ul> <ul>
<li><a href="https://gitlab.com/o9000/tint2/wikis/Home">Tint2 wiki</a></li> <li><a href="https://gitlab.com/o9000/tint2/wikis/Home">Tint2 wiki</a>
Home)</li>
</ul> </ul>
</body> </body>
</html> </html>

View File

@@ -1,4 +1,4 @@
.TH TINT2 1 "2018\-08\-05" 16.6.1 .TH TINT2 1 "2021\-12\-04" 17.0.2
.SH NAME .SH NAME
.PP .PP
tint2 \- lightweight panel/taskbar tint2 \- lightweight panel/taskbar
@@ -379,9 +379,11 @@ panel_size = 94% 30
.IP \(bu 2 .IP \(bu 2
\fB\fCpanel_dock = boolean (0 or 1)\fR : Defines if tint2 is placed into the window manager's dock. For the openbox window manager it is advised to also use a modifier for the moveButton option, otherwise the mouse click is not forwarded to tint2 (in ~/.config/openbox/rc.xml). \fB\fCpanel_dock = boolean (0 or 1)\fR : Defines if tint2 is placed into the window manager's dock. For the openbox window manager it is advised to also use a modifier for the moveButton option, otherwise the mouse click is not forwarded to tint2 (in ~/.config/openbox/rc.xml).
.IP \(bu 2 .IP \(bu 2
\fB\fCpanel_pivot_struts = boolean (0 or 1)\fR : Defines if tint2 lies to the window manager about its orientation (horizontal vs vertical) when requesting reserved space with STRUTs (see \fB\fCstrut_policy\fR below). On some window managers, this allows placing a panel in the middle of the virtual screen, e.g. on the bottom edge of the top monitor in a vertical dual\-monitor setup.
.IP \(bu 2
\fB\fCpanel_layer = bottom/normal/top\fR : Places tint2 into the bottom/normal/top layer. This is helpful for specifying if the panel can be covered by other windows or not. The default is the bottom layer, but with real transparency normal or top layer may be a nice alternative. \fB\fCpanel_layer = bottom/normal/top\fR : Places tint2 into the bottom/normal/top layer. This is helpful for specifying if the panel can be covered by other windows or not. The default is the bottom layer, but with real transparency normal or top layer may be a nice alternative.
.IP \(bu 2 .IP \(bu 2
\fB\fCstrut_policy = follow_size/minimum/none\fR : STRUTs are used by the window manager to decide the size of maximized windows. Note: on multi\-monitor (Xinerama) setups, the panel must be placed at the edge (not in the middle) of the virtual screen for this to work correctly. \fB\fCstrut_policy = follow_size/minimum/none\fR : STRUTs are used by the window manager to decide the size of maximized windows. Note: on multi\-monitor (Xinerama) setups, the panel generally must be placed at the edge (not in the middle) of the virtual screen for this to work correctly (though on some window managers, setting \fB\fCpanel_pivot_struts\fR may work around this limitation).
.RS .RS
.IP \(bu 2 .IP \(bu 2
\fB\fCfollow_size\fR means that the maximized windows always resize to have a common edge with tint2. \fB\fCfollow_size\fR means that the maximized windows always resize to have a common edge with tint2.
@@ -687,6 +689,8 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
%t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\[rs]" when full. %t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\[rs]" when full.
.IP \(bu 2 .IP \(bu 2
%p: Percentage. Includes the % sign. %p: Percentage. Includes the % sign.
.IP \(bu 2
%P: Percentage. Without the % sign.
.RE .RE
.IP \(bu 2 .IP \(bu 2
\fB\fCbat2_format = FORMAT_STRING\fR : Format for battery line 2. Default: %t. \fI(since 1.0)\fP \fB\fCbat2_format = FORMAT_STRING\fR : Format for battery line 2. Default: %t. \fI(since 1.0)\fP
@@ -744,6 +748,8 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
.IP \(bu 2 .IP \(bu 2
\fB\fCexecp_padding = horizontal_padding vertical_padding spacing_between_icon_and_text\fR \fI(since 0.12.4)\fP \fB\fCexecp_padding = horizontal_padding vertical_padding spacing_between_icon_and_text\fR \fI(since 0.12.4)\fP
.IP \(bu 2 .IP \(bu 2
\fB\fCexecp_monitor = integer (1, 2, ...), primary or all\fR : On which monitor to draw the executor. The first monitor is \fB\fC1\fR\&. \fI(since 17.0)\fP
.IP \(bu 2
\fB\fCexecp_lclick_command = text\fR : Command to execute on left click. If not defined, \fB\fCexecp_command\fR is executed immediately, unless it is currently running. \fI(since 0.12.4)\fP \fB\fCexecp_lclick_command = text\fR : Command to execute on left click. If not defined, \fB\fCexecp_command\fR is executed immediately, unless it is currently running. \fI(since 0.12.4)\fP
.IP \(bu 2 .IP \(bu 2
\fB\fCexecp_mclick_command = text\fR : Command to execute on right click. If not defined, \fB\fCexecp_command\fR is executed immediately, unless it is currently running. \fI(since 0.12.4)\fP \fB\fCexecp_mclick_command = text\fR : Command to execute on right click. If not defined, \fB\fCexecp_command\fR is executed immediately, unless it is currently running. \fI(since 0.12.4)\fP
@@ -827,19 +833,19 @@ execp_markup = 1
.PP .PP
.RS .RS
.nf .nf
# Note the use of "stdbuf \-oL" to force the program to flush the output line by line.
execp = new execp = new
execp_command = free | awk '/^\-/ { printf "Mem: '$(free \-h | awk '/^Mem:/ { print $2 }')' %.0f%%\\n", 100*$3/($3+$4); fflush(stdout) }' execp_command = free \-b \-s1 | stdbuf \-oL awk '/^Mem:/ { printf "Mem: %s %.0f%%\\n", $2, 100 * ($2 \- $7) / $2 }' | stdbuf \-oL numfmt \-\-to=iec\-i \-\-field=2 \-d' '
execp_interval = 5 execp_interval = 1
execp_continuous = 0 execp_continuous = 1
.fi .fi
.RE .RE
.SS Network load .SS Network load
.PP .PP
.RS .RS
.nf .nf
# Note the use of "stdbuf \-oL" to force the program to flush the output line by line.
execp = new execp = new
execp_command = stdbuf \-oL bwm\-ng \-o csv \-t 1000 | awk \-F ';' '/total/ { printf "Net: %.0f Mb/s\\n", ($5*8/1.0e6) }; fflush(stdout)' execp_command = stdbuf \-oL bwm\-ng \-o csv \-t 1000 | stdbuf \-oL awk \-F ';' '/total/ { printf "Net: %.0f Mb/s\\n", ($5*8/1.0e6) }'
execp_continuous = 1 execp_continuous = 1
execp_interval = 1 execp_interval = 1
.fi .fi
@@ -910,3 +916,4 @@ and the wiki page at \[la]https://gitlab.com/o9000/tint2/wikis/home\[ra]\&.
This documentation is also provided in HTML and Markdown format in the system's default location This documentation is also provided in HTML and Markdown format in the system's default location
for documentation files, usually \fB\fC/usr/share/doc/tint2\fR or \fB\fC/usr/local/share/doc/tint2\fR\&. for documentation files, usually \fB\fC/usr/share/doc/tint2\fR or \fB\fC/usr/local/share/doc/tint2\fR\&.
\&. \&.
\&.

View File

@@ -372,14 +372,14 @@ execp_continuous = 1
execp_interval = 1 execp_interval = 1
execp_markup = 1 execp_markup = 1
</code></pre> </code></pre>
<h5 id="memory-usage">Memory usage<a name="memory-usage" href="#memory-usage" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new <h5 id="memory-usage">Memory usage<a name="memory-usage" href="#memory-usage" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code># Note the use of "stdbuf -oL" to force the program to flush the output line by line.
execp_command = free -s 2 | awk '/^-/ { printf "Mem: '$(free -h | awk '/^Mem:/ { print $2 }')' %.0f%\n", 100*$3/($3+$4); fflush(stdout) }' execp = new
execp_command = free -b -s1 | stdbuf -oL awk '/^Mem:/ { printf "Mem: %s %.0f%%\n", $2, 100 * ($2 - $7) / $2 }' | stdbuf -oL numfmt --to=iec-i --field=2 -d' '
execp_interval = 1 execp_interval = 1
execp_continuous = 1 execp_continuous = 1
</code></pre> </code></pre>
<h5 id="network-load">Network load<a name="network-load" href="#network-load" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code># Note the use of "stdbuf -oL" to force the program to flush the output line by line. <h5 id="network-load">Network load<a name="network-load" href="#network-load" class="md2man-permalink" title="permalink"></a></h5><pre class="highlight plaintext"><code>execp = new
execp = new execp_command = stdbuf -oL bwm-ng -o csv -t 1000 | stdbuf -oL awk -F ';' '/total/ { printf "Net: %.0f Mb/s\n", ($5*8/1.0e6) }'
execp_command = stdbuf -oL bwm-ng -o csv -t 1000 | awk -F ';' '/total/ { printf "Net: %.0f Mb/s\n", ($5*8/1.0e6) }; fflush(stdout)'
execp_continuous = 1 execp_continuous = 1
execp_interval = 1 execp_interval = 1
</code></pre> </code></pre>

View File

@@ -1,4 +1,4 @@
# TINT2 1 "2018-08-05" 16.6.1 # TINT2 1 "2021-12-04" 17.0.2
## NAME ## NAME
tint2 - lightweight panel/taskbar tint2 - lightweight panel/taskbar
@@ -306,9 +306,11 @@ panel_size = 94% 30
* `panel_dock = boolean (0 or 1)` : Defines if tint2 is placed into the window manager's dock. For the openbox window manager it is advised to also use a modifier for the moveButton option, otherwise the mouse click is not forwarded to tint2 (in ~/.config/openbox/rc.xml). * `panel_dock = boolean (0 or 1)` : Defines if tint2 is placed into the window manager's dock. For the openbox window manager it is advised to also use a modifier for the moveButton option, otherwise the mouse click is not forwarded to tint2 (in ~/.config/openbox/rc.xml).
* `panel_pivot_struts = boolean (0 or 1)` : Defines if tint2 lies to the window manager about its orientation (horizontal vs vertical) when requesting reserved space with STRUTs (see `strut_policy` below). On some window managers, this allows placing a panel in the middle of the virtual screen, e.g. on the bottom edge of the top monitor in a vertical dual-monitor setup.
* `panel_layer = bottom/normal/top` : Places tint2 into the bottom/normal/top layer. This is helpful for specifying if the panel can be covered by other windows or not. The default is the bottom layer, but with real transparency normal or top layer may be a nice alternative. * `panel_layer = bottom/normal/top` : Places tint2 into the bottom/normal/top layer. This is helpful for specifying if the panel can be covered by other windows or not. The default is the bottom layer, but with real transparency normal or top layer may be a nice alternative.
* `strut_policy = follow_size/minimum/none` : STRUTs are used by the window manager to decide the size of maximized windows. Note: on multi-monitor (Xinerama) setups, the panel must be placed at the edge (not in the middle) of the virtual screen for this to work correctly. * `strut_policy = follow_size/minimum/none` : STRUTs are used by the window manager to decide the size of maximized windows. Note: on multi-monitor (Xinerama) setups, the panel generally must be placed at the edge (not in the middle) of the virtual screen for this to work correctly (though on some window managers, setting `panel_pivot_struts` may work around this limitation).
* `follow_size` means that the maximized windows always resize to have a common edge with tint2. * `follow_size` means that the maximized windows always resize to have a common edge with tint2.
* `minimum` means that the maximized windows always expand to have a common edge with the hidden panel. This is useful if the `autohide` option is enabled. * `minimum` means that the maximized windows always expand to have a common edge with the hidden panel. This is useful if the `autohide` option is enabled.
* `none` means that the maximized windows use the full screen size. * `none` means that the maximized windows use the full screen size.
@@ -563,6 +565,7 @@ The action semantics:
* %h: Hours left until completely charged/discharged (estimated). * %h: Hours left until completely charged/discharged (estimated).
* %t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\" when full. * %t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\" when full.
* %p: Percentage. Includes the % sign. * %p: Percentage. Includes the % sign.
* %P: Percentage. Without the % sign.
* `bat2_format = FORMAT_STRING` : Format for battery line 2. Default: %t. *(since 1.0)* * `bat2_format = FORMAT_STRING` : Format for battery line 2. Default: %t. *(since 1.0)*
@@ -618,6 +621,8 @@ The action semantics:
* `execp_padding = horizontal_padding vertical_padding spacing_between_icon_and_text` *(since 0.12.4)* * `execp_padding = horizontal_padding vertical_padding spacing_between_icon_and_text` *(since 0.12.4)*
* `execp_monitor = integer (1, 2, ...), primary or all` : On which monitor to draw the executor. The first monitor is `1`. *(since 17.0)*
* `execp_lclick_command = text` : Command to execute on left click. If not defined, `execp_command` is executed immediately, unless it is currently running. *(since 0.12.4)* * `execp_lclick_command = text` : Command to execute on left click. If not defined, `execp_command` is executed immediately, unless it is currently running. *(since 0.12.4)*
* `execp_mclick_command = text` : Command to execute on right click. If not defined, `execp_command` is executed immediately, unless it is currently running. *(since 0.12.4)* * `execp_mclick_command = text` : Command to execute on right click. If not defined, `execp_command` is executed immediately, unless it is currently running. *(since 0.12.4)*
* `execp_rclick_command = text` : Command to execute on middle click. If not defined, `execp_command` is executed immediately, unless it is currently running. *(since 0.12.4)* * `execp_rclick_command = text` : Command to execute on middle click. If not defined, `execp_command` is executed immediately, unless it is currently running. *(since 0.12.4)*
@@ -691,18 +696,18 @@ execp_markup = 1
##### Memory usage ##### Memory usage
``` ```
# Note the use of "stdbuf -oL" to force the program to flush the output line by line.
execp = new execp = new
execp_command = free | awk '/^-/ { printf "Mem: '$(free -h | awk '/^Mem:/ { print $2 }')' %.0f%%\n", 100*$3/($3+$4); fflush(stdout) }' execp_command = free -b -s1 | stdbuf -oL awk '/^Mem:/ { printf "Mem: %s %.0f%%\n", $2, 100 * ($2 - $7) / $2 }' | stdbuf -oL numfmt --to=iec-i --field=2 -d' '
execp_interval = 5 execp_interval = 1
execp_continuous = 0 execp_continuous = 1
``` ```
##### Network load ##### Network load
``` ```
# Note the use of "stdbuf -oL" to force the program to flush the output line by line.
execp = new execp = new
execp_command = stdbuf -oL bwm-ng -o csv -t 1000 | awk -F ';' '/total/ { printf "Net: %.0f Mb/s\n", ($5*8/1.0e6) }; fflush(stdout)' execp_command = stdbuf -oL bwm-ng -o csv -t 1000 | stdbuf -oL awk -F ';' '/total/ { printf "Net: %.0f Mb/s\n", ($5*8/1.0e6) }'
execp_continuous = 1 execp_continuous = 1
execp_interval = 1 execp_interval = 1
``` ```
@@ -766,3 +771,4 @@ and the wiki page at https://gitlab.com/o9000/tint2/wikis/home.
This documentation is also provided in HTML and Markdown format in the system's default location This documentation is also provided in HTML and Markdown format in the system's default location
for documentation files, usually `/usr/share/doc/tint2` or `/usr/local/share/doc/tint2`. for documentation files, usually `/usr/share/doc/tint2` or `/usr/local/share/doc/tint2`.
. .
.

View File

@@ -55,13 +55,14 @@ def cmd(s):
def run(s): def run(s):
proc = subprocess.Popen(cmd(s), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) proc = subprocess.Popen(cmd(s), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
ret = proc.wait() ret = proc.wait()
out = proc.communicate()[0] out, err = proc.communicate()
for line in out.split("\n"): for line in out.split("\n"):
debug(ansi_pinky + line + ansi_reset) debug(ansi_pinky + line + ansi_reset)
debug(ansi_pinky + "Exit code: " + str(ret)) debug(ansi_pinky + "Exit code: " + str(ret))
if ret != 0: if ret != 0:
print(err)
raise Exception("Command failed!") raise Exception("Command failed!")
return out return out

79
packaging/compile-deps.sh Executable file
View File

@@ -0,0 +1,79 @@
#!/bin/bash
PS4='\e[99;33m${BASH_SOURCE}:$LINENO\e[0m '
set -e
set -x
sudo apt-get install ninja-build python2.7 wget
sudo apt-get build-dep libx11-6 libxrender1 libcairo2 libglib2.0-0 libpango-1.0-0 libimlib2 librsvg2-2
export PKG_CONFIG_PATH=""
DEPS=$HOME/tint2-deps
X11=$(pkg-config --modversion x11)
XRENDER=$(pkg-config --modversion xrender)
XCOMPOSITE=$(pkg-config --modversion xcomposite)
XDAMAGE=$(pkg-config --modversion xdamage)
XEXT=$(pkg-config --modversion xext)
XRANDR=$(pkg-config --modversion xrandr)
XINERAMA=$(pkg-config --modversion xinerama)
IMLIB=$(pkg-config --modversion imlib2)
GLIB=$(pkg-config --modversion glib-2.0)
CAIRO=$(pkg-config --modversion cairo)
PANGO=$(pkg-config --modversion pango)
PIXBUF=$(pkg-config --modversion gdk-pixbuf-2.0)
RSVG=$(pkg-config --modversion librsvg-2.0)
mkdir -p $DEPS/src
function two_digits() {
echo "$@" | cut -d. -f 1-2
}
function download_and_build() {
URL="$1"
shift
CFGARGS="$@"
ARCHIVE="$(basename "$URL")"
NAME="$(echo "$ARCHIVE" | sed s/\.tar.*$//g)"
cd "$DEPS/src"
rm -rf "$ARCHIVE"
rm -rf "$NAME"
wget "$URL" -O "$ARCHIVE"
tar xf "$ARCHIVE"
cd "$NAME"
export PKG_CONFIG_PATH="$DEPS/lib/pkgconfig"
export PATH="$DEPS/bin:$PATH"
export CFLAGS="-O0 -fno-common -fno-omit-frame-pointer -rdynamic -fsanitize=address -g"
export LDFLAGS="-Wl,--no-as-needed -Wl,-z,defs -O0 -fno-common -fno-omit-frame-pointer -rdynamic -fsanitize=address -fuse-ld=gold -g -ldl -lasan"
if [[ -x ./configure ]]
then
./configure "--prefix=$DEPS" "$@"
make -j
make install
elif [[ -f meson.build ]]
then
mkdir build
cd build
meson "--prefix=$DEPS" "$@" ..
ninja install
else
echo "unknown build method"
exit 1
fi
}
download_and_build "https://www.x.org/archive/individual/lib/libX11-$X11.tar.gz" --enable-static=no
download_and_build "https://www.x.org/archive//individual/lib/libXrender-$XRENDER.tar.gz" --enable-static=no
download_and_build "https://www.x.org/archive//individual/lib/libXcomposite-$XCOMPOSITE.tar.gz" --enable-static=no
download_and_build "https://www.x.org/archive//individual/lib/libXdamage-$XDAMAGE.tar.gz" --enable-static=no
download_and_build "https://www.x.org/archive//individual/lib/libXext-$XEXT.tar.gz" --enable-static=no
download_and_build "https://www.x.org/archive//individual/lib/libXrandr-$XRANDR.tar.gz" --enable-static=no
download_and_build "https://www.x.org/archive//individual/lib/libXinerama-$XINERAMA.tar.gz" --enable-static=no
download_and_build "https://downloads.sourceforge.net/enlightenment/imlib2-$IMLIB.tar.bz2" --enable-static=no
download_and_build "https://ftp.gnome.org/pub/gnome/sources/glib/$(two_digits "$GLIB")/glib-$GLIB.tar.xz" --enable-debug=yes
download_and_build "https://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/$(two_digits "$PIXBUF")/gdk-pixbuf-$PIXBUF.tar.xz"
download_and_build "https://cairographics.org/snapshots/cairo-$CAIRO.tar.xz"
download_and_build "https://ftp.gnome.org/pub/gnome/sources/pango/$(two_digits "$PANGO")/pango-$PANGO.tar.xz"
download_and_build "https://ftp.gnome.org/pub/gnome/sources/librsvg/$(two_digits "$RSVG")/librsvg-$RSVG.tar.xz" --enable-pixbuf-loader

27
packaging/configure vendored
View File

@@ -52,6 +52,7 @@ def pkg_config(lib):
lf = _pkgconfig(lib, '--libs-only-l') lf = _pkgconfig(lib, '--libs-only-l')
cf = _pkgconfig(lib, '--cflags') cf = _pkgconfig(lib, '--cflags')
ldf = _pkgconfig(lib, '--libs-only-L') ldf = _pkgconfig(lib, '--libs-only-L')
print("Found", lib, "in:", ldf)
return (lf, cf, ldf) return (lf, cf, ldf)
@@ -110,6 +111,14 @@ def install_dir(prefix, suffix, dest_dir, dest_suffix=''):
return result return result
def remove_duplicates(ls):
result = []
for x in ls:
if x not in result:
result.append(x)
return result
class Executable(object): class Executable(object):
def __init__(self, name): def __init__(self, name):
self.name = name self.name = name
@@ -126,9 +135,9 @@ class Executable(object):
f.write('# Executable: {}\n'.format(self.name)) f.write('# Executable: {}\n'.format(self.name))
ninja_write_vars(f, **{ ninja_write_vars(f, **{
'cc_' + self.name: self.cc, 'cc_' + self.name: self.cc,
'cflags_' + self.name: ninja_join(self.cflags), 'cflags_' + self.name: ninja_join(remove_duplicates(self.cflags)),
'lflags_' + self.name: ninja_join(self.lflags), 'lflags_' + self.name: ninja_join(remove_duplicates(self.lflags)),
'libs_' + self.name: ninja_join(self.libs)}) 'libs_' + self.name: ninja_join(remove_duplicates(self.libs))})
ninja_write_rule(f, 'cc_' + self.name, ninja_write_rule(f, 'cc_' + self.name,
command='$cc_{} -MMD -MT $out -MF $out.d $cflags_{} -c $in -o $out'.format(self.name, self.name), command='$cc_{} -MMD -MT $out -MF $out.d $cflags_{} -c $in -o $out'.format(self.name, self.name),
description='CC $out', description='CC $out',
@@ -339,11 +348,13 @@ for dep in ['x11',
'xext', 'xext',
'xrender', 'xrender',
'xrandr>=1.3', 'xrandr>=1.3',
'gmodule-2.0',
'gio-2.0',
'glib-2.0',
'gobject-2.0',
'pangocairo', 'pangocairo',
'pango', 'pango',
'cairo', 'cairo',
'glib-2.0',
'gobject-2.0',
'imlib2>=1.4.2']: 'imlib2>=1.4.2']:
lib, cf, lf = pkg_config(dep) lib, cf, lf = pkg_config(dep)
LIBS += lib LIBS += lib
@@ -409,7 +420,8 @@ if args.asan or args.memory_tracing or args.tracing:
trace_flags = ['-O0', trace_flags = ['-O0',
'-fno-common', '-fno-common',
'-fno-omit-frame-pointer', '-fno-omit-frame-pointer',
'-rdynamic'] '-rdynamic',
'-DUSE_REAL_MALLOC']
CFLAGS += trace_flags CFLAGS += trace_flags
LFLAGS += trace_flags + ['-fuse-ld=gold'] LFLAGS += trace_flags + ['-fuse-ld=gold']
@@ -510,7 +522,8 @@ tint2conf.cflags += ['-DTINT2CONF',
'-DINSTALL_PREFIX=\\"{}\\"'.format(prefix), '-DINSTALL_PREFIX=\\"{}\\"'.format(prefix),
'-DLOCALEDIR=\\"{}\\"'.format(localedir), '-DLOCALEDIR=\\"{}\\"'.format(localedir),
'-DGETTEXT_PACKAGE=\\"tint2conf\\"', '-DGETTEXT_PACKAGE=\\"tint2conf\\"',
'-DHAVE_VERSION_H'] '-DHAVE_VERSION_H',
'-Wno-shadow']
tint2conf.sources = ['src/util/bt.c', tint2conf.sources = ['src/util/bt.c',
'src/util/common.c', 'src/util/common.c',

View File

@@ -6,7 +6,7 @@ Build-Depends: cmake,
debhelper (>= 9), debhelper (>= 9),
libcairo2-dev, libcairo2-dev,
libglib2.0-dev, libglib2.0-dev,
libgtk2.0-dev, libgtk-3-dev,
libimlib2-dev, libimlib2-dev,
libpango1.0-dev, libpango1.0-dev,
librsvg2-dev, librsvg2-dev,

View File

@@ -42,6 +42,7 @@ gboolean battery_enabled;
gboolean battery_tooltip_enabled; gboolean battery_tooltip_enabled;
int percentage_hide; int percentage_hide;
static Timer battery_timer; static Timer battery_timer;
static Timer battery_blink_timer;
#define BATTERY_BUF_SIZE 256 #define BATTERY_BUF_SIZE 256
static char buf_bat_line1[BATTERY_BUF_SIZE]; static char buf_bat_line1[BATTERY_BUF_SIZE];
@@ -60,6 +61,8 @@ char *battery_rclick_command;
char *battery_uwheel_command; char *battery_uwheel_command;
char *battery_dwheel_command; char *battery_dwheel_command;
gboolean battery_found; gboolean battery_found;
gboolean battery_warn;
gboolean battery_warn_red;
char *battery_sys_prefix = (char *)""; char *battery_sys_prefix = (char *)"";
@@ -77,6 +80,9 @@ void default_battery()
battery_low_cmd_sent = FALSE; battery_low_cmd_sent = FALSE;
battery_full_cmd_sent = FALSE; battery_full_cmd_sent = FALSE;
INIT_TIMER(battery_timer); INIT_TIMER(battery_timer);
INIT_TIMER(battery_blink_timer);
battery_warn = FALSE;
battery_warn_red = FALSE;
bat1_has_font = FALSE; bat1_has_font = FALSE;
bat1_font_desc = NULL; bat1_font_desc = NULL;
bat1_format = NULL; bat1_format = NULL;
@@ -128,6 +134,7 @@ void cleanup_battery()
free(ac_disconnected_cmd); free(ac_disconnected_cmd);
ac_disconnected_cmd = NULL; ac_disconnected_cmd = NULL;
destroy_timer(&battery_timer); destroy_timer(&battery_timer);
destroy_timer(&battery_blink_timer);
battery_found = FALSE; battery_found = FALSE;
battery_os_free(); battery_os_free();
@@ -164,6 +171,7 @@ void battery_update_text(char *dest, char *format)
// %h : Hours left (estimated). // %h : Hours left (estimated).
// %t : Time left. This is equivalent to the old behaviour; i.e. "(plugged in)" or "hrs:mins" otherwise. // %t : Time left. This is equivalent to the old behaviour; i.e. "(plugged in)" or "hrs:mins" otherwise.
// %p : Percentage left. Includes the % sign. // %p : Percentage left. Includes the % sign.
// %P : Percentage left without the % sign.
if (*c == '%') { if (*c == '%') {
c++; c++;
o++; // Skip the format control character. o++; // Skip the format control character.
@@ -192,6 +200,10 @@ void battery_update_text(char *dest, char *format)
snprintf(buf, sizeof(buf), "%d%%", battery_state.percentage); snprintf(buf, sizeof(buf), "%d%%", battery_state.percentage);
strnappend(dest, buf, BATTERY_BUF_SIZE); strnappend(dest, buf, BATTERY_BUF_SIZE);
break; break;
case 'P':
snprintf(buf, sizeof(buf), "%d", battery_state.percentage);
strnappend(dest, buf, BATTERY_BUF_SIZE);
break;
case 't': case 't':
if (battery_state.state == BATTERY_FULL) { if (battery_state.state == BATTERY_FULL) {
snprintf(buf, sizeof(buf), "Full"); snprintf(buf, sizeof(buf), "Full");
@@ -310,6 +322,18 @@ void battery_default_font_changed()
schedule_panel_redraw(); schedule_panel_redraw();
} }
void blink_battery(void *arg)
{
if (!battery_enabled)
return;
battery_warn_red = battery_warn ? !battery_warn_red : FALSE;
for (int i = 0; i < num_panels; i++) {
if (panels[i].battery.area.on_screen) {
schedule_redraw(&panels[i].battery.area);
}
}
}
void update_battery_tick(void *arg) void update_battery_tick(void *arg)
{ {
if (!battery_enabled) if (!battery_enabled)
@@ -320,6 +344,7 @@ void update_battery_tick(void *arg)
gboolean old_ac_connected = battery_state.ac_connected; gboolean old_ac_connected = battery_state.ac_connected;
int16_t old_hours = battery_state.time.hours; int16_t old_hours = battery_state.time.hours;
int8_t old_minutes = battery_state.time.minutes; int8_t old_minutes = battery_state.time.minutes;
gboolean old_warn = battery_warn;
if (!battery_found) { if (!battery_found) {
init_battery(); init_battery();
@@ -357,6 +382,20 @@ void update_battery_tick(void *arg)
battery_full_cmd_sent = FALSE; battery_full_cmd_sent = FALSE;
} }
if (!battery_blink_timer.enabled_) {
if ((battery_state.percentage < battery_low_status &&
battery_state.state == BATTERY_DISCHARGING) || debug_blink) {
change_timer(&battery_blink_timer, true, 10, 1000, blink_battery, 0);
battery_warn = TRUE;
}
} else {
if (battery_state.percentage > battery_low_status ||
battery_state.state != BATTERY_DISCHARGING) {
stop_timer(&battery_blink_timer);
battery_warn = FALSE;
}
}
for (int i = 0; i < num_panels; i++) { for (int i = 0; i < num_panels; i++) {
// Show/hide if needed // Show/hide if needed
if (!battery_found) { if (!battery_found) {
@@ -370,8 +409,11 @@ void update_battery_tick(void *arg)
// Redraw if needed // Redraw if needed
if (panels[i].battery.area.on_screen) { if (panels[i].battery.area.on_screen) {
if (old_found != battery_found || old_percentage != battery_state.percentage || if (old_found != battery_found || old_percentage != battery_state.percentage ||
old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes) { old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes ||
old_warn != battery_warn) {
panels[i].battery.area.resize_needed = TRUE; panels[i].battery.area.resize_needed = TRUE;
if (!battery_warn)
panels[i].battery.area.bg = panel_config.battery.area.bg;
schedule_panel_redraw(); schedule_panel_redraw();
} }
} }
@@ -433,6 +475,12 @@ void draw_battery(void *obj, cairo_t *c)
battery->bat2_posy, battery->bat2_posy,
&battery->font_color, &battery->font_color,
panel->scale); panel->scale);
if (battery_warn && battery_warn_red) {
cairo_set_source_rgba(c, 1, 0, 0, 1);
cairo_set_line_width(c, 0);
cairo_rectangle(c, 0, 0, battery->area.width, battery->area.height);
cairo_fill(c);
}
} }
void battery_dump_geometry(void *obj, int indent) void battery_dump_geometry(void *obj, int indent)

View File

@@ -478,7 +478,7 @@ void draw_button(void *obj, cairo_t *c)
button->frontend->textx, button->frontend->textx,
button->frontend->texty, button->frontend->texty,
&button->backend->font_color, &button->backend->font_color,
panel_config.font_shadow); panel_config.font_shadow ? layout : NULL);
g_object_unref(layout); g_object_unref(layout);
g_object_unref(context); g_object_unref(context);

View File

@@ -129,18 +129,29 @@ struct tm *clock_gettime_for_tz(const char *timezone)
} }
} }
void update_clock_text(char *dst, size_t size, const char *format,
const char *timezone, bool *changed)
{
if (!dst || !format) {
return;
}
char tmp[256] = "";
strncpy(tmp, dst, sizeof(tmp) - 1);
strftime(dst, size, format, clock_gettime_for_tz(timezone));
*changed = *changed || strcmp(dst, tmp) != 0;
}
void update_clocks() void update_clocks()
{ {
if (time1_format) bool changed = false;
strftime(buf_time, sizeof(buf_time), time1_format, clock_gettime_for_tz(time1_timezone)); update_clock_text(buf_time, sizeof(buf_time), time1_format, time1_timezone, &changed);
if (time2_format) update_clock_text(buf_date, sizeof(buf_date), time2_format, time2_timezone, &changed);
strftime(buf_date, sizeof(buf_date), time2_format, clock_gettime_for_tz(time2_timezone)); if (changed) {
if (time1_format || time2_format) {
for (int i = 0; i < num_panels; i++) for (int i = 0; i < num_panels; i++)
panels[i].clock.area.resize_needed = 1; panels[i].clock.area.resize_needed = 1;
}
schedule_panel_redraw(); schedule_panel_redraw();
} }
}
int ms_until_second_change(struct timeval* tm) int ms_until_second_change(struct timeval* tm)
{ {
@@ -157,27 +168,6 @@ void update_clocks_sec(void *arg)
change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_sec, 0); change_timer(&clock_timer, true, ms_until_second_change(&time_clock), 0, update_clocks_sec, 0);
} }
void update_clocks_min(void *arg)
{
// remember old_sec because after suspend/hibernate the clock should be updated directly, and not
// on next minute change
static time_t old_sec = 0;
gettimeofday(&time_clock, 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();
old_sec = time_clock.tv_sec;
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)
{
if (!time_format)
return FALSE;
if (strchr(time_format, 'S') || strchr(time_format, 'T') || strchr(time_format, 'r'))
return TRUE;
return FALSE;
}
void init_clock() void init_clock()
{ {
} }
@@ -216,11 +206,7 @@ void init_clock_panel(void *p)
} }
if (!clock_timer.enabled_) { if (!clock_timer.enabled_) {
if (time_format_needs_sec_ticks(time1_format) || time_format_needs_sec_ticks(time2_format)) {
update_clocks_sec(NULL); update_clocks_sec(NULL);
} else {
update_clocks_min(NULL);
}
} }
} }

View File

@@ -508,6 +508,8 @@ void add_entry(char *key, char *value)
wm_menu = atoi(value); wm_menu = atoi(value);
else if (strcmp(key, "panel_dock") == 0) else if (strcmp(key, "panel_dock") == 0)
panel_dock = atoi(value); panel_dock = atoi(value);
else if (strcmp(key, "panel_pivot_struts") == 0)
panel_pivot_struts = atoi(value);
else if (strcmp(key, "urgent_nb_of_blink") == 0) else if (strcmp(key, "urgent_nb_of_blink") == 0)
max_tick_urgent = atoi(value); max_tick_urgent = atoi(value);
else if (strcmp(key, "panel_layer") == 0) { else if (strcmp(key, "panel_layer") == 0) {
@@ -695,6 +697,9 @@ void add_entry(char *key, char *value)
} else { } else {
execp->backend->interval = v; execp->backend->interval = v;
} }
} else if (strcmp(key, "execp_monitor") == 0) {
Execp *execp = get_or_create_last_execp();
execp->backend->monitor = config_get_monitor(value);
} else if (strcmp(key, "execp_has_icon") == 0) { } else if (strcmp(key, "execp_has_icon") == 0) {
Execp *execp = get_or_create_last_execp(); Execp *execp = get_or_create_last_execp();
execp->backend->has_icon = atoi(value); execp->backend->has_icon = atoi(value);
@@ -792,7 +797,7 @@ void add_entry(char *key, char *value)
} else if (strcmp(key, "button_icon") == 0) { } else if (strcmp(key, "button_icon") == 0) {
if (strlen(value)) { if (strlen(value)) {
Button *button = get_or_create_last_button(); Button *button = get_or_create_last_button();
button->backend->icon_name = strdup(value); button->backend->icon_name = expand_tilde(value);
} }
} else if (strcmp(key, "button_text") == 0) { } else if (strcmp(key, "button_text") == 0) {
if (strlen(value)) { if (strlen(value)) {

View File

@@ -43,13 +43,36 @@ 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;
execp->backend->monitor = -1;
INIT_TIMER(execp->backend->timer); INIT_TIMER(execp->backend->timer);
execp->backend->bg = &g_array_index(backgrounds, Background, 0);
execp->backend->buf_stdout_capacity = 1024;
execp->backend->buf_stdout = calloc(execp->backend->buf_stdout_capacity, 1);
execp->backend->buf_stderr_capacity = 1024;
execp->backend->buf_stderr = calloc(execp->backend->buf_stderr_capacity, 1);
execp->backend->text = strdup("");
execp->backend->icon_path = NULL;
return execp; return execp;
} }
gpointer create_execp_frontend(gconstpointer arg, gpointer data) gpointer create_execp_frontend(gconstpointer arg, gpointer data)
{ {
Execp *execp_backend = (Execp *)arg; Execp *execp_backend = (Execp *)arg;
Panel *panel = data;
if (execp_backend->backend->monitor >= 0 &&
panel->monitor != execp_backend->backend->monitor) {
printf("Skipping executor '%s' with monitor %d for panel on monitor %d\n",
execp_backend->backend->command,
execp_backend->backend->monitor, panel->monitor);
Execp *dummy = create_execp();
dummy->frontend = (ExecpFrontend *)calloc(1, sizeof(ExecpFrontend));
dummy->backend->instances = g_list_append(dummy->backend->instances, dummy);
dummy->dummy = true;
return dummy;
}
printf("Creating executor '%s' with monitor %d for panel on monitor %d\n",
execp_backend->backend->command,
execp_backend->backend->monitor, panel->monitor);
Execp *execp_frontend = (Execp *)calloc(1, sizeof(Execp)); Execp *execp_frontend = (Execp *)calloc(1, sizeof(Execp));
execp_frontend->backend = execp_backend->backend; execp_frontend->backend = execp_backend->backend;
@@ -67,7 +90,11 @@ void destroy_execp(void *obj)
free_and_null(execp->frontend); free_and_null(execp->frontend);
remove_area(&execp->area); remove_area(&execp->area);
free_area(&execp->area); free_area(&execp->area);
if (execp->dummy) {
destroy_execp(execp);
} else {
free_and_null(execp); free_and_null(execp);
}
} else { } else {
// This is a backend element // This is a backend element
destroy_timer(&execp->backend->timer); destroy_timer(&execp->backend->timer);
@@ -144,12 +171,6 @@ void init_execp()
// Set missing config options // Set missing config options
if (!execp->backend->bg) if (!execp->backend->bg)
execp->backend->bg = &g_array_index(backgrounds, Background, 0); execp->backend->bg = &g_array_index(backgrounds, Background, 0);
execp->backend->buf_stdout_capacity = 1024;
execp->backend->buf_stdout = calloc(execp->backend->buf_stdout_capacity, 1);
execp->backend->buf_stderr_capacity = 1024;
execp->backend->buf_stderr = calloc(execp->backend->buf_stderr_capacity, 1);
execp->backend->text = strdup("");
execp->backend->icon_path = NULL;
} }
} }
@@ -163,7 +184,7 @@ void init_execp_panel(void *p)
// panel->execp_list is now a copy of the pointer panel_config.execp_list // panel->execp_list is now a copy of the pointer panel_config.execp_list
// We make it a deep copy // We make it a deep copy
panel->execp_list = g_list_copy_deep(panel_config.execp_list, create_execp_frontend, NULL); panel->execp_list = g_list_copy_deep(panel_config.execp_list, create_execp_frontend, panel);
for (GList *l = panel->execp_list; l; l = l->next) { for (GList *l = panel->execp_list; l; l = l->next) {
Execp *execp = l->data; Execp *execp = l->data;
@@ -373,7 +394,11 @@ void execp_compute_icon_text_geometry(Execp *execp,
*new_size = *txt_height + 2 * *vert_padding + top_bottom_border_width(area); *new_size = *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
*new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area)); *new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area));
} else { } else {
if (strlen(execp->backend->text)) {
*new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area); *new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
} else {
*new_size = *icon_h + 2 * *vert_padding + top_bottom_border_width(area);
}
} }
if (*new_size != area->height) { if (*new_size != area->height) {
*resized = TRUE; *resized = TRUE;
@@ -441,10 +466,17 @@ gboolean resize_execp(void *obj)
execp->frontend->texty = (execp->area.height - txt_height) / 2; execp->frontend->texty = (execp->area.height - txt_height) / 2;
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding; execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
} else { } else {
if (strlen(execp->backend->text)) {
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2; execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
execp->frontend->iconx = (execp->area.width - icon_w) / 2; execp->frontend->iconx = (execp->area.width - icon_w) / 2;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding; execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = (execp->area.width - txt_width) / 2; execp->frontend->textx = (execp->area.width - txt_width) / 2;
} else {
execp->frontend->icony = (execp->area.height - icon_h) / 2;
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = (execp->area.width - txt_width) / 2;
}
} }
} else { } else {
execp->frontend->texty = (execp->area.height - txt_height) / 2; execp->frontend->texty = (execp->area.height - txt_height) / 2;
@@ -458,10 +490,17 @@ gboolean resize_execp(void *obj)
execp->frontend->texty = (execp->area.height - txt_height) / 2; execp->frontend->texty = (execp->area.height - txt_height) / 2;
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding; execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
} else { } else {
if (strlen(execp->backend->text)) {
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2; execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding; execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding; execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = execp->frontend->iconx; execp->frontend->textx = execp->frontend->iconx;
} else {
execp->frontend->icony = (execp->area.height - icon_h) / 2;
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
execp->frontend->textx = execp->frontend->iconx;
}
} }
} else { } else {
execp->frontend->texty = (execp->area.height - txt_height) / 2; execp->frontend->texty = (execp->area.height - txt_height) / 2;
@@ -473,6 +512,18 @@ gboolean resize_execp(void *obj)
return resized; return resized;
} }
PangoLayout *create_execp_text_layout(Execp *execp, PangoContext *context)
{
PangoLayout *layout = pango_layout_new(context);
pango_layout_set_font_description(layout, execp->backend->font_desc);
pango_layout_set_width(layout, (execp->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_height(layout, (execp->frontend->texth + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
return layout;
}
void draw_execp(void *obj, cairo_t *c) void draw_execp(void *obj, cairo_t *c)
{ {
Execp *execp = (Execp *)obj; Execp *execp = (Execp *)obj;
@@ -480,7 +531,8 @@ void draw_execp(void *obj, cairo_t *c)
PangoContext *context = pango_cairo_create_context(c); PangoContext *context = pango_cairo_create_context(c);
pango_cairo_context_set_resolution(context, 96 * panel->scale); pango_cairo_context_set_resolution(context, 96 * panel->scale);
PangoLayout *layout = pango_layout_new(context); PangoLayout *layout = create_execp_text_layout(execp, context);
PangoLayout *shadow_layout = NULL;
if (execp->backend->has_icon && execp->backend->icon) { if (execp->backend->has_icon && execp->backend->icon) {
imlib_context_set_image(execp->backend->icon); imlib_context_set_image(execp->backend->icon);
@@ -489,16 +541,18 @@ void draw_execp(void *obj, cairo_t *c)
} }
// draw layout // draw layout
pango_layout_set_font_description(layout, execp->backend->font_desc); if (!execp->backend->has_markup) {
pango_layout_set_width(layout, (execp->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_height(layout, (execp->frontend->texth + TINT2_PANGO_SLACK) * PANGO_SCALE);
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
if (!execp->backend->has_markup)
pango_layout_set_text(layout, execp->backend->text, strlen(execp->backend->text)); pango_layout_set_text(layout, execp->backend->text, strlen(execp->backend->text));
else } else {
pango_layout_set_markup(layout, execp->backend->text, strlen(execp->backend->text)); pango_layout_set_markup(layout, execp->backend->text, strlen(execp->backend->text));
if (panel_config.font_shadow) {
shadow_layout = create_execp_text_layout(execp, context);
if (!layout_set_markup_strip_colors(shadow_layout, execp->backend->text)) {
g_object_unref(shadow_layout);
shadow_layout = NULL;
}
}
}
pango_cairo_update_layout(c, layout); pango_cairo_update_layout(c, layout);
draw_text(layout, draw_text(layout,
@@ -506,7 +560,7 @@ void draw_execp(void *obj, cairo_t *c)
execp->frontend->textx, execp->frontend->textx,
execp->frontend->texty, execp->frontend->texty,
&execp->backend->font_color, &execp->backend->font_color,
panel_config.font_shadow); shadow_layout);
g_object_unref(layout); g_object_unref(layout);
g_object_unref(context); g_object_unref(context);
@@ -531,12 +585,13 @@ void execp_dump_geometry(void *obj, int indent)
imlib_context_set_image(tmp); imlib_context_set_image(tmp);
} }
fprintf(stderr, fprintf(stderr,
"tint2: %*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n", "tint2: %*sText: x = %d, y = %d, w = %d, h = %d, align = %s, text = %s\n",
indent, indent,
"", "",
execp->frontend->textx, execp->frontend->textx,
execp->frontend->texty, execp->frontend->texty,
execp->frontend->textw, execp->frontend->textw,
execp->frontend->texth,
execp->backend->centered ? "center" : "left", execp->backend->centered ? "center" : "left",
execp->backend->text); execp->backend->text);
} }
@@ -857,7 +912,7 @@ gboolean read_execp(void *obj)
} else { } else {
execp->backend->text = strdup(""); execp->backend->text = strdup("");
} }
execp->backend->icon_path = strdup(execp->backend->buf_stdout); execp->backend->icon_path = expand_tilde(execp->backend->buf_stdout);
} }
size_t len = strlen(execp->backend->text); size_t len = strlen(execp->backend->text);
if (len > 0 && execp->backend->text[len - 1] == '\n') if (len > 0 && execp->backend->text[len - 1] == '\n')

View File

@@ -24,6 +24,7 @@ typedef struct ExecpBackend {
char *command; char *command;
// Interval in seconds // Interval in seconds
int interval; int interval;
int monitor;
// 1 if first line of output is an icon path // 1 if first line of output is an icon path
gboolean has_icon; gboolean has_icon;
gboolean cache_icon; gboolean cache_icon;
@@ -96,6 +97,7 @@ typedef struct Execp {
ExecpBackend *backend; ExecpBackend *backend;
// Set only for frontend Execp items. // Set only for frontend Execp items.
ExecpFrontend *frontend; ExecpFrontend *frontend;
bool dummy;
} Execp; } Execp;
// Called before the config is read and panel_config/panels are created. // Called before the config is read and panel_config/panels are created.

View File

@@ -107,6 +107,8 @@ void handle_env_vars()
debug_thumbnails = getenv("DEBUG_THUMBNAILS") != NULL; debug_thumbnails = getenv("DEBUG_THUMBNAILS") != NULL;
debug_timers = getenv("DEBUG_TIMERS") != NULL; debug_timers = getenv("DEBUG_TIMERS") != NULL;
debug_executors = getenv("DEBUG_EXECUTORS") != NULL; debug_executors = getenv("DEBUG_EXECUTORS") != NULL;
debug_blink = getenv("DEBUG_BLINK") != NULL;
thumb_use_shm = getenv("TINT2_THUMBNAIL_SHM") != 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");
@@ -209,8 +211,8 @@ void init_X11_pre_config()
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
server.x11_fd = ConnectionNumber(server.display); server.x11_fd = ConnectionNumber(server.display);
XSetErrorHandler((XErrorHandler)server_catch_error); XSetErrorHandler(server_catch_error);
XSetIOErrorHandler((XIOErrorHandler)x11_io_error); XSetIOErrorHandler(x11_io_error);
server_init_atoms(); server_init_atoms();
server.screen = DefaultScreen(server.display); server.screen = DefaultScreen(server.display);
server.root_win = RootWindow(server.display, server.screen); server.root_win = RootWindow(server.display, server.screen);
@@ -247,8 +249,9 @@ void init(int argc, char **argv)
if (!config_read()) { if (!config_read()) {
fprintf(stderr, "tint2: Could not read config file.\n"); fprintf(stderr, "tint2: Could not read config file.\n");
print_usage(); print_usage();
warnings_for_timers = false;
cleanup(); cleanup();
return; exit(EXIT_FAILURE);
} }
init_post_config(); init_post_config();

View File

@@ -566,6 +566,10 @@ char *icon_path_from_full_path(const char *s)
{ {
if (is_full_path(s) && file_exists(s)) if (is_full_path(s) && file_exists(s))
return strdup(s); return strdup(s);
char *expanded = expand_tilde(s);
if (is_full_path(expanded) && file_exists(expanded))
return expanded;
free(expanded);
return NULL; return NULL;
} }

View File

@@ -399,7 +399,12 @@ void launcher_icon_dump_geometry(void *obj, int indent)
Imlib_Image scale_icon(Imlib_Image original, int icon_size) Imlib_Image scale_icon(Imlib_Image original, int icon_size)
{ {
Imlib_Image icon_scaled; Imlib_Image icon_scaled;
if (original) { if (!icon_size) {
icon_scaled = imlib_create_image(1, 1);
imlib_context_set_image(icon_scaled);
imlib_context_set_color(255, 255, 255, 255);
imlib_image_fill_rectangle(0, 0, icon_size, icon_size);
} else if (original) {
imlib_context_set_image(original); imlib_context_set_image(original);
icon_scaled = imlib_create_cropped_scaled_image(0, icon_scaled = imlib_create_cropped_scaled_image(0,
0, 0,

View File

@@ -389,9 +389,9 @@ gboolean handle_x_event_autohide(XEvent *e)
Panel *panel = get_panel(e->xany.window); Panel *panel = get_panel(e->xany.window);
if (panel && panel_autohide) { if (panel && panel_autohide) {
if (e->type == EnterNotify) if (e->type == EnterNotify)
autohide_trigger_show(panel); autohide_trigger_show(panel, e->xany.send_event);
else if (e->type == LeaveNotify) else if (e->type == LeaveNotify)
autohide_trigger_hide(panel); autohide_trigger_hide(panel, e->xany.send_event);
if (panel->is_hidden) { if (panel->is_hidden) {
if (e->type == ClientMessage && e->xclient.message_type == server.atom.XdndPosition) { if (e->type == ClientMessage && e->xclient.message_type == server.atom.XdndPosition) {
hidden_panel_shown_for_dnd = TRUE; hidden_panel_shown_for_dnd = TRUE;
@@ -797,6 +797,19 @@ void tint2(int argc, char **argv, gboolean *restart)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
#ifdef USE_REAL_MALLOC
if (!getenv("G_SLICE") && setenv("G_SLICE", "always-malloc", 1) == 0) {
fprintf(stderr,
YELLOW "tint2: reexecuting tint2 without glib slice allocator..." RESET "\n");
execvp(argv[0], argv);
fprintf(stderr, RED "tint2: %s %d: execvp failed! carrying on..." RESET "\n",
__FILE__, __LINE__);
}
#else
fprintf(stderr, "tint2: Using glib slice allocator (default). "
"Run tint2 with environment variable G_SLICE=always-malloc "
"in case of strange behavior or crashes\n");
#endif
gboolean restart; gboolean restart;
do { do {
restart = FALSE; restart = FALSE;

View File

@@ -49,6 +49,7 @@ MouseAction mouse_tilt_right;
TaskbarMode taskbar_mode; TaskbarMode taskbar_mode;
gboolean wm_menu; gboolean wm_menu;
gboolean panel_dock; gboolean panel_dock;
gboolean panel_pivot_struts;
Layer panel_layer; Layer panel_layer;
PanelPosition panel_position; PanelPosition panel_position;
gboolean panel_horizontal; gboolean panel_horizontal;
@@ -59,7 +60,7 @@ gboolean debug_geometry;
gboolean debug_gradients; gboolean debug_gradients;
gboolean startup_notifications; gboolean startup_notifications;
gboolean debug_thumbnails; gboolean debug_thumbnails;
gboolean debug_blink;
gboolean panel_autohide; gboolean panel_autohide;
int panel_autohide_show_timeout; int panel_autohide_show_timeout;
int panel_autohide_hide_timeout; int panel_autohide_hide_timeout;
@@ -103,6 +104,7 @@ void default_panel()
panel_shrink = FALSE; panel_shrink = FALSE;
panel_strut_policy = STRUT_FOLLOW_SIZE; panel_strut_policy = STRUT_FOLLOW_SIZE;
panel_dock = FALSE; // default not in the dock panel_dock = FALSE; // default not in the dock
panel_pivot_struts = FALSE;
panel_layer = BOTTOM_LAYER; // default is bottom layer panel_layer = BOTTOM_LAYER; // default is bottom layer
panel_window_name = strdup("tint2"); panel_window_name = strdup("tint2");
wm_menu = FALSE; wm_menu = FALSE;
@@ -267,8 +269,9 @@ void init_panel()
init_freespace_panel(p); init_freespace_panel(p);
if (panel_items_order[k] == ':') if (panel_items_order[k] == ':')
init_separator_panel(p); init_separator_panel(p);
if (panel_items_order[k] == 'E') if (panel_items_order[k] == 'E') {
init_execp_panel(p); init_execp_panel(p);
}
if (panel_items_order[k] == 'P') if (panel_items_order[k] == 'P')
init_button_panel(p); init_button_panel(p);
} }
@@ -314,7 +317,7 @@ void init_panel()
} }
if (panel_autohide) if (panel_autohide)
autohide_trigger_hide(p); autohide_trigger_hide(p, false);
} }
taskbar_refresh_tasklist(); taskbar_refresh_tasklist();
@@ -610,6 +613,21 @@ gboolean resize_panel(void *obj)
return FALSE; return FALSE;
} }
#define STRUT_LEFT 0
#define STRUT_RIGHT 1
#define STRUT_TOP 2
#define STRUT_BOTTOM 3
#define STRUT_LEFT_Y1 4
#define STRUT_LEFT_Y2 5
#define STRUT_RIGHT_Y1 6
#define STRUT_RIGHT_Y2 7
#define STRUT_TOP_X1 8
#define STRUT_TOP_X2 9
#define STRUT_BOTTOM_X1 10
#define STRUT_BOTTOM_X2 11
#define STRUT_COUNT 12
#define STRUT_COUNT_OLD 4
void update_strut(Panel *p) void update_strut(Panel *p)
{ {
if (panel_strut_policy == STRUT_NONE) { if (panel_strut_policy == STRUT_NONE) {
@@ -624,36 +642,36 @@ void update_strut(Panel *p)
int d3; int d3;
XGetGeometry(server.display, server.root_win, &d2, &d3, &d3, &screen_width, &screen_height, &d1, &d1); XGetGeometry(server.display, server.root_win, &d2, &d3, &d3, &screen_width, &screen_height, &d1, &d1);
Monitor monitor = server.monitors[p->monitor]; Monitor monitor = server.monitors[p->monitor];
long struts[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; long struts[STRUT_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (panel_horizontal) { if (panel_horizontal ^ panel_pivot_struts) {
int height = p->area.height + p->marginy; int height = p->area.height + p->marginy;
if (panel_strut_policy == STRUT_MINIMUM || (panel_strut_policy == STRUT_FOLLOW_SIZE && panel_autohide && p->is_hidden)) if (panel_strut_policy == STRUT_MINIMUM || (panel_strut_policy == STRUT_FOLLOW_SIZE && panel_autohide && p->is_hidden))
height = p->hidden_height; height = p->hidden_height;
if (panel_position & TOP) { if (panel_position & TOP) {
struts[2] = height + monitor.y; struts[STRUT_TOP] = height + monitor.y;
struts[8] = p->posx; struts[STRUT_TOP_X1] = p->posx;
// p->area.width - 1 allowed full screen on monitor 2 // p->area.width - 1 allowed full screen on monitor 2
struts[9] = p->posx + p->area.width - 1; struts[STRUT_TOP_X2] = p->posx + p->area.width - 1;
} else { } else {
struts[3] = height + screen_height - monitor.y - monitor.height; struts[STRUT_BOTTOM] = height + screen_height - monitor.y - monitor.height;
struts[10] = p->posx; struts[STRUT_BOTTOM_X1] = p->posx;
// p->area.width - 1 allowed full screen on monitor 2 // p->area.width - 1 allowed full screen on monitor 2
struts[11] = p->posx + p->area.width - 1; struts[STRUT_BOTTOM_X2] = p->posx + p->area.width - 1;
} }
} else { } else {
int width = p->area.width + p->marginx; int width = p->area.width + p->marginx;
if (panel_strut_policy == STRUT_MINIMUM || (panel_strut_policy == STRUT_FOLLOW_SIZE && panel_autohide && p->is_hidden)) if (panel_strut_policy == STRUT_MINIMUM || (panel_strut_policy == STRUT_FOLLOW_SIZE && panel_autohide && p->is_hidden))
width = p->hidden_width; width = p->hidden_width;
if (panel_position & LEFT) { if (panel_position & LEFT) {
struts[0] = width + monitor.x; struts[STRUT_LEFT] = width + monitor.x;
struts[4] = p->posy; struts[STRUT_LEFT_Y1] = p->posy;
// p->area.width - 1 allowed full screen on monitor 2 // p->area.width - 1 allowed full screen on monitor 2
struts[5] = p->posy + p->area.height - 1; struts[STRUT_LEFT_Y2] = p->posy + p->area.height - 1;
} else { } else {
struts[1] = width + screen_width - monitor.x - monitor.width; struts[STRUT_RIGHT] = width + screen_width - monitor.x - monitor.width;
struts[6] = p->posy; struts[STRUT_RIGHT_Y1] = p->posy;
// p->area.width - 1 allowed full screen on monitor 2 // p->area.width - 1 allowed full screen on monitor 2
struts[7] = p->posy + p->area.height - 1; struts[STRUT_RIGHT_Y2] = p->posy + p->area.height - 1;
} }
} }
// Old specification : fluxbox need _NET_WM_STRUT. // Old specification : fluxbox need _NET_WM_STRUT.
@@ -664,7 +682,7 @@ void update_strut(Panel *p)
32, 32,
PropModeReplace, PropModeReplace,
(unsigned char *)&struts, (unsigned char *)&struts,
4); STRUT_COUNT_OLD);
XChangeProperty(server.display, XChangeProperty(server.display,
p->main_win, p->main_win,
server.atom._NET_WM_STRUT_PARTIAL, server.atom._NET_WM_STRUT_PARTIAL,
@@ -672,7 +690,7 @@ void update_strut(Panel *p)
32, 32,
PropModeReplace, PropModeReplace,
(unsigned char *)&struts, (unsigned char *)&struts,
12); STRUT_COUNT);
} }
void set_panel_items_order(Panel *p) void set_panel_items_order(Panel *p)
@@ -1122,26 +1140,27 @@ void autohide_hide(void *p)
schedule_panel_redraw(); schedule_panel_redraw();
} }
void autohide_trigger_show(Panel *p) void autohide_trigger_show(Panel *p, bool forced)
{ {
if (!p) if (!p)
return; return;
change_timer(&p->autohide_timer, true, panel_autohide_show_timeout, 0, autohide_show, p); change_timer(&p->autohide_timer, true, forced ? 0 : panel_autohide_show_timeout, 0, autohide_show, p);
} }
void autohide_trigger_hide(Panel *p) void autohide_trigger_hide(Panel *p, bool forced)
{ {
if (!p) if (!p)
return; return;
if (!forced) {
Window root, child; Window root, child;
int xr, yr, xw, yw; int xr, yr, xw, yw;
unsigned int mask; unsigned int mask;
if (XQueryPointer(server.display, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask)) if (XQueryPointer(server.display, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask))
if (child) if (child)
return; // mouse over one of the system tray icons return; // mouse over one of the system tray icons
}
change_timer(&p->autohide_timer, true, panel_autohide_hide_timeout, 0, autohide_hide, p); change_timer(&p->autohide_timer, true, forced ? 0 : panel_autohide_hide_timeout, 0, autohide_hide, p);
} }
void shrink_panel(Panel *panel) void shrink_panel(Panel *panel)

View File

@@ -69,6 +69,7 @@ typedef enum Strut {
extern TaskbarMode taskbar_mode; extern TaskbarMode taskbar_mode;
extern gboolean wm_menu; extern gboolean wm_menu;
extern gboolean panel_dock; extern gboolean panel_dock;
extern gboolean panel_pivot_struts;
extern Layer panel_layer; extern Layer panel_layer;
extern char *panel_window_name; extern char *panel_window_name;
extern PanelPosition panel_position; extern PanelPosition panel_position;
@@ -97,6 +98,8 @@ extern gboolean debug_frames;
extern gboolean debug_thumbnails; extern gboolean debug_thumbnails;
extern double ui_scale_dpi_ref; extern double ui_scale_dpi_ref;
extern double ui_scale_monitor_size_ref; extern double ui_scale_monitor_size_ref;
extern gboolean thumb_use_shm;
extern gboolean debug_blink;
typedef struct Panel { typedef struct Panel {
Area area; Area area;
@@ -200,8 +203,8 @@ Button *click_button(Panel *panel, int x, int y);
void autohide_show(void *p); void autohide_show(void *p);
void autohide_hide(void *p); void autohide_hide(void *p);
void autohide_trigger_show(Panel *p); void autohide_trigger_show(Panel *p, bool forced);
void autohide_trigger_hide(Panel *p); void autohide_trigger_hide(Panel *p, bool forced);
const char *get_default_font(); const char *get_default_font();

View File

@@ -312,10 +312,16 @@ Imlib_Image task_get_icon(Window win, int icon_size)
int w, h; int w, h;
gulong *tmp_data = get_best_icon(data, get_icon_count(data, len), len, &w, &h, icon_size); gulong *tmp_data = get_best_icon(data, get_icon_count(data, len), len, &w, &h, icon_size);
if (tmp_data) { if (tmp_data) {
DATA32 icon_data[w * h]; int array_size = w * h;
for (int j = 0; j < w * h; ++j) // imlib needs the array in DATA32 type
// using malloc for the array to protect from stack overflow
DATA32 *icon_data = (DATA32*) g_try_malloc(sizeof(*icon_data) * array_size);
if (icon_data) {
for (int j = 0; j < array_size; ++j)
icon_data[j] = tmp_data[j]; icon_data[j] = tmp_data[j];
img = imlib_create_image_using_copied_data(w, h, icon_data); img = imlib_create_image_using_copied_data(w, h, icon_data);
g_free(icon_data);
}
} }
} }
XFree(data); XFree(data);
@@ -497,7 +503,7 @@ void draw_task(void *obj, cairo_t *c)
task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0; task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0;
Color *config_text = &panel->g_task.font[task->current_state]; Color *config_text = &panel->g_task.font[task->current_state];
draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow); draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow ? layout : NULL);
g_object_unref(layout); g_object_unref(layout);
g_object_unref(context); g_object_unref(context);

View File

@@ -845,7 +845,8 @@ void taskbar_update_thumbnails(void *arg)
c; c;
c = c->next) { c = c->next) {
Task *t = (Task *)c->data; Task *t = (Task *)c->data;
if ((mode == THUMB_MODE_ALL && t->current_state == TASK_ACTIVE && !g_list_find(taskbar_thumbnail_jobs_done, t)) || (mode == THUMB_MODE_ACTIVE_WINDOW && t->current_state == TASK_ACTIVE) || if ((mode == THUMB_MODE_ALL && t->current_state == TASK_ACTIVE && !g_list_find(taskbar_thumbnail_jobs_done, t)) ||
(mode == THUMB_MODE_ACTIVE_WINDOW && t->current_state == TASK_ACTIVE) ||
(mode == THUMB_MODE_TOOLTIP_WINDOW && g_tooltip.mapped && g_tooltip.area == &t->area)) { (mode == THUMB_MODE_TOOLTIP_WINDOW && g_tooltip.mapped && g_tooltip.area == &t->area)) {
task_refresh_thumbnail(t); task_refresh_thumbnail(t);
if (mode == THUMB_MODE_ALL) if (mode == THUMB_MODE_ALL)

View File

@@ -215,7 +215,7 @@ void draw_taskbarname(void *obj, cairo_t *c)
cairo_set_source_rgba(c, config_text->rgb[0], config_text->rgb[1], config_text->rgb[2], config_text->alpha); cairo_set_source_rgba(c, config_text->rgb[0], config_text->rgb[1], config_text->rgb[2], config_text->alpha);
pango_cairo_update_layout(c, layout); pango_cairo_update_layout(c, layout);
draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel *)taskbar_name->area.panel)->font_shadow); draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel *)taskbar_name->area.panel)->font_shadow ? layout : NULL);
g_object_unref(layout); g_object_unref(layout);
g_object_unref(context); g_object_unref(context);

12
src/tint2-send/Makefile Normal file
View File

@@ -0,0 +1,12 @@
ifeq ($(PREFIX),)
PREFIX := /usr/local
endif
tint2-send: tint2-send.c
$(CC) tint2-send.c -lX11 -o tint2-send
install: tint2-send
install -m 755 tint2-send $(DESTDIR)/$(PREFIX)/bin/
clean:
rm -f tint2-send

128
src/tint2-send/tint2-send.c Normal file
View File

@@ -0,0 +1,128 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static Display *display = 0;
/* From wmctrl */
char *get_property(Window window, Atom xa_prop_type, const char *prop_name) {
Atom xa_prop_name = XInternAtom(display, prop_name, False);
Atom xa_ret_type;
int ret_format;
unsigned long ret_nitems;
unsigned long ret_bytes_after;
unsigned long tmp_size;
unsigned char *ret_prop;
if (XGetWindowProperty(display, window, xa_prop_name, 0, 1024,
False, xa_prop_type, &xa_ret_type, &ret_format,
&ret_nitems, &ret_bytes_after, &ret_prop) != Success) {
return NULL;
}
if (xa_ret_type != xa_prop_type) {
XFree(ret_prop);
return NULL;
}
/* Correct 64 Architecture implementation of 32 bit data */
tmp_size = (ret_format / 8) * ret_nitems;
if (ret_format == 32)
tmp_size *= sizeof(long) / 4;
char *ret = (char *)calloc(1, tmp_size + 1);
memcpy(ret, ret_prop, tmp_size);
XFree(ret_prop);
return ret;
}
int is_tint2(Window window)
{
XWindowAttributes attr = {};
if (!XGetWindowAttributes(display, window, &attr))
return 0;
if (attr.map_state != IsViewable)
return 0;
char *wm_class = get_property(window, XA_STRING, "WM_NAME");
if (!wm_class) {
return 0;
}
int class_match = 0;
if (strcmp(wm_class, "tint2") == 0) {
class_match = 1;
}
free(wm_class);
return class_match;
}
void handle_tint2_window(Window window, void *arg)
{
if (!is_tint2(window))
return;
char *action = (char *)arg;
if (strcmp(action, "show") == 0) {
fprintf(stderr, "Showing tint2 window: %lx\n", window);
XEvent event = {};
event.xcrossing.type = EnterNotify;
event.xcrossing.window = window;
event.xcrossing.mode = NotifyNormal;
event.xcrossing.detail = NotifyVirtual;
event.xcrossing.same_screen = True;
XSendEvent(display, window, False, 0, &event);
XFlush(display);
} else if (strcmp(action, "hide") == 0) {
fprintf(stderr, "Hiding tint2 window: %lx\n", window);
XEvent event = {};
event.xcrossing.type = LeaveNotify;
event.xcrossing.window = window;
event.xcrossing.mode = NotifyNormal;
event.xcrossing.detail = NotifyVirtual;
event.xcrossing.same_screen = True;
XSendEvent(display, window, False, 0, &event);
XFlush(display);
} else {
fprintf(stderr, "Error: unknown action %s\n", action);
}
}
typedef void window_callback_t(Window window, void *arg);
void walk_windows(Window node, window_callback_t *callback, void *arg)
{
callback(node, arg);
Window root = 0;
Window parent = 0;
Window *children = 0;
unsigned int nchildren = 0;
if (!XQueryTree(display, node,
&root, &parent, &children, &nchildren)) {
return;
}
for (unsigned int i = 0; i < nchildren; i++) {
walk_windows(children[i], callback, arg);
}
}
int main(int argc, char **argv)
{
display = XOpenDisplay(NULL);
if (!display ) {
fprintf(stderr, "Failed to open X11 connection\n");
exit(1);
}
argc--, argv++;
if (!argc) {
fprintf(stderr, "Usage: tint2-show [show|hide]\n");
exit(1);
}
char *action = argv[0];
walk_windows(DefaultRootWindow(display), handle_tint2_window, action);
return 0;
}

View File

@@ -7,7 +7,7 @@ pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 ) pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
pkg_check_modules( IMLIB2 REQUIRED imlib2 ) pkg_check_modules( IMLIB2 REQUIRED imlib2 )
pkg_check_modules( GTHREAD2 REQUIRED gthread-2.0 ) pkg_check_modules( GTHREAD2 REQUIRED gthread-2.0 )
pkg_check_modules( GTK2 REQUIRED gtk+-x11-2.0 ) pkg_check_modules( GTK3 REQUIRED gtk+-x11-3.0 )
pkg_check_modules( RSVG librsvg-2.0>=2.36.0 ) pkg_check_modules( RSVG librsvg-2.0>=2.36.0 )
include_directories( ../util include_directories( ../util
@@ -16,7 +16,7 @@ include_directories( ../util
${GOBJECT2_INCLUDE_DIRS} ${GOBJECT2_INCLUDE_DIRS}
${IMLIB2_INCLUDE_DIRS} ${IMLIB2_INCLUDE_DIRS}
${GTHREAD2_INCLUDE_DIRS} ${GTHREAD2_INCLUDE_DIRS}
${GTK2_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS}
${RSVG_INCLUDE_DIRS} ) ${RSVG_INCLUDE_DIRS} )
set(SOURCES ../util/common.c set(SOURCES ../util/common.c
@@ -55,7 +55,7 @@ link_directories( ${X11_T2C_LIBRARY_DIRS}
${GOBJECT2_LIBRARY_DIRS} ${GOBJECT2_LIBRARY_DIRS}
${IMLIB2_LIBRARY_DIRS} ${IMLIB2_LIBRARY_DIRS}
${GTHREAD2_LIBRARY_DIRS} ${GTHREAD2_LIBRARY_DIRS}
${GTK2_LIBRARY_DIRS} ${GTK3_LIBRARY_DIRS}
${RSVG_LIBRARY_DIRS} ) ${RSVG_LIBRARY_DIRS} )
add_executable( tint2conf ${SOURCES} ) add_executable( tint2conf ${SOURCES} )
target_link_libraries( tint2conf ${X11_T2C_LIBRARIES} target_link_libraries( tint2conf ${X11_T2C_LIBRARIES}
@@ -63,13 +63,14 @@ target_link_libraries( tint2conf ${X11_T2C_LIBRARIES}
${GOBJECT2_LIBRARIES} ${GOBJECT2_LIBRARIES}
${IMLIB2_LIBRARIES} ${IMLIB2_LIBRARIES}
${GTHREAD2_LIBRARIES} ${GTHREAD2_LIBRARIES}
${GTK2_LIBRARIES} ${GTK3_LIBRARIES}
${RSVG_LIBRARIES} ) ${RSVG_LIBRARIES} )
add_definitions( -DINSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\" ) add_definitions( -DINSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\" )
add_definitions( -DLOCALEDIR=\"${CMAKE_INSTALL_FULL_LOCALEDIR}\" ) add_definitions( -DLOCALEDIR=\"${CMAKE_INSTALL_FULL_LOCALEDIR}\" )
add_definitions( -DGETTEXT_PACKAGE=\"tint2conf\" ) add_definitions( -DGETTEXT_PACKAGE=\"tint2conf\" )
set_target_properties( tint2conf PROPERTIES COMPILE_FLAGS "-Wall -pthread -std=c99" ) add_definitions( -DDGLIB_DISABLE_DEPRECATION_WARNINGS=1 )
set_target_properties( tint2conf PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=c99 -Werror-implicit-function-declaration -Wno-deprecated -Wno-deprecated-declarations" )
set_target_properties( tint2conf PROPERTIES LINK_FLAGS "-pthread" ) set_target_properties( tint2conf PROPERTIES LINK_FLAGS "-pthread" )
add_subdirectory(po) add_subdirectory(po)

View File

@@ -95,7 +95,7 @@ void create_background(GtkWidget *parent)
backgrounds = gtk_list_store_new(bgNumCols, backgrounds = gtk_list_store_new(bgNumCols,
GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF,
GDK_TYPE_COLOR, GDK_TYPE_COLOR,
GTK_TYPE_INT, GTK_TYPE_SHADOW_TYPE,
GDK_TYPE_COLOR, GDK_TYPE_COLOR,
GTK_TYPE_INT, GTK_TYPE_INT,
GTK_TYPE_INT, GTK_TYPE_INT,
@@ -121,7 +121,6 @@ void create_background(GtkWidget *parent)
GtkWidget *table, *label, *button; GtkWidget *table, *label, *button;
int row, col; int row, col;
GtkTooltips *tooltips = gtk_tooltips_new();
table = gtk_table_new(1, 4, FALSE); table = gtk_table_new(1, 4, FALSE);
gtk_widget_show(table); gtk_widget_show(table);
@@ -141,21 +140,21 @@ void create_background(GtkWidget *parent)
gtk_widget_show(current_background); gtk_widget_show(current_background);
gtk_table_attach(GTK_TABLE(table), current_background, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), current_background, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, current_background, _("Selects the background you would like to modify"), NULL); gtk_widget_set_tooltip_text(current_background, _("Selects the background you would like to modify"));
button = gtk_button_new_from_stock("gtk-add"); button = gtk_button_new_from_stock("gtk-add");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(background_duplicate), NULL); g_signal_connect(button, "clicked", G_CALLBACK(background_duplicate), NULL);
gtk_widget_show(button); gtk_widget_show(button);
gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, button, _("Creates a copy of the current background"), NULL); gtk_widget_set_tooltip_text(button, _("Creates a copy of the current background"));
button = gtk_button_new_from_stock("gtk-remove"); button = gtk_button_new_from_stock("gtk-remove");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(background_delete), NULL); g_signal_connect(button, "clicked", G_CALLBACK(background_delete), NULL);
gtk_widget_show(button); gtk_widget_show(button);
gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, button, _("Deletes the current background"), NULL); gtk_widget_set_tooltip_text(button, _("Deletes the current background"));
table = gtk_table_new(4, 4, FALSE); table = gtk_table_new(4, 4, FALSE);
gtk_widget_show(table); gtk_widget_show(table);
@@ -175,7 +174,7 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_fill_color); gtk_widget_show(background_fill_color);
gtk_table_attach(GTK_TABLE(table), background_fill_color, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_fill_color, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, background_fill_color, _("The fill color of the current background"), NULL); gtk_widget_set_tooltip_text(background_fill_color, _("The fill color of the current background"));
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Fill tint")); label = gtk_label_new(_("Fill tint"));
@@ -188,7 +187,7 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_fill_content_tint_weight); gtk_widget_show(background_fill_content_tint_weight);
gtk_table_attach(GTK_TABLE(table), background_fill_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_fill_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, background_fill_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL); gtk_widget_set_tooltip_text(background_fill_content_tint_weight, _("How much the border color should be tinted with the content color"));
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Border color")); label = gtk_label_new(_("Border color"));
@@ -202,7 +201,7 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_border_color); gtk_widget_show(background_border_color);
gtk_table_attach(GTK_TABLE(table), background_border_color, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_border_color, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, background_border_color, _("The border color of the current background"), NULL); gtk_widget_set_tooltip_text(background_border_color, _("The border color of the current background"));
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Border tint")); label = gtk_label_new(_("Border tint"));
@@ -215,7 +214,7 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_border_content_tint_weight); gtk_widget_show(background_border_content_tint_weight);
gtk_table_attach(GTK_TABLE(table), background_border_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_border_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, background_border_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL); gtk_widget_set_tooltip_text(background_border_content_tint_weight, _("How much the border color should be tinted with the content color"));
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Gradient")); label = gtk_label_new(_("Gradient"));
@@ -241,10 +240,8 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_fill_color_over); gtk_widget_show(background_fill_color_over);
gtk_table_attach(GTK_TABLE(table), background_fill_color_over, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_fill_color_over, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, gtk_widget_set_tooltip_text(background_fill_color_over,
background_fill_color_over, _("The fill color of the current background on mouse over"));
_("The fill color of the current background on mouse over"),
NULL);
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Border color (mouse over)")); label = gtk_label_new(_("Border color (mouse over)"));
@@ -258,10 +255,9 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_border_color_over); gtk_widget_show(background_border_color_over);
gtk_table_attach(GTK_TABLE(table), background_border_color_over, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_border_color_over, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, gtk_widget_set_tooltip_text(
background_border_color_over, background_border_color_over,
_("The border color of the current background on mouse over"), _("The border color of the current background on mouse over"));
NULL);
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Gradient (mouse over)")); label = gtk_label_new(_("Gradient (mouse over)"));
@@ -287,10 +283,8 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_fill_color_press); gtk_widget_show(background_fill_color_press);
gtk_table_attach(GTK_TABLE(table), background_fill_color_press, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_fill_color_press, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, gtk_widget_set_tooltip_text(background_fill_color_press,
background_fill_color_press, _("The fill color of the current background on mouse button press"));
_("The fill color of the current background on mouse button press"),
NULL);
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Border color (pressed)")); label = gtk_label_new(_("Border color (pressed)"));
@@ -304,10 +298,8 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_border_color_press); gtk_widget_show(background_border_color_press);
gtk_table_attach(GTK_TABLE(table), background_border_color_press, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_border_color_press, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, gtk_widget_set_tooltip_text(background_border_color_press,
background_border_color_press, _("The border color of the current background on mouse button press"));
_("The border color of the current background on mouse button press"),
NULL);
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Gradient (pressed)")); label = gtk_label_new(_("Gradient (pressed)"));
@@ -332,10 +324,8 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_border_width); gtk_widget_show(background_border_width);
gtk_table_attach(GTK_TABLE(table), background_border_width, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_border_width, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, gtk_widget_set_tooltip_text(background_border_width,
background_border_width, _("The width of the border of the current background, in pixels"));
_("The width of the border of the current background, in pixels"),
NULL);
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Corner radius")); label = gtk_label_new(_("Corner radius"));
@@ -348,7 +338,7 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_corner_radius); gtk_widget_show(background_corner_radius);
gtk_table_attach(GTK_TABLE(table), background_corner_radius, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), background_corner_radius, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_tooltips_set_tip(tooltips, background_corner_radius, _("The corner radius of the current background"), NULL); gtk_widget_set_tooltip_text(background_corner_radius, _("The corner radius of the current background"));
row++; row++;
col = 2; col = 2;
@@ -712,9 +702,8 @@ void background_update_image(int index)
g_boxed_free(GDK_TYPE_COLOR, fillColor); g_boxed_free(GDK_TYPE_COLOR, fillColor);
g_boxed_free(GDK_TYPE_COLOR, borderColor); g_boxed_free(GDK_TYPE_COLOR, borderColor);
GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24); cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
cairo_t *cr = cairo_create(s);
cairo_t *cr = gdk_cairo_create(pixmap);
cairo_set_line_width(cr, b); cairo_set_line_width(cr, b);
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
@@ -744,13 +733,12 @@ void background_update_image(int index)
cairo_destroy(cr); cairo_destroy(cr);
cr = NULL; cr = NULL;
pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, gdk_colormap_get_system(), 0, 0, 0, 0, w, h); pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, w, h);
if (pixmap)
g_object_unref(pixmap);
gtk_list_store_set(backgrounds, &iter, bgColPixbuf, pixbuf, -1); gtk_list_store_set(backgrounds, &iter, bgColPixbuf, pixbuf, -1);
if (pixbuf) if (pixbuf)
g_object_unref(pixbuf); g_object_unref(pixbuf);
cairo_surface_destroy(s);
} }
void background_force_update() void background_force_update()

View File

@@ -32,7 +32,7 @@ GtkWidget *create_gradient_combo()
void create_gradient(GtkWidget *parent) void create_gradient(GtkWidget *parent)
{ {
gradient_ids = gtk_list_store_new(grNumCols, GDK_TYPE_PIXBUF, GTK_TYPE_INT, GTK_TYPE_STRING); gradient_ids = gtk_list_store_new(grNumCols, GDK_TYPE_PIXBUF, G_TYPE_INT, G_TYPE_STRING);
gradients = NULL; gradients = NULL;
gradient_stop_ids = gtk_list_store_new(grStopNumCols, GDK_TYPE_PIXBUF); gradient_stop_ids = gtk_list_store_new(grStopNumCols, GDK_TYPE_PIXBUF);
@@ -61,13 +61,13 @@ void create_gradient(GtkWidget *parent)
col++; col++;
button = gtk_button_new_from_stock("gtk-add"); button = gtk_button_new_from_stock("gtk-add");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_duplicate), NULL); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_duplicate), NULL);
gtk_widget_show(button); gtk_widget_show(button);
gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
button = gtk_button_new_from_stock("gtk-remove"); button = gtk_button_new_from_stock("gtk-remove");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_delete), NULL); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_delete), NULL);
gtk_widget_show(button); gtk_widget_show(button);
gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
@@ -85,13 +85,13 @@ void create_gradient(GtkWidget *parent)
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gradient_combo_type = gtk_combo_box_new_text(); gradient_combo_type = gtk_combo_box_text_new();
gtk_widget_show(gradient_combo_type); gtk_widget_show(gradient_combo_type);
gtk_table_attach(GTK_TABLE(table), gradient_combo_type, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), gradient_combo_type, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
gtk_combo_box_append_text(GTK_COMBO_BOX(gradient_combo_type), _("Vertical")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gradient_combo_type), _("Vertical"));
gtk_combo_box_append_text(GTK_COMBO_BOX(gradient_combo_type), _("Horizontal")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gradient_combo_type), _("Horizontal"));
gtk_combo_box_append_text(GTK_COMBO_BOX(gradient_combo_type), _("Radial")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gradient_combo_type), _("Radial"));
gtk_combo_box_set_active(GTK_COMBO_BOX(gradient_combo_type), 0); gtk_combo_box_set_active(GTK_COMBO_BOX(gradient_combo_type), 0);
row++, col = 2; row++, col = 2;
@@ -142,13 +142,13 @@ void create_gradient(GtkWidget *parent)
col++; col++;
button = gtk_button_new_from_stock("gtk-add"); button = gtk_button_new_from_stock("gtk-add");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_stop_duplicate), NULL); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_stop_duplicate), NULL);
gtk_widget_show(button); gtk_widget_show(button);
gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
button = gtk_button_new_from_stock("gtk-remove"); button = gtk_button_new_from_stock("gtk-remove");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_stop_delete), NULL); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_stop_delete), NULL);
gtk_widget_show(button); gtk_widget_show(button);
gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++; col++;
@@ -327,18 +327,17 @@ void gradient_update_image(int index)
int w = 70; int w = 70;
int h = 30; int h = 30;
GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24); cairo_surface_t *pixmap = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
cairo_t *cr = gdk_cairo_create(pixmap); cairo_t *cr = cairo_create(pixmap);
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
cairo_rectangle(cr, 0, 0, w, h); cairo_rectangle(cr, 0, 0, w, h);
cairo_fill(cr); cairo_fill(cr);
gradient_draw(cr, g, w, h, FALSE); gradient_draw(cr, g, w, h, FALSE);
GdkPixbuf *pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, gdk_colormap_get_system(), 0, 0, 0, 0, w, h); GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(pixmap, 0, 0, w, h);
if (pixmap) cairo_surface_destroy(pixmap);
g_object_unref(pixmap);
GtkTreePath *path; GtkTreePath *path;
GtkTreeIter iter; GtkTreeIter iter;
@@ -528,16 +527,14 @@ void gradient_stop_update_image(int index)
int w = 70; int w = 70;
int h = 30; int h = 30;
GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24); cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
cairo_t *cr = cairo_create(s);
cairo_t *cr = gdk_cairo_create(pixmap);
cairo_set_source_rgba(cr, stop->color.rgb[0], stop->color.rgb[1], stop->color.rgb[2], stop->color.alpha); cairo_set_source_rgba(cr, stop->color.rgb[0], stop->color.rgb[1], stop->color.rgb[2], stop->color.alpha);
cairo_rectangle(cr, 0, 0, w, h); cairo_rectangle(cr, 0, 0, w, h);
cairo_fill(cr); cairo_fill(cr);
GdkPixbuf *pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, gdk_colormap_get_system(), 0, 0, 0, 0, w, h); GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, w, h);
if (pixmap) cairo_surface_destroy(s);
g_object_unref(pixmap);
GtkTreePath *path; GtkTreePath *path;
GtkTreeIter iter; GtkTreeIter iter;

View File

@@ -383,6 +383,11 @@ static void menuAbout()
// ====== Theme import/copy/delete ====== // ====== Theme import/copy/delete ======
static void free_data(gpointer data, gpointer userdata)
{
g_free(data);
}
// Shows open dialog and copies the selected files to ~ without overwrite. // Shows open dialog and copies the selected files to ~ without overwrite.
static void menuImportFile() static void menuImportFile()
{ {
@@ -407,7 +412,7 @@ static void menuImportFile()
gchar *newpath = import_no_overwrite(l->data); gchar *newpath = import_no_overwrite(l->data);
g_free(newpath); g_free(newpath);
} }
g_slist_foreach(list, (GFunc)g_free, NULL); g_slist_foreach(list, free_data, NULL);
g_slist_free(list); g_slist_free(list);
gtk_widget_destroy(dialog); gtk_widget_destroy(dialog);
} }

View File

@@ -14,6 +14,27 @@
#define GETTEXT_PACKAGE "tint2conf" #define GETTEXT_PACKAGE "tint2conf"
#endif #endif
#ifndef GTK_TYPE_INT
#define GTK_TYPE_INT G_TYPE_INT
#endif
#ifndef GTK_TYPE_STRING
#define GTK_TYPE_STRING G_TYPE_STRING
#endif
#ifndef GTK_TYPE_BOOL
#define GTK_TYPE_BOOL G_TYPE_BOOLEAN
#endif
#ifndef GTK_TYPE_DOUBLE
#define GTK_TYPE_DOUBLE G_TYPE_DOUBLE
#endif
#define gtk_tooltips_set_tip(t, widget, txt, arg) gtk_widget_set_tooltip_text(widget, txt)
#define GTK_OBJECT(x) (x)
#define GTK_SIGNAL_FUNC G_CALLBACK
#define SNAPSHOT_TICK 190 #define SNAPSHOT_TICK 190
gboolean update_snapshot(gpointer ignored); gboolean update_snapshot(gpointer ignored);
void menuApply(); void menuApply();

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

File diff suppressed because it is too large Load Diff

View File

@@ -12,8 +12,8 @@
extern GtkWidget *scale_relative_to_dpi, *scale_relative_to_screen_height; 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_pivot_struts, *panel_autohide, *panel_autohide_show_time,
*panel_autohide_size; *panel_autohide_hide_time, *panel_autohide_size;
extern GtkWidget *panel_combo_strut_policy, *panel_combo_layer, *panel_combo_width_type, *panel_combo_height_type, extern GtkWidget *panel_combo_strut_policy, *panel_combo_layer, *panel_combo_width_type, *panel_combo_height_type,
*panel_combo_monitor; *panel_combo_monitor;
extern GtkWidget *panel_window_name, *disable_transparency; extern GtkWidget *panel_window_name, *disable_transparency;
@@ -133,7 +133,7 @@ typedef struct Executor {
GtkWidget *page_execp; GtkWidget *page_execp;
GtkWidget *page_label; GtkWidget *page_label;
GtkWidget *execp_command, *execp_interval, *execp_has_icon, *execp_cache_icon, *execp_show_tooltip; GtkWidget *execp_command, *execp_interval, *execp_has_icon, *execp_cache_icon, *execp_show_tooltip;
GtkWidget *execp_continuous, *execp_markup, *execp_tooltip; GtkWidget *execp_continuous, *execp_markup, *execp_tooltip, *execp_monitor;
GtkWidget *execp_left_command, *execp_right_command; GtkWidget *execp_left_command, *execp_right_command;
GtkWidget *execp_mclick_command, *execp_rclick_command, *execp_uwheel_command, *execp_dwheel_command; GtkWidget *execp_mclick_command, *execp_rclick_command, *execp_uwheel_command, *execp_dwheel_command;
GtkWidget *execp_font, *execp_font_set, *execp_font_color, *execp_padding_x, *execp_padding_y, *execp_centered; GtkWidget *execp_font, *execp_font_set, *execp_font_color, *execp_padding_x, *execp_padding_y, *execp_centered;

View File

@@ -295,6 +295,7 @@ void config_write_panel(FILE *fp)
fprintf(fp, "panel_background_id = %d\n", gtk_combo_box_get_active(GTK_COMBO_BOX(panel_background))); fprintf(fp, "panel_background_id = %d\n", gtk_combo_box_get_active(GTK_COMBO_BOX(panel_background)));
fprintf(fp, "wm_menu = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel_wm_menu)) ? 1 : 0); fprintf(fp, "wm_menu = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel_wm_menu)) ? 1 : 0);
fprintf(fp, "panel_dock = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel_dock)) ? 1 : 0); fprintf(fp, "panel_dock = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel_dock)) ? 1 : 0);
fprintf(fp, "panel_pivot_struts = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel_pivot_struts)) ? 1 : 0);
fprintf(fp, "panel_position = "); fprintf(fp, "panel_position = ");
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(screen_position[POS_BLH]))) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(screen_position[POS_BLH]))) {
@@ -870,6 +871,16 @@ void config_write_execp(FILE *fp)
fprintf(fp, fprintf(fp,
"execp_markup = %d\n", "execp_markup = %d\n",
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(executor->execp_markup)) ? 1 : 0); gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(executor->execp_markup)) ? 1 : 0);
fprintf(fp, "execp_monitor = ");
if (gtk_combo_box_get_active(GTK_COMBO_BOX(executor->execp_monitor)) <= 0) {
fprintf(fp, "all");
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(executor->execp_monitor)) == 1) {
fprintf(fp, "primary");
} else {
fprintf(fp, "%d", MAX(1, gtk_combo_box_get_active(GTK_COMBO_BOX(executor->execp_monitor)) - 1));
}
fprintf(fp, "\n");
if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(executor->execp_show_tooltip))) { if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(executor->execp_show_tooltip))) {
fprintf(fp, "execp_tooltip = \n"); fprintf(fp, "execp_tooltip = \n");
} else { } else {
@@ -1384,6 +1395,8 @@ void add_entry(char *key, char *value)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel_wm_menu), atoi(value)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel_wm_menu), atoi(value));
} else if (strcmp(key, "panel_dock") == 0) { } else if (strcmp(key, "panel_dock") == 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel_dock), atoi(value)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel_dock), atoi(value));
} else if (strcmp(key, "panel_pivot_struts") == 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel_pivot_struts), atoi(value));
} else if (strcmp(key, "panel_layer") == 0) { } else if (strcmp(key, "panel_layer") == 0) {
if (strcmp(value, "bottom") == 0) if (strcmp(value, "bottom") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(panel_combo_layer), 2); gtk_combo_box_set_active(GTK_COMBO_BOX(panel_combo_layer), 2);
@@ -1852,10 +1865,12 @@ void add_entry(char *key, char *value)
} else if (strcmp(key, "launcher_apps_dir") == 0) { } else if (strcmp(key, "launcher_apps_dir") == 0) {
char *path = expand_tilde(value); char *path = expand_tilde(value);
if (gtk_entry_get_text_length(GTK_ENTRY(launcher_apps_dirs)) > 0) { int position = gtk_entry_get_text_length(GTK_ENTRY(launcher_apps_dirs));
gtk_entry_append_text(GTK_ENTRY(launcher_apps_dirs), ","); if (position > 0) {
gtk_editable_insert_text(GTK_EDITABLE(launcher_apps_dirs), ",", 1, &position);
} }
gtk_entry_append_text(GTK_ENTRY(launcher_apps_dirs), path); position = gtk_entry_get_text_length(GTK_ENTRY(launcher_apps_dirs));
gtk_editable_insert_text(GTK_EDITABLE(launcher_apps_dirs), path, strlen(path), &position);
free(path); free(path);
} else if (strcmp(key, "launcher_icon_theme") == 0) { } else if (strcmp(key, "launcher_icon_theme") == 0) {
@@ -1959,6 +1974,23 @@ void add_entry(char *key, char *value)
gtk_spin_button_set_value(GTK_SPIN_BUTTON(execp_get_last()->execp_continuous), atoi(value)); gtk_spin_button_set_value(GTK_SPIN_BUTTON(execp_get_last()->execp_continuous), atoi(value));
} else if (strcmp(key, "execp_markup") == 0) { } else if (strcmp(key, "execp_markup") == 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execp_get_last()->execp_markup), atoi(value)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execp_get_last()->execp_markup), atoi(value));
} else if (strcmp(key, "execp_monitor") == 0) {
if (strcmp(value, "all") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 0);
else if (strcmp(value, "primary") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 1);
else if (strcmp(value, "1") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 2);
else if (strcmp(value, "2") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 3);
else if (strcmp(value, "3") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 4);
else if (strcmp(value, "4") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 5);
else if (strcmp(value, "5") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 6);
else if (strcmp(value, "6") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(execp_get_last()->execp_monitor), 7);
} else if (strcmp(key, "execp_tooltip") == 0) { } else if (strcmp(key, "execp_tooltip") == 0) {
if (strlen(value) > 0) { if (strlen(value) > 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execp_get_last()->execp_show_tooltip), 1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execp_get_last()->execp_show_tooltip), 1);

View File

@@ -1084,7 +1084,7 @@ void draw_text_area(Area *area,
pango_layout_set_font_description(layout, line1_font_desc); pango_layout_set_font_description(layout, line1_font_desc);
pango_layout_set_text(layout, line1, strlen(line1)); pango_layout_set_text(layout, line1, strlen(line1));
pango_cairo_update_layout(c, layout); pango_cairo_update_layout(c, layout);
draw_text(layout, c, (area->width - inner_w) / 2, line1_posy, color, ((Panel *)area->panel)->font_shadow); draw_text(layout, c, (area->width - inner_w) / 2, line1_posy, color, ((Panel *)area->panel)->font_shadow ? layout : NULL);
} }
if (line2 && line2[0]) { if (line2 && line2[0]) {
@@ -1092,7 +1092,7 @@ void draw_text_area(Area *area,
pango_layout_set_indent(layout, 0); pango_layout_set_indent(layout, 0);
pango_layout_set_text(layout, line2, strlen(line2)); pango_layout_set_text(layout, line2, strlen(line2));
pango_cairo_update_layout(c, layout); pango_cairo_update_layout(c, layout);
draw_text(layout, c, (area->width - inner_w) / 2, line2_posy, color, ((Panel *)area->panel)->font_shadow); draw_text(layout, c, (area->width - inner_w) / 2, line2_posy, color, ((Panel *)area->panel)->font_shadow ? layout : NULL);
} }
g_object_unref(layout); g_object_unref(layout);

View File

@@ -362,8 +362,12 @@ pid_t tint_exec(const char *command,
// Allow children to exist after parent destruction // Allow children to exist after parent destruction
setsid(); setsid();
// Run the command // Run the command
if (dir) if (dir) {
chdir(dir); int ret = chdir(dir);
if (ret != 0) {
fprintf(stderr, "tint2: failed to chdir to %s\n", dir);
}
}
close_all_fds(); close_all_fds();
reset_signals(); reset_signals();
if (terminal) { if (terminal) {
@@ -724,9 +728,37 @@ void render_image(Drawable d, int x, int y)
XFreePixmap(server.display, pixmap); XFreePixmap(server.display, pixmap);
} }
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow) gboolean is_color_attribute(PangoAttribute *attr, gpointer user_data)
{
return attr->klass->type == PANGO_ATTR_FOREGROUND ||
attr->klass->type == PANGO_ATTR_BACKGROUND ||
attr->klass->type == PANGO_ATTR_UNDERLINE_COLOR ||
attr->klass->type == PANGO_ATTR_STRIKETHROUGH_COLOR ||
attr->klass->type == PANGO_ATTR_FOREGROUND_ALPHA ||
attr->klass->type == PANGO_ATTR_BACKGROUND_ALPHA;
}
gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup)
{
PangoAttrList *attrs = NULL;
char *text = NULL;
GError *error = NULL;
if (!pango_parse_markup(markup, -1, 0, &attrs, &text, NULL, &error)) {
g_error_free(error);
return FALSE;
}
pango_layout_set_text(layout, text, -1);
g_free(text);
pango_attr_list_filter(attrs, is_color_attribute, NULL);
pango_layout_set_attributes(layout, attrs);
pango_attr_list_unref(attrs);
return TRUE;
}
void draw_shadow(cairo_t *c, int posx, int posy, PangoLayout *shadow_layout)
{ {
if (font_shadow) {
const int shadow_size = 3; const int shadow_size = 3;
const double shadow_edge_alpha = 0.0; const double shadow_edge_alpha = 0.0;
int i, j; int i, j;
@@ -739,12 +771,17 @@ void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color
1.0 - 1.0 -
(1.0 - shadow_edge_alpha) * (1.0 - shadow_edge_alpha) *
sqrt((i * i + j * j) / (double)(shadow_size * shadow_size))); sqrt((i * i + j * j) / (double)(shadow_size * shadow_size)));
pango_cairo_update_layout(c, layout); pango_cairo_update_layout(c, shadow_layout);
cairo_move_to(c, posx + i, posy + j); cairo_move_to(c, posx + i, posy + j);
pango_cairo_show_layout(c, layout); pango_cairo_show_layout(c, shadow_layout);
} }
} }
} }
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, PangoLayout *shadow_layout)
{
if (shadow_layout)
draw_shadow(c, posx, posy, shadow_layout);
cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha); cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha);
pango_cairo_update_layout(c, layout); pango_cairo_update_layout(c, layout);
cairo_move_to(c, posx, posy); cairo_move_to(c, posx, posy);
@@ -757,8 +794,8 @@ Imlib_Image load_image(const char *path, int cached)
static unsigned long counter = 0; static unsigned long counter = 0;
if (debug_icons) if (debug_icons)
fprintf(stderr, "tint2: loading icon %s\n", path); fprintf(stderr, "tint2: loading icon %s\n", path);
#ifdef HAVE_RSVG
image = imlib_load_image(path); image = imlib_load_image(path);
#ifdef HAVE_RSVG
if (!image && g_str_has_suffix(path, ".svg")) { if (!image && g_str_has_suffix(path, ".svg")) {
char tmp_filename[128]; char tmp_filename[128];
snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d-%lu.png", (int)getpid(), counter); snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d-%lu.png", (int)getpid(), counter);
@@ -788,11 +825,8 @@ Imlib_Image load_image(const char *path, int cached)
unlink(tmp_filename); unlink(tmp_filename);
} }
} }
} else
#endif
{
image = imlib_load_image(path);
} }
#endif
imlib_context_set_image(image); imlib_context_set_image(image);
imlib_image_set_changes_on_disk(); imlib_image_set_changes_on_disk();
return image; return image;

View File

@@ -126,7 +126,8 @@ void get_text_size2(const PangoFontDescription *font,
gboolean markup, gboolean markup,
double scale); double scale);
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow); gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup);
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, PangoLayout *shadow_layout);
// Draws a rounded rectangle // Draws a rounded rectangle
void draw_rect(cairo_t *c, double x, double y, double w, double h, double r); void draw_rect(cairo_t *c, double x, double y, double w, double h, double r);

View File

@@ -36,8 +36,9 @@
Server server; Server server;
void server_catch_error(Display *d, XErrorEvent *ev) int server_catch_error(Display *d, XErrorEvent *ev)
{ {
return 0;
} }
void server_init_atoms() void server_init_atoms()
@@ -676,9 +677,10 @@ void handle_crash(const char *reason)
#endif #endif
} }
void x11_io_error(Display *display) int x11_io_error(Display *display)
{ {
handle_crash("X11 I/O error"); handle_crash("X11 I/O error");
return 0;
} }
#ifdef HAVE_SN #ifdef HAVE_SN

View File

@@ -164,12 +164,12 @@ void send_event32(Window win, Atom at, long data1, long data2, long data3);
int get_property32(Window win, Atom at, Atom type); int get_property32(Window win, Atom at, Atom type);
void *server_get_property(Window win, Atom at, Atom type, int *num_results); void *server_get_property(Window win, Atom at, Atom type, int *num_results);
Atom server_get_atom(char *atom_name); Atom server_get_atom(char *atom_name);
void server_catch_error(Display *d, XErrorEvent *ev); int server_catch_error(Display *d, XErrorEvent *ev);
void server_init_atoms(); void server_init_atoms();
void server_init_visual(); void server_init_visual();
void server_init_xdamage(); void server_init_xdamage();
void x11_io_error(Display *display); int x11_io_error(Display *display);
void handle_crash(const char *reason); void handle_crash(const char *reason);
// detect root background // detect root background

View File

@@ -85,7 +85,6 @@ static void sigchld_handler(int sig)
int savedErrno = errno; int savedErrno = errno;
ssize_t unused = write(sigchild_pipe[1], "x", 1); ssize_t unused = write(sigchild_pipe[1], "x", 1);
(void)unused; (void)unused;
fsync(sigchild_pipe[1]);
errno = savedErrno; errno = savedErrno;
} }

View File

@@ -25,6 +25,7 @@
#include "timer.h" #include "timer.h"
#include "test.h" #include "test.h"
bool warnings_for_timers = true;
bool debug_timers = false; bool debug_timers = false;
#define MOCK_ORIGIN 1000000 #define MOCK_ORIGIN 1000000
@@ -59,7 +60,7 @@ void init_timer(Timer *timer, const char *name)
void destroy_timer(Timer *timer) void destroy_timer(Timer *timer)
{ {
if (!g_list_find(timers, timer)) { if (warnings_for_timers && !g_list_find(timers, timer)) {
fprintf(stderr, RED "tint2: Attempt to destroy nonexisting timer: %s" RESET "\n", timer->name_); fprintf(stderr, RED "tint2: Attempt to destroy nonexisting timer: %s" RESET "\n", timer->name_);
return; return;
} }
@@ -130,7 +131,8 @@ struct timeval *get_duration_to_next_timer_expiration()
next_timer->expiration_time_ms_, next_timer->expiration_time_ms_,
next_timer->period_ms_); next_timer->period_ms_);
result.tv_sec = duration / 1000; result.tv_sec = duration / 1000;
result.tv_usec = 1000 * (duration - result.tv_sec); duration -= result.tv_sec * 1000;
result.tv_usec = 1000 * duration;
return &result; return &result;
} }

View File

@@ -23,6 +23,7 @@
#include <sys/time.h> #include <sys/time.h>
#include "bool.h" #include "bool.h"
extern bool warnings_for_timers;
extern bool debug_timers; extern bool debug_timers;
typedef void TimerCallback(void *arg); typedef void TimerCallback(void *arg);

View File

@@ -169,31 +169,40 @@ int get_window_desktop(Window win)
return best_match; return best_match;
} }
#define swap(a, b) do { __typeof__(a) _tmp = (a); (a) = (b); (b) = _tmp; } while(0)
int get_interval_overlap(int a1, int a2, int b1, int b2)
{
if (a1 > b1) {
swap(a1, b1);
swap(a2, b2);
}
if (b1 <= a2)
return a2 - b1;
return 0;
}
int get_window_monitor(Window win) int get_window_monitor(Window win)
{ {
int x, y, w, h; int x, y, w, h;
get_window_coordinates(win, &x, &y, &w, &h); get_window_coordinates(win, &x, &y, &w, &h);
int best_match = -1; int best_match = 0;
int match_right = 0; int best_area = -1;
int match_bottom = 0;
// There is an ambiguity when a window is right on the edge between screens.
// In that case, prefer the monitor which is on the right and bottom of the window's top-left corner.
for (int i = 0; i < server.num_monitors; i++) { for (int i = 0; i < server.num_monitors; i++) {
if (x >= server.monitors[i].x && x <= (server.monitors[i].x + server.monitors[i].width) && int commonx = get_interval_overlap(x, x + w, server.monitors[i].x, server.monitors[i].x + server.monitors[i].width);
y >= server.monitors[i].y && y <= (server.monitors[i].y + server.monitors[i].height)) { int commony = get_interval_overlap(y, y + h, server.monitors[i].y, server.monitors[i].y + server.monitors[i].height);
int current_right = x < (server.monitors[i].x + server.monitors[i].width); int area = commonx * commony;
int current_bottom = y < (server.monitors[i].y + server.monitors[i].height); if (0)
if (best_match < 0 || (!match_right && current_right) || (!match_bottom && current_bottom)) { printf("Monitor %d (%dx%d+%dx%d): win (%dx%d+%dx%d) area %dx%d=%d\n",
i, server.monitors[i].x, server.monitors[i].y, server.monitors[i].width, server.monitors[i].height,
x, y, w, h,
commonx, commony, area);
if (area > best_area) {
best_area = area;
best_match = i; best_match = i;
} }
} }
}
if (best_match < 0)
best_match = 0;
// fprintf(stderr, "tint2: desktop %d, window %lx %s : monitor %d, (%d, %d)\n", 1 + get_current_desktop(), win,
// get_task(win) ? get_task(win)->title : "??", best_match+1, x, y);
return best_match; return best_match;
} }
@@ -371,7 +380,7 @@ void smooth_thumbnail(cairo_surface_t *image_surface)
const size_t rmask = 0xff0000; const size_t rmask = 0xff0000;
const size_t gmask = 0xff00; const size_t gmask = 0xff00;
const size_t bmask = 0xff; const size_t bmask = 0xff;
for (size_t i = 0; i < tw * (th - 1) - 1; i++) { for (size_t i = 0; i < tw * (th - 1) - 1 && i < tw * th; i++) {
u_int32_t c1 = data[i]; u_int32_t c1 = data[i];
u_int32_t c2 = data[i + 1]; u_int32_t c2 = data[i + 1];
u_int32_t c3 = data[i + tw]; u_int32_t c3 = data[i + tw];
@@ -390,13 +399,27 @@ void smooth_thumbnail(cairo_surface_t *image_surface)
cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm) cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm)
{ {
cairo_surface_t *result = NULL; cairo_surface_t *result = NULL;
XWindowAttributes wa; XWindowAttributes wa = {};
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 || if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 ||
wa.map_state != IsViewable) wa.map_state != IsViewable) {
if (debug_thumbnails) {
fprintf(stderr, "tint2: could not get thumbnail, invalid geometry %d x %d\n",
wa.width, wa.height);
}
goto err0; goto err0;
}
if (window_is_iconified(win)) if (window_is_iconified(win)) {
if (debug_thumbnails) {
fprintf(stderr, "tint2: could not get thumbnail, minimized window\n");
}
goto err0; goto err0;
}
if (debug_thumbnails) {
fprintf(stderr, "tint2: getting thumbnail for window with size %d x %d\n",
wa.width, wa.height);
}
size_t w, h; size_t w, h;
w = (size_t)wa.width; w = (size_t)wa.width;
@@ -414,6 +437,20 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
fw = tw; fw = tw;
ox = oy = 0; ox = oy = 0;
} }
if (debug_thumbnails) {
fprintf(stderr,
"tint2: thumbnail size %zu x %zu, "
"proportional width %zu, offset %zu\n",
tw, th, fw, ox);
}
if (!w || !h || !tw || !th || !fw) {
if (debug_thumbnails) {
fprintf(stderr, "tint2: could not get thumbnail, invalid thumbnail size: "
"%zu x %zu => %zu x %zu, %zu\n",
w, h, tw, th, fw);
}
goto err0;
}
XShmSegmentInfo shminfo; XShmSegmentInfo shminfo;
XImage *ximg; XImage *ximg;
@@ -443,7 +480,7 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
goto err1; goto err1;
} }
shminfo.shmaddr = ximg->data = (char *)shmat(shminfo.shmid, 0, 0); shminfo.shmaddr = ximg->data = (char *)shmat(shminfo.shmid, 0, 0);
if (!shminfo.shmaddr) { if (shminfo.shmaddr == (void*)-1) {
fprintf(stderr, RED "tint2: !shmat" RESET "\n"); fprintf(stderr, RED "tint2: !shmat" RESET "\n");
goto err2; goto err2;
} }
@@ -459,8 +496,18 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
} }
XGetWindowAttributes(server.display, win, &wa); XGetWindowAttributes(server.display, win, &wa);
if (wa.map_state != IsViewable) if (wa.map_state != IsViewable) {
if (debug_thumbnails) {
fprintf(stderr, "tint2: could not get thumbnail, window not viewable\n");
}
goto err4; goto err4;
}
if (debug_thumbnails) {
fprintf(stderr,
"tint2: creating cairo surface with size %zu x %zu = %zu px\n",
tw, th, tw * th);
}
result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, (int)tw, (int)th); result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, (int)tw, (int)th);
u_int32_t *data = (u_int32_t *)cairo_image_surface_get_data(result); u_int32_t *data = (u_int32_t *)cairo_image_surface_get_data(result);
@@ -498,6 +545,7 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
for (size_t yt = 0, y = 0; yt < th; yt++, y += ystep) { for (size_t yt = 0, y = 0; yt < th; yt++, y += ystep) {
for (size_t xt = 0, x = 0; xt < fw; xt++, x += xstep) { for (size_t xt = 0, x = 0; xt < fw; xt++, x += xstep) {
size_t j = yt * tw + ox + xt; size_t j = yt * tw + ox + xt;
if (j < tw * th) {
u_int32_t c1 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x1) / prec), (int)((y + offset_y1) / prec)); u_int32_t c1 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x1) / prec), (int)((y + offset_y1) / prec));
u_int32_t c2 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x2) / prec), (int)((y + offset_y2) / prec)); u_int32_t c2 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x2) / prec), (int)((y + offset_y2) / prec));
u_int32_t c3 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x3) / prec), (int)((y + offset_y3) / prec)); u_int32_t c3 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x3) / prec), (int)((y + offset_y3) / prec));
@@ -517,6 +565,7 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
data[j] = (r & rmask) | (g & gmask) | (b & bmask); data[j] = (r & rmask) | (g & gmask) | (b & bmask);
} }
} }
}
// Convert to argb32 // Convert to argb32
if (rmask & 0xff0000) { if (rmask & 0xff0000) {
// argb32 or rgb24 => Nothing to do // argb32 or rgb24 => Nothing to do
@@ -540,6 +589,7 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
// 2nd pass // 2nd pass
smooth_thumbnail(result); smooth_thumbnail(result);
cairo_surface_mark_dirty(result);
if (ximg) { if (ximg) {
XDestroyImage(ximg); XDestroyImage(ximg);
@@ -573,11 +623,12 @@ gboolean cairo_surface_is_blank(cairo_surface_t *image_surface)
return empty; return empty;
} }
gboolean thumb_use_shm = FALSE;
cairo_surface_t *get_window_thumbnail(Window win, int size) cairo_surface_t *get_window_thumbnail(Window win, int size)
{ {
cairo_surface_t *image_surface = NULL; cairo_surface_t *image_surface = NULL;
const gboolean shm_allowed = FALSE; if (thumb_use_shm && server.has_shm && server.composite_manager) {
if (shm_allowed && server.has_shm && server.composite_manager) {
image_surface = get_window_thumbnail_ximage(win, (size_t)size, TRUE); image_surface = get_window_thumbnail_ximage(win, (size_t)size, TRUE);
if (image_surface && cairo_surface_is_blank(image_surface)) { if (image_surface && cairo_surface_is_blank(image_surface)) {
cairo_surface_destroy(image_surface); cairo_surface_destroy(image_surface);

View File

@@ -22,7 +22,7 @@
/usr/include/librsvg-2.0 /usr/include/librsvg-2.0
/usr/include/gdk-pixbuf-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/include/gtk-3.0
/usr/lib/x86_64-linux-gnu/gtk-2.0/include /usr/lib/x86_64-linux-gnu/gtk-2.0/include
/usr/include/atk-1.0 /usr/include/atk-1.0
/usr/include/gio-unix-2.0 /usr/include/gio-unix-2.0