Compare commits

...

49 Commits

Author SHA1 Message Date
o9000
477d08b5da Remove v from git tag when generating version string 2015-07-12 18:24:19 +02:00
o9000
50a07df5d2 Silence g_thread_init warning 2015-07-12 17:54:40 +02:00
o9000
b3cdde78b1 Add define _GNU_SOURCE for getline() 2015-07-12 17:50:59 +02:00
o9000
8207b16598 Updated theme files 2015-07-12 17:40:32 +02:00
o9000
f61f2af2f4 Updated string files for translations 2015-07-12 17:24:43 +02:00
o9000
90805cb526 tint2conf: Better theme management 2015-07-12 17:01:44 +02:00
o9000
04fe80b498 copy_file(): prevent truncating file if src == dest 2015-07-12 17:01:20 +02:00
o9000
60657c9809 Updated themes 2015-07-12 17:00:37 +02:00
o9000
3150b91f80 Install additional themes to /usr/[local/]share/tint2 2015-07-12 17:00:16 +02:00
o9000
7b854d49e3 Update readme 2015-07-12 14:42:47 +02:00
o9000
81a48b8f79 Update changelog 2015-07-12 14:40:00 +02:00
o9000
655ea6f06f Update build script 2015-07-12 14:36:11 +02:00
o9000
efe9aadb39 Prevent race at startup in detecting screen resolution changes 2015-07-12 14:36:11 +02:00
o9000
c0e1709d57 Capitalize name in desktop shortcut 2015-07-05 15:48:09 +00:00
o9000
ea8a4fbb1e Capitalize title in desktop shortcut 2015-07-05 10:34:36 +00:00
o9000
093963dadd Merge branch 'doc-fixes' into 'master'
Doc fixes

Hi o9000, thanks for resurrecting tint2!

Here are some purely "bureaucratic" fixes: I fixed some typo's, updated URLs, and cleaned up a few files.

See merge request !4
2015-07-05 10:33:43 +00:00
Sebastiaan Lokhorst
df429e8c34 Clean up .desktop file: remove unnecessary localization, fix English translation, use consistent captitalization of "tint2" (with a lowercase "t"). 2015-07-05 11:34:57 +02:00
Sebastiaan Lokhorst
d3c45adf34 Fix some typo's and clean up indentation. 2015-07-05 11:23:57 +02:00
Sebastiaan Lokhorst
043a0f7ab3 Update old Google Code URLs to new GitLab location. 2015-07-05 11:14:00 +02:00
o9000
574b6bc214 tint2conf: Fix typo to load desktop files from subdirectories 2015-07-04 18:41:04 +02:00
o9000
89e4a5a460 Fix crash in tint2conf (wrong string length in allocation) 2015-07-04 18:31:01 +02:00
o9000
2ebc75944e tint2conf: Sort launchers by name 2015-07-04 17:33:19 +02:00
o9000
acedd48708 Add IDE files 2015-07-04 16:57:45 +02:00
o9000
9fd9d51010 Fix timer bug (again) 2015-07-04 16:47:29 +02:00
o9000
9f8423f2eb Updated changelog 2015-07-04 13:37:42 +02:00
o9000
8242c969e3 Detect compositor at startup 2015-07-04 13:34:42 +02:00
o9000
7cd5c16fca Fix crash when calling stop_timeout from the callback of a repeated timer 2015-07-04 13:34:09 +02:00
o9000
290ddc1fea tint2conf: fix launcher_apps_dir 2015-07-04 08:39:46 +02:00
o9000
47a7013029 Remove noisy debug messages 2015-06-28 11:34:53 +02:00
o9000
a4de005a54 Add missing include 2015-06-26 23:46:43 +02:00
o9000
7ace3a5956 Updated changelog 2015-06-25 14:18:35 +00:00
o9000
5abbf168a9 Cosmetic changes 2015-06-25 15:56:36 +02:00
o9000
4d69a0bc33 tint2: Do not rely only on select() to detect new X events, since we sync the socket in the system tray which messes up select 2015-06-25 15:36:47 +02:00
o9000
222eca4099 systray: (disable_transparency=1) detect empty icons whenever a new icon is added, from any process; clear icon area because some icons were failing to redraw 2015-06-21 15:23:55 +02:00
o9000
ea75558ac2 systray: reduce icon flicker by painting on buffer instead of directly on window 2015-06-21 15:00:01 +02:00
o9000
876cae8239 systray: fix black icon background for 32-bit icons when disable_transparency = 1; fix empty icon detection when disable_transparency = 1; fix icon blinking by delaying rendering less aggressively; removed XClearArea on traywin->win (triggers unnecessary redraws); cache icon names; profiling messages updated 2015-06-21 14:50:08 +02:00
o9000
7c3951e3a0 systray: Profiling code. Export environment variable SYSTRAY_PROFILING=1 when running tint2 to enable it 2015-06-19 10:46:29 +02:00
o9000
552f060612 Updated strings in pl.po 2015-06-15 19:27:05 +02:00
o9000
e7cfa35288 Merge branch 'translation-bs_hr_sr' into 'master'
tint2conf: added bs, hr and sr translations

I translated tint2conf into Bosnian, Croatian and Serbian (Cyrillic).

See merge request !3
2015-06-15 07:52:22 +00:00
dglava
4326cd1380 tint2conf: added bs, hr and sr translations 2015-06-14 23:10:30 +02:00
o9000
19b40bc59e systray: Check icon position 2015-06-14 12:23:34 +02:00
o9000
8c9a9a111e systray: trigger resizes in some places 2015-06-14 11:39:51 +02:00
o9000
b13540123b systray: force a repaint on icon resize 2015-06-14 11:21:42 +02:00
o9000
f5b2de62b6 systray: reorder operations to prevent the long icon first show delay that occurs sometimes 2015-06-14 10:51:30 +02:00
o9000
1ba023fc83 Removed tintwizard.py as it no longer supports all config options 2015-06-14 10:06:33 +02:00
o9000
36e9e92df1 Changed tintwizard #! to python 2 (note that tintwizard is obsolete) 2015-06-13 10:54:28 +00:00
o9000
0f1dac50f1 Updated readme for 0.12-rc6 2015-06-13 10:08:43 +00:00
o9000
eb0346e02a Updated changelog 2015-06-13 10:07:23 +00:00
o9000
cae621918e systray: Do not turn off compositing for missing window errors 2015-06-13 11:32:22 +02:00
46 changed files with 9881 additions and 5976 deletions

View File

@@ -3,7 +3,7 @@ cmake_minimum_required( VERSION 2.6 )
option( ENABLE_BATTERY "Enable battery status plugin" ON )
option( ENABLE_TINT2CONF "Enable tint2conf build, a GTK+2 theme configurator for tint2" ON )
option( ENABLE_EXAMPLES "Install additional tin2rc examples" OFF )
option( ENABLE_EXAMPLES "Install additional tin2rc examples" ON )
option( ENABLE_RSVG "Rsvg support (launcher only)" ON )
option( ENABLE_SN "Startup notification support" ON )
option( ENABLE_ASAN "Build tint2 with AddressSanitizer" OFF )
@@ -23,7 +23,7 @@ pkg_check_modules( SN libstartup-notification-1.0>=0.12 )
find_library( RT_LIBRARY rt )
if( NOT X11_FOUND OR NOT PANGOCAIRO_FOUND OR NOT PANGO_FOUND OR NOT CAIRO_FOUND OR NOT GLIB2_FOUND OR NOT GOBJECT2_FOUND OR NOT IMLIB2_FOUND )
message( FATAL_ERROR "Not all dependencies fulfilled. See https://code.google.com/p/tint2/wiki/Install" )
message( FATAL_ERROR "Not all dependencies fulfilled. See https://gitlab.com/o9000/tint2/wikis/Install" )
endif( NOT X11_FOUND OR NOT PANGOCAIRO_FOUND OR NOT PANGO_FOUND OR NOT CAIRO_FOUND OR NOT GLIB2_FOUND OR NOT GOBJECT2_FOUND OR NOT IMLIB2_FOUND )
string( REPLACE ";" " " FLAGS_REPLACED "${IMLIB2_LDFLAGS}" )
@@ -33,6 +33,8 @@ if( NOT IMLIB_BUILD_WITH_X )
message( FATAL_ERROR "Imlib is not built with X support" )
endif( NOT IMLIB_BUILD_WITH_X )
add_definitions( -D_GNU_SOURCE )
include_directories( ${PROJECT_BINARY_DIR}
src
src/battery
@@ -42,7 +44,7 @@ include_directories( ${PROJECT_BINARY_DIR}
src/launcher
src/tooltip
src/util
src/freespace
src/freespace
${X11_INCLUDE_DIRS}
${PANGOCAIRO_INCLUDE_DIRS}
${PANGO_INCLUDE_DIRS}
@@ -68,8 +70,8 @@ set( SOURCES src/config.c
src/taskbar/taskbar.c
src/taskbar/taskbarname.c
src/tooltip/tooltip.c
src/freespace/freespace.c
src/util/area.c
src/freespace/freespace.c
src/util/area.c
src/util/common.c
src/util/strnatcmp.c
src/util/timer.c
@@ -156,5 +158,5 @@ install( FILES AUTHORS ChangeLog README.md DESTINATION ${DOCDIR} )
install( FILES doc/tint2.1 DESTINATION ${MANDIR}/man1 )
if( ENABLE_EXAMPLES )
file( GLOB SAMPLEFILES sample/*.tint2rc )
install( FILES ${SAMPLEFILES} DESTINATION ${DOCDIR}/examples )
install( FILES ${SAMPLEFILES} DESTINATION ${DATADIR}/tint2 )
endif( ENABLE_EXAMPLES )

View File

@@ -1,8 +1,11 @@
2015-05-23 master
2015-07-12 master
- Note: the changes listed here are based on the previous release tint2 0.11, however some distributions (e.g. Debian)
offered packages using newer commits and/or patches; thus from the user's perspective some of these features are
already present. They are marked with '(already released by distros)'.
- Major changes:
- Panel:
- Checks if a compositor is launched during the first 30 seconds after startup and if found, restarts the panel with
transparency enabled.
- Launcher:
- The launcher is now considered stable
- Enhancement: SVG icon support
@@ -27,7 +30,7 @@
- taskbar_hide_inactive_tasks
- taskbar_sort_order
- taskbar_name (already released by distros)
- task_align (already released by distros)
- task_align (already released by distros)
- Launcher:
- launcher* (already released by distros)
- launcher_apps_dir (previously patched in by some distros)
@@ -70,6 +73,7 @@
background of other icons;
- a crash caused by a change that prevents Google Chrome (and possibly other misbehaving applications) from leaving a large
number of empty icons in the system tray;
- a crash caused by the system tray code on computers with ATI cards;
- the panel window had a shadow;
- some ATI drivers return an extra monitor with size zero which should be ignored when using panel_monitor = all;
- the battery applet was sometimes working incorrectly with certain laptop models (the battery applet stopped updating after
@@ -79,7 +83,10 @@
application was started;
- seconds were not updating in the clock;
- tint2 hang triggered when an application started from the launcher was closed and startup notifications were enabled;
- the code that loads SVG icons was using a lot of memory.
- tint2 may fail to process X events for a few seconds when a new icon is added to the system tray;
- the code that loads SVG icons was using a lot of memory;
- fixed occasional race at startup in detecting screen resolution changes;
- modified timer code to prevent some rare double-frees or duplicate timers.
2010-06-26
- unhide tint2 panel when dragging something

View File

@@ -7,5 +7,4 @@ cmake -DCMAKE_INSTALL_PREFIX=/usr ../
make
sudo make install
To see additional options you can do after the cmake step a 'cmake -L ../'
To see additional options you can set at the 'cmake' step, run 'cmake -L ../'

View File

@@ -1,14 +1,14 @@
### New unstable release: 0.12-rc5
### New stable release: 0.12
Changes: https://gitlab.com/o9000/tint2/blob/master/ChangeLog
Documentation: https://gitlab.com/o9000/tint2/wikis/home
Try it out with (see also [dependencies](https://gitlab.com/o9000/tint2/wikis/Install#dependencies)):
```
mkdir tint2-0.12-rc5
cd tint2-0.12-rc5
wget 'https://gitlab.com/o9000/tint2/repository/archive.tar.gz?ref=v0.12-rc5' --output-document tint2-0.12-rc5.tar.gz
tar -xzf tint2-0.12-rc5.tar.gz
mkdir tint2-0.12
cd tint2-0.12
wget 'https://gitlab.com/o9000/tint2/repository/archive.tar.gz?ref=v0.12' --output-document tint2-0.12.tar.gz
tar -xzf tint2-0.12.tar.gz
cd tint2.git
mkdir build
cd build
@@ -17,6 +17,12 @@ make -j4
./tint2 &
./src/tint2conf/tint2conf &
```
To install from source, also run (as root):
```
make install
```
Please report any problems to https://gitlab.com/o9000/tint2/issues. Your feedback is much appreciated.
P.S. GitLab is now the official location of the tint2 project, migrated from Google Code, which is shutting down. In case you are wondering why not GitHub, BitBucket etc., we chose GitLab because it is open source, it is mature and works well, looks cool and has a very nice team.

View File

@@ -1,4 +1,3 @@
DEPENDENCIES:
cairo (whit X support), pango, glib2, libX11, libXinerama, libXrandr, libXrender, libXcomposite, libXdamage imlib2 (with X support)
you might need -dev packages on debian
cairo (with X support), pango, glib2, libX11, libXinerama, libXrandr, libXrender, libXcomposite, libXdamage, imlib2 (with X support)
you might need -dev packages on Debian

View File

@@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH TINT2 1 "2009-01-17"
.TH TINT2 1 "2015-07-05"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@@ -37,7 +37,7 @@ compliance with freedesktop specifications.
.PP
On the first startup tint2 creates a config file in $HOME/.config/tint2/tint2rc.
.PP
See wiki page on http://code.google.com/p/tint2/wiki/Welcome for more information.
See the wiki page at https://gitlab.com/o9000/tint2/wikis/home for more information.
.SH OPTIONS
.TP
.B \-c config-file

View File

@@ -1,5 +1,6 @@
#!/bin/sh
MAJOR=0.12
DIRTY=""
git update-index -q --ignore-submodules --refresh
@@ -29,7 +30,8 @@ then
fi
fi
VERSION=$(git describe --exact-match 2>/dev/null || echo "0.11-git$(git show -s --pretty=format:%cI.%h | tr -d ':' | tr -d '-' | tr '.' '-' | sed 's/T[0-9\+]*//g')")$DIRTY
VERSION=$(git describe --exact-match 2>/dev/null || echo "$MAJOR-git$(git show -s --pretty=format:%cI.%h | tr -d ':' | tr -d '-' | tr '.' '-' | sed 's/T[0-9\+]*//g')")$DIRTY
VERSION=$(echo "$VERSION" | sed 's/^v//')
echo '#define VERSION_STRING "'$VERSION'"' > version.h
echo $VERSION

View File

@@ -121,8 +121,12 @@ launcher_icon_size = 22
launcher_icon_asb = 100 0 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock

View File

@@ -121,8 +121,12 @@ launcher_icon_size = 22
launcher_icon_asb = 100 0 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock

View File

@@ -127,8 +127,12 @@ launcher_icon_size = 22
launcher_icon_asb = 100 0 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock

View File

@@ -0,0 +1,176 @@
#---- Generated by tint2conf e324 ----
# See https://gitlab.com/o9000/tint2/wikis/Configure for
# full documentation of the configuration options.
#-------------------------------------
# Backgrounds
# Background 1
rounded = 0
border_width = 1
background_color = #eeeeee 0
border_color = #bbbbbb 10
# Background 2
rounded = 5
border_width = 0
background_color = #eeeeee 4
border_color = #cccccc 100
# Background 3
rounded = 5
border_width = 1
background_color = #dddddd 4
border_color = #999999 100
# Background 4
rounded = 5
border_width = 1
background_color = #aa4400 100
border_color = #aa7733 100
# Background 5
rounded = 2
border_width = 1
background_color = #ffffaa 100
border_color = #999999 100
# Background 6
rounded = 2
border_width = 1
background_color = #eeeeee 4
border_color = #cccccc 100
# Background 7
rounded = 2
border_width = 1
background_color = #dddddd 3
border_color = #999999 100
# Background 8
rounded = 3
border_width = 0
background_color = #999999 4
border_color = #cccccc 100
#-------------------------------------
# Panel
panel_items = LTSC
panel_size = 100% 32
panel_margin = 0 0
panel_padding = 4 2 4
panel_background_id = 1
wm_menu = 1
panel_dock = 0
panel_position = bottom center horizontal
panel_layer = normal
panel_monitor = all
autohide = 0
autohide_show_timeout = 0
autohide_hide_timeout = 0.5
autohide_height = 2
strut_policy = follow_size
panel_window_name = tint2
disable_transparency = 0
font_shadow = 0
#-------------------------------------
# Taskbar
taskbar_mode = single_desktop
taskbar_padding = 0 0 2
taskbar_background_id = 0
taskbar_active_background_id = 0
taskbar_name = 1
taskbar_hide_inactive_tasks = 0
taskbar_hide_different_monitor = 0
taskbar_name_padding = 6 3
taskbar_name_background_id = 6
taskbar_name_active_background_id = 7
taskbar_name_font = sans bold 9
taskbar_name_font_color = #ffffff 100
taskbar_name_active_font_color = #ffffff 100
taskbar_distribute_size = 1
taskbar_sort_order = none
task_align = left
#-------------------------------------
# Task
task_text = 1
task_icon = 1
task_centered = 1
urgent_nb_of_blink = 100000
task_maximum_size = 140 35
task_padding = 4 3 4
task_font = sans 8
task_tooltip = 1
task_font_color = #ffffff 100
task_icon_asb = 100 0 0
task_background_id = 2
task_active_background_id = 3
task_urgent_background_id = 4
task_iconified_background_id = 2
mouse_left = toggle_iconify
mouse_middle = none
mouse_right = close
mouse_scroll_up = prev_task
mouse_scroll_down = next_task
#-------------------------------------
# System tray (notification area)
systray_padding = 4 0 2
systray_background_id = 0
systray_sort = ascending
systray_icon_size = 22
systray_icon_asb = 100 0 0
systray_monitor = 1
#-------------------------------------
# Launcher
launcher_padding = 0 0 2
launcher_background_id = 0
launcher_icon_size = 22
launcher_icon_asb = 100 0 0
launcher_icon_theme_override = 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock
time1_format = %H:%M
time2_format = %A %d %B
time1_font = sans bold 8
time1_timezone =
time2_timezone =
time2_font = sans 7
clock_font_color = #ffffff 100
clock_padding = 1 0
clock_background_id = 0
clock_tooltip =
clock_tooltip_timezone =
clock_lclick_command = zenity --calendar --text ""
clock_rclick_command = orage
#-------------------------------------
# Battery
battery_low_status = 10
battery_low_cmd = notify-send "battery low"
bat1_font = sans 8
bat2_font = sans 6
battery_font_color = #ffffff 100
battery_padding = 1 0
battery_background_id = 0
battery_hide = 101
#-------------------------------------
# Tooltip
tooltip_show_timeout = 0.5
tooltip_hide_timeout = 0.1
tooltip_padding = 2 2
tooltip_background_id = 5
tooltip_font_color = #222222 100
tooltip_font = sans 9

View File

@@ -59,8 +59,12 @@ launcher_icon_size = 18
launcher_icon_asb = 100 0 0
launcher_tooltip = 1
startup_notifications = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
# Taskbar
taskbar_mode = single_desktop
@@ -85,7 +89,7 @@ urgent_nb_of_blink = 100000
task_icon_asb = 100 0 0
task_active_icon_asb = 100 0 0
task_urgent_icon_asb = 100 0 0
task_iconified_icon_asb = 70 0 0
task_iconified_icon_asb = 100 0 0
# Fonts
task_font = sans 8
@@ -113,7 +117,7 @@ time1_format = %H:%M
time1_font = sans 8
time2_format = %A %d %B
time2_font = sans 7
clock_font_color = #FFFFFF 90
clock_font_color = #FFFFFF 100
clock_padding = 1 0
clock_background_id = 0
clock_rclick_command = orage
@@ -132,7 +136,7 @@ battery_low_cmd = notify-send "battery low"
battery_hide = 101
bat1_font = sans 8
bat2_font = sans 6
battery_font_color = #FFFFFF 94
battery_font_color = #FFFFFF 100
battery_padding = 1 0
battery_background_id = 0

View File

@@ -1,4 +1,6 @@
#---- Generated by tint2conf c113 ----
#---- Generated by tint2conf 258e ----
# See https://gitlab.com/o9000/tint2/wikis/Configure for
# full documentation of the configuration options.
#-------------------------------------
# Backgrounds
# Background 1
@@ -81,6 +83,7 @@ taskbar_name_font_color = #dddddd 100
taskbar_name_active_font_color = #dddddd 100
taskbar_distribute_size = 1
taskbar_sort_order = none
task_align = left
#-------------------------------------
# Task
@@ -119,10 +122,15 @@ launcher_padding = 0 0 2
launcher_background_id = 0
launcher_icon_size = 22
launcher_icon_asb = 100 0 0
launcher_icon_theme_override = 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock

View File

@@ -121,8 +121,12 @@ launcher_icon_size = 22
launcher_icon_asb = 100 0 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock

View File

@@ -127,8 +127,12 @@ launcher_icon_size = 22
launcher_icon_asb = 100 0 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock

View File

@@ -0,0 +1,176 @@
#---- Generated by tint2conf e324 ----
# See https://gitlab.com/o9000/tint2/wikis/Configure for
# full documentation of the configuration options.
#-------------------------------------
# Backgrounds
# Background 1
rounded = 0
border_width = 1
background_color = #eeeeee 0
border_color = #bbbbbb 10
# Background 2
rounded = 5
border_width = 0
background_color = #eeeeee 4
border_color = #cccccc 100
# Background 3
rounded = 5
border_width = 1
background_color = #dddddd 4
border_color = #999999 100
# Background 4
rounded = 5
border_width = 1
background_color = #aa4400 100
border_color = #aa7733 100
# Background 5
rounded = 2
border_width = 1
background_color = #ffffaa 100
border_color = #999999 100
# Background 6
rounded = 2
border_width = 1
background_color = #eeeeee 4
border_color = #cccccc 100
# Background 7
rounded = 2
border_width = 1
background_color = #dddddd 3
border_color = #999999 100
# Background 8
rounded = 3
border_width = 0
background_color = #999999 4
border_color = #cccccc 100
#-------------------------------------
# Panel
panel_items = CSTL
panel_size = 100% 152
panel_margin = 0 0
panel_padding = 2 2 2
panel_background_id = 1
wm_menu = 1
panel_dock = 0
panel_position = bottom left vertical
panel_layer = normal
panel_monitor = all
autohide = 0
autohide_show_timeout = 0
autohide_hide_timeout = 0.5
autohide_height = 2
strut_policy = follow_size
panel_window_name = tint2
disable_transparency = 0
font_shadow = 0
#-------------------------------------
# Taskbar
taskbar_mode = multi_desktop
taskbar_padding = 0 0 2
taskbar_background_id = 0
taskbar_active_background_id = 0
taskbar_name = 1
taskbar_hide_inactive_tasks = 0
taskbar_hide_different_monitor = 0
taskbar_name_padding = 6 3
taskbar_name_background_id = 6
taskbar_name_active_background_id = 7
taskbar_name_font = sans bold 9
taskbar_name_font_color = #ffffff 100
taskbar_name_active_font_color = #ffffff 100
taskbar_distribute_size = 1
taskbar_sort_order = none
task_align = left
#-------------------------------------
# Task
task_text = 1
task_icon = 1
task_centered = 0
urgent_nb_of_blink = 100000
task_maximum_size = 152 35
task_padding = 4 3 4
task_font = sans 8
task_tooltip = 1
task_font_color = #ffffff 100
task_icon_asb = 100 0 0
task_background_id = 2
task_active_background_id = 3
task_urgent_background_id = 4
task_iconified_background_id = 2
mouse_left = toggle_iconify
mouse_middle = none
mouse_right = close
mouse_scroll_up = prev_task
mouse_scroll_down = next_task
#-------------------------------------
# System tray (notification area)
systray_padding = 0 0 2
systray_background_id = 0
systray_sort = ascending
systray_icon_size = 22
systray_icon_asb = 100 0 0
systray_monitor = 1
#-------------------------------------
# Launcher
launcher_padding = 0 0 2
launcher_background_id = 0
launcher_icon_size = 22
launcher_icon_asb = 100 0 0
launcher_icon_theme_override = 0
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/tint2conf.desktop
launcher_item_app = /usr/local/share/applications/tint2conf.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/iceweasel.desktop
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/google-chrome.desktop
#-------------------------------------
# Clock
time1_format = %H:%M
time2_format = %A %d %B
time1_font = sans bold 9
time1_timezone =
time2_timezone =
time2_font = sans 9
clock_font_color = #ffffff 100
clock_padding = 1 0
clock_background_id = 0
clock_tooltip =
clock_tooltip_timezone =
clock_lclick_command = zenity --calendar --text ""
clock_rclick_command = orage
#-------------------------------------
# Battery
battery_low_status = 10
battery_low_cmd = notify-send "battery low"
bat1_font = sans 8
bat2_font = sans 6
battery_font_color = #ffffff 100
battery_padding = 1 0
battery_background_id = 0
battery_hide = 101
#-------------------------------------
# Tooltip
tooltip_show_timeout = 0.5
tooltip_hide_timeout = 0.1
tooltip_padding = 2 2
tooltip_background_id = 5
tooltip_font_color = #222222 100
tooltip_font = sans 9

View File

@@ -105,6 +105,7 @@ int read_desktop_file(const char *path, DesktopEntry *entry)
char *key, *value;
int i;
entry->path = strdup(path);
entry->name = entry->icon = entry->exec = NULL;
if ((fp = fopen(path, "rt")) == NULL) {
@@ -174,7 +175,8 @@ void free_desktop_entry(DesktopEntry *entry)
free(entry->name);
free(entry->icon);
free(entry->exec);
entry->name = entry->icon = entry->exec = NULL;
free(entry->path);
entry->name = entry->icon = entry->exec = entry->path = NULL;
}
void test_read_desktop_file()

View File

@@ -11,6 +11,7 @@ typedef struct DesktopEntry {
char *name;
char *exec;
char *icon;
char *path;
} DesktopEntry;
// Parses a line of the form "key = value". Modifies the line.

View File

@@ -549,7 +549,7 @@ void set_panel_properties(Panel *p)
memset(&wmhints, 0, sizeof(wmhints));
if (panel_dock) {
// Necessary for placing the panel into the dock on Openbox and Fluxbox.
// See https://code.google.com/p/tint2/issues/detail?id=465
// See https://gitlab.com/o9000/tint2/issues/465
wmhints.icon_window = wmhints.window_group = p->main_win;
wmhints.flags = StateHint | IconWindowHint;
wmhints.initial_state = WithdrawnState;

View File

@@ -284,7 +284,7 @@ void get_monitors()
if (res && res->ncrtc >= nbmonitor) {
// use xrandr to identify monitors (does not work with proprietery nvidia drivers)
// Workaround for issue https://code.google.com/p/tint2/issues/detail?id=353
// Workaround for issue https://gitlab.com/o9000/tint2/issues/353
// on some recent configs, XRRGetScreenResourcesCurrent returns a fantom monitor at last position
{
int i = res->ncrtc - 1;

View File

@@ -52,9 +52,12 @@ int systray_max_icon_size;
int systray_monitor;
int chrono;
int systray_composited;
int systray_profile;
// background pixmap if we render ourselves the icons
static Pixmap render_background;
const int min_refresh_period = 50;
const int max_fast_refreshes = 5;
void default_systray()
{
@@ -67,6 +70,7 @@ void default_systray()
systray.area._on_change_layout = on_change_systray;
systray.area.size_mode = SIZE_BY_CONTENT;
systray.area._resize = resize_systray;
systray_profile = getenv("SYSTRAY_PROFILING") != NULL;
}
void cleanup_systray()
@@ -89,10 +93,10 @@ void init_systray()
return;
systray_composited = !server.disable_transparency && server.visual32 && server.colormap32;
printf("Systray composited rendering %s\n", systray_composited ? "on" : "off");
fprintf(stderr, "Systray composited rendering %s\n", systray_composited ? "on" : "off");
if (!systray_composited) {
printf("systray_asb forced to 100 0 0\n");
fprintf(stderr, "systray_asb forced to 100 0 0\n");
systray.alpha = 100;
systray.brightness = systray.saturation = 0;
}
@@ -125,6 +129,8 @@ void init_systray_panel(void *p)
void draw_systray(void *obj, cairo_t *c)
{
if (systray_profile)
fprintf(stderr, BLUE "[%f] %s:%d\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
if (systray_composited) {
if (render_background)
XFreePixmap(server.dsp, render_background);
@@ -138,6 +144,8 @@ void draw_systray(void *obj, cairo_t *c)
int resize_systray(void *obj)
{
if (systray_profile)
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
Systraybar *sysbar = obj;
GSList *l;
int count;
@@ -155,7 +163,7 @@ int resize_systray(void *obj)
continue;
count++;
}
//printf("count %d\n", count);
fprintf(stderr, BLUE "%s:%d number of icons = %d\n" RESET, __FUNCTION__, __LINE__, count);
if (panel_horizontal) {
int height = sysbar->area.height - 2*sysbar->area.bg->border.width - 2*sysbar->area.paddingy;
@@ -178,6 +186,8 @@ int resize_systray(void *obj)
void on_change_systray (void *obj)
{
if (systray_profile)
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
// here, systray.area.posx/posy are defined by rendering engine. so we can calculate position of tray icon.
Systraybar *sysbar = obj;
if (sysbar->icons_per_column == 0 || sysbar->icons_per_row == 0)
@@ -203,7 +213,8 @@ void on_change_systray (void *obj)
traywin->y = posy;
traywin->x = posx;
// printf("systray %d %d : pos %d, %d\n", traywin->parent, traywin->win, posx, posy);
if (systray_profile)
fprintf(stderr, "%s:%d win = %lu (%s), parent = %lu, x = %d, y = %d\n", __FUNCTION__, __LINE__, traywin->win, traywin->name, traywin->parent, posx, posy);
traywin->width = sysbar->icon_size;
traywin->height = sysbar->icon_size;
if (panel_horizontal) {
@@ -237,6 +248,8 @@ void on_change_systray (void *obj)
void start_net()
{
if (systray_profile)
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
if (net_sel_win) {
// protocol already started
if (!systray_enabled)
@@ -262,13 +275,13 @@ void start_net()
_NET_WM_PID = XInternAtom(server.dsp, "_NET_WM_PID", True);
int ret = XGetWindowProperty(server.dsp, win, _NET_WM_PID, 0, 1024, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
fprintf(stderr, "tint2 : another systray is running");
fprintf(stderr, RED "tint2 : another systray is running");
if (ret == Success && prop) {
pid = prop[1] * 256;
pid += prop[0];
fprintf(stderr, " pid=%d", pid);
}
fprintf(stderr, "\n");
fprintf(stderr, "\n" RESET);
return;
}
@@ -289,11 +302,13 @@ void start_net()
XSetSelectionOwner(server.dsp, server.atom._NET_SYSTEM_TRAY_SCREEN, net_sel_win, CurrentTime);
if (XGetSelectionOwner(server.dsp, server.atom._NET_SYSTEM_TRAY_SCREEN) != net_sel_win) {
stop_net();
fprintf(stderr, "tint2 : can't get systray manager\n");
fprintf(stderr, RED "tint2 : can't get systray manager\n" RESET);
return;
}
//fprintf(stderr, "tint2 : systray started\n");
fprintf(stderr, GREEN "tint2 : systray started\n" RESET);
if (systray_profile)
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
XClientMessageEvent ev;
ev.type = ClientMessage;
ev.window = server.root_win;
@@ -308,9 +323,40 @@ void start_net()
}
void net_message(XClientMessageEvent *e)
{
if (systray_profile)
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
unsigned long opcode;
Window win;
opcode = e->data.l[1];
switch (opcode) {
case SYSTEM_TRAY_REQUEST_DOCK:
win = e->data.l[2];
if (win)
add_icon(win);
break;
case SYSTEM_TRAY_BEGIN_MESSAGE:
case SYSTEM_TRAY_CANCEL_MESSAGE:
// we don't show baloons messages.
break;
default:
if (opcode == server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA)
fprintf(stderr, "message from dockapp: %s\n", e->data.b);
else
fprintf(stderr, RED "SYSTEM_TRAY : unknown message type\n" RESET);
break;
}
}
void stop_net()
{
//fprintf(stderr, "tint2 : systray stopped\n");
if (systray_profile)
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
if (systray.list_icons) {
// remove_icon change systray.list_icons
while(systray.list_icons)
@@ -330,9 +376,11 @@ void stop_net()
gboolean error;
int window_error_handler(Display *d, XErrorEvent *e)
{
if (systray_profile)
fprintf(stderr, RED "[%f] %s:%d\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
error = TRUE;
if (e->error_code != BadWindow) {
printf("systray: error code %d\n", e->error_code);
fprintf(stderr, RED "systray: error code %d\n" RESET, e->error_code);
}
return 0;
}
@@ -350,20 +398,8 @@ static gint compare_traywindows(gconstpointer a, gconstpointer b)
if (systray.sort == SYSTRAY_SORT_ASCENDING ||
systray.sort == SYSTRAY_SORT_DESCENDING) {
XTextProperty name_a, name_b;
if (XGetWMName(server.dsp, traywin_a->win, &name_a) == 0) {
return -1;
} else if (XGetWMName(server.dsp, traywin_b->win, &name_b) == 0) {
XFree(name_a.value);
return 1;
} else {
gint retval = g_ascii_strncasecmp((char*)name_a.value, (char*)name_b.value, -1) *
(systray.sort == SYSTRAY_SORT_ASCENDING ? 1 : -1);
XFree(name_a.value);
XFree(name_b.value);
return retval;
}
return g_ascii_strncasecmp(traywin_a->name, traywin_b->name, -1) *
(systray.sort == SYSTRAY_SORT_ASCENDING ? 1 : -1);
}
if (systray.sort == SYSTRAY_SORT_LEFT2RIGHT ||
@@ -378,7 +414,17 @@ static gint compare_traywindows(gconstpointer a, gconstpointer b)
gboolean add_icon(Window win)
{
TrayWindow *traywin;
XTextProperty xname;
char *name;
if (XGetWMName(server.dsp, win, &xname)) {
name = strdup((char*)xname.value);
XFree(xname.value);
} else {
name = strdup("");
}
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, win, name);
Panel *panel = systray.area.panel;
int hide = 0;
@@ -401,10 +447,56 @@ gboolean add_icon(Window win)
GSList *l;
int num_empty_same_pid = 0;
for (l = systray.list_icons; l; l = l->next) {
if (((TrayWindow*)l->data)->win == win)
TrayWindow *other = (TrayWindow*)l->data;
if (other->win == win) {
free(name);
return FALSE;
if (pid && ((TrayWindow*)l->data)->pid == pid && ((TrayWindow*)l->data)->empty)
num_empty_same_pid++;
}
if (!systray_composited) {
// Empty icon detection: we compare the contents of the icon with the contents of the panel pixmap.
// If any pixel is different, the icon is not empty.
imlib_context_set_visual(server.visual);
imlib_context_set_colormap(server.colormap);
imlib_context_set_drawable(other->win);
Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, other->width, other->height, 1);
if (image) {
imlib_context_set_drawable(panel->temp_pmap);
Imlib_Image bg = imlib_create_image_from_drawable(0, other->x, other->y, other->width, other->height, 1);
imlib_context_set_image(bg);
DATA32* data_bg = imlib_image_get_data_for_reading_only();
imlib_context_set_image(image);
imlib_image_set_has_alpha(other->depth > 24);
DATA32* data = imlib_image_get_data_for_reading_only();
int x, y;
int empty = 1;
for (x = 0; x < other->width && empty; x++) {
for (y = 0; y < other->height && empty; y++) {
DATA32 pixel = data[y * other->width + x];
DATA32 a = (pixel >> 24) & 0xff;
if (a == 0)
continue;
DATA32 rgb = pixel & 0xffFFff;
DATA32 pixel_bg = data_bg[y * other->width + x];
DATA32 rgb_bg = pixel_bg & 0xffFFff;
if (rgb != rgb_bg) {
fprintf(stderr, "Pixel: %x different from bg %x at pos %d %d\n", pixel, pixel_bg, x, y);
empty = 0;
}
}
}
other->empty = empty;
imlib_free_image_and_decache();
imlib_context_set_image(bg);
imlib_free_image_and_decache();
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s) empty = %d\n", profiling_get_time(), __FUNCTION__, __LINE__, other->win, other->name, other->empty);
}
}
if (pid && other->pid == pid) {
if (other->empty)
num_empty_same_pid++;
}
}
// Remove empty icons if the application leaves behind more than 1
@@ -413,46 +505,56 @@ gboolean add_icon(Window win)
for (l = systray.list_icons; l; l = l->next) {
if (pid && ((TrayWindow*)l->data)->pid == pid && ((TrayWindow*)l->data)->empty) {
num_empty_same_pid++;
fprintf(stderr, "Removing tray icon %lu from misbehaving application with pid=%d\n", ((TrayWindow*)l->data)->win, pid);
fprintf(stderr, RED "Removing tray icon %lu (%s) from misbehaving application with pid=%d (too many icons)\n" RESET, ((TrayWindow*)l->data)->win, ((TrayWindow*)l->data)->name, pid);
remove_icon((TrayWindow*)l->data);
break;
}
}
}
//printf("add_icon: %d, pid %d, %d\n", win, pid, num_empty_same_pid);
// Create the parent window that will embed the icon
XWindowAttributes attr;
if (XGetWindowAttributes(server.dsp, win, &attr) == False)
if (XGetWindowAttributes(server.dsp, win, &attr) == False) {
free(name);
return FALSE;
}
unsigned long mask = 0;
XSetWindowAttributes set_attr;
Visual* visual = server.visual;
//printf("icon with depth: %d, width %d, height %d\n", attr.depth, attr.width, attr.height);
if (systray_composited || attr.depth != server.depth) {
visual = attr.visual;
set_attr.colormap = attr.colormap;
set_attr.background_pixel = 0;
set_attr.border_pixel = 0;
mask = CWColormap|CWBackPixel|CWBorderPixel;
} else {
fprintf(stderr, GREEN "add_icon: %lu (%s), pid %d, %d, visual %p, colormap %lu, depth %d, width %d, height %d\n" RESET,
win, name, pid, num_empty_same_pid, attr.visual, attr.colormap, attr.depth, attr.width, attr.height);
if (server.disable_transparency) {
set_attr.background_pixmap = ParentRelative;
mask = CWBackPixmap;
if (systray_composited || attr.depth != server.depth) {
visual = attr.visual;
set_attr.colormap = attr.colormap;
mask |= CWColormap;
}
} else {
if (systray_composited || attr.depth != server.depth) {
visual = attr.visual;
set_attr.background_pixel = 0;
set_attr.border_pixel = 0;
set_attr.colormap = attr.colormap;
mask = CWColormap|CWBackPixel|CWBorderPixel;
} else {
set_attr.background_pixmap = ParentRelative;
mask = CWBackPixmap;
}
}
Window parent = XCreateWindow(server.dsp, panel->main_win, 0, 0, 30, 30, 0, attr.depth, InputOutput, visual, mask, &set_attr);
// Add the icon to the list
traywin = g_new0(TrayWindow, 1);
TrayWindow *traywin = g_new0(TrayWindow, 1);
traywin->parent = parent;
traywin->win = win;
traywin->hide = hide;
traywin->depth = attr.depth;
// Reparenting is done at the first paint event when the window is positioned correctly over its empty background,
// to prevent graphical corruptions in icons with fake transparency
traywin->reparented = 0;
traywin->damage = 0;
traywin->empty = 0;
traywin->pid = pid;
traywin->name = name;
traywin->chrono = chrono;
chrono++;
@@ -464,18 +566,29 @@ gboolean add_icon(Window win)
else
systray.list_icons = g_slist_append(systray.list_icons, traywin);
systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
// printf("add_icon win %lx, %d\n", win, g_slist_length(systray.list_icons));
if (!traywin->hide && !panel->is_hidden)
XMapRaised(server.dsp, traywin->parent);
XSync(server.dsp, False);
if (systray_profile)
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
// Resize and redraw the systray
if (systray_profile)
fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
systray.area.resize = 1;
systray.area.redraw = 1;
panel->area.resize = 1;
panel_refresh = 1;
refresh_systray = 1;
return TRUE;
}
gboolean reparent_icon(TrayWindow *traywin)
{
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
if (traywin->reparented)
return TRUE;
@@ -489,7 +602,7 @@ gboolean reparent_icon(TrayWindow *traywin)
XSync(server.dsp, False);
XSetErrorHandler(old);
if (error != FALSE) {
printf("systray %d: cannot embed icon for window %lu parent %lu pid %d\n", __LINE__, traywin->win, traywin->parent, traywin->pid);
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid);
remove_icon(traywin);
return FALSE;
}
@@ -502,13 +615,11 @@ gboolean reparent_icon(TrayWindow *traywin)
XSync(server.dsp, False);
XSetErrorHandler(old);
if (error != FALSE) {
printf("systray %d: cannot embed icon for window %lu parent %lu pid %d\n", __LINE__, traywin->win, traywin->parent, traywin->pid);
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid);
remove_icon(traywin);
return FALSE;
}
traywin->reparented = 1;
// Embed into parent
{
XEvent e;
@@ -530,13 +641,12 @@ gboolean reparent_icon(TrayWindow *traywin)
XSync(server.dsp, False);
XSetErrorHandler(old);
if (error != FALSE) {
printf("systray %d: cannot embed icon for window %lu pid %d\n", __LINE__, traywin->win, traywin->pid);
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->pid);
remove_icon(traywin);
return FALSE;
}
}
// Check if window was embedded
{
Atom acttype;
int actfmt;
@@ -547,14 +657,22 @@ gboolean reparent_icon(TrayWindow *traywin)
ret = XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data);
if (ret == Success) {
if (data) {
if (nbitem == 2) {
//hide = ((data[1] & XEMBED_MAPPED) == 0);
//printf("hide %d\n", hide);
if (nbitem >= 2) {
int hide = ((data[1] & XEMBED_MAPPED) == 0);
if (hide) {
// In theory we have to check the embedding with this and remove icons that refuse embedding.
// In practice we have no idea when the other application processes the event and accepts the embed so we cannot check without a race.
// Race can be triggered with PyGtk(2) apps.
//fprintf(stderr, RED "tint2: window refused embedding\n" RESET);
//remove_icon(traywin);
//XFree(data);
//return FALSE;
}
}
XFree(data);
}
} else {
fprintf(stderr, "tint2 : xembed error\n");
fprintf(stderr, RED "tint2 : xembed error\n" RESET);
remove_icon(traywin);
return FALSE;
}
@@ -571,20 +689,30 @@ gboolean reparent_icon(TrayWindow *traywin)
XMapWindow(server.dsp, traywin->win);
if (!traywin->hide && !panel->is_hidden)
XMapRaised(server.dsp, traywin->parent);
XSync(server.dsp, False);
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
XFlush(server.dsp);
XSync(server.dsp, False);
traywin->reparented = 1;
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
return TRUE;
}
void remove_icon(TrayWindow *traywin)
{
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
Panel* panel = systray.area.panel;
// remove from our list
systray.list_icons = g_slist_remove(systray.list_icons, traywin);
printf("remove_icon: %lu\n", traywin->win);
fprintf(stderr, YELLOW "remove_icon: %lu (%s)\n" RESET, traywin->win, traywin->name);
XSelectInput(server.dsp, traywin->win, NoEventMask);
if (traywin->damage)
@@ -601,6 +729,7 @@ void remove_icon(TrayWindow *traywin)
XSync(server.dsp, False);
XSetErrorHandler(old);
stop_timeout(traywin->render_timeout);
free(traywin->name);
g_free(traywin);
// check empty systray
@@ -614,81 +743,81 @@ void remove_icon(TrayWindow *traywin)
if (count == 0)
hide(&systray.area);
// changed in systray
// Resize and redraw the systray
if (systray_profile)
fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
systray.area.resize = 1;
systray.area.redraw = 1;
panel->area.resize = 1;
panel_refresh = 1;
refresh_systray = 1;
}
void net_message(XClientMessageEvent *e)
void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
{
unsigned long opcode;
Window win;
if (systray_profile)
fprintf(stderr, "XConfigure event: win = %lu (%s), x = %d, y = %d, w = %d, h = %d\n",
traywin->win, traywin->name, e->xconfigure.x, e->xconfigure.y, e->xconfigure.width, e->xconfigure.height);
Panel* panel = systray.area.panel;
opcode = e->data.l[1];
switch (opcode) {
case SYSTEM_TRAY_REQUEST_DOCK:
win = e->data.l[2];
if (win)
add_icon(win);
break;
case SYSTEM_TRAY_BEGIN_MESSAGE:
case SYSTEM_TRAY_CANCEL_MESSAGE:
// we don't show baloons messages.
break;
default:
if (opcode == server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA)
printf("message from dockapp: %s\n", e->data.b);
else
fprintf(stderr, "SYSTEM_TRAY : unknown message type\n");
break;
//fprintf(stderr, "move tray %d\n", traywin->x);
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
if (traywin->reparented) {
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
// Trigger window repaint
stop_timeout(traywin->render_timeout);
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
}
// Resize and redraw the systray
if (systray_profile)
fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
systray.area.resize = 1;
systray.area.redraw = 1;
panel->area.resize = 1;
panel_refresh = 1;
refresh_systray = 1;
}
Display *display = NULL;
XImage *tintXGetImage(Window win)
void systray_destroy_event(TrayWindow *traywin)
{
char *display_name = XDisplayName(NULL);
if (!display_name)
return NULL;
if (!display)
display = XOpenDisplay(display_name);
if (!display)
return NULL;
unsigned int border_width;
int xpos, ypos;
unsigned int width, height, depth;
Window root;
if (!XGetGeometry(display, win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
fprintf(stderr, "Couldn't get geometry of window!\n");
return NULL;
}
return XGetImage(display, win, 0, 0, width, height, AllPlanes, XYPixmap);
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
remove_icon(traywin);
}
void systray_render_icon_composited(void* t)
{
// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0
// we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here
TrayWindow* traywin = t;
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
struct timespec earliest_render = add_msec_to_timespec(traywin->time_last_render, 50);
if (compare_timespecs(&earliest_render, &now) > 0) {
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
return;
struct timespec earliest_render = add_msec_to_timespec(traywin->time_last_render, min_refresh_period);
if (compare_timespecs(&earliest_render, &now) > min_refresh_period) {
traywin->num_fast_renders++;
if (traywin->num_fast_renders > max_fast_refreshes) {
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
if (systray_profile)
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
return;
}
} else {
traywin->time_last_render.tv_sec = now.tv_sec;
traywin->time_last_render.tv_nsec = now.tv_nsec;
traywin->num_fast_renders = 0;
}
traywin->time_last_render.tv_sec = now.tv_sec;
traywin->time_last_render.tv_nsec = now.tv_nsec;
if ( traywin->width == 0 || traywin->height == 0 ) {
if (traywin->width == 0 || traywin->height == 0) {
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
if (systray_profile)
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
return;
}
@@ -697,44 +826,25 @@ void systray_render_icon_composited(void* t)
traywin->render_timeout = NULL;
}
int empty = 1;
XImage *ximage = tintXGetImage(traywin->win);
if (ximage) {
if (ximage->width != traywin->width ||
ximage->height != traywin->height) {
XFree(ximage);
XCloseDisplay(display);
display = NULL;
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
{
// We shouldn't have to do this as we already listen for structure notify events.
// But things work fine so why change it.
unsigned int border_width;
int xpos, ypos;
unsigned int width, height, depth;
Window root;
if (!XGetGeometry(server.dsp, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
fprintf(stderr, RED "Couldn't get geometry of window!\n" RESET);
return;
}
XColor color;
if (ximage->width > 0 && ximage->height > 0) {
color.pixel = XGetPixel(ximage, ximage->width/2, ximage->height/2);
if (color.pixel != 0)
empty = 0;
int x, y;
for (x = 0; empty && x < ximage->width; x++) {
for (y = 0; empty && y < ximage->height; y++) {
color.pixel = XGetPixel(ximage, x, y);
if (color.pixel != 0)
empty = 0;
}
}
if (width != traywin->width || height != traywin->height || xpos != 0 || ypos != 0) {
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
if (systray_profile)
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
return;
}
XFree(ximage);
XCloseDisplay(display);
display = NULL;
}
if (traywin->empty != empty) {
traywin->empty = empty;
systray.area.resize = 1;
panel_refresh = 1;
systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
}
//printf("systray_render_icon_now: %d empty %d\n", traywin->win, empty);
if (empty)
return;
// good systray icons support 32 bit depth, but some icons are still 24 bit.
// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
@@ -746,7 +856,7 @@ void systray_render_icon_composited(void* t)
// drawable. If someone knows why it does not work with the traywindow itself, please tell me ;)
Pixmap tmp_pmap = XCreatePixmap(server.dsp, traywin->win, traywin->width, traywin->height, 32);
if (!tmp_pmap) {
goto on_error;
goto on_systray_error;
}
XRenderPictFormat *f;
if (traywin->depth == 24) {
@@ -754,14 +864,14 @@ void systray_render_icon_composited(void* t)
} else if (traywin->depth == 32) {
f = XRenderFindStandardFormat(server.dsp, PictStandardARGB32);
} else {
printf("Strange tray icon found with depth: %d\n", traywin->depth);
fprintf(stderr, RED "Strange tray icon found with depth: %d\n" RESET, traywin->depth);
XFreePixmap(server.dsp, tmp_pmap);
return;
}
XRenderPictFormat *f32 = XRenderFindVisualFormat(server.dsp, server.visual32);
if (!f || !f32) {
XFreePixmap(server.dsp, tmp_pmap);
goto on_error;
goto on_systray_error;
}
XSync(server.dsp, False);
@@ -809,12 +919,14 @@ void systray_render_icon_composited(void* t)
if (traywin->depth == 24) {
createHeuristicMask(data, traywin->width, traywin->height);
}
int empty = imageEmpty(data, traywin->width, traywin->height);
if (systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0)
adjust_asb(data, traywin->width, traywin->height, systray.alpha, (float)systray.saturation/100, (float)systray.brightness/100);
imlib_image_put_back_data(data);
XCopyArea(server.dsp, render_background, systray.area.pix, server.gc, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height, traywin->x-systray.area.posx, traywin->y-systray.area.posy);
render_image(systray.area.pix, traywin->x-systray.area.posx, traywin->y-systray.area.posy);
XCopyArea(server.dsp, systray.area.pix, panel->main_win, server.gc, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height, traywin->x, traywin->y);
XCopyArea(server.dsp, systray.area.pix, panel->temp_pmap, server.gc, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height, traywin->x, traywin->y);
imlib_free_image_and_decache();
XFreePixmap(server.dsp, tmp_pmap);
imlib_context_set_visual(server.visual);
@@ -822,18 +934,37 @@ void systray_render_icon_composited(void* t)
if (traywin->damage)
XDamageSubtract(server.dsp, traywin->damage, None, None);
XFlush(server.dsp);
XSync(server.dsp, False);
XSetErrorHandler(old);
if (error)
goto on_error;
if (traywin->empty != empty) {
traywin->empty = empty;
systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
// Resize and redraw the systray
if (systray_profile)
fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
systray.area.resize = 1;
systray.area.redraw = 1;
panel->area.resize = 1;
panel_refresh = 1;
refresh_systray = 1;
}
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
return;
on_error:
printf("systray: rendering error. Disabling compositing and restarting systray...\n");
fprintf(stderr, RED "systray %d: rendering error for icon %lu (%s) pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->pid);
return;
on_systray_error:
fprintf(stderr, RED "systray %d: rendering error for icon %lu (%s) pid %d. "
"Disabling compositing and restarting systray...\n" RESET, __LINE__, traywin->win, traywin->name, traywin->pid);
systray_composited = 0;
stop_net();
start_net();
@@ -841,14 +972,26 @@ on_error:
}
void systray_render_icon(TrayWindow* traywin)
void systray_render_icon(void* t)
{
if (!reparent_icon(traywin))
return;
TrayWindow* traywin = t;
if (systray_profile)
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
if (!traywin->reparented) {
if (!reparent_icon(traywin))
return;
if (systray_composited) {
// We need to process the events in the main loop first
stop_timeout(traywin->render_timeout);
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
if (systray_profile)
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
return;
}
}
if (systray_composited) {
if (!traywin->render_timeout)
systray_render_icon_composited(traywin);
systray_render_icon_composited(traywin);
} else {
// Trigger window repaint
XClearArea(server.dsp, traywin->parent, 0, 0, traywin->width, traywin->height, True);
@@ -857,8 +1000,10 @@ void systray_render_icon(TrayWindow* traywin)
}
void refresh_systray_icon()
void refresh_systray_icons()
{
if (systray_profile)
fprintf(stderr, BLUE "[%f] %s:%d\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
TrayWindow *traywin;
GSList *l;
for (l = systray.list_icons; l ; l = l->next) {

View File

@@ -48,7 +48,9 @@ typedef struct
int pid;
int chrono;
struct timespec time_last_render;
int num_fast_renders;
int reparented;
char *name;
} TrayWindow;
@@ -59,6 +61,7 @@ extern int refresh_systray;
extern int systray_enabled;
extern int systray_max_icon_size;
extern int systray_monitor;
extern int systray_profile;
// default global data
void default_systray();
@@ -84,8 +87,10 @@ void net_message(XClientMessageEvent *e);
gboolean add_icon(Window id);
void remove_icon(TrayWindow *traywin);
void refresh_systray_icon();
void systray_render_icon(TrayWindow* traywin);
void refresh_systray_icons();
void systray_render_icon(void *t);
void systray_reconfigure_event(TrayWindow *traywin, XEvent *e);
void systray_destroy_event(TrayWindow *traywin);
void kde_update_icons();
#endif

View File

@@ -20,6 +20,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -58,6 +59,43 @@ Atom dnd_atom;
int dnd_sent_request;
char *dnd_launcher_exec;
timeout* detect_compositor_timer = NULL;
int detect_compositor_timer_counter = 0;
void detect_compositor(void *arg)
{
if (server.composite_manager) {
stop_timeout(detect_compositor_timer);
return;
}
detect_compositor_timer_counter--;
if (detect_compositor_timer_counter < 0) {
stop_timeout(detect_compositor_timer);
return;
}
// No compositor, check for one
if (XGetSelectionOwner(server.dsp, server.atom._NET_WM_CM_S0) != None) {
stop_timeout(detect_compositor_timer);
// Restart tint2
fprintf(stderr, "Detected compositor, restarting tint2...\n");
kill(getpid(), SIGUSR1);
}
}
void start_detect_compositor()
{
// Already have a compositor, nothing to do
if (server.composite_manager)
return;
stop_timeout(detect_compositor_timer);
// Check every 0.5 seconds for up to 30 seconds
detect_compositor_timer_counter = 60;
detect_compositor_timer = add_timeout(500, 500, detect_compositor, 0, &detect_compositor_timer);
}
void signal_handler(int sig)
{
// signal handler is light as it should be
@@ -165,9 +203,7 @@ static void sigchld_handler_async() {
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
SnLauncherContext *ctx;
ctx = (SnLauncherContext *) g_tree_lookup (server.pids, GINT_TO_POINTER (pid));
if (ctx == NULL) {
fprintf(stderr, "Unknown child %d terminated!\n", pid);
} else {
if (ctx) {
g_tree_remove (server.pids, GINT_TO_POINTER (pid));
sn_launcher_context_complete (ctx);
sn_launcher_context_unref (ctx);
@@ -203,6 +239,9 @@ void init_X11_pre_config()
// config file use '.' as decimal separator
setlocale(LC_NUMERIC, "POSIX");
/* Catch events */
XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
// get monitor and desktop config
get_monitors();
get_desktops();
@@ -224,9 +263,11 @@ void init_X11_post_config()
if (pipe(sn_pipe) != 0) {
fprintf(stderr, "Creating pipe failed.\n");
} else {
fcntl(sn_pipe[0], F_SETFL, O_NONBLOCK | fcntl(sn_pipe[0], F_GETFL));
fcntl(sn_pipe[1], F_SETFL, O_NONBLOCK | fcntl(sn_pipe[1], F_GETFL));
sn_pipe_valid = 1;
struct sigaction act;
memset (&act, 0, sizeof (struct sigaction));
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = sigchld_handler;
if (sigaction(SIGCHLD, &act, 0)) {
perror("sigaction");
@@ -239,9 +280,6 @@ void init_X11_post_config()
imlib_context_set_visual (server.visual);
imlib_context_set_colormap (server.colormap);
/* Catch events */
XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
// load default icon
gchar *path;
const gchar * const *data_dirs;
@@ -817,8 +855,10 @@ void event_expose (XEvent *e)
}
void event_configure_notify (Window win)
void event_configure_notify(XEvent *e)
{
Window win = e->xconfigure.window;
// change in root window (xrandr)
if (win == server.root_win) {
signal_pending = SIGUSR1;
@@ -831,12 +871,7 @@ void event_configure_notify (Window win)
for (l = systray.list_icons; l ; l = l->next) {
traywin = (TrayWindow*)l->data;
if (traywin->win == win) {
//printf("move tray %d\n", traywin->x);
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
if (traywin->reparented)
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
panel_refresh = 1;
refresh_systray = 1;
systray_reconfigure_event(traywin, e);
return;
}
}
@@ -1081,7 +1116,7 @@ int main (int argc, char *argv[])
int x11_fd, i;
Panel *panel;
GSList *it;
struct timeval* timeout;
struct timeval* select_timeout;
int hidden_dnd = 0;
// Make stdout/stderr flush after a newline (for some reason they don't even if tint2 is started from a terminal)
@@ -1105,6 +1140,7 @@ start:
}
init_X11_post_config();
start_detect_compositor();
init_panel();
if (snapshot_path) {
@@ -1132,32 +1168,32 @@ start:
while (1) {
if (panel_refresh) {
if (systray_profile)
fprintf(stderr, BLUE "[%f] %s:%d redrawing panel\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
panel_refresh = 0;
for (i=0 ; i < nb_panel ; i++) {
for (i = 0; i < nb_panel ;i++) {
panel = &panel1[i];
if (panel->is_hidden) {
XCopyArea(server.dsp, panel->hidden_pixmap, panel->main_win, server.gc, 0, 0, panel->hidden_width, panel->hidden_height, 0, 0);
XSetWindowBackgroundPixmap(server.dsp, panel->main_win, panel->hidden_pixmap);
}
else {
if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap);
} else {
if (panel->temp_pmap)
XFreePixmap(server.dsp, panel->temp_pmap);
panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth);
rendering(panel);
if (panel == (Panel*)systray.area.panel) {
if (refresh_systray && panel && !panel->is_hidden) {
refresh_systray = 0;
XSetWindowBackgroundPixmap(server.dsp, panel->main_win, panel->temp_pmap);
refresh_systray_icons();
}
}
XCopyArea(server.dsp, panel->temp_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0);
}
}
XFlush (server.dsp);
panel = (Panel*)systray.area.panel;
if (refresh_systray && panel && !panel->is_hidden) {
refresh_systray = 0;
// tint2 doen't draw systray icons. it just redraw background.
XSetWindowBackgroundPixmap (server.dsp, panel->main_win, panel->temp_pmap);
// force icon's refresh
refresh_systray_icon();
}
XFlush(server.dsp);
}
// thanks to AngryLlama for the timer
@@ -1171,253 +1207,249 @@ start:
}
update_next_timeout();
if (next_timeout.tv_sec >= 0 && next_timeout.tv_usec >= 0)
timeout = &next_timeout;
select_timeout = &next_timeout;
else
timeout = 0;
select_timeout = 0;
// Wait for X Event or a Timer
if (select(maxfd+1, &fdset, 0, 0, timeout) > 0) {
if (FD_ISSET(sn_pipe[0], &fdset)) {
if (XPending(server.dsp) > 0 || select(maxfd+1, &fdset, 0, 0, select_timeout) >= 0) {
if (sn_pipe_valid) {
char buffer[1];
ssize_t wur = read(sn_pipe[0], buffer, 1);
(void) wur;
sigchld_handler_async();
while (read(sn_pipe[0], buffer, sizeof(buffer)) > 0) {
sigchld_handler_async();
}
}
if (FD_ISSET(x11_fd, &fdset)) {
while (XPending (server.dsp)) {
XNextEvent(server.dsp, &e);
while (XPending(server.dsp) > 0) {
XNextEvent(server.dsp, &e);
#if HAVE_SN
if (startup_notifications)
sn_display_process_event(server.sn_dsp, &e);
if (startup_notifications)
sn_display_process_event(server.sn_dsp, &e);
#endif // HAVE_SN
panel = get_panel(e.xany.window);
if (panel && panel_autohide) {
if (e.type == EnterNotify)
autohide_trigger_show(panel);
else if (e.type == LeaveNotify)
autohide_trigger_hide(panel);
if (panel->is_hidden) {
if (e.type == ClientMessage && e.xclient.message_type == server.atom.XdndPosition) {
hidden_dnd = 1;
autohide_show(panel);
}
else
continue; // discard further processing of this event because the panel is not visible yet
panel = get_panel(e.xany.window);
if (panel && panel_autohide) {
if (e.type == EnterNotify)
autohide_trigger_show(panel);
else if (e.type == LeaveNotify)
autohide_trigger_hide(panel);
if (panel->is_hidden) {
if (e.type == ClientMessage && e.xclient.message_type == server.atom.XdndPosition) {
hidden_dnd = 1;
autohide_show(panel);
}
else if (hidden_dnd && e.type == ClientMessage && e.xclient.message_type == server.atom.XdndLeave) {
hidden_dnd = 0;
autohide_hide(panel);
}
}
switch (e.type) {
case ButtonPress:
tooltip_hide(0);
event_button_press (&e);
break;
case ButtonRelease:
event_button_release(&e);
break;
case MotionNotify: {
unsigned int button_mask = Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
if (e.xmotion.state & button_mask)
event_button_motion_notify (&e);
Panel* panel = get_panel(e.xmotion.window);
Area* area = click_area(panel, e.xmotion.x, e.xmotion.y);
if (area->_get_tooltip_text)
tooltip_trigger_show(area, panel, &e);
else
tooltip_trigger_hide();
continue; // discard further processing of this event because the panel is not visible yet
}
else if (hidden_dnd && e.type == ClientMessage && e.xclient.message_type == server.atom.XdndLeave) {
hidden_dnd = 0;
autohide_hide(panel);
}
}
switch (e.type) {
case ButtonPress:
tooltip_hide(0);
event_button_press (&e);
break;
case ButtonRelease:
event_button_release(&e);
break;
case MotionNotify: {
unsigned int button_mask = Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
if (e.xmotion.state & button_mask)
event_button_motion_notify (&e);
Panel* panel = get_panel(e.xmotion.window);
Area* area = click_area(panel, e.xmotion.x, e.xmotion.y);
if (area->_get_tooltip_text)
tooltip_trigger_show(area, panel, &e);
else
tooltip_trigger_hide();
break;
}
case LeaveNotify:
tooltip_trigger_hide();
break;
case Expose:
event_expose(&e);
break;
case PropertyNotify:
event_property_notify(&e);
break;
case ConfigureNotify:
event_configure_notify(&e);
break;
case ReparentNotify:
if (!systray_enabled)
break;
panel = (Panel*)systray.area.panel;
if (e.xany.window == panel->main_win) // reparented to us
break;
// FIXME: 'reparent to us' badly detected => disabled
break;
case UnmapNotify:
case DestroyNotify:
if (e.xany.window == server.composite_manager) {
// Stop real_transparency
fprintf(stderr, "Detected compositor shutdown, restarting tint2...\n");
signal_pending = SIGUSR1;
break;
}
case LeaveNotify:
tooltip_trigger_hide();
if (e.xany.window == g_tooltip.window || !systray_enabled)
break;
case Expose:
event_expose(&e);
break;
case PropertyNotify:
event_property_notify(&e);
break;
case ConfigureNotify:
event_configure_notify (e.xconfigure.window);
break;
case ReparentNotify:
if (!systray_enabled)
for (it = systray.list_icons; it; it = g_slist_next(it)) {
if (((TrayWindow*)it->data)->win == e.xany.window) {
systray_destroy_event((TrayWindow*)it->data);
break;
panel = (Panel*)systray.area.panel;
if (e.xany.window == panel->main_win) // reparented to us
break;
// FIXME: 'reparent to us' badly detected => disabled
break;
case UnmapNotify:
case DestroyNotify:
if (e.xany.window == server.composite_manager) {
}
}
break;
case ClientMessage:
ev = &e.xclient;
if (ev->data.l[1] == server.atom._NET_WM_CM_S0) {
if (ev->data.l[2] == None)
// Stop real_transparency
signal_pending = SIGUSR1;
break;
}
if (e.xany.window == g_tooltip.window || !systray_enabled)
break;
for (it = systray.list_icons; it; it = g_slist_next(it)) {
if (((TrayWindow*)it->data)->win == e.xany.window) {
remove_icon((TrayWindow*)it->data);
break;
else
// Start real_transparency
signal_pending = SIGUSR1;
}
if (systray_enabled && e.xclient.message_type == server.atom._NET_SYSTEM_TRAY_OPCODE && e.xclient.format == 32 && e.xclient.window == net_sel_win) {
net_message(&e.xclient);
}
else if (e.xclient.message_type == server.atom.XdndEnter) {
dnd_enter(&e.xclient);
}
else if (e.xclient.message_type == server.atom.XdndPosition) {
dnd_position(&e.xclient);
}
else if (e.xclient.message_type == server.atom.XdndDrop) {
dnd_drop(&e.xclient);
}
break;
case SelectionNotify:
{
Atom target = e.xselection.target;
fprintf(stderr, "DnD %s:%d: A selection notify has arrived!\n", __FILE__, __LINE__);
fprintf(stderr, "DnD %s:%d: Requestor = %lu\n", __FILE__, __LINE__, e.xselectionrequest.requestor);
fprintf(stderr, "DnD %s:%d: Selection atom = %s\n", __FILE__, __LINE__, GetAtomName(server.dsp, e.xselection.selection));
fprintf(stderr, "DnD %s:%d: Target atom = %s\n", __FILE__, __LINE__, GetAtomName(server.dsp, target));
fprintf(stderr, "DnD %s:%d: Property atom = %s\n", __FILE__, __LINE__, GetAtomName(server.dsp, e.xselection.property));
if (e.xselection.property != None && dnd_launcher_exec) {
Property prop = read_property(server.dsp, dnd_target_window, dnd_selection);
//If we're being given a list of targets (possible conversions)
if (target == server.atom.TARGETS && !dnd_sent_request) {
dnd_sent_request = 1;
dnd_atom = pick_target_from_targets(server.dsp, prop);
if (dnd_atom == None) {
fprintf(stderr, "No matching datatypes.\n");
} else {
//Request the data type we are able to select
fprintf(stderr, "Now requsting type %s", GetAtomName(server.dsp, dnd_atom));
XConvertSelection(server.dsp, dnd_selection, dnd_atom, dnd_selection, dnd_target_window, CurrentTime);
}
}
break;
} else if (target == dnd_atom) {
//Dump the binary data
fprintf(stderr, "DnD %s:%d: Data begins:\n", __FILE__, __LINE__);
fprintf(stderr, "--------\n");
int i;
for (i = 0; i < prop.nitems * prop.format/8; i++)
fprintf(stderr, "%c", ((char*)prop.data)[i]);
fprintf(stderr, "--------\n");
case ClientMessage:
ev = &e.xclient;
if (ev->data.l[1] == server.atom._NET_WM_CM_S0) {
if (ev->data.l[2] == None)
// Stop real_transparency
signal_pending = SIGUSR1;
else
// Start real_transparency
signal_pending = SIGUSR1;
}
if (systray_enabled && e.xclient.message_type == server.atom._NET_SYSTEM_TRAY_OPCODE && e.xclient.format == 32 && e.xclient.window == net_sel_win) {
net_message(&e.xclient);
}
else if (e.xclient.message_type == server.atom.XdndEnter) {
dnd_enter(&e.xclient);
}
else if (e.xclient.message_type == server.atom.XdndPosition) {
dnd_position(&e.xclient);
}
else if (e.xclient.message_type == server.atom.XdndDrop) {
dnd_drop(&e.xclient);
}
break;
case SelectionNotify:
{
Atom target = e.xselection.target;
fprintf(stderr, "DnD %s:%d: A selection notify has arrived!\n", __FILE__, __LINE__);
fprintf(stderr, "DnD %s:%d: Requestor = %lu\n", __FILE__, __LINE__, e.xselectionrequest.requestor);
fprintf(stderr, "DnD %s:%d: Selection atom = %s\n", __FILE__, __LINE__, GetAtomName(server.dsp, e.xselection.selection));
fprintf(stderr, "DnD %s:%d: Target atom = %s\n", __FILE__, __LINE__, GetAtomName(server.dsp, target));
fprintf(stderr, "DnD %s:%d: Property atom = %s\n", __FILE__, __LINE__, GetAtomName(server.dsp, e.xselection.property));
if (e.xselection.property != None && dnd_launcher_exec) {
Property prop = read_property(server.dsp, dnd_target_window, dnd_selection);
//If we're being given a list of targets (possible conversions)
if (target == server.atom.TARGETS && !dnd_sent_request) {
dnd_sent_request = 1;
dnd_atom = pick_target_from_targets(server.dsp, prop);
if (dnd_atom == None) {
fprintf(stderr, "No matching datatypes.\n");
int cmd_length = 0;
cmd_length += 1; // (
cmd_length += strlen(dnd_launcher_exec) + 1; // exec + space
cmd_length += 1; // open double quotes
for (i = 0; i < prop.nitems * prop.format/8; i++) {
char c = ((char*)prop.data)[i];
if (c == '\n') {
if (i < prop.nitems * prop.format/8 - 1) {
cmd_length += 3; // close double quotes, space, open double quotes
}
} else if (c == '\r') {
} else {
//Request the data type we are able to select
fprintf(stderr, "Now requsting type %s", GetAtomName(server.dsp, dnd_atom));
XConvertSelection(server.dsp, dnd_selection, dnd_atom, dnd_selection, dnd_target_window, CurrentTime);
}
} else if (target == dnd_atom) {
//Dump the binary data
fprintf(stderr, "DnD %s:%d: Data begins:\n", __FILE__, __LINE__);
fprintf(stderr, "--------\n");
int i;
for (i = 0; i < prop.nitems * prop.format/8; i++)
fprintf(stderr, "%c", ((char*)prop.data)[i]);
fprintf(stderr, "--------\n");
int cmd_length = 0;
cmd_length += 1; // (
cmd_length += strlen(dnd_launcher_exec) + 1; // exec + space
cmd_length += 1; // open double quotes
for (i = 0; i < prop.nitems * prop.format/8; i++) {
char c = ((char*)prop.data)[i];
if (c == '\n') {
if (i < prop.nitems * prop.format/8 - 1) {
cmd_length += 3; // close double quotes, space, open double quotes
}
} else if (c == '\r') {
} else {
cmd_length += 1; // 1 character
if (c == '`' || c == '$' || c == '\\') {
cmd_length += 1; // escape with one backslash
}
cmd_length += 1; // 1 character
if (c == '`' || c == '$' || c == '\\') {
cmd_length += 1; // escape with one backslash
}
}
cmd_length += 1; // close double quotes
cmd_length += 2; // &)
cmd_length += 1; // terminator
char *cmd = calloc(cmd_length, 1);
cmd[0] = '\0';
strcat(cmd, "(");
strcat(cmd, dnd_launcher_exec);
strcat(cmd, " \"");
for (i = 0; i < prop.nitems * prop.format/8; i++) {
char c = ((char*)prop.data)[i];
if (c == '\n') {
if (i < prop.nitems * prop.format/8 - 1) {
strcat(cmd, "\" \"");
}
} else if (c == '\r') {
} else {
if (c == '`' || c == '$' || c == '\\') {
strcat(cmd, "\\");
}
char sc[2];
sc[0] = c;
sc[1] = '\0';
strcat(cmd, sc);
}
}
strcat(cmd, "\"");
strcat(cmd, "&)");
fprintf(stderr, "DnD %s:%d: Running command: %s\n", __FILE__, __LINE__, cmd);
tint_exec(cmd);
free(cmd);
// Reply OK.
XClientMessageEvent m;
memset(&m, 0, sizeof(m));
m.type = ClientMessage;
m.display = server.dsp;
m.window = dnd_source_window;
m.message_type = server.atom.XdndFinished;
m.format = 32;
m.data.l[0] = dnd_target_window;
m.data.l[1] = 1;
m.data.l[2] = server.atom.XdndActionCopy; //We only ever copy.
XSendEvent(server.dsp, dnd_source_window, False, NoEventMask, (XEvent*)&m);
XSync(server.dsp, False);
}
cmd_length += 1; // close double quotes
cmd_length += 2; // &)
cmd_length += 1; // terminator
XFree(prop.data);
char *cmd = calloc(cmd_length, 1);
cmd[0] = '\0';
strcat(cmd, "(");
strcat(cmd, dnd_launcher_exec);
strcat(cmd, " \"");
for (i = 0; i < prop.nitems * prop.format/8; i++) {
char c = ((char*)prop.data)[i];
if (c == '\n') {
if (i < prop.nitems * prop.format/8 - 1) {
strcat(cmd, "\" \"");
}
} else if (c == '\r') {
} else {
if (c == '`' || c == '$' || c == '\\') {
strcat(cmd, "\\");
}
char sc[2];
sc[0] = c;
sc[1] = '\0';
strcat(cmd, sc);
}
}
strcat(cmd, "\"");
strcat(cmd, "&)");
fprintf(stderr, "DnD %s:%d: Running command: %s\n", __FILE__, __LINE__, cmd);
tint_exec(cmd);
free(cmd);
// Reply OK.
XClientMessageEvent m;
memset(&m, 0, sizeof(m));
m.type = ClientMessage;
m.display = server.dsp;
m.window = dnd_source_window;
m.message_type = server.atom.XdndFinished;
m.format = 32;
m.data.l[0] = dnd_target_window;
m.data.l[1] = 1;
m.data.l[2] = server.atom.XdndActionCopy; //We only ever copy.
XSendEvent(server.dsp, dnd_source_window, False, NoEventMask, (XEvent*)&m);
XSync(server.dsp, False);
}
break;
XFree(prop.data);
}
default:
if (e.type == XDamageNotify+damage_event) {
// union needed to avoid strict-aliasing warnings by gcc
union { XEvent e; XDamageNotifyEvent de; } event_union = {.e=e};
TrayWindow *traywin;
GSList *l;
XDamageNotifyEvent* de = &event_union.de;
for (l = systray.list_icons; l ; l = l->next) {
traywin = (TrayWindow*)l->data;
if ( traywin->parent == de->drawable ) {
systray_render_icon(traywin);
break;
}
break;
}
default:
if (e.type == XDamageNotify+damage_event) {
XDamageNotifyEvent *de = (XDamageNotifyEvent*)&e;
GSList *l;
for (l = systray.list_icons; l ; l = l->next) {
TrayWindow *traywin = (TrayWindow*)l->data;
if (traywin->parent == de->drawable) {
systray_render_icon(traywin);
break;
}
}
}
@@ -1432,7 +1464,6 @@ start:
if (signal_pending == SIGUSR1) {
// restart tint2
// SIGUSR1 used when : user's signal, composite manager stop/start or xrandr
FD_CLR (x11_fd, &fdset); // not sure if needed
goto start;
}
else {

View File

@@ -20,6 +20,7 @@ include_directories( ../util
${RSVG_INCLUDE_DIRS} )
set(SOURCES ../util/common.c
../util/strnatcmp.c
../config.c
../server.c
../launcher/apps-common.c

View File

@@ -18,6 +18,7 @@
**************************************************************************/
#include <time.h>
#include <unistd.h>
#ifdef HAVE_VERSION_H
#include "version.h"
@@ -65,6 +66,7 @@ static void menuImportDefault();
static void menuSaveAs();
static void menuDelete();
static void edit_current_theme();
static void set_current_theme();
static void refresh_current_theme();
static void menuAbout();
static gboolean view_onPopupMenu(GtkWidget *treeview, gpointer userdata);
@@ -110,6 +112,7 @@ static const char *global_ui =
" </menubar>"
" <toolbar name='ToolBar'>"
" <toolitem action='ThemeProperties'/>"
" <toolitem action='ThemeSelect'/>"
" </toolbar>"
" <popup name='ThemePopup'>"
" <menuitem action='ThemeProperties'/>"
@@ -129,7 +132,10 @@ int main(int argc, char **argv)
GtkActionGroup *actionGroup;
gtk_init(&argc, &argv);
g_thread_init((NULL));
#if !GLIB_CHECK_VERSION(2, 31, 0)
g_thread_init(NULL);
#endif
{
gchar *tint2_config_dir = g_build_filename(g_get_user_config_dir(), "tint2", NULL);
@@ -162,6 +168,7 @@ int main(int argc, char **argv)
{"ThemeSaveAs", GTK_STOCK_SAVE_AS, _("_Save as..."), NULL, _("Save theme as"), G_CALLBACK(menuSaveAs)},
{"ThemeDelete", GTK_STOCK_DELETE, _("_Delete"), NULL, _("Delete theme"), G_CALLBACK(menuDelete)},
{"ThemeProperties", GTK_STOCK_PROPERTIES, _("_Edit theme..."), NULL, _("Edit selected theme"), G_CALLBACK(edit_current_theme)},
{"ThemeSelect", GTK_STOCK_APPLY, _("_Make default"), NULL, _("Replace the default theme with the selected one"), G_CALLBACK(set_current_theme)},
{"ThemeQuit", GTK_STOCK_QUIT, _("_Quit"), "<control>Q", _("Quit"), G_CALLBACK(gtk_main_quit)},
{"EditMenu", NULL, _("Edit"), NULL, NULL, NULL},
{"EditRefresh", GTK_STOCK_REFRESH, _("Refresh"), NULL, _("Refresh"), G_CALLBACK(refresh_current_theme)},
@@ -482,6 +489,33 @@ static void edit_current_theme()
}
}
static void set_current_theme()
{
GtkTreeSelection *sel;
GtkTreeIter iter;
GtkTreeModel *model;
gchar *file;
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_theme_view));
if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(sel), &model, &iter)) {
gtk_tree_model_get(model, &iter, COL_THEME_FILE, &file, -1);
// config_read_file(file);
gchar *main_file = g_build_filename(g_get_user_config_dir(), "tint2", "tint2rc", NULL);
{
gchar *backup_path = g_strdup_printf("%s.backup.%ld", main_file, time(NULL));
copy_file(main_file, backup_path);
g_free(backup_path);
}
copy_file(file, main_file);
int unused = system("killall -SIGUSR1 tint2 || pkill -SIGUSR1 -x tint2");
(void)unused;
g_free(file);
select_first_theme();
refresh_current_theme();
}
}
static void viewRowActivated(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
{
edit_current_theme();
@@ -489,8 +523,56 @@ static void viewRowActivated(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeV
// ====== Theme load/reload ======
static void copy_default_themes()
{
gchar *path_home = g_build_filename(g_get_user_config_dir(), "tint2", "tint2rc", NULL);
if (!g_file_test(path_home, G_FILE_TEST_EXISTS)) {
const gchar * const * system_dirs = g_get_system_config_dirs();
int i;
for (i = 0; system_dirs[i]; i++) {
gchar *path = g_build_filename(system_dirs[i], "tint2", "tint2rc", NULL);
if (g_file_test(path, G_FILE_TEST_EXISTS)) {
copy_file(path, path_home);
}
g_free(path);
}
}
g_free(path_home);
const gchar * const * data_dirs = g_get_system_data_dirs();
int i;
for (i = 0; data_dirs[i]; i++) {
gchar *path_tint2 = g_build_filename(data_dirs[i], "tint2", NULL);
fprintf(stderr, "%s\n", path_tint2);
GDir *dir = g_dir_open(path_tint2, 0, NULL);
if (dir) {
const gchar *file_name;
while ((file_name = g_dir_read_name(dir))) {
if (!g_file_test(file_name, G_FILE_TEST_IS_DIR) &&
!strstr(file_name, "backup") &&
!strstr(file_name, "copy") &&
!strstr(file_name, "~") &&
(endswith(file_name, "tint2rc") ||
endswith(file_name, ".conf"))) {
gchar *path_home = g_build_filename(g_get_user_config_dir(), "tint2", file_name, NULL);
if (!g_file_test(path_home, G_FILE_TEST_EXISTS)) {
gchar *path_usr = g_build_filename(path_tint2, file_name, NULL);
copy_file(path_usr, path_home);
g_free(path_usr);
}
g_free(path_home);
}
}
g_dir_close(dir);
}
g_free(path_tint2);
}
}
static void load_all_themes()
{
copy_default_themes();
gtk_list_store_clear(GTK_LIST_STORE(g_store));
gchar *tint2_config_dir = g_build_filename(g_get_user_config_dir(), "tint2", NULL);
@@ -500,6 +582,7 @@ static void load_all_themes()
return;
}
gboolean found_theme = FALSE;
const gchar *file_name;
while ((file_name = g_dir_read_name(dir))) {
if (!g_file_test(file_name, G_FILE_TEST_IS_DIR) &&
@@ -515,12 +598,7 @@ static void load_all_themes()
}
}
if (!found_theme) {
gchar *path_tint2rc = g_build_filename (g_get_user_config_dir(), "tint2", "tint2rc", NULL);
copy_file(get_default_config_path(), path_tint2rc);
g_free(path_tint2rc);
load_all_themes();
} else {
if (found_theme) {
select_first_theme();
GtkTreeIter iter;

1720
src/tint2conf/po/bs.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1720
src/tint2conf/po/hr.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
Updating pot file:
find .. -name '*.c' | xargs xgettext --keyword=_ --language=C --output=updated.pot -
Followed by manual editing of updated.pot to make sure the header is OK. Then:
cat updated.pot > tint2conf.pot && rm -f updated.pot
Then update the po files:
for f in *.po ; do lang=$(basename $f .po); echo $lang ; msgmerge -i -o $lang.pox $lang.po tint2conf.pot ; cat ${lang}.pox > ${lang}.po ; rm ${lang}.pox ; done

1719
src/tint2conf/po/sr.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
#include "../launcher/apps-common.h"
#include "../launcher/icon-theme-common.h"
#include "../util/common.h"
#include "strnatcmp.h"
#define ROW_SPACING 10
#define COL_SPACING 8
@@ -1769,23 +1770,84 @@ void load_desktop_file(const char *file, gboolean selected)
free_desktop_entry(&entry);
}
void load_desktop_files(const gchar *path)
void populate_from_entries(GList *entries, gboolean selected)
{
GList *l;
for (l = entries; l; l = l->next) {
DesktopEntry *entry = (DesktopEntry *)l->data;
GdkPixbuf *pixbuf = load_icon(entry->icon);
GtkTreeIter iter;
gtk_list_store_append(selected ? launcher_apps : all_apps, &iter);
gtk_list_store_set(selected ? launcher_apps :all_apps, &iter,
appsColIcon, pixbuf,
appsColText, g_strdup(entry->name),
appsColPath, g_strdup(entry->path),
appsColIconName, g_strdup(entry->icon),
-1);
if (pixbuf)
g_object_unref(pixbuf);
}
}
static gint compare_entries(gconstpointer a, gconstpointer b)
{
return strnatcasecmp(((DesktopEntry*)a)->name, ((DesktopEntry*)b)->name);
}
void load_desktop_entry(const char *file, GList **entries)
{
DesktopEntry *entry = calloc(1, sizeof(DesktopEntry));
if (!read_desktop_file(file, entry))
printf("Could not load %s\n", file);
if (!entry->name)
entry->name = strdup(file);
if (!entry->icon)
entry->icon = strdup("");
*entries = g_list_append(*entries, entry);
}
static gint compare_strings(gconstpointer a, gconstpointer b)
{
return strnatcasecmp((const char*)a, (const char*)b);
}
void load_desktop_entries(const char *path, GList **entries)
{
GList *subdirs = NULL;
GList *files = NULL;
GDir *d = g_dir_open(path, 0, NULL);
if (!d)
return;
const gchar *name;
while ((name = g_dir_read_name(d))) {
gchar *file = g_build_filename(path, name, NULL);
if (!g_file_test(file, G_FILE_TEST_IS_DIR) &&
g_str_has_suffix(file, ".desktop")) {
load_desktop_file(file, FALSE);
} else if (g_file_test(file, G_FILE_TEST_IS_DIR)) {
load_desktop_files(file);
if (d) {
const gchar *name;
while ((name = g_dir_read_name(d))) {
gchar *file = g_build_filename(path, name, NULL);
if (!g_file_test(file, G_FILE_TEST_IS_DIR) && g_str_has_suffix(file, ".desktop")) {
files = g_list_append(files, file);
} else if (g_file_test(file, G_FILE_TEST_IS_DIR)) {
subdirs = g_list_append(subdirs, file);
} else {
g_free(file);
}
}
g_dir_close(d);
}
subdirs = g_list_sort(subdirs, compare_strings);
GList *l;
for (l = subdirs; l; l = g_list_next(l)) {
gchar *dir = (gchar *)l->data;
load_desktop_entries(dir, entries);
g_free(dir);
}
g_list_free(subdirs);
files = g_list_sort(files, compare_strings);
for (l = files; l; l = g_list_next(l)) {
gchar *file = (gchar *)l->data;
load_desktop_entry(file, entries);
g_free(file);
}
g_dir_close(d);
g_list_free(files);
}
void load_theme_file(const char *file_name, const char *theme)
@@ -2215,10 +2277,20 @@ void create_launcher(GtkWidget *parent)
fprintf(stderr, "Icon themes loaded\n");
fprintf(stderr, "Loading .desktop files\n");
load_desktop_files("/usr/share/applications");
load_desktop_files("/usr/local/share/applications");
GList *entries = NULL;
load_desktop_entries("/usr/share/applications", &entries);
load_desktop_entries("/usr/local/share/applications", &entries);
gchar *path = g_build_filename(g_get_home_dir(), ".local/share/applications", NULL);
load_desktop_files(path);
load_desktop_entries(path, &entries);
entries = g_list_sort(entries, compare_entries);
populate_from_entries(entries, FALSE);
GList *l;
for (l = entries; l; l = l->next) {
free_desktop_entry((DesktopEntry*)l->data);
}
g_list_free(entries);
g_free(path);
icon_theme_changed();

View File

@@ -511,7 +511,7 @@ void config_write_launcher(FILE *fp)
g_strstrip(dir);
if (strlen(dir) > 0) {
char *contracted = contract_tilde(dir);
fprintf(fp, "launcher_item_app = %s\n", contracted);
fprintf(fp, "launcher_apps_dir = %s\n", contracted);
free(contracted);
}
}
@@ -1010,13 +1010,13 @@ void add_entry(char *key, char *value)
}
else if (strcmp(key, "task_align") == 0) {
if (strcmp(value, "left") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_alignment), 0);
else if (strcmp(value, "center") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 1);
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_alignment), 1);
else if (strcmp(value, "right") == 0)
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 2);
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_alignment), 2);
else
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_alignment), 0);
}
else if (strcmp(key, "taskbar_padding") == 0) {
extract_values(value, &value1, &value2, &value3);

View File

@@ -19,6 +19,7 @@
#include "main.h"
#include "strnatcmp.h"
#include "theme_view.h"
// The data columns that we export via the tree model interface
@@ -27,6 +28,11 @@ GtkListStore *g_store;
int g_width_list, g_height_list;
GtkCellRenderer *g_renderer;
gint theme_name_compare(GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
gpointer user_data);
GtkWidget *create_view()
{
GtkTreeViewColumn *col;
@@ -69,21 +75,50 @@ GtkWidget *create_view()
GtkTreeSortable *sortable;
sortable = GTK_TREE_SORTABLE(g_store);
gtk_tree_sortable_set_sort_column_id(sortable, COL_THEME_FILE, GTK_SORT_ASCENDING);
gtk_tree_sortable_set_sort_func(sortable, COL_THEME_FILE, theme_name_compare, NULL, NULL);
return view;
}
gint theme_name_compare(GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
gpointer user_data)
{
gchar *path_a, *path_b;
gtk_tree_model_get(model, a, COL_THEME_FILE, &path_a, -1);
gtk_tree_model_get(model, b, COL_THEME_FILE, &path_b, -1);
gchar *name_a = path_a;
gchar *p;
for (p = name_a; *p; p++) {
if (*p == '/')
name_a = p + 1;
}
gchar *name_b = path_b;
for (p = name_b; *p; p++) {
if (*p == '/')
name_b = p + 1;
}
if (g_str_equal(name_a, name_b))
return 0;
if (g_str_equal(name_a, "tint2rc"))
return -1;
if (g_str_equal(name_b, "tint2rc"))
return 1;
gint result = strnatcasecmp(name_a, name_b);
g_free(path_a);
g_free(path_b);
return result;
}
void custom_list_append(const gchar *name)
void custom_list_append(const gchar *path)
{
GtkTreeIter iter;
gtk_list_store_append(g_store, &iter);
gtk_list_store_set(g_store, &iter, COL_THEME_FILE, name, -1);
gtk_list_store_set(g_store, &iter, COL_THEME_FILE, path, -1);
gchar *b, *n;
b = strrchr(name, '/');
n = g_strdup(b+1);
gtk_list_store_set(g_store, &iter, COL_THEME_NAME, n, -1);
gchar *name = g_strdup(strrchr(path, '/') + 1);
gtk_list_store_set(g_store, &iter, COL_THEME_NAME, name, -1);
}

View File

@@ -10,7 +10,7 @@ enum { COL_THEME_FILE = 0, COL_THEME_NAME, COL_SNAPSHOT, NB_COL, };
GtkWidget *create_view();
void custom_list_append(const gchar *name);
void custom_list_append(const gchar *path);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,9 @@
void copy_file(const char *pathSrc, const char *pathDest)
{
if (g_str_equal(pathSrc, pathDest))
return;
FILE *fileSrc, *fileDest;
char buffer[100];
int nb;
@@ -117,13 +120,13 @@ char *contract_tilde(char *s)
if (!home)
return strdup(s);
char *home_slash = calloc(strlen(home) + 1, 1);
char *home_slash = calloc(strlen(home) + 2, 1);
strcat(home_slash, home);
strcat(home_slash, "/");
if ((strcmp(s, home) == 0 ||
strstr(s, home_slash) == s)) {
char *result = calloc(strlen(s) - strlen(home) + 1, 1);
char *result = calloc(strlen(s) - strlen(home) + 2, 1);
strcat(result, "~");
strcat(result, s + strlen(home));
free(home_slash);
@@ -362,6 +365,42 @@ void createHeuristicMask(DATA32* data, int w, int h)
}
}
int pixelEmpty(DATA32 argb)
{
DATA32 a = (argb >> 24) & 0xff;
if (a == 0)
return 1;
DATA32 rgb = argb & 0xffFFff;
return rgb == 0;
}
int imageEmpty(DATA32* data, int w, int h)
{
unsigned int x, y;
if (w > 0 && h > 0) {
x = w / 2;
y = h / 2;
if (!pixelEmpty(data[y * w + x])) {
//fprintf(stderr, "Non-empty pixel: [%u, %u] = %x\n", x, y, data[y * w + x]);
return 0;
}
}
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
if (!pixelEmpty(data[y * w + x])) {
//fprintf(stderr, "Non-empty pixel: [%u, %u] = %x\n", x, y, data[y * w + x]);
return 0;
}
}
}
//fprintf(stderr, "All pixels are empty\n");
return 1;
}
void render_image(Drawable d, int x, int y)
{

View File

@@ -12,6 +12,12 @@
#include <pango/pangocairo.h>
#include "area.h"
#define GREEN "\033[1;32m"
#define YELLOW "\033[1;33m"
#define RED "\033[31m"
#define BLUE "\033[1;34m"
#define RESET "\033[0m"
/*
void fxfree(void** ptr){
if(*ptr){
@@ -62,6 +68,7 @@ void extract_values (const char *value, char **value1, char **value2, char **val
// alpha from 0 to 100, satur from 0 to 1, bright from 0 to 1.
void adjust_asb(DATA32 *data, int w, int h, int alpha, float satur, float bright);
void createHeuristicMask(DATA32* data, int w, int h);
int imageEmpty(DATA32* data, int w, int h);
void render_image(Drawable d, int x, int y);

View File

@@ -393,8 +393,13 @@ void callback_multi_timeout(void* arg)
timeout* t = it->data;
if (++t->multi_timeout->current_count >= t->multi_timeout->count_to_expiration) {
t->_callback(t->arg);
t->multi_timeout->current_count = 0;
t->timeout_expires = add_msec_to_timespec(cur_time, t->interval_msec);
if (multi_timeouts && g_hash_table_lookup(multi_timeouts, t)) {
// Timer still exists
t->multi_timeout->current_count = 0;
t->timeout_expires = add_msec_to_timespec(cur_time, t->interval_msec);
} else {
return;
}
}
it = it->next;
}
@@ -445,3 +450,16 @@ void stop_multi_timeout(timeout* t)
}
free(mth);
}
double profiling_get_time_old_time = 0;
double profiling_get_time()
{
struct timespec cur_time;
clock_gettime(CLOCK_MONOTONIC, &cur_time);
double t = cur_time.tv_sec + cur_time.tv_nsec * 1.0e-9;
if (profiling_get_time_old_time == 0)
profiling_get_time_old_time = t;
double delta = t - profiling_get_time_old_time;
profiling_get_time_old_time = t;
return delta;
}

View File

@@ -73,4 +73,9 @@ gint compare_timespecs(const struct timespec* t1, const struct timespec* t2);
struct timespec add_msec_to_timespec(struct timespec ts, int msec);
/** Returns the time difference in seconds between the current time and the last time this function was called.
* At the first call returns zero.
**/
double profiling_get_time();
#endif // TIMER_H

4
tint2.config Normal file
View File

@@ -0,0 +1,4 @@
// ADD PREDEFINED MACROS HERE!
#define HAVE_RSVG 1
#define HAVE_SN 1
#define ENABLE_BATTERY 1

1
tint2.creator Normal file
View File

@@ -0,0 +1 @@
[General]

View File

@@ -2,7 +2,7 @@
Type=Application
Encoding=UTF-8
Name=Tint2 panel
Name[am]=ፓነል tint2
Name[am]=ፓነል tint2
Name[ar]=الشريط tint2
Name[ast]=Panel tint2
Name[be]=Панэль tint2
@@ -12,7 +12,7 @@ Name[da]=Panel tint2
Name[de]=Leiste tint2
Name[dz]=པེ་ནཱལ། tint2
Name[el]=Ταμπλό tint2
Name[en_GB]=Panel tint2
Name[en]=Tint2 panel
Name[eo]=Panelo tint2
Name[es]=Panel tint2
Name[et]=Ääreriba tint2
@@ -36,7 +36,6 @@ Name[nn]=Panel tint2
Name[pa]=ਪੈਨਲ tint2
Name[pl]=Panel tint2
Name[pt]=Painel tint2
Name[pt_BR]=Painel tint2
Name[ro]=Panou tint2
Name[ru]=Панель tint2
Name[si]=පුවරුව tint2
@@ -48,12 +47,10 @@ Name[tr]=Panel tint2
Name[ug]=panel tint2
Name[uk]=Панель tint2
Name[ur]=پینل tint2
Name[ur_PK]=پینل tint2
Name[vi]=Panel tint2
Name[zh_CN]=面板 tint2
Name[zh_TW]=面板 tint2
Name[zh]=面板 tint2
Comment=Lightweight panel
Comment[fr_FR]=Panel léger
Comment[fr]=Panel léger
Comment[pl]=Lekki panel
Exec=tint2
Icon=taskbar

153
tint2.files Normal file
View File

@@ -0,0 +1,153 @@
doc/tint2.1
sample/icon_and_text_1.tint2rc
sample/icon_and_text_2.tint2rc
sample/icon_and_text_3.tint2rc
sample/icon_and_text_4.tint2rc
sample/icon_only_1.tint2rc
sample/icon_only_2.tint2rc
sample/icon_only_3.tint2rc
sample/icon_only_4.tint2rc
sample/icon_only_6.tint2rc
sample/icon_only_7.tint2rc
sample/text_only_1.tint2rc
sample/text_only_2.tint2rc
sample/text_only_3.tint2rc
sample/text_only_4.tint2rc
sample/text_only_5.tint2rc
sample/text_only_6.tint2rc
sample/tint2rc
src/battery/battery.c
src/battery/battery.h
src/clock/clock.c
src/clock/clock.h
src/execplugin/execplugin.c
src/execplugin/execplugin.h
src/launcher/launcher.c
src/launcher/launcher.h
src/launcher/xsettings-client.c
src/launcher/xsettings-client.h
src/launcher/xsettings-common.c
src/launcher/xsettings-common.h
src/sysmon/sysmon.c
src/sysmon/sysmon.h
src/systray/systraybar.c
src/systray/systraybar.h
src/taskbar/task.c
src/taskbar/task.h
src/taskbar/taskbar.c
src/taskbar/taskbar.h
src/taskbar/taskbarname.c
src/taskbar/taskbarname.h
src/tint2conf/CMakeLists.txt
src/tint2conf/main.c
src/tint2conf/main.h
src/tint2conf/properties.c
src/tint2conf/properties.h
src/tint2conf/properties_rw.c
src/tint2conf/properties_rw.h
src/tint2conf/taskbar.svg
src/tint2conf/theme_view.c
src/tint2conf/theme_view.h
src/tint2conf/tint2conf.desktop
src/tint2conf/tintwizard.py
src/tooltip/tooltip.c
src/tooltip/tooltip.h
src/util/area.c
src/util/area.h
src/util/blur.c
src/util/blur.h
src/util/common.c
src/util/common.h
src/util/timer.c
src/util/timer.h
src/util/window.c
src/util/window.h
src/config.c
src/config.h
src/panel.c
src/panel.h
src/server.c
src/server.h
src/tint.c
AUTHORS
ChangeLog
CMakeLists.txt
COPYING
default_icon.png
get_svnrev.sh
INSTALL.txt
make_release.sh
README
README.source
src/launcher/apps-common.c
src/launcher/apps-common.h
src/launcher/icon-theme-common.c
src/launcher/icon-theme-common.h
src/util/strnatcmp.c
src/util/strnatcmp.h
get_version.sh
src/battery/battery.c
src/battery/battery.h
src/clock/clock.c
src/clock/clock.h
src/launcher/apps-common.c
src/launcher/apps-common.h
src/launcher/icon-theme-common.c
src/launcher/icon-theme-common.h
src/launcher/launcher.c
src/launcher/launcher.h
src/launcher/xsettings-client.c
src/launcher/xsettings-client.h
src/launcher/xsettings-common.c
src/launcher/xsettings-common.h
src/systray/systraybar.c
src/systray/systraybar.h
src/taskbar/task.c
src/taskbar/task.h
src/taskbar/taskbar.c
src/taskbar/taskbar.h
src/taskbar/taskbarname.c
src/taskbar/taskbarname.h
src/tint2conf/CMakeLists.txt
src/tint2conf/main.c
src/tint2conf/main.h
src/tint2conf/properties.c
src/tint2conf/properties.h
src/tint2conf/properties_rw.c
src/tint2conf/properties_rw.h
src/tint2conf/theme_view.c
src/tint2conf/theme_view.h
src/tint2conf/tint2conf.desktop
src/tint2conf/tint2conf.svg
src/tint2conf/tintwizard.py
src/tooltip/tooltip.c
src/tooltip/tooltip.h
src/util/area.c
src/util/area.h
src/util/common.c
src/util/common.h
src/util/strnatcmp.c
src/util/strnatcmp.h
src/util/timer.c
src/util/timer.h
src/util/window.c
src/util/window.h
src/config.c
src/config.h
src/panel.c
src/panel.h
src/server.c
src/server.h
src/tint.c
po/CMakeLists.txt
po/LINGUAS
po/POTFILES.in
src/tint2conf/po/CMakeLists.txt
src/tint2conf/po/CMakeLists.txt
src/tint2conf/po/fr.po
src/tint2conf/po/tint2conf.pot
src/tint2conf/po/pl.po
src/tint2conf/po/tint2conf.pot
src/freespace/freespace.c
src/freespace/freespace.h
src/tint2conf/po/readme.txt

22
tint2.includes Normal file
View File

@@ -0,0 +1,22 @@
.
./src
./src/battery
./src/clock
./src/execplugin
./src/launcher
./src/sysmon
./src/systray
./src/taskbar
./src/tint2conf
./src/tooltip
./src/util
/usr/include
/usr/include/gtk-2.0
/usr/include/glib-2.0
/usr/include/gdk-pixbuf-2.0
/usr/include/cairo
/usr/include/pango-1.0
/usr/include/startup-notification-1.0
po
src/tint2conf/po
src/freespace