Compare commits
46 Commits
area-align
...
translatio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd043dd14e | ||
|
|
f28983e5a7 | ||
|
|
b35cdb70df | ||
|
|
80361a121e | ||
|
|
b4ff007e42 | ||
|
|
ae379d865c | ||
|
|
0a3876dc8c | ||
|
|
e2d95acfa1 | ||
|
|
5ac1a6a653 | ||
|
|
481c409617 | ||
|
|
e8869b4d87 | ||
|
|
b1b95e086d | ||
|
|
df1f2d4e4b | ||
|
|
18b0ef2d1b | ||
|
|
860c100a04 | ||
|
|
9040764cf1 | ||
|
|
d8d4bc76cd | ||
|
|
fbcfa54061 | ||
|
|
b235f77f39 | ||
|
|
1b4b0a8d8d | ||
|
|
7ea0dc241c | ||
|
|
39e67df44d | ||
|
|
cb17e5a662 | ||
|
|
ea67f24051 | ||
| 7e2e1d5adf | |||
|
|
c49d231875 | ||
| d839d80c2e | |||
|
|
cc826cbcb5 | ||
|
|
f59702054d | ||
|
|
06dfcf70be | ||
|
|
44785a49da | ||
|
|
e20448d6b5 | ||
|
|
6014b51850 | ||
|
|
5acda6a0c0 | ||
|
|
f4f028a773 | ||
|
|
66c98bc820 | ||
|
|
de1d255088 | ||
|
|
b381ad2905 | ||
|
|
a4894b8257 | ||
|
|
b7dbb919a9 | ||
|
|
a08491c122 | ||
|
|
8795f50bb8 | ||
|
|
3ab42f9b72 | ||
|
|
7bce19452e | ||
|
|
1ff028e99f | ||
|
|
5450dcca0b |
1
AUTHORS
1
AUTHORS
@@ -5,6 +5,7 @@ tint2 is developped by :
|
|||||||
- 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
|
- Ovidiu M <mrovi9000 at gmail.com> : launcher, bug fixes
|
||||||
|
- Mishael A Sibiryakov (death@junki.org) : freespace
|
||||||
|
|
||||||
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>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ include_directories( ${PROJECT_BINARY_DIR}
|
|||||||
src/launcher
|
src/launcher
|
||||||
src/tooltip
|
src/tooltip
|
||||||
src/util
|
src/util
|
||||||
|
src/freespace
|
||||||
${X11_INCLUDE_DIRS}
|
${X11_INCLUDE_DIRS}
|
||||||
${PANGOCAIRO_INCLUDE_DIRS}
|
${PANGOCAIRO_INCLUDE_DIRS}
|
||||||
${PANGO_INCLUDE_DIRS}
|
${PANGO_INCLUDE_DIRS}
|
||||||
@@ -67,6 +68,7 @@ set( SOURCES src/config.c
|
|||||||
src/taskbar/taskbar.c
|
src/taskbar/taskbar.c
|
||||||
src/taskbar/taskbarname.c
|
src/taskbar/taskbarname.c
|
||||||
src/tooltip/tooltip.c
|
src/tooltip/tooltip.c
|
||||||
|
src/freespace/freespace.c
|
||||||
src/util/area.c
|
src/util/area.c
|
||||||
src/util/common.c
|
src/util/common.c
|
||||||
src/util/strnatcmp.c
|
src/util/strnatcmp.c
|
||||||
|
|||||||
36
ChangeLog
36
ChangeLog
@@ -1,4 +1,4 @@
|
|||||||
2015-05-03 master
|
2015-05-23 master
|
||||||
- Note: the changes listed here are based on the previous release tint2 0.11, however some distributions (e.g. Debian)
|
- 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
|
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)'.
|
already present. They are marked with '(already released by distros)'.
|
||||||
@@ -11,6 +11,10 @@
|
|||||||
- Experimental, testing/feedback needed
|
- Experimental, testing/feedback needed
|
||||||
- Icons (system tray, task buttons, launcher):
|
- Icons (system tray, task buttons, launcher):
|
||||||
- Changed rendering method to fix icon corruptions (please report any problems)
|
- Changed rendering method to fix icon corruptions (please report any problems)
|
||||||
|
- System tray:
|
||||||
|
- Icon rendering is faster
|
||||||
|
- Several kinds of graphical corruptions have been fixed
|
||||||
|
- Added workaround for misbehaving applications leaving empty tray icons
|
||||||
- Many bugfixes
|
- Many bugfixes
|
||||||
- New config options (see https://gitlab.com/o9000/tint2/wikis/Configure):
|
- New config options (see https://gitlab.com/o9000/tint2/wikis/Configure):
|
||||||
- Panel:
|
- Panel:
|
||||||
@@ -23,6 +27,7 @@
|
|||||||
- taskbar_hide_inactive_tasks
|
- taskbar_hide_inactive_tasks
|
||||||
- taskbar_sort_order
|
- taskbar_sort_order
|
||||||
- taskbar_name (already released by distros)
|
- taskbar_name (already released by distros)
|
||||||
|
- task_align (already released by distros)
|
||||||
- Launcher:
|
- Launcher:
|
||||||
- launcher* (already released by distros)
|
- launcher* (already released by distros)
|
||||||
- launcher_apps_dir (previously patched in by some distros)
|
- launcher_apps_dir (previously patched in by some distros)
|
||||||
@@ -30,6 +35,7 @@
|
|||||||
- launcher_icon_theme_override
|
- launcher_icon_theme_override
|
||||||
- System tray:
|
- System tray:
|
||||||
- systray_monitor
|
- systray_monitor
|
||||||
|
- Freespace (already released by distros)
|
||||||
- Config options with changed behavior:
|
- Config options with changed behavior:
|
||||||
- Panel:
|
- Panel:
|
||||||
- panel_dock: previously, 'panel_dock = 1' was actually not placing the panel into the dock. This option now
|
- panel_dock: previously, 'panel_dock = 1' was actually not placing the panel into the dock. This option now
|
||||||
@@ -44,8 +50,36 @@
|
|||||||
Reason for change: legibility improved for transparent panels.
|
Reason for change: legibility improved for transparent panels.
|
||||||
- Launcher:
|
- Launcher:
|
||||||
- launcher_item_app: now it expands leading ~ to the path to the user's home directory.
|
- launcher_item_app: now it expands leading ~ to the path to the user's home directory.
|
||||||
|
- Known issues:
|
||||||
|
- tint2 might close unexpectedly and/or cause X to freeze on certain ATI graphics cards.
|
||||||
|
Workaround: set 'disable_transparency = 1' in the config.
|
||||||
|
Reference: https://gitlab.com/o9000/tint2/issues/497
|
||||||
- Project hosting:
|
- Project hosting:
|
||||||
- Migrated from https://code.google.com/p/tint2 to https://gitlab.com/o9000/tint2 and switched from svn to git
|
- Migrated from https://code.google.com/p/tint2 to https://gitlab.com/o9000/tint2 and switched from svn to git
|
||||||
|
- Bugfixes:
|
||||||
|
- task switching from tint2 using the mouse wheel (mouse_scroll_up = prev_task and mouse_scroll_down = next_task) with
|
||||||
|
multiple desktops and taskbar_mode = multi_desktop when hovering over the first/last window in the taskbar was broken;
|
||||||
|
also when a window is set to appear on all desktops;
|
||||||
|
- the launcher was not loading an icon if the icon theme was not providing it in a size close to the value of launcher_icon_size;
|
||||||
|
- the launcher was not loading an icon if the extension was incorrect (e.g. file contents were PNG but the file name
|
||||||
|
had extension SVG);
|
||||||
|
- some launcher icons (PNG files saved with an indexed colormap and alpha mask) were sometimes rendered with white instead of
|
||||||
|
transparency;
|
||||||
|
- icons looked washed out when the panel was very transparent;
|
||||||
|
- the panel border was rendered in the background of every systray icon; sometimes systray icons were rendered in the
|
||||||
|
background of other icons;
|
||||||
|
- a crash caused by a change that prevents Google Chrome (and possibly other misbehaving applications) from leaving a large
|
||||||
|
number of empty icons in the system tray;
|
||||||
|
- the panel window had a shadow;
|
||||||
|
- some ATI drivers return an extra monitor with size zero which should be ignored when using panel_monitor = all;
|
||||||
|
- the battery applet was sometimes working incorrectly with certain laptop models (the battery applet stopped updating after
|
||||||
|
suspend with the battery unplugged);
|
||||||
|
- crashed caused by incomplete or malformed config files;
|
||||||
|
- with the fvwm window manager, the window title was sometimes not displayed correctly if it changed right after an
|
||||||
|
application was started;
|
||||||
|
- seconds were not updating in the clock;
|
||||||
|
- tint2 hang triggered when an application started from the launcher was closed and startup notifications were enabled;
|
||||||
|
- the code that loads SVG icons was using a lot of memory.
|
||||||
|
|
||||||
2010-06-26
|
2010-06-26
|
||||||
- unhide tint2 panel when dragging something
|
- unhide tint2 panel when dragging something
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -1,14 +1,14 @@
|
|||||||
### New unstable release: 0.12-rc3
|
### New unstable release: 0.12-rc5
|
||||||
Changes: https://gitlab.com/o9000/tint2/blob/master/ChangeLog
|
Changes: https://gitlab.com/o9000/tint2/blob/master/ChangeLog
|
||||||
|
|
||||||
Documentation: https://gitlab.com/o9000/tint2/wikis/home
|
Documentation: https://gitlab.com/o9000/tint2/wikis/home
|
||||||
|
|
||||||
Try it out with (see also [dependencies](https://gitlab.com/o9000/tint2/wikis/Install#dependencies)):
|
Try it out with (see also [dependencies](https://gitlab.com/o9000/tint2/wikis/Install#dependencies)):
|
||||||
```
|
```
|
||||||
mkdir tint2-0.12-rc3
|
mkdir tint2-0.12-rc5
|
||||||
cd tint2-0.12-rc3
|
cd tint2-0.12-rc5
|
||||||
wget 'https://gitlab.com/o9000/tint2/repository/archive.tar.gz?ref=v0.12-rc3' --output-document tint2-0.12-rc3.tar.gz
|
wget 'https://gitlab.com/o9000/tint2/repository/archive.tar.gz?ref=v0.12-rc5' --output-document tint2-0.12-rc5.tar.gz
|
||||||
tar -xzf tint2-0.12-rc3.tar.gz
|
tar -xzf tint2-0.12-rc5.tar.gz
|
||||||
cd tint2.git
|
cd tint2.git
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ void update_battery_tick(void* arg)
|
|||||||
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;
|
||||||
|
|
||||||
|
if (!battery_found) {
|
||||||
|
init_battery();
|
||||||
|
}
|
||||||
if (update_battery() != 0) {
|
if (update_battery() != 0) {
|
||||||
// Reconfigure
|
// Reconfigure
|
||||||
init_battery();
|
init_battery();
|
||||||
@@ -103,16 +106,24 @@ void update_battery_tick(void* arg)
|
|||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < nb_panel; i++) {
|
for (i = 0; i < nb_panel; i++) {
|
||||||
if (!battery_found && panel1[i].battery.area.on_screen == 1) {
|
if (!battery_found) {
|
||||||
|
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) {
|
}
|
||||||
|
} else {
|
||||||
|
if (battery_state.percentage >= percentage_hide) {
|
||||||
|
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 == 0) {
|
}
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
@@ -279,7 +290,7 @@ void init_battery()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!battery_timeout)
|
if (!battery_timeout)
|
||||||
battery_timeout = add_timeout(10, 10000, update_battery_tick, 0, &battery_timeout);
|
battery_timeout = add_timeout(10, 30000, update_battery_tick, 0, &battery_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -474,7 +485,7 @@ int update_battery() {
|
|||||||
battery_state.time.seconds = seconds;
|
battery_state.time.seconds = seconds;
|
||||||
|
|
||||||
if (energy_full > 0)
|
if (energy_full > 0)
|
||||||
new_percentage = ((energy_now <= energy_full ? energy_now : energy_full) * 100) / energy_full;
|
new_percentage = 0.5 + ((energy_now <= energy_full ? energy_now : energy_full) * 100.0) / energy_full;
|
||||||
|
|
||||||
battery_state.percentage = new_percentage;
|
battery_state.percentage = new_percentage;
|
||||||
|
|
||||||
|
|||||||
53
src/config.c
53
src/config.c
@@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "strnatcmp.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "taskbar.h"
|
#include "taskbar.h"
|
||||||
@@ -153,23 +154,48 @@ int config_get_monitor(char* monitor)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint compare_strings(gconstpointer a, gconstpointer b)
|
||||||
|
{
|
||||||
|
return strnatcasecmp((const char*)a, (const char*)b);
|
||||||
|
}
|
||||||
|
|
||||||
void load_launcher_app_dir(const char *path)
|
void load_launcher_app_dir(const char *path)
|
||||||
{
|
{
|
||||||
|
GList *subdirs = NULL;
|
||||||
|
GList *files = NULL;
|
||||||
|
|
||||||
GDir *d = g_dir_open(path, 0, NULL);
|
GDir *d = g_dir_open(path, 0, NULL);
|
||||||
if (d) {
|
if (d) {
|
||||||
const gchar *name;
|
const gchar *name;
|
||||||
while ((name = g_dir_read_name(d))) {
|
while ((name = g_dir_read_name(d))) {
|
||||||
gchar *file = g_build_filename(path, name, NULL);
|
gchar *file = g_build_filename(path, name, NULL);
|
||||||
if (!g_file_test(file, G_FILE_TEST_IS_DIR) &&
|
if (!g_file_test(file, G_FILE_TEST_IS_DIR) && g_str_has_suffix(file, ".desktop")) {
|
||||||
g_str_has_suffix(file, ".desktop")) {
|
files = g_list_append(files, file);
|
||||||
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)) {
|
} else if (g_file_test(file, G_FILE_TEST_IS_DIR)) {
|
||||||
load_launcher_app_dir(file);
|
subdirs = g_list_append(subdirs, file);
|
||||||
}
|
} else {
|
||||||
g_free(file);
|
g_free(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_dir_close(d);
|
g_dir_close(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subdirs = g_list_sort(subdirs, compare_strings);
|
||||||
|
GList *l;
|
||||||
|
for (l = subdirs; l; l = g_list_next(l)) {
|
||||||
|
gchar *dir = (gchar *)l->data;
|
||||||
|
load_launcher_app_dir(dir);
|
||||||
|
g_free(dir);
|
||||||
|
}
|
||||||
|
g_list_free(subdirs);
|
||||||
|
|
||||||
|
files = g_list_sort(files, compare_strings);
|
||||||
|
for (l = files; l; l = g_list_next(l)) {
|
||||||
|
gchar *file = (gchar *)l->data;
|
||||||
|
panel_config.launcher.list_apps = g_slist_append(panel_config.launcher.list_apps, strdup(file));
|
||||||
|
g_free(file);
|
||||||
|
}
|
||||||
|
g_list_free(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_entry (char *key, char *value)
|
void add_entry (char *key, char *value)
|
||||||
@@ -518,6 +544,15 @@ void add_entry (char *key, char *value)
|
|||||||
taskbar_sort_method = TASKBAR_NOSORT;
|
taskbar_sort_method = TASKBAR_NOSORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp (key, "task_align") == 0) {
|
||||||
|
if (strcmp(value, "center") == 0) {
|
||||||
|
taskbar_alignment = ALIGN_CENTER;
|
||||||
|
} else if (strcmp(value, "right") == 0) {
|
||||||
|
taskbar_alignment = ALIGN_RIGHT;
|
||||||
|
} else {
|
||||||
|
taskbar_alignment = ALIGN_LEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Task */
|
/* Task */
|
||||||
else if (strcmp (key, "task_text") == 0)
|
else if (strcmp (key, "task_text") == 0)
|
||||||
@@ -613,13 +648,13 @@ void add_entry (char *key, char *value)
|
|||||||
}
|
}
|
||||||
else if (strcmp(key, "systray_sort") == 0) {
|
else if (strcmp(key, "systray_sort") == 0) {
|
||||||
if (strcmp(value, "descending") == 0)
|
if (strcmp(value, "descending") == 0)
|
||||||
systray.sort = -1;
|
systray.sort = SYSTRAY_SORT_DESCENDING;
|
||||||
else if (strcmp(value, "ascending") == 0)
|
else if (strcmp(value, "ascending") == 0)
|
||||||
systray.sort = 1;
|
systray.sort = SYSTRAY_SORT_ASCENDING;
|
||||||
else if (strcmp(value, "left2right") == 0)
|
else if (strcmp(value, "left2right") == 0)
|
||||||
systray.sort = 2;
|
systray.sort = SYSTRAY_SORT_LEFT2RIGHT;
|
||||||
else if (strcmp(value, "right2left") == 0)
|
else if (strcmp(value, "right2left") == 0)
|
||||||
systray.sort = 3;
|
systray.sort = SYSTRAY_SORT_RIGHT2LEFT;
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "systray_icon_size") == 0) {
|
else if (strcmp(key, "systray_icon_size") == 0) {
|
||||||
systray_max_icon_size = atoi(value);
|
systray_max_icon_size = atoi(value);
|
||||||
|
|||||||
93
src/freespace/freespace.c
Normal file
93
src/freespace/freespace.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Tint2 : freespace
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Mishael A Sibiryakov (death@junki.org)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
#include <cairo-xlib.h>
|
||||||
|
#include <pango/pangocairo.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "panel.h"
|
||||||
|
#include "freespace.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void init_freespace_panel(void *p)
|
||||||
|
{
|
||||||
|
Panel *panel = (Panel*)p;
|
||||||
|
FreeSpace *freespace = &panel->freespace;
|
||||||
|
|
||||||
|
if (freespace->area.bg == 0)
|
||||||
|
freespace->area.bg = &g_array_index(backgrounds, Background, 0);
|
||||||
|
freespace->area.parent = p;
|
||||||
|
freespace->area.panel = p;
|
||||||
|
freespace->area.size_mode = SIZE_BY_CONTENT;
|
||||||
|
freespace->area.resize = 1;
|
||||||
|
freespace->area.on_screen = 1;
|
||||||
|
freespace->area._resize = resize_freespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freespace_get_max_size(Panel *p) {
|
||||||
|
// Get space used by every element except the freespace
|
||||||
|
GList *walk;
|
||||||
|
int size = 0;
|
||||||
|
for (walk = p->area.list; walk; walk = g_list_next(walk)) {
|
||||||
|
Area *a = (Area *)walk->data;
|
||||||
|
|
||||||
|
if (a->_resize == resize_freespace || !a->on_screen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (panel_horizontal)
|
||||||
|
size += a->width + (a->bg->border.width * 2) + p->area.paddingx;
|
||||||
|
else
|
||||||
|
size += a->height + (a->bg->border.width * 2) + p->area.paddingy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panel_horizontal)
|
||||||
|
size = p->area.width - size - (p->area.bg->border.width * 2) - p->area.paddingxlr;
|
||||||
|
else
|
||||||
|
size = p->area.height - size - (p->area.bg->border.width * 2) - p->area.paddingxlr;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resize_freespace(void *obj) {
|
||||||
|
FreeSpace *freespace = (FreeSpace*)obj;
|
||||||
|
Panel *panel = (Panel*)freespace->area.panel;
|
||||||
|
if (!freespace->area.on_screen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int old_size = panel_horizontal ? freespace->area.width : freespace->area.height;
|
||||||
|
int size = freespace_get_max_size(panel);
|
||||||
|
if (old_size == size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (panel_horizontal) {
|
||||||
|
freespace->area.width = size;
|
||||||
|
} else {
|
||||||
|
freespace->area.height = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
freespace->area.redraw = 1;
|
||||||
|
panel_refresh = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
20
src/freespace/freespace.h
Normal file
20
src/freespace/freespace.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* Copyright (C) 2011 Mishael A Sibiryakov (death@junki.org)
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef FREESPACE_H
|
||||||
|
#define FREESPACE_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "area.h"
|
||||||
|
|
||||||
|
typedef struct FreeSpace {
|
||||||
|
Area area;
|
||||||
|
} FreeSpace;
|
||||||
|
|
||||||
|
void cleanup_freespace();
|
||||||
|
void init_freespace_panel(void *panel);
|
||||||
|
|
||||||
|
int resize_freespace(void *obj);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -536,6 +536,9 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
char *next_larger = NULL;
|
char *next_larger = NULL;
|
||||||
GSList *next_larger_theme = NULL;
|
GSList *next_larger_theme = NULL;
|
||||||
|
|
||||||
|
int file_name_size = 4096;
|
||||||
|
char *file_name = calloc(file_name_size, 1);
|
||||||
|
|
||||||
for (theme = themes; theme; theme = g_slist_next(theme)) {
|
for (theme = themes; theme; theme = g_slist_next(theme)) {
|
||||||
((IconTheme*)theme->data)->list_directories = g_slist_sort_with_data(((IconTheme*)theme->data)->list_directories,
|
((IconTheme*)theme->data)->list_directories = g_slist_sort_with_data(((IconTheme*)theme->data)->list_directories,
|
||||||
compare_theme_directories,
|
compare_theme_directories,
|
||||||
@@ -560,8 +563,13 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
char *theme_name = ((IconTheme*)theme->data)->name;
|
char *theme_name = ((IconTheme*)theme->data)->name;
|
||||||
char *dir_name = ((IconThemeDir*)dir->data)->name;
|
char *dir_name = ((IconThemeDir*)dir->data)->name;
|
||||||
char *extension = (char*) ext->data;
|
char *extension = (char*) ext->data;
|
||||||
char *file_name = calloc(strlen(base_name) + strlen(theme_name) +
|
if (strlen(base_name) + strlen(theme_name) +
|
||||||
strlen(dir_name) + strlen(icon_name) + strlen(extension) + 100, 1);
|
strlen(dir_name) + strlen(icon_name) + strlen(extension) + 100 > file_name_size) {
|
||||||
|
file_name_size = strlen(base_name) + strlen(theme_name) +
|
||||||
|
strlen(dir_name) + strlen(icon_name) + strlen(extension) + 100;
|
||||||
|
file_name = realloc(file_name, file_name_size);
|
||||||
|
}
|
||||||
|
file_name[0] = 0;
|
||||||
// filename = directory/$(themename)/subdirectory/iconname.extension
|
// filename = directory/$(themename)/subdirectory/iconname.extension
|
||||||
sprintf(file_name, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
sprintf(file_name, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension);
|
||||||
if (DEBUG_ICON_SEARCH)
|
if (DEBUG_ICON_SEARCH)
|
||||||
@@ -596,11 +604,12 @@ char *get_icon_path_helper(GSList *themes, const char *icon_name, int size)
|
|||||||
printf("next_larger = %s; next_larger_size = %d\n", next_larger, next_larger_size);
|
printf("next_larger = %s; next_larger_size = %d\n", next_larger, next_larger_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
free(file_name);
|
free(file_name);
|
||||||
}
|
file_name = NULL;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (next_larger) {
|
if (next_larger) {
|
||||||
g_slist_free(extensions);
|
g_slist_free(extensions);
|
||||||
free(best_file_name);
|
free(best_file_name);
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib/gstdio.h>
|
#include <glib/gstdio.h>
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#ifdef HAVE_RSVG
|
#ifdef HAVE_RSVG
|
||||||
#include <librsvg/rsvg.h>
|
#include <librsvg/rsvg.h>
|
||||||
@@ -150,8 +152,7 @@ void cleanup_launcher_theme(Launcher *launcher)
|
|||||||
for (l = launcher->list_icons; l ; l = l->next) {
|
for (l = launcher->list_icons; l ; l = l->next) {
|
||||||
LauncherIcon *launcherIcon = (LauncherIcon*)l->data;
|
LauncherIcon *launcherIcon = (LauncherIcon*)l->data;
|
||||||
if (launcherIcon) {
|
if (launcherIcon) {
|
||||||
free_icon(launcherIcon->icon_scaled);
|
free_icon(launcherIcon->image);
|
||||||
free_icon(launcherIcon->icon_original);
|
|
||||||
free(launcherIcon->icon_name);
|
free(launcherIcon->icon_name);
|
||||||
free(launcherIcon->icon_path);
|
free(launcherIcon->icon_path);
|
||||||
free(launcherIcon->cmd);
|
free(launcherIcon->cmd);
|
||||||
@@ -186,7 +187,7 @@ int resize_launcher(void *obj)
|
|||||||
// Resize icons if necessary
|
// Resize icons if necessary
|
||||||
for (l = launcher->list_icons; l ; l = l->next) {
|
for (l = launcher->list_icons; l ; l = l->next) {
|
||||||
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
||||||
if (launcherIcon->icon_size != icon_size || !launcherIcon->icon_original) {
|
if (launcherIcon->icon_size != icon_size || !launcherIcon->image) {
|
||||||
launcherIcon->icon_size = icon_size;
|
launcherIcon->icon_size = icon_size;
|
||||||
launcherIcon->area.width = launcherIcon->icon_size;
|
launcherIcon->area.width = launcherIcon->icon_size;
|
||||||
launcherIcon->area.height = launcherIcon->icon_size;
|
launcherIcon->area.height = launcherIcon->icon_size;
|
||||||
@@ -195,72 +196,72 @@ int resize_launcher(void *obj)
|
|||||||
char *new_icon_path = get_icon_path(launcher->list_themes, launcherIcon->icon_name, launcherIcon->icon_size);
|
char *new_icon_path = get_icon_path(launcher->list_themes, launcherIcon->icon_name, launcherIcon->icon_size);
|
||||||
if (!new_icon_path) {
|
if (!new_icon_path) {
|
||||||
// Draw a blank icon
|
// Draw a blank icon
|
||||||
free_icon(launcherIcon->icon_original);
|
free_icon(launcherIcon->image);
|
||||||
launcherIcon->icon_original = NULL;
|
launcherIcon->image = NULL;
|
||||||
free_icon(launcherIcon->icon_scaled);
|
|
||||||
launcherIcon->icon_scaled = NULL;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (launcherIcon->icon_path && strcmp(new_icon_path, launcherIcon->icon_path) == 0) {
|
|
||||||
// If it's the same file just rescale
|
|
||||||
free_icon(launcherIcon->icon_scaled);
|
|
||||||
launcherIcon->icon_scaled = scale_icon(launcherIcon->icon_original, icon_size);
|
|
||||||
free(new_icon_path);
|
|
||||||
fprintf(stderr, "launcher.c %d: Using icon %s\n", __LINE__, launcherIcon->icon_path);
|
|
||||||
} else {
|
|
||||||
// Free the old files
|
// Free the old files
|
||||||
free_icon(launcherIcon->icon_original);
|
free_icon(launcherIcon->image);
|
||||||
free_icon(launcherIcon->icon_scaled);
|
launcherIcon->image = NULL;
|
||||||
launcherIcon->icon_original = launcherIcon->icon_scaled = NULL;
|
|
||||||
// Load the new file and scale
|
// Load the new file and scale
|
||||||
launcherIcon->icon_original = imlib_load_image_immediately(new_icon_path);
|
launcherIcon->image = imlib_load_image_immediately(new_icon_path);
|
||||||
#ifdef HAVE_RSVG
|
#ifdef HAVE_RSVG
|
||||||
if (!launcherIcon->icon_original && g_str_has_suffix(new_icon_path, ".svg")) {
|
if (!launcherIcon->image && g_str_has_suffix(new_icon_path, ".svg")) {
|
||||||
|
char suffix[128];
|
||||||
|
sprintf(suffix, "tmpicon-%d.png", getpid());
|
||||||
|
// We fork here because librsvg allocates memory like crazy
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
// Child
|
||||||
GError* err = NULL;
|
GError* err = NULL;
|
||||||
RsvgHandle* svg = rsvg_handle_new_from_file(new_icon_path, &err);
|
RsvgHandle* svg = rsvg_handle_new_from_file(new_icon_path, &err);
|
||||||
|
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
fprintf(stderr, "Could not load svg image!: %s", err->message);
|
fprintf(stderr, "Could not load svg image!: %s", err->message);
|
||||||
g_error_free(err);
|
g_error_free(err);
|
||||||
launcherIcon->icon_original = NULL;
|
launcherIcon->image = NULL;
|
||||||
} else {
|
} else {
|
||||||
char suffix[128];
|
|
||||||
sprintf(suffix, "tmpicon-%d.png", getpid());
|
|
||||||
gchar *name = g_build_filename(g_get_user_config_dir(), "tint2", suffix, NULL);
|
gchar *name = g_build_filename(g_get_user_config_dir(), "tint2", suffix, NULL);
|
||||||
GdkPixbuf *pixbuf = rsvg_handle_get_pixbuf(svg);
|
GdkPixbuf *pixbuf = rsvg_handle_get_pixbuf(svg);
|
||||||
gdk_pixbuf_save(pixbuf, name, "png", NULL, NULL);
|
gdk_pixbuf_save(pixbuf, name, "png", NULL, NULL);
|
||||||
launcherIcon->icon_original = imlib_load_image_immediately_without_cache(name);
|
}
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
// Parent
|
||||||
|
waitpid(pid, 0, 0);
|
||||||
|
gchar *name = g_build_filename(g_get_user_config_dir(), "tint2", suffix, NULL);
|
||||||
|
launcherIcon->image = imlib_load_image_immediately_without_cache(name);
|
||||||
g_remove(name);
|
g_remove(name);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
g_object_unref(G_OBJECT(pixbuf));
|
|
||||||
g_object_unref(G_OBJECT(svg));
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
launcherIcon->icon_original = imlib_load_image_immediately(new_icon_path);
|
launcherIcon->image = imlib_load_image_immediately(new_icon_path);
|
||||||
}
|
}
|
||||||
// On loading error, fallback to default
|
// On loading error, fallback to default
|
||||||
if (!launcherIcon->icon_original) {
|
if (!launcherIcon->image) {
|
||||||
free(new_icon_path);
|
free(new_icon_path);
|
||||||
new_icon_path = get_icon_path(launcher->list_themes, DEFAULT_ICON, launcherIcon->icon_size);
|
new_icon_path = get_icon_path(launcher->list_themes, DEFAULT_ICON, launcherIcon->icon_size);
|
||||||
if (new_icon_path)
|
if (new_icon_path)
|
||||||
launcherIcon->icon_original = imlib_load_image_immediately(new_icon_path);
|
launcherIcon->image = imlib_load_image_immediately(new_icon_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!launcherIcon->icon_original) {
|
if (!launcherIcon->image) {
|
||||||
// Loading default icon failed, draw a blank icon
|
// Loading default icon failed, draw a blank icon
|
||||||
free(new_icon_path);
|
free(new_icon_path);
|
||||||
} else {
|
} else {
|
||||||
// Loaded icon successfully
|
// Loaded icon successfully
|
||||||
launcherIcon->icon_scaled = scale_icon(launcherIcon->icon_original, launcherIcon->icon_size);
|
Imlib_Image original = launcherIcon->image;
|
||||||
|
launcherIcon->image = scale_icon(launcherIcon->image, launcherIcon->icon_size);
|
||||||
|
free_icon(original);
|
||||||
free(launcherIcon->icon_path);
|
free(launcherIcon->icon_path);
|
||||||
launcherIcon->icon_path = new_icon_path;
|
launcherIcon->icon_path = new_icon_path;
|
||||||
fprintf(stderr, "launcher.c %d: Using icon %s\n", __LINE__, launcherIcon->icon_path);
|
fprintf(stderr, "launcher.c %d: Using icon %s\n", __LINE__, launcherIcon->icon_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
count = g_slist_length(launcher->list_icons);
|
count = g_slist_length(launcher->list_icons);
|
||||||
|
|
||||||
@@ -331,6 +332,7 @@ int resize_launcher(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,9 +357,8 @@ void draw_launcher_icon(void *obj, cairo_t *c)
|
|||||||
{
|
{
|
||||||
LauncherIcon *launcherIcon = (LauncherIcon*)obj;
|
LauncherIcon *launcherIcon = (LauncherIcon*)obj;
|
||||||
|
|
||||||
Imlib_Image icon_scaled = launcherIcon->icon_scaled;
|
|
||||||
// Render
|
// Render
|
||||||
imlib_context_set_image(icon_scaled);
|
imlib_context_set_image(launcherIcon->image);
|
||||||
if (server.real_transparency) {
|
if (server.real_transparency) {
|
||||||
render_image(launcherIcon->area.pix, 0, 0);
|
render_image(launcherIcon->area.pix, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
@@ -403,7 +404,7 @@ void launcher_action(LauncherIcon *icon, XEvent* evt)
|
|||||||
char *cmd = calloc(strlen(icon->cmd) + 10, 1);
|
char *cmd = calloc(strlen(icon->cmd) + 10, 1);
|
||||||
sprintf(cmd, "(%s&)", icon->cmd);
|
sprintf(cmd, "(%s&)", icon->cmd);
|
||||||
#if HAVE_SN
|
#if HAVE_SN
|
||||||
SnLauncherContext* ctx;
|
SnLauncherContext* ctx = 0;
|
||||||
Time time;
|
Time time;
|
||||||
if (startup_notifications) {
|
if (startup_notifications) {
|
||||||
ctx = sn_launcher_context_new(server.sn_dsp, server.screen);
|
ctx = sn_launcher_context_new(server.sn_dsp, server.screen);
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ typedef struct Launcher {
|
|||||||
typedef struct LauncherIcon {
|
typedef struct LauncherIcon {
|
||||||
// always start with area
|
// always start with area
|
||||||
Area area;
|
Area area;
|
||||||
Imlib_Image icon_scaled;
|
Imlib_Image image;
|
||||||
Imlib_Image icon_original;
|
|
||||||
char *cmd;
|
char *cmd;
|
||||||
char *icon_name;
|
char *icon_name;
|
||||||
char *icon_path;
|
char *icon_path;
|
||||||
|
|||||||
33
src/panel.c
33
src/panel.c
@@ -204,6 +204,8 @@ void init_panel()
|
|||||||
}
|
}
|
||||||
if (panel_items_order[k] == 'C')
|
if (panel_items_order[k] == 'C')
|
||||||
init_clock_panel(p);
|
init_clock_panel(p);
|
||||||
|
if (panel_items_order[k] == 'F' && !strstr(panel_items_order, "T"))
|
||||||
|
init_freespace_panel(p);
|
||||||
}
|
}
|
||||||
set_panel_items_order(p);
|
set_panel_items_order(p);
|
||||||
|
|
||||||
@@ -322,13 +324,13 @@ void init_panel_size_and_position(Panel *panel)
|
|||||||
|
|
||||||
int resize_panel(void *obj)
|
int resize_panel(void *obj)
|
||||||
{
|
{
|
||||||
resize_by_layout(obj, 0);
|
Panel *panel = (Panel*)obj;
|
||||||
|
resize_by_layout(panel, 0);
|
||||||
|
|
||||||
//printf("resize_panel\n");
|
//printf("resize_panel\n");
|
||||||
if (panel_mode != MULTI_DESKTOP && taskbar_enabled) {
|
if (panel_mode != MULTI_DESKTOP && taskbar_enabled) {
|
||||||
// propagate width/height on hidden taskbar
|
// propagate width/height on hidden taskbar
|
||||||
int i, width, height;
|
int i, width, height;
|
||||||
Panel *panel = (Panel*)obj;
|
|
||||||
width = panel->taskbar[server.desktop].area.width;
|
width = panel->taskbar[server.desktop].area.width;
|
||||||
height = panel->taskbar[server.desktop].area.height;
|
height = panel->taskbar[server.desktop].area.height;
|
||||||
for (i=0 ; i < panel->nb_desktop ; i++) {
|
for (i=0 ; i < panel->nb_desktop ; i++) {
|
||||||
@@ -339,7 +341,6 @@ int resize_panel(void *obj)
|
|||||||
}
|
}
|
||||||
if (panel_mode == MULTI_DESKTOP && taskbar_enabled && taskbar_distribute_size) {
|
if (panel_mode == MULTI_DESKTOP && taskbar_enabled && taskbar_distribute_size) {
|
||||||
// Distribute the available space between taskbars
|
// Distribute the available space between taskbars
|
||||||
Panel *panel = (Panel*)obj;
|
|
||||||
|
|
||||||
// Compute the total available size, and the total size requested by the taskbars
|
// Compute the total available size, and the total size requested by the taskbars
|
||||||
int total_size = 0;
|
int total_size = 0;
|
||||||
@@ -354,7 +355,7 @@ int resize_panel(void *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Taskbar *taskbar = &panel->taskbar[i];
|
Taskbar *taskbar = &panel->taskbar[i];
|
||||||
GSList *l;
|
GList *l;
|
||||||
for (l = taskbar->area.list; l; l = l->next) {
|
for (l = taskbar->area.list; l; l = l->next) {
|
||||||
Area *child = l->data;
|
Area *child = l->data;
|
||||||
if (!child->on_screen)
|
if (!child->on_screen)
|
||||||
@@ -389,7 +390,7 @@ int resize_panel(void *obj)
|
|||||||
|
|
||||||
int requested_size = (2 * taskbar->area.bg->border.width) + (2 * taskbar->area.paddingxlr);
|
int requested_size = (2 * taskbar->area.bg->border.width) + (2 * taskbar->area.paddingxlr);
|
||||||
int items = 0;
|
int items = 0;
|
||||||
GSList *l = taskbar->area.list;
|
GList *l = taskbar->area.list;
|
||||||
if (taskbarname_enabled)
|
if (taskbarname_enabled)
|
||||||
l = l->next;
|
l = l->next;
|
||||||
for (; l; l = l->next) {
|
for (; l; l = l->next) {
|
||||||
@@ -418,6 +419,8 @@ int resize_panel(void *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (panel->freespace.area.on_screen)
|
||||||
|
resize_freespace(&panel->freespace);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,29 +485,31 @@ void set_panel_items_order(Panel *p)
|
|||||||
int k, j;
|
int k, j;
|
||||||
|
|
||||||
if (p->area.list) {
|
if (p->area.list) {
|
||||||
g_slist_free(p->area.list);
|
g_list_free(p->area.list);
|
||||||
p->area.list = 0;
|
p->area.list = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_list_append(p->area.list, &p->launcher);
|
||||||
p->launcher.area.resize = 1;
|
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_list_append(p->area.list, &p->taskbar[j]);
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_BATTERY
|
#ifdef ENABLE_BATTERY
|
||||||
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_list_append(p->area.list, &p->battery);
|
||||||
#endif
|
#endif
|
||||||
int i = p - panel1;
|
int i = p - panel1;
|
||||||
if (panel_items_order[k] == 'S' && systray_on_monitor(i, nb_panel)) {
|
if (panel_items_order[k] == 'S' && systray_on_monitor(i, nb_panel)) {
|
||||||
p->area.list = g_slist_append(p->area.list, &systray);
|
p->area.list = g_list_append(p->area.list, &systray);
|
||||||
}
|
}
|
||||||
if (panel_items_order[k] == 'C')
|
if (panel_items_order[k] == 'C')
|
||||||
p->area.list = g_slist_append(p->area.list, &p->clock);
|
p->area.list = g_list_append(p->area.list, &p->clock);
|
||||||
|
if (panel_items_order[k] == 'F')
|
||||||
|
p->area.list = g_list_append(p->area.list, &p->freespace);
|
||||||
}
|
}
|
||||||
init_rendering(&p->area, 0);
|
init_rendering(&p->area, 0);
|
||||||
}
|
}
|
||||||
@@ -629,7 +634,7 @@ void set_panel_background(Panel *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// redraw panel's object
|
// redraw panel's object
|
||||||
GSList *l0;
|
GList *l0;
|
||||||
Area *a;
|
Area *a;
|
||||||
for (l0 = p->area.list; l0 ; l0 = l0->next) {
|
for (l0 = p->area.list; l0 ; l0 = l0->next) {
|
||||||
a = l0->data;
|
a = l0->data;
|
||||||
@@ -695,7 +700,7 @@ Taskbar *click_taskbar (Panel *panel, int x, int y)
|
|||||||
|
|
||||||
Task *click_task (Panel *panel, int x, int y)
|
Task *click_task (Panel *panel, int x, int y)
|
||||||
{
|
{
|
||||||
GSList *l0;
|
GList *l0;
|
||||||
Taskbar *tskbar;
|
Taskbar *tskbar;
|
||||||
|
|
||||||
if ( (tskbar = click_taskbar(panel, x, y)) ) {
|
if ( (tskbar = click_taskbar(panel, x, y)) ) {
|
||||||
@@ -797,7 +802,7 @@ Area* click_area(Panel *panel, int x, int y)
|
|||||||
Area* new_result = result;
|
Area* new_result = result;
|
||||||
do {
|
do {
|
||||||
result = new_result;
|
result = new_result;
|
||||||
GSList* it = result->list;
|
GList* it = result->list;
|
||||||
while (it) {
|
while (it) {
|
||||||
Area* a = it->data;
|
Area* a = it->data;
|
||||||
if (a->on_screen && x >= a->posx && x <= (a->posx + a->width)
|
if (a->on_screen && x >= a->posx && x <= (a->posx + a->width)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "taskbar.h"
|
#include "taskbar.h"
|
||||||
#include "systraybar.h"
|
#include "systraybar.h"
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
|
#include "freespace.h"
|
||||||
|
|
||||||
#ifdef ENABLE_BATTERY
|
#ifdef ENABLE_BATTERY
|
||||||
#include "battery.h"
|
#include "battery.h"
|
||||||
@@ -116,6 +117,8 @@ typedef struct {
|
|||||||
|
|
||||||
Launcher launcher;
|
Launcher launcher;
|
||||||
|
|
||||||
|
FreeSpace freespace;
|
||||||
|
|
||||||
// autohide
|
// autohide
|
||||||
int is_hidden;
|
int is_hidden;
|
||||||
int hidden_width, hidden_height;
|
int hidden_width, hidden_height;
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ void server_init_atoms ()
|
|||||||
server.atom._NET_SYSTEM_TRAY_ORIENTATION = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_ORIENTATION", False);
|
server.atom._NET_SYSTEM_TRAY_ORIENTATION = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_ORIENTATION", False);
|
||||||
server.atom._XEMBED = XInternAtom(server.dsp, "_XEMBED", False);
|
server.atom._XEMBED = XInternAtom(server.dsp, "_XEMBED", False);
|
||||||
server.atom._XEMBED_INFO = XInternAtom(server.dsp, "_XEMBED_INFO", False);
|
server.atom._XEMBED_INFO = XInternAtom(server.dsp, "_XEMBED_INFO", False);
|
||||||
|
server.atom._NET_WM_PID = XInternAtom(server.dsp, "_NET_WM_PID", True);
|
||||||
|
|
||||||
// drag 'n' drop
|
// drag 'n' drop
|
||||||
server.atom.XdndAware = XInternAtom(server.dsp, "XdndAware", False);
|
server.atom.XdndAware = XInternAtom(server.dsp, "XdndAware", False);
|
||||||
|
|||||||
@@ -15,9 +15,8 @@
|
|||||||
|
|
||||||
#ifdef HAVE_SN
|
#ifdef HAVE_SN
|
||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
#include <glib.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
typedef struct Global_atom
|
typedef struct Global_atom
|
||||||
{
|
{
|
||||||
@@ -74,6 +73,7 @@ typedef struct Global_atom
|
|||||||
Atom _NET_SYSTEM_TRAY_ORIENTATION;
|
Atom _NET_SYSTEM_TRAY_ORIENTATION;
|
||||||
Atom _XEMBED;
|
Atom _XEMBED;
|
||||||
Atom _XEMBED_INFO;
|
Atom _XEMBED_INFO;
|
||||||
|
Atom _NET_WM_PID;
|
||||||
Atom _XSETTINGS_SCREEN;
|
Atom _XSETTINGS_SCREEN;
|
||||||
Atom _XSETTINGS_SETTINGS;
|
Atom _XSETTINGS_SETTINGS;
|
||||||
Atom XdndAware;
|
Atom XdndAware;
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ 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;
|
||||||
|
|
||||||
@@ -52,7 +50,8 @@ int refresh_systray;
|
|||||||
int systray_enabled;
|
int systray_enabled;
|
||||||
int systray_max_icon_size;
|
int systray_max_icon_size;
|
||||||
int systray_monitor;
|
int systray_monitor;
|
||||||
|
int chrono;
|
||||||
|
int systray_composited;
|
||||||
// background pixmap if we render ourselves the icons
|
// background pixmap if we render ourselves the icons
|
||||||
static Pixmap render_background;
|
static Pixmap render_background;
|
||||||
|
|
||||||
@@ -61,8 +60,9 @@ void default_systray()
|
|||||||
{
|
{
|
||||||
memset(&systray, 0, sizeof(Systraybar));
|
memset(&systray, 0, sizeof(Systraybar));
|
||||||
render_background = 0;
|
render_background = 0;
|
||||||
|
chrono = 0;
|
||||||
systray.alpha = 100;
|
systray.alpha = 100;
|
||||||
systray.sort = 3;
|
systray.sort = SYSTRAY_SORT_LEFT2RIGHT;
|
||||||
systray.area._draw_foreground = draw_systray;
|
systray.area._draw_foreground = draw_systray;
|
||||||
systray.area._on_change_layout = on_change_systray;
|
systray.area._on_change_layout = on_change_systray;
|
||||||
systray.area.size_mode = SIZE_BY_CONTENT;
|
systray.area.size_mode = SIZE_BY_CONTENT;
|
||||||
@@ -85,16 +85,19 @@ void cleanup_systray()
|
|||||||
|
|
||||||
void init_systray()
|
void init_systray()
|
||||||
{
|
{
|
||||||
start_net();
|
|
||||||
|
|
||||||
if (!systray_enabled)
|
if (!systray_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!server.visual32 && (systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0)) {
|
systray_composited = !server.disable_transparency && server.visual32 && server.colormap32;
|
||||||
printf("No 32 bit visual for your X implementation. 'systray_asb = 100 0 0' will be forced\n");
|
printf("Systray composited rendering %s\n", systray_composited ? "on" : "off");
|
||||||
|
|
||||||
|
if (!systray_composited) {
|
||||||
|
printf("systray_asb forced to 100 0 0\n");
|
||||||
systray.alpha = 100;
|
systray.alpha = 100;
|
||||||
systray.brightness = systray.saturation = 0;
|
systray.brightness = systray.saturation = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start_net();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -108,7 +111,8 @@ void init_systray_panel(void *p)
|
|||||||
GSList *l;
|
GSList *l;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
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)
|
||||||
|
continue;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@@ -121,8 +125,9 @@ void init_systray_panel(void *p)
|
|||||||
|
|
||||||
void draw_systray(void *obj, cairo_t *c)
|
void draw_systray(void *obj, cairo_t *c)
|
||||||
{
|
{
|
||||||
if (FORCE_COMPOSITED_RENDERING || server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
if (systray_composited) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -146,7 +151,8 @@ int resize_systray(void *obj)
|
|||||||
sysbar->icon_size = systray_max_icon_size;
|
sysbar->icon_size = systray_max_icon_size;
|
||||||
count = 0;
|
count = 0;
|
||||||
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)
|
||||||
|
continue;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
//printf("count %d\n", count);
|
//printf("count %d\n", count);
|
||||||
@@ -158,8 +164,7 @@ int resize_systray(void *obj)
|
|||||||
sysbar->marging = height - (sysbar->icons_per_column-1)*(sysbar->icon_size+sysbar->area.paddingx) - sysbar->icon_size;
|
sysbar->marging = height - (sysbar->icons_per_column-1)*(sysbar->icon_size+sysbar->area.paddingx) - sysbar->icon_size;
|
||||||
sysbar->icons_per_row = count / sysbar->icons_per_column + (count%sysbar->icons_per_column != 0);
|
sysbar->icons_per_row = count / sysbar->icons_per_column + (count%sysbar->icons_per_column != 0);
|
||||||
systray.area.width = (2 * systray.area.bg->border.width) + (2 * systray.area.paddingxlr) + (sysbar->icon_size * sysbar->icons_per_row) + ((sysbar->icons_per_row-1) * systray.area.paddingx);
|
systray.area.width = (2 * systray.area.bg->border.width) + (2 * systray.area.paddingxlr) + (sysbar->icon_size * sysbar->icons_per_row) + ((sysbar->icons_per_row-1) * systray.area.paddingx);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
int width = sysbar->area.width - 2*sysbar->area.bg->border.width - 2*sysbar->area.paddingy;
|
int width = sysbar->area.width - 2*sysbar->area.bg->border.width - 2*sysbar->area.paddingy;
|
||||||
// here icons_per_row always higher than 0
|
// here icons_per_row always higher than 0
|
||||||
sysbar->icons_per_row = (width+sysbar->area.paddingx) / (sysbar->icon_size+sysbar->area.paddingx);
|
sysbar->icons_per_row = (width+sysbar->area.paddingx) / (sysbar->icon_size+sysbar->area.paddingx);
|
||||||
@@ -184,8 +189,7 @@ void on_change_systray (void *obj)
|
|||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx = systray.area.posx + systray.area.bg->border.width + systray.area.paddingxlr;
|
posx = systray.area.posx + systray.area.bg->border.width + systray.area.paddingxlr;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
posx = start;
|
posx = start;
|
||||||
posy = systray.area.posy + systray.area.bg->border.width + systray.area.paddingxlr;
|
posy = systray.area.posy + systray.area.bg->border.width + systray.area.paddingxlr;
|
||||||
}
|
}
|
||||||
@@ -194,35 +198,38 @@ void on_change_systray (void *obj)
|
|||||||
GSList *l;
|
GSList *l;
|
||||||
for (i = 1, l = systray.list_icons; l ; i++, l = l->next) {
|
for (i = 1, l = systray.list_icons; l ; i++, l = l->next) {
|
||||||
traywin = (TrayWindow*)l->data;
|
traywin = (TrayWindow*)l->data;
|
||||||
if (traywin->hide) continue;
|
if (traywin->hide)
|
||||||
|
continue;
|
||||||
|
|
||||||
traywin->y = posy;
|
traywin->y = posy;
|
||||||
traywin->x = posx;
|
traywin->x = posx;
|
||||||
//printf("systray %d : %d,%d\n", i, posx, posy);
|
// printf("systray %d %d : pos %d, %d\n", traywin->parent, traywin->win, posx, posy);
|
||||||
traywin->width = sysbar->icon_size;
|
traywin->width = sysbar->icon_size;
|
||||||
traywin->height = sysbar->icon_size;
|
traywin->height = sysbar->icon_size;
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (i % sysbar->icons_per_column)
|
if (i % sysbar->icons_per_column) {
|
||||||
posy += sysbar->icon_size + sysbar->area.paddingx;
|
posy += sysbar->icon_size + sysbar->area.paddingx;
|
||||||
else {
|
} else {
|
||||||
posy = start;
|
posy = start;
|
||||||
posx += (sysbar->icon_size + systray.area.paddingx);
|
posx += (sysbar->icon_size + systray.area.paddingx);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
if (i % sysbar->icons_per_row) {
|
||||||
if (i % sysbar->icons_per_row)
|
|
||||||
posx += sysbar->icon_size + systray.area.paddingx;
|
posx += sysbar->icon_size + systray.area.paddingx;
|
||||||
else {
|
} else {
|
||||||
posx = start;
|
posx = start;
|
||||||
posy += (sysbar->icon_size + systray.area.paddingx);
|
posy += (sysbar->icon_size + systray.area.paddingx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// position and size the icon window
|
// position and size the icon window
|
||||||
XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, sysbar->icon_size, sysbar->icon_size);
|
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||||
XResizeWindow(server.dsp, traywin->tray_id, sysbar->icon_size, sysbar->icon_size);
|
if (traywin->reparented) {
|
||||||
|
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
refresh_systray = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ***********************************************
|
// ***********************************************
|
||||||
@@ -235,10 +242,10 @@ void start_net()
|
|||||||
if (!systray_enabled)
|
if (!systray_enabled)
|
||||||
stop_net();
|
stop_net();
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
if (!systray_enabled)
|
if (!systray_enabled)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Window win = XGetSelectionOwner(server.dsp, server.atom._NET_SYSTEM_TRAY_SCREEN);
|
Window win = XGetSelectionOwner(server.dsp, server.atom._NET_SYSTEM_TRAY_SCREEN);
|
||||||
|
|
||||||
@@ -273,7 +280,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 && (FORCE_COMPOSITED_RENDERING || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0))
|
if (systray_composited)
|
||||||
vid = XVisualIDFromVisual(server.visual32);
|
vid = XVisualIDFromVisual(server.visual32);
|
||||||
else
|
else
|
||||||
vid = XVisualIDFromVisual(server.visual);
|
vid = XVisualIDFromVisual(server.visual);
|
||||||
@@ -323,10 +330,9 @@ void stop_net()
|
|||||||
gboolean error;
|
gboolean error;
|
||||||
int window_error_handler(Display *d, XErrorEvent *e)
|
int window_error_handler(Display *d, XErrorEvent *e)
|
||||||
{
|
{
|
||||||
d=d;e=e;
|
|
||||||
error = TRUE;
|
error = TRUE;
|
||||||
if (e->error_code != BadWindow) {
|
if (e->error_code != BadWindow) {
|
||||||
printf("error_handler %d\n", e->error_code);
|
printf("systray: error code %d\n", e->error_code);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -336,70 +342,201 @@ static gint compare_traywindows(gconstpointer a, gconstpointer b)
|
|||||||
{
|
{
|
||||||
const TrayWindow * traywin_a = (TrayWindow*)a;
|
const TrayWindow * traywin_a = (TrayWindow*)a;
|
||||||
const TrayWindow * traywin_b = (TrayWindow*)b;
|
const TrayWindow * traywin_b = (TrayWindow*)b;
|
||||||
|
|
||||||
|
if (traywin_a->empty && !traywin_b->empty)
|
||||||
|
return 1 * (systray.sort == SYSTRAY_SORT_RIGHT2LEFT ? -1 : 1);
|
||||||
|
if (!traywin_a->empty && traywin_b->empty)
|
||||||
|
return -1 * (systray.sort == SYSTRAY_SORT_RIGHT2LEFT ? -1 : 1);
|
||||||
|
|
||||||
|
if (systray.sort == SYSTRAY_SORT_ASCENDING ||
|
||||||
|
systray.sort == SYSTRAY_SORT_DESCENDING) {
|
||||||
XTextProperty name_a, name_b;
|
XTextProperty name_a, name_b;
|
||||||
|
|
||||||
if(XGetWMName(server.dsp, traywin_a->tray_id, &name_a) == 0) {
|
if (XGetWMName(server.dsp, traywin_a->win, &name_a) == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
} else if (XGetWMName(server.dsp, traywin_b->win, &name_b) == 0) {
|
||||||
else if(XGetWMName(server.dsp, traywin_b->tray_id, &name_b) == 0) {
|
|
||||||
XFree(name_a.value);
|
XFree(name_a.value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else {
|
gint retval = g_ascii_strncasecmp((char*)name_a.value, (char*)name_b.value, -1) *
|
||||||
gint retval = g_ascii_strncasecmp((char*)name_a.value, (char*)name_b.value, -1) * systray.sort;
|
(systray.sort == SYSTRAY_SORT_ASCENDING ? 1 : -1);
|
||||||
XFree(name_a.value);
|
XFree(name_a.value);
|
||||||
XFree(name_b.value);
|
XFree(name_b.value);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (systray.sort == SYSTRAY_SORT_LEFT2RIGHT ||
|
||||||
|
systray.sort == SYSTRAY_SORT_RIGHT2LEFT) {
|
||||||
|
return (traywin_a->chrono - traywin_b->chrono) *
|
||||||
|
(systray.sort == SYSTRAY_SORT_LEFT2RIGHT ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean add_icon(Window id)
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean add_icon(Window win)
|
||||||
{
|
{
|
||||||
TrayWindow *traywin;
|
TrayWindow *traywin;
|
||||||
XErrorHandler old;
|
|
||||||
Panel *panel = systray.area.panel;
|
Panel *panel = systray.area.panel;
|
||||||
int hide = 0;
|
int hide = 0;
|
||||||
|
|
||||||
GSList *l;
|
// Get the process ID of the application that created the window
|
||||||
for (l = systray.list_icons; l; l = l->next) {
|
int pid = 0;
|
||||||
if (((TrayWindow*)l->data)->tray_id == id)
|
{
|
||||||
return FALSE;
|
Atom actual_type;
|
||||||
|
int actual_format;
|
||||||
|
unsigned long nitems;
|
||||||
|
unsigned long bytes_after;
|
||||||
|
unsigned char *prop = 0;
|
||||||
|
int ret = XGetWindowProperty(server.dsp, win, server.atom._NET_WM_PID, 0, 1024, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
|
||||||
|
if (ret == Success && prop) {
|
||||||
|
pid = prop[1] * 256;
|
||||||
|
pid += prop[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = FALSE;
|
// Check if the application leaves behind empty icons
|
||||||
|
GSList *l;
|
||||||
|
int num_empty_same_pid = 0;
|
||||||
|
for (l = systray.list_icons; l; l = l->next) {
|
||||||
|
if (((TrayWindow*)l->data)->win == win)
|
||||||
|
return FALSE;
|
||||||
|
if (pid && ((TrayWindow*)l->data)->pid == pid && ((TrayWindow*)l->data)->empty)
|
||||||
|
num_empty_same_pid++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove empty icons if the application leaves behind more than 1
|
||||||
|
const int max_num_empty_same_pid = 0;
|
||||||
|
if (num_empty_same_pid > max_num_empty_same_pid) {
|
||||||
|
for (l = systray.list_icons; l; l = l->next) {
|
||||||
|
if (pid && ((TrayWindow*)l->data)->pid == pid && ((TrayWindow*)l->data)->empty) {
|
||||||
|
num_empty_same_pid++;
|
||||||
|
fprintf(stderr, "Removing tray icon %lu from misbehaving application with pid=%d\n", ((TrayWindow*)l->data)->win, pid);
|
||||||
|
remove_icon((TrayWindow*)l->data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("add_icon: %d, pid %d, %d\n", win, pid, num_empty_same_pid);
|
||||||
|
|
||||||
|
// Create the parent window that will embed the icon
|
||||||
XWindowAttributes attr;
|
XWindowAttributes attr;
|
||||||
if ( XGetWindowAttributes(server.dsp, id, &attr) == False ) return FALSE;
|
if (XGetWindowAttributes(server.dsp, win, &attr) == False)
|
||||||
|
return FALSE;
|
||||||
unsigned long mask = 0;
|
unsigned long mask = 0;
|
||||||
XSetWindowAttributes set_attr;
|
XSetWindowAttributes set_attr;
|
||||||
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);
|
if (systray_composited || attr.depth != server.depth) {
|
||||||
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;
|
||||||
set_attr.border_pixel = 0;
|
set_attr.border_pixel = 0;
|
||||||
mask = CWColormap|CWBackPixel|CWBorderPixel;
|
mask = CWColormap|CWBackPixel|CWBorderPixel;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
set_attr.background_pixmap = ParentRelative;
|
set_attr.background_pixmap = ParentRelative;
|
||||||
mask = CWBackPixmap;
|
mask = CWBackPixmap;
|
||||||
}
|
}
|
||||||
Window parent_window;
|
Window parent = XCreateWindow(server.dsp, panel->main_win, 0, 0, 30, 30, 0, attr.depth, InputOutput, visual, mask, &set_attr);
|
||||||
parent_window = XCreateWindow(server.dsp, panel->main_win, 0, 0, 30, 30, 0, attr.depth, InputOutput, visual, mask, &set_attr);
|
|
||||||
old = XSetErrorHandler(window_error_handler);
|
// Add the icon to the list
|
||||||
XReparentWindow(server.dsp, id, parent_window, 0, 0);
|
traywin = g_new0(TrayWindow, 1);
|
||||||
// watch for the icon trying to resize itself / closing again!
|
traywin->parent = parent;
|
||||||
XSelectInput(server.dsp, id, StructureNotifyMask);
|
traywin->win = win;
|
||||||
|
traywin->hide = hide;
|
||||||
|
traywin->depth = attr.depth;
|
||||||
|
// Reparenting is done at the first paint event when the window is positioned correctly over its empty background,
|
||||||
|
// to prevent graphical corruptions in icons with fake transparency
|
||||||
|
traywin->reparented = 0;
|
||||||
|
traywin->damage = 0;
|
||||||
|
traywin->empty = 0;
|
||||||
|
traywin->pid = pid;
|
||||||
|
traywin->chrono = chrono;
|
||||||
|
chrono++;
|
||||||
|
|
||||||
|
if (systray.area.on_screen == 0)
|
||||||
|
show(&systray.area);
|
||||||
|
|
||||||
|
if (systray.sort == SYSTRAY_SORT_RIGHT2LEFT)
|
||||||
|
systray.list_icons = g_slist_prepend(systray.list_icons, traywin);
|
||||||
|
else
|
||||||
|
systray.list_icons = g_slist_append(systray.list_icons, traywin);
|
||||||
|
systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
|
||||||
|
// printf("add_icon win %lx, %d\n", win, g_slist_length(systray.list_icons));
|
||||||
|
|
||||||
|
// Resize and redraw the systray
|
||||||
|
systray.area.resize = 1;
|
||||||
|
systray.area.redraw = 1;
|
||||||
|
panel->area.resize = 1;
|
||||||
|
panel_refresh = 1;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean reparent_icon(TrayWindow *traywin)
|
||||||
|
{
|
||||||
|
if (traywin->reparented)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
Panel* panel = systray.area.panel;
|
||||||
|
|
||||||
|
// Reparent
|
||||||
|
XSync(server.dsp, False);
|
||||||
|
error = FALSE;
|
||||||
|
XErrorHandler old = XSetErrorHandler(window_error_handler);
|
||||||
|
XReparentWindow(server.dsp, traywin->win, traywin->parent, 0, 0);
|
||||||
XSync(server.dsp, False);
|
XSync(server.dsp, False);
|
||||||
XSetErrorHandler(old);
|
XSetErrorHandler(old);
|
||||||
if (error != FALSE) {
|
if (error != FALSE) {
|
||||||
fprintf(stderr, "tint2 : not icon_swallow\n");
|
printf("systray %d: cannot embed icon for window %lu parent %lu pid %d\n", __LINE__, traywin->win, traywin->parent, traywin->pid);
|
||||||
XDestroyWindow(server.dsp, parent_window);
|
remove_icon(traywin);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Watch for the icon trying to resize itself / closing again
|
||||||
|
XSync(server.dsp, False);
|
||||||
|
error = FALSE;
|
||||||
|
old = XSetErrorHandler(window_error_handler);
|
||||||
|
XSelectInput(server.dsp, traywin->win, StructureNotifyMask);
|
||||||
|
XSync(server.dsp, False);
|
||||||
|
XSetErrorHandler(old);
|
||||||
|
if (error != FALSE) {
|
||||||
|
printf("systray %d: cannot embed icon for window %lu parent %lu pid %d\n", __LINE__, traywin->win, traywin->parent, traywin->pid);
|
||||||
|
remove_icon(traywin);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
traywin->reparented = 1;
|
||||||
|
|
||||||
|
// Embed into parent
|
||||||
|
{
|
||||||
|
XEvent e;
|
||||||
|
e.xclient.type = ClientMessage;
|
||||||
|
e.xclient.serial = 0;
|
||||||
|
e.xclient.send_event = True;
|
||||||
|
e.xclient.message_type = server.atom._XEMBED;
|
||||||
|
e.xclient.window = traywin->win;
|
||||||
|
e.xclient.format = 32;
|
||||||
|
e.xclient.data.l[0] = CurrentTime;
|
||||||
|
e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY;
|
||||||
|
e.xclient.data.l[2] = 0;
|
||||||
|
e.xclient.data.l[3] = traywin->parent;
|
||||||
|
e.xclient.data.l[4] = 0;
|
||||||
|
XSync(server.dsp, False);
|
||||||
|
error = FALSE;
|
||||||
|
XErrorHandler old = XSetErrorHandler(window_error_handler);
|
||||||
|
XSendEvent(server.dsp, traywin->win, False, 0xFFFFFF, &e);
|
||||||
|
XSync(server.dsp, False);
|
||||||
|
XSetErrorHandler(old);
|
||||||
|
if (error != FALSE) {
|
||||||
|
printf("systray %d: cannot embed icon for window %lu pid %d\n", __LINE__, traywin->win, traywin->pid);
|
||||||
|
remove_icon(traywin);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if window was embedded
|
||||||
{
|
{
|
||||||
Atom acttype;
|
Atom acttype;
|
||||||
int actfmt;
|
int actfmt;
|
||||||
@@ -407,7 +544,7 @@ gboolean add_icon(Window id)
|
|||||||
unsigned char *data = 0;
|
unsigned char *data = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = XGetWindowProperty(server.dsp, id, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data);
|
ret = XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data);
|
||||||
if (ret == Success) {
|
if (ret == Success) {
|
||||||
if (data) {
|
if (data) {
|
||||||
if (nbitem == 2) {
|
if (nbitem == 2) {
|
||||||
@@ -416,84 +553,51 @@ gboolean add_icon(Window id)
|
|||||||
}
|
}
|
||||||
XFree(data);
|
XFree(data);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
fprintf(stderr, "tint2 : xembed error\n");
|
fprintf(stderr, "tint2 : xembed error\n");
|
||||||
XDestroyWindow(server.dsp, parent_window);
|
remove_icon(traywin);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
|
||||||
XEvent e;
|
// Redirect rendering when using compositing
|
||||||
e.xclient.type = ClientMessage;
|
if (systray_composited) {
|
||||||
e.xclient.serial = 0;
|
traywin->damage = XDamageCreate(server.dsp, traywin->parent, XDamageReportRawRectangles);
|
||||||
e.xclient.send_event = True;
|
XCompositeRedirectWindow(server.dsp, traywin->parent, CompositeRedirectManual);
|
||||||
e.xclient.message_type = server.atom._XEMBED;
|
|
||||||
e.xclient.window = id;
|
|
||||||
e.xclient.format = 32;
|
|
||||||
e.xclient.data.l[0] = CurrentTime;
|
|
||||||
e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY;
|
|
||||||
e.xclient.data.l[2] = 0;
|
|
||||||
e.xclient.data.l[3] = parent_window;
|
|
||||||
e.xclient.data.l[4] = 0;
|
|
||||||
XSendEvent(server.dsp, id, False, 0xFFFFFF, &e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
traywin = g_new0(TrayWindow, 1);
|
// Make the icon visible
|
||||||
traywin->id = parent_window;
|
|
||||||
traywin->tray_id = id;
|
|
||||||
traywin->hide = hide;
|
|
||||||
traywin->depth = attr.depth;
|
|
||||||
traywin->damage = 0;
|
|
||||||
|
|
||||||
if (systray.area.on_screen == 0)
|
|
||||||
show(&systray.area);
|
|
||||||
|
|
||||||
if (systray.sort == 3)
|
|
||||||
systray.list_icons = g_slist_prepend(systray.list_icons, traywin);
|
|
||||||
else if (systray.sort == 2)
|
|
||||||
systray.list_icons = g_slist_append(systray.list_icons, traywin);
|
|
||||||
else
|
|
||||||
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));
|
|
||||||
|
|
||||||
if (FORCE_COMPOSITED_RENDERING || server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
|
||||||
traywin->damage = XDamageCreate(server.dsp, traywin->id, XDamageReportRawRectangles);
|
|
||||||
XCompositeRedirectWindow(server.dsp, traywin->id, CompositeRedirectManual);
|
|
||||||
}
|
|
||||||
|
|
||||||
// show the window
|
|
||||||
if (!traywin->hide)
|
if (!traywin->hide)
|
||||||
XMapWindow(server.dsp, traywin->tray_id);
|
XMapWindow(server.dsp, traywin->win);
|
||||||
if (!traywin->hide && !panel->is_hidden)
|
if (!traywin->hide && !panel->is_hidden)
|
||||||
XMapRaised(server.dsp, traywin->id);
|
XMapRaised(server.dsp, traywin->parent);
|
||||||
|
|
||||||
|
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||||
|
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||||
|
|
||||||
|
XFlush(server.dsp);
|
||||||
|
|
||||||
// changed in systray
|
|
||||||
systray.area.resize = 1;
|
|
||||||
panel_refresh = 1;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void remove_icon(TrayWindow *traywin)
|
void remove_icon(TrayWindow *traywin)
|
||||||
{
|
{
|
||||||
XErrorHandler old;
|
|
||||||
|
|
||||||
// remove from our list
|
// remove from our list
|
||||||
systray.list_icons = g_slist_remove(systray.list_icons, traywin);
|
systray.list_icons = g_slist_remove(systray.list_icons, traywin);
|
||||||
//printf("remove_icon id %lx, %d\n", traywin->id);
|
printf("remove_icon: %lu\n", traywin->win);
|
||||||
|
|
||||||
XSelectInput(server.dsp, traywin->tray_id, NoEventMask);
|
XSelectInput(server.dsp, traywin->win, NoEventMask);
|
||||||
if (traywin->damage)
|
if (traywin->damage)
|
||||||
XDamageDestroy(server.dsp, traywin->damage);
|
XDamageDestroy(server.dsp, traywin->damage);
|
||||||
|
|
||||||
// reparent to root
|
// reparent to root
|
||||||
|
XSync(server.dsp, False);
|
||||||
error = FALSE;
|
error = FALSE;
|
||||||
old = XSetErrorHandler(window_error_handler);
|
XErrorHandler old = XSetErrorHandler(window_error_handler);
|
||||||
if (!traywin->hide)
|
if (!traywin->hide)
|
||||||
XUnmapWindow(server.dsp, traywin->tray_id);
|
XUnmapWindow(server.dsp, traywin->win);
|
||||||
XReparentWindow(server.dsp, traywin->tray_id, server.root_win, 0, 0);
|
XReparentWindow(server.dsp, traywin->win, server.root_win, 0, 0);
|
||||||
XDestroyWindow(server.dsp, traywin->id);
|
XDestroyWindow(server.dsp, traywin->parent);
|
||||||
XSync(server.dsp, False);
|
XSync(server.dsp, False);
|
||||||
XSetErrorHandler(old);
|
XSetErrorHandler(old);
|
||||||
stop_timeout(traywin->render_timeout);
|
stop_timeout(traywin->render_timeout);
|
||||||
@@ -503,7 +607,8 @@ void remove_icon(TrayWindow *traywin)
|
|||||||
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)
|
||||||
|
continue;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@@ -518,13 +623,14 @@ void remove_icon(TrayWindow *traywin)
|
|||||||
void net_message(XClientMessageEvent *e)
|
void net_message(XClientMessageEvent *e)
|
||||||
{
|
{
|
||||||
unsigned long opcode;
|
unsigned long opcode;
|
||||||
Window id;
|
Window win;
|
||||||
|
|
||||||
opcode = e->data.l[1];
|
opcode = e->data.l[1];
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case SYSTEM_TRAY_REQUEST_DOCK:
|
case SYSTEM_TRAY_REQUEST_DOCK:
|
||||||
id = e->data.l[2];
|
win = e->data.l[2];
|
||||||
if (id) add_icon(id);
|
if (win)
|
||||||
|
add_icon(win);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSTEM_TRAY_BEGIN_MESSAGE:
|
case SYSTEM_TRAY_BEGIN_MESSAGE:
|
||||||
@@ -541,17 +647,94 @@ void net_message(XClientMessageEvent *e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void systray_render_icon_now(void* t)
|
Display *display = NULL;
|
||||||
|
XImage *tintXGetImage(Window win)
|
||||||
|
{
|
||||||
|
char *display_name = XDisplayName(NULL);
|
||||||
|
if (!display_name)
|
||||||
|
return NULL;
|
||||||
|
if (!display)
|
||||||
|
display = XOpenDisplay(display_name);
|
||||||
|
if (!display)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
unsigned int border_width;
|
||||||
|
int xpos, ypos;
|
||||||
|
unsigned int width, height, depth;
|
||||||
|
Window root;
|
||||||
|
if (!XGetGeometry(display, win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
||||||
|
fprintf(stderr, "Couldn't get geometry of window!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return XGetImage(display, win, 0, 0, width, height, AllPlanes, XYPixmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void systray_render_icon_composited(void* t)
|
||||||
{
|
{
|
||||||
// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0
|
// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0
|
||||||
// we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here
|
// we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here
|
||||||
TrayWindow* traywin = t;
|
TrayWindow* traywin = t;
|
||||||
traywin->render_timeout = 0;
|
|
||||||
if ( traywin->width == 0 || traywin->height == 0 ) {
|
// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
|
||||||
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
|
struct timespec now;
|
||||||
systray_render_icon(traywin);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
struct timespec earliest_render = add_msec_to_timespec(traywin->time_last_render, 50);
|
||||||
|
if (compare_timespecs(&earliest_render, &now) > 0) {
|
||||||
|
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
traywin->time_last_render.tv_sec = now.tv_sec;
|
||||||
|
traywin->time_last_render.tv_nsec = now.tv_nsec;
|
||||||
|
|
||||||
|
if ( traywin->width == 0 || traywin->height == 0 ) {
|
||||||
|
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
|
||||||
|
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (traywin->render_timeout) {
|
||||||
|
stop_timeout(traywin->render_timeout);
|
||||||
|
traywin->render_timeout = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int empty = 1;
|
||||||
|
XImage *ximage = tintXGetImage(traywin->win);
|
||||||
|
if (ximage) {
|
||||||
|
if (ximage->width != traywin->width ||
|
||||||
|
ximage->height != traywin->height) {
|
||||||
|
XFree(ximage);
|
||||||
|
XCloseDisplay(display);
|
||||||
|
display = NULL;
|
||||||
|
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
XColor color;
|
||||||
|
if (ximage->width > 0 && ximage->height > 0) {
|
||||||
|
color.pixel = XGetPixel(ximage, ximage->width/2, ximage->height/2);
|
||||||
|
if (color.pixel != 0)
|
||||||
|
empty = 0;
|
||||||
|
int x, y;
|
||||||
|
for (x = 0; empty && x < ximage->width; x++) {
|
||||||
|
for (y = 0; empty && y < ximage->height; y++) {
|
||||||
|
color.pixel = XGetPixel(ximage, x, y);
|
||||||
|
if (color.pixel != 0)
|
||||||
|
empty = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(ximage);
|
||||||
|
XCloseDisplay(display);
|
||||||
|
display = NULL;
|
||||||
|
}
|
||||||
|
if (traywin->empty != empty) {
|
||||||
|
traywin->empty = empty;
|
||||||
|
systray.area.resize = 1;
|
||||||
|
panel_refresh = 1;
|
||||||
|
systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
|
||||||
|
}
|
||||||
|
//printf("systray_render_icon_now: %d empty %d\n", traywin->win, empty);
|
||||||
|
if (empty)
|
||||||
|
return;
|
||||||
|
|
||||||
// good systray icons support 32 bit depth, but some icons are still 24 bit.
|
// good systray icons support 32 bit depth, but some icons are still 24 bit.
|
||||||
// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
|
// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
|
||||||
@@ -561,22 +744,46 @@ void systray_render_icon_now(void* t)
|
|||||||
// Very ugly hack, but somehow imlib2 is not able to get the image from the traywindow itself,
|
// Very ugly hack, but somehow imlib2 is not able to get the image from the traywindow itself,
|
||||||
// so we first render the tray window onto a pixmap, and then we tell imlib2 to use this pixmap as
|
// so we first render the tray window onto a pixmap, and then we tell imlib2 to use this pixmap as
|
||||||
// drawable. If someone knows why it does not work with the traywindow itself, please tell me ;)
|
// drawable. If someone knows why it does not work with the traywindow itself, please tell me ;)
|
||||||
Pixmap tmp_pmap = XCreatePixmap(server.dsp, server.root_win, traywin->width, traywin->height, 32);
|
Pixmap tmp_pmap = XCreatePixmap(server.dsp, traywin->win, traywin->width, traywin->height, 32);
|
||||||
|
if (!tmp_pmap) {
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
XRenderPictFormat *f;
|
XRenderPictFormat *f;
|
||||||
if (traywin->depth == 24)
|
if (traywin->depth == 24) {
|
||||||
f = XRenderFindStandardFormat(server.dsp, PictStandardRGB24);
|
f = XRenderFindStandardFormat(server.dsp, PictStandardRGB24);
|
||||||
else if (traywin->depth == 32)
|
} else if (traywin->depth == 32) {
|
||||||
f = XRenderFindStandardFormat(server.dsp, PictStandardARGB32);
|
f = XRenderFindStandardFormat(server.dsp, PictStandardARGB32);
|
||||||
else {
|
} else {
|
||||||
printf("Strange tray icon found with depth: %d\n", traywin->depth);
|
printf("Strange tray icon found with depth: %d\n", traywin->depth);
|
||||||
|
XFreePixmap(server.dsp, tmp_pmap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Picture pict_image;
|
XRenderPictFormat *f32 = XRenderFindVisualFormat(server.dsp, server.visual32);
|
||||||
|
if (!f || !f32) {
|
||||||
|
XFreePixmap(server.dsp, tmp_pmap);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
XSync(server.dsp, False);
|
||||||
|
error = FALSE;
|
||||||
|
XErrorHandler old = XSetErrorHandler(window_error_handler);
|
||||||
|
|
||||||
//if (server.real_transparency)
|
//if (server.real_transparency)
|
||||||
//pict_image = XRenderCreatePicture(server.dsp, traywin->id, f, 0, 0);
|
//Picture pict_image = XRenderCreatePicture(server.dsp, traywin->parent, f, 0, 0);
|
||||||
// reverted Rev 407 because here it's breaking alls icon with systray + xcompmgr
|
// reverted Rev 407 because here it's breaking alls icon with systray + xcompmgr
|
||||||
pict_image = XRenderCreatePicture(server.dsp, traywin->tray_id, f, 0, 0);
|
Picture pict_image = XRenderCreatePicture(server.dsp, traywin->win, f, 0, 0);
|
||||||
|
if (!pict_image) {
|
||||||
|
XFreePixmap(server.dsp, tmp_pmap);
|
||||||
|
XSetErrorHandler(old);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
Picture pict_drawable = XRenderCreatePicture(server.dsp, tmp_pmap, XRenderFindVisualFormat(server.dsp, server.visual32), 0, 0);
|
Picture pict_drawable = XRenderCreatePicture(server.dsp, tmp_pmap, XRenderFindVisualFormat(server.dsp, server.visual32), 0, 0);
|
||||||
|
if (!pict_drawable) {
|
||||||
|
XRenderFreePicture(server.dsp, pict_image);
|
||||||
|
XFreePixmap(server.dsp, tmp_pmap);
|
||||||
|
XSetErrorHandler(old);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
XRenderComposite(server.dsp, PictOpSrc, pict_image, None, pict_drawable, 0, 0, 0, 0, 0, 0, traywin->width, traywin->height);
|
XRenderComposite(server.dsp, PictOpSrc, pict_image, None, pict_drawable, 0, 0, 0, 0, 0, 0, traywin->width, traywin->height);
|
||||||
XRenderFreePicture(server.dsp, pict_image);
|
XRenderFreePicture(server.dsp, pict_image);
|
||||||
XRenderFreePicture(server.dsp, pict_drawable);
|
XRenderFreePicture(server.dsp, pict_drawable);
|
||||||
@@ -586,8 +793,13 @@ void systray_render_icon_now(void* t)
|
|||||||
imlib_context_set_colormap(server.colormap32);
|
imlib_context_set_colormap(server.colormap32);
|
||||||
imlib_context_set_drawable(tmp_pmap);
|
imlib_context_set_drawable(tmp_pmap);
|
||||||
Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, traywin->width, traywin->height, 1);
|
Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, traywin->width, traywin->height, 1);
|
||||||
if (image == 0)
|
if (!image) {
|
||||||
return;
|
imlib_context_set_visual(server.visual);
|
||||||
|
imlib_context_set_colormap(server.colormap);
|
||||||
|
XFreePixmap(server.dsp, tmp_pmap);
|
||||||
|
XSetErrorHandler(old);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
imlib_context_set_image(image);
|
imlib_context_set_image(image);
|
||||||
//if (traywin->depth == 24)
|
//if (traywin->depth == 24)
|
||||||
@@ -611,21 +823,36 @@ void systray_render_icon_now(void* t)
|
|||||||
if (traywin->damage)
|
if (traywin->damage)
|
||||||
XDamageSubtract(server.dsp, traywin->damage, None, None);
|
XDamageSubtract(server.dsp, traywin->damage, None, None);
|
||||||
XFlush(server.dsp);
|
XFlush(server.dsp);
|
||||||
|
|
||||||
|
XSync(server.dsp, False);
|
||||||
|
XSetErrorHandler(old);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
printf("systray: rendering error. Disabling compositing and restarting systray...\n");
|
||||||
|
systray_composited = 0;
|
||||||
|
stop_net();
|
||||||
|
start_net();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void systray_render_icon(TrayWindow* traywin)
|
void systray_render_icon(TrayWindow* traywin)
|
||||||
{
|
{
|
||||||
if (FORCE_COMPOSITED_RENDERING || server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) {
|
if (!reparent_icon(traywin))
|
||||||
// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
|
return;
|
||||||
|
|
||||||
|
if (systray_composited) {
|
||||||
if (!traywin->render_timeout)
|
if (!traywin->render_timeout)
|
||||||
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_now, traywin, &traywin->render_timeout);
|
systray_render_icon_composited(traywin);
|
||||||
}
|
} else {
|
||||||
else {
|
// Trigger window repaint
|
||||||
// Pixmap pix = XCreatePixmap(server.dsp, server.root_win, traywin->width, traywin->height, server.depth);
|
XClearArea(server.dsp, traywin->parent, 0, 0, traywin->width, traywin->height, True);
|
||||||
// XCopyArea(server.dsp, panel->temp_pmap, pix, server.gc, traywin->x, traywin->y, traywin->width, traywin->height, 0, 0);
|
XClearArea(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height, True);
|
||||||
// XSetWindowBackgroundPixmap(server.dsp, traywin->id, pix);
|
|
||||||
XClearArea(server.dsp, traywin->tray_id, 0, 0, traywin->width, traywin->height, True);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,7 +863,8 @@ void refresh_systray_icon()
|
|||||||
GSList *l;
|
GSList *l;
|
||||||
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->hide) continue;
|
if (traywin->hide)
|
||||||
|
continue;
|
||||||
systray_render_icon(traywin);
|
systray_render_icon(traywin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
// Flags for _XEMBED_INFO
|
// Flags for _XEMBED_INFO
|
||||||
#define XEMBED_MAPPED (1 << 0)
|
#define XEMBED_MAPPED (1 << 0)
|
||||||
|
|
||||||
|
enum { SYSTRAY_SORT_ASCENDING, SYSTRAY_SORT_DESCENDING, SYSTRAY_SORT_LEFT2RIGHT, SYSTRAY_SORT_RIGHT2LEFT };
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// always start with area
|
// always start with area
|
||||||
@@ -34,8 +35,8 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Window id;
|
Window parent;
|
||||||
Window tray_id;
|
Window win;
|
||||||
int x, y;
|
int x, y;
|
||||||
int width, height;
|
int width, height;
|
||||||
// TODO: manage icon's show/hide
|
// TODO: manage icon's show/hide
|
||||||
@@ -43,6 +44,11 @@ typedef struct
|
|||||||
int depth;
|
int depth;
|
||||||
Damage damage;
|
Damage damage;
|
||||||
timeout* render_timeout;
|
timeout* render_timeout;
|
||||||
|
int empty;
|
||||||
|
int pid;
|
||||||
|
int chrono;
|
||||||
|
struct timespec time_last_render;
|
||||||
|
int reparented;
|
||||||
} TrayWindow;
|
} TrayWindow;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ Task *add_task (Window win)
|
|||||||
if (!win) return 0;
|
if (!win) return 0;
|
||||||
if (window_is_hidden(win)) return 0;
|
if (window_is_hidden(win)) return 0;
|
||||||
|
|
||||||
|
XSelectInput(server.dsp, win, PropertyChangeMask|StructureNotifyMask);
|
||||||
|
XFlush(server.dsp);
|
||||||
|
|
||||||
int monitor;
|
int monitor;
|
||||||
if (nb_panel > 1) {
|
if (nb_panel > 1) {
|
||||||
monitor = window_get_monitor (win);
|
monitor = window_get_monitor (win);
|
||||||
@@ -75,8 +78,7 @@ Task *add_task (Window win)
|
|||||||
get_title(&new_tsk);
|
get_title(&new_tsk);
|
||||||
get_icon(&new_tsk);
|
get_icon(&new_tsk);
|
||||||
|
|
||||||
//printf("task %s : desktop %d, monitor %d\n", new_tsk->title, desktop, monitor);
|
//printf("new task %s win %u: desktop %d, monitor %d\n", new_tsk.title, win, new_tsk.desktop, monitor);
|
||||||
XSelectInput (server.dsp, new_tsk.win, PropertyChangeMask|StructureNotifyMask);
|
|
||||||
|
|
||||||
GPtrArray* task_group = g_ptr_array_new();
|
GPtrArray* task_group = g_ptr_array_new();
|
||||||
Taskbar *tskbar;
|
Taskbar *tskbar;
|
||||||
@@ -109,7 +111,7 @@ Task *add_task (Window win)
|
|||||||
}
|
}
|
||||||
new_tsk2->icon_width = new_tsk.icon_width;
|
new_tsk2->icon_width = new_tsk.icon_width;
|
||||||
new_tsk2->icon_height = new_tsk.icon_height;
|
new_tsk2->icon_height = new_tsk.icon_height;
|
||||||
tskbar->area.list = g_slist_append(tskbar->area.list, new_tsk2);
|
tskbar->area.list = g_list_append(tskbar->area.list, new_tsk2);
|
||||||
tskbar->area.resize = 1;
|
tskbar->area.resize = 1;
|
||||||
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);
|
||||||
@@ -167,7 +169,7 @@ void remove_task (Task *tsk)
|
|||||||
for (i=0; i<task_group->len; ++i) {
|
for (i=0; i<task_group->len; ++i) {
|
||||||
tsk2 = g_ptr_array_index(task_group, i);
|
tsk2 = g_ptr_array_index(task_group, i);
|
||||||
tskbar = tsk2->area.parent;
|
tskbar = tsk2->area.parent;
|
||||||
tskbar->area.list = g_slist_remove(tskbar->area.list, tsk2);
|
tskbar->area.list = g_list_remove(tskbar->area.list, tsk2);
|
||||||
tskbar->area.resize = 1;
|
tskbar->area.resize = 1;
|
||||||
if (tsk2 == task_active) task_active = 0;
|
if (tsk2 == task_active) task_active = 0;
|
||||||
if (tsk2 == task_drag) task_drag = 0;
|
if (tsk2 == task_drag) task_drag = 0;
|
||||||
@@ -422,15 +424,13 @@ Task *find_active_task(Task *current_task, Task *active_task)
|
|||||||
if (active_task == NULL)
|
if (active_task == NULL)
|
||||||
return current_task;
|
return current_task;
|
||||||
|
|
||||||
GSList *l0;
|
|
||||||
Task *tsk;
|
|
||||||
Taskbar* tskbar = current_task->area.parent;
|
Taskbar* tskbar = current_task->area.parent;
|
||||||
|
|
||||||
l0 = tskbar->area.list;
|
GList *l0 = tskbar->area.list;
|
||||||
if (taskbarname_enabled)
|
if (taskbarname_enabled)
|
||||||
l0 = l0->next;
|
l0 = l0->next;
|
||||||
for (; l0 ; l0 = l0->next) {
|
for (; l0 ; l0 = l0->next) {
|
||||||
tsk = l0->data;
|
Task *tsk = l0->data;
|
||||||
if (tsk->win == active_task->win)
|
if (tsk->win == active_task->win)
|
||||||
return tsk;
|
return tsk;
|
||||||
}
|
}
|
||||||
@@ -443,15 +443,13 @@ Task *next_task(Task *tsk)
|
|||||||
if (tsk == 0)
|
if (tsk == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
GSList *l0, *lfirst_tsk;
|
|
||||||
Task *tsk1;
|
|
||||||
Taskbar* tskbar = tsk->area.parent;
|
Taskbar* tskbar = tsk->area.parent;
|
||||||
|
|
||||||
l0 = tskbar->area.list;
|
GList *l0 = tskbar->area.list;
|
||||||
if (taskbarname_enabled) l0 = l0->next;
|
if (taskbarname_enabled) l0 = l0->next;
|
||||||
lfirst_tsk = l0;
|
GList *lfirst_tsk = l0;
|
||||||
for (; l0 ; l0 = l0->next) {
|
for (; l0 ; l0 = l0->next) {
|
||||||
tsk1 = l0->data;
|
Task *tsk1 = l0->data;
|
||||||
if (tsk1 == tsk) {
|
if (tsk1 == tsk) {
|
||||||
if (l0->next == 0) l0 = lfirst_tsk;
|
if (l0->next == 0) l0 = lfirst_tsk;
|
||||||
else l0 = l0->next;
|
else l0 = l0->next;
|
||||||
@@ -467,19 +465,18 @@ Task *prev_task(Task *tsk)
|
|||||||
if (tsk == 0)
|
if (tsk == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
GSList *l0, *lfirst_tsk;
|
|
||||||
Task *tsk1, *tsk2;
|
Task *tsk1, *tsk2;
|
||||||
Taskbar* tskbar = tsk->area.parent;
|
Taskbar* tskbar = tsk->area.parent;
|
||||||
|
|
||||||
tsk2 = 0;
|
tsk2 = 0;
|
||||||
l0 = tskbar->area.list;
|
GList *l0 = tskbar->area.list;
|
||||||
if (taskbarname_enabled) l0 = l0->next;
|
if (taskbarname_enabled) l0 = l0->next;
|
||||||
lfirst_tsk = l0;
|
GList *lfirst_tsk = l0;
|
||||||
for (; l0 ; l0 = l0->next) {
|
for (; l0 ; l0 = l0->next) {
|
||||||
tsk1 = l0->data;
|
tsk1 = l0->data;
|
||||||
if (tsk1 == tsk) {
|
if (tsk1 == tsk) {
|
||||||
if (l0 == lfirst_tsk) {
|
if (l0 == lfirst_tsk) {
|
||||||
l0 = g_slist_last ( l0 );
|
l0 = g_list_last ( l0 );
|
||||||
tsk2 = l0->data;
|
tsk2 = l0->data;
|
||||||
}
|
}
|
||||||
return tsk2;
|
return tsk2;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ int taskbar_distribute_size;
|
|||||||
int hide_inactive_tasks;
|
int hide_inactive_tasks;
|
||||||
int hide_task_diff_monitor;
|
int hide_task_diff_monitor;
|
||||||
int taskbar_sort_method;
|
int taskbar_sort_method;
|
||||||
|
int taskbar_alignment;
|
||||||
|
|
||||||
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)); }
|
||||||
@@ -63,6 +64,7 @@ void default_taskbar()
|
|||||||
hide_inactive_tasks = 0;
|
hide_inactive_tasks = 0;
|
||||||
hide_task_diff_monitor = 0;
|
hide_task_diff_monitor = 0;
|
||||||
taskbar_sort_method = TASKBAR_NOSORT;
|
taskbar_sort_method = TASKBAR_NOSORT;
|
||||||
|
taskbar_alignment = ALIGN_LEFT;
|
||||||
default_taskbarname();
|
default_taskbarname();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +99,7 @@ void cleanup_taskbar()
|
|||||||
}
|
}
|
||||||
free_area(&tskbar->area);
|
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_list_remove(panel->area.list, tskbar);
|
||||||
}
|
}
|
||||||
if (panel->taskbar) {
|
if (panel->taskbar) {
|
||||||
free(panel->taskbar);
|
free(panel->taskbar);
|
||||||
@@ -153,6 +155,7 @@ void init_taskbar_panel(void *p)
|
|||||||
panel->g_taskbar.area.parent = panel;
|
panel->g_taskbar.area.parent = panel;
|
||||||
panel->g_taskbar.area.panel = panel;
|
panel->g_taskbar.area.panel = panel;
|
||||||
panel->g_taskbar.area.size_mode = SIZE_BY_LAYOUT;
|
panel->g_taskbar.area.size_mode = SIZE_BY_LAYOUT;
|
||||||
|
panel->g_taskbar.area.alignment = taskbar_alignment;
|
||||||
panel->g_taskbar.area._resize = resize_taskbar;
|
panel->g_taskbar.area._resize = resize_taskbar;
|
||||||
panel->g_taskbar.area._draw_foreground = draw_taskbar;
|
panel->g_taskbar.area._draw_foreground = draw_taskbar;
|
||||||
panel->g_taskbar.area._on_change_layout = on_change_taskbar;
|
panel->g_taskbar.area._on_change_layout = on_change_taskbar;
|
||||||
@@ -334,7 +337,7 @@ int resize_taskbar(void *obj)
|
|||||||
resize_by_layout(obj, panel->g_task.maximum_width);
|
resize_by_layout(obj, panel->g_task.maximum_width);
|
||||||
|
|
||||||
text_width = panel->g_task.maximum_width;
|
text_width = panel->g_task.maximum_width;
|
||||||
GSList *l = taskbar->area.list;
|
GList *l = taskbar->area.list;
|
||||||
if (taskbarname_enabled) l = l->next;
|
if (taskbarname_enabled) l = l->next;
|
||||||
for (; l != NULL; l = l->next) {
|
for (; l != NULL; l = l->next) {
|
||||||
if (((Task *)l->data)->area.on_screen) {
|
if (((Task *)l->data)->area.on_screen) {
|
||||||
@@ -388,7 +391,7 @@ void set_taskbar_state(Taskbar *tskbar, int state)
|
|||||||
if (taskbarname_enabled && tskbar->bar_name.state_pix[state] == 0)
|
if (taskbarname_enabled && tskbar->bar_name.state_pix[state] == 0)
|
||||||
tskbar->bar_name.area.redraw = 1;
|
tskbar->bar_name.area.redraw = 1;
|
||||||
if (panel_mode == MULTI_DESKTOP && panel1[0].g_taskbar.background[TASKBAR_NORMAL] != panel1[0].g_taskbar.background[TASKBAR_ACTIVE]) {
|
if (panel_mode == MULTI_DESKTOP && panel1[0].g_taskbar.background[TASKBAR_NORMAL] != panel1[0].g_taskbar.background[TASKBAR_ACTIVE]) {
|
||||||
GSList *l = tskbar->area.list;
|
GList *l = tskbar->area.list;
|
||||||
if (taskbarname_enabled) l = l->next;
|
if (taskbarname_enabled) l = l->next;
|
||||||
for ( ; l ; l = l->next)
|
for ( ; l ; l = l->next)
|
||||||
set_task_redraw(l->data);
|
set_task_redraw(l->data);
|
||||||
@@ -511,7 +514,7 @@ int taskbar_needs_sort(Taskbar *taskbar)
|
|||||||
if (taskbar_sort_method == TASKBAR_NOSORT)
|
if (taskbar_sort_method == TASKBAR_NOSORT)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
GSList *i, *j;
|
GList *i, *j;
|
||||||
for (i = taskbar->area.list, j = i ? i->next : NULL; i && j; i = i->next, j = j->next) {
|
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) {
|
if (compare_tasks(i->data, j->data, taskbar) > 0) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -528,7 +531,7 @@ void sort_tasks(Taskbar *taskbar)
|
|||||||
if (!taskbar_needs_sort(taskbar)) {
|
if (!taskbar_needs_sort(taskbar)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
taskbar->area.list = g_slist_sort_with_data(taskbar->area.list, (GCompareDataFunc)compare_tasks, taskbar);
|
taskbar->area.list = g_list_sort_with_data(taskbar->area.list, (GCompareDataFunc)compare_tasks, taskbar);
|
||||||
taskbar->area.resize = 1;
|
taskbar->area.resize = 1;
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
((Panel*)taskbar->area.panel)->area.resize = 1;
|
((Panel*)taskbar->area.panel)->area.resize = 1;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ extern int hide_inactive_tasks;
|
|||||||
extern int hide_task_diff_monitor;
|
extern int hide_task_diff_monitor;
|
||||||
enum { TASKBAR_NOSORT, TASKBAR_SORT_CENTER, TASKBAR_SORT_TITLE };
|
enum { TASKBAR_NOSORT, TASKBAR_SORT_CENTER, TASKBAR_SORT_TITLE };
|
||||||
extern int taskbar_sort_method;
|
extern int taskbar_sort_method;
|
||||||
|
extern int taskbar_alignment;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// always start with area
|
// always start with area
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ void init_taskbarname_panel(void *p)
|
|||||||
tskbar->bar_name.name = g_strdup_printf("%d", j+1);
|
tskbar->bar_name.name = g_strdup_printf("%d", j+1);
|
||||||
|
|
||||||
// append the name at the beginning of taskbar
|
// append the name at the beginning of taskbar
|
||||||
tskbar->area.list = g_slist_append(tskbar->area.list, &tskbar->bar_name);
|
tskbar->area.list = g_list_append(tskbar->area.list, &tskbar->bar_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l=list ; l ; l = l->next)
|
for (l=list ; l ; l = l->next)
|
||||||
@@ -103,7 +103,7 @@ void cleanup_taskbarname()
|
|||||||
XFreePixmap(server.dsp, tskbar->bar_name.state_pix[k]);
|
XFreePixmap(server.dsp, tskbar->bar_name.state_pix[k]);
|
||||||
tskbar->bar_name.state_pix[k] = 0;
|
tskbar->bar_name.state_pix[k] = 0;
|
||||||
}
|
}
|
||||||
tskbar->area.list = g_slist_remove(tskbar->area.list, &tskbar->bar_name);
|
tskbar->area.list = g_list_remove(tskbar->area.list, &tskbar->bar_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
src/tint.c
28
src/tint.c
@@ -470,8 +470,8 @@ void event_button_motion_notify (XEvent *e)
|
|||||||
} else {
|
} else {
|
||||||
// Swap the task_drag with the task on the event's location (if they differ)
|
// Swap the task_drag with the task on the event's location (if they differ)
|
||||||
if(event_task && event_task != task_drag) {
|
if(event_task && event_task != task_drag) {
|
||||||
GSList * drag_iter = g_slist_find(event_taskbar->area.list, task_drag);
|
GList * drag_iter = g_list_find(event_taskbar->area.list, task_drag);
|
||||||
GSList * task_iter = g_slist_find(event_taskbar->area.list, event_task);
|
GList * task_iter = g_list_find(event_taskbar->area.list, event_task);
|
||||||
if(drag_iter && task_iter) {
|
if(drag_iter && task_iter) {
|
||||||
gpointer temp = task_iter->data;
|
gpointer temp = task_iter->data;
|
||||||
task_iter->data = drag_iter->data;
|
task_iter->data = drag_iter->data;
|
||||||
@@ -488,14 +488,14 @@ void event_button_motion_notify (XEvent *e)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Taskbar * drag_taskbar = (Taskbar*)task_drag->area.parent;
|
Taskbar * drag_taskbar = (Taskbar*)task_drag->area.parent;
|
||||||
drag_taskbar->area.list = g_slist_remove(drag_taskbar->area.list, task_drag);
|
drag_taskbar->area.list = g_list_remove(drag_taskbar->area.list, task_drag);
|
||||||
|
|
||||||
if(event_taskbar->area.posx > drag_taskbar->area.posx || event_taskbar->area.posy > drag_taskbar->area.posy) {
|
if(event_taskbar->area.posx > drag_taskbar->area.posx || event_taskbar->area.posy > drag_taskbar->area.posy) {
|
||||||
int i = (taskbarname_enabled) ? 1 : 0;
|
int i = (taskbarname_enabled) ? 1 : 0;
|
||||||
event_taskbar->area.list = g_slist_insert(event_taskbar->area.list, task_drag, i);
|
event_taskbar->area.list = g_list_insert(event_taskbar->area.list, task_drag, i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
event_taskbar->area.list = g_slist_append(event_taskbar->area.list, task_drag);
|
event_taskbar->area.list = g_list_append(event_taskbar->area.list, task_drag);
|
||||||
|
|
||||||
// Move task to other desktop (but avoid the 'Window desktop changed' code in 'event_property_notify')
|
// Move task to other desktop (but avoid the 'Window desktop changed' code in 'event_property_notify')
|
||||||
task_drag->area.parent = event_taskbar;
|
task_drag->area.parent = event_taskbar;
|
||||||
@@ -677,10 +677,9 @@ void event_property_notify (XEvent *e)
|
|||||||
// check ALLDESKTOP task => resize taskbar
|
// check ALLDESKTOP task => resize taskbar
|
||||||
Taskbar *tskbar;
|
Taskbar *tskbar;
|
||||||
Task *tsk;
|
Task *tsk;
|
||||||
GSList *l;
|
|
||||||
if (server.nb_desktop > old_desktop) {
|
if (server.nb_desktop > old_desktop) {
|
||||||
tskbar = &panel->taskbar[old_desktop];
|
tskbar = &panel->taskbar[old_desktop];
|
||||||
l = tskbar->area.list;
|
GList *l = tskbar->area.list;
|
||||||
if (taskbarname_enabled) l = l->next;
|
if (taskbarname_enabled) l = l->next;
|
||||||
for (; l ; l = l->next) {
|
for (; l ; l = l->next) {
|
||||||
tsk = l->data;
|
tsk = l->data;
|
||||||
@@ -694,7 +693,7 @@ void event_property_notify (XEvent *e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tskbar = &panel->taskbar[server.desktop];
|
tskbar = &panel->taskbar[server.desktop];
|
||||||
l = tskbar->area.list;
|
GList *l = tskbar->area.list;
|
||||||
if (taskbarname_enabled) l = l->next;
|
if (taskbarname_enabled) l = l->next;
|
||||||
for (; l ; l = l->next) {
|
for (; l ; l = l->next) {
|
||||||
tsk = l->data;
|
tsk = l->data;
|
||||||
@@ -727,6 +726,7 @@ void event_property_notify (XEvent *e)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tsk = task_get_task (win);
|
tsk = task_get_task (win);
|
||||||
|
//printf("change win = %u, task = %p\n", win, tsk);
|
||||||
if (!tsk) {
|
if (!tsk) {
|
||||||
if (at != server.atom._NET_WM_STATE)
|
if (at != server.atom._NET_WM_STATE)
|
||||||
return;
|
return;
|
||||||
@@ -830,11 +830,13 @@ void event_configure_notify (Window win)
|
|||||||
GSList *l;
|
GSList *l;
|
||||||
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->tray_id == win) {
|
if (traywin->win == win) {
|
||||||
//printf("move tray %d\n", traywin->x);
|
//printf("move tray %d\n", traywin->x);
|
||||||
XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, traywin->width, traywin->height);
|
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||||
XResizeWindow(server.dsp, traywin->tray_id, traywin->width, traywin->height);
|
if (traywin->reparented)
|
||||||
|
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||||
panel_refresh = 1;
|
panel_refresh = 1;
|
||||||
|
refresh_systray = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1267,7 +1269,7 @@ start:
|
|||||||
if (e.xany.window == g_tooltip.window || !systray_enabled)
|
if (e.xany.window == g_tooltip.window || !systray_enabled)
|
||||||
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)->win == e.xany.window) {
|
||||||
remove_icon((TrayWindow*)it->data);
|
remove_icon((TrayWindow*)it->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1412,7 +1414,7 @@ start:
|
|||||||
XDamageNotifyEvent* de = &event_union.de;
|
XDamageNotifyEvent* de = &event_union.de;
|
||||||
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->parent == de->drawable ) {
|
||||||
systray_render_icon(traywin);
|
systray_render_icon(traywin);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,9 +60,13 @@ if ( NOT DATADIR )
|
|||||||
endif( NOT DATADIR )
|
endif( NOT DATADIR )
|
||||||
|
|
||||||
add_definitions( -DINSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\" )
|
add_definitions( -DINSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\" )
|
||||||
|
add_definitions( -DLOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${DATADIR}/locale\" )
|
||||||
|
add_definitions( -DGETTEXT_PACKAGE=\"tint2conf\" )
|
||||||
set_target_properties( tint2conf PROPERTIES COMPILE_FLAGS "-Wall -pthread" )
|
set_target_properties( tint2conf PROPERTIES COMPILE_FLAGS "-Wall -pthread" )
|
||||||
set_target_properties( tint2conf PROPERTIES LINK_FLAGS "-pthread" )
|
set_target_properties( tint2conf PROPERTIES LINK_FLAGS "-pthread" )
|
||||||
|
|
||||||
|
add_subdirectory(po)
|
||||||
|
|
||||||
install( TARGETS tint2conf DESTINATION bin )
|
install( TARGETS tint2conf DESTINATION bin )
|
||||||
install( FILES tint2conf.svg DESTINATION ${DATADIR}/icons/hicolor/scalable/apps )
|
install( FILES tint2conf.svg DESTINATION ${DATADIR}/icons/hicolor/scalable/apps )
|
||||||
install( FILES tint2conf.desktop DESTINATION ${DATADIR}/applications )
|
install( FILES tint2conf.desktop DESTINATION ${DATADIR}/applications )
|
||||||
|
|||||||
@@ -119,26 +119,12 @@ static const char *global_ui =
|
|||||||
" </popup>"
|
" </popup>"
|
||||||
"</ui>";
|
"</ui>";
|
||||||
|
|
||||||
|
|
||||||
// define menubar and toolbar action
|
|
||||||
static GtkActionEntry entries[] = {
|
|
||||||
{"ThemeMenu", NULL, _("Theme"), NULL, NULL, NULL},
|
|
||||||
{"ThemeAdd", GTK_STOCK_ADD, _("_Import theme..."), "<Control>N", _("Import theme"), G_CALLBACK(menuImport)},
|
|
||||||
{"ThemeDefault", GTK_STOCK_NEW, _("_Import default theme..."), NULL, _("Import default theme"), G_CALLBACK(menuImportDefault)},
|
|
||||||
{"ThemeSaveAs", GTK_STOCK_SAVE_AS, _("_Save as..."), NULL, _("Save theme as"), G_CALLBACK(menuSaveAs)},
|
|
||||||
{"ThemeDelete", GTK_STOCK_DELETE, _("_Delete"), NULL, _("Delete theme"), G_CALLBACK(menuDelete)},
|
|
||||||
{"ThemeProperties", GTK_STOCK_PROPERTIES, _("_Edit theme..."), NULL, _("Edit selected theme"), G_CALLBACK(edit_current_theme)},
|
|
||||||
{"ThemeQuit", GTK_STOCK_QUIT, _("_Quit"), "<control>Q", _("Quit"), G_CALLBACK(gtk_main_quit)},
|
|
||||||
{"EditMenu", NULL, "Edit", NULL, NULL, NULL},
|
|
||||||
{"EditRefresh", GTK_STOCK_REFRESH, _("Refresh"), NULL, _("Refresh"), G_CALLBACK(refresh_current_theme)},
|
|
||||||
{"EditRefreshAll", GTK_STOCK_REFRESH, _("Refresh all"), NULL, _("Refresh all"), G_CALLBACK(load_all_themes)},
|
|
||||||
{"HelpMenu", NULL, _("Help"), NULL, NULL, NULL},
|
|
||||||
{"HelpAbout", GTK_STOCK_ABOUT, _("_About"), "<Control>A", _("About"), G_CALLBACK(menuAbout)}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
|
||||||
|
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
||||||
|
textdomain(GETTEXT_PACKAGE);
|
||||||
|
|
||||||
GtkWidget *vBox = NULL, *scrollbar = NULL;
|
GtkWidget *vBox = NULL, *scrollbar = NULL;
|
||||||
GtkActionGroup *actionGroup;
|
GtkActionGroup *actionGroup;
|
||||||
|
|
||||||
@@ -167,6 +153,23 @@ int main(int argc, char **argv)
|
|||||||
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");
|
||||||
|
|
||||||
|
// Menubar and toolbar entries
|
||||||
|
GtkActionEntry entries[] = {
|
||||||
|
{"ThemeMenu", NULL, _("Theme"), NULL, NULL, NULL},
|
||||||
|
{"ThemeAdd", GTK_STOCK_ADD, _("_Import theme..."), "<Control>N", _("Import theme"), G_CALLBACK(menuImport)},
|
||||||
|
{"ThemeDefault", GTK_STOCK_NEW, _("_Import default theme..."), NULL, _("Import default theme"), G_CALLBACK(menuImportDefault)},
|
||||||
|
{"ThemeSaveAs", GTK_STOCK_SAVE_AS, _("_Save as..."), NULL, _("Save theme as"), G_CALLBACK(menuSaveAs)},
|
||||||
|
{"ThemeDelete", GTK_STOCK_DELETE, _("_Delete"), NULL, _("Delete theme"), G_CALLBACK(menuDelete)},
|
||||||
|
{"ThemeProperties", GTK_STOCK_PROPERTIES, _("_Edit theme..."), NULL, _("Edit selected theme"), G_CALLBACK(edit_current_theme)},
|
||||||
|
{"ThemeQuit", GTK_STOCK_QUIT, _("_Quit"), "<control>Q", _("Quit"), G_CALLBACK(gtk_main_quit)},
|
||||||
|
{"EditMenu", NULL, _("Edit"), NULL, NULL, NULL},
|
||||||
|
{"EditRefresh", GTK_STOCK_REFRESH, _("Refresh"), NULL, _("Refresh"), G_CALLBACK(refresh_current_theme)},
|
||||||
|
{"EditRefreshAll", GTK_STOCK_REFRESH, _("Refresh all"), NULL, _("Refresh all"), G_CALLBACK(load_all_themes)},
|
||||||
|
{"HelpMenu", NULL, _("Help"), NULL, NULL, NULL},
|
||||||
|
{"HelpAbout", GTK_STOCK_ABOUT, _("_About"), "<Control>A", _("About"), G_CALLBACK(menuAbout)}
|
||||||
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <glib/gi18n-lib.h>
|
#include <glib/gi18n-lib.h>
|
||||||
#else
|
#else
|
||||||
#define _(String) String
|
#define _(String) String
|
||||||
|
#define GETTEXT_PACKAGE "tint2conf"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SNAPSHOT_TICK 190
|
#define SNAPSHOT_TICK 190
|
||||||
|
|||||||
20
src/tint2conf/po/CMakeLists.txt
Normal file
20
src/tint2conf/po/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
include(FindGettext)
|
||||||
|
if (GETTEXT_FOUND)
|
||||||
|
set(GETTEXT_PACKAGE tint2conf)
|
||||||
|
file(GLOB POTFILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.po")
|
||||||
|
string(REPLACE ".po" " " LANGUAGES ${POTFILES})
|
||||||
|
message(STATUS "gettext found languages: ${LANGUAGES}")
|
||||||
|
string(REPLACE " " ";" LANGUAGES ${LANGUAGES})
|
||||||
|
if ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_LESS "2.8.8")
|
||||||
|
GETTEXT_CREATE_TRANSLATIONS("${CMAKE_CURRENT_SOURCE_DIR}/tint2conf.pot" ALL ${POTFILES})
|
||||||
|
else()
|
||||||
|
foreach(LANG ${LANGUAGES})
|
||||||
|
GETTEXT_PROCESS_PO_FILES(${LANG} ALL PO_FILES ${LANG}.po)
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/${DATADIR}/locale/${LANG}/LC_MESSAGES"
|
||||||
|
RENAME "${GETTEXT_PACKAGE}.mo")
|
||||||
|
endforeach ()
|
||||||
|
endif()
|
||||||
|
else ()
|
||||||
|
message(STATUS "gettext not found")
|
||||||
|
endif ()
|
||||||
1588
src/tint2conf/po/fr.po
Normal file
1588
src/tint2conf/po/fr.po
Normal file
File diff suppressed because it is too large
Load Diff
1834
src/tint2conf/po/pl.po
Normal file
1834
src/tint2conf/po/pl.po
Normal file
File diff suppressed because it is too large
Load Diff
1607
src/tint2conf/po/tint2conf.pot
Normal file
1607
src/tint2conf/po/tint2conf.pot
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -51,7 +51,7 @@ extern GtkWidget *taskbar_hide_inactive_tasks, *taskbar_hide_diff_monitor;
|
|||||||
extern GtkWidget *taskbar_name_padding_x, *taskbar_name_padding_y, *taskbar_name_inactive_color, *taskbar_name_active_color, *taskbar_name_font;
|
extern GtkWidget *taskbar_name_padding_x, *taskbar_name_padding_y, *taskbar_name_inactive_color, *taskbar_name_active_color, *taskbar_name_font;
|
||||||
extern GtkWidget *taskbar_active_background, *taskbar_inactive_background;
|
extern GtkWidget *taskbar_active_background, *taskbar_inactive_background;
|
||||||
extern GtkWidget *taskbar_name_active_background, *taskbar_name_inactive_background;
|
extern GtkWidget *taskbar_name_active_background, *taskbar_name_inactive_background;
|
||||||
extern GtkWidget *taskbar_distribute_size, *taskbar_sort_order;
|
extern GtkWidget *taskbar_distribute_size, *taskbar_sort_order, *taskbar_alignment;
|
||||||
|
|
||||||
// task
|
// task
|
||||||
extern GtkWidget *task_mouse_left, *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;
|
||||||
|
|||||||
@@ -272,6 +272,16 @@ void config_write_taskbar(FILE *fp)
|
|||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
|
fprintf(fp, "task_align = ");
|
||||||
|
if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_alignment)) <= 0) {
|
||||||
|
fprintf(fp, "left");
|
||||||
|
} else if (gtk_combo_box_get_active(GTK_COMBO_BOX(taskbar_alignment)) == 1) {
|
||||||
|
fprintf(fp, "center");
|
||||||
|
} else {
|
||||||
|
fprintf(fp, "right");
|
||||||
|
}
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -998,6 +1008,16 @@ void add_entry(char *key, char *value)
|
|||||||
else
|
else
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(key, "task_align") == 0) {
|
||||||
|
if (strcmp(value, "left") == 0)
|
||||||
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
||||||
|
else if (strcmp(value, "center") == 0)
|
||||||
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 1);
|
||||||
|
else if (strcmp(value, "right") == 0)
|
||||||
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 2);
|
||||||
|
else
|
||||||
|
gtk_combo_box_set_active(GTK_COMBO_BOX(taskbar_sort_order), 0);
|
||||||
|
}
|
||||||
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);
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(taskbar_padding_x), atoi(value1));
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(taskbar_padding_x), atoi(value1));
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ Name[nb]=Panelbehandler
|
|||||||
Name[nl]=Paneel Manager
|
Name[nl]=Paneel Manager
|
||||||
Name[nn]=Panelhandsamar
|
Name[nn]=Panelhandsamar
|
||||||
Name[pa]=ਪੈਨਲ ਮੈਨੇਜਰ
|
Name[pa]=ਪੈਨਲ ਮੈਨੇਜਰ
|
||||||
Name[pl]=Panel
|
Name[pl]=Ustawienia panelu
|
||||||
Name[pt]=Gestor do Painel
|
Name[pt]=Gestor do Painel
|
||||||
Name[pt_BR]=Gerenciador do painel
|
Name[pt_BR]=Gerenciador do painel
|
||||||
Name[ro]=Manager de panouri
|
Name[ro]=Manager de panouri
|
||||||
|
|||||||
133
src/util/area.c
133
src/util/area.c
@@ -76,7 +76,7 @@ void init_rendering(void *obj, int pos)
|
|||||||
Area *a = (Area*)obj;
|
Area *a = (Area*)obj;
|
||||||
|
|
||||||
// initialize fixed position/size
|
// initialize fixed position/size
|
||||||
GSList *l;
|
GList *l;
|
||||||
for (l = a->list; l ; l = l->next) {
|
for (l = a->list; l ; l = l->next) {
|
||||||
Area *child = ((Area*)l->data);
|
Area *child = ((Area*)l->data);
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
@@ -102,7 +102,7 @@ void rendering(void *obj)
|
|||||||
Panel *panel = (Panel*)obj;
|
Panel *panel = (Panel*)obj;
|
||||||
|
|
||||||
size_by_content(&panel->area);
|
size_by_content(&panel->area);
|
||||||
size_by_layout(&panel->area, 0, 1);
|
size_by_layout(&panel->area, 1);
|
||||||
|
|
||||||
refresh(&panel->area);
|
refresh(&panel->area);
|
||||||
}
|
}
|
||||||
@@ -111,10 +111,11 @@ void rendering(void *obj)
|
|||||||
void size_by_content (Area *a)
|
void size_by_content (Area *a)
|
||||||
{
|
{
|
||||||
// don't resize hiden objects
|
// don't resize hiden objects
|
||||||
if (!a->on_screen) return;
|
if (!a->on_screen)
|
||||||
|
return;
|
||||||
|
|
||||||
// children node are resized before its parent
|
// children node are resized before its parent
|
||||||
GSList *l;
|
GList *l;
|
||||||
for (l = a->list; l ; l = l->next)
|
for (l = a->list; l ; l = l->next)
|
||||||
size_by_content(l->data);
|
size_by_content(l->data);
|
||||||
|
|
||||||
@@ -134,14 +135,15 @@ void size_by_content (Area *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void size_by_layout (Area *a, int pos, int level)
|
void size_by_layout (Area *a, int level)
|
||||||
{
|
{
|
||||||
// don't resize hiden objects
|
// don't resize hiden objects
|
||||||
if (!a->on_screen) return;
|
if (!a->on_screen)
|
||||||
|
return;
|
||||||
|
|
||||||
// parent node is resized before its children
|
// parent node is resized before its children
|
||||||
// calculate area's size
|
// calculate area's size
|
||||||
GSList *l;
|
GList *l;
|
||||||
if (a->resize && a->size_mode == SIZE_BY_LAYOUT) {
|
if (a->resize && a->size_mode == SIZE_BY_LAYOUT) {
|
||||||
a->resize = 0;
|
a->resize = 0;
|
||||||
|
|
||||||
@@ -156,13 +158,15 @@ void size_by_layout (Area *a, int pos, int level)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update position of childs
|
// update position of children
|
||||||
pos += a->paddingxlr + a->bg->border.width;
|
if (a->list) {
|
||||||
int i=0;
|
if (a->alignment == ALIGN_LEFT) {
|
||||||
|
int pos = (panel_horizontal ? a->posx : a->posy) + a->bg->border.width + a->paddingxlr;
|
||||||
|
|
||||||
for (l = a->list; l ; l = l->next) {
|
for (l = a->list; l ; l = l->next) {
|
||||||
Area *child = ((Area*)l->data);
|
Area *child = ((Area*)l->data);
|
||||||
if (!child->on_screen) continue;
|
if (!child->on_screen)
|
||||||
i++;
|
continue;
|
||||||
|
|
||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
if (pos != child->posx) {
|
if (pos != child->posx) {
|
||||||
@@ -170,8 +174,7 @@ void size_by_layout (Area *a, int pos, int level)
|
|||||||
child->posx = pos;
|
child->posx = pos;
|
||||||
child->on_changed = 1;
|
child->on_changed = 1;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (pos != child->posy) {
|
if (pos != child->posy) {
|
||||||
// pos changed => redraw
|
// pos changed => redraw
|
||||||
child->posy = pos;
|
child->posy = pos;
|
||||||
@@ -179,16 +182,78 @@ void size_by_layout (Area *a, int pos, int level)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*// position of each visible object
|
size_by_layout(child, level+1);
|
||||||
int k;
|
|
||||||
for (k=0 ; k < level ; k++) printf(" ");
|
|
||||||
printf("tree level %d, object %d, pos %d, %s\n", level, i, pos, (child->size_mode == SIZE_BY_LAYOUT) ? "SIZE_BY_LAYOUT" : "SIZE_BY_CONTENT");*/
|
|
||||||
size_by_layout(child, pos, level+1);
|
|
||||||
|
|
||||||
if (panel_horizontal)
|
pos += panel_horizontal ? child->width + a->paddingx : child->height + a->paddingx;
|
||||||
pos += child->width + a->paddingx;
|
}
|
||||||
else
|
} else if (a->alignment == ALIGN_RIGHT) {
|
||||||
pos += child->height + a->paddingx;
|
int pos = (panel_horizontal ? a->posx + a->width : a->posy + a->height) - a->bg->border.width - a->paddingxlr;
|
||||||
|
|
||||||
|
for (l = g_list_last(a->list); l ; l = l->prev) {
|
||||||
|
Area *child = ((Area*)l->data);
|
||||||
|
if (!child->on_screen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pos -= panel_horizontal ? child->width : child->height;
|
||||||
|
|
||||||
|
if (panel_horizontal) {
|
||||||
|
if (pos != child->posx) {
|
||||||
|
// pos changed => redraw
|
||||||
|
child->posx = pos;
|
||||||
|
child->on_changed = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pos != child->posy) {
|
||||||
|
// pos changed => redraw
|
||||||
|
child->posy = pos;
|
||||||
|
child->on_changed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_by_layout(child, level+1);
|
||||||
|
|
||||||
|
pos -= a->paddingx;
|
||||||
|
}
|
||||||
|
} else if (a->alignment == ALIGN_CENTER) {
|
||||||
|
|
||||||
|
int children_size = 0;
|
||||||
|
|
||||||
|
for (l = a->list; l ; l = l->next) {
|
||||||
|
Area *child = ((Area*)l->data);
|
||||||
|
if (!child->on_screen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
children_size += panel_horizontal ? child->width : child->height;
|
||||||
|
children_size += (l == a->list) ? 0 : a->paddingx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = (panel_horizontal ? a->posx : a->posy) + a->bg->border.width + a->paddingxlr;
|
||||||
|
pos += ((panel_horizontal ? a->width : a->height) - children_size) / 2;
|
||||||
|
|
||||||
|
for (l = a->list; l ; l = l->next) {
|
||||||
|
Area *child = ((Area*)l->data);
|
||||||
|
if (!child->on_screen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (panel_horizontal) {
|
||||||
|
if (pos != child->posx) {
|
||||||
|
// pos changed => redraw
|
||||||
|
child->posx = pos;
|
||||||
|
child->on_changed = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pos != child->posy) {
|
||||||
|
// pos changed => redraw
|
||||||
|
child->posy = pos;
|
||||||
|
child->on_changed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_by_layout(child, level+1);
|
||||||
|
|
||||||
|
pos += panel_horizontal ? child->width + a->paddingx : child->height + a->paddingx;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a->on_changed) {
|
if (a->on_changed) {
|
||||||
@@ -209,7 +274,7 @@ void refresh (Area *a)
|
|||||||
if (a->redraw) {
|
if (a->redraw) {
|
||||||
a->redraw = 0;
|
a->redraw = 0;
|
||||||
// force redraw of child
|
// force redraw of child
|
||||||
//GSList *l;
|
//GList *l;
|
||||||
//for (l = a->list ; l ; l = l->next)
|
//for (l = a->list ; l ; l = l->next)
|
||||||
//((Area*)l->data)->redraw = 1;
|
//((Area*)l->data)->redraw = 1;
|
||||||
|
|
||||||
@@ -222,7 +287,7 @@ void refresh (Area *a)
|
|||||||
XCopyArea (server.dsp, a->pix, ((Panel *)a->panel)->temp_pmap, server.gc, 0, 0, a->width, a->height, a->posx, a->posy);
|
XCopyArea (server.dsp, a->pix, ((Panel *)a->panel)->temp_pmap, server.gc, 0, 0, a->width, a->height, a->posx, a->posy);
|
||||||
|
|
||||||
// and then refresh child object
|
// and then refresh child object
|
||||||
GSList *l;
|
GList *l;
|
||||||
for (l = a->list; l ; l = l->next)
|
for (l = a->list; l ; l = l->next)
|
||||||
refresh(l->data);
|
refresh(l->data);
|
||||||
}
|
}
|
||||||
@@ -236,7 +301,7 @@ int resize_by_layout(void *obj, int maximum_size)
|
|||||||
if (panel_horizontal) {
|
if (panel_horizontal) {
|
||||||
// detect free size for SIZE_BY_LAYOUT's Area
|
// detect free size for SIZE_BY_LAYOUT's Area
|
||||||
size = a->width - (2 * (a->paddingxlr + a->bg->border.width));
|
size = a->width - (2 * (a->paddingxlr + a->bg->border.width));
|
||||||
GSList *l;
|
GList *l;
|
||||||
for (l = a->list ; l ; l = l->next) {
|
for (l = a->list ; l ; l = l->next) {
|
||||||
child = (Area*)l->data;
|
child = (Area*)l->data;
|
||||||
if (child->on_screen && child->size_mode == SIZE_BY_CONTENT) {
|
if (child->on_screen && child->size_mode == SIZE_BY_CONTENT) {
|
||||||
@@ -278,7 +343,7 @@ int resize_by_layout(void *obj, int maximum_size)
|
|||||||
else {
|
else {
|
||||||
// detect free size for SIZE_BY_LAYOUT's Area
|
// detect free size for SIZE_BY_LAYOUT's Area
|
||||||
size = a->height - (2 * (a->paddingxlr + a->bg->border.width));
|
size = a->height - (2 * (a->paddingxlr + a->bg->border.width));
|
||||||
GSList *l;
|
GList *l;
|
||||||
for (l = a->list ; l ; l = l->next) {
|
for (l = a->list ; l ; l = l->next) {
|
||||||
child = (Area*)l->data;
|
child = (Area*)l->data;
|
||||||
if (child->on_screen && child->size_mode == SIZE_BY_CONTENT) {
|
if (child->on_screen && child->size_mode == SIZE_BY_CONTENT) {
|
||||||
@@ -291,7 +356,7 @@ int resize_by_layout(void *obj, int maximum_size)
|
|||||||
if (nb_by_content+nb_by_layout)
|
if (nb_by_content+nb_by_layout)
|
||||||
size -= ((nb_by_content+nb_by_layout-1) * a->paddingx);
|
size -= ((nb_by_content+nb_by_layout-1) * a->paddingx);
|
||||||
|
|
||||||
int height=0, modulo=0, old_height;
|
int height=0, modulo=0;
|
||||||
if (nb_by_layout) {
|
if (nb_by_layout) {
|
||||||
height = size / nb_by_layout;
|
height = size / nb_by_layout;
|
||||||
modulo = size % nb_by_layout;
|
modulo = size % nb_by_layout;
|
||||||
@@ -305,7 +370,7 @@ int resize_by_layout(void *obj, int maximum_size)
|
|||||||
for (l = a->list ; l ; l = l->next) {
|
for (l = a->list ; l ; l = l->next) {
|
||||||
child = (Area*)l->data;
|
child = (Area*)l->data;
|
||||||
if (child->on_screen && child->size_mode == SIZE_BY_LAYOUT) {
|
if (child->on_screen && child->size_mode == SIZE_BY_LAYOUT) {
|
||||||
old_height = child->height;
|
int old_height = child->height;
|
||||||
child->height = height;
|
child->height = height;
|
||||||
if (modulo) {
|
if (modulo) {
|
||||||
child->height++;
|
child->height++;
|
||||||
@@ -324,7 +389,7 @@ void set_redraw (Area *a)
|
|||||||
{
|
{
|
||||||
a->redraw = 1;
|
a->redraw = 1;
|
||||||
|
|
||||||
GSList *l;
|
GList *l;
|
||||||
for (l = a->list ; l ; l = l->next)
|
for (l = a->list ; l ; l = l->next)
|
||||||
set_redraw(l->data);
|
set_redraw(l->data);
|
||||||
}
|
}
|
||||||
@@ -438,7 +503,7 @@ void remove_area (Area *a)
|
|||||||
{
|
{
|
||||||
Area *parent = (Area*)a->parent;
|
Area *parent = (Area*)a->parent;
|
||||||
|
|
||||||
parent->list = g_slist_remove(parent->list, a);
|
parent->list = g_list_remove(parent->list, a);
|
||||||
set_redraw (parent);
|
set_redraw (parent);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -448,7 +513,7 @@ void add_area (Area *a)
|
|||||||
{
|
{
|
||||||
Area *parent = (Area*)a->parent;
|
Area *parent = (Area*)a->parent;
|
||||||
|
|
||||||
parent->list = g_slist_append(parent->list, a);
|
parent->list = g_list_append(parent->list, a);
|
||||||
set_redraw (parent);
|
set_redraw (parent);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -459,12 +524,12 @@ void free_area (Area *a)
|
|||||||
if (!a)
|
if (!a)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GSList *l0;
|
GList *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);
|
||||||
|
|
||||||
if (a->list) {
|
if (a->list) {
|
||||||
g_slist_free(a->list);
|
g_list_free(a->list);
|
||||||
a->list = 0;
|
a->list = 0;
|
||||||
}
|
}
|
||||||
if (a->pix) {
|
if (a->pix) {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ typedef struct
|
|||||||
// SIZE_BY_LAYOUT objects : taskbar and task
|
// SIZE_BY_LAYOUT objects : taskbar and task
|
||||||
// SIZE_BY_CONTENT objects : clock, battery, launcher, systray
|
// SIZE_BY_CONTENT objects : clock, battery, launcher, systray
|
||||||
enum { SIZE_BY_LAYOUT, SIZE_BY_CONTENT };
|
enum { SIZE_BY_LAYOUT, SIZE_BY_CONTENT };
|
||||||
|
enum { ALIGN_LEFT = 0, ALIGN_CENTER = 1, ALIGN_RIGHT = 2 };
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// coordinate relative to panel window
|
// coordinate relative to panel window
|
||||||
@@ -61,13 +62,15 @@ typedef struct {
|
|||||||
Background *bg;
|
Background *bg;
|
||||||
|
|
||||||
// list of child : Area object
|
// list of child : Area object
|
||||||
GSList *list;
|
GList *list;
|
||||||
|
|
||||||
// object visible on screen.
|
// object visible on screen.
|
||||||
// An object (like systray) could be enabled but hidden (because no tray icon).
|
// An object (like systray) could be enabled but hidden (because no tray icon).
|
||||||
int on_screen;
|
int on_screen;
|
||||||
// way to calculate the size (SIZE_BY_CONTENT or SIZE_BY_LAYOUT)
|
// way to calculate the size (SIZE_BY_CONTENT or SIZE_BY_LAYOUT)
|
||||||
int size_mode;
|
int size_mode;
|
||||||
|
|
||||||
|
int alignment;
|
||||||
// need to calculate position and width
|
// need to calculate position and width
|
||||||
int resize;
|
int resize;
|
||||||
// need redraw Pixmap
|
// need redraw Pixmap
|
||||||
@@ -96,7 +99,7 @@ void init_rendering(void *obj, int pos);
|
|||||||
|
|
||||||
void rendering(void *obj);
|
void rendering(void *obj);
|
||||||
void size_by_content (Area *a);
|
void size_by_content (Area *a);
|
||||||
void size_by_layout (Area *a, int pos, int level);
|
void size_by_layout (Area *a, int level);
|
||||||
// draw background and foreground
|
// draw background and foreground
|
||||||
void refresh (Area *a);
|
void refresh (Area *a);
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,7 @@ struct _timeout {
|
|||||||
|
|
||||||
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);
|
||||||
gint compare_timeouts(gconstpointer t1, gconstpointer t2);
|
gint compare_timeouts(gconstpointer t1, gconstpointer t2);
|
||||||
gint compare_timespecs(const struct timespec* t1, const struct timespec* t2);
|
|
||||||
int timespec_subtract(struct timespec* result, struct timespec* x, struct timespec* y);
|
int timespec_subtract(struct timespec* result, struct timespec* x, struct timespec* y);
|
||||||
struct timespec add_msec_to_timespec(struct timespec ts, int msec);
|
|
||||||
|
|
||||||
|
|
||||||
int align_with_existing_timeouts(timeout* t);
|
int align_with_existing_timeouts(timeout* t);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#define TIMER_H
|
#define TIMER_H
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
extern struct timeval next_timeout;
|
extern struct timeval next_timeout;
|
||||||
|
|
||||||
@@ -66,4 +68,9 @@ void update_next_timeout();
|
|||||||
/** Callback of all expired timeouts **/
|
/** Callback of all expired timeouts **/
|
||||||
void callback_timeout_expired();
|
void callback_timeout_expired();
|
||||||
|
|
||||||
|
/** Returns -1 if t1 < t2, 0 if t1 == t2, 1 if t1 > t2 **/
|
||||||
|
gint compare_timespecs(const struct timespec* t1, const struct timespec* t2);
|
||||||
|
|
||||||
|
struct timespec add_msec_to_timespec(struct timespec ts, int msec);
|
||||||
|
|
||||||
#endif // TIMER_H
|
#endif // TIMER_H
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ Name[zh_CN]=面板 tint2
|
|||||||
Name[zh_TW]=面板 tint2
|
Name[zh_TW]=面板 tint2
|
||||||
Comment=Lightweight panel
|
Comment=Lightweight panel
|
||||||
Comment[fr_FR]=Panel léger
|
Comment[fr_FR]=Panel léger
|
||||||
|
Comment[pl]=Lekki panel
|
||||||
Exec=tint2
|
Exec=tint2
|
||||||
Icon=taskbar
|
Icon=taskbar
|
||||||
Terminal=false
|
Terminal=false
|
||||||
|
|||||||
Reference in New Issue
Block a user