Compare commits
69
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36c8d41914 | ||
|
|
4dafea185f | ||
|
|
77890d463a | ||
|
|
e1211a929f | ||
|
|
00f0bbd354 | ||
|
|
15d2570a3e | ||
|
|
c76f056746 | ||
|
|
cacd4b8dad | ||
|
|
b539c0a1c0 | ||
|
|
970c597796 | ||
|
|
a82b9a1d7f | ||
|
|
89a6cadfcd | ||
|
|
fb9da655df | ||
|
|
cb137674e4 | ||
|
|
1054aac7ca | ||
|
|
81c7c65a9f | ||
|
|
044bad6c40 | ||
|
|
aaa0e40af7 | ||
|
|
34f9fcaca4 | ||
|
|
f8c6dc1ecc | ||
|
|
11c468816d | ||
|
|
595d04451b | ||
|
|
6681cfbca6 | ||
|
|
14074894f9 | ||
|
|
3fcbf58873 | ||
|
|
1c2a12eb05 | ||
|
|
ec5bda6ddf | ||
|
|
5875015c11 | ||
|
|
21e9303502 | ||
|
|
94d4a219ee | ||
|
|
8a7ba9bf50 | ||
|
|
ffa6e5ba49 | ||
|
|
d1f5a46a73 | ||
|
|
131704081c | ||
|
|
21466cc94e | ||
|
|
e06b63e1dc | ||
|
|
9a03b8b4e6 | ||
|
|
47bc01d608 | ||
|
|
0e4b3bd32e | ||
|
|
9ac0cd1254 | ||
|
|
73ab9b6930 | ||
|
|
96361ab1cd | ||
|
|
b9589450bb | ||
|
|
b810bad93f | ||
|
|
b85362b5c7 | ||
|
|
03675b152d | ||
|
|
c3fdd76b58 | ||
|
|
04ba5a6617 | ||
|
|
f5f8792d42 | ||
|
|
965a2665b0 | ||
|
|
b2b0119f4d | ||
|
|
41e49ef4e6 | ||
|
|
25dd623618 | ||
|
|
28b1174c0f | ||
|
|
b70edc437c | ||
|
|
bf58e16b83 | ||
|
|
3190c5b7de | ||
|
|
5db0dceec2 | ||
|
|
5c5f507e54 | ||
|
|
d301ada47a | ||
|
|
b3f9834313 | ||
|
|
c7b23ee94a | ||
|
|
12f04e3055 | ||
|
|
7f62594cf6 | ||
|
|
405c2c9286 | ||
|
|
90a445868c | ||
|
|
427afc61b5 | ||
|
|
ee92fac10e | ||
|
|
95eea350fe |
@@ -6,6 +6,7 @@ tint2 is developped by :
|
|||||||
- Ovidiu M <mrovi9000 at gmail.com> : launcher, bug fixes
|
- Ovidiu M <mrovi9000 at gmail.com> : launcher, bug fixes
|
||||||
- Mishael A Sibiryakov (death@junki.org) : freespace
|
- Mishael A Sibiryakov (death@junki.org) : freespace
|
||||||
- Sebastian Reichel <sre@ring0.de> : battery, various fixes, debian package maintainer
|
- Sebastian Reichel <sre@ring0.de> : battery, various fixes, debian package maintainer
|
||||||
|
- Chris Lee <chrlee at protonmail> : bug fixes, maintainer starting with v16.3
|
||||||
|
|
||||||
tint2 is based on the ttm source code (http://code.google.com/p/ttm/)
|
tint2 is based on the ttm source code (http://code.google.com/p/ttm/)
|
||||||
- 2007-2008 Pål Staurland <staura@gmail.com>
|
- 2007-2008 Pål Staurland <staura@gmail.com>
|
||||||
@@ -32,6 +33,7 @@ Contributors:
|
|||||||
Ryan Gray, Jeff Blake (https://gitlab.com/berkley4) : battery format
|
Ryan Gray, Jeff Blake (https://gitlab.com/berkley4) : battery format
|
||||||
aaaz (https://gitlab.com/aaaz) : clock fixes
|
aaaz (https://gitlab.com/aaaz) : clock fixes
|
||||||
heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color
|
heisenbug (https://gitlab.com/heisenbugh) : taskbar button tinting with icon color
|
||||||
|
Fabian Carlström : taskbar sort order by app name
|
||||||
|
|
||||||
Translations:
|
Translations:
|
||||||
Bosnian:
|
Bosnian:
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ set( SOURCES src/config.c
|
|||||||
src/separator/separator.c
|
src/separator/separator.c
|
||||||
src/tint2rc.c
|
src/tint2rc.c
|
||||||
src/util/area.c
|
src/util/area.c
|
||||||
|
src/util/bt.c
|
||||||
src/util/common.c
|
src/util/common.c
|
||||||
src/util/fps_distribution.c
|
src/util/fps_distribution.c
|
||||||
src/util/strnatcmp.c
|
src/util/strnatcmp.c
|
||||||
|
|||||||
@@ -1,3 +1,38 @@
|
|||||||
|
2019-02-17 master
|
||||||
|
- Fix spacing around icons in executor without text in vertical panels (issue #716)
|
||||||
|
- Fix Bug: Clock Only Updates Every Minute With Format %s (issue #724)
|
||||||
|
- Fix markup drawing when font shadow enabled (issue #709)
|
||||||
|
- Blink battery when low (issue #723)
|
||||||
|
|
||||||
|
2018-08-05 16.6.1
|
||||||
|
- Fix packaging regression for debian (issue #715)
|
||||||
|
|
||||||
|
2018-08-04 16.6
|
||||||
|
- Fix regression in task icon brightness (issue #714)
|
||||||
|
|
||||||
|
2018-08-04 16.5
|
||||||
|
- Add new build script
|
||||||
|
- Add option to sort taskbar by application name
|
||||||
|
- Fix regression in image loading
|
||||||
|
|
||||||
|
2018-05-03 16.4
|
||||||
|
- Update AUTHORS
|
||||||
|
- Fixes:
|
||||||
|
- Fix leak in image loading (issue #704)
|
||||||
|
- Executors no longer log unless env var DEBUG_EXECUTORS is set
|
||||||
|
|
||||||
|
2018-04-17 16.3
|
||||||
|
- Fixes:
|
||||||
|
- Layout in executor (issue #695)
|
||||||
|
- Other small issues
|
||||||
|
|
||||||
|
2018-01-21 16.2
|
||||||
|
- Fixes:
|
||||||
|
- Proper fix for issue #688
|
||||||
|
- Fix bad word wrapping (issue #693)
|
||||||
|
- Enhancements:
|
||||||
|
- Preliminary high DPI support
|
||||||
|
|
||||||
2017-12-30 16.1
|
2017-12-30 16.1
|
||||||
- Fixes:
|
- Fixes:
|
||||||
- Fixed several use-after-free errors in the timer code
|
- Fixed several use-after-free errors in the timer code
|
||||||
@@ -985,3 +1020,8 @@ released tint-0.2
|
|||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Latest stable release: 16.1
|
# Latest stable release: 16.6.1
|
||||||
Changes: https://gitlab.com/o9000/tint2/blob/16.1/ChangeLog
|
Changes: https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog
|
||||||
|
|
||||||
Documentation: [doc/tint2.md](doc/tint2.md)
|
Documentation: [doc/tint2.md](doc/tint2.md)
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ Compile it with (after you install the [dependencies](https://gitlab.com/o9000/t
|
|||||||
```
|
```
|
||||||
git clone https://gitlab.com/o9000/tint2.git
|
git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 16.1
|
git checkout 16.6.1
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
@@ -97,4 +97,3 @@ tint2 is a simple panel/taskbar made for modern X window managers. It was specif
|
|||||||
## More
|
## More
|
||||||
|
|
||||||
* [Tint2 wiki](https://gitlab.com/o9000/tint2/wikis/Home)
|
* [Tint2 wiki](https://gitlab.com/o9000/tint2/wikis/Home)
|
||||||
Home)
|
|
||||||
|
|||||||
+4
-1
@@ -386,6 +386,8 @@ gradient_id_pressed = 2
|
|||||||
<li><code>width</code> and <code>height</code> can be specified without units (e.g. <code>123</code>) as pixels, or followed by <code>%</code> as percentages of the monitor size (e.g. <code>50%</code>). Use <code>100%</code> for full monitor width/height.
|
<li><code>width</code> and <code>height</code> can be specified without units (e.g. <code>123</code>) as pixels, or followed by <code>%</code> as percentages of the monitor size (e.g. <code>50%</code>). Use <code>100%</code> for full monitor width/height.
|
||||||
Example:</li>
|
Example:</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
<li><p><code>scale_relative_to_dpi = integer</code> : If set to a non-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI - this is the DPI for which exising user configs looked normal, for backward compatibility.</p></li>
|
||||||
|
<li><p><code>scale_relative_to_screen_height = integer</code> : Similar to <code>scale_relative_to_dpi</code>, except the scaling factor is computed as the ratio between the monitor height and <code>scale_relative_to_screen_height</code>. The effect is cumulative with <code>scale_relative_to_dpi</code>, i.e. if both options are present, the factors are multiplied.</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
<pre class="highlight plaintext"><code># The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
<pre class="highlight plaintext"><code># The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
||||||
panel_size = 94% 30
|
panel_size = 94% 30
|
||||||
@@ -464,6 +466,7 @@ panel_size = 94% 30
|
|||||||
<ul>
|
<ul>
|
||||||
<li><code>none</code> : No sorting. New tasks are simply appended at the end of the taskbar when they appear.</li>
|
<li><code>none</code> : No sorting. New tasks are simply appended at the end of the taskbar when they appear.</li>
|
||||||
<li><code>title</code> : Sorts the tasks by title.</li>
|
<li><code>title</code> : Sorts the tasks by title.</li>
|
||||||
|
<li><code>application</code> : Sorts the tasks by application name. <em>(since 16.3)</em></li>
|
||||||
<li><code>center</code> : Sorts the tasks by their window centers.</li>
|
<li><code>center</code> : Sorts the tasks by their window centers.</li>
|
||||||
<li><code>mru</code> : Shows the most recently used tasks first. <em>(since 0.12.4)</em></li>
|
<li><code>mru</code> : Shows the most recently used tasks first. <em>(since 0.12.4)</em></li>
|
||||||
<li><code>lru</code> : Shows the most recently used tasks last. <em>(since 0.12.4)</em></li>
|
<li><code>lru</code> : Shows the most recently used tasks last. <em>(since 0.12.4)</em></li>
|
||||||
@@ -570,7 +573,7 @@ panel_size = 94% 30
|
|||||||
<ul>
|
<ul>
|
||||||
<li><p><code>battery_hide = never/integer (0 to 100)</code> : At what battery percentage the battery item is hidden.</p></li>
|
<li><p><code>battery_hide = never/integer (0 to 100)</code> : At what battery percentage the battery item is hidden.</p></li>
|
||||||
<li><p><code>battery_low_status = integer</code>: At what battery percentage the low command is executed.</p></li>
|
<li><p><code>battery_low_status = integer</code>: At what battery percentage the low command is executed.</p></li>
|
||||||
<li><p><code>battery_low_cmd = notify-send "battery low"</code> : Command to execute when the battery is low.</p></li>
|
<li><p><code>battery_low_cmd = xmessage 'tint2: Battery low!'</code> : Command to execute when the battery is low.</p></li>
|
||||||
<li><p><code>battery_full_cmd = notify-send "battery full"</code> : Command to execute when the battery is full.</p></li>
|
<li><p><code>battery_full_cmd = notify-send "battery full"</code> : Command to execute when the battery is full.</p></li>
|
||||||
<li><p><code>bat1_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
<li><p><code>bat1_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
||||||
<li><p><code>bat2_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
<li><p><code>bat2_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li>
|
||||||
|
|||||||
+3
-4
@@ -199,9 +199,9 @@ pre {
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 id="latest-stable-release-16-1"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.1</span><a name="latest-stable-release-16-1" href="#latest-stable-release-16-1" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.1/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.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-16-6-1"><span class="md2man-title">Latest</span> <span class="md2man-section">stable</span> <span class="md2man-date">release:</span> <span class="md2man-source">16.6.1</span><a name="latest-stable-release-16-6-1" href="#latest-stable-release-16-6-1" class="md2man-permalink" title="permalink"></a></h1><p>Changes: <a href="https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog">https://gitlab.com/o9000/tint2/blob/16.6.1/ChangeLog</a></p><p>Documentation: <a href="manual.html">manual.html</a></p><p>Compile it with (after you install the <a href="https://gitlab.com/o9000/tint2/wikis/Install#dependencies">dependencies</a>):</p><pre class="highlight plaintext"><code>git clone https://gitlab.com/o9000/tint2.git
|
||||||
cd tint2
|
cd tint2
|
||||||
git checkout 16.1
|
git checkout 16.6.1
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
@@ -269,8 +269,7 @@ update-mime-database /usr/local/share/mime
|
|||||||
</ul>
|
</ul>
|
||||||
<h2 id="more">More<a name="more" href="#more" class="md2man-permalink" title="permalink"></a></h2>
|
<h2 id="more">More<a name="more" href="#more" class="md2man-permalink" title="permalink"></a></h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://gitlab.com/o9000/tint2/wikis/Home">Tint2 wiki</a>
|
<li><a href="https://gitlab.com/o9000/tint2/wikis/Home">Tint2 wiki</a></li>
|
||||||
Home)</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+8
-2
@@ -1,4 +1,4 @@
|
|||||||
.TH TINT2 1 "2017\-12\-30" 16.1
|
.TH TINT2 1 "2018\-08\-05" 16.6.1
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
tint2 \- lightweight panel/taskbar
|
tint2 \- lightweight panel/taskbar
|
||||||
@@ -343,6 +343,10 @@ Use \fB\fCpanel_monitor = all\fR to get a separate panel per monitor
|
|||||||
\fB\fCwidth\fR and \fB\fCheight\fR can be specified without units (e.g. \fB\fC123\fR) as pixels, or followed by \fB\fC%\fR as percentages of the monitor size (e.g. \fB\fC50%\fR). Use \fB\fC100%\fR for full monitor width/height.
|
\fB\fCwidth\fR and \fB\fCheight\fR can be specified without units (e.g. \fB\fC123\fR) as pixels, or followed by \fB\fC%\fR as percentages of the monitor size (e.g. \fB\fC50%\fR). Use \fB\fC100%\fR for full monitor width/height.
|
||||||
Example:
|
Example:
|
||||||
.RE
|
.RE
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fCscale_relative_to_dpi = integer\fR : If set to a non\-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI \- this is the DPI for which exising user configs looked normal, for backward compatibility.
|
||||||
|
.IP \(bu 2
|
||||||
|
\fB\fCscale_relative_to_screen_height = integer\fR : Similar to \fB\fCscale_relative_to_dpi\fR, except the scaling factor is computed as the ratio between the monitor height and \fB\fCscale_relative_to_screen_height\fR\&. The effect is cumulative with \fB\fCscale_relative_to_dpi\fR, i.e. if both options are present, the factors are multiplied.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
@@ -476,6 +480,8 @@ You can switch between virtual desktops.
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCtitle\fR : Sorts the tasks by title.
|
\fB\fCtitle\fR : Sorts the tasks by title.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
|
\fB\fCapplication\fR : Sorts the tasks by application name. \fI(since 16.3)\fP
|
||||||
|
.IP \(bu 2
|
||||||
\fB\fCcenter\fR : Sorts the tasks by their window centers.
|
\fB\fCcenter\fR : Sorts the tasks by their window centers.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCmru\fR : Shows the most recently used tasks first. \fI(since 0.12.4)\fP
|
\fB\fCmru\fR : Shows the most recently used tasks first. \fI(since 0.12.4)\fP
|
||||||
@@ -659,7 +665,7 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCbattery_low_status = integer\fR: At what battery percentage the low command is executed.
|
\fB\fCbattery_low_status = integer\fR: At what battery percentage the low command is executed.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCbattery_low_cmd = notify\-send "battery low"\fR : Command to execute when the battery is low.
|
\fB\fCbattery_low_cmd = xmessage 'tint2: Battery low!'\fR : Command to execute when the battery is low.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fB\fCbattery_full_cmd = notify\-send "battery full"\fR : Command to execute when the battery is full.
|
\fB\fCbattery_full_cmd = notify\-send "battery full"\fR : Command to execute when the battery is full.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
|
|||||||
+7
-2
@@ -1,4 +1,4 @@
|
|||||||
# TINT2 1 "2017-12-30" 16.1
|
# TINT2 1 "2018-08-05" 16.6.1
|
||||||
|
|
||||||
## NAME
|
## NAME
|
||||||
tint2 - lightweight panel/taskbar
|
tint2 - lightweight panel/taskbar
|
||||||
@@ -279,6 +279,10 @@ gradient_id_pressed = 2
|
|||||||
* `width` and `height` can be specified without units (e.g. `123`) as pixels, or followed by `%` as percentages of the monitor size (e.g. `50%`). Use `100%` for full monitor width/height.
|
* `width` and `height` can be specified without units (e.g. `123`) as pixels, or followed by `%` as percentages of the monitor size (e.g. `50%`). Use `100%` for full monitor width/height.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
* `scale_relative_to_dpi = integer` : If set to a non-zero value, HiDPI scaling is enabled. Each panel is visible on a different monitor. Thus each panel has a specific scaling factor. The scaling factor is computed as the ratio between the monitor DPI (obtained from the dimensions in pixels and millimeters from RandR) and a configured reference DPI - this is the DPI for which exising user configs looked normal, for backward compatibility.
|
||||||
|
|
||||||
|
* `scale_relative_to_screen_height = integer` : Similar to `scale_relative_to_dpi`, except the scaling factor is computed as the ratio between the monitor height and `scale_relative_to_screen_height`. The effect is cumulative with `scale_relative_to_dpi`, i.e. if both options are present, the factors are multiplied.
|
||||||
|
|
||||||
```
|
```
|
||||||
# The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
# The panel's width is 94% the size of the monitor, the height is 30 pixels:
|
||||||
panel_size = 94% 30
|
panel_size = 94% 30
|
||||||
@@ -381,6 +385,7 @@ panel_size = 94% 30
|
|||||||
* `taskbar_sort_order = none/title/center` : Specifies the sort order of the tasks on the taskbar. *(since 0.12)*
|
* `taskbar_sort_order = none/title/center` : Specifies the sort order of the tasks on the taskbar. *(since 0.12)*
|
||||||
* `none` : No sorting. New tasks are simply appended at the end of the taskbar when they appear.
|
* `none` : No sorting. New tasks are simply appended at the end of the taskbar when they appear.
|
||||||
* `title` : Sorts the tasks by title.
|
* `title` : Sorts the tasks by title.
|
||||||
|
* `application` : Sorts the tasks by application name. *(since 16.3)*
|
||||||
* `center` : Sorts the tasks by their window centers.
|
* `center` : Sorts the tasks by their window centers.
|
||||||
* `mru` : Shows the most recently used tasks first. *(since 0.12.4)*
|
* `mru` : Shows the most recently used tasks first. *(since 0.12.4)*
|
||||||
* `lru` : Shows the most recently used tasks last. *(since 0.12.4)*
|
* `lru` : Shows the most recently used tasks last. *(since 0.12.4)*
|
||||||
@@ -542,7 +547,7 @@ The action semantics:
|
|||||||
|
|
||||||
* `battery_low_status = integer`: At what battery percentage the low command is executed.
|
* `battery_low_status = integer`: At what battery percentage the low command is executed.
|
||||||
|
|
||||||
* `battery_low_cmd = notify-send "battery low"` : Command to execute when the battery is low.
|
* `battery_low_cmd = xmessage 'tint2: Battery low!'` : Command to execute when the battery is low.
|
||||||
|
|
||||||
* `battery_full_cmd = notify-send "battery full"` : Command to execute when the battery is full.
|
* `battery_full_cmd = notify-send "battery full"` : Command to execute when the battery is full.
|
||||||
|
|
||||||
|
|||||||
+16
-15
@@ -76,19 +76,23 @@ def get_last_version():
|
|||||||
return tags[-1]
|
return tags[-1]
|
||||||
|
|
||||||
|
|
||||||
def inc_version(v, feature=False):
|
def inc_version(v, feature=False, tiny=False):
|
||||||
if v.startswith("v0."):
|
if v.startswith("v0."):
|
||||||
assert v == "v0.14.6"
|
assert v == "v0.14.6"
|
||||||
return "v15.0"
|
return "v15.0"
|
||||||
# v4.11 -> v4.12 or v5.0
|
# v4.11 -> v4.12 or v5.0 or v4.11.1
|
||||||
parts = v.split(".")
|
parts = v.split(".")
|
||||||
while len(parts) < 2:
|
while len(parts) < 3:
|
||||||
parts.append("0")
|
parts.append("0")
|
||||||
assert len(parts) == 2
|
assert len(parts) == 3
|
||||||
if feature:
|
if feature:
|
||||||
|
del parts[-1]
|
||||||
parts[-2] = "v" + str(int(parts[-2].replace("v", "")) + 1)
|
parts[-2] = "v" + str(int(parts[-2].replace("v", "")) + 1)
|
||||||
parts[-1] = "0"
|
parts[-1] = "0"
|
||||||
|
elif tiny:
|
||||||
|
parts[-1] = str(int(parts[-1]) + 1)
|
||||||
else:
|
else:
|
||||||
|
del parts[-1]
|
||||||
parts[-1] = str(int(parts[-1]) + 1)
|
parts[-1] = str(int(parts[-1]) + 1)
|
||||||
return ".".join([s for s in parts if s])
|
return ".".join([s for s in parts if s])
|
||||||
|
|
||||||
@@ -153,23 +157,14 @@ def update_log(path, version, date):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--feature", action="store_true")
|
parser.add_argument("--feature", action="store_true")
|
||||||
parser.add_argument("--undo", action="store_true")
|
parser.add_argument("--tiny", action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
logging.basicConfig(format=ansi_lblue + "%(asctime)s %(pathname)s %(levelname)s" + ansi_reset + " %(message)s", level=logging.DEBUG)
|
logging.basicConfig(format=ansi_lblue + "%(asctime)s %(pathname)s %(levelname)s" + ansi_reset + " %(message)s", level=logging.DEBUG)
|
||||||
test_inc_version()
|
test_inc_version()
|
||||||
# Read version from last tag and increment
|
# Read version from last tag and increment
|
||||||
old_version = get_last_version()
|
old_version = get_last_version()
|
||||||
if args.undo:
|
|
||||||
info("Revering last commit...")
|
|
||||||
run("git tag -d %s" % old_version)
|
|
||||||
run("git tag -d %s" % old_version.replace("v", ""))
|
|
||||||
run("git reset --soft HEAD~")
|
|
||||||
run("git reset")
|
|
||||||
run("git stash")
|
|
||||||
os.system("git log -1")
|
|
||||||
sys.exit(0)
|
|
||||||
info("Old version:", old_version)
|
info("Old version:", old_version)
|
||||||
version = inc_version(old_version, args.feature)
|
version = inc_version(old_version, args.feature, args.tiny)
|
||||||
readable_version = version.replace("v", "")
|
readable_version = version.replace("v", "")
|
||||||
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
info("New version:", readable_version, version, date)
|
info("New version:", readable_version, version, date)
|
||||||
@@ -194,3 +189,9 @@ if __name__ == '__main__':
|
|||||||
choice = raw_input().lower()
|
choice = raw_input().lower()
|
||||||
if choice != "y":
|
if choice != "y":
|
||||||
run("git reset --hard HEAD~ ; git tag -d %s ; git tag -d %s" % (version, readable_version))
|
run("git reset --hard HEAD~ ; git tag -d %s ; git tag -d %s" % (version, readable_version))
|
||||||
|
sys.exit(1)
|
||||||
|
print "Publish? [y/n]"
|
||||||
|
choice = raw_input().lower()
|
||||||
|
if choice != "y":
|
||||||
|
sys.exit(1)
|
||||||
|
run("git push origin master && git push --tags origin master")
|
||||||
|
|||||||
+544
@@ -0,0 +1,544 @@
|
|||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
def check_c_compiles(cmd, code):
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.c') as f:
|
||||||
|
f.write(code)
|
||||||
|
f.flush()
|
||||||
|
cmd += [f.name, '-o', '/dev/null']
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
out, err = proc.communicate()
|
||||||
|
ret = proc.returncode
|
||||||
|
return ret == 0
|
||||||
|
|
||||||
|
|
||||||
|
def makedirs(path):
|
||||||
|
try:
|
||||||
|
os.makedirs(path)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.EEXIST and os.path.isdir(path):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def pkg_config(lib):
|
||||||
|
def _pkgconfig(lib, query):
|
||||||
|
lib = lib.replace('>=', ' >= ')
|
||||||
|
cmd = 'pkg-config {} {}'.format(query, lib).split()
|
||||||
|
popen = subprocess.Popen(cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
out, err = popen.communicate()
|
||||||
|
if popen.returncode != 0:
|
||||||
|
print(cmd)
|
||||||
|
print(err)
|
||||||
|
raise ValueError("Could not find library: {}".format(lib))
|
||||||
|
return out.split()
|
||||||
|
|
||||||
|
lf = _pkgconfig(lib, '--libs-only-l')
|
||||||
|
cf = _pkgconfig(lib, '--cflags')
|
||||||
|
ldf = _pkgconfig(lib, '--libs-only-L')
|
||||||
|
return (lf, cf, ldf)
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_escape(s):
|
||||||
|
s = s.replace(' ', '$ ')
|
||||||
|
s = s.replace('\n', '$\n')
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_join(words):
|
||||||
|
indent = ' '
|
||||||
|
if len(words) > 1:
|
||||||
|
prefix = '$\n' + indent
|
||||||
|
else:
|
||||||
|
prefix = ''
|
||||||
|
spacer = ' $\n' + indent
|
||||||
|
return prefix + spacer.join(ninja_escape(s) for s in words)
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_write_vars(f, **kwargs):
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
f.write('{} = {}\n'.format(k, v))
|
||||||
|
f.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_write_rule(f, name, **kwargs):
|
||||||
|
f.write('rule {}\n'.format(name))
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
f.write(' {} = {}\n'.format(k, v))
|
||||||
|
f.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
def remove_prefix(s, prefix):
|
||||||
|
while prefix and s.startswith(prefix):
|
||||||
|
s = s[len(prefix):]
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def install(prefix, suffix, dest_dir, dest_suffix=''):
|
||||||
|
src_path = os.path.join(prefix, suffix) if suffix else prefix
|
||||||
|
fname = os.path.basename(src_path)
|
||||||
|
if dest_suffix:
|
||||||
|
dest_dir = os.path.join(dest_dir, dest_suffix)
|
||||||
|
dst_path = os.path.join(dest_dir, fname)
|
||||||
|
return [(src_path, dst_path)]
|
||||||
|
|
||||||
|
|
||||||
|
def install_dir(prefix, suffix, dest_dir, dest_suffix=''):
|
||||||
|
result = []
|
||||||
|
src_path = os.path.join(prefix, suffix)
|
||||||
|
for root, dirs, files in os.walk(src_path):
|
||||||
|
for f in files:
|
||||||
|
fname = os.path.join(root, f)
|
||||||
|
fsuffix = remove_prefix(remove_prefix(fname, prefix), '/')
|
||||||
|
result += install(prefix, fsuffix, dest_dir, os.path.join(dest_suffix, os.path.dirname(fsuffix)))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class Executable(object):
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.cc = 'cc'
|
||||||
|
self.cflags = []
|
||||||
|
self.lflags = []
|
||||||
|
self.libs = []
|
||||||
|
self.sources = []
|
||||||
|
self.pos = []
|
||||||
|
self.install_exec = []
|
||||||
|
self.install_data = []
|
||||||
|
|
||||||
|
def write_ninja(self, f):
|
||||||
|
f.write('# Executable: {}\n'.format(self.name))
|
||||||
|
ninja_write_vars(f, **{
|
||||||
|
'cc_' + self.name: self.cc,
|
||||||
|
'cflags_' + self.name: ninja_join(self.cflags),
|
||||||
|
'lflags_' + self.name: ninja_join(self.lflags),
|
||||||
|
'libs_' + self.name: ninja_join(self.libs)})
|
||||||
|
ninja_write_rule(f, 'cc_' + self.name,
|
||||||
|
command='$cc_{} -MMD -MT $out -MF $out.d $cflags_{} -c $in -o $out'.format(self.name, self.name),
|
||||||
|
description='CC $out',
|
||||||
|
depfile='$out.d',
|
||||||
|
deps='gcc')
|
||||||
|
ninja_write_rule(f, 'link_' + self.name,
|
||||||
|
command='$cc_{} $lflags_{} -o $out $in $libs_{}'.format(self.name, self.name, self.name),
|
||||||
|
description='LINK $out')
|
||||||
|
ninja_write_rule(f, 'po2mo_' + self.name,
|
||||||
|
command='msgfmt -o $out $in',
|
||||||
|
description='GEN $out')
|
||||||
|
f.write('# Compilation\n')
|
||||||
|
for src in self.sources:
|
||||||
|
f.write('build $build_dir/{}.{}.o: cc_{} $source_dir/{}\n'.format(src, self.name, self.name, src))
|
||||||
|
f.write('# Translation\n')
|
||||||
|
for po in self.pos:
|
||||||
|
f.write('build $build_dir/{}.mo: po2mo_{} $source_dir/{}\n'.format(os.path.splitext(po)[0], self.name, po))
|
||||||
|
f.write('# Linking\n')
|
||||||
|
f.write('build $build_dir/{}: link_{} '.format(self.name, self.name))
|
||||||
|
f.write(ninja_join(['$build_dir/{}.{}.o'.format(src, self.name) for src in self.sources]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('# Installation\n')
|
||||||
|
for fin, fout in self.install_exec:
|
||||||
|
f.write('build {}: install_exec {}\n'.format(fout, fin))
|
||||||
|
for fin, fout in self.install_data:
|
||||||
|
f.write('build {}: install_data {}\n'.format(fout, fin))
|
||||||
|
f.write('build install_{}: phony '.format(self.name))
|
||||||
|
f.write(ninja_join([fout for fin, fout in self.install_exec + self.install_data]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('# Uninstallation\n')
|
||||||
|
for fin, fout in self.install_exec + self.install_data:
|
||||||
|
f.write('build uninstall_{}: uninstall {}\n'.format(fout, fout))
|
||||||
|
f.write('build uninstall_{}: phony '.format(self.name))
|
||||||
|
f.write(ninja_join(['uninstall_{}'.format(fout) for fin, fout in self.install_exec + self.install_data]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('\n')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate_ninja(targets, source_dir, build_dir):
|
||||||
|
ninja_file_name = os.path.join(build_dir, 'build.ninja')
|
||||||
|
f = open(ninja_file_name, 'w')
|
||||||
|
# `deps` was introduced in ninja 1.3.
|
||||||
|
ninja_write_vars(f, ninja_required_version='1.3')
|
||||||
|
ninja_write_vars(f, **{
|
||||||
|
'source_dir':source_dir,
|
||||||
|
'build_dir':build_dir
|
||||||
|
})
|
||||||
|
ninja_write_rule(f, 'install_exec',
|
||||||
|
command='install -D -m0755 $in $out',
|
||||||
|
description='INSTALL $out')
|
||||||
|
ninja_write_rule(f, 'install_data',
|
||||||
|
command='install -D -m0644 $in $out',
|
||||||
|
description='INSTALL $out')
|
||||||
|
ninja_write_rule(f, 'uninstall',
|
||||||
|
command='rm -f $in',
|
||||||
|
description='RM $in')
|
||||||
|
for t in targets:
|
||||||
|
t.write_ninja(f)
|
||||||
|
f.write('# Targets\n')
|
||||||
|
f.write('build all: phony ')
|
||||||
|
f.write(ninja_join(['$build_dir/{}'.format(t.name) for t in targets]))
|
||||||
|
f.write('\n')
|
||||||
|
installs = sum([(t.install_exec + t.install_data) for t in targets], [])
|
||||||
|
if installs:
|
||||||
|
f.write('build install: phony ')
|
||||||
|
f.write(ninja_join(['install_{}'.format(t.name) for t in targets]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('build uninstall: phony ')
|
||||||
|
f.write(ninja_join(['uninstall_{}'.format(t.name) for t in targets]))
|
||||||
|
f.write('\n')
|
||||||
|
f.write('\n')
|
||||||
|
f.write('default all\n')
|
||||||
|
f.close()
|
||||||
|
print('Wrote {}.'.format(ninja_file_name))
|
||||||
|
print('Run `ninja -v -C {} all` to compile.'.format(build_dir))
|
||||||
|
print('Run `ninja -v -C {} install` to install.'.format(build_dir))
|
||||||
|
|
||||||
|
|
||||||
|
# Parse CLI options
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--uevent', dest='uevent', action='store_true',
|
||||||
|
help='Enable uevent support. Default: on under Linux')
|
||||||
|
parser.add_argument('--debug', dest='debug', action='store_true',
|
||||||
|
help='Enable debug build. Default: off')
|
||||||
|
parser.add_argument('--asan', dest='asan', action='store_true',
|
||||||
|
help='Enable AddressSanitizer. Default: off')
|
||||||
|
parser.add_argument('--tracing', dest='tracing', action='store_true',
|
||||||
|
help='Enable tracing. Default: off')
|
||||||
|
parser.add_argument('--memory-tracing', dest='memory_tracing', action='store_true',
|
||||||
|
help='Enable memory allocation tracing. Default: off')
|
||||||
|
parser.add_argument('--prefix', help='Prefix for constructing the file installation paths. Default: /usr/local', default=None)
|
||||||
|
parser.add_argument('--exec_prefix', help='Prefix for binary paths. Default: $prefix', default=None)
|
||||||
|
parser.add_argument('--bindir', help='Path where executables must be installed. Default: $exec_prefix/bin', default=None)
|
||||||
|
parser.add_argument('--sysconfdir', help='Path where config files must be installed. Default: /etc', default=None)
|
||||||
|
parser.add_argument('--datarootdir', help='Path where data files must be installed. Default: $prefix/share', default=None)
|
||||||
|
parser.add_argument('--localedir', help='Path where locale files must be installed. Default: $datarootdir/locale', default=None)
|
||||||
|
parser.add_argument('--docdir', help='Path where documentation files must be installed. Default: $datarootdir/doc/tint2', default=None)
|
||||||
|
parser.add_argument('--htmldir', help='Path where documentation files must be installed. Default: $docdir/html', default=None)
|
||||||
|
parser.add_argument('--mandir', help='Path where man files must be installed. Default: $datarootdir/man', default=None)
|
||||||
|
parser.add_argument('--home', dest='home', action='store_true',
|
||||||
|
help='Install to $HOME (sets all paths accordingly). Default: off')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Get relevant environment variables
|
||||||
|
CC = os.environ.get('CC', 'cc')
|
||||||
|
CFLAGS = shlex.split(os.environ.get('CFLAGS', ''))
|
||||||
|
LFLAGS = shlex.split(os.environ.get('LDFLAGS', ''))
|
||||||
|
LIBS = []
|
||||||
|
|
||||||
|
# Get paths
|
||||||
|
source_dir = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + '/..')
|
||||||
|
build_dir = os.path.join(os.getcwd(), 'build')
|
||||||
|
if not args.home:
|
||||||
|
prefix = args.prefix or '/usr/local'
|
||||||
|
exec_prefix = args.exec_prefix or prefix
|
||||||
|
bindir = args.bindir or os.path.join(exec_prefix, 'bin')
|
||||||
|
datarootdir = args.datarootdir or os.path.join(prefix, 'share')
|
||||||
|
sysconfdir = args.sysconfdir or '/etc'
|
||||||
|
docdir = args.docdir or os.path.join(datarootdir, 'doc/tint2')
|
||||||
|
htmldir = args.htmldir or os.path.join(docdir, 'html')
|
||||||
|
localedir = args.localedir or os.path.join(datarootdir, 'locale')
|
||||||
|
mandir = args.mandir or os.path.join(datarootdir, 'man')
|
||||||
|
else:
|
||||||
|
prefix = args.prefix or os.path.expanduser("~")
|
||||||
|
exec_prefix = args.exec_prefix or prefix
|
||||||
|
bindir = args.bindir or os.path.join(exec_prefix, 'bin')
|
||||||
|
datarootdir = args.datarootdir or os.path.join(prefix, '.local/share')
|
||||||
|
sysconfdir = args.sysconfdir or os.path.expanduser("~/.config/tint2")
|
||||||
|
docdir = args.docdir or os.path.join(datarootdir, 'doc/tint2')
|
||||||
|
htmldir = args.htmldir or os.path.join(docdir, 'html')
|
||||||
|
localedir = args.localedir or os.path.join(datarootdir, 'locale')
|
||||||
|
mandir = args.mandir or os.path.join(datarootdir, 'man')
|
||||||
|
|
||||||
|
|
||||||
|
# Check if C11 is supported by the compiler, fall back to C99
|
||||||
|
if check_c_compiles([CC],
|
||||||
|
'''#define print(x) _Generic((x), default : print_unknown)(x)
|
||||||
|
void print_unknown() {
|
||||||
|
}
|
||||||
|
int main () {
|
||||||
|
print(0);
|
||||||
|
}'''):
|
||||||
|
CFLAGS += ['-std=c11', '-DHAS_GENERIC']
|
||||||
|
else:
|
||||||
|
print("No C11 support.")
|
||||||
|
CFLAGS += ['-std=c99']
|
||||||
|
|
||||||
|
# Set mandatory flags
|
||||||
|
CFLAGS += ['-g',
|
||||||
|
'-Wall',
|
||||||
|
'-Wextra',
|
||||||
|
'-Wshadow',
|
||||||
|
'-Wpointer-arith',
|
||||||
|
'-Wno-deprecated',
|
||||||
|
'-Wno-missing-field-initializers',
|
||||||
|
'-Wno-unused-parameter',
|
||||||
|
'-Wno-sign-compare',
|
||||||
|
'-fno-strict-aliasing',
|
||||||
|
'-pthread',
|
||||||
|
'-D_BSD_SOURCE',
|
||||||
|
'-D_DEFAULT_SOURCE',
|
||||||
|
'-D_WITH_GETLINE',
|
||||||
|
'-DENABLE_BATTERY']
|
||||||
|
LFLAGS += ['-fno-strict-aliasing',
|
||||||
|
'-pthread']
|
||||||
|
LFLAGS += ['-L' + build_dir]
|
||||||
|
|
||||||
|
# Set platform dependent C flags
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
CFLAGS += ['-D_POSIX_C_SOURCE=200809L']
|
||||||
|
|
||||||
|
if sys.platform.startswith('freebsd') or sys.platform.startswith('openbsd') or sys.platform.startswith('dragonfly'):
|
||||||
|
CFLAGS += ['-I/usr/local/include']
|
||||||
|
LFLAGS += ['-L/usr/local/lib']
|
||||||
|
|
||||||
|
if sys.platform.startswith('linux') or args.uevent:
|
||||||
|
CFLAGS += ['-DENABLE_UEVENT']
|
||||||
|
|
||||||
|
# Turn on color messages if supported
|
||||||
|
if check_c_compiles([CC, '-fdiagnostics-color', '-c', '-x', 'c'], ''):
|
||||||
|
CFLAGS += ['-fdiagnostics-color=always']
|
||||||
|
|
||||||
|
# Set project-specific include dirs
|
||||||
|
CFLAGS += ['-I.']
|
||||||
|
for inc in ['src',
|
||||||
|
'src/battery',
|
||||||
|
'src/clock',
|
||||||
|
'src/systray',
|
||||||
|
'src/taskbar',
|
||||||
|
'src/launcher',
|
||||||
|
'src/tooltip',
|
||||||
|
'src/util',
|
||||||
|
'src/execplugin',
|
||||||
|
'src/button',
|
||||||
|
'src/freespace',
|
||||||
|
'src/separator']:
|
||||||
|
CFLAGS += ['-I' + os.path.join(source_dir, inc)]
|
||||||
|
|
||||||
|
# Add mandatory library dependencies
|
||||||
|
LIBS += ['-lm', '-lrt']
|
||||||
|
|
||||||
|
# Add mandatory libray dependencies detected with pkg-config
|
||||||
|
for dep in ['x11',
|
||||||
|
'xcomposite',
|
||||||
|
'xdamage',
|
||||||
|
'xinerama',
|
||||||
|
'xext',
|
||||||
|
'xrender',
|
||||||
|
'xrandr>=1.3',
|
||||||
|
'pangocairo',
|
||||||
|
'pango',
|
||||||
|
'cairo',
|
||||||
|
'glib-2.0',
|
||||||
|
'gobject-2.0',
|
||||||
|
'imlib2>=1.4.2']:
|
||||||
|
lib, cf, lf = pkg_config(dep)
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf
|
||||||
|
LFLAGS += lf
|
||||||
|
|
||||||
|
# Add optional library dependencies detected with pkg-config
|
||||||
|
try:
|
||||||
|
lib, cf, lf = pkg_config('librsvg-2.0>=2.14.0')
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf + ['-DHAVE_RSVG']
|
||||||
|
LFLAGS += lf
|
||||||
|
except:
|
||||||
|
print("No SVG support.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
lib, cf, lf = pkg_config('libstartup-notification-1.0>=0.12')
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf + ['-DHAVE_SN', '-DSN_API_NOT_YET_FROZEN']
|
||||||
|
LFLAGS += lf
|
||||||
|
except:
|
||||||
|
print("No startup notification support.")
|
||||||
|
|
||||||
|
# Add library dependencies detected with using successful compilation test
|
||||||
|
bt = False
|
||||||
|
if not bt:
|
||||||
|
try:
|
||||||
|
lib, cf, lf = pkg_config('libunwind')
|
||||||
|
LIBS += lib
|
||||||
|
CFLAGS += cf + ['-DHAS_LIBUNWIND']
|
||||||
|
LFLAGS += lf
|
||||||
|
bt = True
|
||||||
|
print("Backtrace support via libunwind.")
|
||||||
|
except:
|
||||||
|
print("No backtrace support via libunwind.")
|
||||||
|
if not bt:
|
||||||
|
if check_c_compiles([CC, '-lbacktrace'], '''#include <backtrace.h>
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}'''):
|
||||||
|
CFLAGS += ['-DHAS_BACKTRACE']
|
||||||
|
LIBS += ['-lbacktrace']
|
||||||
|
bt = True
|
||||||
|
print("Backtrace support via libbacktrace.")
|
||||||
|
else:
|
||||||
|
print("No backtrace support via libbacktrace.")
|
||||||
|
|
||||||
|
# Add option-dependent flags
|
||||||
|
if not args.debug:
|
||||||
|
CFLAGS += ['-O2']
|
||||||
|
|
||||||
|
if args.asan:
|
||||||
|
asan_flags = ['-fsanitize=address']
|
||||||
|
CFLAGS += asan_flags
|
||||||
|
LFLAGS += asan_flags
|
||||||
|
|
||||||
|
if args.tracing:
|
||||||
|
CFLAGS += ['-finstrument-functions',
|
||||||
|
'-finstrument-functions-exclude-file-list=tracing.c',
|
||||||
|
'-finstrument-functions-exclude-function-list=get_time,gettime']
|
||||||
|
|
||||||
|
if args.asan or args.memory_tracing or args.tracing:
|
||||||
|
trace_flags = ['-O0',
|
||||||
|
'-fno-common',
|
||||||
|
'-fno-omit-frame-pointer',
|
||||||
|
'-rdynamic']
|
||||||
|
CFLAGS += trace_flags
|
||||||
|
LFLAGS += trace_flags + ['-fuse-ld=gold']
|
||||||
|
|
||||||
|
if args.memory_tracing:
|
||||||
|
LIBS += ['-ldl']
|
||||||
|
|
||||||
|
# Define targets
|
||||||
|
tint2 = Executable('tint2')
|
||||||
|
tint2.cflags += CFLAGS
|
||||||
|
tint2.lflags += LFLAGS
|
||||||
|
tint2.libs += LIBS
|
||||||
|
tint2.sources = ['src/config.c',
|
||||||
|
'src/panel.c',
|
||||||
|
'src/util/server.c',
|
||||||
|
'src/main.c',
|
||||||
|
'src/init.c',
|
||||||
|
'src/util/signals.c',
|
||||||
|
'src/util/tracing.c',
|
||||||
|
'src/mouse_actions.c',
|
||||||
|
'src/drag_and_drop.c',
|
||||||
|
'src/default_icon.c',
|
||||||
|
'src/clock/clock.c',
|
||||||
|
'src/systray/systraybar.c',
|
||||||
|
'src/launcher/launcher.c',
|
||||||
|
'src/launcher/apps-common.c',
|
||||||
|
'src/launcher/icon-theme-common.c',
|
||||||
|
'src/launcher/xsettings-client.c',
|
||||||
|
'src/launcher/xsettings-common.c',
|
||||||
|
'src/taskbar/task.c',
|
||||||
|
'src/taskbar/taskbar.c',
|
||||||
|
'src/taskbar/taskbarname.c',
|
||||||
|
'src/tooltip/tooltip.c',
|
||||||
|
'src/execplugin/execplugin.c',
|
||||||
|
'src/button/button.c',
|
||||||
|
'src/freespace/freespace.c',
|
||||||
|
'src/separator/separator.c',
|
||||||
|
'src/tint2rc.c',
|
||||||
|
'src/util/area.c',
|
||||||
|
'src/util/bt.c',
|
||||||
|
'src/util/common.c',
|
||||||
|
'src/util/fps_distribution.c',
|
||||||
|
'src/util/strnatcmp.c',
|
||||||
|
'src/util/timer.c',
|
||||||
|
'src/util/cache.c',
|
||||||
|
'src/util/color.c',
|
||||||
|
'src/util/strlcat.c',
|
||||||
|
'src/util/print.c',
|
||||||
|
'src/util/gradient.c',
|
||||||
|
'src/util/test.c',
|
||||||
|
'src/util/uevent.c',
|
||||||
|
'src/util/window.c',
|
||||||
|
'src/battery/battery.c']
|
||||||
|
|
||||||
|
# Battery implementation is platform-specific
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
tint2.sources += ['src/battery/linux.c']
|
||||||
|
elif sys.platform.startswith('freebsd') or \
|
||||||
|
sys.platform.startswith('dragonfly') or \
|
||||||
|
sys.platform.startswith('gnukfreebsd'):
|
||||||
|
tint2.sources += ['src/battery/freebsd.c']
|
||||||
|
elif sys.platform.startswith('openbsd') or \
|
||||||
|
sys.platform.startswith('netbsd'):
|
||||||
|
tint2.sources += ['src/battery/openbsd.c']
|
||||||
|
else:
|
||||||
|
print("No battery support for platform:", sys.platform)
|
||||||
|
tint2.sources += ['src/battery/dummy.c']
|
||||||
|
|
||||||
|
if args.memory_tracing:
|
||||||
|
tint2.sources += ['src/util/mem.c']
|
||||||
|
|
||||||
|
tint2.install_exec = install(build_dir, 'tint2', bindir)
|
||||||
|
tint2.install_data = (install(source_dir, 'tint2.svg', datarootdir, 'icons/hicolor/scalable/apps') +
|
||||||
|
install(source_dir, 'tint2.desktop', datarootdir, 'applications') +
|
||||||
|
install(source_dir, 'themes/tint2rc', sysconfdir, 'xdg/tint2') +
|
||||||
|
install(source_dir, 'default_icon.png', datarootdir, 'tint2') +
|
||||||
|
install(source_dir, 'AUTHORS', docdir) +
|
||||||
|
install(source_dir, 'ChangeLog', docdir) +
|
||||||
|
install(source_dir, 'README.md', docdir) +
|
||||||
|
install(source_dir, 'doc/tint2.md', docdir) +
|
||||||
|
install(source_dir, 'doc/manual.html', htmldir) +
|
||||||
|
install(source_dir, 'doc/readme.html', htmldir) +
|
||||||
|
install_dir(source_dir, 'doc/images', htmldir) +
|
||||||
|
install(source_dir, 'doc/tint2.1', mandir, 'man1'))
|
||||||
|
|
||||||
|
tint2conf = Executable('tint2conf')
|
||||||
|
tint2conf.cflags += CFLAGS
|
||||||
|
tint2conf.lflags += LFLAGS
|
||||||
|
tint2conf.libs += LIBS
|
||||||
|
|
||||||
|
for dep in ['gthread-2.0',
|
||||||
|
'gtk+-x11-2.0']:
|
||||||
|
lib, cf, lf = pkg_config(dep)
|
||||||
|
tint2conf.libs += lib
|
||||||
|
tint2conf.cflags += cf
|
||||||
|
tint2conf.lflags += lf
|
||||||
|
|
||||||
|
tint2conf.cflags += ['-DTINT2CONF',
|
||||||
|
'-DINSTALL_PREFIX=\\"{}\\"'.format(prefix),
|
||||||
|
'-DLOCALEDIR=\\"{}\\"'.format(localedir),
|
||||||
|
'-DGETTEXT_PACKAGE=\\"tint2conf\\"',
|
||||||
|
'-DHAVE_VERSION_H',
|
||||||
|
'-Wno-shadow']
|
||||||
|
|
||||||
|
tint2conf.sources = ['src/util/bt.c',
|
||||||
|
'src/util/common.c',
|
||||||
|
'src/util/strnatcmp.c',
|
||||||
|
'src/util/cache.c',
|
||||||
|
'src/util/timer.c',
|
||||||
|
'src/util/test.c',
|
||||||
|
'src/util/print.c',
|
||||||
|
'src/util/signals.c',
|
||||||
|
'src/config.c',
|
||||||
|
'src/util/server.c',
|
||||||
|
'src/util/strlcat.c',
|
||||||
|
'src/launcher/apps-common.c',
|
||||||
|
'src/launcher/icon-theme-common.c',
|
||||||
|
'src/tint2conf/md4.c',
|
||||||
|
'src/tint2conf/main.c',
|
||||||
|
'src/tint2conf/properties.c',
|
||||||
|
'src/tint2conf/properties_rw.c',
|
||||||
|
'src/tint2conf/theme_view.c',
|
||||||
|
'src/tint2conf/background_gui.c',
|
||||||
|
'src/tint2conf/gradient_gui.c']
|
||||||
|
tint2conf.pos = [os.path.join('src/tint2conf/po', f) for f in os.listdir('src/tint2conf/po') if f.endswith('.po')]
|
||||||
|
tint2conf.install_exec = install(build_dir, 'tint2conf', bindir)
|
||||||
|
tint2conf.install_data = (install(source_dir, 'src/tint2conf/tint2conf.svg', datarootdir, 'icons/hicolor/scalable/apps') +
|
||||||
|
install(source_dir, 'src/tint2conf/tint2conf.desktop', datarootdir, 'applications') +
|
||||||
|
install(source_dir, 'src/tint2conf/tint2conf.xml', datarootdir, 'mime/packages'))
|
||||||
|
|
||||||
|
makedirs(build_dir)
|
||||||
|
assert 0 == os.system('cd {}; {}/get_version.sh'.format(build_dir, source_dir))
|
||||||
|
generate_ninja([tint2, tint2conf], source_dir, build_dir)
|
||||||
@@ -49,7 +49,7 @@ echo "echo \"#define VERSION_STRING \\\"$VERSION\\\"\" > version.h" > $DIR/get_v
|
|||||||
# Copy the debian files into the source directory
|
# Copy the debian files into the source directory
|
||||||
cp -r debian $DIR/debian
|
cp -r debian $DIR/debian
|
||||||
|
|
||||||
for DISTRO in trusty xenial zesty artful bionic
|
for DISTRO in trusty xenial artful bionic
|
||||||
do
|
do
|
||||||
# Cleanup from previous builds
|
# Cleanup from previous builds
|
||||||
rm -rf tint2_$VERSION-*
|
rm -rf tint2_$VERSION-*
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ git reset --hard
|
|||||||
git pull
|
git pull
|
||||||
|
|
||||||
|
|
||||||
~/tint2/packaging/version_status.py > packaging.tmp.md
|
timeout -k 10 600 ~/tint2/packaging/version_status.py > packaging.tmp.md
|
||||||
cat packaging.tmp.md > packaging.md
|
cat packaging.tmp.md > packaging.md
|
||||||
rm packaging.tmp.md
|
rm packaging.tmp.md
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ def get_gentoo_versions():
|
|||||||
|
|
||||||
def get_void_versions():
|
def get_void_versions():
|
||||||
print >> sys.stderr, "Void ..."
|
print >> sys.stderr, "Void ..."
|
||||||
template = http_download_txt("https://raw.githubusercontent.com/voidlinux/void-packages/master/srcpkgs/tint2/template")
|
template = http_download_txt("https://raw.githubusercontent.com/void-linux/void-packages/master/srcpkgs/tint2/template")
|
||||||
versions = []
|
versions = []
|
||||||
version = None
|
version = None
|
||||||
maintainer = None
|
maintainer = None
|
||||||
|
|||||||
+69
-3
@@ -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,9 @@ char *battery_rclick_command;
|
|||||||
char *battery_uwheel_command;
|
char *battery_uwheel_command;
|
||||||
char *battery_dwheel_command;
|
char *battery_dwheel_command;
|
||||||
gboolean battery_found;
|
gboolean battery_found;
|
||||||
|
gboolean battery_warn;
|
||||||
|
gboolean battery_warn_red;
|
||||||
|
Background *battery_warn_bg;
|
||||||
|
|
||||||
char *battery_sys_prefix = (char *)"";
|
char *battery_sys_prefix = (char *)"";
|
||||||
|
|
||||||
@@ -77,6 +81,10 @@ 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;
|
||||||
|
battery_warn_bg = NULL;
|
||||||
bat1_has_font = FALSE;
|
bat1_has_font = FALSE;
|
||||||
bat1_font_desc = NULL;
|
bat1_font_desc = NULL;
|
||||||
bat1_format = NULL;
|
bat1_format = NULL;
|
||||||
@@ -128,7 +136,9 @@ 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;
|
||||||
|
free_and_null(battery_warn_bg);
|
||||||
|
|
||||||
battery_os_free();
|
battery_os_free();
|
||||||
}
|
}
|
||||||
@@ -225,7 +235,8 @@ void init_battery()
|
|||||||
|
|
||||||
battery_found = battery_os_init();
|
battery_found = battery_os_init();
|
||||||
|
|
||||||
change_timer(&battery_timer, true, 10, 30000, update_battery_tick, 0);
|
if (!battery_timer.enabled_)
|
||||||
|
change_timer(&battery_timer, true, 30000, 30000, update_battery_tick, 0);
|
||||||
|
|
||||||
update_battery();
|
update_battery();
|
||||||
}
|
}
|
||||||
@@ -272,6 +283,7 @@ void init_battery_panel(void *p)
|
|||||||
bat1_format = strdup("%p");
|
bat1_format = strdup("%p");
|
||||||
bat2_format = strdup("%t");
|
bat2_format = strdup("%t");
|
||||||
}
|
}
|
||||||
|
update_battery_tick(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_init_fonts()
|
void battery_init_fonts()
|
||||||
@@ -308,6 +320,40 @@ void battery_default_font_changed()
|
|||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void blink_battery(void *arg)
|
||||||
|
{
|
||||||
|
if (!battery_enabled)
|
||||||
|
return;
|
||||||
|
battery_warn_red = battery_warn ? !battery_warn_red : FALSE;
|
||||||
|
if (battery_warn_red && !battery_warn_bg) {
|
||||||
|
battery_warn_bg = calloc(1, sizeof(*battery_warn_bg));
|
||||||
|
*battery_warn_bg = *panel_config.battery.area.bg;
|
||||||
|
battery_warn_bg->fill_color.alpha = 1.0;
|
||||||
|
battery_warn_bg->border.color.alpha = 1.0;
|
||||||
|
}
|
||||||
|
if (battery_warn_red) {
|
||||||
|
battery_warn_bg->fill_color.rgb[0] = 0.6;
|
||||||
|
battery_warn_bg->fill_color.rgb[1] = 0.1;
|
||||||
|
battery_warn_bg->fill_color.rgb[2] = 0.1;
|
||||||
|
battery_warn_bg->border.color.rgb[0] = 0.5;
|
||||||
|
battery_warn_bg->border.color.rgb[1] = 0.0;
|
||||||
|
battery_warn_bg->border.color.rgb[2] = 0.0;
|
||||||
|
} else {
|
||||||
|
battery_warn_bg->fill_color.rgb[0] = 0.9;
|
||||||
|
battery_warn_bg->fill_color.rgb[1] = 0.7;
|
||||||
|
battery_warn_bg->fill_color.rgb[2] = 0.1;
|
||||||
|
battery_warn_bg->border.color.rgb[0] = 0.7;
|
||||||
|
battery_warn_bg->border.color.rgb[1] = 0.5;
|
||||||
|
battery_warn_bg->border.color.rgb[2] = 0.1;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < num_panels; i++) {
|
||||||
|
if (panels[i].battery.area.on_screen) {
|
||||||
|
panels[i].battery.area.bg = battery_warn_bg;
|
||||||
|
schedule_redraw(&panels[i].battery.area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void update_battery_tick(void *arg)
|
void update_battery_tick(void *arg)
|
||||||
{
|
{
|
||||||
if (!battery_enabled)
|
if (!battery_enabled)
|
||||||
@@ -318,6 +364,7 @@ void update_battery_tick(void *arg)
|
|||||||
gboolean old_ac_connected = battery_state.ac_connected;
|
gboolean old_ac_connected = battery_state.ac_connected;
|
||||||
int16_t old_hours = battery_state.time.hours;
|
int16_t old_hours = battery_state.time.hours;
|
||||||
int8_t old_minutes = battery_state.time.minutes;
|
int8_t old_minutes = battery_state.time.minutes;
|
||||||
|
gboolean old_warn = battery_warn;
|
||||||
|
|
||||||
if (!battery_found) {
|
if (!battery_found) {
|
||||||
init_battery();
|
init_battery();
|
||||||
@@ -355,6 +402,20 @@ void update_battery_tick(void *arg)
|
|||||||
battery_full_cmd_sent = FALSE;
|
battery_full_cmd_sent = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!battery_blink_timer.enabled_) {
|
||||||
|
if (battery_state.percentage < battery_low_status &&
|
||||||
|
battery_state.state == BATTERY_DISCHARGING) {
|
||||||
|
change_timer(&battery_blink_timer, true, 10, 1000, blink_battery, 0);
|
||||||
|
battery_warn = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (battery_state.percentage > battery_low_status ||
|
||||||
|
battery_state.state != BATTERY_DISCHARGING) {
|
||||||
|
stop_timer(&battery_blink_timer);
|
||||||
|
battery_warn = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_panels; i++) {
|
for (int i = 0; i < num_panels; i++) {
|
||||||
// Show/hide if needed
|
// Show/hide if needed
|
||||||
if (!battery_found) {
|
if (!battery_found) {
|
||||||
@@ -368,8 +429,11 @@ void update_battery_tick(void *arg)
|
|||||||
// Redraw if needed
|
// Redraw if needed
|
||||||
if (panels[i].battery.area.on_screen) {
|
if (panels[i].battery.area.on_screen) {
|
||||||
if (old_found != battery_found || old_percentage != battery_state.percentage ||
|
if (old_found != battery_found || old_percentage != battery_state.percentage ||
|
||||||
old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes) {
|
old_hours != battery_state.time.hours || old_minutes != battery_state.time.minutes ||
|
||||||
|
old_warn != battery_warn) {
|
||||||
panels[i].battery.area.resize_needed = TRUE;
|
panels[i].battery.area.resize_needed = TRUE;
|
||||||
|
if (!battery_warn)
|
||||||
|
panels[i].battery.area.bg = panel_config.battery.area.bg;
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,6 +484,7 @@ gboolean resize_battery(void *obj)
|
|||||||
void draw_battery(void *obj, cairo_t *c)
|
void draw_battery(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Battery *battery = (Battery *)obj;
|
Battery *battery = (Battery *)obj;
|
||||||
|
Panel *panel = (Panel *)battery->area.panel;
|
||||||
draw_text_area(&battery->area,
|
draw_text_area(&battery->area,
|
||||||
c,
|
c,
|
||||||
buf_bat_line1,
|
buf_bat_line1,
|
||||||
@@ -428,7 +493,8 @@ void draw_battery(void *obj, cairo_t *c)
|
|||||||
bat2_font_desc,
|
bat2_font_desc,
|
||||||
battery->bat1_posy,
|
battery->bat1_posy,
|
||||||
battery->bat2_posy,
|
battery->bat2_posy,
|
||||||
&battery->font_color);
|
&battery->font_color,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void battery_dump_geometry(void *obj, int indent)
|
void battery_dump_geometry(void *obj, int indent)
|
||||||
|
|||||||
+30
-23
@@ -269,9 +269,9 @@ int button_compute_desired_size(void *obj)
|
|||||||
{
|
{
|
||||||
Button *button = (Button *)obj;
|
Button *button = (Button *)obj;
|
||||||
Panel *panel = (Panel *)button->area.panel;
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy);
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy) * panel->scale;
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
||||||
int interior_padding = button->area.paddingx;
|
int interior_padding = button->area.paddingx * panel->scale;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -280,18 +280,17 @@ int button_compute_desired_size(void *obj)
|
|||||||
else
|
else
|
||||||
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
||||||
if (button->backend->max_icon_size) {
|
if (button->backend->max_icon_size) {
|
||||||
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
icon_w = MIN(icon_w, button->backend->max_icon_size * panel->scale);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -300,10 +299,11 @@ int button_compute_desired_size(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
} else {
|
} else {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -313,10 +313,12 @@ int button_compute_desired_size(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
txt_height_ink = txt_height = txt_width = 0;
|
txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -336,9 +338,9 @@ gboolean resize_button(void *obj)
|
|||||||
Button *button = (Button *)obj;
|
Button *button = (Button *)obj;
|
||||||
Panel *panel = (Panel *)button->area.panel;
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
Area *area = &button->area;
|
Area *area = &button->area;
|
||||||
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy);
|
int horiz_padding = (panel_horizontal ? button->area.paddingxlr : button->area.paddingy) * panel->scale;
|
||||||
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr);
|
int vert_padding = (panel_horizontal ? button->area.paddingy : button->area.paddingxlr) * panel->scale;
|
||||||
int interior_padding = button->area.paddingx;
|
int interior_padding = button->area.paddingx * panel->scale;
|
||||||
|
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
if (button->backend->icon_name) {
|
if (button->backend->icon_name) {
|
||||||
@@ -347,8 +349,8 @@ gboolean resize_button(void *obj)
|
|||||||
else
|
else
|
||||||
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
icon_h = icon_w = button->area.width - left_right_border_width(&button->area) - 2 * horiz_padding;
|
||||||
if (button->backend->max_icon_size) {
|
if (button->backend->max_icon_size) {
|
||||||
icon_w = MIN(icon_w, button->backend->max_icon_size);
|
icon_w = MIN(icon_w, button->backend->max_icon_size * panel->scale);
|
||||||
icon_h = MIN(icon_h, button->backend->max_icon_size);
|
icon_h = MIN(icon_h, button->backend->max_icon_size * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
icon_h = icon_w = 0;
|
icon_h = icon_w = 0;
|
||||||
@@ -369,10 +371,9 @@ gboolean resize_button(void *obj)
|
|||||||
available_h = panel->area.height;
|
available_h = panel->area.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
get_text_size2(button->backend->font_desc,
|
get_text_size2(button->backend->font_desc,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -381,9 +382,11 @@ gboolean resize_button(void *obj)
|
|||||||
strlen(button->backend->text),
|
strlen(button->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
} else {
|
} else {
|
||||||
txt_height_ink = txt_height = txt_width = 0;
|
txt_height = txt_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
@@ -436,6 +439,7 @@ gboolean resize_button(void *obj)
|
|||||||
void draw_button(void *obj, cairo_t *c)
|
void draw_button(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Button *button = obj;
|
Button *button = obj;
|
||||||
|
Panel *panel = (Panel *)button->area.panel;
|
||||||
|
|
||||||
if (button->frontend->icon) {
|
if (button->frontend->icon) {
|
||||||
// Render icon
|
// Render icon
|
||||||
@@ -457,10 +461,12 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
// Render text
|
// Render text
|
||||||
if (button->backend->text) {
|
if (button->backend->text) {
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_font_description(layout, button->backend->font_desc);
|
pango_layout_set_font_description(layout, button->backend->font_desc);
|
||||||
pango_layout_set_width(layout, (button->frontend->textw + 1) * PANGO_SCALE);
|
pango_layout_set_width(layout, (button->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
pango_layout_set_alignment(layout, button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
pango_layout_set_alignment(layout, button->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
||||||
@@ -472,9 +478,10 @@ void draw_button(void *obj, cairo_t *c)
|
|||||||
button->frontend->textx,
|
button->frontend->textx,
|
||||||
button->frontend->texty,
|
button->frontend->texty,
|
||||||
&button->backend->font_color,
|
&button->backend->font_color,
|
||||||
panel_config.font_shadow);
|
panel_config.font_shadow ? layout : NULL);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -173,7 +173,13 @@ gboolean time_format_needs_sec_ticks(char *time_format)
|
|||||||
{
|
{
|
||||||
if (!time_format)
|
if (!time_format)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (strchr(time_format, 'S') || strchr(time_format, 'T') || strchr(time_format, 'r'))
|
if (strchr(time_format, 'c') ||
|
||||||
|
strchr(time_format, 'r') ||
|
||||||
|
strchr(time_format, 's') ||
|
||||||
|
strchr(time_format, 'S') ||
|
||||||
|
strchr(time_format, 'T') ||
|
||||||
|
strchr(time_format, 'X') ||
|
||||||
|
strchr(time_format, '+'))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -261,10 +267,8 @@ void clock_default_font_changed()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void clock_compute_text_geometry(Clock *clock,
|
void clock_compute_text_geometry(Clock *clock,
|
||||||
int *time_height_ink,
|
|
||||||
int *time_height,
|
int *time_height,
|
||||||
int *time_width,
|
int *time_width,
|
||||||
int *date_height_ink,
|
|
||||||
int *date_height,
|
int *date_height,
|
||||||
int *date_width)
|
int *date_width)
|
||||||
{
|
{
|
||||||
@@ -273,10 +277,8 @@ void clock_compute_text_geometry(Clock *clock,
|
|||||||
time2_format ? buf_date : NULL,
|
time2_format ? buf_date : NULL,
|
||||||
time1_font_desc,
|
time1_font_desc,
|
||||||
time2_font_desc,
|
time2_font_desc,
|
||||||
time_height_ink,
|
|
||||||
time_height,
|
time_height,
|
||||||
time_width,
|
time_width,
|
||||||
date_height_ink,
|
|
||||||
date_height,
|
date_height,
|
||||||
date_width);
|
date_width);
|
||||||
}
|
}
|
||||||
@@ -306,6 +308,7 @@ gboolean resize_clock(void *obj)
|
|||||||
void draw_clock(void *obj, cairo_t *c)
|
void draw_clock(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Clock *clock = (Clock *)obj;
|
Clock *clock = (Clock *)obj;
|
||||||
|
Panel *panel = (Panel *)clock->area.panel;
|
||||||
draw_text_area(&clock->area,
|
draw_text_area(&clock->area,
|
||||||
c,
|
c,
|
||||||
buf_time,
|
buf_time,
|
||||||
@@ -314,7 +317,8 @@ void draw_clock(void *obj, cairo_t *c)
|
|||||||
time2_font_desc,
|
time2_font_desc,
|
||||||
clock->time1_posy,
|
clock->time1_posy,
|
||||||
clock->time2_posy,
|
clock->time2_posy,
|
||||||
&clock->font);
|
&clock->font,
|
||||||
|
panel->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clock_dump_geometry(void *obj, int indent)
|
void clock_dump_geometry(void *obj, int indent)
|
||||||
|
|||||||
+7
-1
@@ -244,7 +244,11 @@ void add_entry(char *key, char *value)
|
|||||||
char *value1 = 0, *value2 = 0, *value3 = 0;
|
char *value1 = 0, *value2 = 0, *value3 = 0;
|
||||||
|
|
||||||
/* Background and border */
|
/* Background and border */
|
||||||
if (strcmp(key, "rounded") == 0) {
|
if (strcmp(key, "scale_relative_to_dpi") == 0) {
|
||||||
|
ui_scale_dpi_ref = atof(value);
|
||||||
|
} else if (strcmp(key, "scale_relative_to_screen_height") == 0) {
|
||||||
|
ui_scale_monitor_size_ref = atof(value);
|
||||||
|
} else if (strcmp(key, "rounded") == 0) {
|
||||||
// 'rounded' is the first parameter => alloc a new background
|
// 'rounded' is the first parameter => alloc a new background
|
||||||
if (backgrounds->len > 0) {
|
if (backgrounds->len > 0) {
|
||||||
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
||||||
@@ -1012,6 +1016,8 @@ void add_entry(char *key, char *value)
|
|||||||
taskbar_sort_method = TASKBAR_SORT_CENTER;
|
taskbar_sort_method = TASKBAR_SORT_CENTER;
|
||||||
} else if (strcmp(value, "title") == 0) {
|
} else if (strcmp(value, "title") == 0) {
|
||||||
taskbar_sort_method = TASKBAR_SORT_TITLE;
|
taskbar_sort_method = TASKBAR_SORT_TITLE;
|
||||||
|
} else if (strcmp(value, "application") == 0) {
|
||||||
|
taskbar_sort_method = TASKBAR_SORT_APPLICATION;
|
||||||
} else if (strcmp(value, "lru") == 0) {
|
} else if (strcmp(value, "lru") == 0) {
|
||||||
taskbar_sort_method = TASKBAR_SORT_LRU;
|
taskbar_sort_method = TASKBAR_SORT_LRU;
|
||||||
} else if (strcmp(value, "mru") == 0) {
|
} else if (strcmp(value, "mru") == 0) {
|
||||||
|
|||||||
+62
-21
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#define MAX_TOOLTIP_LEN 4096
|
#define MAX_TOOLTIP_LEN 4096
|
||||||
|
|
||||||
|
bool debug_executors = false;
|
||||||
|
|
||||||
void execp_timer_callback(void *arg);
|
void execp_timer_callback(void *arg);
|
||||||
char *execp_get_tooltip(void *obj);
|
char *execp_get_tooltip(void *obj);
|
||||||
void execp_init_fonts();
|
void execp_init_fonts();
|
||||||
@@ -304,7 +306,6 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
int *icon_w,
|
int *icon_w,
|
||||||
int *icon_h,
|
int *icon_h,
|
||||||
gboolean *text_next_line,
|
gboolean *text_next_line,
|
||||||
int *txt_height_ink,
|
|
||||||
int *txt_height,
|
int *txt_height,
|
||||||
int *txt_width,
|
int *txt_width,
|
||||||
int *new_size,
|
int *new_size,
|
||||||
@@ -312,9 +313,9 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
{
|
{
|
||||||
Panel *panel = (Panel *)execp->area.panel;
|
Panel *panel = (Panel *)execp->area.panel;
|
||||||
Area *area = &execp->area;
|
Area *area = &execp->area;
|
||||||
*horiz_padding = (panel_horizontal ? area->paddingxlr : area->paddingy);
|
*horiz_padding = (panel_horizontal ? area->paddingxlr : area->paddingy) * panel->scale;
|
||||||
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr);
|
*vert_padding = (panel_horizontal ? area->paddingy : area->paddingxlr) * panel->scale;
|
||||||
*interior_padding = area->paddingx;
|
*interior_padding = area->paddingx * panel->scale;
|
||||||
|
|
||||||
if (reload_icon(execp)) {
|
if (reload_icon(execp)) {
|
||||||
if (execp->backend->icon) {
|
if (execp->backend->icon) {
|
||||||
@@ -333,7 +334,7 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
int available_w, available_h;
|
int available_w, available_h;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
available_w = panel->area.width;
|
available_w = panel->area.width;
|
||||||
available_h = area->height - 2 * area->paddingy - left_right_border_width(area);
|
available_h = area->height - 2 * *vert_padding - left_right_border_width(area);
|
||||||
} else {
|
} else {
|
||||||
available_w = !text_next_line
|
available_w = !text_next_line
|
||||||
? area->width - *icon_w - (*icon_w ? *interior_padding : 0) - 2 * *horiz_padding -
|
? area->width - *icon_w - (*icon_w ? *interior_padding : 0) - 2 * *horiz_padding -
|
||||||
@@ -342,7 +343,6 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
available_h = panel->area.height;
|
available_h = panel->area.height;
|
||||||
}
|
}
|
||||||
get_text_size2(execp->backend->font_desc,
|
get_text_size2(execp->backend->font_desc,
|
||||||
txt_height_ink,
|
|
||||||
txt_height,
|
txt_height,
|
||||||
txt_width,
|
txt_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -351,7 +351,9 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
strlen(execp->backend->text),
|
strlen(execp->backend->text),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
execp->backend->has_markup);
|
execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
execp->backend->has_markup,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
*resized = FALSE;
|
*resized = FALSE;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -371,7 +373,11 @@ void execp_compute_icon_text_geometry(Execp *execp,
|
|||||||
*new_size = *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
*new_size = *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
||||||
*new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area));
|
*new_size = MAX(*new_size, *icon_h + 2 * *vert_padding + top_bottom_border_width(area));
|
||||||
} else {
|
} else {
|
||||||
|
if (strlen(execp->backend->text)) {
|
||||||
*new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
*new_size = *icon_h + *interior_padding + *txt_height + 2 * *vert_padding + top_bottom_border_width(area);
|
||||||
|
} else {
|
||||||
|
*new_size = *icon_h + 2 * *vert_padding + top_bottom_border_width(area);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (*new_size != area->height) {
|
if (*new_size != area->height) {
|
||||||
*resized = TRUE;
|
*resized = TRUE;
|
||||||
@@ -385,7 +391,7 @@ int execp_compute_desired_size(void *obj)
|
|||||||
int horiz_padding, vert_padding, interior_padding;
|
int horiz_padding, vert_padding, interior_padding;
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
gboolean text_next_line;
|
gboolean text_next_line;
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
int new_size;
|
int new_size;
|
||||||
gboolean resized;
|
gboolean resized;
|
||||||
execp_compute_icon_text_geometry(execp,
|
execp_compute_icon_text_geometry(execp,
|
||||||
@@ -395,7 +401,6 @@ int execp_compute_desired_size(void *obj)
|
|||||||
&icon_w,
|
&icon_w,
|
||||||
&icon_h,
|
&icon_h,
|
||||||
&text_next_line,
|
&text_next_line,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
&new_size,
|
&new_size,
|
||||||
@@ -410,7 +415,7 @@ gboolean resize_execp(void *obj)
|
|||||||
int horiz_padding, vert_padding, interior_padding;
|
int horiz_padding, vert_padding, interior_padding;
|
||||||
int icon_w, icon_h;
|
int icon_w, icon_h;
|
||||||
gboolean text_next_line;
|
gboolean text_next_line;
|
||||||
int txt_height_ink, txt_height, txt_width;
|
int txt_height, txt_width;
|
||||||
int new_size;
|
int new_size;
|
||||||
gboolean resized;
|
gboolean resized;
|
||||||
execp_compute_icon_text_geometry(execp,
|
execp_compute_icon_text_geometry(execp,
|
||||||
@@ -420,7 +425,6 @@ gboolean resize_execp(void *obj)
|
|||||||
&icon_w,
|
&icon_w,
|
||||||
&icon_h,
|
&icon_h,
|
||||||
&text_next_line,
|
&text_next_line,
|
||||||
&txt_height_ink,
|
|
||||||
&txt_height,
|
&txt_height,
|
||||||
&txt_width,
|
&txt_width,
|
||||||
&new_size,
|
&new_size,
|
||||||
@@ -441,10 +445,17 @@ gboolean resize_execp(void *obj)
|
|||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
||||||
} else {
|
} else {
|
||||||
|
if (strlen(execp->backend->text)) {
|
||||||
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
||||||
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
||||||
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
execp->frontend->textx = (execp->area.width - txt_width) / 2;
|
execp->frontend->textx = (execp->area.width - txt_width) / 2;
|
||||||
|
} else {
|
||||||
|
execp->frontend->icony = (execp->area.height - icon_h) / 2;
|
||||||
|
execp->frontend->iconx = (execp->area.width - icon_w) / 2;
|
||||||
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
|
execp->frontend->textx = (execp->area.width - txt_width) / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
@@ -458,10 +469,17 @@ gboolean resize_execp(void *obj)
|
|||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
execp->frontend->textx = execp->frontend->iconx + icon_w + interior_padding;
|
||||||
} else {
|
} else {
|
||||||
|
if (strlen(execp->backend->text)) {
|
||||||
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
execp->frontend->icony = (execp->area.height - icon_h - interior_padding - txt_height) / 2;
|
||||||
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
||||||
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
execp->frontend->textx = execp->frontend->iconx;
|
execp->frontend->textx = execp->frontend->iconx;
|
||||||
|
} else {
|
||||||
|
execp->frontend->icony = (execp->area.height - icon_h) / 2;
|
||||||
|
execp->frontend->iconx = left_border_width(&execp->area) + horiz_padding;
|
||||||
|
execp->frontend->texty = execp->frontend->icony + icon_h + interior_padding;
|
||||||
|
execp->frontend->textx = execp->frontend->iconx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
execp->frontend->texty = (execp->area.height - txt_height) / 2;
|
||||||
@@ -473,10 +491,27 @@ gboolean resize_execp(void *obj)
|
|||||||
return resized;
|
return resized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PangoLayout *create_execp_text_layout(Execp *execp, PangoContext *context)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
pango_layout_set_font_description(layout, execp->backend->font_desc);
|
||||||
|
pango_layout_set_width(layout, (execp->frontend->textw + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
|
pango_layout_set_height(layout, (execp->frontend->texth + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
|
pango_layout_set_alignment(layout, execp->backend->centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT);
|
||||||
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
void draw_execp(void *obj, cairo_t *c)
|
void draw_execp(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
Execp *execp = (Execp *)obj;
|
Execp *execp = (Execp *)obj;
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
Panel *panel = (Panel *)execp->area.panel;
|
||||||
|
|
||||||
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = create_execp_text_layout(execp, context);
|
||||||
|
PangoLayout *shadow_layout = NULL;
|
||||||
|
|
||||||
if (execp->backend->has_icon && execp->backend->icon) {
|
if (execp->backend->has_icon && execp->backend->icon) {
|
||||||
imlib_context_set_image(execp->backend->icon);
|
imlib_context_set_image(execp->backend->icon);
|
||||||
@@ -485,15 +520,18 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw layout
|
// draw layout
|
||||||
pango_layout_set_font_description(layout, execp->backend->font_desc);
|
if (!execp->backend->has_markup) {
|
||||||
pango_layout_set_width(layout, (execp->frontend->textw + 1) * 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,
|
||||||
@@ -501,9 +539,10 @@ void draw_execp(void *obj, cairo_t *c)
|
|||||||
execp->frontend->textx,
|
execp->frontend->textx,
|
||||||
execp->frontend->texty,
|
execp->frontend->texty,
|
||||||
&execp->backend->font_color,
|
&execp->backend->font_color,
|
||||||
panel_config.font_shadow);
|
shadow_layout);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execp_dump_geometry(void *obj, int indent)
|
void execp_dump_geometry(void *obj, int indent)
|
||||||
@@ -525,12 +564,13 @@ void execp_dump_geometry(void *obj, int indent)
|
|||||||
imlib_context_set_image(tmp);
|
imlib_context_set_image(tmp);
|
||||||
}
|
}
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"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);
|
||||||
}
|
}
|
||||||
@@ -631,6 +671,7 @@ void execp_timer_callback(void *arg)
|
|||||||
close(pipe_fd_stderr[0]);
|
close(pipe_fd_stderr[0]);
|
||||||
return;
|
return;
|
||||||
} else if (child == 0) {
|
} else if (child == 0) {
|
||||||
|
if (debug_executors)
|
||||||
fprintf(stderr, "tint2: Executing: %s\n", execp->backend->command);
|
fprintf(stderr, "tint2: Executing: %s\n", execp->backend->command);
|
||||||
// We are in the child
|
// We are in the child
|
||||||
close(pipe_fd_stdout[0]);
|
close(pipe_fd_stdout[0]);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
extern bool debug_executors;
|
||||||
|
|
||||||
// Architecture:
|
// Architecture:
|
||||||
// Panel panel_config contains an array of Execp, each storing all config options and all the state variables.
|
// Panel panel_config contains an array of Execp, each storing all config options and all the state variables.
|
||||||
// Only these run commands.
|
// Only these run commands.
|
||||||
|
|||||||
@@ -65,14 +65,14 @@ void cleanup_freespace(Panel *panel)
|
|||||||
panel->freespace_list = NULL;
|
panel->freespace_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int freespace_get_max_size(Panel *p)
|
int freespace_get_max_size(Panel *panel)
|
||||||
{
|
{
|
||||||
if (panel_shrink)
|
if (panel_shrink)
|
||||||
return 0;
|
return 0;
|
||||||
// Get space used by every element except the freespace
|
// Get space used by every element except the freespace
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int spacers = 0;
|
int spacers = 0;
|
||||||
for (GList *walk = p->area.children; walk; walk = g_list_next(walk)) {
|
for (GList *walk = panel->area.children; walk; walk = g_list_next(walk)) {
|
||||||
Area *a = (Area *)walk->data;
|
Area *a = (Area *)walk->data;
|
||||||
|
|
||||||
if (!a->on_screen)
|
if (!a->on_screen)
|
||||||
@@ -83,15 +83,15 @@ int freespace_get_max_size(Panel *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size += a->width + p->area.paddingx;
|
size += a->width + panel->area.paddingx * panel->scale;
|
||||||
else
|
else
|
||||||
size += a->height + p->area.paddingy;
|
size += a->height + panel->area.paddingy * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
size = p->area.width - size - left_right_border_width(&p->area) - p->area.paddingxlr;
|
size = panel->area.width - size - left_right_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
||||||
else
|
else
|
||||||
size = p->area.height - size - top_bottom_border_width(&p->area) - p->area.paddingxlr;
|
size = panel->area.height - size - top_bottom_border_width(&panel->area) - panel->area.paddingxlr * panel->scale;
|
||||||
|
|
||||||
return size / spacers;
|
return size / spacers;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -106,6 +106,7 @@ void handle_env_vars()
|
|||||||
debug_dnd = getenv("DEBUG_DND") != NULL;
|
debug_dnd = getenv("DEBUG_DND") != NULL;
|
||||||
debug_thumbnails = getenv("DEBUG_THUMBNAILS") != NULL;
|
debug_thumbnails = getenv("DEBUG_THUMBNAILS") != NULL;
|
||||||
debug_timers = getenv("DEBUG_TIMERS") != NULL;
|
debug_timers = getenv("DEBUG_TIMERS") != NULL;
|
||||||
|
debug_executors = getenv("DEBUG_EXECUTORS") != NULL;
|
||||||
if (debug_fps) {
|
if (debug_fps) {
|
||||||
init_fps_distribution();
|
init_fps_distribution();
|
||||||
char *s = getenv("TRACING_FPS_THRESHOLD");
|
char *s = getenv("TRACING_FPS_THRESHOLD");
|
||||||
@@ -208,8 +209,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);
|
||||||
@@ -246,8 +247,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();
|
||||||
|
|||||||
+31
-23
@@ -112,7 +112,7 @@ void init_launcher_panel(void *p)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// This will be recomputed on resize, we just initialize to a non-zero value
|
// This will be recomputed on resize, we just initialize to a non-zero value
|
||||||
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size : 24;
|
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size * panel->scale : 24;
|
||||||
|
|
||||||
launcher->area.on_screen = TRUE;
|
launcher->area.on_screen = TRUE;
|
||||||
schedule_panel_redraw();
|
schedule_panel_redraw();
|
||||||
@@ -174,11 +174,12 @@ void cleanup_launcher_theme(Launcher *launcher)
|
|||||||
|
|
||||||
int launcher_compute_icon_size(Launcher *launcher)
|
int launcher_compute_icon_size(Launcher *launcher)
|
||||||
{
|
{
|
||||||
|
Panel *panel = launcher->area.panel;
|
||||||
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
|
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
|
||||||
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
|
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
|
||||||
(2 * launcher->area.paddingy);
|
(2 * launcher->area.paddingy * panel->scale);
|
||||||
if (launcher_max_icon_size > 0 && icon_size > launcher_max_icon_size)
|
if (launcher_max_icon_size)
|
||||||
icon_size = launcher_max_icon_size;
|
icon_size = MIN(icon_size, launcher_max_icon_size * panel->scale);
|
||||||
return icon_size;
|
return icon_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ void launcher_compute_geometry(Launcher *launcher,
|
|||||||
int *icons_per_row,
|
int *icons_per_row,
|
||||||
int *margin)
|
int *margin)
|
||||||
{
|
{
|
||||||
|
Panel *panel = (Panel*)launcher->area.panel;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (GSList *l = launcher->list_icons; l; l = l->next) {
|
for (GSList *l = launcher->list_icons; l; l = l->next) {
|
||||||
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
||||||
@@ -204,25 +206,25 @@ void launcher_compute_geometry(Launcher *launcher,
|
|||||||
if (!count) {
|
if (!count) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
} else {
|
} else {
|
||||||
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy * panel->scale;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
*icons_per_column = (height + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
*icons_per_column = (height + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
||||||
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
|
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
||||||
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
|
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
|
||||||
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr * panel->scale +
|
||||||
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx);
|
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!count) {
|
if (!count) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
} else {
|
} else {
|
||||||
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
|
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy * panel->scale;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
*icons_per_row = (width + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
|
*icons_per_row = (width + launcher->area.paddingx * panel->scale) / (*icon_size + launcher->area.paddingx * panel->scale);
|
||||||
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
|
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx * panel->scale) - *icon_size;
|
||||||
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
|
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
|
||||||
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
|
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr * panel->scale +
|
||||||
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx);
|
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,6 +241,7 @@ int launcher_compute_desired_size(void *obj)
|
|||||||
gboolean resize_launcher(void *obj)
|
gboolean resize_launcher(void *obj)
|
||||||
{
|
{
|
||||||
Launcher *launcher = (Launcher *)obj;
|
Launcher *launcher = (Launcher *)obj;
|
||||||
|
Panel *panel = (Panel*)launcher->area.panel;
|
||||||
|
|
||||||
int size, icons_per_column, icons_per_row, margin;
|
int size, icons_per_column, icons_per_row, margin;
|
||||||
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
|
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
|
||||||
@@ -281,11 +284,11 @@ gboolean resize_launcher(void *obj)
|
|||||||
int posx, posy;
|
int posx, posy;
|
||||||
int start;
|
int start;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy * panel->scale + margin / 2;
|
||||||
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr;
|
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
|
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy * panel->scale + margin / 2;
|
||||||
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
|
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -300,17 +303,17 @@ gboolean resize_launcher(void *obj)
|
|||||||
// fprintf(stderr, "tint2: launcher %d : %d,%d\n", i, posx, posy);
|
// fprintf(stderr, "tint2: launcher %d : %d,%d\n", i, posx, posy);
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (i % icons_per_column) {
|
if (i % icons_per_column) {
|
||||||
posy += launcher->icon_size + launcher->area.paddingx;
|
posy += launcher->icon_size + launcher->area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (launcher->icon_size + launcher->area.paddingx);
|
posx += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % icons_per_row) {
|
if (i % icons_per_row) {
|
||||||
posx += launcher->icon_size + launcher->area.paddingx;
|
posx += launcher->icon_size + launcher->area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (launcher->icon_size + launcher->area.paddingx);
|
posy += (launcher->icon_size + launcher->area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,7 +399,12 @@ void launcher_icon_dump_geometry(void *obj, int indent)
|
|||||||
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
|
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
|
||||||
{
|
{
|
||||||
Imlib_Image icon_scaled;
|
Imlib_Image icon_scaled;
|
||||||
if (original) {
|
if (!icon_size) {
|
||||||
|
icon_scaled = imlib_create_image(1, 1);
|
||||||
|
imlib_context_set_image(icon_scaled);
|
||||||
|
imlib_context_set_color(255, 255, 255, 255);
|
||||||
|
imlib_image_fill_rectangle(0, 0, icon_size, icon_size);
|
||||||
|
} else if (original) {
|
||||||
imlib_context_set_image(original);
|
imlib_context_set_image(original);
|
||||||
icon_scaled = imlib_create_cropped_scaled_image(0,
|
icon_scaled = imlib_create_cropped_scaled_image(0,
|
||||||
0,
|
0,
|
||||||
|
|||||||
+39
-4
@@ -79,11 +79,16 @@ int num_panels;
|
|||||||
GArray *backgrounds;
|
GArray *backgrounds;
|
||||||
GArray *gradients;
|
GArray *gradients;
|
||||||
|
|
||||||
|
double ui_scale_dpi_ref;
|
||||||
|
double ui_scale_monitor_size_ref;
|
||||||
|
|
||||||
Imlib_Image default_icon;
|
Imlib_Image default_icon;
|
||||||
char *default_font = NULL;
|
char *default_font = NULL;
|
||||||
|
|
||||||
void default_panel()
|
void default_panel()
|
||||||
{
|
{
|
||||||
|
ui_scale_dpi_ref = 0;
|
||||||
|
ui_scale_monitor_size_ref = 0;
|
||||||
panels = NULL;
|
panels = NULL;
|
||||||
num_panels = 0;
|
num_panels = 0;
|
||||||
default_icon = NULL;
|
default_icon = NULL;
|
||||||
@@ -218,6 +223,17 @@ void init_panel()
|
|||||||
|
|
||||||
if (panel_config.monitor < 0)
|
if (panel_config.monitor < 0)
|
||||||
p->monitor = i;
|
p->monitor = i;
|
||||||
|
if (ui_scale_dpi_ref > 0 && server.monitors[p->monitor].dpi > 0)
|
||||||
|
p->scale = server.monitors[p->monitor].dpi / ui_scale_dpi_ref;
|
||||||
|
else
|
||||||
|
p->scale = 1;
|
||||||
|
if (ui_scale_monitor_size_ref > 0)
|
||||||
|
p->scale *= server.monitors[p->monitor].height / ui_scale_monitor_size_ref;
|
||||||
|
if (p->scale > 8 || p->scale < 1./8) {
|
||||||
|
fprintf(stderr, RED "tint2: panel %d having scale %g outside bounds, resetting to 1.0" RESET "\n", i + 1, p->scale);
|
||||||
|
p->scale = 1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, BLUE "tint2: panel %d uses scale %g " RESET "\n", i + 1, p->scale);
|
||||||
if (!p->area.bg)
|
if (!p->area.bg)
|
||||||
p->area.bg = &g_array_index(backgrounds, Background, 0);
|
p->area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
p->area.parent = p;
|
p->area.parent = p;
|
||||||
@@ -355,6 +371,19 @@ void panel_compute_size(Panel *panel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!panel->fractional_width) {
|
||||||
|
if (panel_horizontal)
|
||||||
|
panel->area.width *= panel->scale;
|
||||||
|
else
|
||||||
|
panel->area.height *= panel->scale;
|
||||||
|
}
|
||||||
|
if (!panel->fractional_height) {
|
||||||
|
if (panel_horizontal)
|
||||||
|
panel->area.height *= panel->scale;
|
||||||
|
else
|
||||||
|
panel->area.width *= panel->scale;
|
||||||
|
}
|
||||||
|
|
||||||
if (panel->area.width + panel->marginx > server.monitors[panel->monitor].width)
|
if (panel->area.width + panel->marginx > server.monitors[panel->monitor].width)
|
||||||
panel->area.width = server.monitors[panel->monitor].width - panel->marginx;
|
panel->area.width = server.monitors[panel->monitor].width - panel->marginx;
|
||||||
if (panel->area.height + panel->marginy > server.monitors[panel->monitor].height)
|
if (panel->area.height + panel->marginy > server.monitors[panel->monitor].height)
|
||||||
@@ -449,9 +478,9 @@ gboolean resize_panel(void *obj)
|
|||||||
if (!taskbar->area.on_screen)
|
if (!taskbar->area.on_screen)
|
||||||
continue;
|
continue;
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
taskbar->area.width = 2 * taskbar->area.paddingxlr;
|
taskbar->area.width = 2 * taskbar->area.paddingxlr * panel->scale;
|
||||||
else
|
else
|
||||||
taskbar->area.height = 2 * taskbar->area.paddingxlr;
|
taskbar->area.height = 2 * taskbar->area.paddingxlr * panel->scale;
|
||||||
if (taskbarname_enabled && taskbar->area.children) {
|
if (taskbarname_enabled && taskbar->area.children) {
|
||||||
Area *name = (Area *)taskbar->area.children->data;
|
Area *name = (Area *)taskbar->area.children->data;
|
||||||
if (name->on_screen) {
|
if (name->on_screen) {
|
||||||
@@ -468,9 +497,9 @@ gboolean resize_panel(void *obj)
|
|||||||
continue;
|
continue;
|
||||||
if (!first_child) {
|
if (!first_child) {
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
taskbar->area.width += taskbar->area.paddingx;
|
taskbar->area.width += taskbar->area.paddingx * panel->scale;
|
||||||
else
|
else
|
||||||
taskbar->area.height += taskbar->area.paddingy;
|
taskbar->area.height += taskbar->area.paddingy * panel->scale;
|
||||||
}
|
}
|
||||||
first_child = FALSE;
|
first_child = FALSE;
|
||||||
}
|
}
|
||||||
@@ -528,6 +557,8 @@ gboolean resize_panel(void *obj)
|
|||||||
}
|
}
|
||||||
} else if (taskbar_alignment == ALIGN_CENTER) {
|
} else if (taskbar_alignment == ALIGN_CENTER) {
|
||||||
slack /= 2;
|
slack /= 2;
|
||||||
|
Taskbar *left_taskbar = NULL;
|
||||||
|
Taskbar *right_taskbar = NULL;
|
||||||
for (int i = 0; i < panel->num_desktops; i++) {
|
for (int i = 0; i < panel->num_desktops; i++) {
|
||||||
Taskbar *taskbar = &panel->taskbar[i];
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
if (!taskbar->area.on_screen)
|
if (!taskbar->area.on_screen)
|
||||||
@@ -537,6 +568,7 @@ gboolean resize_panel(void *obj)
|
|||||||
else
|
else
|
||||||
taskbar->area.height += slack;
|
taskbar->area.height += slack;
|
||||||
taskbar->area.alignment = ALIGN_RIGHT;
|
taskbar->area.alignment = ALIGN_RIGHT;
|
||||||
|
left_taskbar = taskbar;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (int i = panel->num_desktops - 1; i >= 0; i--) {
|
for (int i = panel->num_desktops - 1; i >= 0; i--) {
|
||||||
@@ -548,8 +580,11 @@ gboolean resize_panel(void *obj)
|
|||||||
else
|
else
|
||||||
taskbar->area.height += slack;
|
taskbar->area.height += slack;
|
||||||
taskbar->area.alignment = ALIGN_LEFT;
|
taskbar->area.alignment = ALIGN_LEFT;
|
||||||
|
right_taskbar = taskbar;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (left_taskbar == right_taskbar)
|
||||||
|
left_taskbar->area.alignment = ALIGN_CENTER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No tasks => expand the first visible taskbar
|
// No tasks => expand the first visible taskbar
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ extern gboolean debug_fps;
|
|||||||
extern double tracing_fps_threshold;
|
extern double tracing_fps_threshold;
|
||||||
extern gboolean debug_frames;
|
extern gboolean debug_frames;
|
||||||
extern gboolean debug_thumbnails;
|
extern gboolean debug_thumbnails;
|
||||||
|
extern double ui_scale_dpi_ref;
|
||||||
|
extern double ui_scale_monitor_size_ref;
|
||||||
|
|
||||||
typedef struct Panel {
|
typedef struct Panel {
|
||||||
Area area;
|
Area area;
|
||||||
@@ -117,6 +119,7 @@ typedef struct Panel {
|
|||||||
int mouse_pressed_alpha;
|
int mouse_pressed_alpha;
|
||||||
int mouse_pressed_saturation;
|
int mouse_pressed_saturation;
|
||||||
int mouse_pressed_brightness;
|
int mouse_pressed_brightness;
|
||||||
|
double scale;
|
||||||
|
|
||||||
// Per-panel parameters and states for Taskbar and Task
|
// Per-panel parameters and states for Taskbar and Task
|
||||||
GlobalTaskbar g_taskbar;
|
GlobalTaskbar g_taskbar;
|
||||||
|
|||||||
@@ -115,31 +115,33 @@ void cleanup_separator()
|
|||||||
int separator_compute_desired_size(void *obj)
|
int separator_compute_desired_size(void *obj)
|
||||||
{
|
{
|
||||||
Separator *separator = (Separator *)obj;
|
Separator *separator = (Separator *)obj;
|
||||||
|
Panel *panel = (Panel*)separator->area.panel;
|
||||||
if (!separator->area.on_screen)
|
if (!separator->area.on_screen)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (panel_horizontal)
|
if (panel_horizontal)
|
||||||
return separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr * panel->scale + left_right_border_width(&separator->area);
|
||||||
else
|
else
|
||||||
return separator->thickness + 2 * separator->area.paddingxlr + top_bottom_border_width(&separator->area);
|
return separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean resize_separator(void *obj)
|
gboolean resize_separator(void *obj)
|
||||||
{
|
{
|
||||||
Separator *separator = (Separator *)obj;
|
Separator *separator = (Separator *)obj;
|
||||||
|
Panel *panel = (Panel*)separator->area.panel;
|
||||||
if (!separator->area.on_screen)
|
if (!separator->area.on_screen)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
separator->area.width =
|
separator->area.width =
|
||||||
separator->thickness + 2 * separator->area.paddingxlr + left_right_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr * panel->scale + left_right_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.height - 2 * separator->area.paddingy - top_bottom_border_width(&separator->area);
|
separator->area.height - 2 * separator->area.paddingy * panel->scale - top_bottom_border_width(&separator->area);
|
||||||
} else {
|
} else {
|
||||||
separator->area.height =
|
separator->area.height =
|
||||||
separator->thickness + 2 * separator->area.paddingxlr + top_bottom_border_width(&separator->area);
|
separator->thickness + 2 * separator->area.paddingxlr * panel->scale + top_bottom_border_width(&separator->area);
|
||||||
separator->length =
|
separator->length =
|
||||||
separator->area.width - 2 * separator->area.paddingy - left_right_border_width(&separator->area);
|
separator->area.width - 2 * separator->area.paddingy * panel->scale - left_right_border_width(&separator->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule_redraw(&separator->area);
|
schedule_redraw(&separator->area);
|
||||||
|
|||||||
+23
-22
@@ -141,11 +141,12 @@ void init_systray_panel(void *p)
|
|||||||
|
|
||||||
void systray_compute_geometry(int *size)
|
void systray_compute_geometry(int *size)
|
||||||
{
|
{
|
||||||
|
Panel *panel = (Panel*)systray.area.panel;
|
||||||
systray.icon_size = panel_horizontal ? systray.area.height : systray.area.width;
|
systray.icon_size = panel_horizontal ? systray.area.height : systray.area.width;
|
||||||
systray.icon_size -=
|
systray.icon_size -=
|
||||||
MAX(left_right_border_width(&systray.area), top_bottom_border_width(&systray.area)) + 2 * systray.area.paddingy;
|
MAX(left_right_border_width(&systray.area), top_bottom_border_width(&systray.area)) + 2 * systray.area.paddingy * panel->scale;
|
||||||
if (systray_max_icon_size > 0)
|
if (systray_max_icon_size > 0)
|
||||||
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size);
|
systray.icon_size = MIN(systray.icon_size, systray_max_icon_size * panel->scale);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (GSList *l = systray.list_icons; l; l = l->next) {
|
for (GSList *l = systray.list_icons; l; l = l->next) {
|
||||||
@@ -153,24 +154,24 @@ void systray_compute_geometry(int *size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
int height = systray.area.height - top_bottom_border_width(&systray.area) - 2 * systray.area.paddingy;
|
int height = systray.area.height - top_bottom_border_width(&systray.area) - 2 * systray.area.paddingy * panel->scale;
|
||||||
// here icons_per_column always higher than 0
|
// here icons_per_column always higher than 0
|
||||||
systray.icons_per_column = (height + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
systray.icons_per_column = (height + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx) - systray.icon_size;
|
height - (systray.icons_per_column - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
||||||
systray.icons_per_row = count / systray.icons_per_column + (count % systray.icons_per_column != 0);
|
systray.icons_per_row = count / systray.icons_per_column + (count % systray.icons_per_column != 0);
|
||||||
*size = left_right_border_width(&systray.area) + 2 * systray.area.paddingxlr +
|
*size = left_right_border_width(&systray.area) + 2 * systray.area.paddingxlr * panel->scale +
|
||||||
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx);
|
(systray.icon_size * systray.icons_per_row) + ((systray.icons_per_row - 1) * systray.area.paddingx * panel->scale);
|
||||||
} else {
|
} else {
|
||||||
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy;
|
int width = systray.area.width - left_right_border_width(&systray.area) - 2 * systray.area.paddingy * panel->scale;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
systray.icons_per_row = (width + systray.area.paddingx) / (systray.icon_size + systray.area.paddingx);
|
systray.icons_per_row = (width + systray.area.paddingx * panel->scale) / (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
systray.margin =
|
systray.margin =
|
||||||
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx) - systray.icon_size;
|
width - (systray.icons_per_row - 1) * (systray.icon_size + systray.area.paddingx * panel->scale) - systray.icon_size;
|
||||||
systray.icons_per_column = count / systray.icons_per_row + (count % systray.icons_per_row != 0);
|
systray.icons_per_column = count / systray.icons_per_row + (count % systray.icons_per_row != 0);
|
||||||
*size = top_bottom_border_width(&systray.area) + (2 * systray.area.paddingxlr) +
|
*size = top_bottom_border_width(&systray.area) + (2 * systray.area.paddingxlr * panel->scale) +
|
||||||
(systray.icon_size * systray.icons_per_column) +
|
(systray.icon_size * systray.icons_per_column) +
|
||||||
((systray.icons_per_column - 1) * systray.area.paddingx);
|
((systray.icons_per_column - 1) * systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,13 +282,13 @@ void on_change_systray(void *obj)
|
|||||||
int posx, posy;
|
int posx, posy;
|
||||||
int start;
|
int start;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
posy = start = top_border_width(&panel->area) + panel->area.paddingy + top_border_width(&systray.area) +
|
posy = start = top_border_width(&panel->area) + panel->area.paddingy * panel->scale + top_border_width(&systray.area) +
|
||||||
systray.area.paddingy + systray.margin / 2;
|
systray.area.paddingy * panel->scale + systray.margin / 2;
|
||||||
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr;
|
posx = systray.area.posx + left_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start = left_border_width(&panel->area) + panel->area.paddingy + left_border_width(&systray.area) +
|
posx = start = left_border_width(&panel->area) + panel->area.paddingy * panel->scale + left_border_width(&systray.area) +
|
||||||
systray.area.paddingy + systray.margin / 2;
|
systray.area.paddingy * panel->scale + systray.margin / 2;
|
||||||
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr;
|
posy = systray.area.posy + top_border_width(&systray.area) + systray.area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrayWindow *traywin;
|
TrayWindow *traywin;
|
||||||
@@ -312,17 +313,17 @@ void on_change_systray(void *obj)
|
|||||||
traywin->height = systray.icon_size;
|
traywin->height = systray.icon_size;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (i % systray.icons_per_column) {
|
if (i % systray.icons_per_column) {
|
||||||
posy += systray.icon_size + systray.area.paddingx;
|
posy += systray.icon_size + systray.area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (systray.icon_size + systray.area.paddingx);
|
posx += (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i % systray.icons_per_row) {
|
if (i % systray.icons_per_row) {
|
||||||
posx += systray.icon_size + systray.area.paddingx;
|
posx += systray.icon_size + systray.area.paddingx * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (systray.icon_size + systray.area.paddingx);
|
posy += (systray.icon_size + systray.area.paddingx * panel->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+32
-10
@@ -107,6 +107,21 @@ Task *add_task(Window win)
|
|||||||
(int)win,
|
(int)win,
|
||||||
task_template.title ? task_template.title : "null");
|
task_template.title ? task_template.title : "null");
|
||||||
|
|
||||||
|
// get application name
|
||||||
|
// use res_class property of WM_CLASS as res_name is easily overridable by user
|
||||||
|
XClassHint *classhint = XAllocClassHint();
|
||||||
|
if (classhint && XGetClassHint(server.display, win, classhint))
|
||||||
|
task_template.application = strdup(classhint->res_class);
|
||||||
|
else
|
||||||
|
task_template.application = strdup("Untitled");
|
||||||
|
if (classhint) {
|
||||||
|
if (classhint->res_name)
|
||||||
|
XFree(classhint->res_name);
|
||||||
|
if (classhint->res_class)
|
||||||
|
XFree(classhint->res_class);
|
||||||
|
XFree(classhint);
|
||||||
|
}
|
||||||
|
|
||||||
GPtrArray *task_buttons = g_ptr_array_new();
|
GPtrArray *task_buttons = g_ptr_array_new();
|
||||||
for (int j = 0; j < panels[monitor].num_desktops; j++) {
|
for (int j = 0; j < panels[monitor].num_desktops; j++) {
|
||||||
if (task_template.desktop != ALL_DESKTOPS && task_template.desktop != j)
|
if (task_template.desktop != ALL_DESKTOPS && task_template.desktop != j)
|
||||||
@@ -132,6 +147,7 @@ Task *add_task(Window win)
|
|||||||
task_instance->area.on_screen = always_show_all_desktop_tasks;
|
task_instance->area.on_screen = always_show_all_desktop_tasks;
|
||||||
}
|
}
|
||||||
task_instance->title = task_template.title;
|
task_instance->title = task_template.title;
|
||||||
|
task_instance->application = task_template.application;
|
||||||
if (panels[monitor].g_task.tooltip_enabled) {
|
if (panels[monitor].g_task.tooltip_enabled) {
|
||||||
task_instance->area._get_tooltip_text = task_get_tooltip;
|
task_instance->area._get_tooltip_text = task_get_tooltip;
|
||||||
task_instance->area._get_tooltip_image = task_get_thumbnail;
|
task_instance->area._get_tooltip_image = task_get_thumbnail;
|
||||||
@@ -208,12 +224,14 @@ void remove_task(Task *task)
|
|||||||
|
|
||||||
Window win = task->win;
|
Window win = task->win;
|
||||||
|
|
||||||
// free title and icon just for the first task
|
// free title, icon and application name just for the first task
|
||||||
// even with task_on_all_desktop and with task_on_all_panel
|
// even with task_on_all_desktop and with task_on_all_panel
|
||||||
if (task->title)
|
if (task->title)
|
||||||
free(task->title);
|
free(task->title);
|
||||||
if (task->thumbnail)
|
if (task->thumbnail)
|
||||||
cairo_surface_destroy(task->thumbnail);
|
cairo_surface_destroy(task->thumbnail);
|
||||||
|
if (task->application)
|
||||||
|
free(task->application);
|
||||||
task_remove_icon(task);
|
task_remove_icon(task);
|
||||||
|
|
||||||
GPtrArray *task_buttons = g_hash_table_lookup(win_to_task, &win);
|
GPtrArray *task_buttons = g_hash_table_lookup(win_to_task, &win);
|
||||||
@@ -381,7 +399,7 @@ void task_update_icon(Task *task)
|
|||||||
task->icon[k] = adjust_icon(orig_image,
|
task->icon[k] = adjust_icon(orig_image,
|
||||||
panel->g_task.alpha[k],
|
panel->g_task.alpha[k],
|
||||||
panel->g_task.saturation[k],
|
panel->g_task.saturation[k],
|
||||||
panel->g_task.brightness[k] != 0);
|
panel->g_task.brightness[k]);
|
||||||
if (panel_config.mouse_effects) {
|
if (panel_config.mouse_effects) {
|
||||||
task->icon_hover[k] = adjust_icon(task->icon[k],
|
task->icon_hover[k] = adjust_icon(task->icon[k],
|
||||||
panel_config.mouse_over_alpha,
|
panel_config.mouse_over_alpha,
|
||||||
@@ -429,7 +447,7 @@ void draw_task_icon(Task *task, int text_width)
|
|||||||
else
|
else
|
||||||
task->_icon_x = (task->area.width - panel->g_task.icon_size1) / 2;
|
task->_icon_x = (task->area.width - panel->g_task.icon_size1) / 2;
|
||||||
} else {
|
} else {
|
||||||
task->_icon_x = left_border_width(&task->area) + task->area.paddingxlr;
|
task->_icon_x = left_border_width(&task->area) + task->area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
@@ -459,11 +477,13 @@ void draw_task(void *obj, cairo_t *c)
|
|||||||
|
|
||||||
task->_text_width = 0;
|
task->_text_width = 0;
|
||||||
if (panel->g_task.has_text) {
|
if (panel->g_task.has_text) {
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, panel->g_task.font_desc);
|
pango_layout_set_font_description(layout, panel->g_task.font_desc);
|
||||||
pango_layout_set_text(layout, task->title, -1);
|
pango_layout_set_text(layout, task->title, -1);
|
||||||
|
|
||||||
pango_layout_set_width(layout, (((Taskbar *)task->area.parent)->text_width + 1) * PANGO_SCALE);
|
pango_layout_set_width(layout, (((Taskbar *)task->area.parent)->text_width + TINT2_PANGO_SLACK) * PANGO_SCALE);
|
||||||
pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE);
|
pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
@@ -477,9 +497,10 @@ void draw_task(void *obj, cairo_t *c)
|
|||||||
task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0;
|
task->_text_posy = (panel->g_task.area.height - task->_text_height) / 2.0;
|
||||||
|
|
||||||
Color *config_text = &panel->g_task.font[task->current_state];
|
Color *config_text = &panel->g_task.font[task->current_state];
|
||||||
draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow);
|
draw_text(layout, c, panel->g_task.text_posx, task->_text_posy, config_text, panel->font_shadow ? layout : NULL);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel->g_task.has_icon)
|
if (panel->g_task.has_icon)
|
||||||
@@ -532,7 +553,7 @@ int task_compute_desired_size(void *obj)
|
|||||||
{
|
{
|
||||||
Task *task = (Task *)obj;
|
Task *task = (Task *)obj;
|
||||||
Panel *panel = (Panel *)task->area.panel;
|
Panel *panel = (Panel *)task->area.panel;
|
||||||
int size = panel_horizontal ? panel->g_task.maximum_width : panel->g_task.maximum_height;
|
int size = (panel_horizontal ? panel->g_task.maximum_width : panel->g_task.maximum_height) * panel->scale;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,12 +673,13 @@ void task_refresh_thumbnail(Task *task)
|
|||||||
return;
|
return;
|
||||||
if (task->current_state == TASK_ICONIFIED)
|
if (task->current_state == TASK_ICONIFIED)
|
||||||
return;
|
return;
|
||||||
|
Panel *panel = (Panel*)task->area.panel;
|
||||||
double now = get_time();
|
double now = get_time();
|
||||||
if (now - task->thumbnail_last_update < 0.1)
|
if (now - task->thumbnail_last_update < 0.1)
|
||||||
return;
|
return;
|
||||||
if (debug_thumbnails)
|
if (debug_thumbnails)
|
||||||
fprintf(stderr, "tint2: thumbnail for window: %s" RESET "\n", task->title ? task->title : "");
|
fprintf(stderr, "tint2: thumbnail for window: %s" RESET "\n", task->title ? task->title : "");
|
||||||
cairo_surface_t *thumbnail = get_window_thumbnail(task->win, panel_config.g_task.thumbnail_width);
|
cairo_surface_t *thumbnail = get_window_thumbnail(task->win, panel_config.g_task.thumbnail_width * panel->scale);
|
||||||
if (!thumbnail)
|
if (!thumbnail)
|
||||||
return;
|
return;
|
||||||
if (task->thumbnail)
|
if (task->thumbnail)
|
||||||
@@ -754,8 +776,8 @@ void blink_urgent(void *arg)
|
|||||||
GSList *urgent_task = urgent_list;
|
GSList *urgent_task = urgent_list;
|
||||||
while (urgent_task) {
|
while (urgent_task) {
|
||||||
Task *t = urgent_task->data;
|
Task *t = urgent_task->data;
|
||||||
if (t->urgent_tick < max_tick_urgent) {
|
if (t->urgent_tick <= max_tick_urgent) {
|
||||||
if (t->urgent_tick++ % 2)
|
if (++t->urgent_tick % 2)
|
||||||
set_task_state(t, TASK_URGENT);
|
set_task_state(t, TASK_URGENT);
|
||||||
else
|
else
|
||||||
set_task_state(t, window_is_iconified(t->win) ? TASK_ICONIFIED : TASK_NORMAL);
|
set_task_state(t, window_is_iconified(t->win) ? TASK_ICONIFIED : TASK_NORMAL);
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ typedef struct Task {
|
|||||||
Color icon_color_hover;
|
Color icon_color_hover;
|
||||||
Color icon_color_press;
|
Color icon_color_press;
|
||||||
char *title;
|
char *title;
|
||||||
|
char *application;
|
||||||
int urgent_tick;
|
int urgent_tick;
|
||||||
// These may not be up-to-date
|
// These may not be up-to-date
|
||||||
int win_x;
|
int win_x;
|
||||||
|
|||||||
+34
-22
@@ -238,15 +238,15 @@ void init_taskbar_panel(void *p)
|
|||||||
panel->g_taskbar.area.resize_needed = 1;
|
panel->g_taskbar.area.resize_needed = 1;
|
||||||
panel->g_taskbar.area.on_screen = TRUE;
|
panel->g_taskbar.area.on_screen = TRUE;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy;
|
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area.height =
|
panel->g_taskbar.area.height =
|
||||||
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy;
|
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
||||||
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
||||||
} else {
|
} else {
|
||||||
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy;
|
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area.width =
|
panel->g_taskbar.area.width =
|
||||||
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy;
|
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy * panel->scale;
|
||||||
panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
|
panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
|
||||||
panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
|
panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
|
||||||
}
|
}
|
||||||
@@ -304,19 +304,19 @@ void init_taskbar_panel(void *p)
|
|||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
panel->g_task.area.posy = panel->g_taskbar.area.posy +
|
panel->g_task.area.posy = panel->g_taskbar.area.posy +
|
||||||
top_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
top_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
||||||
panel->g_taskbar.area.paddingy;
|
panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.width = panel->g_task.maximum_width;
|
panel->g_task.area.width = panel->g_task.maximum_width;
|
||||||
panel->g_task.area.height = panel->g_taskbar.area.height -
|
panel->g_task.area.height = panel->g_taskbar.area.height -
|
||||||
top_bottom_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
top_bottom_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
||||||
2 * panel->g_taskbar.area.paddingy;
|
2 * panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
panel->g_task.area.posx = panel->g_taskbar.area.posx +
|
panel->g_task.area.posx = panel->g_taskbar.area.posx +
|
||||||
left_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
left_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
||||||
panel->g_taskbar.area.paddingy;
|
panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.width = panel->g_taskbar.area.width -
|
panel->g_task.area.width = panel->g_taskbar.area.width -
|
||||||
left_right_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
left_right_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
||||||
2 * panel->g_taskbar.area.paddingy;
|
2 * panel->g_taskbar.area.paddingy * panel->scale;
|
||||||
panel->g_task.area.height = panel->g_task.maximum_height;
|
panel->g_task.area.height = panel->g_task.maximum_height * panel->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
||||||
@@ -333,9 +333,8 @@ void init_taskbar_panel(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute vertical position : text and icon
|
// compute vertical position : text and icon
|
||||||
int height_ink, height, width;
|
int height, width;
|
||||||
get_text_size2(panel->g_task.font_desc,
|
get_text_size2(panel->g_task.font_desc,
|
||||||
&height_ink,
|
|
||||||
&height,
|
&height,
|
||||||
&width,
|
&width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -344,17 +343,19 @@ void init_taskbar_panel(void *p)
|
|||||||
5,
|
5,
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_END,
|
PANGO_ELLIPSIZE_END,
|
||||||
FALSE);
|
panel->g_task.centered ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
panel->g_task.text_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr;
|
panel->g_task.text_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr * panel->scale;
|
||||||
panel->g_task.text_height =
|
panel->g_task.text_height =
|
||||||
panel->g_task.area.height - (2 * panel->g_task.area.paddingy) - top_bottom_border_width(&panel->g_task.area);
|
panel->g_task.area.height - (2 * panel->g_task.area.paddingy * panel->scale) - top_bottom_border_width(&panel->g_task.area);
|
||||||
if (panel->g_task.has_icon) {
|
if (panel->g_task.has_icon) {
|
||||||
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width, panel->g_task.maximum_height),
|
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width * panel->scale, panel->g_task.maximum_height * panel->scale),
|
||||||
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
|
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
|
||||||
2 * panel->g_task.area.paddingy - MAX(left_right_border_width(&panel->g_task.area),
|
2 * panel->g_task.area.paddingy * panel->scale - MAX(left_right_border_width(&panel->g_task.area),
|
||||||
top_bottom_border_width(&panel->g_task.area));
|
top_bottom_border_width(&panel->g_task.area));
|
||||||
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx;
|
panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx * panel->scale;
|
||||||
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,12 +574,12 @@ gboolean resize_taskbar(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
taskbar->text_width = text_width - panel->g_task.text_posx - right_border_width(&panel->g_task.area) -
|
taskbar->text_width = text_width - panel->g_task.text_posx - right_border_width(&panel->g_task.area) -
|
||||||
panel->g_task.area.paddingxlr;
|
panel->g_task.area.paddingxlr * panel->scale;
|
||||||
} else {
|
} else {
|
||||||
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height);
|
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height * panel->scale);
|
||||||
|
|
||||||
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy) - panel->g_task.text_posx -
|
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy * panel->scale) - panel->g_task.text_posx -
|
||||||
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr;
|
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr * panel->scale;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -734,6 +735,14 @@ gint compare_task_titles(Task *a, Task *b, Taskbar *taskbar)
|
|||||||
return strnatcasecmp(a->title ? a->title : "", b->title ? b->title : "");
|
return strnatcasecmp(a->title ? a->title : "", b->title ? b->title : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gint compare_task_applications(Task *a, Task *b, Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
||||||
|
if (trivial != NONTRIVIAL)
|
||||||
|
return trivial;
|
||||||
|
return strnatcasecmp(a->application ? a->application : "", b->application ? b->application : "");
|
||||||
|
}
|
||||||
|
|
||||||
gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
||||||
{
|
{
|
||||||
int trivial = compare_tasks_trivial(a, b, taskbar);
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
||||||
@@ -745,6 +754,8 @@ gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
|||||||
return compare_task_centers(a, b, taskbar);
|
return compare_task_centers(a, b, taskbar);
|
||||||
} else if (taskbar_sort_method == TASKBAR_SORT_TITLE) {
|
} else if (taskbar_sort_method == TASKBAR_SORT_TITLE) {
|
||||||
return compare_task_titles(a, b, taskbar);
|
return compare_task_titles(a, b, taskbar);
|
||||||
|
} else if (taskbar_sort_method == TASKBAR_SORT_APPLICATION) {
|
||||||
|
return compare_task_applications(a, b, taskbar);
|
||||||
} else if (taskbar_sort_method == TASKBAR_SORT_LRU) {
|
} else if (taskbar_sort_method == TASKBAR_SORT_LRU) {
|
||||||
return compare_timespecs(&a->last_activation_time, &b->last_activation_time);
|
return compare_timespecs(&a->last_activation_time, &b->last_activation_time);
|
||||||
} else if (taskbar_sort_method == TASKBAR_SORT_MRU) {
|
} else if (taskbar_sort_method == TASKBAR_SORT_MRU) {
|
||||||
@@ -834,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)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ typedef enum TaskbarSortMethod {
|
|||||||
TASKBAR_NOSORT = 0,
|
TASKBAR_NOSORT = 0,
|
||||||
TASKBAR_SORT_CENTER,
|
TASKBAR_SORT_CENTER,
|
||||||
TASKBAR_SORT_TITLE,
|
TASKBAR_SORT_TITLE,
|
||||||
|
TASKBAR_SORT_APPLICATION,
|
||||||
TASKBAR_SORT_LRU,
|
TASKBAR_SORT_LRU,
|
||||||
TASKBAR_SORT_MRU,
|
TASKBAR_SORT_MRU,
|
||||||
} TaskbarSortMethod;
|
} TaskbarSortMethod;
|
||||||
|
|||||||
+16
-10
@@ -134,9 +134,8 @@ int taskbarname_compute_desired_size(void *obj)
|
|||||||
{
|
{
|
||||||
TaskbarName *taskbar_name = (TaskbarName *)obj;
|
TaskbarName *taskbar_name = (TaskbarName *)obj;
|
||||||
Panel *panel = (Panel *)taskbar_name->area.panel;
|
Panel *panel = (Panel *)taskbar_name->area.panel;
|
||||||
int name_height, name_width, name_height_ink;
|
int name_height, name_width;
|
||||||
get_text_size2(panel_config.taskbarname_font_desc,
|
get_text_size2(panel_config.taskbarname_font_desc,
|
||||||
&name_height_ink,
|
|
||||||
&name_height,
|
&name_height,
|
||||||
&name_width,
|
&name_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -145,12 +144,14 @@ int taskbarname_compute_desired_size(void *obj)
|
|||||||
strlen(taskbar_name->name),
|
strlen(taskbar_name->name),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
return name_width + 2 * taskbar_name->area.paddingxlr + left_right_border_width(&taskbar_name->area);
|
return name_width + 2 * taskbar_name->area.paddingxlr * panel->scale + left_right_border_width(&taskbar_name->area);
|
||||||
} else {
|
} else {
|
||||||
return name_height + 2 * taskbar_name->area.paddingxlr + top_bottom_border_width(&taskbar_name->area);
|
return name_height + 2 * taskbar_name->area.paddingxlr * panel->scale + top_bottom_border_width(&taskbar_name->area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,9 +162,8 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
|
|
||||||
schedule_redraw(&taskbar_name->area);
|
schedule_redraw(&taskbar_name->area);
|
||||||
|
|
||||||
int name_height, name_width, name_height_ink;
|
int name_height, name_width;
|
||||||
get_text_size2(panel_config.taskbarname_font_desc,
|
get_text_size2(panel_config.taskbarname_font_desc,
|
||||||
&name_height_ink,
|
|
||||||
&name_height,
|
&name_height,
|
||||||
&name_width,
|
&name_width,
|
||||||
panel->area.height,
|
panel->area.height,
|
||||||
@@ -172,7 +172,9 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
strlen(taskbar_name->name),
|
strlen(taskbar_name->name),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
panel->scale);
|
||||||
|
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
int new_size = taskbarname_compute_desired_size(obj);
|
int new_size = taskbarname_compute_desired_size(obj);
|
||||||
@@ -195,11 +197,14 @@ gboolean resize_taskbarname(void *obj)
|
|||||||
void draw_taskbarname(void *obj, cairo_t *c)
|
void draw_taskbarname(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
TaskbarName *taskbar_name = obj;
|
TaskbarName *taskbar_name = obj;
|
||||||
|
Panel *panel = (Panel *)taskbar_name->area.panel;
|
||||||
Taskbar *taskbar = taskbar_name->area.parent;
|
Taskbar *taskbar = taskbar_name->area.parent;
|
||||||
Color *config_text = (taskbar->desktop == server.desktop) ? &taskbarname_active_font : &taskbarname_font;
|
Color *config_text = (taskbar->desktop == server.desktop) ? &taskbarname_active_font : &taskbarname_font;
|
||||||
|
|
||||||
// draw content
|
// draw content
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, panel_config.taskbarname_font_desc);
|
pango_layout_set_font_description(layout, panel_config.taskbarname_font_desc);
|
||||||
pango_layout_set_width(layout, taskbar_name->area.width * PANGO_SCALE);
|
pango_layout_set_width(layout, taskbar_name->area.width * PANGO_SCALE);
|
||||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||||
@@ -210,9 +215,10 @@ void draw_taskbarname(void *obj, cairo_t *c)
|
|||||||
cairo_set_source_rgba(c, config_text->rgb[0], config_text->rgb[1], config_text->rgb[2], config_text->alpha);
|
cairo_set_source_rgba(c, config_text->rgb[0], config_text->rgb[1], config_text->rgb[2], config_text->alpha);
|
||||||
|
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel *)taskbar_name->area.panel)->font_shadow);
|
draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel *)taskbar_name->area.panel)->font_shadow ? layout : NULL);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_desktop_names()
|
void update_desktop_names()
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ include_directories( ../util
|
|||||||
${RSVG_INCLUDE_DIRS} )
|
${RSVG_INCLUDE_DIRS} )
|
||||||
|
|
||||||
set(SOURCES ../util/common.c
|
set(SOURCES ../util/common.c
|
||||||
|
../util/bt.c
|
||||||
../util/strnatcmp.c
|
../util/strnatcmp.c
|
||||||
../util/cache.c
|
../util/cache.c
|
||||||
../util/timer.c
|
../util/timer.c
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
+443
-428
File diff suppressed because it is too large
Load Diff
+443
-428
File diff suppressed because it is too large
Load Diff
+443
-428
File diff suppressed because it is too large
Load Diff
+443
-428
File diff suppressed because it is too large
Load Diff
+443
-428
File diff suppressed because it is too large
Load Diff
+443
-428
File diff suppressed because it is too large
Load Diff
+443
-428
File diff suppressed because it is too large
Load Diff
+442
-429
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@
|
|||||||
#include "gradient_gui.h"
|
#include "gradient_gui.h"
|
||||||
#include "strlcat.h"
|
#include "strlcat.h"
|
||||||
|
|
||||||
|
GtkWidget *scale_relative_to_dpi, *scale_relative_to_screen_height;
|
||||||
GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
||||||
*panel_spacing;
|
*panel_spacing;
|
||||||
GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
||||||
@@ -600,6 +601,32 @@ void create_panel(GtkWidget *parent)
|
|||||||
"for centered panels, it is evenly distributed on both sides of the panel."),
|
"for centered panels, it is evenly distributed on both sides of the panel."),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
row++;
|
||||||
|
col = 2;
|
||||||
|
label = gtk_label_new(_("Scale relative to DPI"));
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||||
|
gtk_widget_show(label);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
scale_relative_to_dpi = gtk_spin_button_new_with_range(0, 9000, 1);
|
||||||
|
gtk_widget_show(scale_relative_to_dpi);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), scale_relative_to_dpi, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
row++;
|
||||||
|
col = 2;
|
||||||
|
label = gtk_label_new(_("Scale relative to screen height"));
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||||
|
gtk_widget_show(label);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
scale_relative_to_screen_height = gtk_spin_button_new_with_range(0, 9000, 1);
|
||||||
|
gtk_widget_show(scale_relative_to_screen_height);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), scale_relative_to_screen_height, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
change_paragraph(parent);
|
change_paragraph(parent);
|
||||||
|
|
||||||
label = gtk_label_new(_("<b>Appearance</b>"));
|
label = gtk_label_new(_("<b>Appearance</b>"));
|
||||||
@@ -2691,6 +2718,7 @@ void create_taskbar(GtkWidget *parent)
|
|||||||
col++;
|
col++;
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("None"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("None"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By title"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By title"));
|
||||||
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By application"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By center"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("By center"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used first"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used first"));
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used last"));
|
gtk_combo_box_append_text(GTK_COMBO_BOX(taskbar_sort_order), _("Most recently used last"));
|
||||||
@@ -2701,6 +2729,7 @@ void create_taskbar(GtkWidget *parent)
|
|||||||
"'None' means that new tasks are added to the end, and the user can also reorder task "
|
"'None' means that new tasks are added to the end, and the user can also reorder task "
|
||||||
"buttons by mouse dragging. \n"
|
"buttons by mouse dragging. \n"
|
||||||
"'By title' means that tasks are sorted by their window titles. \n"
|
"'By title' means that tasks are sorted by their window titles. \n"
|
||||||
|
"'By application' means that tasks are sorted by their application names. \n"
|
||||||
"'By center' means that tasks are sorted geometrically by their window centers."),
|
"'By center' means that tasks are sorted geometrically by their window centers."),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "../launcher/icon-theme-common.h"
|
#include "../launcher/icon-theme-common.h"
|
||||||
|
|
||||||
// panel
|
// panel
|
||||||
|
extern GtkWidget *scale_relative_to_dpi, *scale_relative_to_screen_height;
|
||||||
extern GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
extern GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y,
|
||||||
*panel_spacing;
|
*panel_spacing;
|
||||||
extern GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
extern GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time,
|
||||||
|
|||||||
@@ -378,6 +378,13 @@ void config_write_panel(FILE *fp)
|
|||||||
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_saturation)),
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_saturation)),
|
||||||
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_brightness)));
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(mouse_pressed_icon_brightness)));
|
||||||
|
|
||||||
|
fprintf(fp,
|
||||||
|
"scale_relative_to_dpi = %d\n",
|
||||||
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scale_relative_to_dpi)));
|
||||||
|
fprintf(fp,
|
||||||
|
"scale_relative_to_screen_height = %d\n",
|
||||||
|
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scale_relative_to_screen_height)));
|
||||||
|
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,10 +457,12 @@ void config_write_taskbar(FILE *fp)
|
|||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 1) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 1) {
|
||||||
fprintf(fp, "title");
|
fprintf(fp, "title");
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 2) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 2) {
|
||||||
fprintf(fp, "center");
|
fprintf(fp, "application");
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 3) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 3) {
|
||||||
fprintf(fp, "mru");
|
fprintf(fp, "center");
|
||||||
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 4) {
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 4) {
|
||||||
|
fprintf(fp, "mru");
|
||||||
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_sort_order)) == 5) {
|
||||||
fprintf(fp, "lru");
|
fprintf(fp, "lru");
|
||||||
} else {
|
} else {
|
||||||
fprintf(fp, "none");
|
fprintf(fp, "none");
|
||||||
@@ -1108,7 +1117,13 @@ void add_entry(char *key, char *value)
|
|||||||
char *value1 = 0, *value2 = 0, *value3 = 0;
|
char *value1 = 0, *value2 = 0, *value3 = 0;
|
||||||
|
|
||||||
/* Gradients */
|
/* Gradients */
|
||||||
if (strcmp(key, "gradient") == 0) {
|
if (strcmp(key, "scale_relative_to_dpi") == 0) {
|
||||||
|
extract_values(value, &value1, &value2, &value3);
|
||||||
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(scale_relative_to_dpi), atoi(value1));
|
||||||
|
} else if (strcmp(key, "scale_relative_to_screen_height") == 0) {
|
||||||
|
extract_values(value, &value1, &value2, &value3);
|
||||||
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(scale_relative_to_screen_height), atoi(value1));
|
||||||
|
} else if (strcmp(key, "gradient") == 0) {
|
||||||
finalize_gradient();
|
finalize_gradient();
|
||||||
GradientConfigType t;
|
GradientConfigType t;
|
||||||
if (g_str_equal(value, "horizontal"))
|
if (g_str_equal(value, "horizontal"))
|
||||||
@@ -1546,12 +1561,14 @@ void add_entry(char *key, char *value)
|
|||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
||||||
else if (strcmp(value, "title") == 0)
|
else if (strcmp(value, "title") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 1);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 1);
|
||||||
else if (strcmp(value, "center") == 0)
|
else if (strcmp(value, "application") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 2);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 2);
|
||||||
else if (strcmp(value, "mru") == 0)
|
else if (strcmp(value, "center") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 3);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 3);
|
||||||
else if (strcmp(value, "lru") == 0)
|
else if (strcmp(value, "mru") == 0)
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 4);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 4);
|
||||||
|
else if (strcmp(value, "lru") == 0)
|
||||||
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 5);
|
||||||
else
|
else
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
||||||
} else if (strcmp(key, "task_align") == 0) {
|
} else if (strcmp(key, "task_align") == 0) {
|
||||||
|
|||||||
+18
-11
@@ -153,7 +153,9 @@ void tooltip_update_geometry()
|
|||||||
|
|
||||||
cairo_surface_t *cs = cairo_xlib_surface_create(server.display, g_tooltip.window, server.visual, width, height);
|
cairo_surface_t *cs = cairo_xlib_surface_create(server.display, g_tooltip.window, server.visual, width, height);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
||||||
PangoRectangle r1, r2;
|
PangoRectangle r1, r2;
|
||||||
@@ -161,7 +163,7 @@ void tooltip_update_geometry()
|
|||||||
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
||||||
int max_width = MIN(r2.width * 5, screen_width * 2 / 3);
|
int max_width = MIN(r2.width * 5, screen_width * 2 / 3);
|
||||||
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
|
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
|
||||||
max_width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx +
|
max_width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx * panel->scale +
|
||||||
cairo_image_surface_get_width(g_tooltip.image);
|
cairo_image_surface_get_width(g_tooltip.image);
|
||||||
}
|
}
|
||||||
pango_layout_set_width(layout, max_width * PANGO_SCALE);
|
pango_layout_set_width(layout, max_width * PANGO_SCALE);
|
||||||
@@ -169,12 +171,12 @@ void tooltip_update_geometry()
|
|||||||
pango_layout_set_text(layout, g_tooltip.tooltip_text ? g_tooltip.tooltip_text : "1234567890abcdef", -1);
|
pango_layout_set_text(layout, g_tooltip.tooltip_text ? g_tooltip.tooltip_text : "1234567890abcdef", -1);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
||||||
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
pango_layout_get_pixel_extents(layout, &r1, &r2);
|
||||||
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx + r2.width;
|
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx * panel->scale + r2.width;
|
||||||
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy + r2.height;
|
height = top_bottom_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingy * panel->scale + r2.height;
|
||||||
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
|
if (g_tooltip.image && cairo_image_surface_get_width(g_tooltip.image) > 0) {
|
||||||
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx +
|
width = left_right_bg_border_width(g_tooltip.bg) + 2 * g_tooltip.paddingx * panel->scale +
|
||||||
cairo_image_surface_get_width(g_tooltip.image);
|
cairo_image_surface_get_width(g_tooltip.image);
|
||||||
height += g_tooltip.paddingy + cairo_image_surface_get_height(g_tooltip.image);
|
height += g_tooltip.paddingy * panel->scale + cairo_image_surface_get_height(g_tooltip.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_horizontal && panel_position & BOTTOM)
|
if (panel_horizontal && panel_position & BOTTOM)
|
||||||
@@ -187,6 +189,7 @@ void tooltip_update_geometry()
|
|||||||
x = panel->posx - width;
|
x = panel->posx - width;
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
}
|
}
|
||||||
@@ -243,6 +246,7 @@ void tooltip_update()
|
|||||||
tooltip_hide(0);
|
tooltip_hide(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Panel *panel = g_tooltip.panel;
|
||||||
|
|
||||||
tooltip_update_geometry();
|
tooltip_update_geometry();
|
||||||
if (just_shown) {
|
if (just_shown) {
|
||||||
@@ -277,7 +281,9 @@ void tooltip_update()
|
|||||||
|
|
||||||
Color fc = g_tooltip.font_color;
|
Color fc = g_tooltip.font_color;
|
||||||
cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha);
|
cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha);
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * panel->scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
pango_layout_set_font_description(layout, g_tooltip.font_desc);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
|
||||||
pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
|
pango_layout_set_text(layout, g_tooltip.tooltip_text, -1);
|
||||||
@@ -289,15 +295,16 @@ void tooltip_update()
|
|||||||
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and
|
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and
|
||||||
// vert.)
|
// vert.)
|
||||||
cairo_move_to(c,
|
cairo_move_to(c,
|
||||||
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
|
-r1.x / 2 + left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx * panel->scale,
|
||||||
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy);
|
-r1.y / 2 + 1 + top_bg_border_width(g_tooltip.bg) + g_tooltip.paddingy * panel->scale);
|
||||||
pango_cairo_show_layout(c, layout);
|
pango_cairo_show_layout(c, layout);
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
|
|
||||||
if (g_tooltip.image) {
|
if (g_tooltip.image) {
|
||||||
cairo_translate(c,
|
cairo_translate(c,
|
||||||
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx,
|
left_bg_border_width(g_tooltip.bg) + g_tooltip.paddingx * panel->scale,
|
||||||
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy - cairo_image_surface_get_height(g_tooltip.image));
|
height - bottom_bg_border_width(g_tooltip.bg) - g_tooltip.paddingy * panel->scale - cairo_image_surface_get_height(g_tooltip.image));
|
||||||
cairo_set_source_surface(c, g_tooltip.image, 0, 0);
|
cairo_set_source_surface(c, g_tooltip.image, 0, 0);
|
||||||
cairo_paint(c);
|
cairo_paint(c);
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-21
@@ -478,14 +478,14 @@ void draw(Area *a)
|
|||||||
a->_clear(a);
|
a->_clear(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t *cs = cairo_xlib_surface_create(server.display, a->pix, server.visual, a->width, a->height);
|
cairo_surface_t *cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, a->width, a->height);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
|
|
||||||
draw_background(a, c);
|
draw_background(a, c);
|
||||||
|
|
||||||
if (a->_draw_foreground)
|
if (a->_draw_foreground)
|
||||||
a->_draw_foreground(a, c);
|
a->_draw_foreground(a, c);
|
||||||
|
|
||||||
|
draw_cairo_surface_to_xpixmap(cs, a->pix);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
}
|
}
|
||||||
@@ -929,10 +929,8 @@ void area_compute_text_geometry(Area *area,
|
|||||||
const char *line2,
|
const char *line2,
|
||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int *line1_height_ink,
|
|
||||||
int *line1_height,
|
int *line1_height,
|
||||||
int *line1_width,
|
int *line1_width,
|
||||||
int *line2_height_ink,
|
|
||||||
int *line2_height,
|
int *line2_height,
|
||||||
int *line2_width)
|
int *line2_width)
|
||||||
{
|
{
|
||||||
@@ -941,7 +939,6 @@ void area_compute_text_geometry(Area *area,
|
|||||||
|
|
||||||
if (line1 && line1[0])
|
if (line1 && line1[0])
|
||||||
get_text_size2(line1_font_desc,
|
get_text_size2(line1_font_desc,
|
||||||
line1_height_ink,
|
|
||||||
line1_height,
|
line1_height,
|
||||||
line1_width,
|
line1_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -950,13 +947,14 @@ void area_compute_text_geometry(Area *area,
|
|||||||
strlen(line1),
|
strlen(line1),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
((Panel*)area->panel)->scale);
|
||||||
else
|
else
|
||||||
*line1_width = *line1_height_ink = *line1_height = 0;
|
*line1_width = *line1_height = 0;
|
||||||
|
|
||||||
if (line2 && line2[0])
|
if (line2 && line2[0])
|
||||||
get_text_size2(line2_font_desc,
|
get_text_size2(line2_font_desc,
|
||||||
line2_height_ink,
|
|
||||||
line2_height,
|
line2_height,
|
||||||
line2_width,
|
line2_width,
|
||||||
available_h,
|
available_h,
|
||||||
@@ -965,9 +963,11 @@ void area_compute_text_geometry(Area *area,
|
|||||||
strlen(line2),
|
strlen(line2),
|
||||||
PANGO_WRAP_WORD_CHAR,
|
PANGO_WRAP_WORD_CHAR,
|
||||||
PANGO_ELLIPSIZE_NONE,
|
PANGO_ELLIPSIZE_NONE,
|
||||||
FALSE);
|
PANGO_ALIGN_CENTER,
|
||||||
|
FALSE,
|
||||||
|
((Panel*)area->panel)->scale);
|
||||||
else
|
else
|
||||||
*line2_width = *line2_height_ink = *line2_height = 0;
|
*line2_width = *line2_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int text_area_compute_desired_size(Area *area,
|
int text_area_compute_desired_size(Area *area,
|
||||||
@@ -976,16 +976,14 @@ int text_area_compute_desired_size(Area *area,
|
|||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc)
|
PangoFontDescription *line2_font_desc)
|
||||||
{
|
{
|
||||||
int line1_height_ink, line1_height, line1_width, line2_height_ink, line2_height, line2_width;
|
int line1_height, line1_width, line2_height, line2_width;
|
||||||
area_compute_text_geometry(area,
|
area_compute_text_geometry(area,
|
||||||
line1,
|
line1,
|
||||||
line2,
|
line2,
|
||||||
line1_font_desc,
|
line1_font_desc,
|
||||||
line2_font_desc,
|
line2_font_desc,
|
||||||
&line1_height_ink,
|
|
||||||
&line1_height,
|
&line1_height,
|
||||||
&line1_width,
|
&line1_width,
|
||||||
&line2_height_ink,
|
|
||||||
&line2_height,
|
&line2_height,
|
||||||
&line2_width);
|
&line2_width);
|
||||||
|
|
||||||
@@ -1010,17 +1008,15 @@ gboolean resize_text_area(Area *area,
|
|||||||
|
|
||||||
schedule_redraw(area);
|
schedule_redraw(area);
|
||||||
|
|
||||||
int line1_height_ink, line1_height, line1_width;
|
int line1_height, line1_width;
|
||||||
int line2_height_ink, line2_height, line2_width;
|
int line2_height, line2_width;
|
||||||
area_compute_text_geometry(area,
|
area_compute_text_geometry(area,
|
||||||
line1,
|
line1,
|
||||||
line2,
|
line2,
|
||||||
line1_font_desc,
|
line1_font_desc,
|
||||||
line2_font_desc,
|
line2_font_desc,
|
||||||
&line1_height_ink,
|
|
||||||
&line1_height,
|
&line1_height,
|
||||||
&line1_width,
|
&line1_width,
|
||||||
&line2_height_ink,
|
|
||||||
&line2_height,
|
&line2_height,
|
||||||
&line2_width);
|
&line2_width);
|
||||||
|
|
||||||
@@ -1067,12 +1063,16 @@ void draw_text_area(Area *area,
|
|||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int line1_posy,
|
int line1_posy,
|
||||||
int line2_posy,
|
int line2_posy,
|
||||||
Color *color)
|
Color *color,
|
||||||
|
double scale)
|
||||||
{
|
{
|
||||||
int inner_w, inner_h;
|
int inner_w, inner_h;
|
||||||
area_compute_inner_size(area, &inner_w, &inner_h);
|
area_compute_inner_size(area, &inner_w, &inner_h);
|
||||||
|
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
|
|
||||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
|
||||||
@@ -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,10 +1092,11 @@ void draw_text_area(Area *area,
|
|||||||
pango_layout_set_indent(layout, 0);
|
pango_layout_set_indent(layout, 0);
|
||||||
pango_layout_set_text(layout, line2, strlen(line2));
|
pango_layout_set_text(layout, line2, strlen(line2));
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
draw_text(layout, c, (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);
|
||||||
|
g_object_unref(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Area *compute_element_area(Area *area, Element element)
|
Area *compute_element_area(Area *area, Element element)
|
||||||
|
|||||||
+2
-3
@@ -273,10 +273,8 @@ void area_compute_text_geometry(Area *area,
|
|||||||
const char *line2,
|
const char *line2,
|
||||||
PangoFontDescription *line1_font_desc,
|
PangoFontDescription *line1_font_desc,
|
||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int *line1_height_ink,
|
|
||||||
int *line1_height,
|
int *line1_height,
|
||||||
int *line1_width,
|
int *line1_width,
|
||||||
int *line2_height_ink,
|
|
||||||
int *line2_height,
|
int *line2_height,
|
||||||
int *line2_width);
|
int *line2_width);
|
||||||
int text_area_compute_desired_size(Area *area,
|
int text_area_compute_desired_size(Area *area,
|
||||||
@@ -299,7 +297,8 @@ void draw_text_area(Area *area,
|
|||||||
PangoFontDescription *line2_font_desc,
|
PangoFontDescription *line2_font_desc,
|
||||||
int line1_posy,
|
int line1_posy,
|
||||||
int line2_posy,
|
int line2_posy,
|
||||||
Color *color);
|
Color *color,
|
||||||
|
double scale);
|
||||||
|
|
||||||
int left_border_width(Area *a);
|
int left_border_width(Area *a);
|
||||||
int right_border_width(Area *a);
|
int right_border_width(Area *a);
|
||||||
|
|||||||
+268
@@ -0,0 +1,268 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Tint2 : backtrace
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Pål Staurland (staura@gmail.com)
|
||||||
|
* Modified (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr) from Omega distribution
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "bt.h"
|
||||||
|
#include "bool.h"
|
||||||
|
|
||||||
|
#if defined(HAS_BACKTRACE) || defined(HAS_LIBUNWIND) || defined(HAS_EXECINFO)
|
||||||
|
|
||||||
|
static void bt_add_frame(struct backtrace *bt, const char *fname)
|
||||||
|
{
|
||||||
|
if (bt->frame_count >= BT_MAX_FRAMES)
|
||||||
|
return;
|
||||||
|
struct backtrace_frame *frame = &bt->frames[bt->frame_count];
|
||||||
|
if (fname && *fname) {
|
||||||
|
strncpy(frame->name, fname, BT_FRAME_SIZE);
|
||||||
|
} else {
|
||||||
|
strncpy(frame->name, "??", BT_FRAME_SIZE);
|
||||||
|
}
|
||||||
|
bt->frame_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_BACKTRACE
|
||||||
|
|
||||||
|
#include <backtrace.h>
|
||||||
|
|
||||||
|
static const char *get_exe()
|
||||||
|
{
|
||||||
|
static char buf[256] = {0};
|
||||||
|
ssize_t ret = readlink("/proc/self/exe", buf, sizeof(buf)-1);
|
||||||
|
if (ret > 0)
|
||||||
|
return buf;
|
||||||
|
ret = readlink("/proc/curproc/file", buf, sizeof(buf)-1);
|
||||||
|
if (ret > 0)
|
||||||
|
return buf;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bt_error_callback(void *data, const char *msg, int errnum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bt_full_callback(void *data, uintptr_t pc,
|
||||||
|
const char *filename, int lineno,
|
||||||
|
const char *function)
|
||||||
|
{
|
||||||
|
struct backtrace *bt = (struct backtrace *)data;
|
||||||
|
bt_add_frame(bt, function);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
static struct backtrace_state *state = NULL;
|
||||||
|
|
||||||
|
if (!state) {
|
||||||
|
const char *exe = get_exe();
|
||||||
|
if (exe)
|
||||||
|
state = backtrace_create_state(exe, 1, bt_error_callback, NULL);
|
||||||
|
}
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
if (state) {
|
||||||
|
backtrace_full(state, skip + 1, bt_full_callback, bt_error_callback, bt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif HAS_LIBUNWIND
|
||||||
|
|
||||||
|
#define UNW_LOCAL_ONLY
|
||||||
|
#include <libunwind.h>
|
||||||
|
|
||||||
|
struct bt_mapping {
|
||||||
|
unw_word_t ip;
|
||||||
|
char fname[BT_FRAME_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BT_BUCKET_SIZE 3
|
||||||
|
struct bt_bucket {
|
||||||
|
struct bt_mapping mappings[BT_BUCKET_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bt_cache {
|
||||||
|
struct bt_bucket *buckets;
|
||||||
|
size_t count;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned oat_hash(void *key, int len)
|
||||||
|
{
|
||||||
|
unsigned char *p = key;
|
||||||
|
unsigned h = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
h += p[i];
|
||||||
|
h += (h << 10);
|
||||||
|
h ^= (h >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
h += (h << 3);
|
||||||
|
h ^= (h >> 11);
|
||||||
|
h += (h << 15);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_bucket *cached_proc_name_bucket(struct bt_cache *cache, unw_word_t ip)
|
||||||
|
{
|
||||||
|
if (!cache->size)
|
||||||
|
return NULL;
|
||||||
|
unsigned h = oat_hash(&ip, sizeof(ip));
|
||||||
|
return &cache->buckets[h % cache->size];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bt_cache_init(struct bt_cache *cache)
|
||||||
|
{
|
||||||
|
if (!cache->size) {
|
||||||
|
cache->size = 119;
|
||||||
|
cache->buckets = calloc(cache->size, sizeof(*cache->buckets));
|
||||||
|
if (!cache->buckets)
|
||||||
|
cache->size = 0;
|
||||||
|
cache->count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cached_proc_name_store(struct bt_cache *cache, unw_word_t ip, const char *fname);
|
||||||
|
|
||||||
|
static void bt_cache_rebalance(struct bt_cache *cache)
|
||||||
|
{
|
||||||
|
struct bt_cache bigger = {};
|
||||||
|
bigger.size = cache->size * 2 + 1337;
|
||||||
|
bigger.buckets = calloc(bigger.size, sizeof(*bigger.buckets));
|
||||||
|
bigger.count = 0;
|
||||||
|
for (size_t b = 0; b < cache->size; b++) {
|
||||||
|
for (size_t i = 0; i < BT_BUCKET_SIZE; i++) {
|
||||||
|
struct bt_mapping *map = &cache->buckets[b].mappings[i];
|
||||||
|
if (map->ip) {
|
||||||
|
cached_proc_name_store(&bigger, map->ip, map->fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(cache->buckets);
|
||||||
|
*cache = bigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cached_proc_name_store(struct bt_cache *cache, unw_word_t ip, const char *fname)
|
||||||
|
{
|
||||||
|
bt_cache_init(cache);
|
||||||
|
if (!cache->size)
|
||||||
|
return;
|
||||||
|
struct bt_bucket *bucket = cached_proc_name_bucket(cache, ip);
|
||||||
|
bool stored = false;
|
||||||
|
for (size_t i = 0; i < BT_BUCKET_SIZE; i++) {
|
||||||
|
if (bucket->mappings[i].ip == ip)
|
||||||
|
return;
|
||||||
|
if (bucket->mappings[i].ip != 0)
|
||||||
|
continue;
|
||||||
|
bucket->mappings[i].ip = ip;
|
||||||
|
strncpy(bucket->mappings[i].fname, fname, sizeof(bucket->mappings[i].fname));
|
||||||
|
cache->count++;
|
||||||
|
stored = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cache->count > cache->size / 4 || !stored) {
|
||||||
|
bt_cache_rebalance(cache);
|
||||||
|
fprintf(stderr, "tint2: proc_name cache: ratio %f, count %lu, size %lu, (%lu bytes)\n",
|
||||||
|
cache->count / (double)cache->size,
|
||||||
|
cache->count, (size_t)cache->size, cache->size * sizeof(*cache->buckets));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cached_proc_name_get(struct bt_cache *cache, unw_word_t ip)
|
||||||
|
{
|
||||||
|
struct bt_bucket *bucket = cached_proc_name_bucket(cache, ip);
|
||||||
|
if (!bucket)
|
||||||
|
return NULL;
|
||||||
|
for (size_t i = 0; i < BT_BUCKET_SIZE; i++) {
|
||||||
|
if (bucket->mappings[i].ip != ip)
|
||||||
|
continue;
|
||||||
|
return bucket->mappings[i].fname;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
static struct bt_cache bt_cache = {};
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
|
||||||
|
unw_cursor_t cursor;
|
||||||
|
unw_context_t context;
|
||||||
|
unw_getcontext(&context);
|
||||||
|
unw_init_local(&cursor, &context);
|
||||||
|
|
||||||
|
while (unw_step(&cursor) > 0) {
|
||||||
|
if (skip > 0) {
|
||||||
|
skip--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unw_word_t offset;
|
||||||
|
char fname[BT_FRAME_SIZE] = {0};
|
||||||
|
unw_word_t ip;
|
||||||
|
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||||
|
const char *fname_cached = cached_proc_name_get(&bt_cache, ip);
|
||||||
|
if (fname_cached) {
|
||||||
|
bt_add_frame(bt, fname_cached);
|
||||||
|
} else {
|
||||||
|
unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
|
||||||
|
cached_proc_name_store(&bt_cache, ip, fname);
|
||||||
|
bt_add_frame(bt, fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif HAS_EXECINFO
|
||||||
|
|
||||||
|
#include <execinfo.h>
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
|
||||||
|
void *array[BT_MAX_FRAMES];
|
||||||
|
int size = backtrace(array, BT_MAX_FRAMES);
|
||||||
|
char **strings = backtrace_symbols(array, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
bt_add_frame(bt, strings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip)
|
||||||
|
{
|
||||||
|
bzero(bt, sizeof(*bt));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef BT_H
|
||||||
|
#define BT_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define BT_FRAME_SIZE 64
|
||||||
|
#define BT_MAX_FRAMES 64
|
||||||
|
|
||||||
|
struct backtrace_frame {
|
||||||
|
char name[BT_FRAME_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct backtrace {
|
||||||
|
struct backtrace_frame frames[BT_MAX_FRAMES];
|
||||||
|
size_t frame_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
void get_backtrace(struct backtrace *bt, int skip);
|
||||||
|
|
||||||
|
#endif // BT_H
|
||||||
+135
-64
@@ -48,18 +48,10 @@
|
|||||||
#include <librsvg/rsvg.h>
|
#include <librsvg/rsvg.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_LIBUNWIND
|
|
||||||
#define UNW_LOCAL_ONLY
|
|
||||||
#include <libunwind.h>
|
|
||||||
#else
|
|
||||||
#ifdef ENABLE_EXECINFO
|
|
||||||
#include <execinfo.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../panel.h"
|
#include "../panel.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
|
#include "bt.h"
|
||||||
|
|
||||||
void write_string(int fd, const char *s)
|
void write_string(int fd, const char *s)
|
||||||
{
|
{
|
||||||
@@ -83,39 +75,13 @@ void log_string(int fd, const char *s)
|
|||||||
|
|
||||||
void dump_backtrace(int log_fd)
|
void dump_backtrace(int log_fd)
|
||||||
{
|
{
|
||||||
#ifndef DISABLE_BACKTRACE
|
struct backtrace bt;
|
||||||
|
get_backtrace(&bt, 1);
|
||||||
log_string(log_fd, "\n" YELLOW "Backtrace:" RESET "\n");
|
log_string(log_fd, "\n" YELLOW "Backtrace:" RESET "\n");
|
||||||
|
for (size_t i = 0; i < bt.frame_count; i++) {
|
||||||
#ifdef ENABLE_LIBUNWIND
|
log_string(log_fd, bt.frames[i].name);
|
||||||
unw_cursor_t cursor;
|
|
||||||
unw_context_t context;
|
|
||||||
unw_getcontext(&context);
|
|
||||||
unw_init_local(&cursor, &context);
|
|
||||||
|
|
||||||
while (unw_step(&cursor) > 0) {
|
|
||||||
unw_word_t offset;
|
|
||||||
char fname[128];
|
|
||||||
fname[0] = '\0';
|
|
||||||
(void)unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
|
|
||||||
log_string(log_fd, fname);
|
|
||||||
log_string(log_fd, "\n");
|
log_string(log_fd, "\n");
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#ifdef ENABLE_EXECINFO
|
|
||||||
#define MAX_TRACE_SIZE 128
|
|
||||||
void *array[MAX_TRACE_SIZE];
|
|
||||||
size_t size = backtrace(array, MAX_TRACE_SIZE);
|
|
||||||
char **strings = backtrace_symbols(array, size);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
log_string(log_fd, strings[i]);
|
|
||||||
log_string(log_fd, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(strings);
|
|
||||||
#endif // ENABLE_EXECINFO
|
|
||||||
#endif // ENABLE_LIBUNWIND
|
|
||||||
#endif // DISABLE_BACKTRACE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep() returns early when signals arrive. This function does not.
|
// sleep() returns early when signals arrive. This function does not.
|
||||||
@@ -396,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) {
|
||||||
@@ -758,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;
|
||||||
@@ -773,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);
|
||||||
@@ -788,15 +791,15 @@ void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color
|
|||||||
Imlib_Image load_image(const char *path, int cached)
|
Imlib_Image load_image(const char *path, int cached)
|
||||||
{
|
{
|
||||||
Imlib_Image image;
|
Imlib_Image image;
|
||||||
|
static unsigned long counter = 0;
|
||||||
|
if (debug_icons)
|
||||||
|
fprintf(stderr, "tint2: loading icon %s\n", path);
|
||||||
#ifdef HAVE_RSVG
|
#ifdef HAVE_RSVG
|
||||||
if (cached) {
|
image = imlib_load_image(path);
|
||||||
image = imlib_load_image_immediately(path);
|
|
||||||
} else {
|
|
||||||
image = imlib_load_image_immediately_without_cache(path);
|
|
||||||
}
|
|
||||||
if (!image && g_str_has_suffix(path, ".svg")) {
|
if (!image && g_str_has_suffix(path, ".svg")) {
|
||||||
char tmp_filename[128];
|
char tmp_filename[128];
|
||||||
snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d.png", (int)getpid());
|
snprintf(tmp_filename, sizeof(tmp_filename), "/tmp/tint2-%d-%lu.png", (int)getpid(), counter);
|
||||||
|
counter++;
|
||||||
int fd = open(tmp_filename, O_CREAT | O_EXCL, 0600);
|
int fd = open(tmp_filename, O_CREAT | O_EXCL, 0600);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
// We fork here because librsvg allocates memory like crazy
|
// We fork here because librsvg allocates memory like crazy
|
||||||
@@ -818,19 +821,17 @@ Imlib_Image load_image(const char *path, int cached)
|
|||||||
// Parent
|
// Parent
|
||||||
close(fd);
|
close(fd);
|
||||||
waitpid(pid, 0, 0);
|
waitpid(pid, 0, 0);
|
||||||
image = imlib_load_image_immediately_without_cache(tmp_filename);
|
image = imlib_load_image_immediately(tmp_filename);
|
||||||
unlink(tmp_filename);
|
unlink(tmp_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (cached) {
|
image = imlib_load_image(path);
|
||||||
image = imlib_load_image_immediately(path);
|
|
||||||
} else {
|
|
||||||
image = imlib_load_image_immediately_without_cache(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
imlib_context_set_image(image);
|
||||||
|
imlib_image_set_changes_on_disk();
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -924,8 +925,7 @@ void clear_pixmap(Pixmap p, int x, int y, int w, int h)
|
|||||||
XRenderFreePicture(server.display, pict);
|
XRenderFreePicture(server.display, pict);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_text_size2(const PangoFontDescription *font,
|
void get_text_size(const PangoFontDescription *font,
|
||||||
int *height_ink,
|
|
||||||
int *height,
|
int *height,
|
||||||
int *width,
|
int *width,
|
||||||
int available_height,
|
int available_height,
|
||||||
@@ -934,20 +934,26 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
int text_len,
|
int text_len,
|
||||||
PangoWrapMode wrap,
|
PangoWrapMode wrap,
|
||||||
PangoEllipsizeMode ellipsis,
|
PangoEllipsizeMode ellipsis,
|
||||||
gboolean markup)
|
PangoAlignment alignment,
|
||||||
|
gboolean markup,
|
||||||
|
double scale)
|
||||||
{
|
{
|
||||||
PangoRectangle rect_ink, rect;
|
PangoRectangle rect_ink, rect;
|
||||||
|
|
||||||
available_width = MAX(0, available_width);
|
available_width = MAX(0, available_width);
|
||||||
available_height = MAX(0, available_height);
|
available_height = MAX(0, available_height);
|
||||||
|
|
||||||
|
Pixmap pmap = XCreatePixmap(server.display, server.root_win, available_height, available_width, server.depth);
|
||||||
cairo_surface_t *cs =
|
cairo_surface_t *cs =
|
||||||
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, available_height, available_width);
|
cairo_xlib_surface_create(server.display, pmap, server.visual, available_height, available_width);
|
||||||
cairo_t *c = cairo_create(cs);
|
cairo_t *c = cairo_create(cs);
|
||||||
|
|
||||||
PangoLayout *layout = pango_cairo_create_layout(c);
|
PangoContext *context = pango_cairo_create_context(c);
|
||||||
|
pango_cairo_context_set_resolution(context, 96 * scale);
|
||||||
|
PangoLayout *layout = pango_layout_new(context);
|
||||||
pango_layout_set_width(layout, available_width * PANGO_SCALE);
|
pango_layout_set_width(layout, available_width * PANGO_SCALE);
|
||||||
pango_layout_set_height(layout, available_height * PANGO_SCALE);
|
pango_layout_set_height(layout, available_height * PANGO_SCALE);
|
||||||
|
pango_layout_set_alignment(layout, alignment);
|
||||||
pango_layout_set_wrap(layout, wrap);
|
pango_layout_set_wrap(layout, wrap);
|
||||||
pango_layout_set_ellipsize(layout, ellipsis);
|
pango_layout_set_ellipsize(layout, ellipsis);
|
||||||
pango_layout_set_font_description(layout, font);
|
pango_layout_set_font_description(layout, font);
|
||||||
@@ -958,14 +964,63 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
pango_layout_set_markup(layout, text, text_len);
|
pango_layout_set_markup(layout, text, text_len);
|
||||||
|
|
||||||
pango_layout_get_pixel_extents(layout, &rect_ink, &rect);
|
pango_layout_get_pixel_extents(layout, &rect_ink, &rect);
|
||||||
*height_ink = rect_ink.height;
|
|
||||||
*height = rect.height;
|
*height = rect.height;
|
||||||
*width = rect.width;
|
*width = rect.width;
|
||||||
|
|
||||||
// fprintf(stderr, "tint2: dimension : %d - %d\n", rect_ink.height, rect.height);
|
// fprintf(stderr, "tint2: dimension : %d - %d\n", rect_ink.height, rect.height);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
g_object_unref(context);
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
cairo_surface_destroy(cs);
|
cairo_surface_destroy(cs);
|
||||||
|
XFreePixmap(server.display, pmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_text_size2(const PangoFontDescription *font,
|
||||||
|
int *height,
|
||||||
|
int *width,
|
||||||
|
int available_height,
|
||||||
|
int available_width,
|
||||||
|
const char *text,
|
||||||
|
int text_len,
|
||||||
|
PangoWrapMode wrap,
|
||||||
|
PangoEllipsizeMode ellipsis,
|
||||||
|
PangoAlignment alignment,
|
||||||
|
gboolean markup,
|
||||||
|
double scale)
|
||||||
|
{
|
||||||
|
get_text_size(font, height, width, available_height, available_width, text, text_len, wrap, ellipsis, alignment, markup, scale);
|
||||||
|
|
||||||
|
// We do multiple passes, because pango sucks
|
||||||
|
int actual_height, actual_width, overflow = 0;
|
||||||
|
while (true) {
|
||||||
|
get_text_size(font, &actual_height, &actual_width, *height, *width, text, text_len, wrap, ellipsis, alignment, markup, scale);
|
||||||
|
if (actual_height <= *height)
|
||||||
|
break;
|
||||||
|
if (*width >= available_width)
|
||||||
|
break;
|
||||||
|
overflow = 1;
|
||||||
|
fprintf(stderr, "tint2: text overflows, recomputing: available %dx%d, computed %dx%d, actual %dx%d: %s\n",
|
||||||
|
available_width,
|
||||||
|
available_height,
|
||||||
|
*width,
|
||||||
|
*height,
|
||||||
|
actual_width,
|
||||||
|
actual_height,
|
||||||
|
text);
|
||||||
|
(*width)++;
|
||||||
|
}
|
||||||
|
if (overflow) {
|
||||||
|
*height = actual_height;
|
||||||
|
fprintf(stderr, "tint2: text final size computed as: available %dx%d, computed %dx%d, actual %dx%d: %s\n",
|
||||||
|
available_width,
|
||||||
|
available_height,
|
||||||
|
*width,
|
||||||
|
*height,
|
||||||
|
actual_width,
|
||||||
|
actual_height,
|
||||||
|
text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !GLIB_CHECK_VERSION(2, 34, 0)
|
#if !GLIB_CHECK_VERSION(2, 34, 0)
|
||||||
@@ -1174,3 +1229,19 @@ void dump_image_data(const char *file_name, const char *name)
|
|||||||
|
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_cairo_surface_to_xpixmap(cairo_surface_t *cs, Pixmap pix)
|
||||||
|
{
|
||||||
|
int w = cairo_image_surface_get_width(cs);
|
||||||
|
int h = cairo_image_surface_get_height(cs);
|
||||||
|
cairo_surface_t *cs_xlib = cairo_xlib_surface_create(server.display, pix, server.visual, w, h);
|
||||||
|
cairo_xlib_surface_set_size(cs_xlib, w, h);
|
||||||
|
cairo_t *c_xlib = cairo_create(cs_xlib);
|
||||||
|
|
||||||
|
cairo_set_source_surface(c_xlib, cs, 0, 0);
|
||||||
|
cairo_paint(c_xlib);
|
||||||
|
cairo_surface_flush(cs_xlib);
|
||||||
|
|
||||||
|
cairo_destroy(c_xlib);
|
||||||
|
cairo_surface_destroy(cs_xlib);
|
||||||
|
}
|
||||||
|
|||||||
+8
-3
@@ -7,6 +7,7 @@
|
|||||||
#define COMMON_H
|
#define COMMON_H
|
||||||
|
|
||||||
#define WM_CLASS_TINT "panel"
|
#define WM_CLASS_TINT "panel"
|
||||||
|
#define TINT2_PANGO_SLACK 0
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
@@ -113,7 +114,6 @@ void create_heuristic_mask(DATA32 *data, int w, int h);
|
|||||||
void render_image(Drawable d, int x, int y);
|
void render_image(Drawable d, int x, int y);
|
||||||
|
|
||||||
void get_text_size2(const PangoFontDescription *font,
|
void get_text_size2(const PangoFontDescription *font,
|
||||||
int *height_ink,
|
|
||||||
int *height,
|
int *height,
|
||||||
int *width,
|
int *width,
|
||||||
int available_height,
|
int available_height,
|
||||||
@@ -122,9 +122,12 @@ void get_text_size2(const PangoFontDescription *font,
|
|||||||
int text_len,
|
int text_len,
|
||||||
PangoWrapMode wrap,
|
PangoWrapMode wrap,
|
||||||
PangoEllipsizeMode ellipsis,
|
PangoEllipsizeMode ellipsis,
|
||||||
gboolean markup);
|
PangoAlignment alignment,
|
||||||
|
gboolean markup,
|
||||||
|
double scale);
|
||||||
|
|
||||||
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
|
gboolean layout_set_markup_strip_colors(PangoLayout *layout, const char *markup);
|
||||||
|
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, PangoLayout *shadow_layout);
|
||||||
|
|
||||||
// Draws a rounded rectangle
|
// Draws a rounded rectangle
|
||||||
void draw_rect(cairo_t *c, double x, double y, double w, double h, double r);
|
void draw_rect(cairo_t *c, double x, double y, double w, double h, double r);
|
||||||
@@ -151,6 +154,8 @@ void get_image_mean_color(const Imlib_Image image, Color *mean_color);
|
|||||||
|
|
||||||
void dump_image_data(const char *file_name, const char *name);
|
void dump_image_data(const char *file_name, const char *name);
|
||||||
|
|
||||||
|
void draw_cairo_surface_to_xpixmap(cairo_surface_t *cs, Pixmap pix);
|
||||||
|
|
||||||
#define free_and_null(p) \
|
#define free_and_null(p) \
|
||||||
{ \
|
{ \
|
||||||
free(p); \
|
free(p); \
|
||||||
|
|||||||
+331
@@ -0,0 +1,331 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <endian.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "bt.h"
|
||||||
|
#include "bool.h"
|
||||||
|
|
||||||
|
#define UNUSED(x) ((void)x)
|
||||||
|
|
||||||
|
void ERR(const char *s)
|
||||||
|
{
|
||||||
|
if (!s) {
|
||||||
|
ERR("(null)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ssize_t ret = write(STDERR_FILENO, s, strlen(s));
|
||||||
|
UNUSED(ret);
|
||||||
|
ret = fsync(STDERR_FILENO);
|
||||||
|
UNUSED(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void utoa(unsigned long n, char *s)
|
||||||
|
{
|
||||||
|
if (n == 0) {
|
||||||
|
*s++ = '0';
|
||||||
|
*s = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buffer[128] = {0};
|
||||||
|
char *digit;
|
||||||
|
for (digit = buffer; n; digit++, n/=10) {
|
||||||
|
*digit = '0' + (n % 10);
|
||||||
|
}
|
||||||
|
digit--;
|
||||||
|
while (digit >= buffer) {
|
||||||
|
*s++ = *digit--;
|
||||||
|
}
|
||||||
|
*s = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long uabs(long n)
|
||||||
|
{
|
||||||
|
if (n == LONG_MIN)
|
||||||
|
return ((unsigned long)LONG_MAX) + 1;
|
||||||
|
return (unsigned long)labs(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void itoa(long n, char *s)
|
||||||
|
{
|
||||||
|
if (n < 0) {
|
||||||
|
*s++ = '-';
|
||||||
|
}
|
||||||
|
utoa(uabs(n), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
static void crash(char *file, int line, char *msg)
|
||||||
|
{
|
||||||
|
ERR(file);
|
||||||
|
ERR(":");
|
||||||
|
char buf[256];
|
||||||
|
itoa(line, buf);
|
||||||
|
ERR(buf);
|
||||||
|
ERR(" ");
|
||||||
|
ERR(msg);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_OK(call) if (0 != (call)) crash(__FILE__, __LINE__, #call)
|
||||||
|
#define ASSERT_FD(fd) if ((fd) == -1) crash(__FILE__, __LINE__, "bad file descriptor")
|
||||||
|
#define ASSERT_PID(pid) if ((pid) == -1) crash(__FILE__, __LINE__, "bad PID")
|
||||||
|
#define ASSERT(b) if (!(b)) crash(__FILE__, __LINE__, "assert failed")
|
||||||
|
|
||||||
|
void *return_null(void *x, void *y)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_func_or_crash(void **result, const char *name)
|
||||||
|
{
|
||||||
|
static int inside_loader = 0;
|
||||||
|
if (inside_loader) {
|
||||||
|
*result = (void*)return_null;
|
||||||
|
return;
|
||||||
|
} else if (*result == (void*)return_null) {
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
if (*result)
|
||||||
|
return;
|
||||||
|
dlerror();
|
||||||
|
inside_loader++;
|
||||||
|
*result = dlsym(RTLD_NEXT, name);
|
||||||
|
inside_loader--;
|
||||||
|
char *err = dlerror();
|
||||||
|
if (err) {
|
||||||
|
ERR("Failed to load ");
|
||||||
|
ERR(name);
|
||||||
|
ERR(" error: ");
|
||||||
|
ERR(err);
|
||||||
|
ERR("\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd = -1;
|
||||||
|
static u_int64_t tstart = 0;
|
||||||
|
static bool stop_alloc_log = false;
|
||||||
|
|
||||||
|
static void write_char(char c)
|
||||||
|
{
|
||||||
|
static char buffer[4096] = {0};
|
||||||
|
static size_t count = 0;
|
||||||
|
if (c) {
|
||||||
|
buffer[count++] = c;
|
||||||
|
}
|
||||||
|
if (!count)
|
||||||
|
return;
|
||||||
|
if (c == '\n' || c == 0 || count >= sizeof(buffer)) {
|
||||||
|
ssize_t ret = write(fd, buffer, count);
|
||||||
|
ASSERT(ret > 0);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_string(const char *s)
|
||||||
|
{
|
||||||
|
for (; *s; s++)
|
||||||
|
write_char(*s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_word(const char *s)
|
||||||
|
{
|
||||||
|
write_string(s);
|
||||||
|
write_string(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static char hex(u_int8_t value)
|
||||||
|
{
|
||||||
|
if (value < 10)
|
||||||
|
return '0' + (char)value;
|
||||||
|
return 'a' + (char)(value - 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_hex(u_int64_t v)
|
||||||
|
{
|
||||||
|
write_string("0x");
|
||||||
|
if (!v) {
|
||||||
|
write_string("0 ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
v = htobe64(v);
|
||||||
|
int leading_zero = 1;
|
||||||
|
while (v) {
|
||||||
|
u_int8_t byte = v & 0xff;
|
||||||
|
if (byte)
|
||||||
|
leading_zero = 0;
|
||||||
|
if (!leading_zero) {
|
||||||
|
write_char(hex(byte >> 4));
|
||||||
|
write_char(hex(byte & 0xf));
|
||||||
|
}
|
||||||
|
v = v >> 8;
|
||||||
|
}
|
||||||
|
write_string(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_backtrace(int skip)
|
||||||
|
{
|
||||||
|
struct backtrace bt;
|
||||||
|
get_backtrace(&bt, skip + 1);
|
||||||
|
for (size_t i = 0; i < bt.frame_count; i++) {
|
||||||
|
write_word(bt.frames[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_finish(void);
|
||||||
|
|
||||||
|
static u_int64_t current_time_ms()
|
||||||
|
{
|
||||||
|
struct timespec t = {0, 0};
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||||
|
u_int64_t result = t.tv_sec * 1000 + t.tv_nsec / 1000 / 1000;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_init(u_int64_t t)
|
||||||
|
{
|
||||||
|
if (stop_alloc_log)
|
||||||
|
return;
|
||||||
|
if (fd == -1) {
|
||||||
|
int pfd[2] = {-1, -1};
|
||||||
|
ASSERT_OK(pipe(pfd));
|
||||||
|
pid_t child = fork();
|
||||||
|
ASSERT_PID(child);
|
||||||
|
if (child == 0) {
|
||||||
|
// child
|
||||||
|
close(pfd[1]);
|
||||||
|
ASSERT_FD(dup2(pfd[0], STDIN_FILENO));
|
||||||
|
ASSERT_OK(close(pfd[0]));
|
||||||
|
int out = open("mem.log.gz", O_APPEND | O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0600);
|
||||||
|
ASSERT_FD(out);
|
||||||
|
ASSERT_FD(dup2(out, STDOUT_FILENO));
|
||||||
|
sigset_t mask;
|
||||||
|
sigfillset(&mask);
|
||||||
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
|
ASSERT_OK(execlp("gzip", "gzip", "-c", NULL));
|
||||||
|
_exit(1);
|
||||||
|
} else {
|
||||||
|
// parent
|
||||||
|
close(pfd[0]);
|
||||||
|
fd = pfd[1];
|
||||||
|
}
|
||||||
|
atexit(log_alloc_finish);
|
||||||
|
tstart = t;
|
||||||
|
write_string("# function time_ms result ptr size count backtrace\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_locked(const char *func_name, void *result, void *ptr, size_t size, size_t count)
|
||||||
|
{
|
||||||
|
if (stop_alloc_log)
|
||||||
|
return;
|
||||||
|
u_int64_t t = current_time_ms();
|
||||||
|
if (fd == -1)
|
||||||
|
log_alloc_init(t);
|
||||||
|
if (fd == -1)
|
||||||
|
return;
|
||||||
|
if (func_name) {
|
||||||
|
write_word(func_name);
|
||||||
|
write_hex((u_int64_t)(t - tstart));
|
||||||
|
write_hex((u_int64_t)result);
|
||||||
|
write_hex((u_int64_t)ptr);
|
||||||
|
write_hex((u_int64_t)size);
|
||||||
|
write_hex((u_int64_t)count);
|
||||||
|
write_backtrace(2);
|
||||||
|
write_string("\n");
|
||||||
|
} else {
|
||||||
|
write_string("# done\n");
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
stop_alloc_log = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pid = -1;
|
||||||
|
static void log_alloc(const char *func_name, void *result, void *ptr, size_t size, size_t count)
|
||||||
|
{
|
||||||
|
static pthread_mutex_t mutex_global = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_mutex_t mutex_recursive;
|
||||||
|
static pthread_mutex_t mutex_nonrecursive = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static bool mutexes_initialized = false;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mutex_global);
|
||||||
|
{
|
||||||
|
if (!mutexes_initialized) {
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&mutex_recursive, &attr);
|
||||||
|
mutexes_initialized = true;
|
||||||
|
pid = getpid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex_global);
|
||||||
|
|
||||||
|
// Do not log from forked processes.
|
||||||
|
if (pid != getpid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mutex_recursive);
|
||||||
|
int ret = pthread_mutex_trylock(&mutex_nonrecursive);
|
||||||
|
if (ret == 0) {
|
||||||
|
log_alloc_locked(func_name, result, ptr, size, count);
|
||||||
|
pthread_mutex_unlock(&mutex_nonrecursive);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex_recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_alloc_finish()
|
||||||
|
{
|
||||||
|
log_alloc(0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *malloc(size_t size)
|
||||||
|
{
|
||||||
|
static void *(*original)(size_t size) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
void *result = original(size);
|
||||||
|
log_alloc(__FUNCTION__, result, 0, size, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *realloc(void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
static void *(*original)(void *p, size_t size) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
void *result = original(ptr, size);
|
||||||
|
log_alloc(__FUNCTION__, result, ptr, size, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *calloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
static void *(*original)(size_t nmemb, size_t size) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
void *result = original(nmemb, size);
|
||||||
|
log_alloc(__FUNCTION__, result, 0, size, nmemb);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void *ptr)
|
||||||
|
{
|
||||||
|
static void *(*original)(void *p) = 0;
|
||||||
|
load_func_or_crash((void *)&original, __FUNCTION__);
|
||||||
|
if (!original) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
original(ptr);
|
||||||
|
log_alloc(__FUNCTION__, 0, ptr, 0, 0);
|
||||||
|
}
|
||||||
+37
-7
@@ -19,11 +19,11 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xrender.h>
|
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -36,8 +36,9 @@
|
|||||||
|
|
||||||
Server server;
|
Server server;
|
||||||
|
|
||||||
void server_catch_error(Display *d, XErrorEvent *ev)
|
int server_catch_error(Display *d, XErrorEvent *ev)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_init_atoms()
|
void server_init_atoms()
|
||||||
@@ -311,6 +312,21 @@ void sort_monitors()
|
|||||||
qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos);
|
qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compute_dpi(XRRCrtcInfo *crtc, XRROutputInfo *output)
|
||||||
|
{
|
||||||
|
double width = output->mm_width;
|
||||||
|
double height = output->mm_height;
|
||||||
|
double x_res = crtc->width;
|
||||||
|
double y_res = crtc->height;
|
||||||
|
|
||||||
|
if (width > 0 && height > 0) {
|
||||||
|
int dpi_x = x_res / width * 25.4;
|
||||||
|
int dpi_y = y_res / height * 25.4;
|
||||||
|
return MAX(dpi_x, dpi_y);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void get_monitors()
|
void get_monitors()
|
||||||
{
|
{
|
||||||
if (XineramaIsActive(server.display)) {
|
if (XineramaIsActive(server.display)) {
|
||||||
@@ -339,12 +355,22 @@ void get_monitors()
|
|||||||
server.monitors[i_monitor].width = crtc_info->width;
|
server.monitors[i_monitor].width = crtc_info->width;
|
||||||
server.monitors[i_monitor].height = crtc_info->height;
|
server.monitors[i_monitor].height = crtc_info->height;
|
||||||
server.monitors[i_monitor].names = calloc((crtc_info->noutput + 1), sizeof(gchar *));
|
server.monitors[i_monitor].names = calloc((crtc_info->noutput + 1), sizeof(gchar *));
|
||||||
|
server.monitors[i_monitor].dpi = 96;
|
||||||
for (int j = 0; j < crtc_info->noutput; ++j) {
|
for (int j = 0; j < crtc_info->noutput; ++j) {
|
||||||
XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]);
|
XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]);
|
||||||
fprintf(stderr, "tint2: xRandr: Linking output %s with crtc %d\n", output_info->name, i);
|
|
||||||
server.monitors[i_monitor].names[j] = g_strdup(output_info->name);
|
server.monitors[i_monitor].names[j] = g_strdup(output_info->name);
|
||||||
XRRFreeOutputInfo(output_info);
|
|
||||||
server.monitors[i_monitor].primary = crtc_info->outputs[j] == primary_output;
|
server.monitors[i_monitor].primary = crtc_info->outputs[j] == primary_output;
|
||||||
|
int dpi = compute_dpi(crtc_info, output_info);
|
||||||
|
if (dpi)
|
||||||
|
server.monitors[i_monitor].dpi = dpi;
|
||||||
|
fprintf(stderr,
|
||||||
|
BLUE "tint2: xRandr: Linking output %s with crtc %d, resolution %dx%d, DPI %d" RESET "\n",
|
||||||
|
output_info->name,
|
||||||
|
i,
|
||||||
|
server.monitors[i_monitor].width,
|
||||||
|
server.monitors[i_monitor].height,
|
||||||
|
server.monitors[i_monitor].dpi);
|
||||||
|
XRRFreeOutputInfo(output_info);
|
||||||
}
|
}
|
||||||
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
server.monitors[i_monitor].names[crtc_info->noutput] = NULL;
|
||||||
XRRFreeCrtcInfo(crtc_info);
|
XRRFreeCrtcInfo(crtc_info);
|
||||||
@@ -357,6 +383,7 @@ void get_monitors()
|
|||||||
server.monitors[i].width = info[i].width;
|
server.monitors[i].width = info[i].width;
|
||||||
server.monitors[i].height = info[i].height;
|
server.monitors[i].height = info[i].height;
|
||||||
server.monitors[i].names = NULL;
|
server.monitors[i].names = NULL;
|
||||||
|
server.monitors[i].dpi = 96;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,6 +420,7 @@ void get_monitors()
|
|||||||
server.monitors[0].width = DisplayWidth(server.display, server.screen);
|
server.monitors[0].width = DisplayWidth(server.display, server.screen);
|
||||||
server.monitors[0].height = DisplayHeight(server.display, server.screen);
|
server.monitors[0].height = DisplayHeight(server.display, server.screen);
|
||||||
server.monitors[0].names = 0;
|
server.monitors[0].names = 0;
|
||||||
|
server.monitors[0].dpi = 96;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +551,8 @@ int get_current_desktop()
|
|||||||
// fprintf(stderr, "tint2: \n");
|
// fprintf(stderr, "tint2: \n");
|
||||||
// fprintf(stderr, "tint2: Work area size: %d x %d\n", work_area_width, work_area_height);
|
// fprintf(stderr, "tint2: Work area size: %d x %d\n", work_area_width, work_area_height);
|
||||||
// fprintf(stderr, "tint2: Viewport pos: %d x %d\n", viewport_x, viewport_y);
|
// fprintf(stderr, "tint2: Viewport pos: %d x %d\n", viewport_x, viewport_y);
|
||||||
// fprintf(stderr, "tint2: Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x / work_area_width);
|
// fprintf(stderr, "tint2: Viewport i: %d\n", (viewport_y / work_area_height) * ncols + viewport_x /
|
||||||
|
//work_area_width);
|
||||||
|
|
||||||
int result = (viewport_y / work_area_height) * ncols + viewport_x / work_area_width;
|
int result = (viewport_y / work_area_height) * ncols + viewport_x / work_area_width;
|
||||||
return MAX(0, MIN(server.num_desktops - 1, result));
|
return MAX(0, MIN(server.num_desktops - 1, result));
|
||||||
@@ -648,9 +677,10 @@ void handle_crash(const char *reason)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void x11_io_error(Display *display)
|
int x11_io_error(Display *display)
|
||||||
{
|
{
|
||||||
handle_crash("X11 I/O error");
|
handle_crash("X11 I/O error");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
|
|||||||
+3
-2
@@ -107,6 +107,7 @@ typedef struct Monitor {
|
|||||||
int y;
|
int y;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
int dpi;
|
||||||
gboolean primary;
|
gboolean primary;
|
||||||
gchar **names;
|
gchar **names;
|
||||||
} Monitor;
|
} Monitor;
|
||||||
@@ -163,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
|
||||||
|
|||||||
+2
-1
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
+110
-115
@@ -21,6 +21,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -383,28 +384,42 @@ void smooth_thumbnail(cairo_surface_t *image_surface)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is measured to be slightly faster.
|
// This is measured to be slightly faster than XGetPixel.
|
||||||
#define GetPixel(ximg, x, y) ((u_int32_t *)&(ximg->data[y * ximg->bytes_per_line]))[x]
|
static u_int32_t GetPixel(XImage *ximg, unsigned x, unsigned y)
|
||||||
//#define GetPixel XGetPixel
|
{
|
||||||
|
if (x >= ximg->width || y >= ximg->height) {
|
||||||
|
fprintf(stderr, RED "GetPixel read overflow: %u %u %d %d\n",
|
||||||
|
x, y, ximg->width, ximg->height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ((u_int32_t *)&(ximg->data[y * ximg->bytes_per_line]))[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: the xrender method only works well if there is a compositor running
|
||||||
cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm)
|
cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, GREEN "tint2: win=%u: getting thumbnail of size %u" RESET "\n", win, size);
|
||||||
cairo_surface_t *result = NULL;
|
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) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no win attributes" RESET "\n", win);
|
||||||
goto err0;
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
if (window_is_iconified(win))
|
if (window_is_iconified(win)) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for minimized window" RESET "\n", win);
|
||||||
goto err0;
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t w, h;
|
size_t w, h;
|
||||||
w = (size_t)wa.width;
|
w = (size_t)wa.width + wa.x;
|
||||||
h = (size_t)wa.height;
|
h = (size_t)wa.height + wa.y;
|
||||||
size_t tw, th, fw;
|
size_t tw, th, fw;
|
||||||
size_t ox, oy;
|
size_t ox, oy;
|
||||||
tw = size;
|
tw = size;
|
||||||
th = h * tw / w;
|
th = h * tw / w;
|
||||||
|
double scale = th / (double)h;
|
||||||
if (th > tw * 0.618) {
|
if (th > tw * 0.618) {
|
||||||
th = (size_t)(tw * 0.618);
|
th = (size_t)(tw * 0.618);
|
||||||
fw = w * th / h;
|
fw = w * th / h;
|
||||||
@@ -414,20 +429,69 @@ 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 (!w || !h || !tw || !th || !fw) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for size 0x0" RESET "\n", win);
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
XShmSegmentInfo shminfo;
|
XImage *ximg = NULL;
|
||||||
XImage *ximg;
|
|
||||||
if (use_shm)
|
XGetWindowAttributes(server.display, win, &wa);
|
||||||
ximg = XShmCreateImage(server.display,
|
if (wa.map_state != IsViewable) {
|
||||||
wa.visual,
|
fprintf(stderr, YELLOW "tint2: win=%u: no thumbnail for non-viewable window" RESET "\n", win);
|
||||||
(unsigned)wa.depth,
|
goto err4;
|
||||||
ZPixmap,
|
}
|
||||||
NULL,
|
|
||||||
&shminfo,
|
Pixmap pix = XCreatePixmap(server.display, win, tw, th, wa.depth);
|
||||||
(unsigned)w,
|
if (!pix) {
|
||||||
(unsigned)h);
|
fprintf(stderr, YELLOW "tint2: win=%u: no pixmap" RESET "\n", win);
|
||||||
else
|
goto err4;
|
||||||
ximg = XGetImage(server.display, win, 0, 0, (unsigned)w, (unsigned)h, AllPlanes, ZPixmap);
|
}
|
||||||
|
XRenderPictureAttributes attrs = {
|
||||||
|
.repeat = RepeatNone
|
||||||
|
};
|
||||||
|
XRenderPictFormat *fmt = XRenderFindVisualFormat(server.display, wa.visual);
|
||||||
|
if (!fmt) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no XRender format" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
Picture src_pic = XRenderCreatePicture(server.display, win, fmt, CPRepeat, &attrs);
|
||||||
|
if (!src_pic) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no src picture" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
Picture dst_pic = XRenderCreatePicture(server.display, pix, fmt, CPRepeat, &attrs);
|
||||||
|
if (!dst_pic) {
|
||||||
|
fprintf(stderr, YELLOW "tint2: win=%u: no src picture" RESET "\n", win);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
fprintf(stderr, GREEN "tint2: win=%u: transformation %u %u %f xy %d %d" RESET "\n", win, ox, oy, scale,
|
||||||
|
wa.x, wa.y);
|
||||||
|
XTransform transform = {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
XDoubleToFixed(1./scale),
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(ox-wa.x/scale)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(1./scale),
|
||||||
|
XDoubleToFixed(oy-wa.y/scale)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(0),
|
||||||
|
XDoubleToFixed(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
XRenderSetPictureTransform(server.display, src_pic, &transform);
|
||||||
|
XRenderSetPictureFilter(server.display, src_pic, FilterBilinear, NULL, 0);
|
||||||
|
XRenderComposite(server.display, PictOpSrc, src_pic, None, dst_pic, 0, 0, 0, 0, 0, 0, w, h);
|
||||||
|
XSync(server.display, False);
|
||||||
|
|
||||||
|
ximg = XGetImage(server.display, pix, 0, 0, (unsigned)tw, (unsigned)th, AllPlanes, ZPixmap);
|
||||||
if (!ximg) {
|
if (!ximg) {
|
||||||
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
|
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
|
||||||
goto err0;
|
goto err0;
|
||||||
@@ -436,87 +500,32 @@ cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean u
|
|||||||
fprintf(stderr, RED "tint2: unusual bits_per_pixel" RESET "\n");
|
fprintf(stderr, RED "tint2: unusual bits_per_pixel" RESET "\n");
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
if (use_shm) {
|
|
||||||
shminfo.shmid = shmget(IPC_PRIVATE, (size_t)(ximg->bytes_per_line * ximg->height), IPC_CREAT | 0777);
|
|
||||||
if (shminfo.shmid < 0) {
|
|
||||||
fprintf(stderr, RED "tint2: !shmget" RESET "\n");
|
|
||||||
goto err1;
|
|
||||||
}
|
|
||||||
shminfo.shmaddr = ximg->data = (char *)shmat(shminfo.shmid, 0, 0);
|
|
||||||
if (!shminfo.shmaddr) {
|
|
||||||
fprintf(stderr, RED "tint2: !shmat" RESET "\n");
|
|
||||||
goto err2;
|
|
||||||
}
|
|
||||||
shminfo.readOnly = False;
|
|
||||||
if (!XShmAttach(server.display, &shminfo)) {
|
|
||||||
fprintf(stderr, RED "tint2: !xshmattach" RESET "\n");
|
|
||||||
goto err3;
|
|
||||||
}
|
|
||||||
if (!XShmGetImage(server.display, win, ximg, 0, 0, AllPlanes)) {
|
|
||||||
fprintf(stderr, RED "tint2: !xshmgetimage" RESET "\n");
|
|
||||||
goto err4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XGetWindowAttributes(server.display, win, &wa);
|
|
||||||
if (wa.map_state != IsViewable)
|
|
||||||
goto err4;
|
|
||||||
|
|
||||||
|
fprintf(stderr, GREEN "tint2: creating image surface %ux%u" RESET "\n", tw, th);
|
||||||
result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, (int)tw, (int)th);
|
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);
|
||||||
memset(data, 0, tw * th);
|
memset(data, 0, tw * th);
|
||||||
|
|
||||||
// Fixed-point precision
|
|
||||||
const size_t prec = 1 << 16;
|
|
||||||
const size_t xstep = w * prec / fw;
|
|
||||||
const size_t ystep = h * prec / th;
|
|
||||||
|
|
||||||
const size_t offset_y1 = 0 * ystep / 8;
|
|
||||||
const size_t offset_x1 = 3 * xstep / 8;
|
|
||||||
|
|
||||||
const size_t offset_y2 = 1 * ystep / 8;
|
|
||||||
const size_t offset_x2 = 6 * xstep / 8;
|
|
||||||
|
|
||||||
const size_t offset_y3 = 4 * ystep / 8;
|
|
||||||
const size_t offset_x3 = 2 * xstep / 8;
|
|
||||||
|
|
||||||
const size_t offset_y4 = 4 * ystep / 8;
|
|
||||||
const size_t offset_x4 = 4 * xstep / 8;
|
|
||||||
|
|
||||||
const size_t offset_y5 = 4 * ystep / 8;
|
|
||||||
const size_t offset_x5 = 7 * xstep / 8;
|
|
||||||
|
|
||||||
const size_t offset_y6 = 6 * ystep / 8;
|
|
||||||
const size_t offset_x6 = 1 * xstep / 8;
|
|
||||||
|
|
||||||
const size_t offset_y7 = 7 * ystep / 8;
|
|
||||||
const size_t offset_x7 = 6 * xstep / 8;
|
|
||||||
|
|
||||||
const u_int32_t rmask = (u_int32_t)ximg->red_mask;
|
const u_int32_t rmask = (u_int32_t)ximg->red_mask;
|
||||||
const u_int32_t gmask = (u_int32_t)ximg->green_mask;
|
const u_int32_t gmask = (u_int32_t)ximg->green_mask;
|
||||||
const u_int32_t bmask = (u_int32_t)ximg->blue_mask;
|
const u_int32_t bmask = (u_int32_t)ximg->blue_mask;
|
||||||
for (size_t yt = 0, y = 0; yt < th; yt++, y += ystep) {
|
for (size_t y = 0; y < th; y++) {
|
||||||
for (size_t xt = 0, x = 0; xt < fw; xt++, x += xstep) {
|
for (size_t x = 0; x < tw; x++) {
|
||||||
size_t j = yt * tw + ox + xt;
|
u_int32_t c = (u_int32_t)XGetPixel(ximg, x, y);
|
||||||
u_int32_t c1 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x1) / prec), (int)((y + offset_y1) / prec));
|
data[y * tw + x] = c;
|
||||||
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 c4 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x4) / prec), (int)((y + offset_y4) / prec));
|
|
||||||
u_int32_t c5 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x5) / prec), (int)((y + offset_y5) / prec));
|
|
||||||
u_int32_t c6 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x6) / prec), (int)((y + offset_y6) / prec));
|
|
||||||
u_int32_t c7 = (u_int32_t)GetPixel(ximg, (int)((x + offset_x7) / prec), (int)((y + offset_y7) / prec));
|
|
||||||
u_int32_t b = ((c1 & bmask) + (c2 & bmask) + (c3 & bmask) + (c4 & bmask) + (c5 & bmask) * 2 + (c6 & bmask) +
|
|
||||||
(c7 & bmask)) /
|
|
||||||
8;
|
|
||||||
u_int32_t g = ((c1 & gmask) + (c2 & gmask) + (c3 & gmask) + (c4 & gmask) + (c5 & gmask) * 2 + (c6 & gmask) +
|
|
||||||
(c7 & gmask)) /
|
|
||||||
8;
|
|
||||||
u_int32_t r = ((c1 & rmask) + (c2 & rmask) + (c3 & rmask) + (c4 & rmask) + (c5 & rmask) * 2 + (c6 & rmask) +
|
|
||||||
(c7 & rmask)) /
|
|
||||||
8;
|
|
||||||
data[j] = (r & rmask) | (g & gmask) | (b & bmask);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imlib_context_set_drawable(pix);
|
||||||
|
Imlib_Image img = imlib_create_image_from_drawable(0, 0, 0, tw, th, 1);
|
||||||
|
//Imlib_Image img = imlib_create_image_using_data(tw, th, data);
|
||||||
|
imlib_context_set_image(img);
|
||||||
|
char path[256];
|
||||||
|
static unsigned count = 0;
|
||||||
|
sprintf(path, "thumb-%u-%u.png", win, count++);
|
||||||
|
imlib_save_image(path);
|
||||||
|
imlib_free_image();
|
||||||
|
|
||||||
// Convert to argb32
|
// Convert to argb32
|
||||||
if (rmask & 0xff0000) {
|
if (rmask & 0xff0000) {
|
||||||
// argb32 or rgb24 => Nothing to do
|
// argb32 or rgb24 => Nothing to do
|
||||||
@@ -539,24 +548,23 @@ 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_flush(result);
|
||||||
|
|
||||||
if (ximg) {
|
if (ximg) {
|
||||||
XDestroyImage(ximg);
|
XDestroyImage(ximg);
|
||||||
ximg = NULL;
|
ximg = NULL;
|
||||||
}
|
}
|
||||||
err4:
|
|
||||||
if (use_shm)
|
|
||||||
XShmDetach(server.display, &shminfo);
|
|
||||||
err3:
|
|
||||||
if (use_shm)
|
|
||||||
shmdt(shminfo.shmaddr);
|
|
||||||
err2:
|
|
||||||
if (use_shm)
|
|
||||||
shmctl(shminfo.shmid, IPC_RMID, NULL);
|
|
||||||
err1:
|
err1:
|
||||||
|
err4:
|
||||||
if (ximg)
|
if (ximg)
|
||||||
XDestroyImage(ximg);
|
XDestroyImage(ximg);
|
||||||
|
if (src_pic)
|
||||||
|
XRenderFreePicture(server.display, src_pic);
|
||||||
|
if (dst_pic)
|
||||||
|
XRenderFreePicture(server.display, dst_pic);
|
||||||
|
if (pix)
|
||||||
|
XFreePixmap(server.display, pix);
|
||||||
err0:
|
err0:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -576,24 +584,11 @@ gboolean cairo_surface_is_blank(cairo_surface_t *image_surface)
|
|||||||
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 (shm_allowed && server.has_shm && server.composite_manager) {
|
|
||||||
image_surface = get_window_thumbnail_ximage(win, (size_t)size, TRUE);
|
|
||||||
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
|
||||||
cairo_surface_destroy(image_surface);
|
|
||||||
image_surface = NULL;
|
|
||||||
}
|
|
||||||
if (debug_thumbnails) {
|
|
||||||
if (!image_surface)
|
|
||||||
fprintf(stderr, YELLOW "tint2: XShmGetImage failed, trying slower method" RESET "\n");
|
|
||||||
else
|
|
||||||
fprintf(stderr, "tint2: captured window using XShmGetImage\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!image_surface) {
|
if (!image_surface) {
|
||||||
image_surface = get_window_thumbnail_ximage(win, (size_t)size, FALSE);
|
image_surface = get_window_thumbnail_ximage(win, (size_t)size, FALSE);
|
||||||
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
||||||
|
fprintf(stderr, RED "tint2: captured blank thumbnail" RESET "\n");
|
||||||
cairo_surface_destroy(image_surface);
|
cairo_surface_destroy(image_surface);
|
||||||
image_surface = NULL;
|
image_surface = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
+1
-1
@@ -175,7 +175,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
battery_font_color = #ffffff 100
|
battery_font_color = #ffffff 100
|
||||||
bat1_format =
|
bat1_format =
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ clock_dwheel_command =
|
|||||||
# Battery
|
# Battery
|
||||||
battery_tooltip = 1
|
battery_tooltip = 1
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = xmessage 'tint2: Battery low!'
|
||||||
battery_full_cmd =
|
battery_full_cmd =
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
configure
|
||||||
doc/tint2.1
|
doc/tint2.1
|
||||||
sample/icon_and_text_1.tint2rc
|
sample/icon_and_text_1.tint2rc
|
||||||
sample/icon_and_text_2.tint2rc
|
sample/icon_and_text_2.tint2rc
|
||||||
@@ -59,8 +60,12 @@ src/util/area.c
|
|||||||
src/util/area.h
|
src/util/area.h
|
||||||
src/util/blur.c
|
src/util/blur.c
|
||||||
src/util/blur.h
|
src/util/blur.h
|
||||||
|
src/util/bt.c
|
||||||
|
src/util/bt.h
|
||||||
src/util/common.c
|
src/util/common.c
|
||||||
src/util/common.h
|
src/util/common.h
|
||||||
|
src/util/server.c
|
||||||
|
src/util/server.h
|
||||||
src/util/strlcat.c
|
src/util/strlcat.c
|
||||||
src/util/strlcat.h
|
src/util/strlcat.h
|
||||||
src/util/timer.c
|
src/util/timer.c
|
||||||
|
|||||||
Reference in New Issue
Block a user