Compare commits
104 Commits
debian-pro
...
v0.12-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d7dfc082d | ||
|
|
aecd658d2b | ||
|
|
89e2057a8e | ||
|
|
2ecb1c4ef4 | ||
|
|
dff7355f3b | ||
|
|
5d11fe5cc1 | ||
|
|
233157930b | ||
|
|
ae76f82ee0 | ||
|
|
00930b217d | ||
|
|
0e322b3563 | ||
|
|
2745eefec7 | ||
|
|
2357e31965 | ||
|
|
3467a44761 | ||
|
|
f6e4820fdb | ||
|
|
0070fd6b34 | ||
|
|
665ce3e5ff | ||
|
|
aed6caca92 | ||
|
|
f762a975b1 | ||
|
|
e6112a7921 | ||
|
|
53c8ee5e9e | ||
|
|
c2f661eba6 | ||
|
|
ad01f1a481 | ||
|
|
60b56599cb | ||
|
|
b4f15db397 | ||
|
|
6ba25fa945 | ||
|
|
aa9e1afdf2 | ||
|
|
167bb31084 | ||
|
|
b9f8bf30f7 | ||
|
|
64c1fc03f9 | ||
|
|
b78c854700 | ||
|
|
eef4987b0b | ||
|
|
66cae4bb7c | ||
|
|
778b9f0ebf | ||
|
|
f88b887074 | ||
|
|
45d6463315 | ||
|
|
d95fbdc2b2 | ||
|
|
d7e48187b1 | ||
|
|
7d70189bee | ||
|
|
eb1244a415 | ||
|
|
e49e05ad69 | ||
|
|
75f8a07ca4 | ||
|
|
af003d0e19 | ||
|
|
321ccc0794 | ||
|
|
cab31cb726 | ||
|
|
40d8d05be7 | ||
|
|
5e0e2c4af9 | ||
|
|
e539c6536f | ||
|
|
67d5bfcfce | ||
|
|
82fe74743c | ||
|
|
5376e09963 | ||
|
|
1a41159142 | ||
|
|
e113080a0e | ||
|
|
5faf063f96 | ||
|
|
c900bc24b2 | ||
|
|
a2de8d6e53 | ||
|
|
f6b78ad094 | ||
|
|
83b6d1ac72 | ||
|
|
f5a18cc4f4 | ||
|
|
c583ea42eb | ||
|
|
4c16f97e73 | ||
|
|
b8a4766773 | ||
|
|
a8600a598b | ||
|
|
da7efb27a9 | ||
|
|
ba40b0752f | ||
|
|
0d1b78d808 | ||
|
|
32db15ae50 | ||
|
|
bab686d8c4 | ||
|
|
51fe905b47 | ||
|
|
a11becfb2e | ||
|
|
f4af2a352a | ||
|
|
7b698e1fe1 | ||
|
|
f527a2639b | ||
|
|
5bd4bcf727 | ||
|
|
89c8338067 | ||
|
|
3f42584fbd | ||
|
|
1272ce4bb9 | ||
|
|
f0e2e72efc | ||
|
|
c392cdf257 | ||
|
|
856385d5c0 | ||
|
|
b70e6b500e | ||
|
|
5a789c2d7f | ||
|
|
0fa10d83b9 | ||
|
|
28d726626d | ||
|
|
45cc690167 | ||
|
|
4e76c2bb5d | ||
|
|
88e0e4fed8 | ||
|
|
d584d04691 | ||
|
|
1a3ba21245 | ||
|
|
ec80e09b0b | ||
|
|
de539e218a | ||
|
|
1cb0c16ff4 | ||
|
|
2432a2ed51 | ||
|
|
9a1ec1884f | ||
|
|
b6efa12bef | ||
|
|
c59f239999 | ||
|
|
9ac902b62b | ||
|
|
42469038a8 | ||
|
|
de5045d88e | ||
|
|
54154e8298 | ||
|
|
364d0cf703 | ||
|
|
f70415d7db | ||
|
|
45a2156c12 | ||
|
|
fc4b29631f | ||
|
|
dc137ef1a6 |
5
AUTHORS
5
AUTHORS
@@ -4,6 +4,7 @@ tint2 is developped by :
|
|||||||
- Andreas Fink <andreas.fink85@googlemail.com>
|
- Andreas Fink <andreas.fink85@googlemail.com>
|
||||||
- Euan Freeman <euan04@gmail.com> (tintwizard)
|
- Euan Freeman <euan04@gmail.com> (tintwizard)
|
||||||
- Christian Ruppert <Spooky85@gmail.com> (autotools build system)
|
- Christian Ruppert <Spooky85@gmail.com> (autotools build system)
|
||||||
|
- Ovidiu M <mrovi9000 at gmail.com> : launcher, bug fixes
|
||||||
|
|
||||||
tint2 is based on ttm source code (http://code.google.com/p/ttm/)
|
tint2 is based on ttm source code (http://code.google.com/p/ttm/)
|
||||||
- 2007-2008 Pål Staurland <staura@gmail.com>
|
- 2007-2008 Pål Staurland <staura@gmail.com>
|
||||||
@@ -16,5 +17,9 @@ Contributors:
|
|||||||
James Buren <ryuo@frugalware.org> : Frugalware package
|
James Buren <ryuo@frugalware.org> : Frugalware package
|
||||||
Pierre-Emmanuel Andre <pea@raveland.org> : openbsd port
|
Pierre-Emmanuel Andre <pea@raveland.org> : openbsd port
|
||||||
Redroar : arch package
|
Redroar : arch package
|
||||||
|
Rene Garcia <garciamx@gmail.com> : launcher SVG support
|
||||||
|
Marcelo Vianna : taskbar sorting
|
||||||
|
Xico Atelo : startup notifications
|
||||||
|
Craig Oakes : WM flags, issue tracker organization
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
project( tint2 )
|
project( tint2 )
|
||||||
cmake_minimum_required( VERSION 2.6 )
|
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_RSVG "Rsvg support (launcher only)" ON )
|
||||||
|
option( ENABLE_SN "Startup notification support" ON )
|
||||||
|
option( ENABLE_ASAN "Build tint2 with AddressSanitizer" OFF )
|
||||||
|
|
||||||
include( FindPkgConfig )
|
include( FindPkgConfig )
|
||||||
include( CheckLibraryExists )
|
include( CheckLibraryExists )
|
||||||
pkg_check_modules( X11 REQUIRED x11 xcomposite xdamage xinerama xrender xrandr>=1.3 )
|
pkg_check_modules( X11 REQUIRED x11 xcomposite xdamage xinerama xrender xrandr>=1.3 )
|
||||||
@@ -10,18 +17,20 @@ pkg_check_modules( CAIRO REQUIRED cairo )
|
|||||||
pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
|
pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
|
||||||
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
||||||
pkg_check_modules( IMLIB2 REQUIRED imlib2>=1.4.2 )
|
pkg_check_modules( IMLIB2 REQUIRED imlib2>=1.4.2 )
|
||||||
|
pkg_check_modules( RSVG librsvg-2.0>=2.14.0 )
|
||||||
pkg_check_modules( SN libstartup-notification-1.0>=0.12 )
|
pkg_check_modules( SN libstartup-notification-1.0>=0.12 )
|
||||||
|
|
||||||
find_library( RT_LIBRARY rt )
|
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 )
|
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 http://code.google.com/p/tint2/wiki/Install" )
|
message( FATAL_ERROR "Not all dependencies fulfilled. See https://code.google.com/p/tint2/wiki/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 )
|
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}" )
|
string( REPLACE ";" " " FLAGS_REPLACED "${IMLIB2_LDFLAGS}" )
|
||||||
set( CMAKE_REQUIRED_FLAGS "${FLAGS_REPLACED}" )
|
set( CMAKE_REQUIRED_FLAGS "${FLAGS_REPLACED}" )
|
||||||
check_library_exists( "${IMLIB2_LIBRARIES}" "imlib_context_set_display" "${IMLIB2_LIBRARY_DIRS}" IMLIB_BUILD_WITH_X )
|
check_library_exists( "${IMLIB2_LIBRARIES}" "imlib_context_set_display" "${IMLIB2_LIBRARY_DIRS}" IMLIB_BUILD_WITH_X )
|
||||||
if( NOT IMLIB_BUILD_WITH_X )
|
if( NOT IMLIB_BUILD_WITH_X )
|
||||||
message( FATAL_ERROR "Imlib is not build with x support" )
|
message( FATAL_ERROR "Imlib is not built with X support" )
|
||||||
endif( NOT IMLIB_BUILD_WITH_X )
|
endif( NOT IMLIB_BUILD_WITH_X )
|
||||||
|
|
||||||
include_directories( ${PROJECT_BINARY_DIR}
|
include_directories( ${PROJECT_BINARY_DIR}
|
||||||
@@ -40,7 +49,8 @@ include_directories( ${PROJECT_BINARY_DIR}
|
|||||||
${GLIB2_INCLUDE_DIRS}
|
${GLIB2_INCLUDE_DIRS}
|
||||||
${GOBJECT2_INCLUDE_DIRS}
|
${GOBJECT2_INCLUDE_DIRS}
|
||||||
${IMLIB2_INCLUDE_DIRS}
|
${IMLIB2_INCLUDE_DIRS}
|
||||||
${SN_INCLUDE_DIRS} )
|
${RSVG_INCLUDE_DIRS}
|
||||||
|
${SN_INCLUDE_DIRS} )
|
||||||
|
|
||||||
set( SOURCES src/config.c
|
set( SOURCES src/config.c
|
||||||
src/panel.c
|
src/panel.c
|
||||||
@@ -49,6 +59,8 @@ set( SOURCES src/config.c
|
|||||||
src/clock/clock.c
|
src/clock/clock.c
|
||||||
src/systray/systraybar.c
|
src/systray/systraybar.c
|
||||||
src/launcher/launcher.c
|
src/launcher/launcher.c
|
||||||
|
src/launcher/apps-common.c
|
||||||
|
src/launcher/icon-theme-common.c
|
||||||
src/launcher/xsettings-client.c
|
src/launcher/xsettings-client.c
|
||||||
src/launcher/xsettings-common.c
|
src/launcher/xsettings-common.c
|
||||||
src/taskbar/task.c
|
src/taskbar/task.c
|
||||||
@@ -57,28 +69,30 @@ set( SOURCES src/config.c
|
|||||||
src/tooltip/tooltip.c
|
src/tooltip/tooltip.c
|
||||||
src/util/area.c
|
src/util/area.c
|
||||||
src/util/common.c
|
src/util/common.c
|
||||||
|
src/util/strnatcmp.c
|
||||||
src/util/timer.c
|
src/util/timer.c
|
||||||
src/util/window.c )
|
src/util/window.c )
|
||||||
|
|
||||||
option( ENABLE_BATTERY "Enable battery status plugin" ON )
|
|
||||||
option( ENABLE_TINT2CONF "Enable tint2conf build, a GTK+2 theme switcher for tint2" ON )
|
|
||||||
option( ENABLE_EXAMPLES "Install additional tin2rc examples" OFF )
|
|
||||||
option( ENABLE_SN "Startup notification support" ON )
|
|
||||||
if( ENABLE_SN )
|
|
||||||
if( SN_FOUND )
|
|
||||||
add_definitions( -DHAVE_SN -DSN_API_NOT_YET_FROZEN )
|
|
||||||
endif( SN_FOUND )
|
|
||||||
endif( ENABLE_SN)
|
|
||||||
|
|
||||||
if( ENABLE_BATTERY )
|
if( ENABLE_BATTERY )
|
||||||
set( SOURCES ${SOURCES} src/battery/battery.c )
|
set( SOURCES ${SOURCES} src/battery/battery.c )
|
||||||
add_definitions( -DENABLE_BATTERY )
|
add_definitions( -DENABLE_BATTERY )
|
||||||
endif( ENABLE_BATTERY )
|
endif( ENABLE_BATTERY )
|
||||||
|
|
||||||
set( MANDIR share/man CACHE PATH "Directory for man pages" )
|
if( ENABLE_RSVG )
|
||||||
set( DATADIR share CACHE PATH "Directory for shared data" )
|
if( RSVG_FOUND )
|
||||||
set( SYSCONFDIR /etc CACHE PATH "Directory for configuration files" )
|
add_definitions( -DHAVE_RSVG )
|
||||||
set( DOCDIR share/doc/tint2 CACHE PATH "Directory for documentation files" )
|
else()
|
||||||
|
message( FATAL_ERROR "SVG support enabled yet dependency not fulfilled: librsvg-2.0" )
|
||||||
|
endif( RSVG_FOUND )
|
||||||
|
endif( ENABLE_RSVG )
|
||||||
|
|
||||||
|
if( ENABLE_SN )
|
||||||
|
if( SN_FOUND )
|
||||||
|
add_definitions( -DHAVE_SN -DSN_API_NOT_YET_FROZEN )
|
||||||
|
else()
|
||||||
|
message( FATAL_ERROR "Startup notification support enabled yet dependency not fulfilled: libstartup-notification-1.0" )
|
||||||
|
endif( SN_FOUND )
|
||||||
|
endif( ENABLE_SN)
|
||||||
|
|
||||||
if( ENABLE_TINT2CONF )
|
if( ENABLE_TINT2CONF )
|
||||||
add_definitions( -DHAVE_VERSION_H )
|
add_definitions( -DHAVE_VERSION_H )
|
||||||
@@ -86,7 +100,20 @@ if( ENABLE_TINT2CONF )
|
|||||||
add_dependencies( tint2conf version )
|
add_dependencies( tint2conf version )
|
||||||
endif( ENABLE_TINT2CONF )
|
endif( ENABLE_TINT2CONF )
|
||||||
|
|
||||||
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_svnrev.sh" "\"${PROJECT_SOURCE_DIR}\"" )
|
if( ENABLE_ASAN )
|
||||||
|
SET(ASAN_C_FLAGS " -O0 -g3 -gdwarf-2 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic ")
|
||||||
|
SET(ASAN_L_FLAGS " -O0 -g3 -gdwarf-2 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic ")
|
||||||
|
else()
|
||||||
|
SET(ASAN_C_FLAGS "")
|
||||||
|
SET(ASAN_L_FLAGS "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set( MANDIR share/man CACHE PATH "Directory for man pages" )
|
||||||
|
set( DATADIR share CACHE PATH "Directory for shared data" )
|
||||||
|
set( SYSCONFDIR /etc CACHE PATH "Directory for configuration files" )
|
||||||
|
set( DOCDIR share/doc/tint2 CACHE PATH "Directory for documentation files" )
|
||||||
|
|
||||||
|
add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" "\"${PROJECT_SOURCE_DIR}\"" )
|
||||||
|
|
||||||
link_directories( ${X11_LIBRARY_DIRS}
|
link_directories( ${X11_LIBRARY_DIRS}
|
||||||
${PANGOCAIRO_LIBRARY_DIRS}
|
${PANGOCAIRO_LIBRARY_DIRS}
|
||||||
@@ -95,7 +122,8 @@ link_directories( ${X11_LIBRARY_DIRS}
|
|||||||
${GLIB2_LIBRARY_DIRS}
|
${GLIB2_LIBRARY_DIRS}
|
||||||
${GOBJECT2_LIBRARY_DIRS}
|
${GOBJECT2_LIBRARY_DIRS}
|
||||||
${IMLIB2_LIBRARY_DIRS}
|
${IMLIB2_LIBRARY_DIRS}
|
||||||
${SN_LIBRARY_DIRS} )
|
${RSVG_LIBRARY_DIRS}
|
||||||
|
${SN_LIBRARY_DIRS} )
|
||||||
add_executable(tint2 ${SOURCES})
|
add_executable(tint2 ${SOURCES})
|
||||||
target_link_libraries( tint2 ${X11_LIBRARIES}
|
target_link_libraries( tint2 ${X11_LIBRARIES}
|
||||||
${PANGOCAIRO_LIBRARIES}
|
${PANGOCAIRO_LIBRARIES}
|
||||||
@@ -104,14 +132,17 @@ target_link_libraries( tint2 ${X11_LIBRARIES}
|
|||||||
${GLIB2_LIBRARIES}
|
${GLIB2_LIBRARIES}
|
||||||
${GOBJECT2_LIBRARIES}
|
${GOBJECT2_LIBRARIES}
|
||||||
${IMLIB2_LIBRARIES}
|
${IMLIB2_LIBRARIES}
|
||||||
${SN_LIBRARIES} )
|
${RSVG_LIBRARIES}
|
||||||
|
${SN_LIBRARIES} )
|
||||||
if( RT_LIBRARY )
|
if( RT_LIBRARY )
|
||||||
target_link_libraries( tint2 ${RT_LIBRARY} )
|
target_link_libraries( tint2 ${RT_LIBRARY} )
|
||||||
endif( RT_LIBRARY )
|
endif( RT_LIBRARY )
|
||||||
|
|
||||||
|
target_link_libraries( tint2 m )
|
||||||
|
|
||||||
add_dependencies( tint2 version )
|
add_dependencies( tint2 version )
|
||||||
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -pthread" )
|
set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -fno-strict-aliasing -pthread ${ASAN_C_FLAGS}" )
|
||||||
set_target_properties(tint2 PROPERTIES LINK_FLAGS "-pthread" )
|
set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS}" )
|
||||||
|
|
||||||
install( TARGETS tint2 DESTINATION bin )
|
install( TARGETS tint2 DESTINATION bin )
|
||||||
install( FILES sample/tint2rc DESTINATION ${SYSCONFDIR}/xdg/tint2 )
|
install( FILES sample/tint2rc DESTINATION ${SYSCONFDIR}/xdg/tint2 )
|
||||||
|
|||||||
51
ChangeLog
51
ChangeLog
@@ -1,3 +1,54 @@
|
|||||||
|
2015-04-25 tint2-0.12-rc1
|
||||||
|
- 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:
|
||||||
|
- Launcher:
|
||||||
|
- The launcher is now considered stable
|
||||||
|
- Enhancement: SVG icon support
|
||||||
|
- Enhancement: more thorough search for icons
|
||||||
|
- Configuration GUI: tint2conf
|
||||||
|
- Experimental, testing/feedback needed
|
||||||
|
- System tray:
|
||||||
|
- Changed rendering method to fix icon corruptions (need user feedback)
|
||||||
|
- Many bugfixes
|
||||||
|
- New config options (see https://gitlab.com/o9000/tint2/wikis/Configure):
|
||||||
|
- Panel:
|
||||||
|
- panel_window_name
|
||||||
|
- panel_items (already released by distros)
|
||||||
|
- disable_transparency
|
||||||
|
- Taskbar:
|
||||||
|
- taskbar_distribute_size
|
||||||
|
- taskbar_hide_different_monitor
|
||||||
|
- taskbar_hide_inactive_tasks
|
||||||
|
- taskbar_sort_order
|
||||||
|
- taskbar_name (already released by distros)
|
||||||
|
- Launcher:
|
||||||
|
- launcher* (already released by distros)
|
||||||
|
- launcher_apps_dir (previously patched in by some distros)
|
||||||
|
- startup_notifications
|
||||||
|
- System tray:
|
||||||
|
- systray_monitor
|
||||||
|
- Config options with changed behavior:
|
||||||
|
- Panel:
|
||||||
|
- panel_dock: previously, 'panel_dock = 1' was actually not placing the panel into the dock. This option now
|
||||||
|
functions correctly. Due to the fact that OpenBox forcefully draws a border around dock windows, you might want to
|
||||||
|
set it to zero (or change the border color/style to match tint2). If you set it to zero, make sure you do not have
|
||||||
|
reserved space at the edge of the screen in the OpenBox config.
|
||||||
|
Reason for change: issues 257, 394, 461, 465, 481.
|
||||||
|
- font_shadow: shadows are thicker and softer, and are now applied to all text elements, not just the taskbar.
|
||||||
|
Reason for change: legibility improved for transparent panels.
|
||||||
|
- Launcher:
|
||||||
|
- launcher_icon_theme: previously, this parameter had a lower priority than the icon theme provided through the
|
||||||
|
XSettings manager; as virtually all DEs provide one, it was useless. Now the parameter has a higher priority.
|
||||||
|
Remove it to respect the XSettings manager settings.
|
||||||
|
Reasons for change:
|
||||||
|
* ability to use a custom icon theme only in tint2
|
||||||
|
* several DEs do not allow selecting the hicolor theme
|
||||||
|
- launcher_item_app: now it expands leading ~ to the path to the user's home directory.
|
||||||
|
- Project hosting:
|
||||||
|
- Migrated from https://code.google.com/p/tint2 to https://gitlab.com/o9000/tint2 and switched from svn to git
|
||||||
|
|
||||||
2010-06-26
|
2010-06-26
|
||||||
- unhide tint2 panel when dragging something
|
- unhide tint2 panel when dragging something
|
||||||
- battery FreeBSD uses the new ACPI API (thx to yamagi.burmeister)
|
- battery FreeBSD uses the new ACPI API (thx to yamagi.burmeister)
|
||||||
|
|||||||
10
README
10
README
@@ -1,10 +0,0 @@
|
|||||||
---------------------------------------------------------
|
|
||||||
execute "tint2"
|
|
||||||
or "tint2 -c path_to_config_file"
|
|
||||||
|
|
||||||
|
|
||||||
check http://code.google.com/p/tint2/
|
|
||||||
for latest release, documentation and sample config file.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
48
README.md
Normal file
48
README.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
### What is tint2?
|
||||||
|
|
||||||
|
tint2 is a simple panel/taskbar made for modern X window managers. It was specifically made for Openbox but it should also work with other window managers (GNOME, KDE, XFCE etc.). It is based on ttm http://code.google.com/p/ttm/.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Panel with taskbar, system tray, clock and launcher icons;
|
||||||
|
* Easy to customize: color/transparency on fonts, icons, borders and backgrounds;
|
||||||
|
* Pager like capability: move tasks between workspaces (virtual desktops), switch between workspaces;
|
||||||
|
* Multi-monitor capability: create one panel per monitor, showing only the tasks from the current monitor;
|
||||||
|
* Customizable mouse events.
|
||||||
|
|
||||||
|
### Goals
|
||||||
|
|
||||||
|
* Be unintrusive and light (in terms of memory, CPU and aesthetic);
|
||||||
|
* Follow the freedesktop.org specifications;
|
||||||
|
* Make certain workflows, such as multi-desktop and multi-monitor, easy to use.
|
||||||
|
|
||||||
|
### I want it!
|
||||||
|
|
||||||
|
* [Install tint2](https://gitlab.com/o9000/tint2/wikis/Install)
|
||||||
|
|
||||||
|
### How do I ...
|
||||||
|
|
||||||
|
* [Install](https://gitlab.com/o9000/tint2/wikis/Install)
|
||||||
|
* [Configure](https://gitlab.com/o9000/tint2/wikis/Configure)
|
||||||
|
* [Add applet not supported by tint2](https://gitlab.com/o9000/tint2/wikis/ThirdPartyApplets)
|
||||||
|
* [Other frequently asked questions](https://gitlab.com/o9000/tint2/wikis/FAQ)
|
||||||
|
* [Debug](https://gitlab.com/o9000/tint2/wikis/Debug)
|
||||||
|
|
||||||
|
### How can I help out?
|
||||||
|
|
||||||
|
* Report bugs and ask questions on the [issue tracker](https://gitlab.com/o9000/tint2/issues);
|
||||||
|
* Contribute to the development by helping us fix bugs and suggesting new features.
|
||||||
|
|
||||||
|
### Links
|
||||||
|
* Home page: https://gitlab.com/o9000/tint2
|
||||||
|
* Git repository: https://gitlab.com/o9000/tint2.git
|
||||||
|
* Documentation: https://gitlab.com/o9000/tint2/wikis/home
|
||||||
|
* Downloads: https://gitlab.com/o9000/tint2-archive/tree/master or https://code.google.com/p/tint2/downloads/list
|
||||||
|
* Old project location (inactive): https://code.google.com/p/tint2
|
||||||
|
|
||||||
|
### Releases
|
||||||
|
* Latest stable release: tint2 0.11 (June 2010)
|
||||||
|
* Next release: planned for mid 2015
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|

|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
FALLBACK=\"0.11-svn\"
|
|
||||||
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
DIR=.
|
|
||||||
else
|
|
||||||
DIR=$1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f version.h ]; then
|
|
||||||
REV_OLD=$(cat version.h | cut -d" " -f3)
|
|
||||||
else
|
|
||||||
REV_OLD=\"\"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -x "$(which svnversion 2>/dev/null)" -a -d "${DIR}/.svn" ] ; then
|
|
||||||
REV=\"$(svnversion -n ${DIR})\"
|
|
||||||
else
|
|
||||||
REV=${FALLBACK}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ${REV_OLD} != ${REV} ]; then
|
|
||||||
echo "Building new version.h"
|
|
||||||
echo "Rev_old: ${REV_OLD} Rev: ${REV}"
|
|
||||||
echo "#define VERSION_STRING ${REV}" > version.h
|
|
||||||
fi
|
|
||||||
35
get_version.sh
Executable file
35
get_version.sh
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
DIRTY=""
|
||||||
|
|
||||||
|
git update-index -q --ignore-submodules --refresh
|
||||||
|
# Disallow unstaged changes in the working tree
|
||||||
|
if ! git diff-files --quiet --ignore-submodules --
|
||||||
|
then
|
||||||
|
if [ "$1" = "--strict" ]
|
||||||
|
then
|
||||||
|
echo >&2 "Error: there are unstaged changes."
|
||||||
|
git diff-files --name-status -r --ignore-submodules -- >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
DIRTY="-dirty"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Disallow uncommitted changes in the index
|
||||||
|
if ! git diff-index --cached --quiet HEAD --ignore-submodules --
|
||||||
|
then
|
||||||
|
if [ "$1" = "--strict" ]
|
||||||
|
then
|
||||||
|
echo >&2 "Error: there are uncommitted changes."
|
||||||
|
git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
DIRTY="-dirty"
|
||||||
|
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
|
||||||
|
|
||||||
|
echo '#define VERSION_STRING "'$VERSION'"' > version.h
|
||||||
|
echo $VERSION
|
||||||
@@ -1,23 +1,45 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# usage: ./make_release.sh RELEASE_VERSION_NUMBER
|
# Usage: ./make_release.sh
|
||||||
|
# Creates a tar.bz2 archive of the current tree.
|
||||||
|
#
|
||||||
|
# To bump the version number for the current commit (make sure you are in HEAD!), run manually:
|
||||||
|
#
|
||||||
|
# git tag -a v0.12 -m 'Version 0.12'
|
||||||
|
#
|
||||||
|
# To generate a release for an older tagged commit, first list the tags with:
|
||||||
|
#
|
||||||
|
# git tags
|
||||||
|
#
|
||||||
|
# then checkout the tagged commit with:
|
||||||
|
#
|
||||||
|
# git checkout tags/v0.1
|
||||||
|
#
|
||||||
|
# Finally, to revert to HEAD:
|
||||||
|
#
|
||||||
|
# git checkout master
|
||||||
|
|
||||||
if [[ $# -ne 1 ]]; then
|
VERSION=$(./get_version.sh --strict)
|
||||||
echo "usage: $0 RELEASE_VERSION_NUMBER"
|
if [ ! $? -eq 0 ]
|
||||||
exit
|
then
|
||||||
|
echo >&2 "Error: get_version.sh failed!"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DIR=tint2-${1}
|
DIR=tint2-$VERSION
|
||||||
echo "Making release ${DIR}"
|
echo "Making release $DIR"
|
||||||
rm -Rf ${DIR}
|
rm -rf $DIR
|
||||||
svn export . ${DIR} > /dev/null
|
|
||||||
|
|
||||||
# delete unneeded files
|
git checkout-index --prefix=$DIR/ -a
|
||||||
rm -f ${DIR}/configure ${DIR}/make_release.sh
|
|
||||||
|
|
||||||
# replace get_svnrev.sh by a simple echo command
|
# Delete unneeded files
|
||||||
echo "echo \"#define VERSION_STRING \\\"${1}\\\"\" > version.h" > ${DIR}/get_svnrev.sh
|
rm -f $DIR/make_release.sh
|
||||||
|
|
||||||
# create tarball and remove the exported directory
|
echo "echo \"#define VERSION_STRING \\\"$VERSION\\\"\" > version.h" > $DIR/get_version.sh
|
||||||
tar -cjf ${DIR}.tar.bz2 ${DIR}
|
|
||||||
rm -Rf ${DIR}
|
# Create tarball and remove the exported directory
|
||||||
|
tar -cjf $DIR.tar.bz2 $DIR
|
||||||
|
rm -rf $DIR
|
||||||
|
|
||||||
|
sha1sum -b $DIR.tar.bz2
|
||||||
|
sha256sum -b $DIR.tar.bz2
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ tooltip_font = sans 10
|
|||||||
tooltip_font_color = #000000 80
|
tooltip_font_color = #000000 80
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -115,4 +116,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ tooltip_font = Sans 10
|
|||||||
tooltip_font_color = #000000 80
|
tooltip_font_color = #000000 80
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = close
|
mouse_middle = close
|
||||||
mouse_right = none
|
mouse_right = none
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -114,4 +115,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ tooltip_font = Sans 9
|
|||||||
tooltip_font_color = #5E5E5E 100
|
tooltip_font_color = #5E5E5E 100
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -120,4 +121,4 @@ battery_font_color = #000000 100
|
|||||||
battery_padding = 1 1
|
battery_padding = 1 1
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ tooltip_font = Sans 12
|
|||||||
tooltip_font_color = #FFFFFF 100
|
tooltip_font_color = #FFFFFF 100
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -120,4 +121,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 1
|
battery_background_id = 1
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ tooltip_font = Sans 8
|
|||||||
tooltip_font_color = #FFFFFF 100
|
tooltip_font_color = #FFFFFF 100
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -134,4 +135,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 2 0
|
battery_padding = 2 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ tooltip_font = sans 10
|
|||||||
tooltip_font_color = #000000 80
|
tooltip_font_color = #000000 80
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -122,4 +123,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ tooltip_font = sans 10
|
|||||||
tooltip_font_color = #000000 80
|
tooltip_font_color = #000000 80
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = none
|
mouse_right = none
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -111,4 +112,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ tooltip_font = Sans 10
|
|||||||
tooltip_font_color = #FFFFFF 80
|
tooltip_font_color = #FFFFFF 80
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -111,4 +112,4 @@ battery_font_color = #FFFFFF 100
|
|||||||
battery_padding = 0 0
|
battery_padding = 0 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ tooltip_font = sans 8
|
|||||||
tooltip_font_color = #000000 89
|
tooltip_font_color = #000000 89
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -122,4 +123,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 4 2
|
battery_padding = 4 2
|
||||||
battery_background_id = 1
|
battery_background_id = 1
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ tooltip_font = Sans 7
|
|||||||
tooltip_font_color = #FFFFFF 100
|
tooltip_font_color = #FFFFFF 100
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -118,4 +119,4 @@ battery_font_color = #FFFFFF 100
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ tooltip_font = Aller 8
|
|||||||
tooltip_font_color = #D3CAAA 33
|
tooltip_font_color = #D3CAAA 33
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -128,4 +129,4 @@ battery_font_color = #D3CAAA 48
|
|||||||
battery_padding = 4 2
|
battery_padding = 4 2
|
||||||
battery_background_id = 4
|
battery_background_id = 4
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ tooltip_font = Aller 8
|
|||||||
tooltip_font_color = #D3CAAA 33
|
tooltip_font_color = #D3CAAA 33
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -128,4 +129,4 @@ battery_font_color = #D3CAAA 48
|
|||||||
battery_padding = 4 2
|
battery_padding = 4 2
|
||||||
battery_background_id = 4
|
battery_background_id = 4
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ tooltip_font = Sans 9
|
|||||||
tooltip_font_color = #FFFFFF 100
|
tooltip_font_color = #FFFFFF 100
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ tooltip_font = Sans 12
|
|||||||
tooltip_font_color = #FFFFFF 100
|
tooltip_font_color = #FFFFFF 100
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ tooltip_font = AvantGardeLTMedium 8
|
|||||||
tooltip_font_color = #434141 100
|
tooltip_font_color = #434141 100
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -112,4 +113,4 @@ battery_font_color = #151515 60
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ tooltip_font = Aller 8
|
|||||||
tooltip_font_color = #D3CAAA 33
|
tooltip_font_color = #D3CAAA 33
|
||||||
|
|
||||||
# Mouse
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
mouse_middle = none
|
mouse_middle = none
|
||||||
mouse_right = close
|
mouse_right = close
|
||||||
mouse_scroll_up = toggle
|
mouse_scroll_up = toggle
|
||||||
@@ -105,4 +106,4 @@ battery_font_color = #FFFFFF 75
|
|||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
115
sample/tint2rc
115
sample/tint2rc
@@ -1,44 +1,67 @@
|
|||||||
# Tint2 config file
|
# Tint2 sample config file
|
||||||
# Generated by tintwizard (http://code.google.com/p/tintwizard/)
|
|
||||||
# For information on manually configuring tint2 see http://code.google.com/p/tint2/wiki/Configure
|
# For information on manually configuring tint2 see http://code.google.com/p/tint2/wiki/Configure
|
||||||
|
|
||||||
# Background definitions
|
# Background definitions
|
||||||
# ID 1
|
# Background 1: panel
|
||||||
rounded = 7
|
rounded = 7
|
||||||
border_width = 2
|
border_width = 1
|
||||||
background_color = #000000 60
|
background_color = #000000 60
|
||||||
border_color = #FFFFFF 16
|
border_color = #FFFFFF 16
|
||||||
|
|
||||||
# ID 2
|
# Background 2: normal/iconified tasks
|
||||||
rounded = 5
|
rounded = 5
|
||||||
border_width = 0
|
border_width = 0
|
||||||
background_color = #FFFFFF 40
|
background_color = #777777 20
|
||||||
border_color = #FFFFFF 48
|
border_color = #777777 30
|
||||||
|
|
||||||
# ID 3
|
# Background 3: active tasks
|
||||||
rounded = 5
|
rounded = 5
|
||||||
border_width = 0
|
border_width = 1
|
||||||
background_color = #FFFFFF 16
|
background_color = #777777 20
|
||||||
border_color = #FFFFFF 68
|
border_color = #ffffff 40
|
||||||
|
|
||||||
|
# Background 4: urgent tasks
|
||||||
|
rounded = 5
|
||||||
|
border_width = 1
|
||||||
|
background_color = #aa4400 100
|
||||||
|
border_color = #aa7733 100
|
||||||
|
|
||||||
|
# Background 5: tooltips
|
||||||
|
rounded = 2
|
||||||
|
border_width = 1
|
||||||
|
background_color = #ffffaa 100
|
||||||
|
border_color = #999999 100
|
||||||
|
|
||||||
# Panel
|
# Panel
|
||||||
|
panel_items = LTSC
|
||||||
panel_monitor = all
|
panel_monitor = all
|
||||||
panel_position = bottom center horizontal
|
panel_position = bottom center horizontal
|
||||||
panel_size = 94% 30
|
panel_size = 85% 30
|
||||||
panel_margin = 0 0
|
panel_margin = 0 0
|
||||||
panel_padding = 7 0 7
|
panel_padding = 7 0 7
|
||||||
panel_dock = 0
|
panel_dock = 0
|
||||||
wm_menu = 0
|
wm_menu = 1
|
||||||
panel_layer = top
|
panel_layer = top
|
||||||
panel_background_id = 1
|
panel_background_id = 1
|
||||||
|
font_shadow = 0
|
||||||
|
|
||||||
# Panel Autohide
|
# Panel Autohide
|
||||||
autohide = 0
|
autohide = 0
|
||||||
autohide_show_timeout = 0.3
|
autohide_show_timeout = 0
|
||||||
autohide_hide_timeout = 2
|
autohide_hide_timeout = 0.5
|
||||||
autohide_height = 2
|
autohide_height = 2
|
||||||
strut_policy = follow_size
|
strut_policy = follow_size
|
||||||
|
|
||||||
|
# Launcher
|
||||||
|
launcher_padding = 2 4 2
|
||||||
|
launcher_background_id = 0
|
||||||
|
launcher_icon_size = 18
|
||||||
|
launcher_icon_asb = 100 0 0
|
||||||
|
launcher_tooltip = 1
|
||||||
|
startup_notifications = 1
|
||||||
|
launcher_item_app = /usr/share/applications/firefox.desktop
|
||||||
|
launcher_item_app = /usr/share/applications/iceweasel.desktop
|
||||||
|
|
||||||
# Taskbar
|
# Taskbar
|
||||||
taskbar_mode = single_desktop
|
taskbar_mode = single_desktop
|
||||||
taskbar_padding = 2 3 2
|
taskbar_padding = 2 3 2
|
||||||
@@ -46,73 +69,71 @@ taskbar_background_id = 0
|
|||||||
taskbar_active_background_id = 0
|
taskbar_active_background_id = 0
|
||||||
|
|
||||||
# Tasks
|
# Tasks
|
||||||
urgent_nb_of_blink = 8
|
|
||||||
task_icon = 1
|
task_icon = 1
|
||||||
task_text = 1
|
task_text = 1
|
||||||
task_centered = 1
|
task_centered = 1
|
||||||
task_maximum_size = 140 35
|
task_maximum_size = 140 35
|
||||||
task_padding = 6 2
|
task_padding = 6 2
|
||||||
task_background_id = 3
|
task_background_id = 2
|
||||||
task_active_background_id = 2
|
task_active_background_id = 3
|
||||||
task_urgent_background_id = 2
|
task_urgent_background_id = 4
|
||||||
task_iconified_background_id = 3
|
task_iconified_background_id = 2
|
||||||
task_tooltip = 0
|
task_tooltip = 1
|
||||||
|
urgent_nb_of_blink = 100000
|
||||||
|
|
||||||
# Task Icons
|
# Task Icons
|
||||||
task_icon_asb = 70 0 0
|
task_icon_asb = 100 0 0
|
||||||
task_active_icon_asb = 100 0 0
|
task_active_icon_asb = 100 0 0
|
||||||
task_urgent_icon_asb = 100 0 0
|
task_urgent_icon_asb = 100 0 0
|
||||||
task_iconified_icon_asb = 70 0 0
|
task_iconified_icon_asb = 70 0 0
|
||||||
|
|
||||||
# Fonts
|
# Fonts
|
||||||
task_font = sans 7
|
task_font = sans 8
|
||||||
task_font_color = #FFFFFF 68
|
task_font_color = #FFFFFF 90
|
||||||
task_active_font_color = #FFFFFF 83
|
task_active_font_color = #FFFFFF 90
|
||||||
task_urgent_font_color = #FFFFFF 83
|
task_urgent_font_color = #FFFFFF 90
|
||||||
task_iconified_font_color = #FFFFFF 68
|
task_iconified_font_color = #FFFFFF 90
|
||||||
font_shadow = 0
|
|
||||||
|
# Mouse
|
||||||
|
mouse_left = toggle_iconify
|
||||||
|
mouse_middle = none
|
||||||
|
mouse_right = close
|
||||||
|
mouse_scroll_up = toggle
|
||||||
|
mouse_scroll_down = iconify
|
||||||
|
|
||||||
# System Tray
|
# System Tray
|
||||||
systray = 1
|
|
||||||
systray_padding = 0 4 5
|
systray_padding = 0 4 5
|
||||||
systray_sort = ascending
|
systray_sort = ascending
|
||||||
systray_background_id = 0
|
systray_background_id = 0
|
||||||
systray_icon_size = 16
|
systray_icon_size = 22
|
||||||
systray_icon_asb = 70 0 0
|
systray_icon_asb = 70 0 0
|
||||||
|
|
||||||
# Clock
|
# Clock
|
||||||
time1_format = %H:%M
|
time1_format = %H:%M
|
||||||
time1_font = sans 8
|
time1_font = sans 8
|
||||||
time2_format = %A %d %B
|
time2_format = %A %d %B
|
||||||
time2_font = sans 6
|
time2_font = sans 7
|
||||||
clock_font_color = #FFFFFF 74
|
clock_font_color = #FFFFFF 90
|
||||||
clock_padding = 1 0
|
clock_padding = 1 0
|
||||||
clock_background_id = 0
|
clock_background_id = 0
|
||||||
clock_rclick_command = orage
|
clock_rclick_command = orage
|
||||||
|
|
||||||
# Tooltips
|
# Tooltips
|
||||||
tooltip_padding = 2 2
|
tooltip_padding = 2 2
|
||||||
tooltip_show_timeout = 0.7
|
tooltip_show_timeout = 0.5
|
||||||
tooltip_hide_timeout = 0.3
|
tooltip_hide_timeout = 0.1
|
||||||
tooltip_background_id = 1
|
tooltip_background_id = 5
|
||||||
tooltip_font = sans 10
|
tooltip_font = sans 9
|
||||||
tooltip_font_color = #000000 80
|
tooltip_font_color = #222222 100
|
||||||
|
|
||||||
# Mouse
|
|
||||||
mouse_middle = none
|
|
||||||
mouse_right = close
|
|
||||||
mouse_scroll_up = toggle
|
|
||||||
mouse_scroll_down = iconify
|
|
||||||
|
|
||||||
# Battery
|
# Battery
|
||||||
battery = 0
|
|
||||||
battery_low_status = 10
|
battery_low_status = 10
|
||||||
battery_low_cmd = notify-send "battery low"
|
battery_low_cmd = notify-send "battery low"
|
||||||
battery_hide = 98
|
battery_hide = 101
|
||||||
bat1_font = sans 8
|
bat1_font = sans 8
|
||||||
bat2_font = sans 6
|
bat2_font = sans 6
|
||||||
battery_font_color = #FFFFFF 74
|
battery_font_color = #FFFFFF 94
|
||||||
battery_padding = 1 0
|
battery_padding = 1 0
|
||||||
battery_background_id = 0
|
battery_background_id = 0
|
||||||
|
|
||||||
# End of config
|
# End of config
|
||||||
|
|||||||
@@ -54,40 +54,64 @@ static char buf_bat_percentage[10];
|
|||||||
static char buf_bat_time[20];
|
static char buf_bat_time[20];
|
||||||
|
|
||||||
int8_t battery_low_status;
|
int8_t battery_low_status;
|
||||||
unsigned char battery_low_cmd_send;
|
unsigned char battery_low_cmd_sent;
|
||||||
char *battery_low_cmd;
|
char *battery_low_cmd;
|
||||||
char *path_energy_now;
|
gchar *path_energy_now;
|
||||||
char *path_energy_full;
|
gchar *path_energy_full;
|
||||||
char *path_current_now;
|
gchar *path_current_now;
|
||||||
char *path_status;
|
gchar *path_status;
|
||||||
|
int battery_found;
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
int apm_fd;
|
int apm_fd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void update_batterys(void* arg)
|
void update_battery_tick(void* arg)
|
||||||
{
|
{
|
||||||
|
if (!battery_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int old_found = battery_found;
|
||||||
int old_percentage = battery_state.percentage;
|
int old_percentage = battery_state.percentage;
|
||||||
int16_t old_hours = battery_state.time.hours;
|
int16_t old_hours = battery_state.time.hours;
|
||||||
int8_t old_minutes = battery_state.time.minutes;
|
int8_t old_minutes = battery_state.time.minutes;
|
||||||
|
|
||||||
update_battery();
|
if (update_battery() != 0) {
|
||||||
if (old_percentage == battery_state.percentage && old_hours == battery_state.time.hours && old_minutes == battery_state.time.minutes)
|
// Reconfigure
|
||||||
|
init_battery();
|
||||||
|
// Try again
|
||||||
|
update_battery();
|
||||||
|
}
|
||||||
|
if (old_found == battery_found &&
|
||||||
|
old_percentage == battery_state.percentage &&
|
||||||
|
old_hours == battery_state.time.hours &&
|
||||||
|
old_minutes == battery_state.time.minutes) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (battery_state.percentage < battery_low_status &&
|
||||||
|
battery_state.state == BATTERY_DISCHARGING &&
|
||||||
|
!battery_low_cmd_sent) {
|
||||||
|
tint_exec(battery_low_cmd);
|
||||||
|
battery_low_cmd_sent = 1;
|
||||||
|
}
|
||||||
|
if (battery_state.percentage > battery_low_status &&
|
||||||
|
battery_state.state == BATTERY_CHARGING &&
|
||||||
|
battery_low_cmd_sent) {
|
||||||
|
battery_low_cmd_sent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i=0 ; i < nb_panel ; i++) {
|
for (i = 0; i < nb_panel; i++) {
|
||||||
if (battery_state.percentage >= percentage_hide) {
|
if (!battery_found && panel1[i].battery.area.on_screen == 1) {
|
||||||
if (panel1[i].battery.area.on_screen == 1) {
|
hide(&panel1[i].battery.area);
|
||||||
hide(&panel1[i].battery.area);
|
panel_refresh = 1;
|
||||||
panel_refresh = 1;
|
} else if (battery_state.percentage >= percentage_hide && panel1[i].battery.area.on_screen == 1) {
|
||||||
}
|
hide(&panel1[i].battery.area);
|
||||||
}
|
panel_refresh = 1;
|
||||||
else {
|
} else if (battery_state.percentage < percentage_hide && panel1[i].battery.area.on_screen == 0) {
|
||||||
if (panel1[i].battery.area.on_screen == 0) {
|
show(&panel1[i].battery.area);
|
||||||
show(&panel1[i].battery.area);
|
panel_refresh = 1;
|
||||||
panel_refresh = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (panel1[i].battery.area.on_screen == 1) {
|
if (panel1[i].battery.area.on_screen == 1) {
|
||||||
panel1[i].battery.area.resize = 1;
|
panel1[i].battery.area.resize = 1;
|
||||||
@@ -99,19 +123,22 @@ void update_batterys(void* arg)
|
|||||||
void default_battery()
|
void default_battery()
|
||||||
{
|
{
|
||||||
battery_enabled = 0;
|
battery_enabled = 0;
|
||||||
|
battery_found = 0;
|
||||||
percentage_hide = 101;
|
percentage_hide = 101;
|
||||||
battery_low_cmd_send = 0;
|
battery_low_cmd_sent = 0;
|
||||||
battery_timeout = 0;
|
battery_timeout = NULL;
|
||||||
bat1_font_desc = 0;
|
bat1_font_desc = NULL;
|
||||||
bat2_font_desc = 0;
|
bat2_font_desc = NULL;
|
||||||
battery_low_cmd = 0;
|
battery_low_cmd = NULL;
|
||||||
path_energy_now = 0;
|
path_energy_now = NULL;
|
||||||
path_energy_full = 0;
|
path_energy_full = NULL;
|
||||||
path_current_now = 0;
|
path_current_now = NULL;
|
||||||
path_status = 0;
|
path_status = NULL;
|
||||||
battery_state.percentage = 0;
|
battery_state.percentage = 0;
|
||||||
battery_state.time.hours = 0;
|
battery_state.time.hours = 0;
|
||||||
battery_state.time.minutes = 0;
|
battery_state.time.minutes = 0;
|
||||||
|
battery_state.time.seconds = 0;
|
||||||
|
battery_state.state = BATTERY_UNKNOWN;
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
apm_fd = -1;
|
apm_fd = -1;
|
||||||
#endif
|
#endif
|
||||||
@@ -119,50 +146,65 @@ void default_battery()
|
|||||||
|
|
||||||
void cleanup_battery()
|
void cleanup_battery()
|
||||||
{
|
{
|
||||||
if (bat1_font_desc) pango_font_description_free(bat1_font_desc);
|
pango_font_description_free(bat1_font_desc);
|
||||||
if (bat2_font_desc) pango_font_description_free(bat2_font_desc);
|
bat1_font_desc = NULL;
|
||||||
if (path_energy_now) g_free(path_energy_now);
|
pango_font_description_free(bat2_font_desc);
|
||||||
if (path_energy_full) g_free(path_energy_full);
|
bat2_font_desc = NULL;
|
||||||
if (path_current_now) g_free(path_current_now);
|
g_free(path_energy_now);
|
||||||
if (path_status) g_free(path_status);
|
path_energy_now = NULL;
|
||||||
if (battery_low_cmd) g_free(battery_low_cmd);
|
g_free(path_energy_full);
|
||||||
if (battery_timeout) stop_timeout(battery_timeout);
|
path_energy_full = NULL;
|
||||||
|
g_free(path_current_now);
|
||||||
|
path_current_now = NULL;
|
||||||
|
g_free(path_status);
|
||||||
|
path_status = NULL;
|
||||||
|
free(battery_low_cmd);
|
||||||
|
battery_low_cmd = NULL;
|
||||||
|
stop_timeout(battery_timeout);
|
||||||
|
battery_timeout = NULL;
|
||||||
|
battery_found = 0;
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
if ((apm_fd != -1) && (close(apm_fd) == -1))
|
if ((apm_fd != -1) && (close(apm_fd) == -1))
|
||||||
warn("cannot close /dev/apm");
|
warn("cannot close /dev/apm");
|
||||||
|
apm_fd = -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void init_battery()
|
void init_battery()
|
||||||
{
|
{
|
||||||
if (!battery_enabled) return;
|
if (!battery_enabled)
|
||||||
|
return;
|
||||||
|
battery_found = 0;
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
|
if (apm_fd > 0)
|
||||||
|
close(apm_fd);
|
||||||
apm_fd = open("/dev/apm", O_RDONLY);
|
apm_fd = open("/dev/apm", O_RDONLY);
|
||||||
if (apm_fd < 0) {
|
if (apm_fd < 0) {
|
||||||
warn("init_battery: failed to open /dev/apm.");
|
warn("ERROR: battery applet cannot open /dev/apm.");
|
||||||
battery_enabled = 0;
|
battery_found = 0;
|
||||||
return;
|
} else {
|
||||||
|
battery_found = 1;
|
||||||
}
|
}
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
#elif !defined(__FreeBSD__)
|
// Nothing to do
|
||||||
// check battery
|
#else // Linux
|
||||||
GDir *directory = 0;
|
GDir *directory = 0;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
const char *entryname;
|
const char *entryname;
|
||||||
char *battery_dir = 0;
|
gchar *battery_dir = 0;
|
||||||
|
|
||||||
directory = g_dir_open("/sys/class/power_supply", 0, &error);
|
directory = g_dir_open("/sys/class/power_supply", 0, &error);
|
||||||
if (error)
|
if (error) {
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
else {
|
} else {
|
||||||
while ((entryname=g_dir_read_name(directory))) {
|
while ((entryname = g_dir_read_name(directory))) {
|
||||||
if (strncmp(entryname,"AC", 2) == 0) continue;
|
if (strncmp(entryname, "AC", 2) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
char *path1 = g_build_filename("/sys/class/power_supply", entryname, "present", NULL);
|
gchar *path1 = g_build_filename("/sys/class/power_supply", entryname, "present", NULL);
|
||||||
if (g_file_test (path1, G_FILE_TEST_EXISTS)) {
|
if (g_file_test(path1, G_FILE_TEST_EXISTS)) {
|
||||||
g_free(path1);
|
g_free(path1);
|
||||||
battery_dir = g_build_filename("/sys/class/power_supply", entryname, NULL);
|
battery_dir = g_build_filename("/sys/class/power_supply", entryname, NULL);
|
||||||
break;
|
break;
|
||||||
@@ -173,60 +215,67 @@ void init_battery()
|
|||||||
if (directory)
|
if (directory)
|
||||||
g_dir_close(directory);
|
g_dir_close(directory);
|
||||||
if (!battery_dir) {
|
if (!battery_dir) {
|
||||||
fprintf(stderr, "ERROR: battery applet can't found power_supply\n");
|
fprintf(stderr, "ERROR: battery applet cannot find any battery\n");
|
||||||
default_battery();
|
battery_found = 0;
|
||||||
return;
|
} else {
|
||||||
}
|
battery_found = 1;
|
||||||
|
|
||||||
char *path1 = g_build_filename(battery_dir, "energy_now", NULL);
|
g_free(path_energy_now);
|
||||||
if (g_file_test (path1, G_FILE_TEST_EXISTS)) {
|
|
||||||
path_energy_now = g_build_filename(battery_dir, "energy_now", NULL);
|
path_energy_now = g_build_filename(battery_dir, "energy_now", NULL);
|
||||||
path_energy_full = g_build_filename(battery_dir, "energy_full", NULL);
|
if (!g_file_test(path_energy_now, G_FILE_TEST_EXISTS)) {
|
||||||
}
|
g_free(path_energy_now);
|
||||||
else {
|
|
||||||
char *path2 = g_build_filename(battery_dir, "charge_now", NULL);
|
|
||||||
if (g_file_test (path2, G_FILE_TEST_EXISTS)) {
|
|
||||||
path_energy_now = g_build_filename(battery_dir, "charge_now", NULL);
|
path_energy_now = g_build_filename(battery_dir, "charge_now", NULL);
|
||||||
|
}
|
||||||
|
if (!g_file_test(path_energy_now, G_FILE_TEST_EXISTS)) {
|
||||||
|
fprintf(stderr, "ERROR: battery applet cannot find energy_now nor charge_now\n");
|
||||||
|
g_free(path_energy_now);
|
||||||
|
path_energy_now = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(path_energy_full);
|
||||||
|
path_energy_full = g_build_filename(battery_dir, "energy_full", NULL);
|
||||||
|
if (!g_file_test(path_energy_full, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_free(path_energy_full);
|
||||||
path_energy_full = g_build_filename(battery_dir, "charge_full", NULL);
|
path_energy_full = g_build_filename(battery_dir, "charge_full", NULL);
|
||||||
}
|
}
|
||||||
else {
|
if (!g_file_test(path_energy_full, G_FILE_TEST_EXISTS)) {
|
||||||
fprintf(stderr, "ERROR: can't found energy_* or charge_*\n");
|
fprintf(stderr, "ERROR: battery applet cannot find energy_now nor charge_now\n");
|
||||||
|
g_free(path_energy_full);
|
||||||
|
path_energy_full = NULL;
|
||||||
}
|
}
|
||||||
g_free(path2);
|
|
||||||
}
|
|
||||||
|
|
||||||
path_current_now = g_build_filename(battery_dir, "power_now", NULL);
|
|
||||||
if (!g_file_test (path_current_now, G_FILE_TEST_EXISTS)) {
|
|
||||||
g_free(path_current_now);
|
g_free(path_current_now);
|
||||||
path_current_now = g_build_filename(battery_dir, "current_now", NULL);
|
path_current_now = g_build_filename(battery_dir, "power_now", NULL);
|
||||||
}
|
if (!g_file_test(path_current_now, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_free(path_current_now);
|
||||||
if (path_energy_now && path_energy_full) {
|
path_current_now = g_build_filename(battery_dir, "current_now", NULL);
|
||||||
path_status = g_build_filename(battery_dir, "status", NULL);
|
|
||||||
|
|
||||||
// check file
|
|
||||||
FILE *fp1, *fp2, *fp3, *fp4;
|
|
||||||
fp1 = fopen(path_energy_now, "r");
|
|
||||||
fp2 = fopen(path_energy_full, "r");
|
|
||||||
fp3 = fopen(path_current_now, "r");
|
|
||||||
fp4 = fopen(path_status, "r");
|
|
||||||
if (fp1 == NULL || fp2 == NULL || fp3 == NULL || fp4 == NULL) {
|
|
||||||
cleanup_battery();
|
|
||||||
default_battery();
|
|
||||||
fprintf(stderr, "ERROR: battery applet can't open energy_now\n");
|
|
||||||
}
|
}
|
||||||
fclose(fp1);
|
if (!g_file_test(path_current_now, G_FILE_TEST_EXISTS)) {
|
||||||
fclose(fp2);
|
fprintf(stderr, "ERROR: battery applet cannot find power_now nor current_now\n");
|
||||||
fclose(fp3);
|
g_free(path_current_now);
|
||||||
fclose(fp4);
|
path_current_now = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(path_status);
|
||||||
|
path_status = g_build_filename(battery_dir, "status", NULL);
|
||||||
|
if (!g_file_test(path_status, G_FILE_TEST_EXISTS)) {
|
||||||
|
fprintf(stderr, "ERROR: battery applet cannot find battery status\n");
|
||||||
|
g_free(path_status);
|
||||||
|
path_status = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(battery_dir);
|
||||||
|
battery_dir = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(path1);
|
if (!path_status) {
|
||||||
g_free(battery_dir);
|
battery_found = 0;
|
||||||
|
fprintf(stderr, "ERROR: battery applet cannot find any batteries\n");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (battery_enabled && battery_timeout==0)
|
if (!battery_timeout)
|
||||||
battery_timeout = add_timeout(10, 10000, update_batterys, 0);
|
battery_timeout = add_timeout(10, 10000, update_battery_tick, 0, &battery_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -238,6 +287,11 @@ void init_battery_panel(void *p)
|
|||||||
if (!battery_enabled)
|
if (!battery_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!bat1_font_desc)
|
||||||
|
bat1_font_desc = pango_font_description_from_string(DEFAULT_FONT);
|
||||||
|
if (!bat2_font_desc)
|
||||||
|
bat2_font_desc = pango_font_description_from_string(DEFAULT_FONT);
|
||||||
|
|
||||||
if (battery->area.bg == 0)
|
if (battery->area.bg == 0)
|
||||||
battery->area.bg = &g_array_index(backgrounds, Background, 0);
|
battery->area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
|
|
||||||
@@ -251,61 +305,53 @@ void init_battery_panel(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void update_battery() {
|
int update_battery() {
|
||||||
#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__)
|
int64_t energy_now = 0,
|
||||||
// unused on OpenBSD, silence compiler warnings
|
energy_full = 0;
|
||||||
FILE *fp;
|
|
||||||
char tmp[25];
|
|
||||||
int64_t current_now = 0;
|
|
||||||
#endif
|
|
||||||
#if defined(__FreeBSD__)
|
|
||||||
int sysctl_out = 0;
|
|
||||||
size_t len = 0;
|
|
||||||
#endif
|
|
||||||
int64_t energy_now = 0, energy_full = 0;
|
|
||||||
int seconds = 0;
|
int seconds = 0;
|
||||||
int8_t new_percentage = 0;
|
int8_t new_percentage = 0;
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
battery_state.state = BATTERY_UNKNOWN;
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
struct apm_power_info info;
|
struct apm_power_info info;
|
||||||
if (ioctl(apm_fd, APM_IOC_GETPOWER, &(info)) < 0)
|
if (apm_fd > 0 && ioctl(apm_fd, APM_IOC_GETPOWER, &(info)) == 0) {
|
||||||
warn("power update: APM_IOC_GETPOWER");
|
// best attempt at mapping to Linux battery states
|
||||||
|
switch (info.battery_state) {
|
||||||
// best attempt at mapping to linux battery states
|
|
||||||
battery_state.state = BATTERY_UNKNOWN;
|
|
||||||
switch (info.battery_state) {
|
|
||||||
case APM_BATT_CHARGING:
|
case APM_BATT_CHARGING:
|
||||||
battery_state.state = BATTERY_CHARGING;
|
battery_state.state = BATTERY_CHARGING;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
battery_state.state = BATTERY_DISCHARGING;
|
battery_state.state = BATTERY_DISCHARGING;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.battery_life == 100)
|
||||||
|
battery_state.state = BATTERY_FULL;
|
||||||
|
|
||||||
|
// no mapping for openbsd really
|
||||||
|
energy_full = 0;
|
||||||
|
energy_now = 0;
|
||||||
|
|
||||||
|
if (info.minutes_left != -1)
|
||||||
|
seconds = info.minutes_left * 60;
|
||||||
|
else
|
||||||
|
seconds = -1;
|
||||||
|
|
||||||
|
new_percentage = info.battery_life;
|
||||||
|
} else {
|
||||||
|
warn("power update: APM_IOC_GETPOWER");
|
||||||
|
errors = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.battery_life == 100)
|
|
||||||
battery_state.state = BATTERY_FULL;
|
|
||||||
|
|
||||||
// no mapping for openbsd really
|
|
||||||
energy_full = 0;
|
|
||||||
energy_now = 0;
|
|
||||||
|
|
||||||
if (info.minutes_left != -1)
|
|
||||||
seconds = info.minutes_left * 60;
|
|
||||||
else
|
|
||||||
seconds = -1;
|
|
||||||
|
|
||||||
new_percentage = info.battery_life;
|
|
||||||
|
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
len = sizeof(sysctl_out);
|
int sysctl_out = 0;
|
||||||
|
size_t len = sizeof(sysctl_out);
|
||||||
|
|
||||||
if (sysctlbyname("hw.acpi.battery.state", &sysctl_out, &len, NULL, 0) != 0)
|
if (sysctlbyname("hw.acpi.battery.state", &sysctl_out, &len, NULL, 0) == 0) {
|
||||||
fprintf(stderr, "power update: no such sysctl");
|
// attemp to map the battery state to Linux
|
||||||
|
battery_state.state = BATTERY_UNKNOWN;
|
||||||
// attemp to map the battery state to linux
|
switch(sysctl_out) {
|
||||||
battery_state.state = BATTERY_UNKNOWN;
|
|
||||||
|
|
||||||
switch(sysctl_out) {
|
|
||||||
case 1:
|
case 1:
|
||||||
battery_state.state = BATTERY_DISCHARGING;
|
battery_state.state = BATTERY_DISCHARGING;
|
||||||
break;
|
break;
|
||||||
@@ -315,6 +361,10 @@ void update_battery() {
|
|||||||
default:
|
default:
|
||||||
battery_state.state = BATTERY_FULL;
|
battery_state.state = BATTERY_FULL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "power update: no such sysctl");
|
||||||
|
errors = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no mapping for freebsd
|
// no mapping for freebsd
|
||||||
@@ -334,50 +384,83 @@ void update_battery() {
|
|||||||
new_percentage = -1;
|
new_percentage = -1;
|
||||||
else
|
else
|
||||||
new_percentage = sysctl_out;
|
new_percentage = sysctl_out;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
fp = fopen(path_status, "r");
|
FILE *fp = NULL;
|
||||||
if(fp != NULL) {
|
char tmp[25] = "";
|
||||||
if (fgets(tmp, sizeof tmp, fp)) {
|
int64_t current_now = 0;
|
||||||
battery_state.state = BATTERY_UNKNOWN;
|
if (path_status) {
|
||||||
if(strcasecmp(tmp, "Charging\n")==0) battery_state.state = BATTERY_CHARGING;
|
fp = fopen(path_status, "r");
|
||||||
if(strcasecmp(tmp, "Discharging\n")==0) battery_state.state = BATTERY_DISCHARGING;
|
if (fp != NULL) {
|
||||||
if(strcasecmp(tmp, "Full\n")==0) battery_state.state = BATTERY_FULL;
|
if (fgets(tmp, sizeof(tmp), fp)) {
|
||||||
|
if (strcasecmp(tmp, "Charging\n") == 0)
|
||||||
|
battery_state.state = BATTERY_CHARGING;
|
||||||
|
if (strcasecmp(tmp, "Discharging\n") == 0)
|
||||||
|
battery_state.state = BATTERY_DISCHARGING;
|
||||||
|
if (strcasecmp(tmp, "Full\n") == 0)
|
||||||
|
battery_state.state = BATTERY_FULL;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
errors = 1;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
} else {
|
||||||
|
errors = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = fopen(path_energy_now, "r");
|
if (path_energy_now) {
|
||||||
if(fp != NULL) {
|
fp = fopen(path_energy_now, "r");
|
||||||
if (fgets(tmp, sizeof tmp, fp)) energy_now = atoi(tmp);
|
if (fp != NULL) {
|
||||||
fclose(fp);
|
if (fgets(tmp, sizeof tmp, fp))
|
||||||
}
|
energy_now = atoi(tmp);
|
||||||
|
fclose(fp);
|
||||||
fp = fopen(path_energy_full, "r");
|
} else {
|
||||||
if(fp != NULL) {
|
errors = 1;
|
||||||
if (fgets(tmp, sizeof tmp, fp)) energy_full = atoi(tmp);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
fp = fopen(path_current_now, "r");
|
|
||||||
if(fp != NULL) {
|
|
||||||
if (fgets(tmp, sizeof tmp, fp)) current_now = atoi(tmp);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(current_now > 0) {
|
|
||||||
switch(battery_state.state) {
|
|
||||||
case BATTERY_CHARGING:
|
|
||||||
seconds = 3600 * (energy_full - energy_now) / current_now;
|
|
||||||
break;
|
|
||||||
case BATTERY_DISCHARGING:
|
|
||||||
seconds = 3600 * energy_now / current_now;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
seconds = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else seconds = 0;
|
} else {
|
||||||
|
errors = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_energy_full) {
|
||||||
|
fp = fopen(path_energy_full, "r");
|
||||||
|
if (fp != NULL) {
|
||||||
|
if (fgets(tmp, sizeof tmp, fp))
|
||||||
|
energy_full = atoi(tmp);
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
errors = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errors = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_current_now) {
|
||||||
|
fp = fopen(path_current_now, "r");
|
||||||
|
if (fp != NULL) {
|
||||||
|
if (fgets(tmp, sizeof tmp, fp))
|
||||||
|
current_now = atoi(tmp);
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
errors = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errors = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_now > 0) {
|
||||||
|
switch (battery_state.state) {
|
||||||
|
case BATTERY_CHARGING:
|
||||||
|
seconds = 3600 * (energy_full - energy_now) / current_now;
|
||||||
|
break;
|
||||||
|
case BATTERY_DISCHARGING:
|
||||||
|
seconds = 3600 * energy_now / current_now;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
seconds = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
seconds = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
battery_state.time.hours = seconds / 3600;
|
battery_state.time.hours = seconds / 3600;
|
||||||
@@ -386,23 +469,17 @@ void update_battery() {
|
|||||||
seconds -= 60 * battery_state.time.minutes;
|
seconds -= 60 * battery_state.time.minutes;
|
||||||
battery_state.time.seconds = seconds;
|
battery_state.time.seconds = seconds;
|
||||||
|
|
||||||
if(energy_full > 0)
|
if (energy_full > 0)
|
||||||
new_percentage = (energy_now*100)/energy_full;
|
new_percentage = ((energy_now <= energy_full ? energy_now : energy_full) * 100) / energy_full;
|
||||||
|
|
||||||
if(battery_low_status > new_percentage && battery_state.state == BATTERY_DISCHARGING && !battery_low_cmd_send) {
|
|
||||||
tint_exec(battery_low_cmd);
|
|
||||||
battery_low_cmd_send = 1;
|
|
||||||
}
|
|
||||||
if(battery_low_status < new_percentage && battery_state.state == BATTERY_CHARGING && battery_low_cmd_send) {
|
|
||||||
battery_low_cmd_send = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
battery_state.percentage = new_percentage;
|
battery_state.percentage = new_percentage;
|
||||||
|
|
||||||
// clamp percentage to 100 in case battery is misreporting that its current charge is more than its max
|
// clamp percentage to 100 in case battery is misreporting that its current charge is more than its max
|
||||||
if(battery_state.percentage > 100) {
|
if (battery_state.percentage > 100) {
|
||||||
battery_state.percentage = 100;
|
battery_state.percentage = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -422,8 +499,7 @@ void draw_battery (void *obj, cairo_t *c)
|
|||||||
cairo_set_source_rgba(c, battery->font.color[0], battery->font.color[1], battery->font.color[2], battery->font.alpha);
|
cairo_set_source_rgba(c, battery->font.color[0], battery->font.color[1], battery->font.color[2], battery->font.alpha);
|
||||||
|
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
cairo_move_to(c, 0, battery->bat1_posy);
|
draw_text(layout, c, 0, battery->bat1_posy, &battery->font, ((Panel*)battery->area.panel)->font_shadow);
|
||||||
pango_cairo_show_layout(c, layout);
|
|
||||||
|
|
||||||
pango_layout_set_font_description(layout, bat2_font_desc);
|
pango_layout_set_font_description(layout, bat2_font_desc);
|
||||||
pango_layout_set_indent(layout, 0);
|
pango_layout_set_indent(layout, 0);
|
||||||
@@ -431,7 +507,7 @@ void draw_battery (void *obj, cairo_t *c)
|
|||||||
pango_layout_set_width(layout, battery->area.width * PANGO_SCALE);
|
pango_layout_set_width(layout, battery->area.width * PANGO_SCALE);
|
||||||
|
|
||||||
pango_cairo_update_layout(c, layout);
|
pango_cairo_update_layout(c, layout);
|
||||||
cairo_move_to(c, 0, battery->bat2_posy);
|
draw_text(layout, c, 0, battery->bat2_posy, &battery->font, ((Panel*)battery->area.panel)->font_shadow);
|
||||||
pango_cairo_show_layout(c, layout);
|
pango_cairo_show_layout(c, layout);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
@@ -449,34 +525,37 @@ int resize_battery(void *obj)
|
|||||||
battery->area.redraw = 1;
|
battery->area.redraw = 1;
|
||||||
|
|
||||||
snprintf(buf_bat_percentage, sizeof(buf_bat_percentage), "%d%%", battery_state.percentage);
|
snprintf(buf_bat_percentage, sizeof(buf_bat_percentage), "%d%%", battery_state.percentage);
|
||||||
if(battery_state.state == BATTERY_FULL) {
|
if (battery_state.state == BATTERY_FULL) {
|
||||||
strcpy(buf_bat_time, "Full");
|
strcpy(buf_bat_time, "Full");
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf_bat_time, sizeof(buf_bat_time), "%02d:%02d", battery_state.time.hours, battery_state.time.minutes);
|
snprintf(buf_bat_time, sizeof(buf_bat_time), "%02d:%02d", battery_state.time.hours, battery_state.time.minutes);
|
||||||
}
|
}
|
||||||
get_text_size2(bat1_font_desc, &bat_percentage_height_ink, &bat_percentage_height, &bat_percentage_width, panel->area.height, panel->area.width, buf_bat_percentage, strlen(buf_bat_percentage));
|
get_text_size2(bat1_font_desc, &bat_percentage_height_ink, &bat_percentage_height, &bat_percentage_width,
|
||||||
get_text_size2(bat2_font_desc, &bat_time_height_ink, &bat_time_height, &bat_time_width, panel->area.height, panel->area.width, buf_bat_time, strlen(buf_bat_time));
|
panel->area.height, panel->area.width, buf_bat_percentage, strlen(buf_bat_percentage));
|
||||||
|
get_text_size2(bat2_font_desc, &bat_time_height_ink, &bat_time_height, &bat_time_width,
|
||||||
|
panel->area.height, panel->area.width, buf_bat_time, strlen(buf_bat_time));
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
int new_size = (bat_percentage_width > bat_time_width) ? bat_percentage_width : bat_time_width;
|
int new_size = (bat_percentage_width > bat_time_width) ? bat_percentage_width : bat_time_width;
|
||||||
new_size += (2*battery->area.paddingxlr) + (2*battery->area.bg->border.width);
|
new_size += 2 * battery->area.paddingxlr + 2 * battery->area.bg->border.width;
|
||||||
if (new_size > battery->area.width || new_size < (battery->area.width-2)) {
|
if (new_size > battery->area.width ||
|
||||||
|
new_size < battery->area.width - 2) {
|
||||||
// we try to limit the number of resize
|
// we try to limit the number of resize
|
||||||
battery->area.width = new_size;
|
battery->area.width = new_size;
|
||||||
battery->bat1_posy = (battery->area.height - bat_percentage_height - bat_time_height)/2;
|
battery->bat1_posy = (battery->area.height - bat_percentage_height - bat_time_height) / 2;
|
||||||
battery->bat2_posy = battery->bat1_posy + bat_percentage_height;
|
battery->bat2_posy = battery->bat1_posy + bat_percentage_height;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
int new_size = bat_percentage_height + bat_time_height +
|
||||||
int new_size = bat_percentage_height + bat_time_height + (2 * (battery->area.paddingxlr + battery->area.bg->border.width));
|
(2 * (battery->area.paddingxlr + battery->area.bg->border.width));
|
||||||
if (new_size > battery->area.height || new_size < (battery->area.height-2)) {
|
if (new_size > battery->area.height ||
|
||||||
|
new_size < battery->area.height - 2) {
|
||||||
battery->area.height = new_size;
|
battery->area.height = new_size;
|
||||||
battery->bat1_posy = (battery->area.height - bat_percentage_height - bat_time_height - 2)/2;
|
battery->bat1_posy = (battery->area.height - bat_percentage_height - bat_time_height - 2) / 2;
|
||||||
battery->bat2_posy = battery->bat1_posy + bat_percentage_height + 2;
|
battery->bat2_posy = battery->bat1_posy + bat_percentage_height + 2;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ extern int percentage_hide;
|
|||||||
|
|
||||||
extern int8_t battery_low_status;
|
extern int8_t battery_low_status;
|
||||||
extern char *battery_low_cmd;
|
extern char *battery_low_cmd;
|
||||||
extern char *path_energy_now, *path_energy_full, *path_current_now, *path_status;
|
|
||||||
|
|
||||||
// default global data
|
// default global data
|
||||||
void default_battery();
|
void default_battery();
|
||||||
@@ -63,8 +62,7 @@ void default_battery();
|
|||||||
// freed memory
|
// freed memory
|
||||||
void cleanup_battery();
|
void cleanup_battery();
|
||||||
|
|
||||||
// initialize clock : y position, ...
|
int update_battery();
|
||||||
void update_battery();
|
|
||||||
|
|
||||||
void init_battery();
|
void init_battery();
|
||||||
void init_battery_panel(void *panel);
|
void init_battery_panel(void *panel);
|
||||||
|
|||||||
@@ -53,32 +53,43 @@ static timeout* clock_timeout;
|
|||||||
void default_clock()
|
void default_clock()
|
||||||
{
|
{
|
||||||
clock_enabled = 0;
|
clock_enabled = 0;
|
||||||
clock_timeout = 0;
|
clock_timeout = NULL;
|
||||||
time1_format = 0;
|
time1_format = NULL;
|
||||||
time1_timezone = 0;
|
time1_timezone = NULL;
|
||||||
time2_format = 0;
|
time2_format = NULL;
|
||||||
time2_timezone = 0;
|
time2_timezone = NULL;
|
||||||
time_tooltip_format = 0;
|
time_tooltip_format = NULL;
|
||||||
time_tooltip_timezone = 0;
|
time_tooltip_timezone = NULL;
|
||||||
clock_lclick_command = 0;
|
clock_lclick_command = NULL;
|
||||||
clock_rclick_command = 0;
|
clock_rclick_command = NULL;
|
||||||
time1_font_desc = 0;
|
time1_font_desc = NULL;
|
||||||
time2_font_desc = 0;
|
time2_font_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_clock()
|
void cleanup_clock()
|
||||||
{
|
{
|
||||||
if (time1_font_desc) pango_font_description_free(time1_font_desc);
|
pango_font_description_free(time1_font_desc);
|
||||||
if (time2_font_desc) pango_font_description_free(time2_font_desc);
|
time1_font_desc = NULL;
|
||||||
if (time1_format) g_free(time1_format);
|
pango_font_description_free(time2_font_desc);
|
||||||
if (time2_format) g_free(time2_format);
|
time2_font_desc = NULL;
|
||||||
if (time_tooltip_format) g_free(time_tooltip_format);
|
free(time1_format);
|
||||||
if (time1_timezone) g_free(time1_timezone);
|
time1_format = NULL;
|
||||||
if (time2_timezone) g_free(time2_timezone);
|
free(time2_format);
|
||||||
if (time_tooltip_timezone) g_free(time_tooltip_timezone);
|
time2_format = NULL;
|
||||||
if (clock_lclick_command) g_free(clock_lclick_command);
|
free(time_tooltip_format);
|
||||||
if (clock_rclick_command) g_free(clock_rclick_command);
|
time_tooltip_format = NULL;
|
||||||
if (clock_timeout) stop_timeout(clock_timeout);
|
free(time1_timezone);
|
||||||
|
time1_timezone = NULL;
|
||||||
|
free(time2_timezone);
|
||||||
|
time2_timezone = NULL;
|
||||||
|
free(time_tooltip_timezone);
|
||||||
|
time_tooltip_timezone = NULL;
|
||||||
|
free(clock_lclick_command);
|
||||||
|
clock_lclick_command = NULL;
|
||||||
|
free(clock_rclick_command);
|
||||||
|
clock_rclick_command = NULL;
|
||||||
|
stop_timeout(clock_timeout);
|
||||||
|
clock_timeout = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -127,14 +138,24 @@ const char* clock_get_tooltip(void* obj)
|
|||||||
return buf_tooltip;
|
return buf_tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int time_format_needs_sec_ticks(char *time_format)
|
||||||
|
{
|
||||||
|
if (!time_format)
|
||||||
|
return 0;
|
||||||
|
if (strchr(time_format, 'S') || strchr(time_format, 'T') || strchr(time_format, 'r'))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void init_clock()
|
void init_clock()
|
||||||
{
|
{
|
||||||
if(time1_format && clock_timeout==0) {
|
if (!clock_timeout) {
|
||||||
if (strchr(time1_format, 'S') || strchr(time1_format, 'T') || strchr(time1_format, 'r'))
|
if (time_format_needs_sec_ticks(time1_format) ||
|
||||||
clock_timeout = add_timeout(10, 1000, update_clocks_sec, 0);
|
time_format_needs_sec_ticks(time2_format)) {
|
||||||
else
|
clock_timeout = add_timeout(10, 1000, update_clocks_sec, 0, &clock_timeout);
|
||||||
clock_timeout = add_timeout(10, 1000, update_clocks_min, 0);
|
} else {
|
||||||
|
clock_timeout = add_timeout(10, 1000, update_clocks_min, 0, &clock_timeout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +165,11 @@ void init_clock_panel(void *p)
|
|||||||
Panel *panel =(Panel*)p;
|
Panel *panel =(Panel*)p;
|
||||||
Clock *clock = &panel->clock;
|
Clock *clock = &panel->clock;
|
||||||
|
|
||||||
if (clock->area.bg == 0)
|
if (!time1_font_desc)
|
||||||
|
time1_font_desc = pango_font_description_from_string(DEFAULT_FONT);
|
||||||
|
if (!time2_font_desc)
|
||||||
|
time2_font_desc = pango_font_description_from_string(DEFAULT_FONT);
|
||||||
|
if (!clock->area.bg)
|
||||||
clock->area.bg = &g_array_index(backgrounds, Background, 0);
|
clock->area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
clock->area.parent = p;
|
clock->area.parent = p;
|
||||||
clock->area.panel = p;
|
clock->area.panel = p;
|
||||||
@@ -152,7 +177,7 @@ void init_clock_panel(void *p)
|
|||||||
clock->area.size_mode = SIZE_BY_CONTENT;
|
clock->area.size_mode = SIZE_BY_CONTENT;
|
||||||
clock->area._resize = resize_clock;
|
clock->area._resize = resize_clock;
|
||||||
// check consistency
|
// check consistency
|
||||||
if (time1_format == 0)
|
if (!time1_format)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clock->area.resize = 1;
|
clock->area.resize = 1;
|
||||||
@@ -181,8 +206,7 @@ void draw_clock (void *obj, cairo_t *c)
|
|||||||
cairo_set_source_rgba (c, clock->font.color[0], clock->font.color[1], clock->font.color[2], clock->font.alpha);
|
cairo_set_source_rgba (c, clock->font.color[0], clock->font.color[1], clock->font.color[2], clock->font.alpha);
|
||||||
|
|
||||||
pango_cairo_update_layout (c, layout);
|
pango_cairo_update_layout (c, layout);
|
||||||
cairo_move_to (c, 0, clock->time1_posy);
|
draw_text(layout, c, 0, clock->time1_posy, &clock->font, ((Panel*)clock->area.panel)->font_shadow);
|
||||||
pango_cairo_show_layout (c, layout);
|
|
||||||
|
|
||||||
if (time2_format) {
|
if (time2_format) {
|
||||||
pango_layout_set_font_description (layout, time2_font_desc);
|
pango_layout_set_font_description (layout, time2_font_desc);
|
||||||
@@ -191,8 +215,7 @@ void draw_clock (void *obj, cairo_t *c)
|
|||||||
pango_layout_set_width (layout, clock->area.width * PANGO_SCALE);
|
pango_layout_set_width (layout, clock->area.width * PANGO_SCALE);
|
||||||
|
|
||||||
pango_cairo_update_layout (c, layout);
|
pango_cairo_update_layout (c, layout);
|
||||||
cairo_move_to (c, 0, clock->time2_posy);
|
draw_text(layout, c, 0, clock->time2_posy, &clock->font, ((Panel*)clock->area.panel)->font_shadow);
|
||||||
pango_cairo_show_layout (c, layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref (layout);
|
g_object_unref (layout);
|
||||||
|
|||||||
193
src/config.c
193
src/config.c
@@ -35,6 +35,10 @@
|
|||||||
#include <pango/pangoxft.h>
|
#include <pango/pangoxft.h>
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifndef TINT2CONF
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
@@ -44,7 +48,6 @@
|
|||||||
#include "systraybar.h"
|
#include "systraybar.h"
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "config.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
@@ -53,10 +56,14 @@
|
|||||||
#include "battery.h"
|
#include "battery.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// global path
|
// global path
|
||||||
char *config_path;
|
char *config_path;
|
||||||
char *snapshot_path;
|
char *snapshot_path;
|
||||||
|
|
||||||
|
#ifndef TINT2CONF
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// backward compatibility
|
// backward compatibility
|
||||||
// detect if it's an old config file (==1)
|
// detect if it's an old config file (==1)
|
||||||
@@ -65,15 +72,17 @@ static int new_config_file;
|
|||||||
|
|
||||||
void default_config()
|
void default_config()
|
||||||
{
|
{
|
||||||
config_path = 0;
|
config_path = NULL;
|
||||||
snapshot_path = 0;
|
snapshot_path = NULL;
|
||||||
new_config_file = 0;
|
new_config_file = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_config()
|
void cleanup_config()
|
||||||
{
|
{
|
||||||
if (config_path) g_free(config_path);
|
free(config_path);
|
||||||
if (snapshot_path) g_free(snapshot_path);
|
config_path = NULL;
|
||||||
|
free(snapshot_path);
|
||||||
|
snapshot_path = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -101,6 +110,8 @@ void get_action (char *event, int *action)
|
|||||||
*action = NEXT_TASK;
|
*action = NEXT_TASK;
|
||||||
else if (strcmp (event, "prev_task") == 0)
|
else if (strcmp (event, "prev_task") == 0)
|
||||||
*action = PREV_TASK;
|
*action = PREV_TASK;
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Error: unrecognized action '%s'. Please fix your config file.\n", event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -112,7 +123,7 @@ int get_task_status(char* status)
|
|||||||
return TASK_ICONIFIED;
|
return TASK_ICONIFIED;
|
||||||
if (strcmp(status, "urgent") == 0)
|
if (strcmp(status, "urgent") == 0)
|
||||||
return TASK_URGENT;
|
return TASK_URGENT;
|
||||||
return TASK_NORMAL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,6 +153,25 @@ int config_get_monitor(char* monitor)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load_launcher_app_dir(const char *path)
|
||||||
|
{
|
||||||
|
GDir *d = g_dir_open(path, 0, NULL);
|
||||||
|
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")) {
|
||||||
|
panel_config.launcher.list_apps = g_slist_append(panel_config.launcher.list_apps, strdup(file));
|
||||||
|
} else if (g_file_test(file, G_FILE_TEST_IS_DIR)) {
|
||||||
|
load_launcher_app_dir(file);
|
||||||
|
}
|
||||||
|
g_free(file);
|
||||||
|
}
|
||||||
|
g_dir_close(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void add_entry (char *key, char *value)
|
void add_entry (char *key, char *value)
|
||||||
{
|
{
|
||||||
char *value1=0, *value2=0, *value3=0;
|
char *value1=0, *value2=0, *value3=0;
|
||||||
@@ -150,6 +180,7 @@ void add_entry (char *key, char *value)
|
|||||||
if (strcmp (key, "rounded") == 0) {
|
if (strcmp (key, "rounded") == 0) {
|
||||||
// 'rounded' is the first parameter => alloc a new background
|
// 'rounded' is the first parameter => alloc a new background
|
||||||
Background bg;
|
Background bg;
|
||||||
|
memset(&bg, 0, sizeof(bg));
|
||||||
bg.border.rounded = atoi(value);
|
bg.border.rounded = atoi(value);
|
||||||
g_array_append_val(backgrounds, bg);
|
g_array_append_val(backgrounds, bg);
|
||||||
}
|
}
|
||||||
@@ -256,7 +287,7 @@ void add_entry (char *key, char *value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp (key, "font_shadow") == 0)
|
else if (strcmp (key, "font_shadow") == 0)
|
||||||
panel_config.g_task.font_shadow = atoi (value);
|
panel_config.font_shadow = atoi (value);
|
||||||
else if (strcmp (key, "panel_background_id") == 0) {
|
else if (strcmp (key, "panel_background_id") == 0) {
|
||||||
int id = atoi (value);
|
int id = atoi (value);
|
||||||
id = (id < backgrounds->len && id >= 0) ? id : 0;
|
id = (id < backgrounds->len && id >= 0) ? id : 0;
|
||||||
@@ -276,6 +307,15 @@ void add_entry (char *key, char *value)
|
|||||||
else
|
else
|
||||||
panel_layer = NORMAL_LAYER;
|
panel_layer = NORMAL_LAYER;
|
||||||
}
|
}
|
||||||
|
else if (strcmp (key, "disable_transparency") == 0) {
|
||||||
|
server.disable_transparency = atoi (value);
|
||||||
|
}
|
||||||
|
else if (strcmp (key, "panel_window_name") == 0) {
|
||||||
|
if (strlen(value) > 0) {
|
||||||
|
free(panel_window_name);
|
||||||
|
panel_window_name = strdup (value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Battery */
|
/* Battery */
|
||||||
else if (strcmp (key, "battery_low_status") == 0) {
|
else if (strcmp (key, "battery_low_status") == 0) {
|
||||||
@@ -337,12 +377,13 @@ void add_entry (char *key, char *value)
|
|||||||
if (new_config_file == 0) {
|
if (new_config_file == 0) {
|
||||||
clock_enabled = 1;
|
clock_enabled = 1;
|
||||||
if (panel_items_order) {
|
if (panel_items_order) {
|
||||||
char* tmp = g_strconcat(panel_items_order, "C", NULL);
|
gchar* tmp = g_strconcat(panel_items_order, "C", NULL);
|
||||||
g_free( panel_items_order );
|
free(panel_items_order);
|
||||||
panel_items_order = tmp;
|
panel_items_order = strdup(tmp);
|
||||||
|
g_free(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
panel_items_order = g_strdup("C");
|
panel_items_order = strdup("C");
|
||||||
}
|
}
|
||||||
if (strlen(value) > 0) {
|
if (strlen(value) > 0) {
|
||||||
time1_format = strdup (value);
|
time1_format = strdup (value);
|
||||||
@@ -406,6 +447,9 @@ void add_entry (char *key, char *value)
|
|||||||
if (strcmp (value, "multi_desktop") == 0) panel_mode = MULTI_DESKTOP;
|
if (strcmp (value, "multi_desktop") == 0) panel_mode = MULTI_DESKTOP;
|
||||||
else panel_mode = SINGLE_DESKTOP;
|
else panel_mode = SINGLE_DESKTOP;
|
||||||
}
|
}
|
||||||
|
else if (strcmp (key, "taskbar_distribute_size") == 0) {
|
||||||
|
taskbar_distribute_size = atoi(value);
|
||||||
|
}
|
||||||
else if (strcmp (key, "taskbar_padding") == 0) {
|
else if (strcmp (key, "taskbar_padding") == 0) {
|
||||||
extract_values(value, &value1, &value2, &value3);
|
extract_values(value, &value1, &value2, &value3);
|
||||||
panel_config.g_taskbar.area.paddingxlr = panel_config.g_taskbar.area.paddingx = atoi (value1);
|
panel_config.g_taskbar.area.paddingxlr = panel_config.g_taskbar.area.paddingx = atoi (value1);
|
||||||
@@ -458,6 +502,21 @@ void add_entry (char *key, char *value)
|
|||||||
if (value2) taskbarname_active_font.alpha = (atoi (value2) / 100.0);
|
if (value2) taskbarname_active_font.alpha = (atoi (value2) / 100.0);
|
||||||
else taskbarname_active_font.alpha = 0.5;
|
else taskbarname_active_font.alpha = 0.5;
|
||||||
}
|
}
|
||||||
|
else if (strcmp (key, "taskbar_hide_inactive_tasks") == 0) {
|
||||||
|
hide_inactive_tasks = atoi (value);
|
||||||
|
}
|
||||||
|
else if (strcmp (key, "taskbar_hide_different_monitor") == 0) {
|
||||||
|
hide_task_diff_monitor = atoi (value);
|
||||||
|
}
|
||||||
|
else if (strcmp (key, "taskbar_sort_order") == 0) {
|
||||||
|
if (strcmp(value, "center") == 0) {
|
||||||
|
taskbar_sort_method = TASKBAR_SORT_CENTER;
|
||||||
|
} else if (strcmp(value, "title") == 0) {
|
||||||
|
taskbar_sort_method = TASKBAR_SORT_TITLE;
|
||||||
|
} else {
|
||||||
|
taskbar_sort_method = TASKBAR_NOSORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Task */
|
/* Task */
|
||||||
else if (strcmp (key, "task_text") == 0)
|
else if (strcmp (key, "task_text") == 0)
|
||||||
@@ -489,34 +548,40 @@ void add_entry (char *key, char *value)
|
|||||||
}
|
}
|
||||||
else if (g_regex_match_simple("task.*_font_color", key, 0, 0)) {
|
else if (g_regex_match_simple("task.*_font_color", key, 0, 0)) {
|
||||||
gchar** split = g_regex_split_simple("_", key, 0, 0);
|
gchar** split = g_regex_split_simple("_", key, 0, 0);
|
||||||
int status = get_task_status(split[1]);
|
int status = g_strv_length(split) == 3 ? TASK_NORMAL : get_task_status(split[1]);
|
||||||
g_strfreev(split);
|
g_strfreev(split);
|
||||||
extract_values(value, &value1, &value2, &value3);
|
if (status >= 0) {
|
||||||
float alpha = 1;
|
extract_values(value, &value1, &value2, &value3);
|
||||||
if (value2) alpha = (atoi (value2) / 100.0);
|
float alpha = 1;
|
||||||
get_color (value1, panel_config.g_task.font[status].color);
|
if (value2) alpha = (atoi (value2) / 100.0);
|
||||||
panel_config.g_task.font[status].alpha = alpha;
|
get_color (value1, panel_config.g_task.font[status].color);
|
||||||
panel_config.g_task.config_font_mask |= (1<<status);
|
panel_config.g_task.font[status].alpha = alpha;
|
||||||
|
panel_config.g_task.config_font_mask |= (1<<status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (g_regex_match_simple("task.*_icon_asb", key, 0, 0)) {
|
else if (g_regex_match_simple("task.*_icon_asb", key, 0, 0)) {
|
||||||
gchar** split = g_regex_split_simple("_", key, 0, 0);
|
gchar** split = g_regex_split_simple("_", key, 0, 0);
|
||||||
int status = get_task_status(split[1]);
|
int status = g_strv_length(split) == 3 ? TASK_NORMAL : get_task_status(split[1]);
|
||||||
g_strfreev(split);
|
g_strfreev(split);
|
||||||
extract_values(value, &value1, &value2, &value3);
|
if (status >= 0) {
|
||||||
panel_config.g_task.alpha[status] = atoi(value1);
|
extract_values(value, &value1, &value2, &value3);
|
||||||
panel_config.g_task.saturation[status] = atoi(value2);
|
panel_config.g_task.alpha[status] = atoi(value1);
|
||||||
panel_config.g_task.brightness[status] = atoi(value3);
|
panel_config.g_task.saturation[status] = atoi(value2);
|
||||||
panel_config.g_task.config_asb_mask |= (1<<status);
|
panel_config.g_task.brightness[status] = atoi(value3);
|
||||||
|
panel_config.g_task.config_asb_mask |= (1<<status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (g_regex_match_simple("task.*_background_id", key, 0, 0)) {
|
else if (g_regex_match_simple("task.*_background_id", key, 0, 0)) {
|
||||||
gchar** split = g_regex_split_simple("_", key, 0, 0);
|
gchar** split = g_regex_split_simple("_", key, 0, 0);
|
||||||
int status = get_task_status(split[1]);
|
int status = g_strv_length(split) == 3 ? TASK_NORMAL : get_task_status(split[1]);
|
||||||
g_strfreev(split);
|
g_strfreev(split);
|
||||||
int id = atoi (value);
|
if (status >= 0) {
|
||||||
id = (id < backgrounds->len && id >= 0) ? id : 0;
|
int id = atoi (value);
|
||||||
panel_config.g_task.background[status] = &g_array_index(backgrounds, Background, id);
|
id = (id < backgrounds->len && id >= 0) ? id : 0;
|
||||||
panel_config.g_task.config_background_mask |= (1<<status);
|
panel_config.g_task.background[status] = &g_array_index(backgrounds, Background, id);
|
||||||
if (status == TASK_NORMAL) panel_config.g_task.area.bg = panel_config.g_task.background[TASK_NORMAL];
|
panel_config.g_task.config_background_mask |= (1<<status);
|
||||||
|
if (status == TASK_NORMAL) panel_config.g_task.area.bg = panel_config.g_task.background[TASK_NORMAL];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// "tooltip" is deprecated but here for backwards compatibility
|
// "tooltip" is deprecated but here for backwards compatibility
|
||||||
else if (strcmp (key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0)
|
else if (strcmp (key, "task_tooltip") == 0 || strcmp(key, "tooltip") == 0)
|
||||||
@@ -527,12 +592,13 @@ void add_entry (char *key, char *value)
|
|||||||
if (new_config_file == 0 && systray_enabled == 0) {
|
if (new_config_file == 0 && systray_enabled == 0) {
|
||||||
systray_enabled = 1;
|
systray_enabled = 1;
|
||||||
if (panel_items_order) {
|
if (panel_items_order) {
|
||||||
char* tmp = g_strconcat(panel_items_order, "S", NULL);
|
gchar* tmp = g_strconcat(panel_items_order, "S", NULL);
|
||||||
g_free( panel_items_order );
|
free(panel_items_order);
|
||||||
panel_items_order = tmp;
|
panel_items_order = strdup(tmp);
|
||||||
|
g_free(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
panel_items_order = g_strdup("S");
|
panel_items_order = strdup("S");
|
||||||
}
|
}
|
||||||
extract_values(value, &value1, &value2, &value3);
|
extract_values(value, &value1, &value2, &value3);
|
||||||
systray.area.paddingxlr = systray.area.paddingx = atoi (value1);
|
systray.area.paddingxlr = systray.area.paddingx = atoi (value1);
|
||||||
@@ -563,6 +629,9 @@ void add_entry (char *key, char *value)
|
|||||||
systray.saturation = atoi(value2);
|
systray.saturation = atoi(value2);
|
||||||
systray.brightness = atoi(value3);
|
systray.brightness = atoi(value3);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(key, "systray_monitor") == 0) {
|
||||||
|
systray_monitor = atoi(value) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Launcher */
|
/* Launcher */
|
||||||
else if (strcmp (key, "launcher_padding") == 0) {
|
else if (strcmp (key, "launcher_padding") == 0) {
|
||||||
@@ -580,13 +649,19 @@ void add_entry (char *key, char *value)
|
|||||||
launcher_max_icon_size = atoi(value);
|
launcher_max_icon_size = atoi(value);
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "launcher_item_app") == 0) {
|
else if (strcmp(key, "launcher_item_app") == 0) {
|
||||||
char *app = strdup(value);
|
char *app = expand_tilde(value);
|
||||||
panel_config.launcher.list_apps = g_slist_append(panel_config.launcher.list_apps, app);
|
panel_config.launcher.list_apps = g_slist_append(panel_config.launcher.list_apps, app);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(key, "launcher_apps_dir") == 0) {
|
||||||
|
char *path = expand_tilde(value);
|
||||||
|
load_launcher_app_dir(path);
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
else if (strcmp(key, "launcher_icon_theme") == 0) {
|
else if (strcmp(key, "launcher_icon_theme") == 0) {
|
||||||
// if XSETTINGS manager running, tint2 use it.
|
// if XSETTINGS manager running, tint2 use it.
|
||||||
if (!icon_theme_name)
|
if (icon_theme_name_config)
|
||||||
icon_theme_name = strdup(value);
|
free(icon_theme_name_config);
|
||||||
|
icon_theme_name_config = strdup(value);
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "launcher_icon_asb") == 0) {
|
else if (strcmp(key, "launcher_icon_asb") == 0) {
|
||||||
extract_values(value, &value1, &value2, &value3);
|
extract_values(value, &value1, &value2, &value3);
|
||||||
@@ -597,6 +672,9 @@ void add_entry (char *key, char *value)
|
|||||||
else if (strcmp(key, "launcher_tooltip") == 0) {
|
else if (strcmp(key, "launcher_tooltip") == 0) {
|
||||||
launcher_tooltip_enabled = atoi(value);
|
launcher_tooltip_enabled = atoi(value);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(key, "startup_notifications") == 0) {
|
||||||
|
startup_notifications = atoi(value);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tooltip */
|
/* Tooltip */
|
||||||
else if (strcmp (key, "tooltip_show_timeout") == 0) {
|
else if (strcmp (key, "tooltip_show_timeout") == 0) {
|
||||||
@@ -628,6 +706,8 @@ void add_entry (char *key, char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mouse actions */
|
/* Mouse actions */
|
||||||
|
else if (strcmp (key, "mouse_left") == 0)
|
||||||
|
get_action (value, &mouse_left);
|
||||||
else if (strcmp (key, "mouse_middle") == 0)
|
else if (strcmp (key, "mouse_middle") == 0)
|
||||||
get_action (value, &mouse_middle);
|
get_action (value, &mouse_middle);
|
||||||
else if (strcmp (key, "mouse_right") == 0)
|
else if (strcmp (key, "mouse_right") == 0)
|
||||||
@@ -666,29 +746,33 @@ void add_entry (char *key, char *value)
|
|||||||
systray_enabled = atoi(value);
|
systray_enabled = atoi(value);
|
||||||
if (systray_enabled) {
|
if (systray_enabled) {
|
||||||
if (panel_items_order) {
|
if (panel_items_order) {
|
||||||
char* tmp = g_strconcat(panel_items_order, "S", NULL);
|
gchar* tmp = g_strconcat(panel_items_order, "S", NULL);
|
||||||
g_free( panel_items_order );
|
free(panel_items_order);
|
||||||
panel_items_order = tmp;
|
panel_items_order = strdup(tmp);
|
||||||
|
g_free(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
panel_items_order = g_strdup("S");
|
panel_items_order = strdup("S");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_BATTERY
|
||||||
else if (strcmp(key, "battery") == 0) {
|
else if (strcmp(key, "battery") == 0) {
|
||||||
if (new_config_file == 0) {
|
if (new_config_file == 0) {
|
||||||
battery_enabled = atoi(value);
|
battery_enabled = atoi(value);
|
||||||
if (battery_enabled) {
|
if (battery_enabled) {
|
||||||
if (panel_items_order) {
|
if (panel_items_order) {
|
||||||
char* tmp = g_strconcat(panel_items_order, "B", NULL);
|
gchar* tmp = g_strconcat(panel_items_order, "B", NULL);
|
||||||
g_free( panel_items_order );
|
free(panel_items_order);
|
||||||
panel_items_order = tmp;
|
panel_items_order = strdup(tmp);
|
||||||
|
g_free(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
panel_items_order = g_strdup("B");
|
panel_items_order = strdup("B");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
fprintf(stderr, "tint2 : invalid option \"%s\",\n upgrade tint2 or correct your config file\n", key);
|
fprintf(stderr, "tint2 : invalid option \"%s\",\n upgrade tint2 or correct your config file\n", key);
|
||||||
|
|
||||||
@@ -701,7 +785,7 @@ void add_entry (char *key, char *value)
|
|||||||
int config_read ()
|
int config_read ()
|
||||||
{
|
{
|
||||||
const gchar * const * system_dirs;
|
const gchar * const * system_dirs;
|
||||||
char *path1;
|
gchar *path1;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
// follow XDG specification
|
// follow XDG specification
|
||||||
@@ -716,19 +800,19 @@ int config_read ()
|
|||||||
g_free(path1);
|
g_free(path1);
|
||||||
|
|
||||||
// copy tint2rc from system directory to user directory
|
// copy tint2rc from system directory to user directory
|
||||||
char *path2 = 0;
|
gchar *path2 = 0;
|
||||||
system_dirs = g_get_system_config_dirs();
|
system_dirs = g_get_system_config_dirs();
|
||||||
for (i = 0; system_dirs[i]; i++) {
|
for (i = 0; system_dirs[i]; i++) {
|
||||||
path2 = g_build_filename(system_dirs[i], "tint2", "tint2rc", NULL);
|
path2 = g_build_filename(system_dirs[i], "tint2", "tint2rc", NULL);
|
||||||
|
|
||||||
if (g_file_test(path2, G_FILE_TEST_EXISTS)) break;
|
if (g_file_test(path2, G_FILE_TEST_EXISTS)) break;
|
||||||
g_free (path2);
|
g_free(path2);
|
||||||
path2 = 0;
|
path2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path2) {
|
if (path2) {
|
||||||
// copy file in user directory (path1)
|
// copy file in user directory (path1)
|
||||||
char *dir = g_build_filename (g_get_user_config_dir(), "tint2", NULL);
|
gchar *dir = g_build_filename (g_get_user_config_dir(), "tint2", NULL);
|
||||||
if (!g_file_test (dir, G_FILE_TEST_IS_DIR)) g_mkdir(dir, 0777);
|
if (!g_file_test (dir, G_FILE_TEST_IS_DIR)) g_mkdir(dir, 0777);
|
||||||
g_free(dir);
|
g_free(dir);
|
||||||
|
|
||||||
@@ -766,16 +850,17 @@ int config_read_file (const char *path)
|
|||||||
if (new_config_file == 0) {
|
if (new_config_file == 0) {
|
||||||
taskbar_enabled = 1;
|
taskbar_enabled = 1;
|
||||||
if (panel_items_order) {
|
if (panel_items_order) {
|
||||||
char* tmp = g_strconcat( "T", panel_items_order, NULL );
|
gchar* tmp = g_strconcat("T", panel_items_order, NULL);
|
||||||
g_free(panel_items_order);
|
free(panel_items_order);
|
||||||
panel_items_order = tmp;
|
panel_items_order = strdup(tmp);
|
||||||
|
g_free(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
panel_items_order = g_strdup("T");
|
panel_items_order = strdup("T");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
187
src/launcher/apps-common.c
Normal file
187
src/launcher/apps-common.c
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* Tint2 : .desktop file handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 (mrovi9000@gmail.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/* http://standards.freedesktop.org/desktop-entry-spec/ */
|
||||||
|
|
||||||
|
#include "apps-common.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int parse_dektop_line(char *line, char **key, char **value)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int found = 0;
|
||||||
|
*key = line;
|
||||||
|
for (p = line; *p; p++) {
|
||||||
|
if (*p == '=') {
|
||||||
|
*value = p + 1;
|
||||||
|
*p = 0;
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
return 0;
|
||||||
|
if (found && (strlen(*key) == 0 || strlen(*value) == 0))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void expand_exec(DesktopEntry *entry, const char *path)
|
||||||
|
{
|
||||||
|
// Expand % in exec
|
||||||
|
// %i -> --icon Icon
|
||||||
|
// %c -> Name
|
||||||
|
// %k -> path
|
||||||
|
if (entry->exec) {
|
||||||
|
char *exec2 = calloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) + (entry->icon ? strlen(entry->icon) : 1) + 100, 1);
|
||||||
|
char *p, *q;
|
||||||
|
// p will never point to an escaped char
|
||||||
|
for (p = entry->exec, q = exec2; *p; p++, q++) {
|
||||||
|
*q = *p; // Copy
|
||||||
|
if (*p == '\\') {
|
||||||
|
p++, q++;
|
||||||
|
// Copy the escaped char
|
||||||
|
if (*p == '%') // For % we delete the backslash, i.e. write % over it
|
||||||
|
q--;
|
||||||
|
*q = *p;
|
||||||
|
if (!*p) break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*p == '%') {
|
||||||
|
p++;
|
||||||
|
if (!*p) break;
|
||||||
|
if (*p == 'i' && entry->icon != NULL) {
|
||||||
|
sprintf(q, "--icon '%s'", entry->icon);
|
||||||
|
q += strlen("--icon ''");
|
||||||
|
q += strlen(entry->icon);
|
||||||
|
q--; // To balance the q++ in the for
|
||||||
|
} else if (*p == 'c' && entry->name != NULL) {
|
||||||
|
sprintf(q, "'%s'", entry->name);
|
||||||
|
q += strlen("''");
|
||||||
|
q += strlen(entry->name);
|
||||||
|
q--; // To balance the q++ in the for
|
||||||
|
} else if (*p == 'c') {
|
||||||
|
sprintf(q, "'%s'", path);
|
||||||
|
q += strlen("''");
|
||||||
|
q += strlen(path);
|
||||||
|
q--; // To balance the q++ in the for
|
||||||
|
} else {
|
||||||
|
// We don't care about other expansions
|
||||||
|
q--; // Delete the last % from q
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*q = '\0';
|
||||||
|
free(entry->exec);
|
||||||
|
entry->exec = exec2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_desktop_file(const char *path, DesktopEntry *entry)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char *line = NULL;
|
||||||
|
size_t line_size;
|
||||||
|
char *key, *value;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
entry->name = entry->icon = entry->exec = NULL;
|
||||||
|
|
||||||
|
if ((fp = fopen(path, "rt")) == NULL) {
|
||||||
|
fprintf(stderr, "Could not open file %s\n", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar **languages = (gchar **)g_get_language_names();
|
||||||
|
// lang_index is the index of the language for the best Name key in the language vector
|
||||||
|
// lang_index_default is a constant that encodes the Name key without a language
|
||||||
|
int lang_index, lang_index_default;
|
||||||
|
#define LANG_DBG 0
|
||||||
|
if (LANG_DBG) printf("Languages:");
|
||||||
|
for (i = 0; languages[i]; i++) {
|
||||||
|
if (LANG_DBG) printf(" %s", languages[i]);
|
||||||
|
}
|
||||||
|
if (LANG_DBG) printf("\n");
|
||||||
|
lang_index_default = i;
|
||||||
|
// we currently do not know about any Name key at all, so use an invalid index
|
||||||
|
lang_index = lang_index_default + 1;
|
||||||
|
|
||||||
|
int inside_desktop_entry = 0;
|
||||||
|
while (getline(&line, &line_size, fp) >= 0) {
|
||||||
|
int len = strlen(line);
|
||||||
|
if (len == 0)
|
||||||
|
continue;
|
||||||
|
line[len - 1] = '\0';
|
||||||
|
if (line[0] == '[') {
|
||||||
|
inside_desktop_entry = (strcmp(line, "[Desktop Entry]") == 0);
|
||||||
|
}
|
||||||
|
if (inside_desktop_entry && parse_dektop_line(line, &key, &value)) {
|
||||||
|
if (strstr(key, "Name") == key) {
|
||||||
|
if (strcmp(key, "Name") == 0 && lang_index > lang_index_default) {
|
||||||
|
entry->name = strdup(value);
|
||||||
|
lang_index = lang_index_default;
|
||||||
|
} else {
|
||||||
|
for (i = 0; languages[i] && i < lang_index; i++) {
|
||||||
|
gchar *localized_key = g_strdup_printf("Name[%s]", languages[i]);
|
||||||
|
if (strcmp(key, localized_key) == 0) {
|
||||||
|
if (entry->name)
|
||||||
|
free(entry->name);
|
||||||
|
entry->name = strdup(value);
|
||||||
|
lang_index = i;
|
||||||
|
}
|
||||||
|
g_free(localized_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!entry->exec && strcmp(key, "Exec") == 0) {
|
||||||
|
entry->exec = strdup(value);
|
||||||
|
} else if (!entry->icon && strcmp(key, "Icon") == 0) {
|
||||||
|
entry->icon = strdup(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose (fp);
|
||||||
|
// From this point:
|
||||||
|
// entry->name, entry->icon, entry->exec will never be empty strings (can be NULL though)
|
||||||
|
|
||||||
|
expand_exec(entry, path);
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_desktop_entry(DesktopEntry *entry)
|
||||||
|
{
|
||||||
|
free(entry->name);
|
||||||
|
free(entry->icon);
|
||||||
|
free(entry->exec);
|
||||||
|
entry->name = entry->icon = entry->exec = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_read_desktop_file()
|
||||||
|
{
|
||||||
|
fprintf(stdout, "\033[1;33m");
|
||||||
|
DesktopEntry entry;
|
||||||
|
read_desktop_file("/usr/share/applications/firefox.desktop", &entry);
|
||||||
|
printf("Name:%s Icon:%s Exec:%s\n", entry.name, entry.icon, entry.exec);
|
||||||
|
fprintf(stdout, "\033[0m");
|
||||||
|
}
|
||||||
29
src/launcher/apps-common.h
Normal file
29
src/launcher/apps-common.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* Copyright (C) 2015 (mrovi9000@gmail.com)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef APPS_COMMON_H
|
||||||
|
#define APPS_COMMON_H
|
||||||
|
|
||||||
|
typedef struct DesktopEntry {
|
||||||
|
char *name;
|
||||||
|
char *exec;
|
||||||
|
char *icon;
|
||||||
|
} DesktopEntry;
|
||||||
|
|
||||||
|
// Parses a line of the form "key = value". Modifies the line.
|
||||||
|
// Returns 1 if successful, and parts are not empty.
|
||||||
|
// Key and value point to the parts.
|
||||||
|
int parse_dektop_line(char *line, char **key, char **value);
|
||||||
|
|
||||||
|
// Reads the .desktop file from the given path into the DesktopEntry entry.
|
||||||
|
// The DesktopEntry object must be initially empty.
|
||||||
|
// Returns 1 if successful.
|
||||||
|
int read_desktop_file(const char *path, DesktopEntry *entry);
|
||||||
|
|
||||||
|
// Empties DesktopEntry: releases the memory of the *members* of entry.
|
||||||
|
void free_desktop_entry(DesktopEntry *entry);
|
||||||
|
|
||||||
|
#endif
|
||||||
660
src/launcher/icon-theme-common.c
Normal file
660
src/launcher/icon-theme-common.c
Normal file
@@ -0,0 +1,660 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* Tint2 : Icon theme handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 (mrovi9000@gmail.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/* http://standards.freedesktop.org/icon-theme-spec/ */
|
||||||
|
|
||||||
|
#include "icon-theme-common.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "apps-common.h"
|
||||||
|
|
||||||
|
#define ICON_DIR_TYPE_SCALABLE 0
|
||||||
|
#define ICON_DIR_TYPE_FIXED 1
|
||||||
|
#define ICON_DIR_TYPE_THRESHOLD 2
|
||||||
|
typedef struct IconThemeDir {
|
||||||
|
char *name;
|
||||||
|
int size;
|
||||||
|
int type;
|
||||||
|
int max_size;
|
||||||
|
int min_size;
|
||||||
|
int threshold;
|
||||||
|
} IconThemeDir;
|
||||||
|
|
||||||
|
|
||||||
|
int parse_theme_line(char *line, char **key, char **value)
|
||||||
|
{
|
||||||
|
return parse_dektop_line(line, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSList *icon_locations = NULL;
|
||||||
|
// Do not free the result.
|
||||||
|
const GSList *get_icon_locations()
|
||||||
|
{
|
||||||
|
if (icon_locations)
|
||||||
|
return icon_locations;
|
||||||
|
|
||||||
|
gchar *path;
|
||||||
|
path = g_build_filename(g_get_home_dir(), ".icons", NULL);
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup(path));
|
||||||
|
g_free(path);
|
||||||
|
path = g_build_filename(g_get_home_dir(), ".local/share/icons", NULL);
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup(path));
|
||||||
|
g_free(path);
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup("/usr/local/share/icons"));
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup("/usr/local/share/pixmaps"));
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup("/usr/share/icons"));
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup("/usr/share/pixmaps"));
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup("/opt/share/icons"));
|
||||||
|
icon_locations = g_slist_append(icon_locations, g_strdup("/opt/share/pixmaps"));
|
||||||
|
return icon_locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
IconTheme *make_theme(char *name)
|
||||||
|
{
|
||||||
|
IconTheme *theme = calloc(1, sizeof(IconTheme));
|
||||||
|
theme->name = strdup(name);
|
||||||
|
theme->list_inherits = NULL;
|
||||||
|
theme->list_directories = NULL;
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Use UTF8 when parsing the file
|
||||||
|
IconTheme *load_theme_from_index(char *file_name, char *name)
|
||||||
|
{
|
||||||
|
IconTheme *theme;
|
||||||
|
FILE *f;
|
||||||
|
char *line = NULL;
|
||||||
|
size_t line_size;
|
||||||
|
|
||||||
|
if ((f = fopen(file_name, "rt")) == NULL) {
|
||||||
|
fprintf(stderr, "Could not open theme '%s'\n", file_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
theme = make_theme(name);
|
||||||
|
|
||||||
|
IconThemeDir *current_dir = NULL;
|
||||||
|
int inside_header = 1;
|
||||||
|
while (getline(&line, &line_size, f) >= 0) {
|
||||||
|
char *key, *value;
|
||||||
|
|
||||||
|
int line_len = strlen(line);
|
||||||
|
if (line_len >= 1) {
|
||||||
|
if (line[line_len - 1] == '\n') {
|
||||||
|
line[line_len - 1] = '\0';
|
||||||
|
line_len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (inside_header) {
|
||||||
|
if (parse_theme_line(line, &key, &value)) {
|
||||||
|
if (strcmp(key, "Inherits") == 0) {
|
||||||
|
// value is like oxygen,wood,default
|
||||||
|
char *token;
|
||||||
|
token = strtok(value, ",\n");
|
||||||
|
while (token != NULL) {
|
||||||
|
theme->list_inherits = g_slist_append(theme->list_inherits, strdup(token));
|
||||||
|
token = strtok(NULL, ",\n");
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "Directories") == 0) {
|
||||||
|
// value is like 48x48/apps,48x48/mimetypes,32x32/apps,scalable/apps,scalable/mimetypes
|
||||||
|
char *token;
|
||||||
|
token = strtok(value, ",\n");
|
||||||
|
while (token != NULL) {
|
||||||
|
IconThemeDir *dir = calloc(1, sizeof(IconThemeDir));
|
||||||
|
dir->name = strdup(token);
|
||||||
|
dir->max_size = dir->min_size = dir->size = -1;
|
||||||
|
dir->type = ICON_DIR_TYPE_THRESHOLD;
|
||||||
|
dir->threshold = 2;
|
||||||
|
theme->list_directories = g_slist_append(theme->list_directories, dir);
|
||||||
|
token = strtok(NULL, ",\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (current_dir != NULL) {
|
||||||
|
if (parse_theme_line(line, &key, &value)) {
|
||||||
|
if (strcmp(key, "Size") == 0) {
|
||||||
|
// value is like 24
|
||||||
|
sscanf(value, "%d", ¤t_dir->size);
|
||||||
|
if (current_dir->max_size == -1)
|
||||||
|
current_dir->max_size = current_dir->size;
|
||||||
|
if (current_dir->min_size == -1)
|
||||||
|
current_dir->min_size = current_dir->size;
|
||||||
|
} else if (strcmp(key, "MaxSize") == 0) {
|
||||||
|
// value is like 24
|
||||||
|
sscanf(value, "%d", ¤t_dir->max_size);
|
||||||
|
} else if (strcmp(key, "MinSize") == 0) {
|
||||||
|
// value is like 24
|
||||||
|
sscanf(value, "%d", ¤t_dir->min_size);
|
||||||
|
} else if (strcmp(key, "Threshold") == 0) {
|
||||||
|
// value is like 2
|
||||||
|
sscanf(value, "%d", ¤t_dir->threshold);
|
||||||
|
} else if (strcmp(key, "Type") == 0) {
|
||||||
|
// value is Fixed, Scalable or Threshold : default to scalable for unknown Type.
|
||||||
|
if (strcmp(value, "Fixed") == 0) {
|
||||||
|
current_dir->type = ICON_DIR_TYPE_FIXED;
|
||||||
|
} else if (strcmp(value, "Threshold") == 0) {
|
||||||
|
current_dir->type = ICON_DIR_TYPE_THRESHOLD;
|
||||||
|
} else {
|
||||||
|
current_dir->type = ICON_DIR_TYPE_SCALABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line[0] == '[' && line[line_len - 1] == ']' && strcmp(line, "[Icon Theme]") != 0) {
|
||||||
|
inside_header = 0;
|
||||||
|
current_dir = NULL;
|
||||||
|
line[line_len - 1] = '\0';
|
||||||
|
char *dir_name = line + 1;
|
||||||
|
GSList* dir_item = theme->list_directories;
|
||||||
|
while (dir_item != NULL)
|
||||||
|
{
|
||||||
|
IconThemeDir *dir = dir_item->data;
|
||||||
|
if (strcmp(dir->name, dir_name) == 0) {
|
||||||
|
current_dir = dir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dir_item = g_slist_next(dir_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_theme_from_fs_dir(IconTheme *theme, char *dir_name)
|
||||||
|
{
|
||||||
|
gchar *file_name = g_build_filename(dir_name, "index.theme", NULL);
|
||||||
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_free(file_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDir *d = g_dir_open(dir_name, 0, NULL);
|
||||||
|
if (d) {
|
||||||
|
const gchar *size_name;
|
||||||
|
while ((size_name = g_dir_read_name(d))) {
|
||||||
|
gchar *full_size_name = g_build_filename(dir_name, size_name, NULL);
|
||||||
|
if (g_file_test(file_name, G_FILE_TEST_IS_DIR)) {
|
||||||
|
int size, size2;
|
||||||
|
if ((sscanf(size_name, "%dx%d", &size, &size2) == 2 && size == size2) ||
|
||||||
|
(sscanf(size_name, "%d", &size) == 1)) {
|
||||||
|
GDir *dSize = g_dir_open(full_size_name, 0, NULL);
|
||||||
|
if (dSize) {
|
||||||
|
const gchar *subdir_name;
|
||||||
|
while ((subdir_name = g_dir_read_name(dSize))) {
|
||||||
|
IconThemeDir *dir = calloc(1, sizeof(IconThemeDir));
|
||||||
|
// value is like 48x48/apps
|
||||||
|
gchar *value = g_build_filename(size_name, subdir_name, NULL);
|
||||||
|
dir->name = strdup(value);
|
||||||
|
g_free(value);
|
||||||
|
dir->max_size = dir->min_size = dir->size = size;
|
||||||
|
dir->type = ICON_DIR_TYPE_FIXED;
|
||||||
|
theme->list_directories = g_slist_append(theme->list_directories, dir);
|
||||||
|
}
|
||||||
|
g_dir_close(dSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free(full_size_name);
|
||||||
|
}
|
||||||
|
g_dir_close(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconTheme *load_theme_from_fs(char *name, IconTheme *theme)
|
||||||
|
{
|
||||||
|
gchar *dir_name = NULL;
|
||||||
|
const GSList *location;
|
||||||
|
for (location = get_icon_locations(); location; location = g_slist_next(location)) {
|
||||||
|
gchar *path = (gchar*) location->data;
|
||||||
|
dir_name = g_build_filename(path, name, NULL);
|
||||||
|
if (g_file_test(dir_name, G_FILE_TEST_IS_DIR)) {
|
||||||
|
if (!theme) {
|
||||||
|
theme = make_theme(name);
|
||||||
|
}
|
||||||
|
load_theme_from_fs_dir(theme, dir_name);
|
||||||
|
}
|
||||||
|
g_free(dir_name);
|
||||||
|
dir_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
IconTheme *load_theme(char *name)
|
||||||
|
{
|
||||||
|
// Look for name/index.theme in $HOME/.icons, /usr/share/icons, /usr/share/pixmaps (stop at the first found)
|
||||||
|
// Parse index.theme -> list of IconThemeDir with attributes
|
||||||
|
// Return IconTheme*
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
gchar *file_name = NULL;
|
||||||
|
const GSList *location;
|
||||||
|
for (location = get_icon_locations(); location; location = g_slist_next(location)) {
|
||||||
|
gchar *path = (gchar*) location->data;
|
||||||
|
file_name = g_build_filename(path, name, "index.theme", NULL);
|
||||||
|
if (!g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_free(file_name);
|
||||||
|
file_name = NULL;
|
||||||
|
}
|
||||||
|
if (file_name)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IconTheme *theme = NULL;
|
||||||
|
if (file_name) {
|
||||||
|
theme = load_theme_from_index(file_name, name);
|
||||||
|
g_free(file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return load_theme_from_fs(name, theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_icon_theme(IconTheme *theme)
|
||||||
|
{
|
||||||
|
if (!theme)
|
||||||
|
return;
|
||||||
|
free(theme->name);
|
||||||
|
theme->name = NULL;
|
||||||
|
GSList *l_inherits;
|
||||||
|
for (l_inherits = theme->list_inherits; l_inherits ; l_inherits = l_inherits->next) {
|
||||||
|
free(l_inherits->data);
|
||||||
|
}
|
||||||
|
g_slist_free(theme->list_inherits);
|
||||||
|
theme->list_inherits = NULL;
|
||||||
|
GSList *l_dir;
|
||||||
|
for (l_dir = theme->list_directories; l_dir ; l_dir = l_dir->next) {
|
||||||
|
IconThemeDir *dir = (IconThemeDir *)l_dir->data;
|
||||||
|
free(dir->name);
|
||||||
|
free(l_dir->data);
|
||||||
|
}
|
||||||
|
g_slist_free(theme->list_directories);
|
||||||
|
theme->list_directories = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_themes(IconThemeWrapper *themes)
|
||||||
|
{
|
||||||
|
if (!themes)
|
||||||
|
return;
|
||||||
|
GSList *l;
|
||||||
|
for (l = themes->themes; l ; l = l->next) {
|
||||||
|
IconTheme *theme = (IconTheme*) l->data;
|
||||||
|
free_icon_theme(theme);
|
||||||
|
free(theme);
|
||||||
|
}
|
||||||
|
g_slist_free(themes->themes);
|
||||||
|
for (l = themes->themes_fallback; l ; l = l->next) {
|
||||||
|
IconTheme *theme = (IconTheme*) l->data;
|
||||||
|
free_icon_theme(theme);
|
||||||
|
free(theme);
|
||||||
|
}
|
||||||
|
g_slist_free(themes->themes_fallback);
|
||||||
|
free(themes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_launcher_read_theme_file()
|
||||||
|
{
|
||||||
|
fprintf(stdout, "\033[1;33m");
|
||||||
|
IconTheme *theme = load_theme("oxygen");
|
||||||
|
if (!theme) {
|
||||||
|
printf("Could not load theme\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("Loaded theme: %s\n", theme->name);
|
||||||
|
GSList* item = theme->list_inherits;
|
||||||
|
while (item != NULL)
|
||||||
|
{
|
||||||
|
printf("Inherits:%s\n", (char*)item->data);
|
||||||
|
item = g_slist_next(item);
|
||||||
|
}
|
||||||
|
item = theme->list_directories;
|
||||||
|
while (item != NULL)
|
||||||
|
{
|
||||||
|
IconThemeDir *dir = item->data;
|
||||||
|
printf("Dir:%s Size=%d MinSize=%d MaxSize=%d Threshold=%d Type=%s\n",
|
||||||
|
dir->name, dir->size, dir->min_size, dir->max_size, dir->threshold,
|
||||||
|
dir->type == ICON_DIR_TYPE_FIXED ? "Fixed" :
|
||||||
|
dir->type == ICON_DIR_TYPE_SCALABLE ? "Scalable" :
|
||||||
|
dir->type == ICON_DIR_TYPE_THRESHOLD ? "Threshold" : "?????");
|
||||||
|
item = g_slist_next(item);
|
||||||
|
}
|
||||||
|
fprintf(stdout, "\033[0m");
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean str_list_contains(const GSList *list, const char *value)
|
||||||
|
{
|
||||||
|
const GSList* item = list;
|
||||||
|
while (item != NULL) {
|
||||||
|
if (g_str_equal(item->data, value)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
item = g_slist_next(item);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_themes_helper(const char *name, GSList **themes, GSList **queued)
|
||||||
|
{
|
||||||
|
if (str_list_contains(*queued, name))
|
||||||
|
return;
|
||||||
|
GSList *queue = g_slist_append(NULL, strdup(name));
|
||||||
|
*queued = g_slist_append(*queued, strdup(name));
|
||||||
|
|
||||||
|
// Load wrapper->themes
|
||||||
|
while (queue) {
|
||||||
|
char *name = queue->data;
|
||||||
|
queue = g_slist_remove(queue, name);
|
||||||
|
|
||||||
|
fprintf(stderr, " '%s',", name);
|
||||||
|
IconTheme *theme = load_theme(name);
|
||||||
|
if (theme != NULL) {
|
||||||
|
*themes = g_slist_append(*themes, theme);
|
||||||
|
|
||||||
|
GSList* item = theme->list_inherits;
|
||||||
|
int pos = 0;
|
||||||
|
while (item != NULL)
|
||||||
|
{
|
||||||
|
char *parent = item->data;
|
||||||
|
if (!str_list_contains(*queued, parent)) {
|
||||||
|
queue = g_slist_insert(queue, strdup(parent), pos);
|
||||||
|
pos++;
|
||||||
|
*queued = g_slist_append(*queued, strdup(parent));
|
||||||
|
}
|
||||||
|
item = g_slist_next(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
// Free the queue
|
||||||
|
GSList *l;
|
||||||
|
for (l = queue; l ; l = l->next)
|
||||||
|
free(l->data);
|
||||||
|
g_slist_free(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconThemeWrapper *load_themes(const char *icon_theme_name)
|
||||||
|
{
|
||||||
|
IconThemeWrapper *wrapper = calloc(1, sizeof(IconThemeWrapper));
|
||||||
|
|
||||||
|
if (!icon_theme_name) {
|
||||||
|
fprintf(stderr, "Missing icon_theme_name theme, default to 'hicolor'.\n");
|
||||||
|
icon_theme_name = "hicolor";
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Loading %s. Icon theme :", icon_theme_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSList *queued = NULL;
|
||||||
|
load_themes_helper(icon_theme_name, &wrapper->themes, &queued);
|
||||||
|
load_themes_helper("hicolor", &wrapper->themes, &queued);
|
||||||
|
|
||||||
|
// Load wrapper->themes_fallback
|
||||||
|
const GSList *location;
|
||||||
|
for (location = get_icon_locations(); location; location = g_slist_next(location)) {
|
||||||
|
gchar *path = (gchar*) location->data;
|
||||||
|
GDir *d = g_dir_open(path, 0, NULL);
|
||||||
|
if (d) {
|
||||||
|
const gchar *name;
|
||||||
|
while ((name = g_dir_read_name(d))) {
|
||||||
|
gchar *file_name = g_build_filename(path, name, "index.theme", NULL);
|
||||||
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS) &&
|
||||||
|
!g_file_test(file_name, G_FILE_TEST_IS_DIR)) {
|
||||||
|
load_themes_helper(name, &wrapper->themes_fallback, &queued);
|
||||||
|
}
|
||||||
|
g_free(file_name);
|
||||||
|
}
|
||||||
|
g_dir_close(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the queued list
|
||||||
|
GSList *l;
|
||||||
|
for (l = queued; l ; l = l->next)
|
||||||
|
free(l->data);
|
||||||
|
g_slist_free(queued);
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
int directory_matches_size(IconThemeDir *dir, int size)
|
||||||
|
{
|
||||||
|
if (dir->type == ICON_DIR_TYPE_FIXED) {
|
||||||
|
return dir->size == size;
|
||||||
|
} else if (dir->type == ICON_DIR_TYPE_SCALABLE) {
|
||||||
|
return dir->min_size <= size && size <= dir->max_size;
|
||||||
|
} else /*if (dir->type == ICON_DIR_TYPE_THRESHOLD)*/ {
|
||||||
|
return dir->size - dir->threshold <= size && size <= dir->size + dir->threshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int directory_size_distance(IconThemeDir *dir, int size)
|
||||||
|
{
|
||||||
|
if (dir->type == ICON_DIR_TYPE_FIXED) {
|
||||||
|
return abs(dir->size - size);
|
||||||
|
} else if (dir->type == ICON_DIR_TYPE_SCALABLE) {
|
||||||
|
if (size < dir->min_size) {
|
||||||
|
return dir->min_size - size;
|
||||||
|
} else if (size > dir->max_size) {
|
||||||
|
return size - dir->max_size;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else /*if (dir->type == ICON_DIR_TYPE_THRESHOLD)*/ {
|
||||||
|
if (size < dir->size - dir->threshold) {
|
||||||
|
return dir->min_size - size;
|
||||||
|
} else if (size > dir->size + dir->threshold) {
|
||||||
|
return size - dir->max_size;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gint compare_theme_directories(gconstpointer a, gconstpointer b, gpointer size_query)
|
||||||
|
{
|
||||||
|
int size = GPOINTER_TO_INT(size_query);
|
||||||
|
const IconThemeDir *da = (const IconThemeDir*)a;
|
||||||
|
const IconThemeDir *db = (const IconThemeDir*)b;
|
||||||
|
return abs(da->size - size) - abs(db->size - size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEBUG_ICON_SEARCH 0
|
||||||
|
char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
||||||
|
{
|
||||||
|
if (icon_name == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// If the icon_name is already a path and the file exists, return it
|
||||||
|
if (strstr(icon_name, "/") == icon_name) {
|
||||||
|
if (g_file_test(icon_name, G_FILE_TEST_EXISTS))
|
||||||
|
return strdup(icon_name);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GSList *basenames = get_icon_locations();
|
||||||
|
GSList *extensions = NULL;
|
||||||
|
extensions = g_slist_append(extensions, ".png");
|
||||||
|
extensions = g_slist_append(extensions, ".xpm");
|
||||||
|
#ifdef HAVE_RSVG
|
||||||
|
extensions = g_slist_append(extensions, ".svg");
|
||||||
|
#endif
|
||||||
|
// if the icon name already contains one of the extensions (e.g. vlc.png instead of vlc) add a special entry
|
||||||
|
GSList *ext;
|
||||||
|
for (ext = extensions; ext; ext = g_slist_next(ext)) {
|
||||||
|
char *extension = (char*) ext->data;
|
||||||
|
if (strlen(icon_name) > strlen(extension) &&
|
||||||
|
strcmp(extension, icon_name + strlen(icon_name) - strlen(extension)) == 0) {
|
||||||
|
extensions = g_slist_append(extensions, "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GSList *theme;
|
||||||
|
|
||||||
|
// Best size match
|
||||||
|
// Contrary to the freedesktop spec, we are not choosing the closest icon in size, but the next larger icon
|
||||||
|
// otherwise the quality is usually crap (for size 22, if you can choose 16 or 32, you're better with 32)
|
||||||
|
// We do fallback to the closest size if we cannot find a larger or equal icon
|
||||||
|
|
||||||
|
// These 3 variables are used for keeping the closest size match
|
||||||
|
int minimal_size = INT_MAX;
|
||||||
|
char *best_file_name = NULL;
|
||||||
|
GSList *best_file_theme = NULL;
|
||||||
|
|
||||||
|
// These 3 variables are used for keeping the next larger match
|
||||||
|
int next_larger_size = -1;
|
||||||
|
char *next_larger = NULL;
|
||||||
|
GSList *next_larger_theme = NULL;
|
||||||
|
|
||||||
|
for (theme = themes; theme; theme = g_slist_next(theme)) {
|
||||||
|
((IconTheme*)theme->data)->list_directories = g_slist_sort_with_data(((IconTheme*)theme->data)->list_directories,
|
||||||
|
compare_theme_directories,
|
||||||
|
GINT_TO_POINTER(size));
|
||||||
|
GSList *dir;
|
||||||
|
for (dir = ((IconTheme*)theme->data)->list_directories; dir; dir = g_slist_next(dir)) {
|
||||||
|
// Closest match
|
||||||
|
gboolean possible = directory_size_distance((IconThemeDir*)dir->data, size) < minimal_size &&
|
||||||
|
(!best_file_theme ? TRUE : theme == best_file_theme);
|
||||||
|
// Next larger match
|
||||||
|
possible = possible ||
|
||||||
|
(((IconThemeDir*)dir->data)->size >= size &&
|
||||||
|
(next_larger_size == -1 || ((IconThemeDir*)dir->data)->size < next_larger_size) &&
|
||||||
|
(!next_larger_theme ? 1 : theme == next_larger_theme));
|
||||||
|
if (!possible)
|
||||||
|
continue;
|
||||||
|
const GSList *base;
|
||||||
|
for (base = basenames; base; base = g_slist_next(base)) {
|
||||||
|
GSList *ext;
|
||||||
|
for (ext = extensions; ext; ext = g_slist_next(ext)) {
|
||||||
|
char *base_name = (char*) base->data;
|
||||||
|
char *theme_name = ((IconTheme*)theme->data)->name;
|
||||||
|
char *dir_name = ((IconThemeDir*)dir->data)->name;
|
||||||
|
char *extension = (char*) ext->data;
|
||||||
|
char *file_name = calloc(strlen(base_name) + strlen(theme_name) +
|
||||||
|
strlen(dir_name) + strlen(icon_name) + strlen(extension) + 100, 1);
|
||||||
|
// filename = directory/$(themename)/subdirectory/iconname.extension
|
||||||
|
sprintf(file_name, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
||||||
|
if (DEBUG_ICON_SEARCH)
|
||||||
|
printf("checking %s\n", file_name);
|
||||||
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
|
if (DEBUG_ICON_SEARCH)
|
||||||
|
printf("found: %s\n", file_name);
|
||||||
|
// Closest match
|
||||||
|
if (directory_size_distance((IconThemeDir*)dir->data, size) < minimal_size && (!best_file_theme ? 1 : theme == best_file_theme)) {
|
||||||
|
if (best_file_name) {
|
||||||
|
free(best_file_name);
|
||||||
|
best_file_name = NULL;
|
||||||
|
}
|
||||||
|
best_file_name = strdup(file_name);
|
||||||
|
minimal_size = directory_size_distance((IconThemeDir*)dir->data, size);
|
||||||
|
best_file_theme = theme;
|
||||||
|
if (DEBUG_ICON_SEARCH)
|
||||||
|
printf("best_file_name = %s; minimal_size = %d\n", best_file_name, minimal_size);
|
||||||
|
}
|
||||||
|
// Next larger match
|
||||||
|
if (((IconThemeDir*)dir->data)->size >= size &&
|
||||||
|
(next_larger_size == -1 || ((IconThemeDir*)dir->data)->size < next_larger_size) &&
|
||||||
|
(!next_larger_theme ? 1 : theme == next_larger_theme)) {
|
||||||
|
if (next_larger) {
|
||||||
|
free(next_larger);
|
||||||
|
next_larger = NULL;
|
||||||
|
}
|
||||||
|
next_larger = strdup(file_name);
|
||||||
|
next_larger_size = ((IconThemeDir*)dir->data)->size;
|
||||||
|
next_larger_theme = theme;
|
||||||
|
if (DEBUG_ICON_SEARCH)
|
||||||
|
printf("next_larger = %s; next_larger_size = %d\n", next_larger, next_larger_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (next_larger) {
|
||||||
|
g_slist_free(extensions);
|
||||||
|
free(best_file_name);
|
||||||
|
return next_larger;
|
||||||
|
}
|
||||||
|
if (best_file_name) {
|
||||||
|
g_slist_free(extensions);
|
||||||
|
return best_file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look in unthemed icons
|
||||||
|
{
|
||||||
|
const GSList *base;
|
||||||
|
for (base = basenames; base; base = g_slist_next(base)) {
|
||||||
|
GSList *ext;
|
||||||
|
for (ext = extensions; ext; ext = g_slist_next(ext)) {
|
||||||
|
char *base_name = (char*) base->data;
|
||||||
|
char *extension = (char*) ext->data;
|
||||||
|
char *file_name = calloc(strlen(base_name) + strlen(icon_name) +
|
||||||
|
strlen(extension) + 100, 1);
|
||||||
|
// filename = directory/iconname.extension
|
||||||
|
sprintf(file_name, "%s/%s%s", base_name, icon_name, extension);
|
||||||
|
if (DEBUG_ICON_SEARCH)
|
||||||
|
printf("checking %s\n", file_name);
|
||||||
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_slist_free(extensions);
|
||||||
|
return file_name;
|
||||||
|
} else {
|
||||||
|
free(file_name);
|
||||||
|
file_name = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free(extensions);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_icon_path(IconThemeWrapper *theme, const char *icon_name, int size)
|
||||||
|
{
|
||||||
|
if (!theme)
|
||||||
|
return NULL;
|
||||||
|
icon_name = icon_name ? icon_name : DEFAULT_ICON;
|
||||||
|
char *path = get_icon_path_helper(theme->themes, icon_name, size);
|
||||||
|
if (!path) {
|
||||||
|
path = get_icon_path_helper(theme->themes_fallback, icon_name, size);
|
||||||
|
}
|
||||||
|
if (!path) {
|
||||||
|
fprintf(stderr, "Could not find icon %s\n", icon_name);
|
||||||
|
path = get_icon_path_helper(theme->themes, DEFAULT_ICON, size);
|
||||||
|
}
|
||||||
|
if (!path) {
|
||||||
|
path = get_icon_path_helper(theme->themes_fallback, DEFAULT_ICON, size);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
45
src/launcher/icon-theme-common.h
Normal file
45
src/launcher/icon-theme-common.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* Copyright (C) 2015 (mrovi9000@gmail.com)
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ICON_THEME_COMMON_H
|
||||||
|
#define ICON_THEME_COMMON_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
typedef struct IconThemeWrapper {
|
||||||
|
// List of IconTheme*
|
||||||
|
GSList *themes;
|
||||||
|
// List of IconTheme*
|
||||||
|
GSList *themes_fallback;
|
||||||
|
} IconThemeWrapper;
|
||||||
|
|
||||||
|
typedef struct IconTheme {
|
||||||
|
char *name;
|
||||||
|
GSList *list_inherits; // each item is a char* (theme name)
|
||||||
|
GSList *list_directories; // each item is an IconThemeDir*
|
||||||
|
} IconTheme;
|
||||||
|
|
||||||
|
// Parses a line of the form "key = value". Modifies the line.
|
||||||
|
// Returns 1 if successful, and parts are not empty.
|
||||||
|
// Key and value point to the parts.
|
||||||
|
int parse_theme_line(char *line, char **key, char **value);
|
||||||
|
|
||||||
|
// Returns an IconThemeWrapper* containing the icon theme identified by the name icon_theme_name, all the
|
||||||
|
// inherited themes, the hicolor theme and possibly fallback themes.
|
||||||
|
IconThemeWrapper *load_themes(const char *icon_theme_name);
|
||||||
|
|
||||||
|
void free_themes(IconThemeWrapper *themes);
|
||||||
|
|
||||||
|
#define DEFAULT_ICON "application-x-executable"
|
||||||
|
|
||||||
|
// Returns the full path to an icon file (or NULL) given the list of icon themes to search and the icon name
|
||||||
|
// Note: needs to be released with free().
|
||||||
|
char *get_icon_path(IconThemeWrapper *theme, const char *icon_name, int size);
|
||||||
|
|
||||||
|
// Returns a list of the directories used to store icons.
|
||||||
|
// Do not free the result, it is cached.
|
||||||
|
const GSList *get_icon_locations();
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -10,13 +10,14 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
#include "xsettings-client.h"
|
#include "xsettings-client.h"
|
||||||
|
#include "icon-theme-common.h"
|
||||||
|
|
||||||
typedef struct Launcher {
|
typedef struct Launcher {
|
||||||
// always start with area
|
// always start with area
|
||||||
Area area;
|
Area area;
|
||||||
GSList *list_apps; // List of char*, each is a path to a app.desktop file
|
GSList *list_apps; // List of char*, each is a path to a app.desktop file
|
||||||
GSList *list_icons; // List of LauncherIcon*
|
GSList *list_icons; // List of LauncherIcon*
|
||||||
GSList *list_themes; // List of IconTheme*
|
IconThemeWrapper *list_themes;
|
||||||
} Launcher;
|
} Launcher;
|
||||||
|
|
||||||
typedef struct LauncherIcon {
|
typedef struct LauncherIcon {
|
||||||
@@ -33,39 +34,16 @@ typedef struct LauncherIcon {
|
|||||||
int x, y;
|
int x, y;
|
||||||
} LauncherIcon;
|
} LauncherIcon;
|
||||||
|
|
||||||
typedef struct DesktopEntry {
|
|
||||||
char *name;
|
|
||||||
char *exec;
|
|
||||||
char *icon;
|
|
||||||
} DesktopEntry;
|
|
||||||
|
|
||||||
#define ICON_DIR_TYPE_SCALABLE 0
|
|
||||||
#define ICON_DIR_TYPE_FIXED 1
|
|
||||||
#define ICON_DIR_TYPE_THRESHOLD 2
|
|
||||||
typedef struct IconThemeDir {
|
|
||||||
char *name;
|
|
||||||
int size;
|
|
||||||
int type;
|
|
||||||
int max_size;
|
|
||||||
int min_size;
|
|
||||||
int threshold;
|
|
||||||
char *context;
|
|
||||||
} IconThemeDir;
|
|
||||||
|
|
||||||
typedef struct IconTheme {
|
|
||||||
char *name;
|
|
||||||
GSList *list_inherits; // each item is a char* (theme name)
|
|
||||||
GSList *list_directories; // each item is an IconThemeDir*
|
|
||||||
} IconTheme;
|
|
||||||
|
|
||||||
extern int launcher_enabled;
|
extern int launcher_enabled;
|
||||||
extern int launcher_max_icon_size;
|
extern int launcher_max_icon_size;
|
||||||
extern int launcher_tooltip_enabled;
|
extern int launcher_tooltip_enabled;
|
||||||
extern int launcher_alpha;
|
extern int launcher_alpha;
|
||||||
extern int launcher_saturation;
|
extern int launcher_saturation;
|
||||||
extern int launcher_brightness;
|
extern int launcher_brightness;
|
||||||
extern char *icon_theme_name; // theme name
|
extern char *icon_theme_name_xsettings; // theme name
|
||||||
|
extern char *icon_theme_name_config;
|
||||||
extern XSettingsClient *xsettings_client;
|
extern XSettingsClient *xsettings_client;
|
||||||
|
extern int startup_notifications;
|
||||||
|
|
||||||
// default global data
|
// default global data
|
||||||
void default_launcher();
|
void default_launcher();
|
||||||
@@ -79,10 +57,10 @@ void cleanup_launcher_theme(Launcher *launcher);
|
|||||||
int resize_launcher(void *obj);
|
int resize_launcher(void *obj);
|
||||||
void draw_launcher (void *obj, cairo_t *c);
|
void draw_launcher (void *obj, cairo_t *c);
|
||||||
|
|
||||||
// Populates the list_themes list
|
|
||||||
void launcher_load_themes(Launcher *launcher);
|
|
||||||
// Populates the list_icons list
|
// Populates the list_icons list
|
||||||
void launcher_load_icons(Launcher *launcher);
|
void launcher_load_icons(Launcher *launcher);
|
||||||
|
// Populates the list_themes list
|
||||||
|
void launcher_load_themes(Launcher *launcher);
|
||||||
void launcher_action(LauncherIcon *icon, XEvent* e);
|
void launcher_action(LauncherIcon *icon, XEvent* e);
|
||||||
|
|
||||||
void test_launcher_read_desktop_file();
|
void test_launcher_read_desktop_file();
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ void xsettings_notify_cb (const char *name, XSettingsAction action, XSettingsSet
|
|||||||
//printf("xsettings_notify_cb\n");
|
//printf("xsettings_notify_cb\n");
|
||||||
if ((action == XSETTINGS_ACTION_NEW || action == XSETTINGS_ACTION_CHANGED) && name != NULL && setting != NULL) {
|
if ((action == XSETTINGS_ACTION_NEW || action == XSETTINGS_ACTION_CHANGED) && name != NULL && setting != NULL) {
|
||||||
if (!strcmp(name, "Net/IconThemeName") && setting->type == XSETTINGS_TYPE_STRING) {
|
if (!strcmp(name, "Net/IconThemeName") && setting->type == XSETTINGS_TYPE_STRING) {
|
||||||
if (icon_theme_name) {
|
if (icon_theme_name_xsettings) {
|
||||||
if (strcmp(icon_theme_name, setting->data.v_string) == 0)
|
if (strcmp(icon_theme_name_xsettings, setting->data.v_string) == 0)
|
||||||
return;
|
return;
|
||||||
free(icon_theme_name);
|
free(icon_theme_name_xsettings);
|
||||||
}
|
}
|
||||||
icon_theme_name = strdup(setting->data.v_string);
|
icon_theme_name_xsettings = strdup(setting->data.v_string);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0 ; i < nb_panel ; i++) {
|
for (i = 0 ; i < nb_panel ; i++) {
|
||||||
@@ -169,13 +169,13 @@ static XSettingsResult fetch_card32 (XSettingsBuffer *buffer, CARD32 *result)
|
|||||||
|
|
||||||
static XSettingsResult fetch_card8 (XSettingsBuffer *buffer, CARD8 *result)
|
static XSettingsResult fetch_card8 (XSettingsBuffer *buffer, CARD8 *result)
|
||||||
{
|
{
|
||||||
if (BYTES_LEFT (buffer) < 1)
|
if (BYTES_LEFT (buffer) < 1)
|
||||||
return XSETTINGS_ACCESS;
|
return XSETTINGS_ACCESS;
|
||||||
|
|
||||||
*result = *(CARD8 *)buffer->pos;
|
*result = *(CARD8 *)buffer->pos;
|
||||||
buffer->pos += 1;
|
buffer->pos += 1;
|
||||||
|
|
||||||
return XSETTINGS_SUCCESS;
|
return XSETTINGS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1)))
|
#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1)))
|
||||||
@@ -192,6 +192,7 @@ static XSettingsList *parse_settings (unsigned char *data, size_t len)
|
|||||||
|
|
||||||
local_byte_order = xsettings_byte_order ();
|
local_byte_order = xsettings_byte_order ();
|
||||||
|
|
||||||
|
buffer.byte_order = local_byte_order;
|
||||||
buffer.pos = buffer.data = data;
|
buffer.pos = buffer.data = data;
|
||||||
buffer.len = len;
|
buffer.len = len;
|
||||||
|
|
||||||
@@ -234,14 +235,14 @@ static XSettingsList *parse_settings (unsigned char *data, size_t len)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
setting = malloc (sizeof *setting);
|
setting = calloc (1, sizeof *setting);
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
result = XSETTINGS_NO_MEM;
|
result = XSETTINGS_NO_MEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */
|
setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */
|
||||||
|
|
||||||
setting->name = malloc (name_len + 1);
|
setting->name = calloc (name_len + 1, 1);
|
||||||
if (!setting->name) {
|
if (!setting->name) {
|
||||||
result = XSETTINGS_NO_MEM;
|
result = XSETTINGS_NO_MEM;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -275,7 +276,7 @@ static XSettingsList *parse_settings (unsigned char *data, size_t len)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
setting->data.v_string = malloc (v_int + 1);
|
setting->data.v_string = calloc (v_int + 1, 1);
|
||||||
if (!setting->data.v_string) {
|
if (!setting->data.v_string) {
|
||||||
result = XSETTINGS_NO_MEM;
|
result = XSETTINGS_NO_MEM;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -399,7 +400,7 @@ XSettingsClient *xsettings_client_new (Display *display, int screen, XSettingsNo
|
|||||||
{
|
{
|
||||||
XSettingsClient *client;
|
XSettingsClient *client;
|
||||||
|
|
||||||
client = malloc (sizeof *client);
|
client = calloc (1, sizeof *client);
|
||||||
if (!client)
|
if (!client)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
|
||||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*
|
*
|
||||||
* Author: Owen Taylor, Red Hat, Inc.
|
* Author: Owen Taylor, Red Hat, Inc.
|
||||||
@@ -31,238 +31,238 @@
|
|||||||
XSettingsSetting *
|
XSettingsSetting *
|
||||||
xsettings_setting_copy (XSettingsSetting *setting)
|
xsettings_setting_copy (XSettingsSetting *setting)
|
||||||
{
|
{
|
||||||
XSettingsSetting *result;
|
XSettingsSetting *result;
|
||||||
size_t str_len;
|
size_t str_len;
|
||||||
|
|
||||||
result = malloc (sizeof *result);
|
|
||||||
if (!result)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
str_len = strlen (setting->name);
|
result = calloc (1, sizeof *result);
|
||||||
result->name = malloc (str_len + 1);
|
if (!result)
|
||||||
if (!result->name)
|
return NULL;
|
||||||
goto err;
|
|
||||||
|
|
||||||
memcpy (result->name, setting->name, str_len + 1);
|
str_len = strlen (setting->name);
|
||||||
|
result->name = calloc (str_len + 1, 1);
|
||||||
|
if (!result->name)
|
||||||
|
goto err;
|
||||||
|
|
||||||
result->type = setting->type;
|
memcpy (result->name, setting->name, str_len + 1);
|
||||||
|
|
||||||
switch (setting->type)
|
result->type = setting->type;
|
||||||
{
|
|
||||||
case XSETTINGS_TYPE_INT:
|
|
||||||
result->data.v_int = setting->data.v_int;
|
|
||||||
break;
|
|
||||||
case XSETTINGS_TYPE_COLOR:
|
|
||||||
result->data.v_color = setting->data.v_color;
|
|
||||||
break;
|
|
||||||
case XSETTINGS_TYPE_STRING:
|
|
||||||
str_len = strlen (setting->data.v_string);
|
|
||||||
result->data.v_string = malloc (str_len + 1);
|
|
||||||
if (!result->data.v_string)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
memcpy (result->data.v_string, setting->data.v_string, str_len + 1);
|
switch (setting->type)
|
||||||
break;
|
{
|
||||||
default:
|
case XSETTINGS_TYPE_INT:
|
||||||
break;
|
result->data.v_int = setting->data.v_int;
|
||||||
}
|
break;
|
||||||
|
case XSETTINGS_TYPE_COLOR:
|
||||||
|
result->data.v_color = setting->data.v_color;
|
||||||
|
break;
|
||||||
|
case XSETTINGS_TYPE_STRING:
|
||||||
|
str_len = strlen (setting->data.v_string);
|
||||||
|
result->data.v_string = calloc (str_len + 1, 1);
|
||||||
|
if (!result->data.v_string)
|
||||||
|
goto err;
|
||||||
|
|
||||||
result->last_change_serial = setting->last_change_serial;
|
memcpy (result->data.v_string, setting->data.v_string, str_len + 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
result->last_change_serial = setting->last_change_serial;
|
||||||
|
|
||||||
err:
|
return result;
|
||||||
if (result->name)
|
|
||||||
free (result->name);
|
err:
|
||||||
free (result);
|
if (result->name)
|
||||||
|
free (result->name);
|
||||||
return NULL;
|
free (result);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
XSettingsList *
|
XSettingsList *
|
||||||
xsettings_list_copy (XSettingsList *list)
|
xsettings_list_copy (XSettingsList *list)
|
||||||
{
|
{
|
||||||
XSettingsList *new = NULL;
|
XSettingsList *new = NULL;
|
||||||
XSettingsList *old_iter = list;
|
XSettingsList *old_iter = list;
|
||||||
XSettingsList *new_iter = NULL;
|
XSettingsList *new_iter = NULL;
|
||||||
|
|
||||||
while (old_iter)
|
while (old_iter)
|
||||||
{
|
|
||||||
XSettingsList *new_node;
|
|
||||||
|
|
||||||
new_node = malloc (sizeof *new_node);
|
|
||||||
if (!new_node)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
new_node->setting = xsettings_setting_copy (old_iter->setting);
|
|
||||||
if (!new_node->setting)
|
|
||||||
{
|
{
|
||||||
free (new_node);
|
XSettingsList *new_node;
|
||||||
goto error;
|
|
||||||
|
new_node = calloc (1, sizeof *new_node);
|
||||||
|
if (!new_node)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
new_node->setting = xsettings_setting_copy (old_iter->setting);
|
||||||
|
if (!new_node->setting)
|
||||||
|
{
|
||||||
|
free (new_node);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_iter)
|
||||||
|
new_iter->next = new_node;
|
||||||
|
else
|
||||||
|
new = new_node;
|
||||||
|
|
||||||
|
new_iter = new_node;
|
||||||
|
|
||||||
|
old_iter = old_iter->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_iter)
|
return new;
|
||||||
new_iter->next = new_node;
|
|
||||||
else
|
|
||||||
new = new_node;
|
|
||||||
|
|
||||||
new_iter = new_node;
|
error:
|
||||||
|
xsettings_list_free (new);
|
||||||
old_iter = old_iter->next;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return new;
|
|
||||||
|
|
||||||
error:
|
|
||||||
xsettings_list_free (new);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xsettings_setting_equal (XSettingsSetting *setting_a,
|
xsettings_setting_equal (XSettingsSetting *setting_a,
|
||||||
XSettingsSetting *setting_b)
|
XSettingsSetting *setting_b)
|
||||||
{
|
{
|
||||||
if (setting_a->type != setting_b->type)
|
if (setting_a->type != setting_b->type)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strcmp (setting_a->name, setting_b->name) != 0)
|
if (strcmp (setting_a->name, setting_b->name) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (setting_a->type)
|
switch (setting_a->type)
|
||||||
{
|
{
|
||||||
case XSETTINGS_TYPE_INT:
|
case XSETTINGS_TYPE_INT:
|
||||||
return setting_a->data.v_int == setting_b->data.v_int;
|
return setting_a->data.v_int == setting_b->data.v_int;
|
||||||
case XSETTINGS_TYPE_COLOR:
|
case XSETTINGS_TYPE_COLOR:
|
||||||
return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
|
return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
|
||||||
setting_a->data.v_color.green == setting_b->data.v_color.green &&
|
setting_a->data.v_color.green == setting_b->data.v_color.green &&
|
||||||
setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
|
setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
|
||||||
setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
|
setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
|
||||||
case XSETTINGS_TYPE_STRING:
|
case XSETTINGS_TYPE_STRING:
|
||||||
return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0;
|
return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xsettings_setting_free (XSettingsSetting *setting)
|
xsettings_setting_free (XSettingsSetting *setting)
|
||||||
{
|
{
|
||||||
if (setting->type == XSETTINGS_TYPE_STRING)
|
if (setting->type == XSETTINGS_TYPE_STRING)
|
||||||
free (setting->data.v_string);
|
free (setting->data.v_string);
|
||||||
|
|
||||||
if (setting->name)
|
if (setting->name)
|
||||||
free (setting->name);
|
free (setting->name);
|
||||||
|
|
||||||
free (setting);
|
free (setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xsettings_list_free (XSettingsList *list)
|
xsettings_list_free (XSettingsList *list)
|
||||||
{
|
{
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
XSettingsList *next = list->next;
|
XSettingsList *next = list->next;
|
||||||
|
|
||||||
xsettings_setting_free (list->setting);
|
xsettings_setting_free (list->setting);
|
||||||
free (list);
|
free (list);
|
||||||
|
|
||||||
list = next;
|
list = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XSettingsResult
|
XSettingsResult
|
||||||
xsettings_list_insert (XSettingsList **list,
|
xsettings_list_insert (XSettingsList **list,
|
||||||
XSettingsSetting *setting)
|
XSettingsSetting *setting)
|
||||||
{
|
{
|
||||||
XSettingsList *node;
|
XSettingsList *node;
|
||||||
XSettingsList *iter;
|
XSettingsList *iter;
|
||||||
XSettingsList *last = NULL;
|
XSettingsList *last = NULL;
|
||||||
|
|
||||||
node = malloc (sizeof *node);
|
node = calloc (1, sizeof *node);
|
||||||
if (!node)
|
if (!node)
|
||||||
return XSETTINGS_NO_MEM;
|
return XSETTINGS_NO_MEM;
|
||||||
node->setting = setting;
|
node->setting = setting;
|
||||||
|
|
||||||
iter = *list;
|
iter = *list;
|
||||||
while (iter)
|
while (iter)
|
||||||
{
|
|
||||||
int cmp = strcmp (setting->name, iter->setting->name);
|
|
||||||
|
|
||||||
if (cmp < 0)
|
|
||||||
break;
|
|
||||||
else if (cmp == 0)
|
|
||||||
{
|
{
|
||||||
free (node);
|
int cmp = strcmp (setting->name, iter->setting->name);
|
||||||
return XSETTINGS_DUPLICATE_ENTRY;
|
|
||||||
|
if (cmp < 0)
|
||||||
|
break;
|
||||||
|
else if (cmp == 0)
|
||||||
|
{
|
||||||
|
free (node);
|
||||||
|
return XSETTINGS_DUPLICATE_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = iter;
|
||||||
|
iter = iter->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
last = iter;
|
if (last)
|
||||||
iter = iter->next;
|
last->next = node;
|
||||||
}
|
else
|
||||||
|
*list = node;
|
||||||
if (last)
|
|
||||||
last->next = node;
|
node->next = iter;
|
||||||
else
|
|
||||||
*list = node;
|
return XSETTINGS_SUCCESS;
|
||||||
|
|
||||||
node->next = iter;
|
|
||||||
|
|
||||||
return XSETTINGS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XSettingsResult
|
XSettingsResult
|
||||||
xsettings_list_delete (XSettingsList **list,
|
xsettings_list_delete (XSettingsList **list,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
XSettingsList *iter;
|
XSettingsList *iter;
|
||||||
XSettingsList *last = NULL;
|
XSettingsList *last = NULL;
|
||||||
|
|
||||||
iter = *list;
|
iter = *list;
|
||||||
while (iter)
|
while (iter)
|
||||||
{
|
|
||||||
if (strcmp (name, iter->setting->name) == 0)
|
|
||||||
{
|
{
|
||||||
if (last)
|
if (strcmp (name, iter->setting->name) == 0)
|
||||||
last->next = iter->next;
|
{
|
||||||
else
|
if (last)
|
||||||
*list = iter->next;
|
last->next = iter->next;
|
||||||
|
else
|
||||||
xsettings_setting_free (iter->setting);
|
*list = iter->next;
|
||||||
free (iter);
|
|
||||||
|
|
||||||
return XSETTINGS_SUCCESS;
|
xsettings_setting_free (iter->setting);
|
||||||
|
free (iter);
|
||||||
|
|
||||||
|
return XSETTINGS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = iter;
|
||||||
|
iter = iter->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
last = iter;
|
return XSETTINGS_FAILED;
|
||||||
iter = iter->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return XSETTINGS_FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XSettingsSetting *
|
XSettingsSetting *
|
||||||
xsettings_list_lookup (XSettingsList *list,
|
xsettings_list_lookup (XSettingsList *list,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
XSettingsList *iter;
|
XSettingsList *iter;
|
||||||
|
|
||||||
iter = list;
|
iter = list;
|
||||||
while (iter)
|
while (iter)
|
||||||
{
|
{
|
||||||
if (strcmp (name, iter->setting->name) == 0)
|
if (strcmp (name, iter->setting->name) == 0)
|
||||||
return iter->setting;
|
return iter->setting;
|
||||||
|
|
||||||
iter = iter->next;
|
iter = iter->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
xsettings_byte_order (void)
|
xsettings_byte_order (void)
|
||||||
{
|
{
|
||||||
CARD32 myint = 0x01020304;
|
CARD32 myint = 0x01020304;
|
||||||
return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
|
return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
|
||||||
}
|
}
|
||||||
|
|||||||
178
src/panel.c
178
src/panel.c
@@ -37,6 +37,7 @@
|
|||||||
int signal_pending;
|
int signal_pending;
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// mouse events
|
// mouse events
|
||||||
|
int mouse_left;
|
||||||
int mouse_middle;
|
int mouse_middle;
|
||||||
int mouse_right;
|
int mouse_right;
|
||||||
int mouse_scroll_up;
|
int mouse_scroll_up;
|
||||||
@@ -52,6 +53,7 @@ int panel_position;
|
|||||||
int panel_horizontal;
|
int panel_horizontal;
|
||||||
int panel_refresh;
|
int panel_refresh;
|
||||||
int task_dragged;
|
int task_dragged;
|
||||||
|
char *panel_window_name = NULL;
|
||||||
|
|
||||||
int panel_autohide;
|
int panel_autohide;
|
||||||
int panel_autohide_show_timeout;
|
int panel_autohide_show_timeout;
|
||||||
@@ -80,7 +82,7 @@ void default_panel()
|
|||||||
task_dragged = 0;
|
task_dragged = 0;
|
||||||
panel_horizontal = 1;
|
panel_horizontal = 1;
|
||||||
panel_position = CENTER;
|
panel_position = CENTER;
|
||||||
panel_items_order = 0;
|
panel_items_order = NULL;
|
||||||
panel_autohide = 0;
|
panel_autohide = 0;
|
||||||
panel_autohide_show_timeout = 0;
|
panel_autohide_show_timeout = 0;
|
||||||
panel_autohide_hide_timeout = 0;
|
panel_autohide_hide_timeout = 0;
|
||||||
@@ -88,8 +90,10 @@ void default_panel()
|
|||||||
panel_strut_policy = STRUT_FOLLOW_SIZE;
|
panel_strut_policy = STRUT_FOLLOW_SIZE;
|
||||||
panel_dock = 0; // default not in the dock
|
panel_dock = 0; // default not in the dock
|
||||||
panel_layer = BOTTOM_LAYER; // default is bottom layer
|
panel_layer = BOTTOM_LAYER; // default is bottom layer
|
||||||
|
panel_window_name = strdup("tint2");
|
||||||
wm_menu = 0;
|
wm_menu = 0;
|
||||||
max_tick_urgent = 14;
|
max_tick_urgent = 14;
|
||||||
|
mouse_left = TOGGLE_ICONIFY;
|
||||||
backgrounds = g_array_new(0, 0, sizeof(Background));
|
backgrounds = g_array_new(0, 0, sizeof(Background));
|
||||||
|
|
||||||
memset(&panel_config, 0, sizeof(Panel));
|
memset(&panel_config, 0, sizeof(Panel));
|
||||||
@@ -102,28 +106,40 @@ void default_panel()
|
|||||||
|
|
||||||
void cleanup_panel()
|
void cleanup_panel()
|
||||||
{
|
{
|
||||||
if (!panel1) return;
|
if (!panel1)
|
||||||
|
return;
|
||||||
|
|
||||||
cleanup_taskbar();
|
cleanup_taskbar();
|
||||||
// taskbarname_font_desc freed here because cleanup_taskbarname() called on _NET_NUMBER_OF_DESKTOPS
|
|
||||||
if (taskbarname_font_desc) pango_font_description_free(taskbarname_font_desc);
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
Panel *p;
|
Panel *p;
|
||||||
for (i=0 ; i < nb_panel ; i++) {
|
for (i = 0; i < nb_panel; i++) {
|
||||||
p = &panel1[i];
|
p = &panel1[i];
|
||||||
|
|
||||||
free_area(&p->area);
|
free_area(&p->area);
|
||||||
if (p->temp_pmap) XFreePixmap(server.dsp, p->temp_pmap);
|
if (p->temp_pmap)
|
||||||
if (p->hidden_pixmap) XFreePixmap(server.dsp, p->hidden_pixmap);
|
XFreePixmap(server.dsp, p->temp_pmap);
|
||||||
if (p->main_win) XDestroyWindow(server.dsp, p->main_win);
|
p->temp_pmap = 0;
|
||||||
|
if (p->hidden_pixmap)
|
||||||
|
XFreePixmap(server.dsp, p->hidden_pixmap);
|
||||||
|
p->hidden_pixmap = 0;
|
||||||
|
if (p->main_win)
|
||||||
|
XDestroyWindow(server.dsp, p->main_win);
|
||||||
|
p->main_win = 0;
|
||||||
|
stop_timeout(p->autohide_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_items_order) g_free(panel_items_order);
|
free(panel_items_order);
|
||||||
if (panel1) free(panel1);
|
panel_items_order = NULL;
|
||||||
|
free(panel_window_name);
|
||||||
|
panel_window_name = NULL;
|
||||||
|
free(panel1);
|
||||||
|
panel1 = NULL;
|
||||||
if (backgrounds)
|
if (backgrounds)
|
||||||
g_array_free(backgrounds, 1);
|
g_array_free(backgrounds, 1);
|
||||||
if (panel_config.g_task.font_desc) pango_font_description_free(panel_config.g_task.font_desc);
|
backgrounds = NULL;
|
||||||
|
pango_font_description_free(panel_config.g_task.font_desc);
|
||||||
|
panel_config.g_task.font_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_panel()
|
void init_panel()
|
||||||
@@ -152,7 +168,7 @@ void init_panel()
|
|||||||
else
|
else
|
||||||
nb_panel = server.nb_monitor;
|
nb_panel = server.nb_monitor;
|
||||||
|
|
||||||
panel1 = malloc(nb_panel * sizeof(Panel));
|
panel1 = calloc(nb_panel, sizeof(Panel));
|
||||||
for (i=0 ; i < nb_panel ; i++) {
|
for (i=0 ; i < nb_panel ; i++) {
|
||||||
memcpy(&panel1[i], &panel_config, sizeof(Panel));
|
memcpy(&panel1[i], &panel_config, sizeof(Panel));
|
||||||
}
|
}
|
||||||
@@ -163,7 +179,7 @@ void init_panel()
|
|||||||
|
|
||||||
if (panel_config.monitor < 0)
|
if (panel_config.monitor < 0)
|
||||||
p->monitor = i;
|
p->monitor = i;
|
||||||
if ( p->area.bg == 0 )
|
if (!p->area.bg)
|
||||||
p->area.bg = &g_array_index(backgrounds, Background, 0);
|
p->area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
p->area.parent = p;
|
p->area.parent = p;
|
||||||
p->area.panel = p;
|
p->area.panel = p;
|
||||||
@@ -182,9 +198,7 @@ void init_panel()
|
|||||||
if (panel_items_order[k] == 'B')
|
if (panel_items_order[k] == 'B')
|
||||||
init_battery_panel(p);
|
init_battery_panel(p);
|
||||||
#endif
|
#endif
|
||||||
if (panel_items_order[k] == 'S' && i==0) {
|
if (panel_items_order[k] == 'S' && systray_on_monitor(i, nb_panel)) {
|
||||||
// TODO : check systray is only on 1 panel
|
|
||||||
// at the moment only on panel1[0] allowed
|
|
||||||
init_systray_panel(p);
|
init_systray_panel(p);
|
||||||
refresh_systray = 1;
|
refresh_systray = 1;
|
||||||
}
|
}
|
||||||
@@ -218,7 +232,7 @@ void init_panel()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel_autohide)
|
if (panel_autohide)
|
||||||
add_timeout(panel_autohide_hide_timeout, 0, autohide_hide, p);
|
autohide_trigger_hide(p);
|
||||||
|
|
||||||
visible_taskbar(p);
|
visible_taskbar(p);
|
||||||
}
|
}
|
||||||
@@ -323,6 +337,87 @@ int resize_panel(void *obj)
|
|||||||
panel->taskbar[i].area.resize = 1;
|
panel->taskbar[i].area.resize = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (panel_mode == MULTI_DESKTOP && taskbar_enabled && taskbar_distribute_size) {
|
||||||
|
// Distribute the available space between taskbars
|
||||||
|
Panel *panel = (Panel*)obj;
|
||||||
|
|
||||||
|
// Compute the total available size, and the total size requested by the taskbars
|
||||||
|
int total_size = 0;
|
||||||
|
int total_name_size = 0;
|
||||||
|
int total_items = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < panel->nb_desktop; i++) {
|
||||||
|
if (panel_horizontal) {
|
||||||
|
total_size += panel->taskbar[i].area.width;
|
||||||
|
} else {
|
||||||
|
total_size += panel->taskbar[i].area.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
|
GSList *l;
|
||||||
|
for (l = taskbar->area.list; l; l = l->next) {
|
||||||
|
Area *child = l->data;
|
||||||
|
if (!child->on_screen)
|
||||||
|
continue;
|
||||||
|
total_items++;
|
||||||
|
}
|
||||||
|
if (taskbarname_enabled) {
|
||||||
|
if (taskbar->area.list) {
|
||||||
|
total_items--;
|
||||||
|
Area *name = taskbar->area.list->data;
|
||||||
|
if (panel_horizontal) {
|
||||||
|
total_name_size += name->width;
|
||||||
|
} else {
|
||||||
|
total_name_size += name->height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Distribute the space proportionally to the requested size (that is, to the
|
||||||
|
// number of tasks in each taskbar)
|
||||||
|
if (total_items) {
|
||||||
|
int actual_name_size;
|
||||||
|
if (total_name_size <= total_size) {
|
||||||
|
actual_name_size = total_name_size / panel->nb_desktop;
|
||||||
|
} else {
|
||||||
|
actual_name_size = total_size / panel->nb_desktop;
|
||||||
|
}
|
||||||
|
total_size -= total_name_size;
|
||||||
|
|
||||||
|
for (i = 0; i < panel->nb_desktop; i++) {
|
||||||
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
|
|
||||||
|
int requested_size = (2 * taskbar->area.bg->border.width) + (2 * taskbar->area.paddingxlr);
|
||||||
|
int items = 0;
|
||||||
|
GSList *l = taskbar->area.list;
|
||||||
|
if (taskbarname_enabled)
|
||||||
|
l = l->next;
|
||||||
|
for (; l; l = l->next) {
|
||||||
|
Area *child = l->data;
|
||||||
|
if (!child->on_screen)
|
||||||
|
continue;
|
||||||
|
items++;
|
||||||
|
if (panel_horizontal) {
|
||||||
|
requested_size += child->width + taskbar->area.paddingy;
|
||||||
|
} else {
|
||||||
|
requested_size += child->height + taskbar->area.paddingx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (panel_horizontal) {
|
||||||
|
requested_size -= taskbar->area.paddingy;
|
||||||
|
} else {
|
||||||
|
requested_size -= taskbar->area.paddingx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panel_horizontal) {
|
||||||
|
taskbar->area.width = actual_name_size + items / (float)total_items * total_size;
|
||||||
|
} else {
|
||||||
|
taskbar->area.height = actual_name_size + items / (float)total_items * total_size;
|
||||||
|
}
|
||||||
|
taskbar->area.resize = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,8 +487,10 @@ void set_panel_items_order(Panel *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (k=0 ; k < strlen(panel_items_order) ; k++) {
|
for (k=0 ; k < strlen(panel_items_order) ; k++) {
|
||||||
if (panel_items_order[k] == 'L')
|
if (panel_items_order[k] == 'L') {
|
||||||
p->area.list = g_slist_append(p->area.list, &p->launcher);
|
p->area.list = g_slist_append(p->area.list, &p->launcher);
|
||||||
|
p->launcher.area.resize = 1;
|
||||||
|
}
|
||||||
if (panel_items_order[k] == 'T') {
|
if (panel_items_order[k] == 'T') {
|
||||||
for (j=0 ; j < p->nb_desktop ; j++)
|
for (j=0 ; j < p->nb_desktop ; j++)
|
||||||
p->area.list = g_slist_append(p->area.list, &p->taskbar[j]);
|
p->area.list = g_slist_append(p->area.list, &p->taskbar[j]);
|
||||||
@@ -402,9 +499,8 @@ void set_panel_items_order(Panel *p)
|
|||||||
if (panel_items_order[k] == 'B')
|
if (panel_items_order[k] == 'B')
|
||||||
p->area.list = g_slist_append(p->area.list, &p->battery);
|
p->area.list = g_slist_append(p->area.list, &p->battery);
|
||||||
#endif
|
#endif
|
||||||
if (panel_items_order[k] == 'S' && p == panel1) {
|
int i = p - panel1;
|
||||||
// TODO : check systray is only on 1 panel
|
if (panel_items_order[k] == 'S' && systray_on_monitor(i, nb_panel)) {
|
||||||
// at the moment only on panel1[0] allowed
|
|
||||||
p->area.list = g_slist_append(p->area.list, &systray);
|
p->area.list = g_slist_append(p->area.list, &systray);
|
||||||
}
|
}
|
||||||
if (panel_items_order[k] == 'C')
|
if (panel_items_order[k] == 'C')
|
||||||
@@ -416,22 +512,24 @@ void set_panel_items_order(Panel *p)
|
|||||||
|
|
||||||
void set_panel_properties(Panel *p)
|
void set_panel_properties(Panel *p)
|
||||||
{
|
{
|
||||||
XStoreName (server.dsp, p->main_win, "tint2");
|
XStoreName (server.dsp, p->main_win, panel_window_name);
|
||||||
|
XSetIconName (server.dsp, p->main_win, panel_window_name);
|
||||||
|
|
||||||
gsize len;
|
gsize len;
|
||||||
gchar *name = g_locale_to_utf8("tint2", -1, NULL, &len, NULL);
|
gchar *name = g_locale_to_utf8(panel_window_name, -1, NULL, &len, NULL);
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
XChangeProperty(server.dsp, p->main_win, server.atom._NET_WM_NAME, server.atom.UTF8_STRING, 8, PropModeReplace, (unsigned char *) name, (int) len);
|
XChangeProperty(server.dsp, p->main_win, server.atom._NET_WM_NAME, server.atom.UTF8_STRING, 8, PropModeReplace, (unsigned char *) name, (int) len);
|
||||||
|
XChangeProperty(server.dsp, p->main_win, server.atom._NET_WM_ICON_NAME, server.atom.UTF8_STRING, 8, PropModeReplace, (unsigned char *) name, (int) len);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dock
|
// Dock
|
||||||
long val = server.atom._NET_WM_WINDOW_TYPE_DOCK;
|
long val = panel_dock ? server.atom._NET_WM_WINDOW_TYPE_DOCK : server.atom._NET_WM_WINDOW_TYPE_SPLASH;
|
||||||
XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *) &val, 1);
|
XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *) &val, 1);
|
||||||
|
|
||||||
// Sticky and below other window
|
|
||||||
val = ALLDESKTOP;
|
val = ALLDESKTOP;
|
||||||
XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_DESKTOP, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &val, 1);
|
XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_DESKTOP, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &val, 1);
|
||||||
|
|
||||||
Atom state[4];
|
Atom state[4];
|
||||||
state[0] = server.atom._NET_WM_STATE_SKIP_PAGER;
|
state[0] = server.atom._NET_WM_STATE_SKIP_PAGER;
|
||||||
state[1] = server.atom._NET_WM_STATE_SKIP_TASKBAR;
|
state[1] = server.atom._NET_WM_STATE_SKIP_TASKBAR;
|
||||||
@@ -440,17 +538,18 @@ void set_panel_properties(Panel *p)
|
|||||||
int nb_atoms = panel_layer == NORMAL_LAYER ? 3 : 4;
|
int nb_atoms = panel_layer == NORMAL_LAYER ? 3 : 4;
|
||||||
XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *) state, nb_atoms);
|
XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *) state, nb_atoms);
|
||||||
|
|
||||||
// Unfocusable
|
|
||||||
XWMHints wmhints;
|
XWMHints wmhints;
|
||||||
|
memset(&wmhints, 0, sizeof(wmhints));
|
||||||
if (panel_dock) {
|
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
|
||||||
wmhints.icon_window = wmhints.window_group = p->main_win;
|
wmhints.icon_window = wmhints.window_group = p->main_win;
|
||||||
wmhints.flags = StateHint | IconWindowHint;
|
wmhints.flags = StateHint | IconWindowHint;
|
||||||
wmhints.initial_state = WithdrawnState;
|
wmhints.initial_state = WithdrawnState;
|
||||||
}
|
}
|
||||||
else {
|
// We do not need keyboard input focus.
|
||||||
wmhints.flags = InputHint;
|
wmhints.flags |= InputHint;
|
||||||
wmhints.input = False;
|
wmhints.input = False;
|
||||||
}
|
|
||||||
XSetWMHints(server.dsp, p->main_win, &wmhints);
|
XSetWMHints(server.dsp, p->main_win, &wmhints);
|
||||||
|
|
||||||
// Undecorated
|
// Undecorated
|
||||||
@@ -713,10 +812,7 @@ Area* click_area(Panel *panel, int x, int y)
|
|||||||
|
|
||||||
void stop_autohide_timeout(Panel* p)
|
void stop_autohide_timeout(Panel* p)
|
||||||
{
|
{
|
||||||
if (p->autohide_timeout) {
|
stop_timeout(p->autohide_timeout);
|
||||||
stop_timeout(p->autohide_timeout);
|
|
||||||
p->autohide_timeout = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -725,8 +821,6 @@ void autohide_show(void* p)
|
|||||||
Panel* panel = p;
|
Panel* panel = p;
|
||||||
stop_autohide_timeout(panel);
|
stop_autohide_timeout(panel);
|
||||||
panel->is_hidden = 0;
|
panel->is_hidden = 0;
|
||||||
if (panel_strut_policy == STRUT_FOLLOW_SIZE)
|
|
||||||
update_strut(p);
|
|
||||||
|
|
||||||
XMapSubwindows(server.dsp, panel->main_win); // systray windows
|
XMapSubwindows(server.dsp, panel->main_win); // systray windows
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -741,6 +835,8 @@ void autohide_show(void* p)
|
|||||||
else
|
else
|
||||||
XMoveResizeWindow(server.dsp, panel->main_win, panel->posx, panel->posy, panel->area.width, panel->area.height);
|
XMoveResizeWindow(server.dsp, panel->main_win, panel->posx, panel->posy, panel->area.width, panel->area.height);
|
||||||
}
|
}
|
||||||
|
if (panel_strut_policy == STRUT_FOLLOW_SIZE)
|
||||||
|
update_strut(p);
|
||||||
refresh_systray = 1; // ugly hack, because we actually only need to call XSetBackgroundPixmap
|
refresh_systray = 1; // ugly hack, because we actually only need to call XSetBackgroundPixmap
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
}
|
}
|
||||||
@@ -777,10 +873,7 @@ void autohide_trigger_show(Panel* p)
|
|||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
return;
|
return;
|
||||||
if (p->autohide_timeout)
|
change_timeout(&p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p);
|
||||||
change_timeout(p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p);
|
|
||||||
else
|
|
||||||
p->autohide_timeout = add_timeout(panel_autohide_show_timeout, 0, autohide_show, p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -795,8 +888,5 @@ void autohide_trigger_hide(Panel* p)
|
|||||||
if (XQueryPointer(server.dsp, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask))
|
if (XQueryPointer(server.dsp, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask))
|
||||||
if (child) return; // mouse over one of the system tray icons
|
if (child) return; // mouse over one of the system tray icons
|
||||||
|
|
||||||
if (p->autohide_timeout)
|
change_timeout(&p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
||||||
change_timeout(p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p);
|
|
||||||
else
|
|
||||||
p->autohide_timeout = add_timeout(panel_autohide_hide_timeout, 0, autohide_hide, p);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
extern int signal_pending;
|
extern int signal_pending;
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// mouse events
|
// mouse events
|
||||||
|
extern int mouse_left;
|
||||||
extern int mouse_middle;
|
extern int mouse_middle;
|
||||||
extern int mouse_right;
|
extern int mouse_right;
|
||||||
extern int mouse_scroll_up;
|
extern int mouse_scroll_up;
|
||||||
@@ -43,6 +44,7 @@ extern int panel_mode;
|
|||||||
extern int wm_menu;
|
extern int wm_menu;
|
||||||
extern int panel_dock;
|
extern int panel_dock;
|
||||||
extern int panel_layer;
|
extern int panel_layer;
|
||||||
|
extern char *panel_window_name;
|
||||||
|
|
||||||
//panel position
|
//panel position
|
||||||
enum { LEFT=0x01, RIGHT=0x02, CENTER=0X04, TOP=0X08, BOTTOM=0x10 };
|
enum { LEFT=0x01, RIGHT=0x02, CENTER=0X04, TOP=0X08, BOTTOM=0x10 };
|
||||||
@@ -66,6 +68,8 @@ extern int max_tick_urgent;
|
|||||||
extern GArray* backgrounds;
|
extern GArray* backgrounds;
|
||||||
|
|
||||||
extern Imlib_Image default_icon;
|
extern Imlib_Image default_icon;
|
||||||
|
// TODO maybe this should be a config option
|
||||||
|
#define DEFAULT_FONT "sans 10"
|
||||||
|
|
||||||
|
|
||||||
// tint2 use one panel per monitor and one taskbar per desktop.
|
// tint2 use one panel per monitor and one taskbar per desktop.
|
||||||
@@ -85,6 +89,7 @@ typedef struct {
|
|||||||
int pourcentx, pourcenty;
|
int pourcentx, pourcenty;
|
||||||
// location of the panel (monitor number)
|
// location of the panel (monitor number)
|
||||||
int monitor;
|
int monitor;
|
||||||
|
int font_shadow;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// task and taskbar parameter per panel
|
// task and taskbar parameter per panel
|
||||||
|
|||||||
55
src/server.c
55
src/server.c
@@ -28,9 +28,10 @@
|
|||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "task.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
Server_global server;
|
||||||
|
|
||||||
void server_catch_error (Display *d, XErrorEvent *ev){}
|
void server_catch_error (Display *d, XErrorEvent *ev){}
|
||||||
|
|
||||||
void server_init_atoms ()
|
void server_init_atoms ()
|
||||||
@@ -71,6 +72,7 @@ void server_init_atoms ()
|
|||||||
server.atom._NET_WM_STRUT = XInternAtom (server.dsp, "_NET_WM_STRUT", False);
|
server.atom._NET_WM_STRUT = XInternAtom (server.dsp, "_NET_WM_STRUT", False);
|
||||||
server.atom._NET_WM_ICON = XInternAtom (server.dsp, "_NET_WM_ICON", False);
|
server.atom._NET_WM_ICON = XInternAtom (server.dsp, "_NET_WM_ICON", False);
|
||||||
server.atom._NET_WM_ICON_GEOMETRY = XInternAtom(server.dsp, "_NET_WM_ICON_GEOMETRY", False );
|
server.atom._NET_WM_ICON_GEOMETRY = XInternAtom(server.dsp, "_NET_WM_ICON_GEOMETRY", False );
|
||||||
|
server.atom._NET_WM_ICON_NAME = XInternAtom(server.dsp, "_NET_WM_ICON_NAME", False );
|
||||||
server.atom._NET_CLOSE_WINDOW = XInternAtom (server.dsp, "_NET_CLOSE_WINDOW", False);
|
server.atom._NET_CLOSE_WINDOW = XInternAtom (server.dsp, "_NET_CLOSE_WINDOW", False);
|
||||||
server.atom.UTF8_STRING = XInternAtom (server.dsp, "UTF8_STRING", False);
|
server.atom.UTF8_STRING = XInternAtom (server.dsp, "UTF8_STRING", False);
|
||||||
server.atom._NET_SUPPORTING_WM_CHECK = XInternAtom (server.dsp, "_NET_SUPPORTING_WM_CHECK", False);
|
server.atom._NET_SUPPORTING_WM_CHECK = XInternAtom (server.dsp, "_NET_SUPPORTING_WM_CHECK", False);
|
||||||
@@ -81,7 +83,7 @@ void server_init_atoms ()
|
|||||||
server.atom.__SWM_VROOT = XInternAtom(server.dsp, "__SWM_VROOT", False);
|
server.atom.__SWM_VROOT = XInternAtom(server.dsp, "__SWM_VROOT", False);
|
||||||
server.atom._MOTIF_WM_HINTS = XInternAtom(server.dsp, "_MOTIF_WM_HINTS", False);
|
server.atom._MOTIF_WM_HINTS = XInternAtom(server.dsp, "_MOTIF_WM_HINTS", False);
|
||||||
server.atom.WM_HINTS = XInternAtom(server.dsp, "WM_HINTS", False);
|
server.atom.WM_HINTS = XInternAtom(server.dsp, "WM_HINTS", False);
|
||||||
char *name = g_strdup_printf("_XSETTINGS_S%d", DefaultScreen(server.dsp));
|
gchar *name = g_strdup_printf("_XSETTINGS_S%d", DefaultScreen(server.dsp));
|
||||||
server.atom._XSETTINGS_SCREEN = XInternAtom(server.dsp, name, False);
|
server.atom._XSETTINGS_SCREEN = XInternAtom(server.dsp, name, False);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
server.atom._XSETTINGS_SETTINGS = XInternAtom(server.dsp, "_XSETTINGS_SETTINGS", False);
|
server.atom._XSETTINGS_SETTINGS = XInternAtom(server.dsp, "_XSETTINGS_SETTINGS", False);
|
||||||
@@ -114,16 +116,25 @@ void server_init_atoms ()
|
|||||||
|
|
||||||
void cleanup_server()
|
void cleanup_server()
|
||||||
{
|
{
|
||||||
if (server.colormap) XFreeColormap(server.dsp, server.colormap);
|
if (server.colormap)
|
||||||
if (server.colormap32) XFreeColormap(server.dsp, server.colormap32);
|
XFreeColormap(server.dsp, server.colormap);
|
||||||
|
server.colormap = 0;
|
||||||
|
if (server.colormap32)
|
||||||
|
XFreeColormap(server.dsp, server.colormap32);
|
||||||
|
server.colormap32 = 0;
|
||||||
if (server.monitor) {
|
if (server.monitor) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<server.nb_monitor; ++i)
|
for (i = 0; i < server.nb_monitor; ++i) {
|
||||||
if (server.monitor[i].names)
|
g_strfreev(server.monitor[i].names);
|
||||||
g_strfreev(server.monitor[i].names);
|
server.monitor[i].names = NULL;
|
||||||
|
}
|
||||||
free(server.monitor);
|
free(server.monitor);
|
||||||
|
server.monitor = NULL;
|
||||||
}
|
}
|
||||||
if (server.gc) XFreeGC(server.dsp, server.gc);
|
if (server.gc)
|
||||||
|
XFreeGC(server.dsp, server.gc);
|
||||||
|
server.gc = NULL;
|
||||||
|
server.disable_transparency = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -271,15 +282,27 @@ void get_monitors()
|
|||||||
|
|
||||||
if (res && res->ncrtc >= nbmonitor) {
|
if (res && res->ncrtc >= nbmonitor) {
|
||||||
// use xrandr to identify monitors (does not work with proprietery nvidia drivers)
|
// 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
|
||||||
|
// on some recent configs, XRRGetScreenResourcesCurrent returns a fantom monitor at last position
|
||||||
|
{
|
||||||
|
int i = res->ncrtc - 1;
|
||||||
|
XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(server.dsp, res, res->crtcs[i]);
|
||||||
|
if (!(crtc_info->x || crtc_info->y || crtc_info->width || crtc_info->height)) {
|
||||||
|
res->ncrtc -= 1;
|
||||||
|
}
|
||||||
|
XRRFreeCrtcInfo(crtc_info);
|
||||||
|
}
|
||||||
|
|
||||||
printf("xRandr: Found crtc's: %d\n", res->ncrtc );
|
printf("xRandr: Found crtc's: %d\n", res->ncrtc );
|
||||||
server.monitor = malloc(res->ncrtc * sizeof(Monitor));
|
server.monitor = calloc(res->ncrtc, sizeof(Monitor));
|
||||||
for (i=0; i<res->ncrtc; ++i) {
|
for (i=0; i<res->ncrtc; ++i) {
|
||||||
XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(server.dsp, res, res->crtcs[i]);
|
XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(server.dsp, res, res->crtcs[i]);
|
||||||
server.monitor[i].x = crtc_info->x;
|
server.monitor[i].x = crtc_info->x;
|
||||||
server.monitor[i].y = crtc_info->y;
|
server.monitor[i].y = crtc_info->y;
|
||||||
server.monitor[i].width = crtc_info->width;
|
server.monitor[i].width = crtc_info->width;
|
||||||
server.monitor[i].height = crtc_info->height;
|
server.monitor[i].height = crtc_info->height;
|
||||||
server.monitor[i].names = malloc((crtc_info->noutput+1) * sizeof(char*));
|
server.monitor[i].names = calloc((crtc_info->noutput+1), sizeof(gchar*));
|
||||||
for (j=0; j<crtc_info->noutput; ++j) {
|
for (j=0; j<crtc_info->noutput; ++j) {
|
||||||
XRROutputInfo* output_info = XRRGetOutputInfo(server.dsp, res, crtc_info->outputs[j]);
|
XRROutputInfo* output_info = XRRGetOutputInfo(server.dsp, res, crtc_info->outputs[j]);
|
||||||
printf("xRandr: Linking output %s with crtc %d\n", output_info->name, i);
|
printf("xRandr: Linking output %s with crtc %d\n", output_info->name, i);
|
||||||
@@ -292,7 +315,7 @@ void get_monitors()
|
|||||||
nbmonitor = res->ncrtc;
|
nbmonitor = res->ncrtc;
|
||||||
}
|
}
|
||||||
else if (info && nbmonitor > 0) {
|
else if (info && nbmonitor > 0) {
|
||||||
server.monitor = malloc(nbmonitor * sizeof(Monitor));
|
server.monitor = calloc(nbmonitor, sizeof(Monitor));
|
||||||
for (i=0 ; i < nbmonitor ; i++) {
|
for (i=0 ; i < nbmonitor ; i++) {
|
||||||
server.monitor[i].x = info[i].x_org;
|
server.monitor[i].x = info[i].x_org;
|
||||||
server.monitor[i].y = info[i].y_org;
|
server.monitor[i].y = info[i].y_org;
|
||||||
@@ -330,7 +353,7 @@ next:
|
|||||||
|
|
||||||
if (!server.nb_monitor) {
|
if (!server.nb_monitor) {
|
||||||
server.nb_monitor = 1;
|
server.nb_monitor = 1;
|
||||||
server.monitor = malloc(sizeof(Monitor));
|
server.monitor = calloc(1, sizeof(Monitor));
|
||||||
server.monitor[0].x = server.monitor[0].y = 0;
|
server.monitor[0].x = server.monitor[0].y = 0;
|
||||||
server.monitor[0].width = DisplayWidth (server.dsp, server.screen);
|
server.monitor[0].width = DisplayWidth (server.dsp, server.screen);
|
||||||
server.monitor[0].height = DisplayHeight (server.dsp, server.screen);
|
server.monitor[0].height = DisplayHeight (server.dsp, server.screen);
|
||||||
@@ -338,6 +361,10 @@ next:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int server_get_number_of_desktops()
|
||||||
|
{
|
||||||
|
return get_property32(server.root_win, server.atom._NET_NUMBER_OF_DESKTOPS, XA_CARDINAL);
|
||||||
|
}
|
||||||
|
|
||||||
void get_desktops()
|
void get_desktops()
|
||||||
{
|
{
|
||||||
@@ -346,7 +373,7 @@ void get_desktops()
|
|||||||
// detect number of desktops
|
// detect number of desktops
|
||||||
// wait 15s to leave some time for window manager startup
|
// wait 15s to leave some time for window manager startup
|
||||||
for (i=0 ; i < 15 ; i++) {
|
for (i=0 ; i < 15 ; i++) {
|
||||||
server.nb_desktop = server_get_number_of_desktop ();
|
server.nb_desktop = server_get_number_of_desktops();
|
||||||
if (server.nb_desktop > 0) break;
|
if (server.nb_desktop > 0) break;
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
@@ -391,7 +418,7 @@ void server_init_visual()
|
|||||||
server.colormap32 = XCreateColormap(server.dsp, server.root_win, visual, AllocNone);
|
server.colormap32 = XCreateColormap(server.dsp, server.root_win, visual, AllocNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visual && server.composite_manager != None && snapshot_path == 0) {
|
if (!server.disable_transparency && visual && server.composite_manager != None && snapshot_path == 0) {
|
||||||
XSetWindowAttributes attrs;
|
XSetWindowAttributes attrs;
|
||||||
attrs.event_mask = StructureNotifyMask;
|
attrs.event_mask = StructureNotifyMask;
|
||||||
XChangeWindowAttributes (server.dsp, server.composite_manager, CWEventMask, &attrs);
|
XChangeWindowAttributes (server.dsp, server.composite_manager, CWEventMask, &attrs);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ typedef struct Global_atom
|
|||||||
Atom _NET_WM_STRUT;
|
Atom _NET_WM_STRUT;
|
||||||
Atom _NET_WM_ICON;
|
Atom _NET_WM_ICON;
|
||||||
Atom _NET_WM_ICON_GEOMETRY;
|
Atom _NET_WM_ICON_GEOMETRY;
|
||||||
|
Atom _NET_WM_ICON_NAME;
|
||||||
Atom _NET_CLOSE_WINDOW;
|
Atom _NET_CLOSE_WINDOW;
|
||||||
Atom UTF8_STRING;
|
Atom UTF8_STRING;
|
||||||
Atom _NET_SUPPORTING_WM_CHECK;
|
Atom _NET_SUPPORTING_WM_CHECK;
|
||||||
@@ -96,7 +97,7 @@ typedef struct Monitor
|
|||||||
int y;
|
int y;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
char** names;
|
gchar** names;
|
||||||
} Monitor;
|
} Monitor;
|
||||||
|
|
||||||
|
|
||||||
@@ -106,6 +107,7 @@ typedef struct
|
|||||||
Window root_win;
|
Window root_win;
|
||||||
Window composite_manager;
|
Window composite_manager;
|
||||||
int real_transparency;
|
int real_transparency;
|
||||||
|
int disable_transparency;
|
||||||
// current desktop
|
// current desktop
|
||||||
int desktop;
|
int desktop;
|
||||||
int screen;
|
int screen;
|
||||||
@@ -130,7 +132,7 @@ typedef struct
|
|||||||
} Server_global;
|
} Server_global;
|
||||||
|
|
||||||
|
|
||||||
Server_global server;
|
extern Server_global server;
|
||||||
|
|
||||||
|
|
||||||
// freed memory
|
// freed memory
|
||||||
@@ -150,6 +152,6 @@ void get_root_pixmap();
|
|||||||
// detect monitors and desktops
|
// detect monitors and desktops
|
||||||
void get_monitors();
|
void get_monitors();
|
||||||
void get_desktops();
|
void get_desktops();
|
||||||
|
int server_get_number_of_desktops();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ GSList *icons;
|
|||||||
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
|
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
|
||||||
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
|
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
|
||||||
|
|
||||||
|
#define FORCE_COMPOSITED_RENDERING 1
|
||||||
|
|
||||||
// selection window
|
// selection window
|
||||||
Window net_sel_win = None;
|
Window net_sel_win = None;
|
||||||
|
|
||||||
@@ -49,6 +51,7 @@ Systraybar systray;
|
|||||||
int refresh_systray;
|
int refresh_systray;
|
||||||
int systray_enabled;
|
int systray_enabled;
|
||||||
int systray_max_icon_size;
|
int systray_max_icon_size;
|
||||||
|
int systray_monitor;
|
||||||
|
|
||||||
// background pixmap if we render ourselves the icons
|
// background pixmap if we render ourselves the icons
|
||||||
static Pixmap render_background;
|
static Pixmap render_background;
|
||||||
@@ -71,6 +74,7 @@ void cleanup_systray()
|
|||||||
stop_net();
|
stop_net();
|
||||||
systray_enabled = 0;
|
systray_enabled = 0;
|
||||||
systray_max_icon_size = 0;
|
systray_max_icon_size = 0;
|
||||||
|
systray_monitor = 0;
|
||||||
systray.area.on_screen = 0;
|
systray.area.on_screen = 0;
|
||||||
free_area(&systray.area);
|
free_area(&systray.area);
|
||||||
if (render_background) {
|
if (render_background) {
|
||||||
@@ -98,7 +102,7 @@ void init_systray_panel(void *p)
|
|||||||
{
|
{
|
||||||
systray.area.parent = p;
|
systray.area.parent = p;
|
||||||
systray.area.panel = p;
|
systray.area.panel = p;
|
||||||
if (systray.area.bg == 0)
|
if (!systray.area.bg)
|
||||||
systray.area.bg = &g_array_index(backgrounds, Background, 0);
|
systray.area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
|
|
||||||
GSList *l;
|
GSList *l;
|
||||||
@@ -117,7 +121,7 @@ void init_systray_panel(void *p)
|
|||||||
|
|
||||||
void draw_systray(void *obj, cairo_t *c)
|
void draw_systray(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
if (server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
if (FORCE_COMPOSITED_RENDERING || server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
||||||
if (render_background) XFreePixmap(server.dsp, render_background);
|
if (render_background) XFreePixmap(server.dsp, render_background);
|
||||||
render_background = XCreatePixmap(server.dsp, server.root_win, systray.area.width, systray.area.height, server.depth);
|
render_background = XCreatePixmap(server.dsp, server.root_win, systray.area.width, systray.area.height, server.depth);
|
||||||
XCopyArea(server.dsp, systray.area.pix, render_background, server.gc, 0, 0, systray.area.width, systray.area.height, 0, 0);
|
XCopyArea(server.dsp, systray.area.pix, render_background, server.gc, 0, 0, systray.area.width, systray.area.height, 0, 0);
|
||||||
@@ -171,6 +175,9 @@ void on_change_systray (void *obj)
|
|||||||
{
|
{
|
||||||
// here, systray.area.posx/posy are defined by rendering engine. so we can calculate position of tray icon.
|
// here, systray.area.posx/posy are defined by rendering engine. so we can calculate position of tray icon.
|
||||||
Systraybar *sysbar = obj;
|
Systraybar *sysbar = obj;
|
||||||
|
if (sysbar->icons_per_column == 0 || sysbar->icons_per_row == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
Panel *panel = sysbar->area.panel;
|
Panel *panel = sysbar->area.panel;
|
||||||
int i, posx, posy;
|
int i, posx, posy;
|
||||||
int start = panel->area.bg->border.width + panel->area.paddingy + systray.area.bg->border.width + systray.area.paddingy + sysbar->marging/2;
|
int start = panel->area.bg->border.width + panel->area.paddingy + systray.area.bg->border.width + systray.area.paddingy + sysbar->marging/2;
|
||||||
@@ -266,7 +273,7 @@ void start_net()
|
|||||||
long orient = 0;
|
long orient = 0;
|
||||||
XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_ORIENTATION, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &orient, 1);
|
XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_ORIENTATION, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &orient, 1);
|
||||||
VisualID vid;
|
VisualID vid;
|
||||||
if (server.visual32 && (systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0))
|
if (server.visual32 && (FORCE_COMPOSITED_RENDERING || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0))
|
||||||
vid = XVisualIDFromVisual(server.visual32);
|
vid = XVisualIDFromVisual(server.visual32);
|
||||||
else
|
else
|
||||||
vid = XVisualIDFromVisual(server.visual);
|
vid = XVisualIDFromVisual(server.visual);
|
||||||
@@ -303,7 +310,7 @@ void stop_net()
|
|||||||
remove_icon((TrayWindow*)systray.list_icons->data);
|
remove_icon((TrayWindow*)systray.list_icons->data);
|
||||||
|
|
||||||
g_slist_free(systray.list_icons);
|
g_slist_free(systray.list_icons);
|
||||||
systray.list_icons = 0;
|
systray.list_icons = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (net_sel_win != None) {
|
if (net_sel_win != None) {
|
||||||
@@ -354,6 +361,12 @@ gboolean add_icon(Window id)
|
|||||||
Panel *panel = systray.area.panel;
|
Panel *panel = systray.area.panel;
|
||||||
int hide = 0;
|
int hide = 0;
|
||||||
|
|
||||||
|
GSList *l;
|
||||||
|
for (l = systray.list_icons; l; l = l->next) {
|
||||||
|
if (((TrayWindow*)l->data)->tray_id == id)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
error = FALSE;
|
error = FALSE;
|
||||||
XWindowAttributes attr;
|
XWindowAttributes attr;
|
||||||
if ( XGetWindowAttributes(server.dsp, id, &attr) == False ) return FALSE;
|
if ( XGetWindowAttributes(server.dsp, id, &attr) == False ) return FALSE;
|
||||||
@@ -362,7 +375,7 @@ gboolean add_icon(Window id)
|
|||||||
Visual* visual = server.visual;
|
Visual* visual = server.visual;
|
||||||
//printf("icon with depth: %d, width %d, height %d\n", attr.depth, attr.width, attr.height);
|
//printf("icon with depth: %d, width %d, height %d\n", attr.depth, attr.width, attr.height);
|
||||||
//printf("icon with depth: %d\n", attr.depth);
|
//printf("icon with depth: %d\n", attr.depth);
|
||||||
if (attr.depth != server.depth || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
if (attr.depth != server.depth || FORCE_COMPOSITED_RENDERING || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
||||||
visual = attr.visual;
|
visual = attr.visual;
|
||||||
set_attr.colormap = attr.colormap;
|
set_attr.colormap = attr.colormap;
|
||||||
set_attr.background_pixel = 0;
|
set_attr.background_pixel = 0;
|
||||||
@@ -444,7 +457,7 @@ gboolean add_icon(Window id)
|
|||||||
systray.list_icons = g_slist_insert_sorted(systray.list_icons, traywin, compare_traywindows);
|
systray.list_icons = g_slist_insert_sorted(systray.list_icons, traywin, compare_traywindows);
|
||||||
//printf("add_icon id %lx, %d\n", id, g_slist_length(systray.list_icons));
|
//printf("add_icon id %lx, %d\n", id, g_slist_length(systray.list_icons));
|
||||||
|
|
||||||
if (server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
if (FORCE_COMPOSITED_RENDERING || server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
||||||
traywin->damage = XDamageCreate(server.dsp, traywin->id, XDamageReportRawRectangles);
|
traywin->damage = XDamageCreate(server.dsp, traywin->id, XDamageReportRawRectangles);
|
||||||
XCompositeRedirectWindow(server.dsp, traywin->id, CompositeRedirectManual);
|
XCompositeRedirectWindow(server.dsp, traywin->id, CompositeRedirectManual);
|
||||||
}
|
}
|
||||||
@@ -483,14 +496,13 @@ void remove_icon(TrayWindow *traywin)
|
|||||||
XDestroyWindow(server.dsp, traywin->id);
|
XDestroyWindow(server.dsp, traywin->id);
|
||||||
XSync(server.dsp, False);
|
XSync(server.dsp, False);
|
||||||
XSetErrorHandler(old);
|
XSetErrorHandler(old);
|
||||||
if (traywin->render_timeout)
|
stop_timeout(traywin->render_timeout);
|
||||||
stop_timeout(traywin->render_timeout);
|
|
||||||
g_free(traywin);
|
g_free(traywin);
|
||||||
|
|
||||||
// check empty systray
|
// check empty systray
|
||||||
int count = 0;
|
int count = 0;
|
||||||
GSList *l;
|
GSList *l;
|
||||||
for (l = systray.list_icons; l ; l = l->next) {
|
for (l = systray.list_icons; l; l = l->next) {
|
||||||
if (!((TrayWindow*)l->data)->hide)
|
if (!((TrayWindow*)l->data)->hide)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -604,18 +616,15 @@ void systray_render_icon_now(void* t)
|
|||||||
|
|
||||||
void systray_render_icon(TrayWindow* traywin)
|
void systray_render_icon(TrayWindow* traywin)
|
||||||
{
|
{
|
||||||
if (server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
if (FORCE_COMPOSITED_RENDERING || server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
||||||
// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
|
// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
|
||||||
if (traywin->render_timeout == 0)
|
if (!traywin->render_timeout)
|
||||||
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_now, traywin);
|
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_now, traywin, &traywin->render_timeout);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// comment by andreas: I'm still not sure, what exactly we need to do here... Somehow trayicons which do not
|
// Pixmap pix = XCreatePixmap(server.dsp, server.root_win, traywin->width, traywin->height, server.depth);
|
||||||
// offer the same depth as tint2 does, need to draw a background pixmap, but this cannot be done with
|
// XCopyArea(server.dsp, panel->temp_pmap, pix, server.gc, traywin->x, traywin->y, traywin->width, traywin->height, 0, 0);
|
||||||
// XCopyArea... So we actually need XRenderComposite???
|
// XSetWindowBackgroundPixmap(server.dsp, traywin->id, pix);
|
||||||
// Pixmap pix = XCreatePixmap(server.dsp, server.root_win, traywin->width, traywin->height, server.depth);
|
|
||||||
// XCopyArea(server.dsp, panel->temp_pmap, pix, server.gc, traywin->x, traywin->y, traywin->width, traywin->height, 0, 0);
|
|
||||||
// XSetWindowBackgroundPixmap(server.dsp, traywin->id, pix);
|
|
||||||
XClearArea(server.dsp, traywin->tray_id, 0, 0, traywin->width, traywin->height, True);
|
XClearArea(server.dsp, traywin->tray_id, 0, 0, traywin->width, traywin->height, True);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -631,3 +640,9 @@ void refresh_systray_icon()
|
|||||||
systray_render_icon(traywin);
|
systray_render_icon(traywin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int systray_on_monitor(int i_monitor, int nb_panels)
|
||||||
|
{
|
||||||
|
return (i_monitor == systray_monitor) ||
|
||||||
|
(i_monitor == 0 && (systray_monitor >= nb_panels || systray_monitor < 0));
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ extern Systraybar systray;
|
|||||||
extern int refresh_systray;
|
extern int refresh_systray;
|
||||||
extern int systray_enabled;
|
extern int systray_enabled;
|
||||||
extern int systray_max_icon_size;
|
extern int systray_max_icon_size;
|
||||||
|
extern int systray_monitor;
|
||||||
|
|
||||||
// default global data
|
// default global data
|
||||||
void default_systray();
|
void default_systray();
|
||||||
@@ -66,7 +67,7 @@ void init_systray_panel(void *p);
|
|||||||
void draw_systray(void *obj, cairo_t *c);
|
void draw_systray(void *obj, cairo_t *c);
|
||||||
int resize_systray(void *obj);
|
int resize_systray(void *obj);
|
||||||
void on_change_systray(void *obj);
|
void on_change_systray(void *obj);
|
||||||
|
int systray_on_monitor(int i_monitor, int nb_panels);
|
||||||
|
|
||||||
// systray protocol
|
// systray protocol
|
||||||
// many tray icon doesn't manage stop/restart of the systray manager
|
// many tray icon doesn't manage stop/restart of the systray manager
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ Task *add_task (Window win)
|
|||||||
new_tsk.desktop = window_get_desktop (win);
|
new_tsk.desktop = window_get_desktop (win);
|
||||||
new_tsk.area.panel = &panel1[monitor];
|
new_tsk.area.panel = &panel1[monitor];
|
||||||
new_tsk.current_state = window_is_iconified(win) ? TASK_ICONIFIED : TASK_NORMAL;
|
new_tsk.current_state = window_is_iconified(win) ? TASK_ICONIFIED : TASK_NORMAL;
|
||||||
|
window_get_coordinates(win, &new_tsk.win_x, &new_tsk.win_y, &new_tsk.win_w, &new_tsk.win_h);
|
||||||
|
|
||||||
// allocate only one title and one icon
|
// allocate only one title and one icon
|
||||||
// even with task_on_all_desktop and with task_on_all_panel
|
// even with task_on_all_desktop and with task_on_all_panel
|
||||||
@@ -85,11 +86,15 @@ Task *add_task (Window win)
|
|||||||
if (new_tsk.desktop != ALLDESKTOP && new_tsk.desktop != j) continue;
|
if (new_tsk.desktop != ALLDESKTOP && new_tsk.desktop != j) continue;
|
||||||
|
|
||||||
tskbar = &panel1[monitor].taskbar[j];
|
tskbar = &panel1[monitor].taskbar[j];
|
||||||
new_tsk2 = malloc(sizeof(Task));
|
new_tsk2 = calloc(1, sizeof(Task));
|
||||||
memcpy(&new_tsk2->area, &panel1[monitor].g_task.area, sizeof(Area));
|
memcpy(&new_tsk2->area, &panel1[monitor].g_task.area, sizeof(Area));
|
||||||
new_tsk2->area.parent = tskbar;
|
new_tsk2->area.parent = tskbar;
|
||||||
new_tsk2->win = new_tsk.win;
|
new_tsk2->win = new_tsk.win;
|
||||||
new_tsk2->desktop = new_tsk.desktop;
|
new_tsk2->desktop = new_tsk.desktop;
|
||||||
|
new_tsk2->win_x = new_tsk.win_x;
|
||||||
|
new_tsk2->win_y = new_tsk.win_y;
|
||||||
|
new_tsk2->win_w = new_tsk.win_w;
|
||||||
|
new_tsk2->win_h = new_tsk.win_h;
|
||||||
new_tsk2->current_state = -1; // to update the current state later in set_task_state...
|
new_tsk2->current_state = -1; // to update the current state later in set_task_state...
|
||||||
if (new_tsk2->desktop == ALLDESKTOP && server.desktop != j) {
|
if (new_tsk2->desktop == ALLDESKTOP && server.desktop != j) {
|
||||||
// hide ALLDESKTOP task on non-current desktop
|
// hide ALLDESKTOP task on non-current desktop
|
||||||
@@ -109,13 +114,21 @@ Task *add_task (Window win)
|
|||||||
g_ptr_array_add(task_group, new_tsk2);
|
g_ptr_array_add(task_group, new_tsk2);
|
||||||
//printf("add_task panel %d, desktop %d, task %s\n", i, j, new_tsk2->title);
|
//printf("add_task panel %d, desktop %d, task %s\n", i, j, new_tsk2->title);
|
||||||
}
|
}
|
||||||
Window* key = malloc(sizeof(Window));
|
Window* key = calloc(1, sizeof(Window));
|
||||||
*key = new_tsk.win;
|
*key = new_tsk.win;
|
||||||
g_hash_table_insert(win_to_task_table, key, task_group);
|
g_hash_table_insert(win_to_task_table, key, task_group);
|
||||||
set_task_state(new_tsk2, new_tsk.current_state);
|
set_task_state(new_tsk2, new_tsk.current_state);
|
||||||
|
|
||||||
if (window_is_urgent(win))
|
sort_taskbar_for_win(win);
|
||||||
|
|
||||||
|
if (panel_mode == MULTI_DESKTOP) {
|
||||||
|
Panel *panel = new_tsk2->area.panel;
|
||||||
|
panel->area.resize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_is_urgent(win)) {
|
||||||
add_urgent(new_tsk2);
|
add_urgent(new_tsk2);
|
||||||
|
}
|
||||||
|
|
||||||
return new_tsk2;
|
return new_tsk2;
|
||||||
}
|
}
|
||||||
@@ -125,6 +138,11 @@ void remove_task (Task *tsk)
|
|||||||
{
|
{
|
||||||
if (!tsk) return;
|
if (!tsk) return;
|
||||||
|
|
||||||
|
if (panel_mode == MULTI_DESKTOP) {
|
||||||
|
Panel *panel = tsk->area.panel;
|
||||||
|
panel->area.resize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
Window win = tsk->win;
|
Window win = tsk->win;
|
||||||
|
|
||||||
// free title and icon just for the first task
|
// free title and icon just for the first task
|
||||||
@@ -165,7 +183,10 @@ int get_title(Task *tsk)
|
|||||||
Panel *panel = tsk->area.panel;
|
Panel *panel = tsk->area.panel;
|
||||||
char *title, *name;
|
char *title, *name;
|
||||||
|
|
||||||
if (!panel->g_task.text && !panel->g_task.tooltip_enabled) return 0;
|
if (!panel->g_task.text &&
|
||||||
|
!panel->g_task.tooltip_enabled &&
|
||||||
|
taskbar_sort_method != TASKBAR_SORT_TITLE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
name = server_get_property (tsk->win, server.atom._NET_WM_VISIBLE_NAME, server.atom.UTF8_STRING, 0);
|
name = server_get_property (tsk->win, server.atom._NET_WM_VISIBLE_NAME, server.atom.UTF8_STRING, 0);
|
||||||
if (!name || !strlen(name)) {
|
if (!name || !strlen(name)) {
|
||||||
@@ -173,14 +194,14 @@ int get_title(Task *tsk)
|
|||||||
if (!name || !strlen(name)) {
|
if (!name || !strlen(name)) {
|
||||||
name = server_get_property (tsk->win, server.atom.WM_NAME, XA_STRING, 0);
|
name = server_get_property (tsk->win, server.atom.WM_NAME, XA_STRING, 0);
|
||||||
if (!name || !strlen(name)) {
|
if (!name || !strlen(name)) {
|
||||||
name = malloc(10);
|
name = calloc(10, 1);
|
||||||
strcpy(name, "Untitled");
|
strcpy(name, "Untitled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add space before title
|
// add space before title
|
||||||
title = malloc(strlen(name)+2);
|
title = calloc(strlen(name)+2, 1);
|
||||||
if (panel->g_task.icon) strcpy(title, " ");
|
if (panel->g_task.icon) strcpy(title, " ");
|
||||||
else title[0] = 0;
|
else title[0] = 0;
|
||||||
strcat(title, name);
|
strcat(title, name);
|
||||||
@@ -313,7 +334,7 @@ void get_icon (Task *tsk)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO icons look too large when the panel is large
|
||||||
void draw_task_icon (Task *tsk, int text_width)
|
void draw_task_icon (Task *tsk, int text_width)
|
||||||
{
|
{
|
||||||
if (tsk->icon[tsk->current_state] == 0) return;
|
if (tsk->icon[tsk->current_state] == 0) return;
|
||||||
@@ -331,13 +352,9 @@ void draw_task_icon (Task *tsk, int text_width)
|
|||||||
|
|
||||||
// Render
|
// Render
|
||||||
imlib_context_set_image (tsk->icon[tsk->current_state]);
|
imlib_context_set_image (tsk->icon[tsk->current_state]);
|
||||||
if (server.real_transparency) {
|
imlib_context_set_blend(1);
|
||||||
render_image(tsk->area.pix, pos_x, panel->g_task.icon_posy, imlib_image_get_width(), imlib_image_get_height() );
|
imlib_context_set_drawable(tsk->area.pix);
|
||||||
}
|
imlib_render_image_on_drawable(pos_x, panel->g_task.icon_posy);
|
||||||
else {
|
|
||||||
imlib_context_set_drawable(tsk->area.pix);
|
|
||||||
imlib_render_image_on_drawable (pos_x, panel->g_task.icon_posy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -371,19 +388,11 @@ void draw_task (void *obj, cairo_t *c)
|
|||||||
pango_layout_get_pixel_size (layout, &width, &height);
|
pango_layout_get_pixel_size (layout, &width, &height);
|
||||||
|
|
||||||
config_text = &panel->g_task.font[tsk->current_state];
|
config_text = &panel->g_task.font[tsk->current_state];
|
||||||
cairo_set_source_rgba (c, config_text->color[0], config_text->color[1], config_text->color[2], config_text->alpha);
|
|
||||||
|
|
||||||
pango_cairo_update_layout (c, layout);
|
|
||||||
double text_posy = (panel->g_task.area.height - height) / 2.0;
|
double text_posy = (panel->g_task.area.height - height) / 2.0;
|
||||||
cairo_move_to (c, panel->g_task.text_posx, text_posy);
|
|
||||||
pango_cairo_show_layout (c, layout);
|
|
||||||
|
|
||||||
if (panel->g_task.font_shadow) {
|
draw_text(layout, c, panel->g_task.text_posx, text_posy, config_text, panel->font_shadow);
|
||||||
cairo_set_source_rgba (c, 0.0, 0.0, 0.0, 0.5);
|
|
||||||
pango_cairo_update_layout (c, layout);
|
|
||||||
cairo_move_to (c, panel->g_task.text_posx + 1, text_posy + 1);
|
|
||||||
pango_cairo_show_layout (c, layout);
|
|
||||||
}
|
|
||||||
g_object_unref (layout);
|
g_object_unref (layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,32 +416,26 @@ void on_change_task (void *obj)
|
|||||||
|
|
||||||
// Given a pointer to the active task (active_task) and a pointer
|
// Given a pointer to the active task (active_task) and a pointer
|
||||||
// to the task that is currently under the mouse (current_task),
|
// to the task that is currently under the mouse (current_task),
|
||||||
// return a pointer to the active task that is on the same desktop
|
// returns a pointer to the active task.
|
||||||
// as current_task. Normally this is simply active_task, except when
|
|
||||||
// it is set to appear on all desktops. In that case we search for
|
|
||||||
// another Task on current_task's taskbar, with the same window as
|
|
||||||
// active_task.
|
|
||||||
Task *find_active_task(Task *current_task, Task *active_task)
|
Task *find_active_task(Task *current_task, Task *active_task)
|
||||||
{
|
{
|
||||||
if (active_task == 0)
|
if (active_task == NULL)
|
||||||
return current_task;
|
return current_task;
|
||||||
if (active_task->desktop != ALLDESKTOP)
|
|
||||||
return active_task;
|
|
||||||
if (current_task == 0)
|
|
||||||
return active_task;
|
|
||||||
|
|
||||||
GSList *l0;
|
GSList *l0;
|
||||||
Task *tsk;
|
Task *tsk;
|
||||||
Taskbar* tskbar = current_task->area.parent;
|
Taskbar* tskbar = current_task->area.parent;
|
||||||
|
|
||||||
l0 = tskbar->area.list;
|
l0 = tskbar->area.list;
|
||||||
if (taskbarname_enabled) l0 = l0->next;
|
if (taskbarname_enabled)
|
||||||
|
l0 = l0->next;
|
||||||
for (; l0 ; l0 = l0->next) {
|
for (; l0 ; l0 = l0->next) {
|
||||||
tsk = l0->data;
|
tsk = l0->data;
|
||||||
if (tsk->win == active_task->win)
|
if (tsk->win == active_task->win)
|
||||||
return tsk;
|
return tsk;
|
||||||
}
|
}
|
||||||
return active_task;
|
|
||||||
|
return current_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task *next_task(Task *tsk)
|
Task *next_task(Task *tsk)
|
||||||
@@ -514,7 +517,7 @@ void set_task_state(Task *tsk, int state)
|
|||||||
if (tsk == 0 || state < 0 || state >= TASK_STATE_COUNT)
|
if (tsk == 0 || state < 0 || state >= TASK_STATE_COUNT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (tsk->current_state != state) {
|
if (tsk->current_state != state || hide_task_diff_monitor) {
|
||||||
GPtrArray* task_group = task_get_tasks(tsk->win);
|
GPtrArray* task_group = task_get_tasks(tsk->win);
|
||||||
if (task_group) {
|
if (task_group) {
|
||||||
int i;
|
int i;
|
||||||
@@ -527,6 +530,25 @@ void set_task_state(Task *tsk, int state)
|
|||||||
tsk1->area.redraw = 1;
|
tsk1->area.redraw = 1;
|
||||||
if (state == TASK_ACTIVE && g_slist_find(urgent_list, tsk1))
|
if (state == TASK_ACTIVE && g_slist_find(urgent_list, tsk1))
|
||||||
del_urgent(tsk1);
|
del_urgent(tsk1);
|
||||||
|
// Show only the active task
|
||||||
|
int hide = 0;
|
||||||
|
if (hide_inactive_tasks) {
|
||||||
|
if (state != TASK_ACTIVE) {
|
||||||
|
hide = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (window_get_monitor(tsk->win) != ((Panel*)tsk->area.panel)->monitor &&
|
||||||
|
(hide_task_diff_monitor || nb_panel > 1)) {
|
||||||
|
hide = 1;
|
||||||
|
}
|
||||||
|
if (1 - hide != tsk1->area.on_screen) {
|
||||||
|
tsk1->area.on_screen = 1 - hide;
|
||||||
|
set_task_redraw(tsk1);
|
||||||
|
Panel *p = (Panel*)tsk->area.panel;
|
||||||
|
tsk->area.resize = 1;
|
||||||
|
p->taskbar->area.resize = 1;
|
||||||
|
p->area.resize = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
}
|
}
|
||||||
@@ -580,16 +602,20 @@ void add_urgent(Task *tsk)
|
|||||||
// not yet in the list, so we have to add it
|
// not yet in the list, so we have to add it
|
||||||
urgent_list = g_slist_prepend(urgent_list, tsk);
|
urgent_list = g_slist_prepend(urgent_list, tsk);
|
||||||
|
|
||||||
if (urgent_timeout == 0)
|
if (!urgent_timeout)
|
||||||
urgent_timeout = add_timeout(10, 1000, blink_urgent, 0);
|
urgent_timeout = add_timeout(10, 1000, blink_urgent, 0, &urgent_timeout);
|
||||||
|
|
||||||
|
Panel *panel = tsk->area.panel;
|
||||||
|
if (panel->is_hidden)
|
||||||
|
autohide_show(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void del_urgent(Task *tsk)
|
void del_urgent(Task *tsk)
|
||||||
{
|
{
|
||||||
urgent_list = g_slist_remove(urgent_list, tsk);
|
urgent_list = g_slist_remove(urgent_list, tsk);
|
||||||
if (urgent_list == 0) {
|
if (!urgent_list) {
|
||||||
stop_timeout(urgent_timeout);
|
stop_timeout(urgent_timeout);
|
||||||
urgent_timeout = 0;
|
urgent_timeout = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ typedef struct {
|
|||||||
// starting position for text ~ task_padding + task_border + icon_size
|
// starting position for text ~ task_padding + task_border + icon_size
|
||||||
double text_posx, text_height;
|
double text_posx, text_height;
|
||||||
|
|
||||||
int font_shadow;
|
|
||||||
PangoFontDescription *font_desc;
|
PangoFontDescription *font_desc;
|
||||||
Color font[TASK_STATE_COUNT];
|
Color font[TASK_STATE_COUNT];
|
||||||
int config_font_mask;
|
int config_font_mask;
|
||||||
@@ -63,6 +62,11 @@ typedef struct {
|
|||||||
unsigned int icon_height;
|
unsigned int icon_height;
|
||||||
char *title;
|
char *title;
|
||||||
int urgent_tick;
|
int urgent_tick;
|
||||||
|
// These may not be up-to-date
|
||||||
|
int win_x;
|
||||||
|
int win_y;
|
||||||
|
int win_w;
|
||||||
|
int win_h;
|
||||||
} Task;
|
} Task;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
|
#include "strnatcmp.h"
|
||||||
|
|
||||||
|
|
||||||
/* win_to_task_table holds for every Window an array of tasks. Usually the array contains only one
|
/* win_to_task_table holds for every Window an array of tasks. Usually the array contains only one
|
||||||
@@ -42,6 +43,10 @@ GHashTable* win_to_task_table;
|
|||||||
Task *task_active;
|
Task *task_active;
|
||||||
Task *task_drag;
|
Task *task_drag;
|
||||||
int taskbar_enabled;
|
int taskbar_enabled;
|
||||||
|
int taskbar_distribute_size;
|
||||||
|
int hide_inactive_tasks;
|
||||||
|
int hide_task_diff_monitor;
|
||||||
|
int taskbar_sort_method;
|
||||||
|
|
||||||
guint win_hash(gconstpointer key) { return (guint)*((Window*)key); }
|
guint win_hash(gconstpointer key) { return (guint)*((Window*)key); }
|
||||||
gboolean win_compare(gconstpointer a, gconstpointer b) { return (*((Window*)a) == *((Window*)b)); }
|
gboolean win_compare(gconstpointer a, gconstpointer b) { return (*((Window*)a) == *((Window*)b)); }
|
||||||
@@ -50,10 +55,14 @@ void free_ptr_array(gpointer data) { g_ptr_array_free(data, 1); }
|
|||||||
|
|
||||||
void default_taskbar()
|
void default_taskbar()
|
||||||
{
|
{
|
||||||
win_to_task_table = 0;
|
win_to_task_table = NULL;
|
||||||
urgent_timeout = 0;
|
urgent_timeout = NULL;
|
||||||
urgent_list = 0;
|
urgent_list = NULL;
|
||||||
taskbar_enabled = 0;
|
taskbar_enabled = 0;
|
||||||
|
taskbar_distribute_size = 0;
|
||||||
|
hide_inactive_tasks = 0;
|
||||||
|
hide_task_diff_monitor = 0;
|
||||||
|
taskbar_sort_method = TASKBAR_NOSORT;
|
||||||
default_taskbarname();
|
default_taskbarname();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,28 +73,42 @@ void cleanup_taskbar()
|
|||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
cleanup_taskbarname();
|
cleanup_taskbarname();
|
||||||
if (win_to_task_table) g_hash_table_foreach(win_to_task_table, taskbar_remove_task, 0);
|
if (win_to_task_table) {
|
||||||
for (i=0 ; i < nb_panel ; i++) {
|
while (g_hash_table_size(win_to_task_table)) {
|
||||||
panel = &panel1[i];
|
GHashTableIter iter;
|
||||||
for (j=0 ; j < panel->nb_desktop ; j++) {
|
gpointer key, value;
|
||||||
tskbar = &panel->taskbar[j];
|
|
||||||
for (k=0; k<TASKBAR_STATE_COUNT; ++k) {
|
g_hash_table_iter_init(&iter, win_to_task_table);
|
||||||
if (tskbar->state_pix[k]) XFreePixmap(server.dsp, tskbar->state_pix[k]);
|
if (g_hash_table_iter_next(&iter, &key, &value)) {
|
||||||
|
taskbar_remove_task(key, 0, 0);
|
||||||
}
|
}
|
||||||
free_area (&tskbar->area);
|
}
|
||||||
|
g_hash_table_destroy(win_to_task_table);
|
||||||
|
win_to_task_table = NULL;
|
||||||
|
}
|
||||||
|
for (i = 0 ; i < nb_panel; i++) {
|
||||||
|
panel = &panel1[i];
|
||||||
|
for (j = 0; j < panel->nb_desktop; j++) {
|
||||||
|
tskbar = &panel->taskbar[j];
|
||||||
|
for (k = 0; k < TASKBAR_STATE_COUNT; ++k) {
|
||||||
|
if (tskbar->state_pix[k])
|
||||||
|
XFreePixmap(server.dsp, tskbar->state_pix[k]);
|
||||||
|
tskbar->state_pix[k] = 0;
|
||||||
|
}
|
||||||
|
free_area(&tskbar->area);
|
||||||
// remove taskbar from the panel
|
// remove taskbar from the panel
|
||||||
panel->area.list = g_slist_remove(panel->area.list, tskbar);
|
panel->area.list = g_slist_remove(panel->area.list, tskbar);
|
||||||
}
|
}
|
||||||
if (panel->taskbar) {
|
if (panel->taskbar) {
|
||||||
free(panel->taskbar);
|
free(panel->taskbar);
|
||||||
panel->taskbar = 0;
|
panel->taskbar = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (win_to_task_table) {
|
g_slist_free(urgent_list);
|
||||||
g_hash_table_destroy(win_to_task_table);
|
urgent_list = NULL;
|
||||||
win_to_task_table = 0;
|
|
||||||
}
|
stop_timeout(urgent_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -112,6 +135,8 @@ void init_taskbar_panel(void *p)
|
|||||||
panel->g_taskbar.background_name[TASKBAR_NORMAL] = &g_array_index(backgrounds, Background, 0);
|
panel->g_taskbar.background_name[TASKBAR_NORMAL] = &g_array_index(backgrounds, Background, 0);
|
||||||
panel->g_taskbar.background_name[TASKBAR_ACTIVE] = &g_array_index(backgrounds, Background, 0);
|
panel->g_taskbar.background_name[TASKBAR_ACTIVE] = &g_array_index(backgrounds, Background, 0);
|
||||||
}
|
}
|
||||||
|
if (!panel->g_task.font_desc)
|
||||||
|
panel->g_task.font_desc = pango_font_description_from_string(DEFAULT_FONT);
|
||||||
if (panel->g_task.area.bg == 0)
|
if (panel->g_task.area.bg == 0)
|
||||||
panel->g_task.area.bg = &g_array_index(backgrounds, Background, 0);
|
panel->g_task.area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
|
|
||||||
@@ -311,8 +336,11 @@ int resize_taskbar(void *obj)
|
|||||||
text_width = panel->g_task.maximum_width;
|
text_width = panel->g_task.maximum_width;
|
||||||
GSList *l = taskbar->area.list;
|
GSList *l = taskbar->area.list;
|
||||||
if (taskbarname_enabled) l = l->next;
|
if (taskbarname_enabled) l = l->next;
|
||||||
if (l != NULL) {
|
for (; l != NULL; l = l->next) {
|
||||||
text_width = ((Task *)l->data)->area.width;
|
if (((Task *)l->data)->area.on_screen) {
|
||||||
|
text_width = ((Task *)l->data)->area.width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
taskbar->text_width = text_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
|
taskbar->text_width = text_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
|
||||||
}
|
}
|
||||||
@@ -389,3 +417,143 @@ void visible_taskbar(void *p)
|
|||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NONTRIVIAL 2
|
||||||
|
gint compare_tasks_trivial(Task *a, Task *b, Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
if (a == b)
|
||||||
|
return 0;
|
||||||
|
if (taskbarname_enabled) {
|
||||||
|
if (a == taskbar->area.list->data)
|
||||||
|
return -1;
|
||||||
|
if (b == taskbar->area.list->data)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return NONTRIVIAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint contained_within(Task *a, Task *b)
|
||||||
|
{
|
||||||
|
if ((a->win_x <= b->win_x) &&
|
||||||
|
(a->win_y <= b->win_y) &&
|
||||||
|
(a->win_x + a->win_w >= b->win_x + b->win_w) &&
|
||||||
|
(a->win_y + a->win_h >= b->win_y + b->win_h)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint compare_task_centers(Task *a, Task *b, Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
||||||
|
if (trivial != NONTRIVIAL)
|
||||||
|
return trivial;
|
||||||
|
|
||||||
|
// If a window has the same coordinates and size as the other,
|
||||||
|
// they are considered to be equal in the comparison.
|
||||||
|
if ((a->win_x == b->win_x) &&
|
||||||
|
(a->win_y == b->win_y) &&
|
||||||
|
(a->win_w == b->win_w) &&
|
||||||
|
(a->win_h == b->win_h)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a window is completely contained in another,
|
||||||
|
// then it is considered to come after (to the right/bottom) of the other.
|
||||||
|
if (contained_within(a, b))
|
||||||
|
return -1;
|
||||||
|
if (contained_within(b, a))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Compare centers
|
||||||
|
int a_horiz_c, a_vert_c, b_horiz_c, b_vert_c;
|
||||||
|
a_horiz_c = a->win_x + a->win_w / 2;
|
||||||
|
b_horiz_c = b->win_x + b->win_w / 2;
|
||||||
|
a_vert_c = a->win_y + a->win_h / 2;
|
||||||
|
b_vert_c = b->win_y + b->win_h / 2;
|
||||||
|
if (panel_horizontal) {
|
||||||
|
if (a_horiz_c != b_horiz_c) {
|
||||||
|
return a_horiz_c - b_horiz_c;
|
||||||
|
}
|
||||||
|
return a_vert_c - b_vert_c;
|
||||||
|
} else {
|
||||||
|
if (a_vert_c != b_vert_c) {
|
||||||
|
return a_vert_c - b_vert_c;
|
||||||
|
}
|
||||||
|
return a_horiz_c - b_horiz_c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gint compare_task_titles(Task *a, Task *b, Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
||||||
|
if (trivial != NONTRIVIAL)
|
||||||
|
return trivial;
|
||||||
|
return strnatcasecmp(a->title ? a->title : "", b->title ? b->title : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
||||||
|
if (trivial != NONTRIVIAL)
|
||||||
|
return trivial;
|
||||||
|
if (taskbar_sort_method == TASKBAR_NOSORT) {
|
||||||
|
return 0;
|
||||||
|
} else if (taskbar_sort_method == TASKBAR_SORT_CENTER) {
|
||||||
|
return compare_task_centers(a, b, taskbar);
|
||||||
|
} else if (taskbar_sort_method == TASKBAR_SORT_TITLE) {
|
||||||
|
return compare_task_titles(a, b, taskbar);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int taskbar_needs_sort(Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
if (taskbar_sort_method == TASKBAR_NOSORT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
GSList *i, *j;
|
||||||
|
for (i = taskbar->area.list, j = i ? i->next : NULL; i && j; i = i->next, j = j->next) {
|
||||||
|
if (compare_tasks(i->data, j->data, taskbar) > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sort_tasks(Taskbar *taskbar)
|
||||||
|
{
|
||||||
|
if (!taskbar)
|
||||||
|
return;
|
||||||
|
if (!taskbar_needs_sort(taskbar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
taskbar->area.list = g_slist_sort_with_data(taskbar->area.list, (GCompareDataFunc)compare_tasks, taskbar);
|
||||||
|
taskbar->area.resize = 1;
|
||||||
|
panel_refresh = 1;
|
||||||
|
((Panel*)taskbar->area.panel)->area.resize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sort_taskbar_for_win(Window win)
|
||||||
|
{
|
||||||
|
if (taskbar_sort_method == TASKBAR_NOSORT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GPtrArray* task_group = task_get_tasks(win);
|
||||||
|
if (task_group) {
|
||||||
|
int i;
|
||||||
|
Task* tsk0 = g_ptr_array_index(task_group, 0);
|
||||||
|
if (tsk0) {
|
||||||
|
window_get_coordinates(win, &tsk0->win_x, &tsk0->win_y, &tsk0->win_w, &tsk0->win_h);
|
||||||
|
}
|
||||||
|
for (i = 0; i < task_group->len; ++i) {
|
||||||
|
Task* tsk = g_ptr_array_index(task_group, i);
|
||||||
|
tsk->win_x = tsk0->win_x;
|
||||||
|
tsk->win_y = tsk0->win_y;
|
||||||
|
tsk->win_w = tsk0->win_w;
|
||||||
|
tsk->win_h = tsk0->win_h;
|
||||||
|
sort_tasks(tsk->area.parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,18 +12,22 @@
|
|||||||
#include "taskbarname.h"
|
#include "taskbarname.h"
|
||||||
|
|
||||||
enum { TASKBAR_NORMAL, TASKBAR_ACTIVE, TASKBAR_STATE_COUNT };
|
enum { TASKBAR_NORMAL, TASKBAR_ACTIVE, TASKBAR_STATE_COUNT };
|
||||||
extern GHashTable* win_to_task_table;
|
extern GHashTable *win_to_task_table;
|
||||||
extern Task *task_active;
|
extern Task *task_active;
|
||||||
extern Task *task_drag;
|
extern Task *task_drag;
|
||||||
extern int taskbar_enabled;
|
extern int taskbar_enabled;
|
||||||
|
extern int taskbar_distribute_size;
|
||||||
|
extern int hide_inactive_tasks;
|
||||||
|
extern int hide_task_diff_monitor;
|
||||||
|
enum { TASKBAR_NOSORT, TASKBAR_SORT_CENTER, TASKBAR_SORT_TITLE };
|
||||||
|
extern int taskbar_sort_method;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// always start with area
|
// always start with area
|
||||||
Area area;
|
Area area;
|
||||||
Pixmap state_pix[TASKBAR_STATE_COUNT];
|
Pixmap state_pix[TASKBAR_STATE_COUNT];
|
||||||
|
|
||||||
char *name;
|
gchar *name;
|
||||||
int posy;
|
int posy;
|
||||||
} Taskbarname;
|
} Taskbarname;
|
||||||
|
|
||||||
@@ -72,6 +76,8 @@ void set_taskbar_state(Taskbar *tskbar, int state);
|
|||||||
// show/hide taskbar according to current desktop
|
// show/hide taskbar according to current desktop
|
||||||
void visible_taskbar(void *p);
|
void visible_taskbar(void *p);
|
||||||
|
|
||||||
|
void sort_taskbar_for_win(Window win);
|
||||||
|
void sort_tasks(Taskbar *taskbar);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Color taskbarname_active_font;
|
|||||||
void default_taskbarname()
|
void default_taskbarname()
|
||||||
{
|
{
|
||||||
taskbarname_enabled = 0;
|
taskbarname_enabled = 0;
|
||||||
taskbarname_font_desc = 0;
|
taskbarname_font_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +51,11 @@ void init_taskbarname_panel(void *p)
|
|||||||
Taskbar *tskbar;
|
Taskbar *tskbar;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (!taskbarname_enabled) return;
|
if (!taskbarname_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!taskbarname_font_desc)
|
||||||
|
taskbarname_font_desc = pango_font_description_from_string(DEFAULT_FONT);
|
||||||
|
|
||||||
GSList *l, *list = server_get_name_of_desktop();
|
GSList *l, *list = server_get_name_of_desktop();
|
||||||
for (j=0, l=list ; j < panel->nb_desktop ; j++) {
|
for (j=0, l=list ; j < panel->nb_desktop ; j++) {
|
||||||
@@ -87,18 +91,24 @@ void cleanup_taskbarname()
|
|||||||
Panel *panel;
|
Panel *panel;
|
||||||
Taskbar *tskbar;
|
Taskbar *tskbar;
|
||||||
|
|
||||||
for (i=0 ; i < nb_panel ; i++) {
|
for (i = 0; i < nb_panel; i++) {
|
||||||
panel = &panel1[i];
|
panel = &panel1[i];
|
||||||
for (j=0 ; j < panel->nb_desktop ; j++) {
|
for (j = 0; j < panel->nb_desktop; j++) {
|
||||||
tskbar = &panel->taskbar[j];
|
tskbar = &panel->taskbar[j];
|
||||||
if (tskbar->bar_name.name) g_free(tskbar->bar_name.name);
|
g_free(tskbar->bar_name.name);
|
||||||
free_area (&tskbar->bar_name.area);
|
tskbar->bar_name.name = NULL;
|
||||||
for (k=0; k<TASKBAR_STATE_COUNT; ++k) {
|
free_area(&tskbar->bar_name.area);
|
||||||
if (tskbar->bar_name.state_pix[k]) XFreePixmap(server.dsp, tskbar->bar_name.state_pix[k]);
|
for (k = 0; k < TASKBAR_STATE_COUNT; ++k) {
|
||||||
|
if (tskbar->bar_name.state_pix[k])
|
||||||
|
XFreePixmap(server.dsp, tskbar->bar_name.state_pix[k]);
|
||||||
|
tskbar->bar_name.state_pix[k] = 0;
|
||||||
}
|
}
|
||||||
tskbar->area.list = g_slist_remove(tskbar->area.list, &tskbar->bar_name);
|
tskbar->area.list = g_slist_remove(tskbar->area.list, &tskbar->bar_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pango_font_description_free(taskbarname_font_desc);
|
||||||
|
taskbarname_font_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -122,8 +132,7 @@ void draw_taskbarname (void *obj, cairo_t *c)
|
|||||||
cairo_set_source_rgba (c, config_text->color[0], config_text->color[1], config_text->color[2], config_text->alpha);
|
cairo_set_source_rgba (c, config_text->color[0], config_text->color[1], config_text->color[2], config_text->alpha);
|
||||||
|
|
||||||
pango_cairo_update_layout (c, layout);
|
pango_cairo_update_layout (c, layout);
|
||||||
cairo_move_to (c, 0, taskbar_name->posy);
|
draw_text(layout, c, 0, taskbar_name->posy, config_text, ((Panel*)taskbar_name->area.panel)->font_shadow);
|
||||||
pango_cairo_show_layout (c, layout);
|
|
||||||
|
|
||||||
g_object_unref (layout);
|
g_object_unref (layout);
|
||||||
//printf("draw_taskbarname %s ******************************\n", taskbar_name->name);
|
//printf("draw_taskbarname %s ******************************\n", taskbar_name->name);
|
||||||
|
|||||||
580
src/tint.c
580
src/tint.c
@@ -30,8 +30,6 @@
|
|||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
@@ -59,84 +57,6 @@ Atom dnd_selection;
|
|||||||
Atom dnd_atom;
|
Atom dnd_atom;
|
||||||
int dnd_sent_request;
|
int dnd_sent_request;
|
||||||
char *dnd_launcher_exec;
|
char *dnd_launcher_exec;
|
||||||
gboolean debug_fps = FALSE;
|
|
||||||
float *fps_distribution = NULL;
|
|
||||||
|
|
||||||
void create_fps_distribution()
|
|
||||||
{
|
|
||||||
// measure FPS with resolution:
|
|
||||||
// 0-59: 1 (60 samples)
|
|
||||||
// 60-199: 10 (14)
|
|
||||||
// 200-1,999: 25 (72)
|
|
||||||
// 1k-19,999: 1000 (19)
|
|
||||||
// 20x+: inf (1)
|
|
||||||
// => 166 samples
|
|
||||||
if (fps_distribution)
|
|
||||||
return;
|
|
||||||
fps_distribution = calloc(170, sizeof(float));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cleanup_fps_distribution()
|
|
||||||
{
|
|
||||||
free(fps_distribution);
|
|
||||||
fps_distribution = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sample_fps(double fps)
|
|
||||||
{
|
|
||||||
int fps_rounded = (int)(fps + 0.5);
|
|
||||||
int i = 1;
|
|
||||||
if (fps_rounded < 60) {
|
|
||||||
i += fps_rounded;
|
|
||||||
} else {
|
|
||||||
i += 60;
|
|
||||||
if (fps_rounded < 200) {
|
|
||||||
i += (fps_rounded - 60) / 10;
|
|
||||||
} else {
|
|
||||||
i += 14;
|
|
||||||
if (fps_rounded < 2000) {
|
|
||||||
i += (fps_rounded - 200) / 25;
|
|
||||||
} else {
|
|
||||||
i += 72;
|
|
||||||
if (fps_rounded < 20000) {
|
|
||||||
i += (fps_rounded - 2000) / 1000;
|
|
||||||
} else {
|
|
||||||
i += 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fprintf(stderr, "fps = %.0f => i = %d\n", fps, i);
|
|
||||||
fps_distribution[i] += 1.;
|
|
||||||
fps_distribution[0] += 1.;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fps_compute_stats(double *low, double *median, double *high, double *samples)
|
|
||||||
{
|
|
||||||
*median = *low = *high = *samples = -1;
|
|
||||||
if (!fps_distribution || fps_distribution[0] < 1)
|
|
||||||
return;
|
|
||||||
float total = fps_distribution[0];
|
|
||||||
*samples = (double) fps_distribution[0];
|
|
||||||
float cum_low = 0.05f * total;
|
|
||||||
float cum_median = 0.5f * total;
|
|
||||||
float cum_high = 0.95f * total;
|
|
||||||
float cum = 0;
|
|
||||||
int i;
|
|
||||||
for (i = 1; i <= 166; i++) {
|
|
||||||
double value =
|
|
||||||
(i < 60) ? i : (i < 74) ? (60 + (i - 60) * 10) : (i < 146) ? (200 + (i - 74) * 25)
|
|
||||||
: (i < 165) ? (2000 + (i - 146) * 1000) : 20000;
|
|
||||||
// fprintf(stderr, "%6.0f (i = %3d) : %.0f | ", value, i, (double)fps_distribution[i]);
|
|
||||||
cum += fps_distribution[i];
|
|
||||||
if (*low < 0 && cum >= cum_low)
|
|
||||||
*low = value;
|
|
||||||
if (*median < 0 && cum >= cum_median)
|
|
||||||
*median = value;
|
|
||||||
if (*high < 0 && cum >= cum_high)
|
|
||||||
*high = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void signal_handler(int sig)
|
void signal_handler(int sig)
|
||||||
{
|
{
|
||||||
@@ -203,27 +123,22 @@ void init (int argc, char *argv[])
|
|||||||
// sigaddset(&block_mask, SIGHUP);
|
// sigaddset(&block_mask, SIGHUP);
|
||||||
// sigaddset(&block_mask, SIGUSR1);
|
// sigaddset(&block_mask, SIGUSR1);
|
||||||
// sigprocmask(SIG_BLOCK, &block_mask, 0);
|
// sigprocmask(SIG_BLOCK, &block_mask, 0);
|
||||||
debug_fps = getenv("DEBUG_FPS") != NULL;
|
|
||||||
if (debug_fps)
|
|
||||||
create_fps_distribution();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sn_pipe_valid = 0;
|
||||||
|
static int sn_pipe[2];
|
||||||
|
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
static int error_trap_depth = 0;
|
static int error_trap_depth = 0;
|
||||||
|
|
||||||
static void
|
static void error_trap_push(SnDisplay *display, Display *xdisplay)
|
||||||
error_trap_push (SnDisplay *display,
|
|
||||||
Display *xdisplay)
|
|
||||||
{
|
{
|
||||||
++error_trap_depth;
|
++error_trap_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void error_trap_pop(SnDisplay *display, Display *xdisplay)
|
||||||
error_trap_pop (SnDisplay *display,
|
|
||||||
Display *xdisplay)
|
|
||||||
{
|
{
|
||||||
if (error_trap_depth == 0)
|
if (error_trap_depth == 0) {
|
||||||
{
|
|
||||||
fprintf(stderr, "Error trap underflow!\n");
|
fprintf(stderr, "Error trap underflow!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -233,16 +148,27 @@ error_trap_pop (SnDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sigchld_handler(int sig) {
|
static void sigchld_handler(int sig) {
|
||||||
// Wait for all dead processes
|
if (!startup_notifications)
|
||||||
pid_t pid;
|
return;
|
||||||
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
|
if (!sn_pipe_valid)
|
||||||
SnLauncherContext *ctx;
|
return;
|
||||||
|
ssize_t wur = write(sn_pipe[1], "x", 1);
|
||||||
|
(void) wur;
|
||||||
|
fsync(sn_pipe[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sigchld_handler_async() {
|
||||||
|
if (!startup_notifications)
|
||||||
|
return;
|
||||||
|
// Wait for all dead processes
|
||||||
|
pid_t pid;
|
||||||
|
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
|
||||||
|
SnLauncherContext *ctx;
|
||||||
ctx = (SnLauncherContext *) g_tree_lookup (server.pids, GINT_TO_POINTER (pid));
|
ctx = (SnLauncherContext *) g_tree_lookup (server.pids, GINT_TO_POINTER (pid));
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
fprintf(stderr, "Unknown child %d terminated!\n", pid);
|
fprintf(stderr, "Unknown child %d terminated!\n", pid);
|
||||||
}
|
} else {
|
||||||
else {
|
g_tree_remove (server.pids, GINT_TO_POINTER (pid));
|
||||||
g_tree_remove (server.pids, GINT_TO_POINTER (pid));
|
|
||||||
sn_launcher_context_complete (ctx);
|
sn_launcher_context_complete (ctx);
|
||||||
sn_launcher_context_unref (ctx);
|
sn_launcher_context_unref (ctx);
|
||||||
}
|
}
|
||||||
@@ -250,17 +176,18 @@ static void sigchld_handler(int sig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gint cmp_ptr(gconstpointer a, gconstpointer b) {
|
static gint cmp_ptr(gconstpointer a, gconstpointer b) {
|
||||||
if (a < b)
|
if (a < b)
|
||||||
return -1;
|
return -1;
|
||||||
else if (a == b)
|
else if (a == b)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static void sigchld_handler_async() {}
|
||||||
#endif // HAVE_SN
|
#endif // HAVE_SN
|
||||||
|
|
||||||
void init_X11()
|
void init_X11_pre_config()
|
||||||
{
|
{
|
||||||
server.dsp = XOpenDisplay (NULL);
|
server.dsp = XOpenDisplay (NULL);
|
||||||
if (!server.dsp) {
|
if (!server.dsp) {
|
||||||
@@ -271,19 +198,40 @@ void init_X11()
|
|||||||
server.screen = DefaultScreen (server.dsp);
|
server.screen = DefaultScreen (server.dsp);
|
||||||
server.root_win = RootWindow(server.dsp, server.screen);
|
server.root_win = RootWindow(server.dsp, server.screen);
|
||||||
server.desktop = server_get_current_desktop ();
|
server.desktop = server_get_current_desktop ();
|
||||||
|
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
// config file use '.' as decimal separator
|
||||||
|
setlocale(LC_NUMERIC, "POSIX");
|
||||||
|
|
||||||
|
// get monitor and desktop config
|
||||||
|
get_monitors();
|
||||||
|
get_desktops();
|
||||||
|
|
||||||
|
server.disable_transparency = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_X11_post_config()
|
||||||
|
{
|
||||||
server_init_visual();
|
server_init_visual();
|
||||||
XSetErrorHandler ((XErrorHandler) server_catch_error);
|
XSetErrorHandler ((XErrorHandler) server_catch_error);
|
||||||
|
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
// Initialize startup-notification
|
// Initialize startup-notification
|
||||||
server.sn_dsp = sn_display_new (server.dsp, error_trap_push, error_trap_pop);
|
if (startup_notifications) {
|
||||||
server.pids = g_tree_new (cmp_ptr);
|
server.sn_dsp = sn_display_new (server.dsp, error_trap_push, error_trap_pop);
|
||||||
// Setup a handler for child termination
|
server.pids = g_tree_new (cmp_ptr);
|
||||||
struct sigaction act;
|
// Setup a handler for child termination
|
||||||
memset (&act, 0, sizeof (struct sigaction));
|
if (pipe(sn_pipe) != 0) {
|
||||||
act.sa_handler = sigchld_handler;
|
fprintf(stderr, "Creating pipe failed.\n");
|
||||||
if (sigaction(SIGCHLD, &act, 0)) {
|
} else {
|
||||||
perror("sigaction");
|
sn_pipe_valid = 1;
|
||||||
|
struct sigaction act;
|
||||||
|
memset (&act, 0, sizeof (struct sigaction));
|
||||||
|
act.sa_handler = sigchld_handler;
|
||||||
|
if (sigaction(SIGCHLD, &act, 0)) {
|
||||||
|
perror("sigaction");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // HAVE_SN
|
#endif // HAVE_SN
|
||||||
|
|
||||||
@@ -293,10 +241,6 @@ void init_X11()
|
|||||||
|
|
||||||
/* Catch events */
|
/* Catch events */
|
||||||
XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
|
XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
|
||||||
|
|
||||||
setlocale (LC_ALL, "");
|
|
||||||
// config file use '.' as decimal separator
|
|
||||||
setlocale(LC_NUMERIC, "POSIX");
|
|
||||||
|
|
||||||
// load default icon
|
// load default icon
|
||||||
gchar *path;
|
gchar *path;
|
||||||
@@ -309,10 +253,6 @@ void init_X11()
|
|||||||
default_icon = imlib_load_image(path);
|
default_icon = imlib_load_image(path);
|
||||||
g_free(path);
|
g_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get monitor and desktop config
|
|
||||||
get_monitors();
|
|
||||||
get_desktops();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -331,13 +271,25 @@ void cleanup()
|
|||||||
if (default_icon) {
|
if (default_icon) {
|
||||||
imlib_context_set_image(default_icon);
|
imlib_context_set_image(default_icon);
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
|
default_icon = NULL;
|
||||||
}
|
}
|
||||||
imlib_context_disconnect_display();
|
imlib_context_disconnect_display();
|
||||||
|
|
||||||
cleanup_server();
|
cleanup_server();
|
||||||
cleanup_timeout();
|
cleanup_timeout();
|
||||||
if (server.dsp) XCloseDisplay(server.dsp);
|
if (server.dsp)
|
||||||
cleanup_fps_distribution();
|
XCloseDisplay(server.dsp);
|
||||||
|
server.dsp = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_SN
|
||||||
|
if (startup_notifications) {
|
||||||
|
if (sn_pipe_valid) {
|
||||||
|
sn_pipe_valid = 0;
|
||||||
|
close(sn_pipe[1]);
|
||||||
|
close(sn_pipe[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -433,7 +385,7 @@ int tint2_handles_click(Panel* panel, XButtonEvent* e)
|
|||||||
{
|
{
|
||||||
Task* task = click_task(panel, e->x, e->y);
|
Task* task = click_task(panel, e->x, e->y);
|
||||||
if (task) {
|
if (task) {
|
||||||
if( (e->button == 1)
|
if( (e->button == 1 && mouse_left != 0)
|
||||||
|| (e->button == 2 && mouse_middle != 0)
|
|| (e->button == 2 && mouse_middle != 0)
|
||||||
|| (e->button == 3 && mouse_right != 0)
|
|| (e->button == 3 && mouse_right != 0)
|
||||||
|| (e->button == 4 && mouse_scroll_up != 0)
|
|| (e->button == 4 && mouse_scroll_up != 0)
|
||||||
@@ -513,17 +465,21 @@ void event_button_motion_notify (XEvent *e)
|
|||||||
|
|
||||||
// If the event takes place on the same taskbar as the task being dragged
|
// If the event takes place on the same taskbar as the task being dragged
|
||||||
if(event_taskbar == task_drag->area.parent) {
|
if(event_taskbar == task_drag->area.parent) {
|
||||||
// Swap the task_drag with the task on the event's location (if they differ)
|
if (taskbar_sort_method != TASKBAR_NOSORT) {
|
||||||
if(event_task && event_task != task_drag) {
|
sort_tasks(event_taskbar);
|
||||||
GSList * drag_iter = g_slist_find(event_taskbar->area.list, task_drag);
|
} else {
|
||||||
GSList * task_iter = g_slist_find(event_taskbar->area.list, event_task);
|
// Swap the task_drag with the task on the event's location (if they differ)
|
||||||
if(drag_iter && task_iter) {
|
if(event_task && event_task != task_drag) {
|
||||||
gpointer temp = task_iter->data;
|
GSList * drag_iter = g_slist_find(event_taskbar->area.list, task_drag);
|
||||||
task_iter->data = drag_iter->data;
|
GSList * task_iter = g_slist_find(event_taskbar->area.list, event_task);
|
||||||
drag_iter->data = temp;
|
if(drag_iter && task_iter) {
|
||||||
event_taskbar->area.resize = 1;
|
gpointer temp = task_iter->data;
|
||||||
panel_refresh = 1;
|
task_iter->data = drag_iter->data;
|
||||||
task_dragged = 1;
|
drag_iter->data = temp;
|
||||||
|
event_taskbar->area.resize = 1;
|
||||||
|
panel_refresh = 1;
|
||||||
|
task_dragged = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -547,10 +503,15 @@ void event_button_motion_notify (XEvent *e)
|
|||||||
|
|
||||||
windows_set_desktop(task_drag->win, event_taskbar->desktop);
|
windows_set_desktop(task_drag->win, event_taskbar->desktop);
|
||||||
|
|
||||||
|
if (taskbar_sort_method != TASKBAR_NOSORT) {
|
||||||
|
sort_tasks(event_taskbar);
|
||||||
|
}
|
||||||
|
|
||||||
event_taskbar->area.resize = 1;
|
event_taskbar->area.resize = 1;
|
||||||
drag_taskbar->area.resize = 1;
|
drag_taskbar->area.resize = 1;
|
||||||
task_dragged = 1;
|
task_dragged = 1;
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
|
panel->area.resize = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,6 +530,9 @@ void event_button_release (XEvent *e)
|
|||||||
|
|
||||||
int action = TOGGLE_ICONIFY;
|
int action = TOGGLE_ICONIFY;
|
||||||
switch (e->xbutton.button) {
|
switch (e->xbutton.button) {
|
||||||
|
case 1:
|
||||||
|
action = mouse_left;
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
action = mouse_middle;
|
action = mouse_middle;
|
||||||
break;
|
break;
|
||||||
@@ -597,7 +561,7 @@ void event_button_release (XEvent *e)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( click_launcher(panel, e->xbutton.x, e->xbutton.y)) {
|
if (e->xbutton.button == 1 && click_launcher(panel, e->xbutton.x, e->xbutton.y)) {
|
||||||
LauncherIcon *icon = click_launcher_icon(panel, e->xbutton.x, e->xbutton.y);
|
LauncherIcon *icon = click_launcher_icon(panel, e->xbutton.x, e->xbutton.y);
|
||||||
if (icon) {
|
if (icon) {
|
||||||
launcher_action(icon, e);
|
launcher_action(icon, e);
|
||||||
@@ -685,7 +649,7 @@ void event_property_notify (XEvent *e)
|
|||||||
// Change number of desktops
|
// Change number of desktops
|
||||||
else if (at == server.atom._NET_NUMBER_OF_DESKTOPS) {
|
else if (at == server.atom._NET_NUMBER_OF_DESKTOPS) {
|
||||||
if (!taskbar_enabled) return;
|
if (!taskbar_enabled) return;
|
||||||
server.nb_desktop = server_get_number_of_desktop ();
|
server.nb_desktop = server_get_number_of_desktops();
|
||||||
if (server.nb_desktop <= server.desktop) {
|
if (server.nb_desktop <= server.desktop) {
|
||||||
server.desktop = server.nb_desktop-1;
|
server.desktop = server.nb_desktop-1;
|
||||||
}
|
}
|
||||||
@@ -724,6 +688,8 @@ void event_property_notify (XEvent *e)
|
|||||||
tsk->area.on_screen = 0;
|
tsk->area.on_screen = 0;
|
||||||
tskbar->area.resize = 1;
|
tskbar->area.resize = 1;
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
|
if (panel_mode == MULTI_DESKTOP)
|
||||||
|
panel->area.resize = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -735,6 +701,8 @@ void event_property_notify (XEvent *e)
|
|||||||
if (tsk->desktop == ALLDESKTOP) {
|
if (tsk->desktop == ALLDESKTOP) {
|
||||||
tsk->area.on_screen = 1;
|
tsk->area.on_screen = 1;
|
||||||
tskbar->area.resize = 1;
|
tskbar->area.resize = 1;
|
||||||
|
if (panel_mode == MULTI_DESKTOP)
|
||||||
|
panel->area.resize = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -786,6 +754,8 @@ void event_property_notify (XEvent *e)
|
|||||||
tooltip_copy_text((Area*)tsk);
|
tooltip_copy_text((Area*)tsk);
|
||||||
tooltip_update();
|
tooltip_update();
|
||||||
}
|
}
|
||||||
|
if (taskbar_sort_method == TASKBAR_SORT_TITLE)
|
||||||
|
sort_taskbar_for_win(win);
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -870,20 +840,26 @@ void event_configure_notify (Window win)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 'win' move in another monitor
|
// 'win' move in another monitor
|
||||||
if (nb_panel == 1) return;
|
if (nb_panel > 1 || hide_task_diff_monitor) {
|
||||||
Task *tsk = task_get_task (win);
|
Task *tsk = task_get_task (win);
|
||||||
if (!tsk) return;
|
if (tsk) {
|
||||||
|
Panel *p = tsk->area.panel;
|
||||||
Panel *p = tsk->area.panel;
|
int monitor = window_get_monitor(win);
|
||||||
if (p->monitor != window_get_monitor (win)) {
|
if ((hide_task_diff_monitor && p->monitor != monitor && tsk->area.on_screen) ||
|
||||||
remove_task (tsk);
|
(hide_task_diff_monitor && p->monitor == monitor && !tsk->area.on_screen) ||
|
||||||
tsk = add_task (win);
|
(p->monitor != monitor && nb_panel > 1)) {
|
||||||
if (win == window_get_active ()) {
|
remove_task (tsk);
|
||||||
set_task_state(tsk, TASK_ACTIVE);
|
tsk = add_task (win);
|
||||||
task_active = tsk;
|
if (win == window_get_active ()) {
|
||||||
|
set_task_state(tsk, TASK_ACTIVE);
|
||||||
|
task_active = tsk;
|
||||||
|
}
|
||||||
|
panel_refresh = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
panel_refresh = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort_taskbar_for_win(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *GetAtomName(Display* disp, Atom a)
|
char *GetAtomName(Display* disp, Atom a)
|
||||||
@@ -1095,19 +1071,6 @@ void dnd_drop(XClientMessageEvent *e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double get_time()
|
|
||||||
{
|
|
||||||
struct timespec cur_time;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &cur_time);
|
|
||||||
return cur_time.tv_sec + cur_time.tv_nsec * 1.0e-9;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GREEN "\033[1;32m"
|
|
||||||
#define YELLOW "\033[1;33m"
|
|
||||||
#define RED "\033[1;31m"
|
|
||||||
#define BLUE "\033[1;34m"
|
|
||||||
#define RESET "\033[0m"
|
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
XEvent e;
|
XEvent e;
|
||||||
@@ -1119,9 +1082,14 @@ int main (int argc, char *argv[])
|
|||||||
struct timeval* timeout;
|
struct timeval* timeout;
|
||||||
int hidden_dnd = 0;
|
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)
|
||||||
|
setlinebuf(stdout);
|
||||||
|
setlinebuf(stderr);
|
||||||
|
|
||||||
start:
|
start:
|
||||||
init (argc, argv);
|
init (argc, argv);
|
||||||
init_X11();
|
|
||||||
|
init_X11_pre_config();
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (config_path)
|
if (config_path)
|
||||||
@@ -1134,6 +1102,8 @@ start:
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_X11_post_config();
|
||||||
|
|
||||||
init_panel();
|
init_panel();
|
||||||
if (snapshot_path) {
|
if (snapshot_path) {
|
||||||
get_snapshot(snapshot_path);
|
get_snapshot(snapshot_path);
|
||||||
@@ -1158,14 +1128,8 @@ start:
|
|||||||
// sigset_t empty_mask;
|
// sigset_t empty_mask;
|
||||||
// sigemptyset(&empty_mask);
|
// sigemptyset(&empty_mask);
|
||||||
|
|
||||||
double ts_event_read = 0;
|
|
||||||
double ts_event_processed = 0;
|
|
||||||
double ts_render_finished = 0;
|
|
||||||
double ts_flush_finished = 0;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (panel_refresh) {
|
if (panel_refresh) {
|
||||||
if (debug_fps)
|
|
||||||
ts_event_processed = get_time();
|
|
||||||
panel_refresh = 0;
|
panel_refresh = 0;
|
||||||
|
|
||||||
for (i=0 ; i < nb_panel ; i++) {
|
for (i=0 ; i < nb_panel ; i++) {
|
||||||
@@ -1192,37 +1156,17 @@ start:
|
|||||||
// force icon's refresh
|
// force icon's refresh
|
||||||
refresh_systray_icon();
|
refresh_systray_icon();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_fps)
|
|
||||||
ts_render_finished = get_time();
|
|
||||||
if (debug_fps && ts_event_read > 0) {
|
|
||||||
ts_flush_finished = get_time();
|
|
||||||
double period = ts_flush_finished - ts_event_read;
|
|
||||||
double fps = 1.0 / period;
|
|
||||||
sample_fps(fps);
|
|
||||||
double proc_ratio = (ts_event_processed - ts_event_read) / period;
|
|
||||||
double render_ratio = (ts_render_finished - ts_event_processed) / period;
|
|
||||||
double flush_ratio = (ts_flush_finished - ts_render_finished) / period;
|
|
||||||
double fps_low, fps_median, fps_high, fps_samples;
|
|
||||||
fps_compute_stats(&fps_low, &fps_median, &fps_high, &fps_samples);
|
|
||||||
fprintf(stderr,
|
|
||||||
BLUE "fps = %.0f (low %.0f, med %.0f, high %.0f, samples %.0f) : processing %.0f%%, rendering %.0f%%, "
|
|
||||||
"flushing %.0f%%" RESET "\n",
|
|
||||||
fps,
|
|
||||||
fps_low,
|
|
||||||
fps_median,
|
|
||||||
fps_high,
|
|
||||||
fps_samples,
|
|
||||||
proc_ratio * 100,
|
|
||||||
render_ratio * 100,
|
|
||||||
flush_ratio * 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// thanks to AngryLlama for the timer
|
// thanks to AngryLlama for the timer
|
||||||
// Create a File Description Set containing x11_fd
|
// Create a File Description Set containing x11_fd
|
||||||
FD_ZERO (&fdset);
|
FD_ZERO (&fdset);
|
||||||
FD_SET (x11_fd, &fdset);
|
FD_SET (x11_fd, &fdset);
|
||||||
|
int maxfd = x11_fd;
|
||||||
|
if (sn_pipe_valid) {
|
||||||
|
FD_SET (sn_pipe[0], &fdset);
|
||||||
|
maxfd = maxfd < sn_pipe[0] ? sn_pipe[0] : maxfd;
|
||||||
|
}
|
||||||
update_next_timeout();
|
update_next_timeout();
|
||||||
if (next_timeout.tv_sec >= 0 && next_timeout.tv_usec >= 0)
|
if (next_timeout.tv_sec >= 0 && next_timeout.tv_usec >= 0)
|
||||||
timeout = &next_timeout;
|
timeout = &next_timeout;
|
||||||
@@ -1230,37 +1174,42 @@ start:
|
|||||||
timeout = 0;
|
timeout = 0;
|
||||||
|
|
||||||
// Wait for X Event or a Timer
|
// Wait for X Event or a Timer
|
||||||
ts_event_read = 0;
|
if (select(maxfd+1, &fdset, 0, 0, timeout) > 0) {
|
||||||
if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) {
|
if (FD_ISSET(sn_pipe[0], &fdset)) {
|
||||||
while (XPending (server.dsp)) {
|
char buffer[1];
|
||||||
XNextEvent(server.dsp, &e);
|
ssize_t wur = read(sn_pipe[0], buffer, 1);
|
||||||
if (debug_fps)
|
(void) wur;
|
||||||
ts_event_read = get_time();
|
sigchld_handler_async();
|
||||||
|
}
|
||||||
|
if (FD_ISSET(x11_fd, &fdset)) {
|
||||||
|
while (XPending (server.dsp)) {
|
||||||
|
XNextEvent(server.dsp, &e);
|
||||||
#if HAVE_SN
|
#if HAVE_SN
|
||||||
sn_display_process_event (server.sn_dsp, &e);
|
if (startup_notifications)
|
||||||
|
sn_display_process_event(server.sn_dsp, &e);
|
||||||
#endif // HAVE_SN
|
#endif // HAVE_SN
|
||||||
|
|
||||||
panel = get_panel(e.xany.window);
|
panel = get_panel(e.xany.window);
|
||||||
if (panel && panel_autohide) {
|
if (panel && panel_autohide) {
|
||||||
if (e.type == EnterNotify)
|
if (e.type == EnterNotify)
|
||||||
autohide_trigger_show(panel);
|
autohide_trigger_show(panel);
|
||||||
else if (e.type == LeaveNotify)
|
else if (e.type == LeaveNotify)
|
||||||
autohide_trigger_hide(panel);
|
autohide_trigger_hide(panel);
|
||||||
if (panel->is_hidden) {
|
if (panel->is_hidden) {
|
||||||
if (e.type == ClientMessage && e.xclient.message_type == server.atom.XdndPosition) {
|
if (e.type == ClientMessage && e.xclient.message_type == server.atom.XdndPosition) {
|
||||||
hidden_dnd = 1;
|
hidden_dnd = 1;
|
||||||
autohide_show(panel);
|
autohide_show(panel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
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) {
|
switch (e.type) {
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
tooltip_hide(0);
|
tooltip_hide(0);
|
||||||
event_button_press (&e);
|
event_button_press (&e);
|
||||||
@@ -1319,7 +1268,7 @@ start:
|
|||||||
break;
|
break;
|
||||||
for (it = systray.list_icons; it; it = g_slist_next(it)) {
|
for (it = systray.list_icons; it; it = g_slist_next(it)) {
|
||||||
if (((TrayWindow*)it->data)->tray_id == e.xany.window) {
|
if (((TrayWindow*)it->data)->tray_id == e.xany.window) {
|
||||||
remove_icon((TrayWindow*)it->data);
|
remove_icon((TrayWindow*)it->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1350,110 +1299,110 @@ start:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SelectionNotify:
|
case SelectionNotify:
|
||||||
{
|
{
|
||||||
Atom target = e.xselection.target;
|
Atom target = e.xselection.target;
|
||||||
|
|
||||||
fprintf(stderr, "DnD %s:%d: A selection notify has arrived!\n", __FILE__, __LINE__);
|
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: 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: 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: 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));
|
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) {
|
if (e.xselection.property != None && dnd_launcher_exec) {
|
||||||
Property prop = read_property(server.dsp, dnd_target_window, dnd_selection);
|
Property prop = read_property(server.dsp, dnd_target_window, dnd_selection);
|
||||||
|
|
||||||
//If we're being given a list of targets (possible conversions)
|
//If we're being given a list of targets (possible conversions)
|
||||||
if (target == server.atom.TARGETS && !dnd_sent_request) {
|
if (target == server.atom.TARGETS && !dnd_sent_request) {
|
||||||
dnd_sent_request = 1;
|
dnd_sent_request = 1;
|
||||||
dnd_atom = pick_target_from_targets(server.dsp, prop);
|
dnd_atom = pick_target_from_targets(server.dsp, prop);
|
||||||
|
|
||||||
if (dnd_atom == None) {
|
if (dnd_atom == None) {
|
||||||
fprintf(stderr, "No matching datatypes.\n");
|
fprintf(stderr, "No matching datatypes.\n");
|
||||||
} else {
|
} else {
|
||||||
//Request the data type we are able to select
|
//Request the data type we are able to select
|
||||||
fprintf(stderr, "Now requsting type %s", GetAtomName(server.dsp, dnd_atom));
|
fprintf(stderr, "Now requsting type %s", GetAtomName(server.dsp, dnd_atom));
|
||||||
XConvertSelection(server.dsp, dnd_selection, dnd_atom, dnd_selection, dnd_target_window, CurrentTime);
|
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; // close double quotes
|
|
||||||
cmd_length += 2; // &)
|
|
||||||
cmd_length += 1; // terminator
|
|
||||||
|
|
||||||
char *cmd = malloc(cmd_length);
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
} 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");
|
||||||
|
|
||||||
XFree(prop.data);
|
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; // 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
XFree(prop.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (e.type == XDamageNotify+damage_event) {
|
if (e.type == XDamageNotify+damage_event) {
|
||||||
// union needed to avoid strict-aliasing warnings by gcc
|
// union needed to avoid strict-aliasing warnings by gcc
|
||||||
@@ -1464,11 +1413,12 @@ start:
|
|||||||
for (l = systray.list_icons; l ; l = l->next) {
|
for (l = systray.list_icons; l ; l = l->next) {
|
||||||
traywin = (TrayWindow*)l->data;
|
traywin = (TrayWindow*)l->data;
|
||||||
if ( traywin->id == de->drawable ) {
|
if ( traywin->id == de->drawable ) {
|
||||||
systray_render_icon(traywin);
|
systray_render_icon(traywin);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ project(tint2conf)
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
|
||||||
include( FindPkgConfig )
|
include( FindPkgConfig )
|
||||||
pkg_check_modules( X11_T2C REQUIRED x11 xrender )
|
pkg_check_modules( X11_T2C REQUIRED x11 xcomposite xdamage xinerama xrender xrandr>=1.3 )
|
||||||
pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
|
pkg_check_modules( GLIB2 REQUIRED glib-2.0 )
|
||||||
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
pkg_check_modules( GOBJECT2 REQUIRED gobject-2.0 )
|
||||||
pkg_check_modules( IMLIB2 REQUIRED imlib2 )
|
pkg_check_modules( IMLIB2 REQUIRED imlib2 )
|
||||||
pkg_check_modules( GTHREAD2 REQUIRED gthread-2.0 )
|
pkg_check_modules( GTHREAD2 REQUIRED gthread-2.0 )
|
||||||
pkg_check_modules( GTK2 REQUIRED gtk+-x11-2.0 )
|
pkg_check_modules( GTK2 REQUIRED gtk+-x11-2.0 )
|
||||||
|
pkg_check_modules( RSVG librsvg-2.0>=2.36.0 )
|
||||||
|
|
||||||
include_directories( ../util
|
include_directories( ../util
|
||||||
${X11_T2C_INCLUDE_DIRS}
|
${X11_T2C_INCLUDE_DIRS}
|
||||||
@@ -15,26 +16,44 @@ include_directories( ../util
|
|||||||
${GOBJECT2_INCLUDE_DIRS}
|
${GOBJECT2_INCLUDE_DIRS}
|
||||||
${IMLIB2_INCLUDE_DIRS}
|
${IMLIB2_INCLUDE_DIRS}
|
||||||
${GTHREAD2_INCLUDE_DIRS}
|
${GTHREAD2_INCLUDE_DIRS}
|
||||||
${GTK2_INCLUDE_DIRS} )
|
${GTK2_INCLUDE_DIRS}
|
||||||
|
${RSVG_INCLUDE_DIRS} )
|
||||||
|
|
||||||
set(SOURCES ../util/common.c
|
set(SOURCES ../util/common.c
|
||||||
|
../config.c
|
||||||
|
../server.c
|
||||||
|
../launcher/apps-common.c
|
||||||
|
../launcher/icon-theme-common.c
|
||||||
main.c
|
main.c
|
||||||
properties.c
|
properties.c
|
||||||
properties_rw.c
|
properties_rw.c
|
||||||
theme_view.c )
|
theme_view.c )
|
||||||
|
|
||||||
|
add_definitions( -DTINT2CONF )
|
||||||
|
|
||||||
|
option( ENABLE_RSVG "Rsvg support (launcher only)" ON )
|
||||||
|
|
||||||
|
if( ENABLE_RSVG )
|
||||||
|
if( RSVG_FOUND )
|
||||||
|
add_definitions( -DHAVE_RSVG )
|
||||||
|
endif( RSVG_FOUND )
|
||||||
|
endif( ENABLE_RSVG )
|
||||||
|
|
||||||
link_directories( ${X11_T2C_LIBRARY_DIRS}
|
link_directories( ${X11_T2C_LIBRARY_DIRS}
|
||||||
${GLIB2_LIBRARY_DIRS}
|
${GLIB2_LIBRARY_DIRS}
|
||||||
${GOBJECT2_LIBRARY_DIRS}
|
${GOBJECT2_LIBRARY_DIRS}
|
||||||
${IMLIB2_LIBRARY_DIRS}
|
${IMLIB2_LIBRARY_DIRS}
|
||||||
${GTHREAD2_LIBRARY_DIRS}
|
${GTHREAD2_LIBRARY_DIRS}
|
||||||
${GTK2_LIBRARY_DIRS} )
|
${GTK2_LIBRARY_DIRS}
|
||||||
|
${RSVG_LIBRARY_DIRS} )
|
||||||
add_executable( tint2conf ${SOURCES} )
|
add_executable( tint2conf ${SOURCES} )
|
||||||
target_link_libraries( tint2conf ${X11_T2C_LIBRARIES}
|
target_link_libraries( tint2conf ${X11_T2C_LIBRARIES}
|
||||||
${GLIB2_LIBRARIES}
|
${GLIB2_LIBRARIES}
|
||||||
${GOBJECT2_LIBRARIES}
|
${GOBJECT2_LIBRARIES}
|
||||||
${IMLIB2_LIBRARIES}
|
${IMLIB2_LIBRARIES}
|
||||||
${GTHREAD2_LIBRARIES}
|
${GTHREAD2_LIBRARIES}
|
||||||
${GTK2_LIBRARIES} )
|
${GTK2_LIBRARIES}
|
||||||
|
${RSVG_LIBRARIES} )
|
||||||
|
|
||||||
if ( NOT DATADIR )
|
if ( NOT DATADIR )
|
||||||
set( DATADIR share )
|
set( DATADIR share )
|
||||||
|
|||||||
@@ -17,68 +17,84 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef HAVE_VERSION_H
|
#ifdef HAVE_VERSION_H
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "theme_view.h"
|
#include "theme_view.h"
|
||||||
#include "properties.h"
|
#include "properties.h"
|
||||||
#include "properties_rw.h"
|
#include "properties_rw.h"
|
||||||
|
|
||||||
#define SNAPSHOT_TICK 190
|
|
||||||
|
|
||||||
|
// ====== Utilities ======
|
||||||
|
|
||||||
// default config file and directory
|
gchar *get_default_config_path()
|
||||||
char *g_path_config = NULL;
|
{
|
||||||
char *g_path_dir = NULL;
|
gchar *path = NULL;
|
||||||
char *g_default_theme = NULL;
|
const gchar * const * system_dirs = g_get_system_config_dirs();
|
||||||
char *g_cmd_property = NULL;
|
int i;
|
||||||
int g_width, g_height;
|
for (i = 0; system_dirs[i]; i++) {
|
||||||
|
path = g_build_filename(system_dirs[i], "tint2", "tint2rc", NULL);
|
||||||
|
if (g_file_test(path, G_FILE_TEST_EXISTS))
|
||||||
|
return path;
|
||||||
|
g_free(path);
|
||||||
|
path = NULL;
|
||||||
|
}
|
||||||
|
return g_strdup("/dev/null");
|
||||||
|
}
|
||||||
|
|
||||||
GtkWidget *g_window;
|
int endswith(const char *str, const char *suffix)
|
||||||
|
{
|
||||||
|
return strlen(str) >= strlen(suffix) &&
|
||||||
|
strcmp(str + strlen(str) - strlen(suffix), suffix) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static GtkUIManager *globalUIManager = NULL;
|
static void menuAddWidget(GtkUIManager *ui_manager, GtkWidget *p_widget, GtkContainer *p_box)
|
||||||
|
{
|
||||||
|
gtk_box_pack_start(GTK_BOX(p_box), p_widget, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show(p_widget);
|
||||||
|
}
|
||||||
|
|
||||||
static void menuAddWidget (GtkUIManager *, GtkWidget *, GtkContainer *);
|
static void menuAddWidget(GtkUIManager *, GtkWidget *, GtkContainer *);
|
||||||
|
static void menuImport();
|
||||||
// action on menus
|
static void menuImportDefault();
|
||||||
static void menuAdd();
|
|
||||||
static void menuSaveAs();
|
static void menuSaveAs();
|
||||||
static void menuDelete();
|
static void menuDelete();
|
||||||
static void menuProperties();
|
static void edit_current_theme();
|
||||||
static void menuQuit();
|
static void refresh_current_theme();
|
||||||
static void menuRefresh();
|
|
||||||
static void menuRefreshAll();
|
|
||||||
static void menuApply();
|
|
||||||
static void menuAbout();
|
static void menuAbout();
|
||||||
|
static gboolean view_onPopupMenu(GtkWidget *treeview, gpointer userdata);
|
||||||
|
static gboolean view_onButtonPressed(GtkWidget *treeview, GdkEventButton *event, gpointer userdata);
|
||||||
|
static gboolean theme_selected(GtkTreeSelection *selection,
|
||||||
|
GtkTreeModel *model,
|
||||||
|
GtkTreePath *path,
|
||||||
|
gboolean path_currently_selected,
|
||||||
|
gpointer userdata);
|
||||||
|
|
||||||
static gboolean view_onPopupMenu (GtkWidget *treeview, gpointer userdata);
|
static void select_first_theme();
|
||||||
static gboolean view_onButtonPressed (GtkWidget *treeview, GdkEventButton *event, gpointer userdata);
|
static void load_all_themes();
|
||||||
static void windowSizeAllocated();
|
|
||||||
static void viewRowActivated(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data);
|
|
||||||
|
|
||||||
|
|
||||||
// theme files
|
// ====== Globals ======
|
||||||
static void selectTheme(const gchar *name);
|
|
||||||
static gboolean searchTheme(const gchar *name_theme, GtkTreeModel *model, GtkTreeIter *iter);
|
|
||||||
static void load_theme();
|
|
||||||
static void initTheme();
|
|
||||||
static void read_config();
|
|
||||||
static void write_config();
|
|
||||||
|
|
||||||
|
GtkWidget *g_window;
|
||||||
|
static GtkUIManager *globalUIManager = NULL;
|
||||||
|
GtkWidget *tint_cmd;
|
||||||
|
|
||||||
// define menubar, toolbar and popup
|
|
||||||
static const char *global_ui =
|
static const char *global_ui =
|
||||||
"<ui>"
|
"<ui>"
|
||||||
" <menubar name='MenuBar'>"
|
" <menubar name='MenuBar'>"
|
||||||
" <menu action='ThemeMenu'>"
|
" <menu action='ThemeMenu'>"
|
||||||
" <menuitem action='ThemeAdd'/>"
|
" <menuitem action='ThemeAdd'/>"
|
||||||
" <menuitem action='ThemeSaveAs'/>"
|
" <menuitem action='ThemeDefault'/>"
|
||||||
" <separator/>"
|
|
||||||
" <menuitem action='ThemeDelete'/>"
|
|
||||||
" <separator/>"
|
" <separator/>"
|
||||||
" <menuitem action='ThemeProperties'/>"
|
" <menuitem action='ThemeProperties'/>"
|
||||||
|
" <menuitem action='ThemeSaveAs'/>"
|
||||||
|
" <menuitem action='ThemeDelete'/>"
|
||||||
" <separator/>"
|
" <separator/>"
|
||||||
" <menuitem action='ThemeQuit'/>"
|
" <menuitem action='ThemeQuit'/>"
|
||||||
" </menu>"
|
" </menu>"
|
||||||
@@ -86,7 +102,6 @@ static const char *global_ui =
|
|||||||
" <menuitem action='EditRefresh'/>"
|
" <menuitem action='EditRefresh'/>"
|
||||||
" <menuitem action='EditRefreshAll'/>"
|
" <menuitem action='EditRefreshAll'/>"
|
||||||
" <separator/>"
|
" <separator/>"
|
||||||
" <menuitem action='EditPreferences'/>"
|
|
||||||
" </menu>"
|
" </menu>"
|
||||||
" <menu action='HelpMenu'>"
|
" <menu action='HelpMenu'>"
|
||||||
" <menuitem action='HelpAbout'/>"
|
" <menuitem action='HelpAbout'/>"
|
||||||
@@ -94,12 +109,10 @@ static const char *global_ui =
|
|||||||
" </menubar>"
|
" </menubar>"
|
||||||
" <toolbar name='ToolBar'>"
|
" <toolbar name='ToolBar'>"
|
||||||
" <toolitem action='ThemeProperties'/>"
|
" <toolitem action='ThemeProperties'/>"
|
||||||
" <toolitem action='ViewApply'/>"
|
|
||||||
" </toolbar>"
|
" </toolbar>"
|
||||||
" <popup name='ThemePopup'>"
|
" <popup name='ThemePopup'>"
|
||||||
" <menuitem action='ThemeProperties'/>"
|
" <menuitem action='ThemeProperties'/>"
|
||||||
" <menuitem action='EditRefresh'/>"
|
" <menuitem action='EditRefresh'/>"
|
||||||
" <menuitem action='ViewApply'/>"
|
|
||||||
" <separator/>"
|
" <separator/>"
|
||||||
" <menuitem action='ThemeDelete'/>"
|
" <menuitem action='ThemeDelete'/>"
|
||||||
" </popup>"
|
" </popup>"
|
||||||
@@ -109,52 +122,78 @@ static const char *global_ui =
|
|||||||
// define menubar and toolbar action
|
// define menubar and toolbar action
|
||||||
static GtkActionEntry entries[] = {
|
static GtkActionEntry entries[] = {
|
||||||
{"ThemeMenu", NULL, _("Theme"), NULL, NULL, NULL},
|
{"ThemeMenu", NULL, _("Theme"), NULL, NULL, NULL},
|
||||||
{"ThemeAdd", GTK_STOCK_ADD, _("_Add..."), "<Control>N", _("Add theme"), G_CALLBACK (menuAdd)},
|
{"ThemeAdd", GTK_STOCK_ADD, _("_Import theme..."), "<Control>N", _("Import theme"), G_CALLBACK(menuImport)},
|
||||||
{"ThemeSaveAs", GTK_STOCK_SAVE_AS, _("_Save as..."), NULL, _("Save theme as"), G_CALLBACK (menuSaveAs)},
|
{"ThemeDefault", GTK_STOCK_NEW, _("_Import default theme..."), NULL, _("Import default theme"), G_CALLBACK(menuImportDefault)},
|
||||||
{"ThemeDelete", GTK_STOCK_DELETE, _("_Delete"), NULL, _("Delete theme"), G_CALLBACK (menuDelete)},
|
{"ThemeSaveAs", GTK_STOCK_SAVE_AS, _("_Save as..."), NULL, _("Save theme as"), G_CALLBACK(menuSaveAs)},
|
||||||
{"ThemeProperties", GTK_STOCK_PROPERTIES, _("_Properties..."), NULL, _("Show properties"), G_CALLBACK (menuProperties)},
|
{"ThemeDelete", GTK_STOCK_DELETE, _("_Delete"), NULL, _("Delete theme"), G_CALLBACK(menuDelete)},
|
||||||
{"ThemeQuit", GTK_STOCK_QUIT, _("_Quit"), "<control>Q", _("Quit"), G_CALLBACK (menuQuit)},
|
{"ThemeProperties", GTK_STOCK_PROPERTIES, _("_Edit theme..."), NULL, _("Edit selected theme"), G_CALLBACK(edit_current_theme)},
|
||||||
|
{"ThemeQuit", GTK_STOCK_QUIT, _("_Quit"), "<control>Q", _("Quit"), G_CALLBACK(gtk_main_quit)},
|
||||||
{"EditMenu", NULL, "Edit", NULL, NULL, NULL},
|
{"EditMenu", NULL, "Edit", NULL, NULL, NULL},
|
||||||
{"EditRefresh", GTK_STOCK_REFRESH, _("Refresh"), NULL, _("Refresh"), G_CALLBACK (menuRefresh)},
|
{"EditRefresh", GTK_STOCK_REFRESH, _("Refresh"), NULL, _("Refresh"), G_CALLBACK(refresh_current_theme)},
|
||||||
{"EditRefreshAll", GTK_STOCK_REFRESH, _("Refresh all"), NULL, _("Refresh all"), G_CALLBACK (menuRefreshAll)},
|
{"EditRefreshAll", GTK_STOCK_REFRESH, _("Refresh all"), NULL, _("Refresh all"), G_CALLBACK(load_all_themes)},
|
||||||
// {"EditPreferences", GTK_STOCK_PREFERENCES, "Preferences", NULL, "Preferences", G_CALLBACK (menuPreferences)},
|
|
||||||
{"ViewApply", GTK_STOCK_APPLY, _("Apply"), NULL, _("Apply theme"), G_CALLBACK (menuApply)},
|
|
||||||
{"HelpMenu", NULL, _("Help"), NULL, NULL, NULL},
|
{"HelpMenu", NULL, _("Help"), NULL, NULL, NULL},
|
||||||
{"HelpAbout", GTK_STOCK_ABOUT, _("_About"), "<Control>A", _("About"), G_CALLBACK (menuAbout)}
|
{"HelpAbout", GTK_STOCK_ABOUT, _("_About"), "<Control>A", _("About"), G_CALLBACK(menuAbout)}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main (int argc, char ** argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
GtkWidget *vBox = NULL, *scrollbar = NULL;
|
GtkWidget *vBox = NULL, *scrollbar = NULL;
|
||||||
GtkActionGroup *actionGroup;
|
GtkActionGroup *actionGroup;
|
||||||
|
|
||||||
gtk_init (&argc, &argv);
|
gtk_init(&argc, &argv);
|
||||||
g_thread_init( NULL );
|
g_thread_init((NULL));
|
||||||
read_config();
|
|
||||||
initTheme();
|
{
|
||||||
g_set_application_name (_("tint2conf"));
|
gchar *tint2_config_dir = g_build_filename(g_get_user_config_dir(), "tint2", NULL);
|
||||||
|
if (!g_file_test(tint2_config_dir, G_FILE_TEST_IS_DIR))
|
||||||
|
g_mkdir(tint2_config_dir, 0777);
|
||||||
|
g_free(tint2_config_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_set_application_name(_("tint2conf"));
|
||||||
gtk_window_set_default_icon_name("taskbar");
|
gtk_window_set_default_icon_name("taskbar");
|
||||||
|
|
||||||
// config file use '.' as decimal separator
|
// config file uses '.' as decimal separator
|
||||||
setlocale(LC_NUMERIC, "POSIX");
|
setlocale(LC_NUMERIC, "POSIX");
|
||||||
|
|
||||||
// define main layout : container, menubar, toolbar
|
// define main layout : container, menubar, toolbar
|
||||||
g_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
g_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
gtk_window_set_title(GTK_WINDOW(g_window), _("Panel theming"));
|
gtk_window_set_title(GTK_WINDOW(g_window), _("Panel theming"));
|
||||||
gtk_window_resize(GTK_WINDOW(g_window), g_width, g_height);
|
gtk_window_resize(GTK_WINDOW(g_window), 800, 600);
|
||||||
g_signal_connect(G_OBJECT(g_window), "destroy", G_CALLBACK (menuQuit), NULL);
|
g_signal_connect(G_OBJECT(g_window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
||||||
g_signal_connect(g_window, "size-allocate", G_CALLBACK(windowSizeAllocated), NULL);
|
vBox = gtk_vbox_new(FALSE, 0);
|
||||||
vBox = gtk_vbox_new (FALSE, 0);
|
gtk_container_add(GTK_CONTAINER(g_window), vBox);
|
||||||
gtk_container_add (GTK_CONTAINER(g_window), vBox);
|
|
||||||
|
|
||||||
actionGroup = gtk_action_group_new ("menuActionGroup");
|
actionGroup = gtk_action_group_new("menuActionGroup");
|
||||||
gtk_action_group_add_actions (actionGroup, entries, G_N_ELEMENTS (entries), NULL);
|
gtk_action_group_add_actions(actionGroup, entries, G_N_ELEMENTS(entries), NULL);
|
||||||
globalUIManager = gtk_ui_manager_new();
|
globalUIManager = gtk_ui_manager_new();
|
||||||
gtk_ui_manager_insert_action_group (globalUIManager, actionGroup, 0);
|
gtk_ui_manager_insert_action_group(globalUIManager, actionGroup, 0);
|
||||||
gtk_ui_manager_add_ui_from_string (globalUIManager, global_ui, -1, NULL );
|
gtk_ui_manager_add_ui_from_string(globalUIManager, global_ui, -1, (NULL));
|
||||||
g_signal_connect(globalUIManager, "add_widget", G_CALLBACK (menuAddWidget), vBox);
|
g_signal_connect(globalUIManager, "add_widget", G_CALLBACK(menuAddWidget), vBox);
|
||||||
gtk_ui_manager_ensure_update(globalUIManager);
|
gtk_ui_manager_ensure_update(globalUIManager);
|
||||||
|
|
||||||
|
GtkWidget *table, *label;
|
||||||
|
int row, col;
|
||||||
|
|
||||||
|
row = col = 0;
|
||||||
|
table = gtk_table_new(1, 2, FALSE);
|
||||||
|
gtk_widget_show(table);
|
||||||
|
gtk_box_pack_start(GTK_BOX(vBox), table, FALSE, TRUE, 0);
|
||||||
|
gtk_table_set_row_spacings(GTK_TABLE(table), 8);
|
||||||
|
gtk_table_set_col_spacings(GTK_TABLE(table), 8);
|
||||||
|
|
||||||
|
label = gtk_label_new(_("Command to run tint2: "));
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||||
|
gtk_widget_show(label);
|
||||||
|
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||||
|
col++;
|
||||||
|
|
||||||
|
tint_cmd = gtk_entry_new();
|
||||||
|
gtk_widget_show(tint_cmd);
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(tint_cmd), "");
|
||||||
|
gtk_table_attach(GTK_TABLE(table), tint_cmd, col, col+1, row, row+1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
|
||||||
|
|
||||||
scrollbar = gtk_scrolled_window_new(NULL, NULL);
|
scrollbar = gtk_scrolled_window_new(NULL, NULL);
|
||||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||||
gtk_box_pack_start(GTK_BOX(vBox), scrollbar, TRUE, TRUE, 0);
|
gtk_box_pack_start(GTK_BOX(vBox), scrollbar, TRUE, TRUE, 0);
|
||||||
@@ -165,108 +204,100 @@ int main (int argc, char ** argv)
|
|||||||
gtk_widget_show(g_theme_view);
|
gtk_widget_show(g_theme_view);
|
||||||
g_signal_connect(g_theme_view, "button-press-event", (GCallback)view_onButtonPressed, NULL);
|
g_signal_connect(g_theme_view, "button-press-event", (GCallback)view_onButtonPressed, NULL);
|
||||||
g_signal_connect(g_theme_view, "popup-menu", (GCallback)view_onPopupMenu, NULL);
|
g_signal_connect(g_theme_view, "popup-menu", (GCallback)view_onPopupMenu, NULL);
|
||||||
g_signal_connect(g_theme_view, "row-activated", G_CALLBACK(viewRowActivated), NULL);
|
gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_theme_view)), theme_selected, NULL, NULL);
|
||||||
|
|
||||||
// load themes
|
// load themes
|
||||||
load_theme(g_theme_view);
|
load_all_themes();
|
||||||
|
|
||||||
gtk_widget_show_all(g_window);
|
gtk_widget_show_all(g_window);
|
||||||
gtk_main ();
|
gtk_main();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void menuAddWidget (GtkUIManager * p_uiManager, GtkWidget * p_widget, GtkContainer * p_box)
|
|
||||||
{
|
|
||||||
gtk_box_pack_start(GTK_BOX(p_box), p_widget, FALSE, FALSE, 0);
|
|
||||||
gtk_widget_show(p_widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void menuAbout()
|
static void menuAbout()
|
||||||
{
|
{
|
||||||
const char *authors[] = { "Thierry Lorthiois <lorthiois@bbsoft.fr>", "Andreas Fink <andreas.fink85@googlemail.com>", "Christian Ruppert <Spooky85@gmail.com> (Build system)", "Euan Freeman <euan04@gmail.com> (tintwizard)\n See http://code.google.com/p/tintwizard/", NULL };
|
const char *authors[] = {
|
||||||
|
"Thierry Lorthiois <lorthiois@bbsoft.fr>",
|
||||||
|
"Andreas Fink <andreas.fink85@googlemail.com>",
|
||||||
|
"Christian Ruppert <Spooky85@gmail.com> (Build system)",
|
||||||
|
"Euan Freeman <euan04@gmail.com> (tintwizard http://code.google.com/p/tintwizard)",
|
||||||
|
(NULL)
|
||||||
|
};
|
||||||
|
|
||||||
gtk_show_about_dialog(GTK_WINDOW(g_window), "name", g_get_application_name( ),
|
gtk_show_about_dialog(GTK_WINDOW(g_window),
|
||||||
"comments", _("Theming tool for tint2 panel"),
|
"name", g_get_application_name( ),
|
||||||
"version", VERSION_STRING,
|
"comments", _("Theming tool for tint2 panel"),
|
||||||
"copyright", _("Copyright 2009 tint2 team\nTint2 License GNU GPL version 2\nTintwizard License GNU GPL version 3"),
|
"version", VERSION_STRING,
|
||||||
"logo-icon-name", "taskbar", "authors", authors,
|
"copyright", _("Copyright 2009-2015 tint2 team\nTint2 License GNU GPL version 2\nTintwizard License GNU GPL version 3"),
|
||||||
/* Translators: translate "translator-credits" as
|
"logo-icon-name", "taskbar", "authors", authors,
|
||||||
your name to have it appear in the credits in the "About"
|
/* Translators: translate "translator-credits" as
|
||||||
dialog */
|
your name to have it appear in the credits in the "About"
|
||||||
"translator-credits", _("translator-credits"),
|
dialog */
|
||||||
NULL);
|
"translator-credits", _("translator-credits"),
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void menuAdd()
|
// ====== Theme import/copy/delete ======
|
||||||
|
|
||||||
|
static void menuImport()
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Import theme(s)"), GTK_WINDOW(g_window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT, NULL);
|
||||||
GtkFileChooser *chooser;
|
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
|
||||||
GtkFileFilter *filter;
|
|
||||||
|
|
||||||
dialog = gtk_file_chooser_dialog_new(_("Add a theme"), GTK_WINDOW(g_window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT, NULL);
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
|
||||||
chooser = GTK_FILE_CHOOSER(dialog);
|
|
||||||
|
|
||||||
gtk_file_chooser_set_current_folder(chooser, g_get_home_dir());
|
|
||||||
gtk_file_chooser_set_select_multiple(chooser, TRUE);
|
|
||||||
|
|
||||||
filter = gtk_file_filter_new();
|
|
||||||
gtk_file_filter_set_name(filter, _("Tint2 theme files"));
|
|
||||||
gtk_file_filter_add_pattern(filter, "*.tint2rc");
|
|
||||||
gtk_file_chooser_add_filter(chooser, filter);
|
|
||||||
|
|
||||||
if (gtk_dialog_run (GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
|
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkTreeIter iter;
|
GSList *list = gtk_file_chooser_get_filenames(chooser);
|
||||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
|
GSList *l;
|
||||||
GSList *l, *list = gtk_file_chooser_get_filenames(chooser);
|
|
||||||
gchar *file, *pt1, *name, *path, *name_first=NULL;
|
|
||||||
for (l = list; l ; l = l->next) {
|
for (l = list; l ; l = l->next) {
|
||||||
file = (char *)l->data;
|
gchar *file = (char *)l->data;
|
||||||
pt1 = strrchr(file, '/');
|
gchar *pt1 = strrchr(file, '/');
|
||||||
if (pt1 == NULL) continue;
|
if (!pt1)
|
||||||
pt1++;
|
continue;
|
||||||
if (*pt1 == 0) continue;
|
pt1++;
|
||||||
|
if (!*pt1)
|
||||||
name = g_strdup(pt1);
|
|
||||||
path = g_build_filename (g_get_user_config_dir(), "tint2", name, NULL);
|
|
||||||
|
|
||||||
// check existing
|
|
||||||
if (searchTheme(path, model, &iter)) {
|
|
||||||
gchar *message;
|
|
||||||
message = g_strdup_printf(_("Couldn't add duplicate theme\n\'%s\'."), pt1);
|
|
||||||
|
|
||||||
GtkWidget *w = gtk_message_dialog_new(GTK_WINDOW(g_window), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, message, NULL);
|
|
||||||
g_signal_connect_swapped(w, "response", G_CALLBACK(gtk_widget_destroy), w);
|
|
||||||
gtk_widget_show(w);
|
|
||||||
g_free(message);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// append theme
|
gchar *name = pt1;
|
||||||
|
gchar *path = g_build_filename(g_get_user_config_dir(), "tint2", name, NULL);
|
||||||
|
if (g_file_test(path, G_FILE_TEST_EXISTS))
|
||||||
|
continue;
|
||||||
copy_file(file, path);
|
copy_file(file, path);
|
||||||
custom_list_append(path);
|
|
||||||
if (name_first == NULL)
|
|
||||||
name_first = g_strdup(path);
|
|
||||||
g_free(path);
|
g_free(path);
|
||||||
g_free(name);
|
|
||||||
}
|
}
|
||||||
g_slist_foreach(list, (GFunc)g_free, NULL);
|
g_slist_foreach(list, (GFunc)g_free, NULL);
|
||||||
g_slist_free(list);
|
g_slist_free(list);
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
|
load_all_themes();
|
||||||
selectTheme(name_first);
|
|
||||||
g_free(name_first);
|
|
||||||
g_timeout_add(SNAPSHOT_TICK, (GSourceFunc)update_snapshot, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void menuImportDefault()
|
||||||
|
{
|
||||||
|
GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Save default theme as"), GTK_WINDOW(g_window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
|
||||||
|
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
|
||||||
|
|
||||||
static void menuSaveAs ()
|
gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
|
||||||
|
gchar *config_dir;
|
||||||
|
config_dir = g_build_filename(g_get_home_dir(), ".config", "tint2", NULL);
|
||||||
|
gtk_file_chooser_set_current_folder(chooser, config_dir);
|
||||||
|
g_free(config_dir);
|
||||||
|
|
||||||
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||||
|
gchar *save_name = gtk_file_chooser_get_filename(chooser);
|
||||||
|
gchar *path_default = get_default_config_path();
|
||||||
|
copy_file(path_default, save_name);
|
||||||
|
g_free(path_default);
|
||||||
|
g_free(save_name);
|
||||||
|
}
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
|
||||||
|
load_all_themes();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void menuSaveAs()
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkFileChooser *chooser;
|
GtkFileChooser *chooser;
|
||||||
@@ -284,25 +315,29 @@ static void menuSaveAs ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
gtk_tree_model_get(model, &iter, COL_THEME_FILE, &file, -1);
|
gtk_tree_model_get(model, &iter, COL_THEME_FILE, &file, -1);
|
||||||
pt1 = strrchr (file, '/');
|
pt1 = strrchr(file, '/');
|
||||||
if (pt1) pt1++;
|
if (pt1) pt1++;
|
||||||
|
|
||||||
dialog = gtk_file_chooser_dialog_new(_("Save theme as"), GTK_WINDOW(g_window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
|
dialog = gtk_file_chooser_dialog_new(_("Save theme as"), GTK_WINDOW(g_window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
|
||||||
chooser = GTK_FILE_CHOOSER(dialog);
|
chooser = GTK_FILE_CHOOSER(dialog);
|
||||||
|
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
|
gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
|
||||||
gtk_file_chooser_set_current_folder(chooser, g_get_home_dir());
|
gchar *config_dir;
|
||||||
|
config_dir = g_build_filename(g_get_home_dir(), ".config", "tint2", NULL);
|
||||||
|
gtk_file_chooser_set_current_folder(chooser, config_dir);
|
||||||
|
g_free(config_dir);
|
||||||
gtk_file_chooser_set_current_name(chooser, pt1);
|
gtk_file_chooser_set_current_name(chooser, pt1);
|
||||||
|
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||||
char *filename = gtk_file_chooser_get_filename(chooser);
|
char *filename = gtk_file_chooser_get_filename(chooser);
|
||||||
copy_file(file, filename);
|
copy_file(file, filename);
|
||||||
g_free (filename);
|
g_free(filename);
|
||||||
}
|
}
|
||||||
g_free(file);
|
g_free(file);
|
||||||
gtk_widget_destroy (dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
|
||||||
|
|
||||||
|
load_all_themes();
|
||||||
|
}
|
||||||
|
|
||||||
static void menuDelete()
|
static void menuDelete()
|
||||||
{
|
{
|
||||||
@@ -326,105 +361,7 @@ static void menuDelete()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void menuProperties()
|
// ====== Theme popup menu ======
|
||||||
{
|
|
||||||
GtkTreeSelection *sel;
|
|
||||||
GtkTreeIter iter;
|
|
||||||
GtkTreeModel *model;
|
|
||||||
char *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);
|
|
||||||
//*
|
|
||||||
GtkWidget *prop;
|
|
||||||
prop = create_properties();
|
|
||||||
config_read_file(file);
|
|
||||||
gtk_window_present(GTK_WINDOW(prop));
|
|
||||||
//printf("menuProperties : fin\n");
|
|
||||||
//*/
|
|
||||||
/*
|
|
||||||
char *cmd = g_strdup_printf("%s \'%s\' &", g_cmd_property, file);
|
|
||||||
printf("cmd %s\n", cmd);
|
|
||||||
system(cmd);
|
|
||||||
g_free(cmd);
|
|
||||||
//*/
|
|
||||||
g_free(file);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void menuQuit()
|
|
||||||
{
|
|
||||||
write_config();
|
|
||||||
|
|
||||||
if (g_path_config)
|
|
||||||
g_free(g_path_config);
|
|
||||||
if (g_path_dir)
|
|
||||||
g_free(g_path_dir);
|
|
||||||
if (g_default_theme)
|
|
||||||
g_free(g_default_theme);
|
|
||||||
if (g_cmd_property)
|
|
||||||
g_free(g_cmd_property);
|
|
||||||
|
|
||||||
gtk_main_quit ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void menuRefresh()
|
|
||||||
{
|
|
||||||
GtkTreeSelection *sel;
|
|
||||||
GtkTreeIter iter;
|
|
||||||
GtkTreeModel *model;
|
|
||||||
|
|
||||||
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_list_store_set(g_store, &iter, COL_SNAPSHOT, NULL, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_timeout_add(SNAPSHOT_TICK, (GSourceFunc)update_snapshot, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void menuRefreshAll()
|
|
||||||
{
|
|
||||||
GtkTreeIter iter;
|
|
||||||
GtkTreeModel *model;
|
|
||||||
gboolean have_iter;
|
|
||||||
|
|
||||||
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
|
|
||||||
have_iter = gtk_tree_model_get_iter_first(model, &iter);
|
|
||||||
while (have_iter) {
|
|
||||||
gtk_list_store_set(g_store, &iter, COL_SNAPSHOT, NULL, -1);
|
|
||||||
have_iter = gtk_tree_model_iter_next(model, &iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_timeout_add(SNAPSHOT_TICK, (GSourceFunc)update_snapshot, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void menuApply()
|
|
||||||
{
|
|
||||||
GtkTreeSelection *sel;
|
|
||||||
GtkTreeIter iter;
|
|
||||||
GtkTreeModel *model;
|
|
||||||
|
|
||||||
if (g_default_theme) {
|
|
||||||
g_free(g_default_theme);
|
|
||||||
g_default_theme = NULL;
|
|
||||||
}
|
|
||||||
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, &g_default_theme, -1);
|
|
||||||
// overwrite tint2rc
|
|
||||||
copy_file(g_default_theme, g_path_config);
|
|
||||||
|
|
||||||
// restart panel
|
|
||||||
system("killall -SIGUSR1 tint2");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void view_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
|
static void view_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
|
||||||
{
|
{
|
||||||
@@ -433,8 +370,7 @@ static void view_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer
|
|||||||
gtk_menu_popup(GTK_MENU(w), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event));
|
gtk_menu_popup(GTK_MENU(w), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean view_onButtonPressed(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
|
||||||
static gboolean view_onButtonPressed (GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
|
|
||||||
{
|
{
|
||||||
// single click with the right mouse button?
|
// single click with the right mouse button?
|
||||||
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
||||||
@@ -459,186 +395,151 @@ static gboolean view_onButtonPressed (GtkWidget *treeview, GdkEventButton *event
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean view_onPopupMenu(GtkWidget *treeview, gpointer userdata)
|
||||||
static gboolean view_onPopupMenu (GtkWidget *treeview, gpointer userdata)
|
|
||||||
{
|
{
|
||||||
view_popup_menu(treeview, NULL, userdata);
|
view_popup_menu(treeview, NULL, userdata);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void viewRowActivated(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
|
// ====== Theme selection ======
|
||||||
|
|
||||||
|
gboolean theme_selected(GtkTreeSelection *selection,
|
||||||
|
GtkTreeModel *model,
|
||||||
|
GtkTreePath *path,
|
||||||
|
gboolean path_currently_selected,
|
||||||
|
gpointer userdata)
|
||||||
{
|
{
|
||||||
menuApply();
|
GtkTreeIter iter;
|
||||||
}
|
if (gtk_tree_model_get_iter(model, &iter, path)) {
|
||||||
|
gchar *current_theme = NULL;
|
||||||
|
gtk_tree_model_get(model, &iter, COL_THEME_FILE, ¤t_theme, -1);
|
||||||
static void windowSizeAllocated()
|
if (!path_currently_selected) {
|
||||||
{
|
gchar *text = g_strdup_printf("tint2 -c %s", current_theme);
|
||||||
const gboolean isMaximized = g_window->window && (gdk_window_get_state(g_window->window) & GDK_WINDOW_STATE_MAXIMIZED);
|
gtk_entry_set_text(GTK_ENTRY(tint_cmd), text);
|
||||||
|
g_free(text);
|
||||||
if(!isMaximized)
|
} else {
|
||||||
gtk_window_get_size(GTK_WINDOW(g_window), &g_width, &g_height);
|
gtk_entry_set_text(GTK_ENTRY(tint_cmd), "");
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void load_theme(GtkWidget *list)
|
|
||||||
{
|
|
||||||
GDir *dir;
|
|
||||||
gchar *pt1, *name;
|
|
||||||
const gchar *file;
|
|
||||||
gboolean found_theme = FALSE;
|
|
||||||
|
|
||||||
dir = g_dir_open(g_path_dir, 0, NULL);
|
|
||||||
if (dir == NULL) return;
|
|
||||||
while ((file = g_dir_read_name(dir))) {
|
|
||||||
pt1 = strstr(file, ".tint2rc");
|
|
||||||
if (pt1) {
|
|
||||||
found_theme = TRUE;
|
|
||||||
name = g_build_filename (g_path_dir, file, NULL);
|
|
||||||
custom_list_append(name);
|
|
||||||
g_free(name);
|
|
||||||
}
|
}
|
||||||
|
g_free(current_theme);
|
||||||
}
|
}
|
||||||
g_dir_close(dir);
|
return TRUE;
|
||||||
|
|
||||||
if (!found_theme) {
|
|
||||||
// create default theme file
|
|
||||||
name = g_build_filename(g_get_user_config_dir(), "tint2", "default.tint2rc", NULL);
|
|
||||||
copy_file(g_path_config, name);
|
|
||||||
custom_list_append(name);
|
|
||||||
if (g_default_theme) g_free(g_default_theme);
|
|
||||||
g_default_theme = strdup(name);
|
|
||||||
g_free(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectTheme(g_default_theme);
|
|
||||||
|
|
||||||
g_timeout_add(SNAPSHOT_TICK, (GSourceFunc)update_snapshot, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void select_first_theme()
|
||||||
void selectTheme(const gchar *name_theme)
|
|
||||||
{
|
{
|
||||||
gboolean have_iter, found_theme;
|
gboolean have_iter;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
GtkTreeModel *model;
|
GtkTreeModel *model;
|
||||||
|
|
||||||
if (!name_theme) return;
|
|
||||||
|
|
||||||
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
|
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
|
||||||
found_theme = searchTheme(name_theme, model, &iter);
|
have_iter = gtk_tree_model_get_iter_first(model, &iter);
|
||||||
|
if (have_iter) {
|
||||||
GtkTreePath *path = NULL;
|
GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
|
||||||
if (found_theme)
|
|
||||||
path = gtk_tree_model_get_path(model, &iter);
|
|
||||||
else {
|
|
||||||
have_iter = gtk_tree_model_get_iter_first(model, &iter);
|
|
||||||
if (have_iter)
|
|
||||||
path = gtk_tree_model_get_path(model, &iter);
|
|
||||||
}
|
|
||||||
if (path) {
|
|
||||||
gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_theme_view)), &iter);
|
gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_theme_view)), &iter);
|
||||||
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(g_theme_view), path, NULL, FALSE, 0, 0);
|
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(g_theme_view), path, NULL, FALSE, 0, 0);
|
||||||
gtk_tree_path_free(path);
|
gtk_tree_path_free(path);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *get_current_theme_file_name()
|
||||||
gboolean searchTheme(const gchar *name_theme, GtkTreeModel *model, GtkTreeIter *iter)
|
|
||||||
{
|
{
|
||||||
gchar *name;
|
GtkTreeSelection *sel;
|
||||||
gboolean have_iter, found = FALSE;
|
GtkTreeIter iter;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
char *file;
|
||||||
|
|
||||||
have_iter = gtk_tree_model_get_iter_first(model, iter);
|
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_theme_view));
|
||||||
while (have_iter) {
|
if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(sel), &model, &iter)) {
|
||||||
gtk_tree_model_get(model, iter, COL_THEME_FILE, &name, -1);
|
gtk_tree_model_get(model, &iter, COL_THEME_FILE, &file, -1);
|
||||||
found = (strcmp(name, name_theme) == 0);
|
return file;
|
||||||
g_free(name);
|
|
||||||
if (found)
|
|
||||||
break;
|
|
||||||
have_iter = gtk_tree_model_iter_next(model, iter);
|
|
||||||
}
|
}
|
||||||
return found;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void edit_current_theme()
|
||||||
void initTheme()
|
|
||||||
{
|
{
|
||||||
g_path_dir = g_build_filename (g_get_user_config_dir(), "tint2", NULL);
|
GtkTreeSelection *sel;
|
||||||
if (!g_file_test (g_path_dir, G_FILE_TEST_IS_DIR))
|
GtkTreeIter iter;
|
||||||
g_mkdir(g_path_dir, 0777);
|
GtkTreeModel *model;
|
||||||
|
char *file;
|
||||||
|
|
||||||
g_path_config = g_build_filename (g_get_user_config_dir(), "tint2", "tint2rc", NULL);
|
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);
|
||||||
|
GtkWidget *prop;
|
||||||
void read_config()
|
prop = create_properties();
|
||||||
{
|
config_read_file(file);
|
||||||
char *path;
|
gtk_window_present(GTK_WINDOW(prop));
|
||||||
|
g_free(file);
|
||||||
// default values
|
|
||||||
if (g_default_theme != NULL) {
|
|
||||||
g_free(g_default_theme);
|
|
||||||
g_default_theme = NULL;
|
|
||||||
}
|
}
|
||||||
g_width = 500;
|
}
|
||||||
g_height = 350;
|
|
||||||
g_cmd_property = g_strconcat( "/usr/bin/env python ", INSTALL_PREFIX, "/bin/tintwizard.py", (void*)0 );
|
|
||||||
|
|
||||||
// load config
|
// ====== Theme load/reload ======
|
||||||
path = g_build_filename (g_get_user_config_dir(), "tint2", "tint2confrc", NULL);
|
|
||||||
if (g_file_test (path, G_FILE_TEST_EXISTS)) {
|
static void load_all_themes()
|
||||||
FILE *fp;
|
{
|
||||||
char line[80];
|
gtk_list_store_clear(GTK_LIST_STORE(g_store));
|
||||||
char *key, *value;
|
|
||||||
if ((fp = fopen(path, "r")) != NULL) {
|
gchar *tint2_config_dir = g_build_filename(g_get_user_config_dir(), "tint2", NULL);
|
||||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
GDir *dir = g_dir_open(tint2_config_dir, 0, NULL);
|
||||||
if (parse_line(line, &key, &value)) {
|
if (dir == NULL) {
|
||||||
if (strcmp (key, "default_theme") == 0)
|
g_free(tint2_config_dir);
|
||||||
g_default_theme = strdup(value);
|
return;
|
||||||
else if (strcmp (key, "cmd_property") == 0) {
|
}
|
||||||
g_free(g_cmd_property);
|
gboolean found_theme = FALSE;
|
||||||
g_cmd_property = strdup(value);
|
const gchar *file_name;
|
||||||
}
|
while ((file_name = g_dir_read_name(dir))) {
|
||||||
else if (strcmp (key, "width") == 0)
|
if (!g_file_test(file_name, G_FILE_TEST_IS_DIR) &&
|
||||||
g_width = atoi(value);
|
!strstr(file_name, "backup") &&
|
||||||
else if (strcmp (key, "height") == 0)
|
!strstr(file_name, "copy") &&
|
||||||
g_height = atoi(value);
|
!strstr(file_name, "~") &&
|
||||||
free (key);
|
(endswith(file_name, "tint2rc") ||
|
||||||
free (value);
|
endswith(file_name, ".conf"))) {
|
||||||
}
|
found_theme = TRUE;
|
||||||
}
|
gchar *name = g_build_filename(tint2_config_dir, file_name, NULL);
|
||||||
fclose (fp);
|
custom_list_append(name);
|
||||||
|
g_free(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_free(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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 {
|
||||||
|
select_first_theme();
|
||||||
|
|
||||||
void write_config()
|
GtkTreeIter iter;
|
||||||
{
|
GtkTreeModel *model;
|
||||||
char *path;
|
gboolean have_iter;
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
path = g_build_filename (g_get_user_config_dir(), "tint2", "tint2confrc", NULL);
|
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
|
||||||
fp = fopen(path, "w");
|
have_iter = gtk_tree_model_get_iter_first(model, &iter);
|
||||||
if (fp != NULL) {
|
while (have_iter) {
|
||||||
fputs("#---------------------------------------------\n", fp);
|
gtk_list_store_set(g_store, &iter, COL_SNAPSHOT, NULL, -1);
|
||||||
fputs("# TINT2CONF CONFIG FILE\n", fp);
|
have_iter = gtk_tree_model_iter_next(model, &iter);
|
||||||
if (g_default_theme != NULL) {
|
|
||||||
fprintf(fp, "default_theme = %s\n", g_default_theme);
|
|
||||||
}
|
}
|
||||||
if (g_cmd_property != NULL) {
|
|
||||||
fprintf(fp, "cmd_property = %s\n", g_cmd_property);
|
g_timeout_add(SNAPSHOT_TICK, (GSourceFunc)update_snapshot, NULL);
|
||||||
}
|
|
||||||
fprintf(fp, "width = %d\n", g_width);
|
|
||||||
fprintf(fp, "height = %d\n", g_height);
|
|
||||||
fputs("\n", fp);
|
|
||||||
fclose (fp);
|
|
||||||
}
|
}
|
||||||
g_free(path);
|
|
||||||
|
g_dir_close(dir);
|
||||||
|
g_free(tint2_config_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void refresh_current_theme()
|
||||||
|
{
|
||||||
|
GtkTreeSelection *sel;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
|
||||||
|
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_list_store_set(g_store, &iter, COL_SNAPSHOT, NULL, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_timeout_add(SNAPSHOT_TICK, (GSourceFunc)update_snapshot, NULL);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -14,3 +13,6 @@
|
|||||||
#define _(String) String
|
#define _(String) String
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SNAPSHOT_TICK 190
|
||||||
|
gboolean update_snapshot();
|
||||||
|
void menuApply();
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -3,49 +3,157 @@
|
|||||||
#define PROPERTIES
|
#define PROPERTIES
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
|
#include "../launcher/icon-theme-common.h"
|
||||||
|
|
||||||
|
|
||||||
// panel
|
// panel
|
||||||
GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y, *panel_spacing;
|
extern GtkWidget *panel_width, *panel_height, *panel_margin_x, *panel_margin_y, *panel_padding_x, *panel_padding_y, *panel_spacing;
|
||||||
GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time, *panel_autohide_size;
|
extern GtkWidget *panel_wm_menu, *panel_dock, *panel_autohide, *panel_autohide_show_time, *panel_autohide_hide_time, *panel_autohide_size;
|
||||||
GtkWidget *panel_combo_strut_policy, *panel_combo_layer, *panel_combo_width_type, *panel_combo_height_type, *panel_combo_monitor;
|
extern GtkWidget *panel_combo_strut_policy, *panel_combo_layer, *panel_combo_width_type, *panel_combo_height_type, *panel_combo_monitor;
|
||||||
GtkWidget *items_order;
|
extern GtkWidget *panel_window_name, *disable_transparency;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
itemsColName = 0,
|
||||||
|
itemsColValue,
|
||||||
|
itemsNumCols
|
||||||
|
};
|
||||||
|
extern GtkListStore *panel_items, *all_items;
|
||||||
|
extern GtkWidget *panel_items_view, *all_items_view;
|
||||||
|
char *get_panel_items();
|
||||||
|
void set_panel_items(const char *items);
|
||||||
|
|
||||||
|
extern GtkWidget *screen_position[12];
|
||||||
|
extern GSList *screen_position_group;
|
||||||
|
extern GtkWidget *panel_background;
|
||||||
|
|
||||||
|
#define POS_TLH 0
|
||||||
|
#define POS_TCH 1
|
||||||
|
#define POS_TRH 2
|
||||||
|
|
||||||
|
#define POS_TLV 3
|
||||||
|
#define POS_CLV 4
|
||||||
|
#define POS_BLV 5
|
||||||
|
|
||||||
|
#define POS_TRV 6
|
||||||
|
#define POS_CRV 7
|
||||||
|
#define POS_BRV 8
|
||||||
|
|
||||||
|
#define POS_BLH 9
|
||||||
|
#define POS_BCH 10
|
||||||
|
#define POS_BRH 11
|
||||||
|
|
||||||
// taskbar
|
// taskbar
|
||||||
GtkWidget *taskbar_show_desktop, *taskbar_show_name, *taskbar_padding_x, *taskbar_padding_y, *taskbar_spacing;
|
extern GtkWidget *taskbar_show_desktop, *taskbar_show_name, *taskbar_padding_x, *taskbar_padding_y, *taskbar_spacing;
|
||||||
GtkWidget *taskbar_name_padding_x, *taskbar_name_inactive_color, *taskbar_name_active_color, *taskbar_name_font;
|
extern GtkWidget *taskbar_hide_inactive_tasks, *taskbar_hide_diff_monitor;
|
||||||
|
extern GtkWidget *taskbar_name_padding_x, *taskbar_name_inactive_color, *taskbar_name_active_color, *taskbar_name_font;
|
||||||
|
extern GtkWidget *taskbar_active_background, *taskbar_inactive_background;
|
||||||
|
extern GtkWidget *taskbar_name_active_background, *taskbar_name_inactive_background;
|
||||||
|
extern GtkWidget *taskbar_distribute_size, *taskbar_sort_order;
|
||||||
|
|
||||||
// task
|
// task
|
||||||
GtkWidget *task_mouse_middle, *task_mouse_right, *task_mouse_scroll_up, *task_mouse_scroll_down;
|
extern GtkWidget *task_mouse_left, *task_mouse_middle, *task_mouse_right, *task_mouse_scroll_up, *task_mouse_scroll_down;
|
||||||
GtkWidget *task_show_icon, *task_show_text, *task_align_center, *task_font_shadow;
|
extern GtkWidget *task_show_icon, *task_show_text, *task_align_center, *font_shadow;
|
||||||
GtkWidget *task_maximum_width, *task_maximum_height, *task_padding_x, *task_padding_y, *task_font;
|
extern GtkWidget *task_maximum_width, *task_maximum_height, *task_padding_x, *task_padding_y, *task_font;
|
||||||
|
extern GtkWidget *task_default_color, *task_default_color_set,
|
||||||
|
*task_default_icon_opacity, *task_default_icon_osb_set,
|
||||||
|
*task_default_icon_saturation,
|
||||||
|
*task_default_icon_brightness,
|
||||||
|
*task_default_background, *task_default_background_set;
|
||||||
|
extern GtkWidget *task_normal_color, *task_normal_color_set,
|
||||||
|
*task_normal_icon_opacity, *task_normal_icon_osb_set,
|
||||||
|
*task_normal_icon_saturation,
|
||||||
|
*task_normal_icon_brightness,
|
||||||
|
*task_normal_background, *task_normal_background_set;
|
||||||
|
extern GtkWidget *task_active_color, *task_active_color_set,
|
||||||
|
*task_active_icon_opacity, *task_active_icon_osb_set,
|
||||||
|
*task_active_icon_saturation,
|
||||||
|
*task_active_icon_brightness,
|
||||||
|
*task_active_background, *task_active_background_set;
|
||||||
|
extern GtkWidget *task_urgent_color, *task_urgent_color_set,
|
||||||
|
*task_urgent_icon_opacity, *task_urgent_icon_osb_set,
|
||||||
|
*task_urgent_icon_saturation,
|
||||||
|
*task_urgent_icon_brightness,
|
||||||
|
*task_urgent_background, *task_urgent_background_set;
|
||||||
|
extern GtkWidget *task_urgent_blinks;
|
||||||
|
extern GtkWidget *task_iconified_color, *task_iconified_color_set,
|
||||||
|
*task_iconified_icon_opacity, *task_iconified_icon_osb_set,
|
||||||
|
*task_iconified_icon_saturation,
|
||||||
|
*task_iconified_icon_brightness,
|
||||||
|
*task_iconified_background, *task_iconified_background_set;
|
||||||
|
|
||||||
// clock
|
// clock
|
||||||
GtkWidget *clock_format_line1, *clock_format_line2, *clock_tmz_line1, *clock_tmz_line2;
|
extern GtkWidget *clock_format_line1, *clock_format_line2, *clock_tmz_line1, *clock_tmz_line2;
|
||||||
GtkWidget *clock_left_command, *clock_right_command;
|
extern GtkWidget *clock_left_command, *clock_right_command;
|
||||||
GtkWidget *clock_padding_x, *clock_padding_y, *clock_font_line1, *clock_font_line2, *clock_font_color;
|
extern GtkWidget *clock_padding_x, *clock_padding_y, *clock_font_line1, *clock_font_line2, *clock_font_color;
|
||||||
|
extern GtkWidget *clock_background;
|
||||||
|
|
||||||
// battery
|
// battery
|
||||||
GtkWidget *battery_hide_if_higher, *battery_alert_if_lower, *battery_alert_cmd;
|
extern GtkWidget *battery_hide_if_higher, *battery_alert_if_lower, *battery_alert_cmd;
|
||||||
GtkWidget *battery_padding_x, *battery_padding_y, *battery_font_line1, *battery_font_line2, *battery_font_color;
|
extern GtkWidget *battery_padding_x, *battery_padding_y, *battery_font_line1, *battery_font_line2, *battery_font_color;
|
||||||
|
extern GtkWidget *battery_background;
|
||||||
|
|
||||||
// systray
|
// systray
|
||||||
GtkWidget *systray_icon_order, *systray_padding_x, *systray_padding_y, *systray_spacing;
|
extern GtkWidget *systray_icon_order, *systray_padding_x, *systray_padding_y, *systray_spacing;
|
||||||
GtkWidget *systray_icon_size, *systray_icon_opacity, *systray_icon_saturation, *systray_icon_brightness;
|
extern GtkWidget *systray_icon_size, *systray_icon_opacity, *systray_icon_saturation, *systray_icon_brightness;
|
||||||
|
extern GtkWidget *systray_background, *systray_monitor;
|
||||||
|
|
||||||
// tooltip
|
// tooltip
|
||||||
GtkWidget *tooltip_padding_x, *tooltip_padding_y, *tooltip_font, *tooltip_font_color;
|
extern GtkWidget *tooltip_padding_x, *tooltip_padding_y, *tooltip_font, *tooltip_font_color;
|
||||||
GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after;
|
extern GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after;
|
||||||
GtkWidget *clock_format_tooltip, *clock_tmz_tooltip;
|
extern GtkWidget *clock_format_tooltip, *clock_tmz_tooltip;
|
||||||
|
extern GtkWidget *tooltip_background;
|
||||||
|
|
||||||
// launcher
|
// launcher
|
||||||
GtkWidget *launcher_icon_size, *launcher_icon_theme, *launcher_padding_x, *launcher_padding_y, *launcher_spacing;
|
|
||||||
|
enum {
|
||||||
|
appsColIcon = 0,
|
||||||
|
appsColIconName,
|
||||||
|
appsColText,
|
||||||
|
appsColPath,
|
||||||
|
appsNumCols
|
||||||
|
};
|
||||||
|
|
||||||
|
extern GtkListStore *launcher_apps, *all_apps;
|
||||||
|
extern GtkWidget *launcher_apps_view, *all_apps_view;
|
||||||
|
extern GtkWidget *launcher_apps_dirs;
|
||||||
|
|
||||||
|
extern GtkWidget *launcher_icon_size, *launcher_icon_theme, *launcher_padding_x, *launcher_padding_y, *launcher_spacing;
|
||||||
|
extern GtkWidget *margin_x, *margin_y;
|
||||||
|
extern GtkWidget *launcher_background;
|
||||||
|
extern GtkWidget *startup_notifications;
|
||||||
|
extern IconThemeWrapper *icon_theme;
|
||||||
|
extern GtkWidget *launcher_tooltip;
|
||||||
|
|
||||||
|
void load_desktop_file(const char *file, gboolean selected);
|
||||||
|
void set_current_icon_theme(const char *theme);
|
||||||
|
gchar *get_current_icon_theme();
|
||||||
|
|
||||||
// background
|
// background
|
||||||
GtkWidget *combo_background;
|
enum {
|
||||||
GtkWidget *margin_x, *margin_y;
|
bgColPixbuf = 0,
|
||||||
|
bgColFillColor,
|
||||||
|
bgColFillOpacity,
|
||||||
|
bgColBorderColor,
|
||||||
|
bgColBorderOpacity,
|
||||||
|
bgColBorderWidth,
|
||||||
|
bgColCornerRadius,
|
||||||
|
bgNumCols
|
||||||
|
};
|
||||||
|
|
||||||
|
extern GtkListStore *backgrounds;
|
||||||
|
extern GtkWidget *current_background,
|
||||||
|
*background_fill_color,
|
||||||
|
*background_border_color,
|
||||||
|
*background_border_width,
|
||||||
|
*background_corner_radius;
|
||||||
|
|
||||||
|
void background_create_new();
|
||||||
|
void background_force_update();
|
||||||
|
int background_index_safe(int index);
|
||||||
|
|
||||||
GtkWidget *create_properties();
|
GtkWidget *create_properties();
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
#ifndef PROPERTIES_RW
|
#ifndef PROPERTIES_RW
|
||||||
#define PROPERTIES_RW
|
#define PROPERTIES_RW
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
char *get_current_theme_file_name();
|
||||||
|
gboolean config_is_manual(const char *path);
|
||||||
void config_read_file (const char *path);
|
void config_read_file (const char *path);
|
||||||
void config_save_file(const char *path);
|
void config_save_file(const char *path);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ GtkListStore *g_store;
|
|||||||
int g_width_list, g_height_list;
|
int g_width_list, g_height_list;
|
||||||
GtkCellRenderer *g_renderer;
|
GtkCellRenderer *g_renderer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GtkWidget *create_view()
|
GtkWidget *create_view()
|
||||||
{
|
{
|
||||||
GtkTreeViewColumn *col;
|
GtkTreeViewColumn *col;
|
||||||
@@ -85,8 +83,6 @@ void custom_list_append(const gchar *name)
|
|||||||
gchar *b, *n;
|
gchar *b, *n;
|
||||||
b = strrchr(name, '/');
|
b = strrchr(name, '/');
|
||||||
n = g_strdup(b+1);
|
n = g_strdup(b+1);
|
||||||
b = strrchr(n, '.');
|
|
||||||
*b = '\0';
|
|
||||||
gtk_list_store_set(g_store, &iter, COL_THEME_NAME, n, -1);
|
gtk_list_store_set(g_store, &iter, COL_THEME_NAME, n, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +92,9 @@ gboolean update_snapshot()
|
|||||||
GtkTreeModel *model;
|
GtkTreeModel *model;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
GdkPixbuf *icon;
|
GdkPixbuf *icon;
|
||||||
gboolean have_iter, found = FALSE;
|
gboolean have_iter;
|
||||||
|
|
||||||
|
gint pixWidth = 200, pixHeight = 30;
|
||||||
|
|
||||||
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
|
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_theme_view));
|
||||||
have_iter = gtk_tree_model_get_iter_first(model, &iter);
|
have_iter = gtk_tree_model_get_iter_first(model, &iter);
|
||||||
@@ -104,54 +102,42 @@ gboolean update_snapshot()
|
|||||||
gtk_tree_model_get(model, &iter, COL_SNAPSHOT, &icon, -1);
|
gtk_tree_model_get(model, &iter, COL_SNAPSHOT, &icon, -1);
|
||||||
if (icon != NULL) {
|
if (icon != NULL) {
|
||||||
g_object_unref(icon);
|
g_object_unref(icon);
|
||||||
have_iter = gtk_tree_model_iter_next(model, &iter);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
found = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
// build panel's snapshot
|
// build panel's snapshot
|
||||||
GdkPixbuf *pixbuf;
|
GdkPixbuf *pixbuf = NULL;
|
||||||
gchar *name, *snap, *cmd;
|
gchar *name, *snap, *cmd;
|
||||||
gint pixWidth, pixHeight;
|
|
||||||
gboolean changeSize = FALSE;
|
|
||||||
|
|
||||||
snap = g_build_filename (g_get_user_config_dir(), "tint2", "snap.jpg", NULL);
|
snap = g_build_filename(g_get_user_config_dir(), "tint2", "snap.jpg", NULL);
|
||||||
g_remove(snap);
|
g_remove(snap);
|
||||||
|
|
||||||
gtk_tree_model_get(model, &iter, COL_THEME_FILE, &name, -1);
|
gtk_tree_model_get(model, &iter, COL_THEME_FILE, &name, -1);
|
||||||
cmd = g_strdup_printf("tint2 -c \'%s\' -s \'%s\'", name, snap);
|
cmd = g_strdup_printf("tint2 -c \'%s\' -s \'%s\'", name, snap);
|
||||||
system(cmd);
|
if (system(cmd) == 0) {
|
||||||
|
// load
|
||||||
// load
|
pixbuf = gdk_pixbuf_new_from_file(snap, NULL);
|
||||||
pixbuf = gdk_pixbuf_new_from_file(snap, NULL);
|
if (pixbuf == NULL) {
|
||||||
if (pixbuf == NULL) {
|
printf("snapshot NULL : %s\n", cmd);
|
||||||
printf("snapshot NULL : %s\n", cmd);
|
}
|
||||||
found = FALSE;
|
|
||||||
}
|
}
|
||||||
g_free(snap);
|
g_free(snap);
|
||||||
g_free(cmd);
|
g_free(cmd);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
|
|
||||||
pixWidth = gdk_pixbuf_get_width(pixbuf);
|
gint w, h;
|
||||||
pixHeight = gdk_pixbuf_get_height(pixbuf);
|
w = gdk_pixbuf_get_width(pixbuf);
|
||||||
if (g_width_list != pixWidth) {
|
h = gdk_pixbuf_get_height(pixbuf);
|
||||||
g_width_list = pixWidth;
|
pixWidth = w > pixWidth ? w : pixWidth;
|
||||||
changeSize = TRUE;
|
pixHeight = h > pixHeight ? h : pixHeight;
|
||||||
}
|
|
||||||
if (g_height_list != (pixHeight+30)) {
|
|
||||||
g_height_list = pixHeight+30;
|
|
||||||
changeSize = TRUE;
|
|
||||||
}
|
|
||||||
if (changeSize)
|
|
||||||
gtk_cell_renderer_set_fixed_size(g_renderer, g_width_list, g_height_list);
|
|
||||||
|
|
||||||
gtk_list_store_set(g_store, &iter, COL_SNAPSHOT, pixbuf, -1);
|
gtk_list_store_set(g_store, &iter, COL_SNAPSHOT, pixbuf, -1);
|
||||||
|
|
||||||
|
have_iter = gtk_tree_model_iter_next(model, &iter);
|
||||||
}
|
}
|
||||||
return found;
|
|
||||||
|
gtk_cell_renderer_set_fixed_size(g_renderer, pixWidth + 30, pixHeight + 30);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ GtkWidget *create_view();
|
|||||||
|
|
||||||
void custom_list_append(const gchar *name);
|
void custom_list_append(const gchar *name);
|
||||||
|
|
||||||
gboolean update_snapshot();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
Encoding=UTF-8
|
|
||||||
Name=Panel tint2
|
Name=Panel tint2
|
||||||
Name[am]=ፓነል tint2
|
Name[am]=ፓነል tint2
|
||||||
Name[ar]=الشريط tint2
|
Name[ar]=الشريط tint2
|
||||||
|
|||||||
@@ -436,6 +436,8 @@ class TintWizardGUI(gtk.Window):
|
|||||||
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
|
self.resetConfig()
|
||||||
|
|
||||||
# If tintwizard was launched with a tint2 config filename
|
# If tintwizard was launched with a tint2 config filename
|
||||||
# as an argument, load that config.
|
# as an argument, load that config.
|
||||||
if self.oneConfigFile:
|
if self.oneConfigFile:
|
||||||
@@ -862,20 +864,24 @@ class TintWizardGUI(gtk.Window):
|
|||||||
|
|
||||||
mouseCmds = ["none", "close", "toggle", "iconify", "shade", "toggle_iconify", "maximize_restore", "desktop_left", "desktop_right", "next_task", "prev_task"]
|
mouseCmds = ["none", "close", "toggle", "iconify", "shade", "toggle_iconify", "maximize_restore", "desktop_left", "desktop_right", "next_task", "prev_task"]
|
||||||
|
|
||||||
createLabel(self.tableMouse, text="Middle Mouse Click Action", gridX=0, gridY=0, xPadding=10)
|
createLabel(self.tableMouse, text="Left Mouse Click Action", gridX=0, gridY=0, xPadding=10)
|
||||||
self.mouseMiddle = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=0, handler=self.changeOccurred)
|
self.mouseLeft = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=0, handler=self.changeOccurred)
|
||||||
|
self.registerComponent("mouse_left", self.mouseLeft)
|
||||||
|
|
||||||
|
createLabel(self.tableMouse, text="Middle Mouse Click Action", gridX=0, gridY=1, xPadding=10)
|
||||||
|
self.mouseMiddle = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=1, handler=self.changeOccurred)
|
||||||
self.registerComponent("mouse_middle", self.mouseMiddle)
|
self.registerComponent("mouse_middle", self.mouseMiddle)
|
||||||
|
|
||||||
createLabel(self.tableMouse, text="Right Mouse Click Action", gridX=0, gridY=1, xPadding=10)
|
createLabel(self.tableMouse, text="Right Mouse Click Action", gridX=0, gridY=2, xPadding=10)
|
||||||
self.mouseRight = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=1, handler=self.changeOccurred)
|
self.mouseRight = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=2, handler=self.changeOccurred)
|
||||||
self.registerComponent("mouse_right", self.mouseRight)
|
self.registerComponent("mouse_right", self.mouseRight)
|
||||||
|
|
||||||
createLabel(self.tableMouse, text="Mouse Wheel Scroll Up Action", gridX=0, gridY=2, xPadding=10)
|
createLabel(self.tableMouse, text="Mouse Wheel Scroll Up Action", gridX=0, gridY=3, xPadding=10)
|
||||||
self.mouseUp = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=2, handler=self.changeOccurred)
|
self.mouseUp = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=3, handler=self.changeOccurred)
|
||||||
self.registerComponent("mouse_scroll_up", self.mouseUp)
|
self.registerComponent("mouse_scroll_up", self.mouseUp)
|
||||||
|
|
||||||
createLabel(self.tableMouse, text="Mouse Wheel Scroll Down Action", gridX=0, gridY=3, xPadding=10)
|
createLabel(self.tableMouse, text="Mouse Wheel Scroll Down Action", gridX=0, gridY=4, xPadding=10)
|
||||||
self.mouseDown = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=3, handler=self.changeOccurred)
|
self.mouseDown = createComboBox(self.tableMouse, mouseCmds, gridX=1, gridY=4, handler=self.changeOccurred)
|
||||||
self.registerComponent("mouse_scroll_down", self.mouseDown)
|
self.registerComponent("mouse_scroll_down", self.mouseDown)
|
||||||
|
|
||||||
def createTooltipsWidgets(self):
|
def createTooltipsWidgets(self):
|
||||||
@@ -1397,6 +1403,7 @@ class TintWizardGUI(gtk.Window):
|
|||||||
int(self.tooltipFontColButton.get_alpha() / 65535.0 * 100)))
|
int(self.tooltipFontColButton.get_alpha() / 65535.0 * 100)))
|
||||||
|
|
||||||
self.configBuf.insert(self.configBuf.get_end_iter(), "\n# Mouse\n")
|
self.configBuf.insert(self.configBuf.get_end_iter(), "\n# Mouse\n")
|
||||||
|
self.configBuf.insert(self.configBuf.get_end_iter(), "mouse_left = %s\n" % (self.mouseLeft.get_active_text()))
|
||||||
self.configBuf.insert(self.configBuf.get_end_iter(), "mouse_middle = %s\n" % (self.mouseMiddle.get_active_text()))
|
self.configBuf.insert(self.configBuf.get_end_iter(), "mouse_middle = %s\n" % (self.mouseMiddle.get_active_text()))
|
||||||
self.configBuf.insert(self.configBuf.get_end_iter(), "mouse_right = %s\n" % (self.mouseRight.get_active_text()))
|
self.configBuf.insert(self.configBuf.get_end_iter(), "mouse_right = %s\n" % (self.mouseRight.get_active_text()))
|
||||||
self.configBuf.insert(self.configBuf.get_end_iter(), "mouse_scroll_up = %s\n" % (self.mouseUp.get_active_text()))
|
self.configBuf.insert(self.configBuf.get_end_iter(), "mouse_scroll_up = %s\n" % (self.mouseUp.get_active_text()))
|
||||||
@@ -1847,6 +1854,7 @@ class TintWizardGUI(gtk.Window):
|
|||||||
self.tooltipFontColButton.set_color(gtk.gdk.color_parse(self.defaults["fgColor"]))
|
self.tooltipFontColButton.set_color(gtk.gdk.color_parse(self.defaults["fgColor"]))
|
||||||
self.tooltipFontCol.set_text(self.defaults["fgColor"])
|
self.tooltipFontCol.set_text(self.defaults["fgColor"])
|
||||||
# Mouse
|
# Mouse
|
||||||
|
self.mouseLeft.set_active(5)
|
||||||
self.mouseMiddle.set_active(0)
|
self.mouseMiddle.set_active(0)
|
||||||
self.mouseRight.set_active(0)
|
self.mouseRight.set_active(0)
|
||||||
self.mouseUp.set_active(0)
|
self.mouseUp.set_active(0)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
static int x, y, width, height;
|
static int x, y, width, height;
|
||||||
|
static int just_shown;
|
||||||
|
|
||||||
// the next functions are helper functions for tooltip handling
|
// the next functions are helper functions for tooltip handling
|
||||||
void start_show_timeout();
|
void start_show_timeout();
|
||||||
@@ -46,22 +47,26 @@ void default_tooltip()
|
|||||||
g_tooltip.font_color.color[1] = 1;
|
g_tooltip.font_color.color[1] = 1;
|
||||||
g_tooltip.font_color.color[2] = 1;
|
g_tooltip.font_color.color[2] = 1;
|
||||||
g_tooltip.font_color.alpha = 1;
|
g_tooltip.font_color.alpha = 1;
|
||||||
|
just_shown = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_tooltip()
|
void cleanup_tooltip()
|
||||||
{
|
{
|
||||||
stop_tooltip_timeout();
|
stop_tooltip_timeout();
|
||||||
tooltip_hide(0);
|
tooltip_hide(NULL);
|
||||||
tooltip_copy_text(0);
|
tooltip_copy_text(NULL);
|
||||||
if (g_tooltip.window) XDestroyWindow(server.dsp, g_tooltip.window);
|
if (g_tooltip.window)
|
||||||
if (g_tooltip.font_desc) pango_font_description_free(g_tooltip.font_desc);
|
XDestroyWindow(server.dsp, g_tooltip.window);
|
||||||
|
g_tooltip.window = 0;
|
||||||
|
pango_font_description_free(g_tooltip.font_desc);
|
||||||
|
g_tooltip.font_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void init_tooltip()
|
void init_tooltip()
|
||||||
{
|
{
|
||||||
if (!g_tooltip.font_desc)
|
if (!g_tooltip.font_desc)
|
||||||
g_tooltip.font_desc = pango_font_description_from_string("sans 10");
|
g_tooltip.font_desc = pango_font_description_from_string(DEFAULT_FONT);
|
||||||
if (g_tooltip.bg == 0)
|
if (g_tooltip.bg == 0)
|
||||||
g_tooltip.bg = &g_array_index(backgrounds, Background, 0);
|
g_tooltip.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
|
|
||||||
@@ -72,7 +77,8 @@ void init_tooltip()
|
|||||||
attr.background_pixel = 0;
|
attr.background_pixel = 0;
|
||||||
attr.border_pixel = 0;
|
attr.border_pixel = 0;
|
||||||
unsigned long mask = CWEventMask|CWColormap|CWBorderPixel|CWBackPixel|CWOverrideRedirect;
|
unsigned long mask = CWEventMask|CWColormap|CWBorderPixel|CWBackPixel|CWOverrideRedirect;
|
||||||
if (g_tooltip.window) XDestroyWindow(server.dsp, g_tooltip.window);
|
if (g_tooltip.window)
|
||||||
|
XDestroyWindow(server.dsp, g_tooltip.window);
|
||||||
g_tooltip.window = XCreateWindow(server.dsp, server.root_win, 0, 0, 100, 20, 0, server.depth, InputOutput, server.visual, mask, &attr);
|
g_tooltip.window = XCreateWindow(server.dsp, server.root_win, 0, 0, 100, 20, 0, server.depth, InputOutput, server.visual, mask, &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,10 +86,9 @@ void init_tooltip()
|
|||||||
void tooltip_trigger_show(Area* area, Panel* p, XEvent *e)
|
void tooltip_trigger_show(Area* area, Panel* p, XEvent *e)
|
||||||
{
|
{
|
||||||
// Position the tooltip in the center of the area
|
// Position the tooltip in the center of the area
|
||||||
x = area->posx + area->width / 2 + e->xmotion.x_root - e->xmotion.x;
|
x = area->posx + MIN(area->width / 3, 22) + e->xmotion.x_root - e->xmotion.x;
|
||||||
y = area->posy + area->height / 2 + e->xmotion.y_root - e->xmotion.y;
|
y = area->posy + area->height / 2 + e->xmotion.y_root - e->xmotion.y;
|
||||||
if (!panel_horizontal)
|
just_shown = 1;
|
||||||
y -= height/2;
|
|
||||||
g_tooltip.panel = p;
|
g_tooltip.panel = p;
|
||||||
if (g_tooltip.mapped && g_tooltip.area != area) {
|
if (g_tooltip.mapped && g_tooltip.area != area) {
|
||||||
tooltip_copy_text(area);
|
tooltip_copy_text(area);
|
||||||
@@ -102,10 +107,7 @@ void tooltip_show(void* arg)
|
|||||||
Window w;
|
Window w;
|
||||||
XTranslateCoordinates( server.dsp, server.root_win, g_tooltip.panel->main_win, x, y, &mx, &my, &w);
|
XTranslateCoordinates( server.dsp, server.root_win, g_tooltip.panel->main_win, x, y, &mx, &my, &w);
|
||||||
Area* area;
|
Area* area;
|
||||||
if (!panel_horizontal)
|
|
||||||
my += height/2; /* we adjusted y in tooltip_trigger_show, revert or we won't find the correct area anymore */
|
|
||||||
area = click_area(g_tooltip.panel, mx, my);
|
area = click_area(g_tooltip.panel, mx, my);
|
||||||
stop_tooltip_timeout();
|
|
||||||
if (!g_tooltip.mapped && area->_get_tooltip_text) {
|
if (!g_tooltip.mapped && area->_get_tooltip_text) {
|
||||||
tooltip_copy_text(area);
|
tooltip_copy_text(area);
|
||||||
g_tooltip.mapped = True;
|
g_tooltip.mapped = True;
|
||||||
@@ -201,6 +203,11 @@ void tooltip_update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
tooltip_update_geometry();
|
tooltip_update_geometry();
|
||||||
|
if (just_shown) {
|
||||||
|
if (!panel_horizontal)
|
||||||
|
y -= height/2; // center vertically
|
||||||
|
just_shown = 0;
|
||||||
|
}
|
||||||
tooltip_adjust_geometry();
|
tooltip_adjust_geometry();
|
||||||
XMoveResizeWindow(server.dsp, g_tooltip.window, x, y, width, height);
|
XMoveResizeWindow(server.dsp, g_tooltip.window, x, y, width, height);
|
||||||
|
|
||||||
@@ -241,7 +248,9 @@ void tooltip_update()
|
|||||||
pango_layout_set_height(layout, height*PANGO_SCALE);
|
pango_layout_set_height(layout, height*PANGO_SCALE);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and vert.)
|
// I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and vert.)
|
||||||
cairo_move_to(c, -r1.x/2+g_tooltip.bg->border.width+g_tooltip.paddingx, -r1.y/2+g_tooltip.bg->border.width+g_tooltip.paddingy);
|
cairo_move_to(c,
|
||||||
|
-r1.x/2 + g_tooltip.bg->border.width + g_tooltip.paddingx,
|
||||||
|
-r1.y/2 + 1 + g_tooltip.bg->border.width + g_tooltip.paddingy);
|
||||||
pango_cairo_show_layout (c, layout);
|
pango_cairo_show_layout (c, layout);
|
||||||
|
|
||||||
g_object_unref (layout);
|
g_object_unref (layout);
|
||||||
@@ -265,7 +274,6 @@ void tooltip_trigger_hide(Tooltip* tooltip)
|
|||||||
|
|
||||||
void tooltip_hide(void* arg)
|
void tooltip_hide(void* arg)
|
||||||
{
|
{
|
||||||
stop_tooltip_timeout();
|
|
||||||
if (g_tooltip.mapped) {
|
if (g_tooltip.mapped) {
|
||||||
g_tooltip.mapped = False;
|
g_tooltip.mapped = False;
|
||||||
XUnmapWindow(server.dsp, g_tooltip.window);
|
XUnmapWindow(server.dsp, g_tooltip.window);
|
||||||
@@ -276,28 +284,19 @@ void tooltip_hide(void* arg)
|
|||||||
|
|
||||||
void start_show_timeout()
|
void start_show_timeout()
|
||||||
{
|
{
|
||||||
if (g_tooltip.timeout)
|
change_timeout(&g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
||||||
change_timeout(g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
|
||||||
else
|
|
||||||
g_tooltip.timeout = add_timeout(g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void start_hide_timeout()
|
void start_hide_timeout()
|
||||||
{
|
{
|
||||||
if (g_tooltip.timeout)
|
change_timeout(&g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
||||||
change_timeout(g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
|
||||||
else
|
|
||||||
g_tooltip.timeout = add_timeout(g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stop_tooltip_timeout()
|
void stop_tooltip_timeout()
|
||||||
{
|
{
|
||||||
if (g_tooltip.timeout) {
|
stop_timeout(g_tooltip.timeout);
|
||||||
stop_timeout(g_tooltip.timeout);
|
|
||||||
g_tooltip.timeout = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -307,6 +306,6 @@ void tooltip_copy_text(Area* area)
|
|||||||
if (area && area->_get_tooltip_text)
|
if (area && area->_get_tooltip_text)
|
||||||
g_tooltip.tooltip_text = strdup(area->_get_tooltip_text(area));
|
g_tooltip.tooltip_text = strdup(area->_get_tooltip_text(area));
|
||||||
else
|
else
|
||||||
g_tooltip.tooltip_text = 0;
|
g_tooltip.tooltip_text = NULL;
|
||||||
g_tooltip.area = area;
|
g_tooltip.area = area;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,11 +82,15 @@ void init_rendering(void *obj, int pos)
|
|||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
child->posy = pos + a->bg->border.width + a->paddingy;
|
child->posy = pos + a->bg->border.width + a->paddingy;
|
||||||
child->height = a->height - (2 * (a->bg->border.width + a->paddingy));
|
child->height = a->height - (2 * (a->bg->border.width + a->paddingy));
|
||||||
|
if (child->_on_change_layout)
|
||||||
|
child->_on_change_layout(child);
|
||||||
init_rendering(child, child->posy);
|
init_rendering(child, child->posy);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
child->posx = pos + a->bg->border.width + a->paddingy;
|
child->posx = pos + a->bg->border.width + a->paddingy;
|
||||||
child->width = a->width - (2 * (a->bg->border.width + a->paddingy));
|
child->width = a->width - (2 * (a->bg->border.width + a->paddingy));
|
||||||
|
if (child->_on_change_layout)
|
||||||
|
child->_on_change_layout(child);
|
||||||
init_rendering(child, child->posx);
|
init_rendering(child, child->posx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -452,6 +456,9 @@ void add_area (Area *a)
|
|||||||
|
|
||||||
void free_area (Area *a)
|
void free_area (Area *a)
|
||||||
{
|
{
|
||||||
|
if (!a)
|
||||||
|
return;
|
||||||
|
|
||||||
GSList *l0;
|
GSList *l0;
|
||||||
for (l0 = a->list; l0 ; l0 = l0->next)
|
for (l0 = a->list; l0 ; l0 = l0->next)
|
||||||
free_area (l0->data);
|
free_area (l0->data);
|
||||||
|
|||||||
@@ -25,8 +25,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <glib.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "../server.h"
|
#include "../server.h"
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@
|
|||||||
void copy_file(const char *pathSrc, const char *pathDest)
|
void copy_file(const char *pathSrc, const char *pathDest)
|
||||||
{
|
{
|
||||||
FILE *fileSrc, *fileDest;
|
FILE *fileSrc, *fileDest;
|
||||||
char line[100];
|
char buffer[100];
|
||||||
int nb;
|
int nb;
|
||||||
|
|
||||||
fileSrc = fopen(pathSrc, "rb");
|
fileSrc = fopen(pathSrc, "rb");
|
||||||
@@ -44,9 +45,11 @@ void copy_file(const char *pathSrc, const char *pathDest)
|
|||||||
fileDest = fopen(pathDest, "wb");
|
fileDest = fopen(pathDest, "wb");
|
||||||
if (fileDest == NULL) return;
|
if (fileDest == NULL) return;
|
||||||
|
|
||||||
while ((nb = fread(line, 1, 100, fileSrc)) > 0)
|
while ((nb = fread(buffer, 1, sizeof(buffer), fileSrc)) > 0) {
|
||||||
if ( nb != fwrite(line, 1, nb, fileDest))
|
if ( nb != fwrite(buffer, 1, nb, fileDest)) {
|
||||||
printf("Error while copying file %s to %s\n", pathSrc, pathDest);
|
printf("Error while copying file %s to %s\n", pathSrc, pathDest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fclose (fileDest);
|
fclose (fileDest);
|
||||||
fclose (fileSrc);
|
fclose (fileSrc);
|
||||||
@@ -93,6 +96,43 @@ void tint_exec(const char *command)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *expand_tilde(char *s)
|
||||||
|
{
|
||||||
|
const gchar *home = g_get_home_dir();
|
||||||
|
if (home &&
|
||||||
|
(strcmp(s, "~") == 0 ||
|
||||||
|
strstr(s, "~/") == s)) {
|
||||||
|
char *result = calloc(strlen(home) + strlen(s), 1);
|
||||||
|
strcat(result, home);
|
||||||
|
strcat(result, s + 1);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return strdup(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *contract_tilde(char *s)
|
||||||
|
{
|
||||||
|
const gchar *home = g_get_home_dir();
|
||||||
|
if (!home)
|
||||||
|
return strdup(s);
|
||||||
|
|
||||||
|
char *home_slash = calloc(strlen(home) + 1, 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);
|
||||||
|
strcat(result, "~");
|
||||||
|
strcat(result, s + strlen(home));
|
||||||
|
free(home_slash);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
free(home_slash);
|
||||||
|
return strdup(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int hex_char_to_int (char c)
|
int hex_char_to_int (char c)
|
||||||
{
|
{
|
||||||
@@ -138,6 +178,7 @@ int hex_to_rgb (char *hex, int *r, int *g, int *b)
|
|||||||
void get_color (char *hex, double *rgb)
|
void get_color (char *hex, double *rgb)
|
||||||
{
|
{
|
||||||
int r, g, b;
|
int r, g, b;
|
||||||
|
r = g = b = 0;
|
||||||
hex_to_rgb (hex, &r, &g, &b);
|
hex_to_rgb (hex, &r, &g, &b);
|
||||||
|
|
||||||
rgb[0] = (r / 255.0);
|
rgb[0] = (r / 255.0);
|
||||||
@@ -294,7 +335,6 @@ void adjust_asb(DATA32 *data, int w, int h, int alpha, float satur, float bright
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void createHeuristicMask(DATA32* data, int w, int h)
|
void createHeuristicMask(DATA32* data, int w, int h)
|
||||||
{
|
{
|
||||||
// first we need to find the mask color, therefore we check all 4 edge pixel and take the color which
|
// first we need to find the mask color, therefore we check all 4 edge pixel and take the color which
|
||||||
@@ -342,3 +382,24 @@ void render_image(Drawable d, int x, int y, int w, int h)
|
|||||||
XRenderFreePicture(server.dsp, pict_image);
|
XRenderFreePicture(server.dsp, pict_image);
|
||||||
XRenderFreePicture(server.dsp, pict_drawable);
|
XRenderFreePicture(server.dsp, pict_drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow)
|
||||||
|
{
|
||||||
|
if (font_shadow) {
|
||||||
|
const int shadow_size = 3;
|
||||||
|
const double shadow_edge_alpha = 0.0;
|
||||||
|
int i, j;
|
||||||
|
for (i = -shadow_size; i <= shadow_size; i++) {
|
||||||
|
for (j = -shadow_size; j <= shadow_size; j++) {
|
||||||
|
cairo_set_source_rgba(c, 0.0, 0.0, 0.0, 1.0 - (1.0 - shadow_edge_alpha) * sqrt((i*i + j*j)/(double)(shadow_size*shadow_size)));
|
||||||
|
pango_cairo_update_layout(c, layout);
|
||||||
|
cairo_move_to(c, posx + i, posy + j);
|
||||||
|
pango_cairo_show_layout(c, layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cairo_set_source_rgba (c, color->color[0], color->color[1], color->color[2], color->alpha);
|
||||||
|
pango_cairo_update_layout (c, layout);
|
||||||
|
cairo_move_to (c, posx, posy);
|
||||||
|
pango_cairo_show_layout (c, layout);
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#define WM_CLASS_TINT "panel"
|
#define WM_CLASS_TINT "panel"
|
||||||
|
|
||||||
#include <Imlib2.h>
|
#include <Imlib2.h>
|
||||||
|
#include <pango/pangocairo.h>
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -43,6 +44,13 @@ int parse_line (const char *line, char **key, char **value);
|
|||||||
// execute a command by calling fork
|
// execute a command by calling fork
|
||||||
void tint_exec(const char* command);
|
void tint_exec(const char* command);
|
||||||
|
|
||||||
|
// Returns a copy of s in which "~" is expanded to the path to the user's home directory.
|
||||||
|
// The returned string must be freed by the caller.
|
||||||
|
char *expand_tilde(char *s);
|
||||||
|
|
||||||
|
// The opposite of expand_tilde: replaces the path to the user's home directory with "~".
|
||||||
|
// The returned string must be freed by the caller.
|
||||||
|
char *contract_tilde(char *s);
|
||||||
|
|
||||||
// conversion
|
// conversion
|
||||||
int hex_char_to_int (char c);
|
int hex_char_to_int (char c);
|
||||||
@@ -57,5 +65,8 @@ void adjust_asb(DATA32 *data, int w, int h, int alpha, float satur, float bright
|
|||||||
void createHeuristicMask(DATA32* data, int w, int h);
|
void createHeuristicMask(DATA32* data, int w, int h);
|
||||||
|
|
||||||
void render_image(Drawable d, int x, int y, int w, int h);
|
void render_image(Drawable d, int x, int y, int w, int h);
|
||||||
|
|
||||||
|
void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color, int font_shadow);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
178
src/util/strnatcmp.c
Normal file
178
src/util/strnatcmp.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/* -*- mode: c; c-file-style: "k&r" -*-
|
||||||
|
|
||||||
|
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
|
||||||
|
Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* partial change history:
|
||||||
|
*
|
||||||
|
* 2004-10-10 mbp: Lift out character type dependencies into macros.
|
||||||
|
*
|
||||||
|
* Eric Sosman pointed out that ctype functions take a parameter whose
|
||||||
|
* value must be that of an unsigned int, even on platforms that have
|
||||||
|
* negative chars in their default char type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "strnatcmp.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* These are defined as macros to make it easier to adapt this code to
|
||||||
|
* different characters types or comparison functions. */
|
||||||
|
static inline int
|
||||||
|
nat_isdigit(nat_char a)
|
||||||
|
{
|
||||||
|
return isdigit((unsigned char) a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nat_isspace(nat_char a)
|
||||||
|
{
|
||||||
|
return isspace((unsigned char) a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline nat_char
|
||||||
|
nat_toupper(nat_char a)
|
||||||
|
{
|
||||||
|
return toupper((unsigned char) a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_right(nat_char const *a, nat_char const *b)
|
||||||
|
{
|
||||||
|
int bias = 0;
|
||||||
|
|
||||||
|
/* The longest run of digits wins. That aside, the greatest
|
||||||
|
value wins, but we can't know that it will until we've scanned
|
||||||
|
both numbers to know that they have the same magnitude, so we
|
||||||
|
remember it in BIAS. */
|
||||||
|
for (;; a++, b++) {
|
||||||
|
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||||
|
return bias;
|
||||||
|
else if (!nat_isdigit(*a))
|
||||||
|
return -1;
|
||||||
|
else if (!nat_isdigit(*b))
|
||||||
|
return +1;
|
||||||
|
else if (*a < *b) {
|
||||||
|
if (!bias)
|
||||||
|
bias = -1;
|
||||||
|
} else if (*a > *b) {
|
||||||
|
if (!bias)
|
||||||
|
bias = +1;
|
||||||
|
} else if (!*a && !*b)
|
||||||
|
return bias;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_left(nat_char const *a, nat_char const *b)
|
||||||
|
{
|
||||||
|
/* Compare two left-aligned numbers: the first to have a
|
||||||
|
different value wins. */
|
||||||
|
for (;; a++, b++) {
|
||||||
|
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||||
|
return 0;
|
||||||
|
else if (!nat_isdigit(*a))
|
||||||
|
return -1;
|
||||||
|
else if (!nat_isdigit(*b))
|
||||||
|
return +1;
|
||||||
|
else if (*a < *b)
|
||||||
|
return -1;
|
||||||
|
else if (*a > *b)
|
||||||
|
return +1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case)
|
||||||
|
{
|
||||||
|
int ai, bi;
|
||||||
|
nat_char ca, cb;
|
||||||
|
int fractional, result;
|
||||||
|
|
||||||
|
assert(a && b);
|
||||||
|
ai = bi = 0;
|
||||||
|
while (1) {
|
||||||
|
ca = a[ai]; cb = b[bi];
|
||||||
|
|
||||||
|
/* skip over leading spaces or zeros */
|
||||||
|
while (nat_isspace(ca))
|
||||||
|
ca = a[++ai];
|
||||||
|
|
||||||
|
while (nat_isspace(cb))
|
||||||
|
cb = b[++bi];
|
||||||
|
|
||||||
|
/* process run of digits */
|
||||||
|
if (nat_isdigit(ca) && nat_isdigit(cb)) {
|
||||||
|
fractional = (ca == '0' || cb == '0');
|
||||||
|
|
||||||
|
if (fractional) {
|
||||||
|
if ((result = compare_left(a+ai, b+bi)) != 0)
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
if ((result = compare_right(a+ai, b+bi)) != 0)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ca && !cb) {
|
||||||
|
/* The strings compare the same. Perhaps the caller
|
||||||
|
will want to call strcmp to break the tie. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fold_case) {
|
||||||
|
ca = nat_toupper(ca);
|
||||||
|
cb = nat_toupper(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ca < cb)
|
||||||
|
return -1;
|
||||||
|
else if (ca > cb)
|
||||||
|
return +1;
|
||||||
|
|
||||||
|
++ai; ++bi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int strnatcmp(nat_char const *a, nat_char const *b) {
|
||||||
|
return strnatcmp0(a, b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Compare, recognizing numeric string and ignoring case. */
|
||||||
|
int strnatcasecmp(nat_char const *a, nat_char const *b) {
|
||||||
|
return strnatcmp0(a, b, 1);
|
||||||
|
}
|
||||||
31
src/util/strnatcmp.h
Normal file
31
src/util/strnatcmp.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* -*- mode: c; c-file-style: "k&r" -*-
|
||||||
|
|
||||||
|
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
|
||||||
|
Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* CUSTOMIZATION SECTION
|
||||||
|
*
|
||||||
|
* You can change this typedef, but must then also change the inline
|
||||||
|
* functions in strnatcmp.c */
|
||||||
|
typedef char nat_char;
|
||||||
|
|
||||||
|
int strnatcmp(nat_char const *a, nat_char const *b);
|
||||||
|
int strnatcasecmp(nat_char const *a, nat_char const *b);
|
||||||
@@ -44,6 +44,7 @@ struct _timeout {
|
|||||||
void (*_callback)(void*);
|
void (*_callback)(void*);
|
||||||
void* arg;
|
void* arg;
|
||||||
multi_timeout* multi_timeout;
|
multi_timeout* multi_timeout;
|
||||||
|
timeout **self;
|
||||||
};
|
};
|
||||||
|
|
||||||
void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(void*), void* arg, timeout* t);
|
void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(void*), void* arg, timeout* t);
|
||||||
@@ -64,8 +65,8 @@ void stop_multi_timeout(timeout* t);
|
|||||||
|
|
||||||
void default_timeout()
|
void default_timeout()
|
||||||
{
|
{
|
||||||
timeout_list = 0;
|
timeout_list = NULL;
|
||||||
multi_timeouts = 0;
|
multi_timeouts = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_timeout()
|
void cleanup_timeout()
|
||||||
@@ -74,12 +75,14 @@ void cleanup_timeout()
|
|||||||
timeout* t = timeout_list->data;
|
timeout* t = timeout_list->data;
|
||||||
if (t->multi_timeout)
|
if (t->multi_timeout)
|
||||||
stop_multi_timeout(t);
|
stop_multi_timeout(t);
|
||||||
|
if (t->self)
|
||||||
|
*t->self = NULL;
|
||||||
free(t);
|
free(t);
|
||||||
timeout_list = g_slist_remove(timeout_list, t);
|
timeout_list = g_slist_remove(timeout_list, t);
|
||||||
}
|
}
|
||||||
if (multi_timeouts) {
|
if (multi_timeouts) {
|
||||||
g_hash_table_destroy(multi_timeouts);
|
g_hash_table_destroy(multi_timeouts);
|
||||||
multi_timeouts = 0;
|
multi_timeouts = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,25 +98,26 @@ void cleanup_timeout()
|
|||||||
* however it's save to call it.
|
* however it's save to call it.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg)
|
timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg, timeout **self)
|
||||||
{
|
{
|
||||||
timeout* t = malloc(sizeof(timeout));
|
timeout* t = calloc(1, sizeof(timeout));
|
||||||
t->multi_timeout = 0;
|
t->self = self;
|
||||||
add_timeout_intern(value_msec, interval_msec, _callback, arg, t);
|
add_timeout_intern(value_msec, interval_msec, _callback, arg, t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void change_timeout(timeout *t, int value_msec, int interval_msec, void(*_callback)(), void* arg)
|
void change_timeout(timeout **t, int value_msec, int interval_msec, void(*_callback)(), void* arg)
|
||||||
{
|
{
|
||||||
if ( g_slist_find(timeout_list, t) == 0 && g_hash_table_lookup(multi_timeouts, t) == 0)
|
if (!((timeout_list && g_slist_find(timeout_list, *t)) ||
|
||||||
printf("programming error: timeout already deleted...");
|
(multi_timeouts && g_hash_table_lookup(multi_timeouts, *t))))
|
||||||
|
*t = add_timeout(value_msec, interval_msec, _callback, arg, t);
|
||||||
else {
|
else {
|
||||||
if (t->multi_timeout)
|
if ((*t)->multi_timeout)
|
||||||
remove_from_multi_timeout((timeout*)t);
|
remove_from_multi_timeout(*t);
|
||||||
else
|
else
|
||||||
timeout_list = g_slist_remove(timeout_list, t);
|
timeout_list = g_slist_remove(timeout_list, *t);
|
||||||
add_timeout_intern(value_msec, interval_msec, _callback, arg, (timeout*)t);
|
add_timeout_intern(value_msec, interval_msec, _callback, arg, *t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,29 +153,40 @@ void callback_timeout_expired()
|
|||||||
if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
|
if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
|
||||||
// it's time for the callback function
|
// it's time for the callback function
|
||||||
t->_callback(t->arg);
|
t->_callback(t->arg);
|
||||||
|
// If _callback() calls stop_timeout(t) the timer 't' was freed and is not in the timeout_list
|
||||||
if (g_slist_find(timeout_list, t)) {
|
if (g_slist_find(timeout_list, t)) {
|
||||||
// if _callback() calls stop_timeout(t) the timeout 't' was freed and is not in the timeout_list
|
// Timer still exists
|
||||||
timeout_list = g_slist_remove(timeout_list, t);
|
timeout_list = g_slist_remove(timeout_list, t);
|
||||||
if (t->interval_msec > 0)
|
if (t->interval_msec > 0) {
|
||||||
add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t->arg, t);
|
add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t->arg, t);
|
||||||
else
|
} else {
|
||||||
|
// Destroy single-shot timer
|
||||||
|
if (t->self)
|
||||||
|
*t->self = NULL;
|
||||||
free(t);
|
free(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stop_timeout(timeout* t)
|
void stop_timeout(timeout* t)
|
||||||
{
|
{
|
||||||
|
if (!t)
|
||||||
|
return;
|
||||||
// if not in the list, it was deleted in callback_timeout_expired
|
// if not in the list, it was deleted in callback_timeout_expired
|
||||||
if (g_slist_find(timeout_list, t) || g_hash_table_lookup(multi_timeouts, t)) {
|
if ((timeout_list && g_slist_find(timeout_list, t)) ||
|
||||||
if (t->multi_timeout)
|
(multi_timeouts && g_hash_table_lookup(multi_timeouts, t))) {
|
||||||
remove_from_multi_timeout((timeout*)t);
|
if (multi_timeouts && t->multi_timeout)
|
||||||
timeout_list = g_slist_remove(timeout_list, t);
|
remove_from_multi_timeout(t);
|
||||||
free((void*)t);
|
if (timeout_list)
|
||||||
|
timeout_list = g_slist_remove(timeout_list, t);
|
||||||
|
if (t->self)
|
||||||
|
*t->self = NULL;
|
||||||
|
free(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +211,7 @@ void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(), v
|
|||||||
gint compare_timeouts(gconstpointer t1, gconstpointer t2)
|
gint compare_timeouts(gconstpointer t1, gconstpointer t2)
|
||||||
{
|
{
|
||||||
return compare_timespecs(&((timeout*)t1)->timeout_expires,
|
return compare_timespecs(&((timeout*)t1)->timeout_expires,
|
||||||
&((timeout*)t2)->timeout_expires);
|
&((timeout*)t2)->timeout_expires);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -260,12 +275,13 @@ int align_with_existing_timeouts(timeout *t)
|
|||||||
if (t->interval_msec % t2->interval_msec == 0 || t2->interval_msec % t->interval_msec == 0) {
|
if (t->interval_msec % t2->interval_msec == 0 || t2->interval_msec % t->interval_msec == 0) {
|
||||||
if (multi_timeouts == 0)
|
if (multi_timeouts == 0)
|
||||||
multi_timeouts = g_hash_table_new(0, 0);
|
multi_timeouts = g_hash_table_new(0, 0);
|
||||||
if (!t->multi_timeout && !t2->multi_timeout)
|
if (!t->multi_timeout && !t2->multi_timeout) {
|
||||||
// both timeouts can be aligned, but there is no multi timeout for them
|
// both timeouts can be aligned, but there is no multi timeout for them
|
||||||
create_multi_timeout(t, t2);
|
create_multi_timeout(t, t2);
|
||||||
else
|
} else {
|
||||||
// there is already a multi timeout, so we append the new timeout to the multi timeout
|
// there is already a multi timeout, so we append the new timeout to the multi timeout
|
||||||
append_multi_timeout(t, t2);
|
append_multi_timeout(t, t2);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,10 +309,10 @@ int calc_multi_timeout_interval(multi_timeout_handler* mth)
|
|||||||
|
|
||||||
void create_multi_timeout(timeout* t1, timeout* t2)
|
void create_multi_timeout(timeout* t1, timeout* t2)
|
||||||
{
|
{
|
||||||
multi_timeout* mt1 = malloc(sizeof(multi_timeout));
|
multi_timeout* mt1 = calloc(1, sizeof(multi_timeout));
|
||||||
multi_timeout* mt2 = malloc(sizeof(multi_timeout));
|
multi_timeout* mt2 = calloc(1, sizeof(multi_timeout));
|
||||||
multi_timeout_handler* mth = malloc(sizeof(multi_timeout_handler));
|
multi_timeout_handler* mth = calloc(1, sizeof(multi_timeout_handler));
|
||||||
timeout* real_timeout = malloc(sizeof(timeout));
|
timeout* real_timeout = calloc(1, sizeof(timeout));
|
||||||
|
|
||||||
mth->timeout_list = 0;
|
mth->timeout_list = 0;
|
||||||
mth->timeout_list = g_slist_prepend(mth->timeout_list, t1);
|
mth->timeout_list = g_slist_prepend(mth->timeout_list, t1);
|
||||||
@@ -329,7 +345,7 @@ void append_multi_timeout(timeout* t1, timeout* t2)
|
|||||||
t1 = tmp;
|
t1 = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
multi_timeout* mt = malloc(sizeof(multi_timeout));
|
multi_timeout* mt = calloc(1, sizeof(multi_timeout));
|
||||||
multi_timeout_handler* mth = g_hash_table_lookup(multi_timeouts, t1);
|
multi_timeout_handler* mth = g_hash_table_lookup(multi_timeouts, t1);
|
||||||
|
|
||||||
mth->timeout_list = g_slist_prepend(mth->timeout_list, t2);
|
mth->timeout_list = g_slist_prepend(mth->timeout_list, t2);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
extern GSList* timeout_list;
|
|
||||||
extern struct timeval next_timeout;
|
extern struct timeval next_timeout;
|
||||||
|
|
||||||
|
|
||||||
@@ -30,26 +29,33 @@ typedef struct _timeout timeout;
|
|||||||
|
|
||||||
// timer functions
|
// timer functions
|
||||||
/**
|
/**
|
||||||
* Single shot timer (i.e. timer with interval_msec == 0) are deleted automatically as soon as they expire
|
* Single shot timers (i.e. timers with interval_msec == 0) are deleted automatically as soon as they expire,
|
||||||
* i.e. you do not need to stop them, however it is safe to call stop_timeout for these timers.
|
* i.e. you do not need to stop them, however it is safe to call stop_timeout for these timers.
|
||||||
|
* You can pass the address of the variable storing the pointer to the timer as 'self' in add_timeout, in which
|
||||||
|
* case it is used to clear the pointer if the timer is destroyed automatically. This enforces the timeout pointers
|
||||||
|
* to be either valid or NULL.
|
||||||
* Periodic timeouts are aligned to each other whenever possible, i.e. one interval_msec is an
|
* Periodic timeouts are aligned to each other whenever possible, i.e. one interval_msec is an
|
||||||
* integral multiple of the other.
|
* integral multiple of the other.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
/** default global data **/
|
/** Initializes default global data. **/
|
||||||
void default_timeout();
|
void default_timeout();
|
||||||
|
|
||||||
/** freed memory : stops all timeouts **/
|
/** Cleans up: stops all timers and frees memory. **/
|
||||||
void cleanup_timeout();
|
void cleanup_timeout();
|
||||||
|
|
||||||
/** installs a timeout with the first timeout of 'value_msec' and then a periodic timeout with
|
/** Installs a timer with the first timeout after 'value_msec' and then an optional periodic timeout every
|
||||||
* 'interval_msec'. '_callback' is the callback function when the timer reaches the timeout.
|
* 'interval_msec' (set it to 0 to prevent periodic timeouts).
|
||||||
* returns a pointer to the timeout, which is needed for stopping it again
|
* '_callback' is the function called when the timer reaches the timeout.
|
||||||
|
* 'arg' is the argument passed to the callback function.
|
||||||
|
* 'self' is an optional pointer to a timeout* variable. If non-NULL, the variable is set to NULL when the timer
|
||||||
|
* is destroyed (with stop_timeout, cleanup_timeout or when the timer expires and it is single-shot).
|
||||||
|
* Returns a pointer to the timer, which is needed for stopping/changing it.
|
||||||
**/
|
**/
|
||||||
timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg);
|
timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg, timeout **self);
|
||||||
|
|
||||||
/** changes timeout 't'. If timeout 't' does not exist, nothing happens **/
|
/** Changes timer 't'. If it does not exist, a new timer is created, with self set to 't'. **/
|
||||||
void change_timeout(timeout* t, int value_msec, int interval_msec, void (*_callback)(void*), void* arg);
|
void change_timeout(timeout** t, int value_msec, int interval_msec, void (*_callback)(void*), void* arg);
|
||||||
|
|
||||||
/** stops the timeout 't' **/
|
/** stops the timeout 't' **/
|
||||||
void stop_timeout(timeout* t);
|
void stop_timeout(timeout* t);
|
||||||
|
|||||||
@@ -144,6 +144,16 @@ int window_get_monitor (Window win)
|
|||||||
else return i;
|
else return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void window_get_coordinates (Window win, int *x, int *y, int *w, int *h)
|
||||||
|
{
|
||||||
|
int dummy_int;
|
||||||
|
unsigned ww, wh, bw, bh;
|
||||||
|
Window src;
|
||||||
|
XTranslateCoordinates(server.dsp, win, server.root_win, 0, 0, x, y, &src);
|
||||||
|
XGetGeometry(server.dsp, win, &src, &dummy_int, &dummy_int, &ww, &wh, &bw, &bh);
|
||||||
|
*w = ww + bw;
|
||||||
|
*h = wh + bh;
|
||||||
|
}
|
||||||
|
|
||||||
int window_is_iconified (Window win)
|
int window_is_iconified (Window win)
|
||||||
{
|
{
|
||||||
@@ -197,11 +207,6 @@ int window_is_skip_taskbar (Window win)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int server_get_number_of_desktop ()
|
|
||||||
{
|
|
||||||
return get_property32(server.root_win, server.atom._NET_NUMBER_OF_DESKTOPS, XA_CARDINAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GSList *server_get_name_of_desktop ()
|
GSList *server_get_name_of_desktop ()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ void set_active (Window win);
|
|||||||
void set_desktop (int desktop);
|
void set_desktop (int desktop);
|
||||||
void set_close (Window win);
|
void set_close (Window win);
|
||||||
int server_get_current_desktop ();
|
int server_get_current_desktop ();
|
||||||
int server_get_number_of_desktop ();
|
|
||||||
GSList *server_get_name_of_desktop ();
|
GSList *server_get_name_of_desktop ();
|
||||||
|
void window_get_coordinates (Window win, int *x, int *y, int *w, int *h);
|
||||||
int window_is_iconified (Window win);
|
int window_is_iconified (Window win);
|
||||||
int window_is_urgent (Window win);
|
int window_is_urgent (Window win);
|
||||||
int window_is_hidden (Window win);
|
int window_is_hidden (Window win);
|
||||||
|
|||||||
Reference in New Issue
Block a user