Compare commits

..

36 Commits

Author SHA1 Message Date
76751355e0 Update src/systray/systraybar.c
https://pastebin.com/UxDTv4ML
2026-05-06 21:43:03 +00:00
Chris Lee
f3aa2ef0c6 freeze code 2022-01-31 18:01:29 +00:00
Chris Lee
60734e0151 changelog for new feature 2021-12-12 02:38:23 +01:00
Chris
646dc4cb46 Merge branch 'refresh-execp-more' into 'master'
Completed refresh-execp

See merge request o9000/tint2!46
2021-12-12 01:29:15 +00:00
Arash Rohani
57dff2aad3 Completed refresh-execp 2021-12-12 01:29:15 +00:00
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
43 changed files with 4552 additions and 4123 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

@@ -35,6 +35,7 @@ Contributors:
heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color
Fabian Carlström : taskbar sort order by app name
Chris Billington (https://gitlab.com/chrisjbillington) : panel struts pivoting
Arash Rohani <rohani.arash@pm.me> : helped with execp refresh
Translations:
Bosnian:

View File

@@ -286,7 +286,11 @@ 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 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-send DESTINATION bin )
install( FILES tint2.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps )
install( FILES tint2.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )
install( FILES themes/tint2rc DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/xdg/tint2 )

View File

@@ -1,3 +1,24 @@
2021-12-11 master
- Enhancements:
- Added command to refresh executors (issue #747)
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)
@@ -1031,3 +1052,4 @@ released tint-0.2
.
.
.
.

View File

@@ -1,5 +1,9 @@
# Latest stable release: 16.7
Changes: https://gitlab.com/o9000/tint2/blob/16.7/ChangeLog
# Latest stable release: 17.0.2
The final release of tint2 is 17.0.2.
The code is frozen and no more feature requests are accepted.
Changes: https://gitlab.com/o9000/tint2/blob/17.0.2/ChangeLog
Documentation: [doc/tint2.md](doc/tint2.md)
@@ -8,7 +12,7 @@ Compile it with (after you install the [dependencies](https://gitlab.com/o9000/t
```
git clone https://gitlab.com/o9000/tint2.git
cd tint2
git checkout 16.7
git checkout 17.0.2
mkdir build
cd build
cmake ..

View File

@@ -595,6 +595,7 @@ panel_size = 94% 30
<h3 id="executor">Executor<a name="executor" href="#executor" class="md2man-permalink" title="permalink"></a></h3>
<ul>
<li><p><code>execp = new</code> : Begins the configuration of a new executor plugin. Multiple such plugins are supported; just use multiple <code>E</code>s in <code>panel_items</code>. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_name = text</code> : A name that can be used with <code>tint2-send refresh-execp</code> to re-execute the command.</p></li>
<li><p><code>execp_command = text</code> : Command to execute. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_interval = integer</code> : The command is executed again after <code>execp_interval</code> seconds from the moment it exits. If zero, the command is executed only once. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_continuous = integer</code> : If non-zero, the last <code>execp_continuous</code> lines from the output of the command are displayed, every <code>execp_continuous</code> lines; this is useful for showing the output of commands that run indefinitely, such as <code>ping 127.0.0.1</code>. If zero, the output of the command is displayed after it finishes executing. <em>(since 0.12.4)</em></p></li>
@@ -609,6 +610,7 @@ 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_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_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_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>
@@ -647,13 +649,13 @@ execp_command = ping -i 1 -c 1 -W 1 -O -D -n $(ip route | grep default | grep vi
execp_continuous = 0
execp_interval = 1
execp_markup = 1
</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>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></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># Note the use of "stdbuf -oL" to force the program to flush the output line by line.
</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.
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_interval = 1
</code></pre></div><h3 id="button">Button<a name="button" href="#button" class="md2man-permalink" title="permalink"></a></h3>

View File

@@ -199,9 +199,9 @@ pre {
</style>
</head>
<body>
<h1 id="latest-stable-release-16-7"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.7</span><a name="latest-stable-release-16-7" href="#latest-stable-release-16-7" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.7/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.7/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
<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
git checkout 16.7
git checkout 17.0.2
mkdir build
cd build
cmake ..

View File

@@ -1,4 +1,4 @@
.TH TINT2 1 "2019\-07\-14" 16.7
.TH TINT2 1 "2021\-12\-04" 17.0.2
.SH NAME
.PP
tint2 \- lightweight panel/taskbar
@@ -720,6 +720,8 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
.IP \(bu 2
\fB\fCexecp = new\fR : Begins the configuration of a new executor plugin. Multiple such plugins are supported; just use multiple \fB\fCE\fRs in \fB\fCpanel_items\fR\&. \fI(since 0.12.4)\fP
.IP \(bu 2
\fB\fCexecp_name = text\fR : A name that can be used with \fB\fCtint2\-send refresh\-execp\fR to re\-execute the command.
.IP \(bu 2
\fB\fCexecp_command = text\fR : Command to execute. \fI(since 0.12.4)\fP
.IP \(bu 2
\fB\fCexecp_interval = integer\fR : The command is executed again after \fB\fCexecp_interval\fR seconds from the moment it exits. If zero, the command is executed only once. \fI(since 0.12.4)\fP
@@ -748,6 +750,8 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
.IP \(bu 2
\fB\fCexecp_padding = horizontal_padding vertical_padding spacing_between_icon_and_text\fR \fI(since 0.12.4)\fP
.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
.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
@@ -831,19 +835,19 @@ execp_markup = 1
.PP
.RS
.nf
# Note the use of "stdbuf \-oL" to force the program to flush the output line by line.
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
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
.fi
.RE
.SS Network load
.PP
.RS
.nf
# Note the use of "stdbuf \-oL" to force the program to flush the output line by line.
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_interval = 1
.fi

View File

@@ -314,6 +314,7 @@ panel_size = 94% 30
<h3 id="executor">Executor<a name="executor" href="#executor" class="md2man-permalink" title="permalink"></a></h3>
<ul>
<li><p><code>execp = new</code> : Begins the configuration of a new executor plugin. Multiple such plugins are supported; just use multiple <code>E</code>s in <code>panel_items</code>. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_name = text</code> : A name that can be used with <code>tint2-send refresh-execp</code> to re-execute the command.</p></li>
<li><p><code>execp_command = text</code> : Command to execute. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_interval = integer</code> : The command is executed again after <code>execp_interval</code> seconds from the moment it exits. If zero, the command is executed only once. <em>(since 0.12.4)</em></p></li>
<li><p><code>execp_continuous = integer</code> : If non-zero, the last <code>execp_continuous</code> lines from the output of the command are displayed, every <code>execp_continuous</code> lines; this is useful for showing the output of commands that run indefinitely, such as <code>ping 127.0.0.1</code>. If zero, the output of the command is displayed after it finishes executing. <em>(since 0.12.4)</em></p></li>
@@ -372,14 +373,14 @@ execp_continuous = 1
execp_interval = 1
execp_markup = 1
</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
execp_command = free -s 2 | awk '/^-/ { printf "Mem: '$(free -h | awk '/^Mem:/ { print $2 }')' %.0f%\n", 100*$3/($3+$4); fflush(stdout) }'
<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 = 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_continuous = 1
</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_command = stdbuf -oL bwm-ng -o csv -t 1000 | awk -F ';' '/total/ { printf "Net: %.0f Mb/s\n", ($5*8/1.0e6) }; fflush(stdout)'
<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_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_interval = 1
</code></pre>

View File

@@ -1,4 +1,4 @@
# TINT2 1 "2019-07-14" 16.7
# TINT2 1 "2021-12-04" 17.0.2
## NAME
tint2 - lightweight panel/taskbar
@@ -593,6 +593,8 @@ The action semantics:
* `execp = new` : Begins the configuration of a new executor plugin. Multiple such plugins are supported; just use multiple `E`s in `panel_items`. *(since 0.12.4)*
* `execp_name = text` : A name that can be used with `tint2-send refresh-execp` to re-execute the command.
* `execp_command = text` : Command to execute. *(since 0.12.4)*
* `execp_interval = integer` : The command is executed again after `execp_interval` seconds from the moment it exits. If zero, the command is executed only once. *(since 0.12.4)*
@@ -621,6 +623,8 @@ The action semantics:
* `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_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)*
@@ -694,18 +698,18 @@ execp_markup = 1
##### Memory usage
```
# Note the use of "stdbuf -oL" to force the program to flush the output line by line.
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
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
```
##### Network load
```
# Note the use of "stdbuf -oL" to force the program to flush the output line by line.
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_interval = 1
```

View File

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

View File

@@ -129,17 +129,28 @@ 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()
{
if (time1_format)
strftime(buf_time, sizeof(buf_time), time1_format, clock_gettime_for_tz(time1_timezone));
if (time2_format)
strftime(buf_date, sizeof(buf_date), time2_format, clock_gettime_for_tz(time2_timezone));
if (time1_format || time2_format) {
bool changed = false;
update_clock_text(buf_time, sizeof(buf_time), time1_format, time1_timezone, &changed);
update_clock_text(buf_date, sizeof(buf_date), time2_format, time2_timezone, &changed);
if (changed) {
for (int i = 0; i < num_panels; i++)
panels[i].clock.area.resize_needed = 1;
schedule_panel_redraw();
}
schedule_panel_redraw();
}
int ms_until_second_change(struct timeval* tm)
@@ -157,33 +168,6 @@ void update_clocks_sec(void *arg)
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, 'c') ||
strchr(time_format, 'r') ||
strchr(time_format, 's') ||
strchr(time_format, 'S') ||
strchr(time_format, 'T') ||
strchr(time_format, 'X') ||
strchr(time_format, '+'))
return TRUE;
return FALSE;
}
void init_clock()
{
}
@@ -222,11 +206,7 @@ void init_clock_panel(void *p)
}
if (!clock_timer.enabled_) {
if (time_format_needs_sec_ticks(time1_format) || time_format_needs_sec_ticks(time2_format)) {
update_clocks_sec(NULL);
} else {
update_clocks_min(NULL);
}
update_clocks_sec(NULL);
}
}

View File

@@ -683,6 +683,14 @@ void add_entry(char *key, char *value)
/* Execp */
else if (strcmp(key, "execp") == 0) {
panel_config.execp_list = g_list_append(panel_config.execp_list, create_execp());
} else if (strcmp(key, "execp_name") == 0) {
Execp *execp = get_or_create_last_execp();
execp->backend->name[0] = 0;
if (strlen(value) > sizeof(execp->backend->name) - 1)
fprintf(stderr, RED "tint2: execp_name cannot be more than %ld bytes: '%s'" RESET "\n",
sizeof(execp->backend->name) - 1, value);
else if (strlen(value) > 0)
snprintf(execp->backend->name, sizeof(execp->backend->name), value);
} else if (strcmp(key, "execp_command") == 0) {
Execp *execp = get_or_create_last_execp();
free_and_null(execp->backend->command);
@@ -697,6 +705,9 @@ void add_entry(char *key, char *value)
} else {
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) {
Execp *execp = get_or_create_last_execp();
execp->backend->has_icon = atoi(value);

View File

@@ -43,13 +43,36 @@ Execp *create_execp()
execp->backend->cache_icon = TRUE;
execp->backend->centered = TRUE;
execp->backend->font_color.alpha = 0.5;
execp->backend->monitor = -1;
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;
}
gpointer create_execp_frontend(gconstpointer arg, gpointer data)
{
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_frontend->backend = execp_backend->backend;
@@ -67,7 +90,11 @@ void destroy_execp(void *obj)
free_and_null(execp->frontend);
remove_area(&execp->area);
free_area(&execp->area);
free_and_null(execp);
if (execp->dummy) {
destroy_execp(execp);
} else {
free_and_null(execp);
}
} else {
// This is a backend element
destroy_timer(&execp->backend->timer);
@@ -144,12 +171,6 @@ void init_execp()
// Set missing config options
if (!execp->backend->bg)
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
// 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) {
Execp *execp = l->data;

View File

@@ -20,10 +20,12 @@ extern bool debug_executors;
typedef struct ExecpBackend {
// Config:
char name[21];
// Command to execute at a specified interval
char *command;
// Interval in seconds
int interval;
int monitor;
// 1 if first line of output is an icon path
gboolean has_icon;
gboolean cache_icon;
@@ -96,6 +98,7 @@ typedef struct Execp {
ExecpBackend *backend;
// Set only for frontend Execp items.
ExecpFrontend *frontend;
bool dummy;
} Execp;
// Called before the config is read and panel_config/panels are created.
@@ -152,4 +155,6 @@ void execp_default_font_changed();
void handle_execp_events();
void execp_force_update(Execp *execp);
#endif // EXECPLUGIN_H

View File

@@ -32,7 +32,6 @@
#include <X11/extensions/Xdamage.h>
#include <Imlib2.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <time.h>
@@ -389,9 +388,9 @@ gboolean handle_x_event_autohide(XEvent *e)
Panel *panel = get_panel(e->xany.window);
if (panel && panel_autohide) {
if (e->type == EnterNotify)
autohide_trigger_show(panel);
autohide_trigger_show(panel, e->xany.send_event);
else if (e->type == LeaveNotify)
autohide_trigger_hide(panel);
autohide_trigger_hide(panel, e->xany.send_event);
if (panel->is_hidden) {
if (e->type == ClientMessage && e->xclient.message_type == server.atom.XdndPosition) {
hidden_panel_shown_for_dnd = TRUE;
@@ -545,6 +544,17 @@ void handle_x_event(XEvent *e)
handle_dnd_position(&e->xclient);
} else if (e->xclient.message_type == server.atom.XdndDrop) {
handle_dnd_drop(&e->xclient);
} else if (e->xclient.message_type == server.atom.TINT2_REFRESH_EXECP &&
e->xclient.format == 8) {
char name[sizeof(e->xclient.data.b) + 1] = {};
memcpy(name, e->xclient.data.b, sizeof(e->xclient.data.b));
for (GList *l = panel_config.execp_list; l; l = l->next) {
Execp *execp = (Execp *)l->data;
if (strncmp(name, execp->backend->name, sizeof(execp->backend->name) - 1) == 0) {
fprintf(stderr, "tint2: Refreshing executor: %s\n", name);
execp_force_update(execp);
}
}
}
break;
}

View File

@@ -269,8 +269,9 @@ void init_panel()
init_freespace_panel(p);
if (panel_items_order[k] == ':')
init_separator_panel(p);
if (panel_items_order[k] == 'E')
if (panel_items_order[k] == 'E') {
init_execp_panel(p);
}
if (panel_items_order[k] == 'P')
init_button_panel(p);
}
@@ -316,7 +317,7 @@ void init_panel()
}
if (panel_autohide)
autohide_trigger_hide(p);
autohide_trigger_hide(p, false);
}
taskbar_refresh_tasklist();
@@ -1139,26 +1140,27 @@ void autohide_hide(void *p)
schedule_panel_redraw();
}
void autohide_trigger_show(Panel *p)
void autohide_trigger_show(Panel *p, bool forced)
{
if (!p)
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)
return;
Window root, child;
int xr, yr, xw, yw;
unsigned int mask;
if (XQueryPointer(server.display, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask))
if (child)
return; // mouse over one of the system tray icons
change_timer(&p->autohide_timer, true, panel_autohide_hide_timeout, 0, autohide_hide, p);
if (!forced) {
Window root, child;
int xr, yr, xw, yw;
unsigned int mask;
if (XQueryPointer(server.display, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask))
if (child)
return; // mouse over one of the system tray icons
}
change_timer(&p->autohide_timer, true, forced ? 0 : panel_autohide_hide_timeout, 0, autohide_hide, p);
}
void shrink_panel(Panel *panel)

View File

@@ -203,8 +203,8 @@ Button *click_button(Panel *panel, int x, int y);
void autohide_show(void *p);
void autohide_hide(void *p);
void autohide_trigger_show(Panel *p);
void autohide_trigger_hide(Panel *p);
void autohide_trigger_show(Panel *p, bool forced);
void autohide_trigger_hide(Panel *p, bool forced);
const char *get_default_font();

View File

@@ -292,9 +292,10 @@ void on_change_systray(void *obj)
}
TrayWindow *traywin;
GSList *l;
GSList *l, *next;
int i;
for (i = 1, l = systray.list_icons; l; i++, l = l->next) {
for (i = 1, l = systray.list_icons; l; i++, l = next) {
next = l->next;
traywin = (TrayWindow *)l->data;
traywin->y = posy;

View File

@@ -312,10 +312,16 @@ Imlib_Image task_get_icon(Window win, int icon_size)
int w, h;
gulong *tmp_data = get_best_icon(data, get_icon_count(data, len), len, &w, &h, icon_size);
if (tmp_data) {
DATA32 icon_data[w * h];
for (int j = 0; j < w * h; ++j)
icon_data[j] = tmp_data[j];
img = imlib_create_image_using_copied_data(w, h, icon_data);
int array_size = w * h;
// 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];
img = imlib_create_image_using_copied_data(w, h, icon_data);
g_free(icon_data);
}
}
}
XFree(data);

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

@@ -0,0 +1,152 @@
#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, char *action, char **args)
{
if (!is_tint2(window))
return;
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 if (strcmp(action, "refresh-execp") == 0) {
XEvent event = {};
char *name = args[0];
if (!name) {
fprintf(stderr, "Error: missing execp name\n");
return;
}
if (!name[0]) {
fprintf(stderr, "Error: empty execp name\n");
return;
}
if (strlen(name) > sizeof(event.xclient.data.b)) {
fprintf(stderr, "Error: execp name bigger than %ld bytes\n", sizeof(event.xclient.data.b));
return;
}
fprintf(stderr, "Refreshing execp '%s' for window: %lx\n", name, window);
event.xclient.type = ClientMessage;
event.xclient.window = window;
event.xclient.send_event = True;
event.xclient.message_type = XInternAtom(display, "_TINT2_REFRESH_EXECP", False);
event.xclient.format = 8;
strncpy(event.xclient.data.b, name, sizeof(event.xclient.data.b));
XSendEvent(display, window, False, 0, &event);
XFlush(display);
} else {
fprintf(stderr, "Error: unknown action %s\n", action);
}
}
typedef void window_callback_t(Window window, char *action, char **args);
void walk_windows(Window node, window_callback_t *callback, char *action, char **args)
{
callback(node, action, args);
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, action, args);
}
}
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-send [show|hide|refresh-execp]\n");
exit(1);
}
char *action = argv[0];
char **args = argv + 1;
walk_windows(DefaultRootWindow(display), handle_tint2_window, action, args);
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( IMLIB2 REQUIRED imlib2 )
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 )
include_directories( ../util
@@ -16,7 +16,7 @@ include_directories( ../util
${GOBJECT2_INCLUDE_DIRS}
${IMLIB2_INCLUDE_DIRS}
${GTHREAD2_INCLUDE_DIRS}
${GTK2_INCLUDE_DIRS}
${GTK3_INCLUDE_DIRS}
${RSVG_INCLUDE_DIRS} )
set(SOURCES ../util/common.c
@@ -55,7 +55,7 @@ link_directories( ${X11_T2C_LIBRARY_DIRS}
${GOBJECT2_LIBRARY_DIRS}
${IMLIB2_LIBRARY_DIRS}
${GTHREAD2_LIBRARY_DIRS}
${GTK2_LIBRARY_DIRS}
${GTK3_LIBRARY_DIRS}
${RSVG_LIBRARY_DIRS} )
add_executable( tint2conf ${SOURCES} )
target_link_libraries( tint2conf ${X11_T2C_LIBRARIES}
@@ -63,13 +63,14 @@ target_link_libraries( tint2conf ${X11_T2C_LIBRARIES}
${GOBJECT2_LIBRARIES}
${IMLIB2_LIBRARIES}
${GTHREAD2_LIBRARIES}
${GTK2_LIBRARIES}
${GTK3_LIBRARIES}
${RSVG_LIBRARIES} )
add_definitions( -DINSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\" )
add_definitions( -DLOCALEDIR=\"${CMAKE_INSTALL_FULL_LOCALEDIR}\" )
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" )
add_subdirectory(po)

View File

@@ -95,7 +95,7 @@ void create_background(GtkWidget *parent)
backgrounds = gtk_list_store_new(bgNumCols,
GDK_TYPE_PIXBUF,
GDK_TYPE_COLOR,
GTK_TYPE_INT,
GTK_TYPE_SHADOW_TYPE,
GDK_TYPE_COLOR,
GTK_TYPE_INT,
GTK_TYPE_INT,
@@ -121,7 +121,6 @@ void create_background(GtkWidget *parent)
GtkWidget *table, *label, *button;
int row, col;
GtkTooltips *tooltips = gtk_tooltips_new();
table = gtk_table_new(1, 4, FALSE);
gtk_widget_show(table);
@@ -141,21 +140,21 @@ void create_background(GtkWidget *parent)
gtk_widget_show(current_background);
gtk_table_attach(GTK_TABLE(table), current_background, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
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");
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_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
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");
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_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
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);
gtk_widget_show(table);
@@ -175,7 +174,7 @@ void create_background(GtkWidget *parent)
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);
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;
label = gtk_label_new(_("Fill tint"));
@@ -188,7 +187,7 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_fill_content_tint_weight);
gtk_table_attach(GTK_TABLE(table), background_fill_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips, background_fill_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL);
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;
label = gtk_label_new(_("Border color"));
@@ -202,7 +201,7 @@ void create_background(GtkWidget *parent)
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);
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;
label = gtk_label_new(_("Border tint"));
@@ -215,7 +214,7 @@ void create_background(GtkWidget *parent)
gtk_widget_show(background_border_content_tint_weight);
gtk_table_attach(GTK_TABLE(table), background_border_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips, background_border_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL);
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;
label = gtk_label_new(_("Gradient"));
@@ -241,10 +240,8 @@ void create_background(GtkWidget *parent)
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);
col++;
gtk_tooltips_set_tip(tooltips,
background_fill_color_over,
_("The fill color of the current background on mouse over"),
NULL);
gtk_widget_set_tooltip_text(background_fill_color_over,
_("The fill color of the current background on mouse over"));
row++, col = 2;
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_table_attach(GTK_TABLE(table), background_border_color_over, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips,
gtk_widget_set_tooltip_text(
background_border_color_over,
_("The border color of the current background on mouse over"),
NULL);
_("The border color of the current background on mouse over"));
row++, col = 2;
label = gtk_label_new(_("Gradient (mouse over)"));
@@ -287,10 +283,8 @@ void create_background(GtkWidget *parent)
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);
col++;
gtk_tooltips_set_tip(tooltips,
background_fill_color_press,
_("The fill color of the current background on mouse button press"),
NULL);
gtk_widget_set_tooltip_text(background_fill_color_press,
_("The fill color of the current background on mouse button press"));
row++, col = 2;
label = gtk_label_new(_("Border color (pressed)"));
@@ -304,10 +298,8 @@ void create_background(GtkWidget *parent)
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);
col++;
gtk_tooltips_set_tip(tooltips,
background_border_color_press,
_("The border color of the current background on mouse button press"),
NULL);
gtk_widget_set_tooltip_text(background_border_color_press,
_("The border color of the current background on mouse button press"));
row++, col = 2;
label = gtk_label_new(_("Gradient (pressed)"));
@@ -332,10 +324,8 @@ void create_background(GtkWidget *parent)
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);
col++;
gtk_tooltips_set_tip(tooltips,
background_border_width,
_("The width of the border of the current background, in pixels"),
NULL);
gtk_widget_set_tooltip_text(background_border_width,
_("The width of the border of the current background, in pixels"));
row++, col = 2;
label = gtk_label_new(_("Corner radius"));
@@ -348,7 +338,7 @@ void create_background(GtkWidget *parent)
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);
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++;
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, borderColor);
GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24);
cairo_t *cr = gdk_cairo_create(pixmap);
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
cairo_t *cr = cairo_create(s);
cairo_set_line_width(cr, b);
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
@@ -744,13 +733,12 @@ void background_update_image(int index)
cairo_destroy(cr);
cr = NULL;
pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, gdk_colormap_get_system(), 0, 0, 0, 0, w, h);
if (pixmap)
g_object_unref(pixmap);
pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, w, h);
gtk_list_store_set(backgrounds, &iter, bgColPixbuf, pixbuf, -1);
if (pixbuf)
g_object_unref(pixbuf);
cairo_surface_destroy(s);
}
void background_force_update()

View File

@@ -32,7 +32,7 @@ GtkWidget *create_gradient_combo()
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;
gradient_stop_ids = gtk_list_store_new(grStopNumCols, GDK_TYPE_PIXBUF);
@@ -61,13 +61,13 @@ void create_gradient(GtkWidget *parent)
col++;
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_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
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_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
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);
col++;
gradient_combo_type = gtk_combo_box_new_text();
gradient_combo_type = gtk_combo_box_text_new();
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);
col++;
gtk_combo_box_append_text(GTK_COMBO_BOX(gradient_combo_type), _("Vertical"));
gtk_combo_box_append_text(GTK_COMBO_BOX(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), _("Vertical"));
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gradient_combo_type), _("Horizontal"));
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);
row++, col = 2;
@@ -142,13 +142,13 @@ void create_gradient(GtkWidget *parent)
col++;
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_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
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_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
col++;
@@ -327,18 +327,17 @@ void gradient_update_image(int index)
int w = 70;
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_rectangle(cr, 0, 0, w, h);
cairo_fill(cr);
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);
if (pixmap)
g_object_unref(pixmap);
GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(pixmap, 0, 0, w, h);
cairo_surface_destroy(pixmap);
GtkTreePath *path;
GtkTreeIter iter;
@@ -528,16 +527,14 @@ void gradient_stop_update_image(int index)
int w = 70;
int h = 30;
GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24);
cairo_t *cr = gdk_cairo_create(pixmap);
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
cairo_t *cr = cairo_create(s);
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_fill(cr);
GdkPixbuf *pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, gdk_colormap_get_system(), 0, 0, 0, 0, w, h);
if (pixmap)
g_object_unref(pixmap);
GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, w, h);
cairo_surface_destroy(s);
GtkTreePath *path;
GtkTreeIter iter;

View File

@@ -14,6 +14,27 @@
#define GETTEXT_PACKAGE "tint2conf"
#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
gboolean update_snapshot(gpointer ignored);
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

@@ -132,8 +132,9 @@ typedef struct Executor {
GtkWidget *container;
GtkWidget *page_execp;
GtkWidget *page_label;
GtkWidget *execp_name;
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_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;

View File

@@ -857,6 +857,7 @@ void config_write_execp(FILE *fp)
Executor *executor = &g_array_index(executors, Executor, i);
fprintf(fp, "execp = new\n");
fprintf(fp, "execp_name = %s\n", gtk_entry_get_text(GTK_ENTRY(executor->execp_name)));
fprintf(fp, "execp_command = %s\n", gtk_entry_get_text(GTK_ENTRY(executor->execp_command)));
fprintf(fp, "execp_interval = %d\n", (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(executor->execp_interval)));
fprintf(fp,
@@ -871,6 +872,16 @@ void config_write_execp(FILE *fp)
fprintf(fp,
"execp_markup = %d\n",
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))) {
fprintf(fp, "execp_tooltip = \n");
} else {
@@ -1855,10 +1866,12 @@ void add_entry(char *key, char *value)
} else if (strcmp(key, "launcher_apps_dir") == 0) {
char *path = expand_tilde(value);
if (gtk_entry_get_text_length(GTK_ENTRY(launcher_apps_dirs)) > 0) {
gtk_entry_append_text(GTK_ENTRY(launcher_apps_dirs), ",");
int position = gtk_entry_get_text_length(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);
} else if (strcmp(key, "launcher_icon_theme") == 0) {
@@ -1950,6 +1963,8 @@ void add_entry(char *key, char *value)
/* Executor */
else if (strcmp(key, "execp") == 0) {
execp_create_new();
} else if (strcmp(key, "execp_name") == 0) {
gtk_entry_set_text(GTK_ENTRY(execp_get_last()->execp_name), value);
} else if (strcmp(key, "execp_command") == 0) {
gtk_entry_set_text(GTK_ENTRY(execp_get_last()->execp_command), value);
} else if (strcmp(key, "execp_interval") == 0) {
@@ -1962,6 +1977,23 @@ void add_entry(char *key, char *value)
gtk_spin_button_set_value(GTK_SPIN_BUTTON(execp_get_last()->execp_continuous), atoi(value));
} else if (strcmp(key, "execp_markup") == 0) {
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) {
if (strlen(value) > 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(execp_get_last()->execp_show_tooltip), 1);

View File

@@ -794,8 +794,8 @@ Imlib_Image load_image(const char *path, int cached)
static unsigned long counter = 0;
if (debug_icons)
fprintf(stderr, "tint2: loading icon %s\n", path);
#ifdef HAVE_RSVG
image = imlib_load_image(path);
#ifdef HAVE_RSVG
if (!image && g_str_has_suffix(path, ".svg")) {
char tmp_filename[128];
snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d-%lu.png", (int)getpid(), counter);
@@ -825,11 +825,8 @@ Imlib_Image load_image(const char *path, int cached)
unlink(tmp_filename);
}
}
} else
#endif
{
image = imlib_load_image(path);
}
#endif
imlib_context_set_image(image);
imlib_image_set_changes_on_disk();
return image;

View File

@@ -122,6 +122,9 @@ void server_init_atoms()
server.atom.XdndActionCopy = XInternAtom(server.display, "XdndActionCopy", False);
server.atom.XdndFinished = XInternAtom(server.display, "XdndFinished", False);
server.atom.TARGETS = XInternAtom(server.display, "TARGETS", False);
// tint2 atoms
server.atom.TINT2_REFRESH_EXECP = XInternAtom(server.display, "_TINT2_REFRESH_EXECP", False);
}
const char *GetAtomName(Display *disp, Atom a)

View File

@@ -91,6 +91,7 @@ typedef struct Global_atom {
Atom XdndActionCopy;
Atom XdndFinished;
Atom TARGETS;
Atom TINT2_REFRESH_EXECP;
} Global_atom;
typedef struct Property {

View File

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

View File

@@ -131,7 +131,8 @@ struct timeval *get_duration_to_next_timer_expiration()
next_timer->expiration_time_ms_,
next_timer->period_ms_);
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;
}

View File

@@ -169,31 +169,40 @@ int get_window_desktop(Window win)
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 x, y, w, h;
get_window_coordinates(win, &x, &y, &w, &h);
int best_match = -1;
int match_right = 0;
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.
int best_match = 0;
int best_area = -1;
for (int i = 0; i < server.num_monitors; i++) {
if (x >= server.monitors[i].x && x <= (server.monitors[i].x + server.monitors[i].width) &&
y >= server.monitors[i].y && y <= (server.monitors[i].y + server.monitors[i].height)) {
int current_right = x < (server.monitors[i].x + server.monitors[i].width);
int current_bottom = y < (server.monitors[i].y + server.monitors[i].height);
if (best_match < 0 || (!match_right && current_right) || (!match_bottom && current_bottom)) {
best_match = i;
}
int commonx = get_interval_overlap(x, x + w, server.monitors[i].x, server.monitors[i].x + server.monitors[i].width);
int commony = get_interval_overlap(y, y + h, server.monitors[i].y, server.monitors[i].y + server.monitors[i].height);
int area = commonx * commony;
if (0)
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;
}
}
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;
}

View File

@@ -22,7 +22,7 @@
/usr/include/librsvg-2.0
/usr/include/gdk-pixbuf-2.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/include/atk-1.0
/usr/include/gio-unix-2.0