Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84c58ce9af | ||
|
|
184703998b | ||
|
|
e345c0ddcd | ||
|
|
c874e76343 | ||
|
|
687f5f2a1b | ||
|
|
c7aa70f078 | ||
|
|
690fe3f4d8 | ||
|
|
c1d0a42bed | ||
|
|
e5cd73f4a7 | ||
|
|
7ffc220891 | ||
|
|
2799fe9346 | ||
|
|
e2023b7172 | ||
|
|
9224971407 | ||
|
|
d492f80468 | ||
|
|
78bc330448 | ||
|
|
3805adc9f3 | ||
|
|
4e3989f9f5 | ||
|
|
9624b5d558 | ||
|
|
754d9187df | ||
|
|
a4996c9d3e | ||
|
|
b99c5c204b | ||
|
|
7162c5dea1 | ||
|
|
e3939a56e1 | ||
|
|
ceafe9b281 | ||
|
|
263d1ab15f | ||
|
|
e76202b355 | ||
|
|
f68eabcf35 | ||
|
|
e218b3fa96 | ||
|
|
50e21b4077 | ||
|
|
b6a1a1c0f6 | ||
|
|
15e12142ca | ||
|
|
b8c1c29df2 | ||
|
|
4a1880ead0 | ||
|
|
57b878d5e4 | ||
|
|
46aab61bf6 | ||
|
|
227dc8e48a | ||
|
|
68c3205b53 | ||
|
|
61f0a4ec85 | ||
|
|
c606a1a35a | ||
|
|
9933399dc4 | ||
|
|
5ce8023ef7 | ||
|
|
6438c75faf | ||
|
|
712097ba45 | ||
|
|
9a5cb749ed | ||
|
|
d730f23027 | ||
|
|
9f161f2baf | ||
|
|
2570ae2cf6 | ||
|
|
8d5c2d8cbb | ||
|
|
28bf0a437c | ||
|
|
fd78e6d886 | ||
|
|
e84d963ab6 | ||
|
|
c4fbc2962e | ||
|
|
a0af851d9d |
2
AUTHORS
2
AUTHORS
@@ -22,5 +22,5 @@ Contributors:
|
||||
Marcelo Vianna : taskbar sorting
|
||||
Xico Atelo : startup notifications
|
||||
Craig Oakes : WM flags, issue tracker organization
|
||||
|
||||
Jeff Blake (https://gitlab.com/u/berkley4) : more mouse event handlers
|
||||
|
||||
|
||||
18
ChangeLog
18
ChangeLog
@@ -1,4 +1,20 @@
|
||||
2015-07-12 master
|
||||
2015-08-01 0.12.1
|
||||
- Fixes:
|
||||
- Config:
|
||||
- Read config correctly when panel_items is at the end of the config file (issue #511)
|
||||
- Panel:
|
||||
- Do not use nested event loops (related: issue #509)
|
||||
- System tray:
|
||||
- Set _NET_SYSTEM_TRAY_ICON_SIZE and _NET_SYSTEM_TRAY_PADDING
|
||||
- Throttle repeated resizes (workaround for issue #509)
|
||||
- Taskbar:
|
||||
- Use consistent visibility for sticky (all desktop) windows (related: issue #279)
|
||||
- Compute monitor correctly for windows when Openbox animations are enabled (issue #511)
|
||||
- tint2conf:
|
||||
- Bad read of option panel_margin
|
||||
- New config options:
|
||||
- Battery mouse actions and clock middle click and wheel actions (thanks to Jeff Blake)
|
||||
2015-07-12 0.12
|
||||
- Note: the changes listed here are based on the previous release tint2 0.11, however some distributions (e.g. Debian)
|
||||
offered packages using newer commits and/or patches; thus from the user's perspective some of these features are
|
||||
already present. They are marked with '(already released by distros)'.
|
||||
|
||||
16
README.md
16
README.md
@@ -1,15 +1,13 @@
|
||||
### New stable release: 0.12
|
||||
### New stable release: 0.12.1
|
||||
Changes: https://gitlab.com/o9000/tint2/blob/master/ChangeLog
|
||||
|
||||
Documentation: https://gitlab.com/o9000/tint2/wikis/home
|
||||
|
||||
Try it out with (see also [dependencies](https://gitlab.com/o9000/tint2/wikis/Install#dependencies)):
|
||||
```
|
||||
mkdir tint2-0.12
|
||||
cd tint2-0.12
|
||||
wget 'https://gitlab.com/o9000/tint2/repository/archive.tar.gz?ref=v0.12' --output-document tint2-0.12.tar.gz
|
||||
tar -xzf tint2-0.12.tar.gz
|
||||
cd tint2.git
|
||||
git clone https://gitlab.com/o9000/tint2.git
|
||||
cd tint2
|
||||
git checkout v0.12.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
@@ -25,6 +23,9 @@ make install
|
||||
|
||||
Please report any problems to https://gitlab.com/o9000/tint2/issues. Your feedback is much appreciated.
|
||||
|
||||
Known issues:
|
||||
* [System tray resize loop with GTK applications](https://gitlab.com/o9000/tint2/issues/509), see also the [GTK bug report](https://bugzilla.gnome.org/show_bug.cgi?id=710375). Fix landed in 0.12.1, if there are still problems please let me know.
|
||||
|
||||
P.S. GitLab is now the official location of the tint2 project, migrated from Google Code, which is shutting down. In case you are wondering why not GitHub, BitBucket etc., we chose GitLab because it is open source, it is mature and works well, looks cool and has a very nice team.
|
||||
|
||||
### What is tint2?
|
||||
@@ -70,8 +71,7 @@ tint2 is a simple panel/taskbar made for modern X window managers. It was specif
|
||||
* Old project location (inactive): https://code.google.com/p/tint2
|
||||
|
||||
### Releases
|
||||
* Latest stable release: tint2 0.11 (June 2010)
|
||||
* Next release: planned for mid 2015
|
||||
* Latest stable release: tint2 0.12 (July 2015)
|
||||
|
||||
### Screenshots
|
||||

|
||||
@@ -56,6 +56,11 @@ static char buf_bat_time[20];
|
||||
int8_t battery_low_status;
|
||||
unsigned char battery_low_cmd_sent;
|
||||
char *battery_low_cmd;
|
||||
char *battery_lclick_command;
|
||||
char *battery_mclick_command;
|
||||
char *battery_rclick_command;
|
||||
char *battery_uwheel_command;
|
||||
char *battery_dwheel_command;
|
||||
gchar *path_energy_now;
|
||||
gchar *path_energy_full;
|
||||
gchar *path_current_now;
|
||||
@@ -141,6 +146,11 @@ void default_battery()
|
||||
bat1_font_desc = NULL;
|
||||
bat2_font_desc = NULL;
|
||||
battery_low_cmd = NULL;
|
||||
battery_lclick_command = NULL;
|
||||
battery_mclick_command = NULL;
|
||||
battery_rclick_command = NULL;
|
||||
battery_uwheel_command = NULL;
|
||||
battery_dwheel_command = NULL;
|
||||
path_energy_now = NULL;
|
||||
path_energy_full = NULL;
|
||||
path_current_now = NULL;
|
||||
@@ -171,6 +181,16 @@ void cleanup_battery()
|
||||
path_status = NULL;
|
||||
free(battery_low_cmd);
|
||||
battery_low_cmd = NULL;
|
||||
free(battery_lclick_command);
|
||||
battery_lclick_command = NULL;
|
||||
free(battery_mclick_command);
|
||||
battery_mclick_command = NULL;
|
||||
free(battery_rclick_command);
|
||||
battery_rclick_command = NULL;
|
||||
free(battery_uwheel_command);
|
||||
battery_uwheel_command = NULL;
|
||||
free(battery_dwheel_command);
|
||||
battery_dwheel_command = NULL;
|
||||
stop_timeout(battery_timeout);
|
||||
battery_timeout = NULL;
|
||||
battery_found = 0;
|
||||
@@ -574,3 +594,26 @@ int resize_battery(void *obj)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void battery_action(int button)
|
||||
{
|
||||
char *command = 0;
|
||||
switch (button) {
|
||||
case 1:
|
||||
command = battery_lclick_command;
|
||||
break;
|
||||
case 2:
|
||||
command = battery_mclick_command;
|
||||
break;
|
||||
case 3:
|
||||
command = battery_rclick_command;
|
||||
break;
|
||||
case 4:
|
||||
command = battery_uwheel_command;
|
||||
break;
|
||||
case 5:
|
||||
command = battery_dwheel_command;
|
||||
break;
|
||||
}
|
||||
tint_exec(command);
|
||||
}
|
||||
@@ -56,6 +56,12 @@ extern int percentage_hide;
|
||||
extern int8_t battery_low_status;
|
||||
extern char *battery_low_cmd;
|
||||
|
||||
extern char *battery_lclick_command;
|
||||
extern char *battery_mclick_command;
|
||||
extern char *battery_rclick_command;
|
||||
extern char *battery_uwheel_command;
|
||||
extern char *battery_dwheel_command;
|
||||
|
||||
// default global data
|
||||
void default_battery();
|
||||
|
||||
@@ -71,4 +77,6 @@ void draw_battery(void *obj, cairo_t *c);
|
||||
|
||||
int resize_battery(void *obj);
|
||||
|
||||
void battery_action(int button);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,7 +39,10 @@ char *time2_timezone;
|
||||
char *time_tooltip_format;
|
||||
char *time_tooltip_timezone;
|
||||
char *clock_lclick_command;
|
||||
char *clock_mclick_command;
|
||||
char *clock_rclick_command;
|
||||
char *clock_uwheel_command;
|
||||
char *clock_dwheel_command;
|
||||
struct timeval time_clock;
|
||||
PangoFontDescription *time1_font_desc;
|
||||
PangoFontDescription *time2_font_desc;
|
||||
@@ -61,7 +64,10 @@ void default_clock()
|
||||
time_tooltip_format = NULL;
|
||||
time_tooltip_timezone = NULL;
|
||||
clock_lclick_command = NULL;
|
||||
clock_mclick_command = NULL;
|
||||
clock_rclick_command = NULL;
|
||||
clock_uwheel_command = NULL;
|
||||
clock_dwheel_command = NULL;
|
||||
time1_font_desc = NULL;
|
||||
time2_font_desc = NULL;
|
||||
}
|
||||
@@ -86,8 +92,14 @@ void cleanup_clock()
|
||||
time_tooltip_timezone = NULL;
|
||||
free(clock_lclick_command);
|
||||
clock_lclick_command = NULL;
|
||||
free(clock_mclick_command);
|
||||
clock_mclick_command = NULL;
|
||||
free(clock_rclick_command);
|
||||
clock_rclick_command = NULL;
|
||||
free(clock_uwheel_command);
|
||||
clock_uwheel_command = NULL;
|
||||
free(clock_dwheel_command);
|
||||
clock_dwheel_command = NULL;
|
||||
stop_timeout(clock_timeout);
|
||||
clock_timeout = NULL;
|
||||
}
|
||||
@@ -277,9 +289,18 @@ void clock_action(int button)
|
||||
case 1:
|
||||
command = clock_lclick_command;
|
||||
break;
|
||||
case 2:
|
||||
command = clock_mclick_command;
|
||||
break;
|
||||
case 3:
|
||||
command = clock_rclick_command;
|
||||
break;
|
||||
case 4:
|
||||
command = clock_uwheel_command;
|
||||
break;
|
||||
case 5:
|
||||
command = clock_dwheel_command;
|
||||
break;
|
||||
}
|
||||
tint_exec(command);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,10 @@ extern char *time_tooltip_timezone;
|
||||
extern PangoFontDescription *time1_font_desc;
|
||||
extern PangoFontDescription *time2_font_desc;
|
||||
extern char *clock_lclick_command;
|
||||
extern char *clock_mclick_command;
|
||||
extern char *clock_rclick_command;
|
||||
extern char *clock_uwheel_command;
|
||||
extern char *clock_dwheel_command;
|
||||
extern int clock_enabled;
|
||||
|
||||
|
||||
|
||||
49
src/config.c
49
src/config.c
@@ -258,6 +258,13 @@ void add_entry (char *key, char *value)
|
||||
new_config_file = 1;
|
||||
panel_items_order = strdup(value);
|
||||
int j;
|
||||
systray_enabled = 0;
|
||||
launcher_enabled = 0;
|
||||
#ifdef ENABLE_BATTERY
|
||||
battery_enabled = 0;
|
||||
#endif
|
||||
clock_enabled = 0;
|
||||
taskbar_enabled = 0;
|
||||
for (j=0 ; j < strlen(panel_items_order) ; j++) {
|
||||
if (panel_items_order[j] == 'L')
|
||||
launcher_enabled = 1;
|
||||
@@ -349,6 +356,36 @@ void add_entry (char *key, char *value)
|
||||
battery_low_status = atoi(value);
|
||||
if(battery_low_status < 0 || battery_low_status > 100)
|
||||
battery_low_status = 0;
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(key, "battery_lclick_command") == 0) {
|
||||
#ifdef ENABLE_BATTERY
|
||||
if (strlen(value) > 0)
|
||||
battery_lclick_command = strdup(value);
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(key, "battery_mclick_command") == 0) {
|
||||
#ifdef ENABLE_BATTERY
|
||||
if (strlen(value) > 0)
|
||||
battery_mclick_command = strdup(value);
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(key, "battery_rclick_command") == 0) {
|
||||
#ifdef ENABLE_BATTERY
|
||||
if (strlen(value) > 0)
|
||||
battery_rclick_command = strdup(value);
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(key, "battery_uwheel_command") == 0) {
|
||||
#ifdef ENABLE_BATTERY
|
||||
if (strlen(value) > 0)
|
||||
battery_uwheel_command = strdup(value);
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(key, "battery_dwheel_command") == 0) {
|
||||
#ifdef ENABLE_BATTERY
|
||||
if (strlen(value) > 0)
|
||||
battery_dwheel_command = strdup(value);
|
||||
#endif
|
||||
}
|
||||
else if (strcmp (key, "battery_low_cmd") == 0) {
|
||||
@@ -463,10 +500,22 @@ void add_entry (char *key, char *value)
|
||||
if (strlen(value) > 0)
|
||||
clock_lclick_command = strdup(value);
|
||||
}
|
||||
else if (strcmp(key, "clock_mclick_command") == 0) {
|
||||
if (strlen(value) > 0)
|
||||
clock_mclick_command = strdup(value);
|
||||
}
|
||||
else if (strcmp(key, "clock_rclick_command") == 0) {
|
||||
if (strlen(value) > 0)
|
||||
clock_rclick_command = strdup(value);
|
||||
}
|
||||
else if (strcmp(key, "clock_uwheel_command") == 0) {
|
||||
if (strlen(value) > 0)
|
||||
clock_uwheel_command = strdup(value);
|
||||
}
|
||||
else if (strcmp(key, "clock_dwheel_command") == 0) {
|
||||
if (strlen(value) > 0)
|
||||
clock_dwheel_command = strdup(value);
|
||||
}
|
||||
|
||||
/* Taskbar */
|
||||
else if (strcmp (key, "taskbar_mode") == 0) {
|
||||
|
||||
@@ -359,13 +359,7 @@ void draw_launcher_icon(void *obj, cairo_t *c)
|
||||
|
||||
// Render
|
||||
imlib_context_set_image(launcherIcon->image);
|
||||
if (server.real_transparency) {
|
||||
render_image(launcherIcon->area.pix, 0, 0);
|
||||
} else {
|
||||
imlib_context_set_blend(1);
|
||||
imlib_context_set_drawable(launcherIcon->area.pix);
|
||||
imlib_render_image_on_drawable(0, 0);
|
||||
}
|
||||
render_image(launcherIcon->area.pix, 0, 0);
|
||||
}
|
||||
|
||||
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
|
||||
|
||||
16
src/panel.c
16
src/panel.c
@@ -796,6 +796,22 @@ int click_clock(Panel *panel, int x, int y)
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_BATTERY
|
||||
int click_battery(Panel *panel, int x, int y)
|
||||
{
|
||||
Battery bat = panel->battery;
|
||||
if (panel_horizontal) {
|
||||
if (bat.area.on_screen && x >= bat.area.posx && x <= (bat.area.posx + bat.area.width))
|
||||
return TRUE;
|
||||
} else {
|
||||
if (bat.area.on_screen && y >= bat.area.posy && y <= (bat.area.posy + bat.area.height))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Area* click_area(Panel *panel, int x, int y)
|
||||
{
|
||||
Area* result = &panel->area;
|
||||
|
||||
@@ -160,6 +160,11 @@ Launcher *click_launcher (Panel *panel, int x, int y);
|
||||
LauncherIcon *click_launcher_icon (Panel *panel, int x, int y);
|
||||
int click_padding(Panel *panel, int x, int y);
|
||||
int click_clock(Panel *panel, int x, int y);
|
||||
|
||||
#ifdef ENABLE_BATTERY
|
||||
int click_battery(Panel *panel, int x, int y);
|
||||
#endif
|
||||
|
||||
Area* click_area(Panel *panel, int x, int y);
|
||||
|
||||
void autohide_show(void* p);
|
||||
|
||||
16
src/server.c
16
src/server.c
@@ -96,6 +96,8 @@ void server_init_atoms ()
|
||||
server.atom.MANAGER = XInternAtom(server.dsp, "MANAGER", False);
|
||||
server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
|
||||
server.atom._NET_SYSTEM_TRAY_ORIENTATION = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_ORIENTATION", False);
|
||||
server.atom._NET_SYSTEM_TRAY_ICON_SIZE = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_ICON_SIZE", False);
|
||||
server.atom._NET_SYSTEM_TRAY_PADDING = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_PADDING", False);
|
||||
server.atom._XEMBED = XInternAtom(server.dsp, "_XEMBED", False);
|
||||
server.atom._XEMBED_INFO = XInternAtom(server.dsp, "_XEMBED_INFO", False);
|
||||
server.atom._NET_WM_PID = XInternAtom(server.dsp, "_NET_WM_PID", True);
|
||||
@@ -362,6 +364,20 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
void print_monitors()
|
||||
{
|
||||
fprintf(stderr, "Number of monitors: %d\n", server.nb_monitor);
|
||||
int i;
|
||||
for (i = 0; i < server.nb_monitor; i++) {
|
||||
fprintf(stderr, "Monitor %d: x = %d, y = %d, w = %d, h = %d\n",
|
||||
i+1,
|
||||
server.monitor[i].x,
|
||||
server.monitor[i].y,
|
||||
server.monitor[i].width,
|
||||
server.monitor[i].height);
|
||||
}
|
||||
}
|
||||
|
||||
int server_get_number_of_desktops()
|
||||
{
|
||||
return get_property32(server.root_win, server.atom._NET_NUMBER_OF_DESKTOPS, XA_CARDINAL);
|
||||
|
||||
@@ -71,6 +71,8 @@ typedef struct Global_atom
|
||||
Atom MANAGER;
|
||||
Atom _NET_SYSTEM_TRAY_MESSAGE_DATA;
|
||||
Atom _NET_SYSTEM_TRAY_ORIENTATION;
|
||||
Atom _NET_SYSTEM_TRAY_ICON_SIZE;
|
||||
Atom _NET_SYSTEM_TRAY_PADDING;
|
||||
Atom _XEMBED;
|
||||
Atom _XEMBED_INFO;
|
||||
Atom _NET_WM_PID;
|
||||
@@ -151,6 +153,7 @@ void get_root_pixmap();
|
||||
|
||||
// detect monitors and desktops
|
||||
void get_monitors();
|
||||
void print_monitors();
|
||||
void get_desktops();
|
||||
int server_get_number_of_desktops();
|
||||
|
||||
|
||||
@@ -58,9 +58,15 @@ static Pixmap render_background;
|
||||
|
||||
const int min_refresh_period = 50;
|
||||
const int max_fast_refreshes = 5;
|
||||
const int resize_period_threshold = 1000;
|
||||
const int fast_resize_period = 50;
|
||||
const int slow_resize_period = 5000;
|
||||
const int min_bad_resize_events = 3;
|
||||
const int max_bad_resize_events = 10;
|
||||
|
||||
void default_systray()
|
||||
{
|
||||
systray_enabled = 0;
|
||||
memset(&systray, 0, sizeof(Systraybar));
|
||||
render_background = 0;
|
||||
chrono = 0;
|
||||
@@ -100,30 +106,22 @@ void init_systray()
|
||||
systray.alpha = 100;
|
||||
systray.brightness = systray.saturation = 0;
|
||||
}
|
||||
|
||||
start_net();
|
||||
}
|
||||
|
||||
|
||||
void init_systray_panel(void *p)
|
||||
{
|
||||
systray.area.parent = p;
|
||||
systray.area.panel = p;
|
||||
Panel *panel = (Panel *)p;
|
||||
systray.area.parent = panel;
|
||||
systray.area.panel = panel;
|
||||
if (!systray.area.bg)
|
||||
systray.area.bg = &g_array_index(backgrounds, Background, 0);
|
||||
|
||||
GSList *l;
|
||||
int count = 0;
|
||||
for (l = systray.list_icons; l ; l = l->next) {
|
||||
if (((TrayWindow*)l->data)->hide)
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
if (count == 0)
|
||||
hide(&systray.area);
|
||||
else
|
||||
show(&systray.area);
|
||||
refresh_systray = 0;
|
||||
show(&systray.area);
|
||||
systray.area.resize = 1;
|
||||
systray.area.redraw = 1;
|
||||
panel->area.resize = 1;
|
||||
panel_refresh = 1;
|
||||
refresh_systray = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,13 +155,20 @@ int resize_systray(void *obj)
|
||||
sysbar->icon_size = sysbar->icon_size - (2 * sysbar->area.bg->border.width) - (2 * sysbar->area.paddingy);
|
||||
if (systray_max_icon_size > 0 && sysbar->icon_size > systray_max_icon_size)
|
||||
sysbar->icon_size = systray_max_icon_size;
|
||||
|
||||
if (systray.icon_size > 0) {
|
||||
long icon_size = systray.icon_size;
|
||||
XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_ICON_SIZE, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &icon_size, 1);
|
||||
}
|
||||
|
||||
count = 0;
|
||||
for (l = systray.list_icons; l ; l = l->next) {
|
||||
if (((TrayWindow*)l->data)->hide)
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
fprintf(stderr, BLUE "%s:%d number of icons = %d\n" RESET, __FUNCTION__, __LINE__, count);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, BLUE "%s:%d number of icons = %d\n" RESET, __FUNCTION__, __LINE__, count);
|
||||
|
||||
if (panel_horizontal) {
|
||||
int height = sysbar->area.height - 2*sysbar->area.bg->border.width - 2*sysbar->area.paddingy;
|
||||
@@ -180,6 +185,11 @@ int resize_systray(void *obj)
|
||||
sysbar->icons_per_column = count / sysbar->icons_per_row+ (count%sysbar->icons_per_row != 0);
|
||||
systray.area.height = (2 * systray.area.bg->border.width) + (2 * systray.area.paddingxlr) + (sysbar->icon_size * sysbar->icons_per_column) + ((sysbar->icons_per_column-1) * systray.area.paddingx);
|
||||
}
|
||||
|
||||
if (net_sel_win == None) {
|
||||
start_net();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -234,10 +244,20 @@ void on_change_systray (void *obj)
|
||||
}
|
||||
|
||||
// position and size the icon window
|
||||
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||
if (traywin->reparented) {
|
||||
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||
unsigned int border_width;
|
||||
int xpos, ypos;
|
||||
unsigned int width, height, depth;
|
||||
Window root;
|
||||
if (!XGetGeometry(server.dsp, traywin->parent, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
||||
fprintf(stderr, RED "Couldn't get geometry of window!\n" RESET);
|
||||
}
|
||||
if (width != traywin->width || height != traywin->height || xpos != traywin->x || ypos != traywin->y) {
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XMoveResizeWindow(server.dsp, traywin->parent = %ld, traywin->x = %d, traywin->y = %d, traywin->width = %d, traywin->height = %d)\n", traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||
}
|
||||
if (!traywin->reparented)
|
||||
reparent_icon(traywin);
|
||||
}
|
||||
refresh_systray = 1;
|
||||
}
|
||||
@@ -287,11 +307,19 @@ void start_net()
|
||||
|
||||
// init systray protocol
|
||||
net_sel_win = XCreateSimpleWindow(server.dsp, server.root_win, -1, -1, 1, 1, 0, 0, 0);
|
||||
fprintf(stderr, "systray window %ld\n", net_sel_win);
|
||||
|
||||
// v0.3 trayer specification. tint2 always horizontal.
|
||||
// Vertical panel will draw the systray horizontal.
|
||||
long orient = 0;
|
||||
XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_ORIENTATION, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &orient, 1);
|
||||
long orientation = 0;
|
||||
XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_ORIENTATION, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &orientation, 1);
|
||||
if (systray.icon_size > 0) {
|
||||
long icon_size = systray.icon_size;
|
||||
XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_ICON_SIZE, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &icon_size, 1);
|
||||
}
|
||||
long padding = 0;
|
||||
XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_PADDING, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &padding, 1);
|
||||
|
||||
VisualID vid;
|
||||
if (systray_composited)
|
||||
vid = XVisualIDFromVisual(server.visual32);
|
||||
@@ -480,7 +508,8 @@ gboolean add_icon(Window win)
|
||||
DATA32 pixel_bg = data_bg[y * other->width + x];
|
||||
DATA32 rgb_bg = pixel_bg & 0xffFFff;
|
||||
if (rgb != rgb_bg) {
|
||||
fprintf(stderr, "Pixel: %x different from bg %x at pos %d %d\n", pixel, pixel_bg, x, y);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "Pixel: %x different from bg %x at pos %d %d\n", pixel, pixel_bg, x, y);
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
@@ -514,6 +543,8 @@ gboolean add_icon(Window win)
|
||||
|
||||
// Create the parent window that will embed the icon
|
||||
XWindowAttributes attr;
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XGetWindowAttributes(server.dsp, win = %ld, &attr)\n", win);
|
||||
if (XGetWindowAttributes(server.dsp, win, &attr) == False) {
|
||||
free(name);
|
||||
return FALSE;
|
||||
@@ -543,7 +574,9 @@ gboolean add_icon(Window win)
|
||||
mask = CWBackPixmap;
|
||||
}
|
||||
}
|
||||
Window parent = XCreateWindow(server.dsp, panel->main_win, 0, 0, 30, 30, 0, attr.depth, InputOutput, visual, mask, &set_attr);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XCreateWindow(...)\n");
|
||||
Window parent = XCreateWindow(server.dsp, panel->main_win, 0, 0, systray.icon_size, systray.icon_size, 0, attr.depth, InputOutput, visual, mask, &set_attr);
|
||||
|
||||
// Add the icon to the list
|
||||
TrayWindow *traywin = g_new0(TrayWindow, 1);
|
||||
@@ -567,9 +600,11 @@ gboolean add_icon(Window win)
|
||||
systray.list_icons = g_slist_append(systray.list_icons, traywin);
|
||||
systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
|
||||
|
||||
if (!traywin->hide && !panel->is_hidden)
|
||||
if (!traywin->hide && !panel->is_hidden) {
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XMapRaised(server.dsp, traywin->parent)\n");
|
||||
XMapRaised(server.dsp, traywin->parent);
|
||||
XSync(server.dsp, False);
|
||||
}
|
||||
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__);
|
||||
@@ -592,33 +627,19 @@ 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);
|
||||
XSetErrorHandler(old);
|
||||
if (error != FALSE) {
|
||||
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid);
|
||||
remove_icon(traywin);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid);
|
||||
remove_icon(traywin);
|
||||
return FALSE;
|
||||
}
|
||||
XErrorHandler old = XSetErrorHandler(window_error_handler);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XSelectInput(server.dsp, traywin->win, ...)\n");
|
||||
XSelectInput(server.dsp, traywin->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
|
||||
XWithdrawWindow(server.dsp, traywin->win, server.screen);
|
||||
XReparentWindow(server.dsp, traywin->win, traywin->parent, 0, 0);
|
||||
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XMoveResizeWindow(server.dsp, traywin->win = %ld, 0, 0, traywin->width = %d, traywin->height = %d)\n", traywin->win, traywin->width, traywin->height);
|
||||
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||
|
||||
// Embed into parent
|
||||
{
|
||||
@@ -634,35 +655,61 @@ gboolean reparent_icon(TrayWindow *traywin)
|
||||
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) {
|
||||
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->pid);
|
||||
remove_icon(traywin);
|
||||
return FALSE;
|
||||
}
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XSendEvent(server.dsp, traywin->win, False, NoEventMask, &e)\n");
|
||||
XSendEvent(server.dsp, traywin->win, False, NoEventMask, &e);
|
||||
}
|
||||
|
||||
{
|
||||
XSync(server.dsp, False);
|
||||
XSetErrorHandler(old);
|
||||
if (error != FALSE) {
|
||||
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid);
|
||||
remove_icon(traywin);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
traywin->reparented = 1;
|
||||
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean embed_icon(TrayWindow *traywin)
|
||||
{
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
if (traywin->embedded)
|
||||
return TRUE;
|
||||
|
||||
Panel* panel = systray.area.panel;
|
||||
|
||||
XSync(server.dsp, False);
|
||||
error = FALSE;
|
||||
XErrorHandler old = XSetErrorHandler(window_error_handler);
|
||||
|
||||
if (0) {
|
||||
Atom acttype;
|
||||
int actfmt;
|
||||
unsigned long nbitem, bytes;
|
||||
unsigned char *data = 0;
|
||||
unsigned long *data = 0;
|
||||
int ret;
|
||||
|
||||
ret = XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data)\n");
|
||||
ret = XGetWindowProperty(server.dsp, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, (unsigned char**)&data);
|
||||
if (ret == Success) {
|
||||
if (data) {
|
||||
if (nbitem >= 2) {
|
||||
int hide = ((data[1] & XEMBED_MAPPED) == 0);
|
||||
if (hide) {
|
||||
// In theory we have to check the embedding with this and remove icons that refuse embedding.
|
||||
// In practice we have no idea when the other application processes the event and accepts the embed so we cannot check without a race.
|
||||
// In practice we have no idea when the other application processes the event and accepts the embed
|
||||
// so we cannot check now without a race.
|
||||
// Race can be triggered with PyGtk(2) apps.
|
||||
// We could defer this for later (if we set PropertyChangeMask in XSelectInput we get notified) but
|
||||
// for some reason it breaks transparency for Qt icons. So we don't.
|
||||
//fprintf(stderr, RED "tint2: window refused embedding\n" RESET);
|
||||
//remove_icon(traywin);
|
||||
//XFree(data);
|
||||
@@ -680,23 +727,39 @@ gboolean reparent_icon(TrayWindow *traywin)
|
||||
|
||||
// Redirect rendering when using compositing
|
||||
if (systray_composited) {
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XDamageCreate(server.dsp, traywin->parent, XDamageReportRawRectangles)\n");
|
||||
traywin->damage = XDamageCreate(server.dsp, traywin->parent, XDamageReportRawRectangles);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XCompositeRedirectWindow(server.dsp, traywin->parent, CompositeRedirectManual)\n");
|
||||
XCompositeRedirectWindow(server.dsp, traywin->parent, CompositeRedirectManual);
|
||||
}
|
||||
|
||||
XRaiseWindow(server.dsp, traywin->win);
|
||||
|
||||
// Make the icon visible
|
||||
if (!traywin->hide)
|
||||
if (!traywin->hide) {
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XMapWindow(server.dsp, traywin->win)\n");
|
||||
XMapWindow(server.dsp, traywin->win);
|
||||
if (!traywin->hide && !panel->is_hidden)
|
||||
}
|
||||
if (!traywin->hide && !panel->is_hidden) {
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XMapRaised(server.dsp, traywin->parent)\n");
|
||||
XMapRaised(server.dsp, traywin->parent);
|
||||
}
|
||||
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XSync(server.dsp, False)\n");
|
||||
XSync(server.dsp, False);
|
||||
XSetErrorHandler(old);
|
||||
if (error != FALSE) {
|
||||
fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d\n" RESET, __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid);
|
||||
remove_icon(traywin);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||
|
||||
XSync(server.dsp, False);
|
||||
|
||||
traywin->reparented = 1;
|
||||
traywin->embedded = 1;
|
||||
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
@@ -729,7 +792,12 @@ void remove_icon(TrayWindow *traywin)
|
||||
XSync(server.dsp, False);
|
||||
XSetErrorHandler(old);
|
||||
stop_timeout(traywin->render_timeout);
|
||||
stop_timeout(traywin->resize_timeout);
|
||||
free(traywin->name);
|
||||
if (traywin->image) {
|
||||
imlib_context_set_image(traywin->image);
|
||||
imlib_free_image_and_decache();
|
||||
}
|
||||
g_free(traywin);
|
||||
|
||||
// check empty systray
|
||||
@@ -753,27 +821,155 @@ void remove_icon(TrayWindow *traywin)
|
||||
refresh_systray = 1;
|
||||
}
|
||||
|
||||
void systray_resize_icon(void* t)
|
||||
{
|
||||
// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0
|
||||
// we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here
|
||||
TrayWindow* traywin = t;
|
||||
|
||||
unsigned int border_width;
|
||||
int xpos, ypos;
|
||||
unsigned int width, height, depth;
|
||||
Window root;
|
||||
if (!XGetGeometry(server.dsp, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
||||
return;
|
||||
} else {
|
||||
if (1 || xpos != 0 || ypos != 0 || width != traywin->width || height != traywin->height) {
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XMoveResizeWindow(server.dsp, traywin->win = %ld, 0, 0, traywin->width = %d, traywin->height = %d)\n", traywin->win, traywin->width, traywin->height);
|
||||
if (0) {
|
||||
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||
}
|
||||
if (0) {
|
||||
XWindowChanges changes;
|
||||
changes.x = changes.y = 0;
|
||||
changes.width = traywin->width;
|
||||
changes.height = traywin->height;
|
||||
XConfigureWindow(server.dsp, traywin->win, CWX|CWY|CWWidth|CWHeight, &changes);
|
||||
}
|
||||
if (1) {
|
||||
XConfigureEvent ev;
|
||||
ev.type = ConfigureNotify;
|
||||
ev.serial = 0;
|
||||
ev.send_event = True;
|
||||
ev.event = traywin->win;
|
||||
ev.window = traywin->win;
|
||||
ev.x = 0;
|
||||
ev.y = 0;
|
||||
ev.width = traywin->width;
|
||||
ev.height = traywin->height;
|
||||
ev.border_width = 0;
|
||||
ev.above = None;
|
||||
ev.override_redirect = False;
|
||||
XSendEvent(server.dsp, traywin->win, False, StructureNotifyMask, (XEvent*)&ev);
|
||||
}
|
||||
XSync(server.dsp, False);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
|
||||
{
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XConfigure event: win = %lu (%s), x = %d, y = %d, w = %d, h = %d\n",
|
||||
traywin->win, traywin->name, e->xconfigure.x, e->xconfigure.y, e->xconfigure.width, e->xconfigure.height);
|
||||
Panel* panel = systray.area.panel;
|
||||
|
||||
//fprintf(stderr, "move tray %d\n", traywin->x);
|
||||
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
|
||||
if (traywin->reparented) {
|
||||
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||
// Trigger window repaint
|
||||
stop_timeout(traywin->render_timeout);
|
||||
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
||||
if (!traywin->reparented)
|
||||
return;
|
||||
|
||||
if (e->xconfigure.width != traywin->width || e->xconfigure.height != traywin->height || e->xconfigure.x != 0 || e->xconfigure.y != 0) {
|
||||
if (traywin->bad_size_counter < max_bad_resize_events) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec earliest_resize = add_msec_to_timespec(traywin->time_last_resize, resize_period_threshold);
|
||||
if (compare_timespecs(&earliest_resize, &now) > 0) {
|
||||
// Fast resize, but below the threshold
|
||||
traywin->bad_size_counter++;
|
||||
} else {
|
||||
// Slow resize, reset counter
|
||||
traywin->time_last_resize.tv_sec = now.tv_sec;
|
||||
traywin->time_last_resize.tv_nsec = now.tv_nsec;
|
||||
traywin->bad_size_counter = 0;
|
||||
}
|
||||
if (traywin->bad_size_counter < min_bad_resize_events) {
|
||||
systray_resize_icon(traywin);
|
||||
} else {
|
||||
if (!traywin->resize_timeout)
|
||||
traywin->resize_timeout = add_timeout(fast_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
||||
}
|
||||
} else {
|
||||
if (traywin->bad_size_counter == max_bad_resize_events) {
|
||||
traywin->bad_size_counter++;
|
||||
fprintf(stderr, RED "Detected resize loop for tray icon %lu (%s), throttling resize events\n" RESET, traywin->win, traywin->name);
|
||||
}
|
||||
// Delayed resize
|
||||
// FIXME Normally we should force the icon to resize back to the size we resized it to when we embedded it.
|
||||
// However this triggers a resize loop in new versions of GTK, which we must avoid.
|
||||
if (!traywin->resize_timeout)
|
||||
traywin->resize_timeout = add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Correct size
|
||||
stop_timeout(traywin->resize_timeout);
|
||||
}
|
||||
|
||||
// Resize and redraw the systray
|
||||
if (systray_profile)
|
||||
fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
|
||||
panel_refresh = 1;
|
||||
refresh_systray = 1;
|
||||
}
|
||||
|
||||
void systray_resize_request_event(TrayWindow *traywin, XEvent *e)
|
||||
{
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XResizeRequest event: win = %lu (%s), w = %d, h = %d\n",
|
||||
traywin->win, traywin->name, e->xresizerequest.width, e->xresizerequest.height);
|
||||
|
||||
if (!traywin->reparented)
|
||||
return;
|
||||
|
||||
if (e->xresizerequest.width != traywin->width || e->xresizerequest.height != traywin->height) {
|
||||
if (traywin->bad_size_counter < max_bad_resize_events) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec earliest_resize = add_msec_to_timespec(traywin->time_last_resize, resize_period_threshold);
|
||||
if (compare_timespecs(&earliest_resize, &now) > 0) {
|
||||
// Fast resize, but below the threshold
|
||||
traywin->bad_size_counter++;
|
||||
} else {
|
||||
// Slow resize, reset counter
|
||||
traywin->time_last_resize.tv_sec = now.tv_sec;
|
||||
traywin->time_last_resize.tv_nsec = now.tv_nsec;
|
||||
traywin->bad_size_counter = 0;
|
||||
}
|
||||
if (traywin->bad_size_counter < min_bad_resize_events) {
|
||||
systray_resize_icon(traywin);
|
||||
} else {
|
||||
if (!traywin->resize_timeout)
|
||||
traywin->resize_timeout = add_timeout(fast_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
||||
}
|
||||
} else {
|
||||
if (traywin->bad_size_counter == max_bad_resize_events) {
|
||||
traywin->bad_size_counter++;
|
||||
fprintf(stderr, RED "Detected resize loop for tray icon %lu (%s), throttling resize events\n" RESET, traywin->win, traywin->name);
|
||||
}
|
||||
// Delayed resize
|
||||
// FIXME Normally we should force the icon to resize back to the size we resized it to when we embedded it.
|
||||
// However this triggers a resize loop in new versions of GTK, which we must avoid.
|
||||
if (!traywin->resize_timeout)
|
||||
traywin->resize_timeout = add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Correct size
|
||||
stop_timeout(traywin->resize_timeout);
|
||||
}
|
||||
|
||||
// Resize and redraw the systray
|
||||
if (systray_profile)
|
||||
fprintf(stderr, BLUE "[%f] %s:%d trigger resize & redraw\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__);
|
||||
systray.area.resize = 1;
|
||||
systray.area.redraw = 1;
|
||||
panel->area.resize = 1;
|
||||
panel_refresh = 1;
|
||||
refresh_systray = 1;
|
||||
}
|
||||
@@ -786,6 +982,17 @@ void systray_destroy_event(TrayWindow *traywin)
|
||||
}
|
||||
|
||||
|
||||
void systray_render_icon_from_image(TrayWindow* traywin)
|
||||
{
|
||||
Panel* panel = systray.area.panel;
|
||||
if (!traywin->image)
|
||||
return;
|
||||
imlib_context_set_image(traywin->image);
|
||||
XCopyArea(server.dsp, render_background, systray.area.pix, server.gc, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height, traywin->x-systray.area.posx, traywin->y-systray.area.posy);
|
||||
render_image(systray.area.pix, traywin->x-systray.area.posx, traywin->y-systray.area.posy);
|
||||
XCopyArea(server.dsp, systray.area.pix, panel->temp_pmap, server.gc, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height, traywin->x, traywin->y);
|
||||
}
|
||||
|
||||
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
|
||||
@@ -799,7 +1006,7 @@ void systray_render_icon_composited(void* t)
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec earliest_render = add_msec_to_timespec(traywin->time_last_render, min_refresh_period);
|
||||
if (compare_timespecs(&earliest_render, &now) > min_refresh_period) {
|
||||
if (compare_timespecs(&earliest_render, &now) > 0) {
|
||||
traywin->num_fast_renders++;
|
||||
if (traywin->num_fast_renders > max_fast_refreshes) {
|
||||
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
||||
@@ -826,26 +1033,6 @@ void systray_render_icon_composited(void* t)
|
||||
traywin->render_timeout = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
// We shouldn't have to do this as we already listen for structure notify events.
|
||||
// But things work fine so why change it.
|
||||
unsigned int border_width;
|
||||
int xpos, ypos;
|
||||
unsigned int width, height, depth;
|
||||
Window root;
|
||||
if (!XGetGeometry(server.dsp, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
||||
fprintf(stderr, RED "Couldn't get geometry of window!\n" RESET);
|
||||
return;
|
||||
}
|
||||
if (width != traywin->width || height != traywin->height || xpos != 0 || ypos != 0) {
|
||||
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
|
||||
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// mask out all pixel with the same rgb value
|
||||
@@ -903,15 +1090,23 @@ void systray_render_icon_composited(void* t)
|
||||
imlib_context_set_colormap(server.colormap32);
|
||||
imlib_context_set_drawable(tmp_pmap);
|
||||
Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, traywin->width, traywin->height, 1);
|
||||
imlib_context_set_visual(server.visual);
|
||||
imlib_context_set_colormap(server.colormap);
|
||||
XFreePixmap(server.dsp, tmp_pmap);
|
||||
if (!image) {
|
||||
imlib_context_set_visual(server.visual);
|
||||
imlib_context_set_colormap(server.colormap);
|
||||
XFreePixmap(server.dsp, tmp_pmap);
|
||||
XSetErrorHandler(old);
|
||||
goto on_error;
|
||||
} else {
|
||||
if (traywin->image) {
|
||||
imlib_context_set_image(traywin->image);
|
||||
imlib_free_image_and_decache();
|
||||
}
|
||||
traywin->image = image;
|
||||
}
|
||||
|
||||
imlib_context_set_image(image);
|
||||
imlib_context_set_image(traywin->image);
|
||||
//if (traywin->depth == 24)
|
||||
//imlib_save_image("/home/thil77/test.jpg");
|
||||
imlib_image_set_has_alpha(1);
|
||||
@@ -924,13 +1119,8 @@ void systray_render_icon_composited(void* t)
|
||||
if (systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0)
|
||||
adjust_asb(data, traywin->width, traywin->height, systray.alpha, (float)systray.saturation/100, (float)systray.brightness/100);
|
||||
imlib_image_put_back_data(data);
|
||||
XCopyArea(server.dsp, render_background, systray.area.pix, server.gc, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height, traywin->x-systray.area.posx, traywin->y-systray.area.posy);
|
||||
render_image(systray.area.pix, traywin->x-systray.area.posx, traywin->y-systray.area.posy);
|
||||
XCopyArea(server.dsp, systray.area.pix, panel->temp_pmap, server.gc, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height, traywin->x, traywin->y);
|
||||
imlib_free_image_and_decache();
|
||||
XFreePixmap(server.dsp, tmp_pmap);
|
||||
imlib_context_set_visual(server.visual);
|
||||
imlib_context_set_colormap(server.colormap);
|
||||
|
||||
systray_render_icon_from_image(traywin);
|
||||
|
||||
if (traywin->damage)
|
||||
XDamageSubtract(server.dsp, traywin->damage, None, None);
|
||||
@@ -952,6 +1142,7 @@ void systray_render_icon_composited(void* t)
|
||||
panel_refresh = 1;
|
||||
refresh_systray = 1;
|
||||
}
|
||||
panel_refresh = 1;
|
||||
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
@@ -977,25 +1168,58 @@ void systray_render_icon(void* t)
|
||||
TrayWindow* traywin = t;
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
if (!traywin->reparented) {
|
||||
if (!reparent_icon(traywin))
|
||||
return;
|
||||
if (systray_composited) {
|
||||
// We need to process the events in the main loop first
|
||||
stop_timeout(traywin->render_timeout);
|
||||
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
return;
|
||||
}
|
||||
if (!traywin->reparented || !traywin->embedded) {
|
||||
if (systray_profile)
|
||||
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
stop_timeout(traywin->render_timeout);
|
||||
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
if (systray_composited) {
|
||||
XSync(server.dsp, False);
|
||||
error = FALSE;
|
||||
XErrorHandler old = XSetErrorHandler(window_error_handler);
|
||||
|
||||
unsigned int border_width;
|
||||
int xpos, ypos;
|
||||
unsigned int width, height, depth;
|
||||
Window root;
|
||||
if (!XGetGeometry(server.dsp, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
|
||||
stop_timeout(traywin->render_timeout);
|
||||
if (!traywin->resize_timeout)
|
||||
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
||||
systray_render_icon_from_image(traywin);
|
||||
XSetErrorHandler(old);
|
||||
return;
|
||||
} else {
|
||||
if (xpos != 0 || ypos != 0 || width != traywin->width || height != traywin->height) {
|
||||
stop_timeout(traywin->render_timeout);
|
||||
if (!traywin->resize_timeout)
|
||||
traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon, traywin, &traywin->render_timeout);
|
||||
systray_render_icon_from_image(traywin);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering\n" RESET, profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name);
|
||||
XSetErrorHandler(old);
|
||||
return;
|
||||
}
|
||||
}
|
||||
XSetErrorHandler(old);
|
||||
}
|
||||
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "rendering tray icon\n");
|
||||
|
||||
if (systray_composited) {
|
||||
systray_render_icon_composited(traywin);
|
||||
} else {
|
||||
// Trigger window repaint
|
||||
XClearArea(server.dsp, traywin->parent, 0, 0, traywin->width, traywin->height, True);
|
||||
XClearArea(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height, True);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XClearArea(server.dsp, traywin->parent = %ld, 0, 0, traywin->width, traywin->height, True)\n", traywin->parent);
|
||||
XClearArea(server.dsp, traywin->parent, 0, 0, 0, 0, True);
|
||||
if (systray_profile)
|
||||
fprintf(stderr, "XClearArea(server.dsp, traywin->win = %ld, 0, 0, traywin->width, traywin->height, True)\n", traywin->win);
|
||||
XClearArea(server.dsp, traywin->win, 0, 0, 0, 0, True);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,12 @@ typedef struct
|
||||
struct timespec time_last_render;
|
||||
int num_fast_renders;
|
||||
int reparented;
|
||||
int embedded;
|
||||
int bad_size_counter;
|
||||
timeout* resize_timeout;
|
||||
struct timespec time_last_resize;
|
||||
char *name;
|
||||
Imlib_Image image;
|
||||
} TrayWindow;
|
||||
|
||||
|
||||
@@ -85,10 +90,15 @@ void stop_net();
|
||||
void net_message(XClientMessageEvent *e);
|
||||
|
||||
gboolean add_icon(Window id);
|
||||
gboolean reparent_icon(TrayWindow *traywin);
|
||||
gboolean embed_icon(TrayWindow *traywin);
|
||||
void remove_icon(TrayWindow *traywin);
|
||||
|
||||
void refresh_systray_icons();
|
||||
void systray_render_icon(void *t);
|
||||
gboolean request_embed_icon(TrayWindow *traywin);
|
||||
void systray_resize_request_event(TrayWindow *traywin, XEvent *e);
|
||||
gboolean request_embed_icon(TrayWindow *traywin);
|
||||
void systray_reconfigure_event(TrayWindow *traywin, XEvent *e);
|
||||
void systray_destroy_event(TrayWindow *traywin);
|
||||
void kde_update_icons();
|
||||
|
||||
@@ -350,13 +350,7 @@ void draw_task_icon (Task *tsk, int text_width)
|
||||
|
||||
// Render
|
||||
imlib_context_set_image (tsk->icon[tsk->current_state]);
|
||||
if (server.real_transparency) {
|
||||
render_image(tsk->area.pix, pos_x, panel->g_task.icon_posy);
|
||||
} else {
|
||||
imlib_context_set_blend(1);
|
||||
imlib_context_set_drawable(tsk->area.pix);
|
||||
imlib_render_image_on_drawable(pos_x, panel->g_task.icon_posy);
|
||||
}
|
||||
render_image(tsk->area.pix, pos_x, panel->g_task.icon_posy);
|
||||
}
|
||||
|
||||
|
||||
@@ -527,9 +521,14 @@ void set_task_state(Task *tsk, int state)
|
||||
tsk1->area.redraw = 1;
|
||||
if (state == TASK_ACTIVE && g_slist_find(urgent_list, tsk1))
|
||||
del_urgent(tsk1);
|
||||
// Show only the active task
|
||||
int hide = 0;
|
||||
Taskbar *taskbar = (Taskbar *)tsk1->area.parent;
|
||||
if (tsk->desktop == ALLDESKTOP && server.desktop != taskbar->desktop) {
|
||||
// Hide ALLDESKTOP task on non-current desktop
|
||||
hide = 1;
|
||||
}
|
||||
if (hide_inactive_tasks) {
|
||||
// Show only the active task
|
||||
if (state != TASK_ACTIVE) {
|
||||
hide = 1;
|
||||
}
|
||||
|
||||
67
src/tint.c
67
src/tint.c
@@ -447,11 +447,27 @@ int tint2_handles_click(Panel* panel, XButtonEvent* e)
|
||||
if (tskbar && e->button == 1 && panel_mode == MULTI_DESKTOP)
|
||||
return 1;
|
||||
if (click_clock(panel, e->x, e->y)) {
|
||||
if ( (e->button == 1 && clock_lclick_command) || (e->button == 3 && clock_rclick_command) )
|
||||
if ( (e->button == 1 && clock_lclick_command) ||
|
||||
(e->button == 2 && clock_mclick_command) ||
|
||||
(e->button == 3 && clock_rclick_command) ||
|
||||
(e->button == 4 && clock_uwheel_command) ||
|
||||
(e->button == 5 && clock_dwheel_command) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#ifdef ENABLE_BATTERY
|
||||
if (click_battery(panel, e->x, e->y)) {
|
||||
if ( (e->button == 1 && battery_lclick_command) ||
|
||||
(e->button == 2 && battery_mclick_command) ||
|
||||
(e->button == 3 && battery_rclick_command) ||
|
||||
(e->button == 4 && battery_uwheel_command) ||
|
||||
(e->button == 5 && battery_dwheel_command) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -599,6 +615,16 @@ void event_button_release (XEvent *e)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BATTERY
|
||||
if (click_battery(panel, e->xbutton.x, e->xbutton.y)) {
|
||||
battery_action(e->xbutton.button);
|
||||
if (panel_layer == BOTTOM_LAYER)
|
||||
XLowerWindow (server.dsp, panel->main_win);
|
||||
task_drag = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e->xbutton.button == 1 && click_launcher(panel, e->xbutton.x, e->xbutton.y)) {
|
||||
LauncherIcon *icon = click_launcher_icon(panel, e->xbutton.x, e->xbutton.y);
|
||||
if (icon) {
|
||||
@@ -1219,7 +1245,7 @@ start:
|
||||
sigchld_handler_async();
|
||||
}
|
||||
}
|
||||
while (XPending(server.dsp) > 0) {
|
||||
if (XPending(server.dsp) > 0) {
|
||||
XNextEvent(server.dsp, &e);
|
||||
#if HAVE_SN
|
||||
if (startup_notifications)
|
||||
@@ -1286,15 +1312,48 @@ start:
|
||||
event_configure_notify(&e);
|
||||
break;
|
||||
|
||||
case ConfigureRequest:
|
||||
// 'win' is a trayer icon
|
||||
for (it = systray.list_icons; it ; it = g_slist_next(it)) {
|
||||
TrayWindow *traywin = (TrayWindow*)it->data;
|
||||
if (traywin->win == e.xany.window) {
|
||||
systray_reconfigure_event(traywin, &e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ResizeRequest:
|
||||
// 'win' is a trayer icon
|
||||
for (it = systray.list_icons; it ; it = g_slist_next(it)) {
|
||||
TrayWindow *traywin = (TrayWindow*)it->data;
|
||||
if (traywin->win == e.xany.window) {
|
||||
systray_resize_request_event(traywin, &e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ReparentNotify:
|
||||
if (!systray_enabled)
|
||||
break;
|
||||
panel = (Panel*)systray.area.panel;
|
||||
if (e.xany.window == panel->main_win) // reparented to us
|
||||
if (e.xany.window == panel->main_win) // don't care
|
||||
break;
|
||||
// FIXME: 'reparent to us' badly detected => disabled
|
||||
for (it = systray.list_icons; it; it = g_slist_next(it)) {
|
||||
TrayWindow *traywin = (TrayWindow*)it->data;
|
||||
if (traywin->win == e.xreparent.window) {
|
||||
if (traywin->parent == e.xreparent.parent) {
|
||||
embed_icon(traywin);
|
||||
} else {
|
||||
remove_icon(traywin);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UnmapNotify:
|
||||
break;
|
||||
case DestroyNotify:
|
||||
if (e.xany.window == server.composite_manager) {
|
||||
// Stop real_transparency
|
||||
|
||||
@@ -84,6 +84,7 @@ GtkWidget *task_iconified_color, *task_iconified_color_set,
|
||||
// clock
|
||||
GtkWidget *clock_format_line1, *clock_format_line2, *clock_tmz_line1, *clock_tmz_line2;
|
||||
GtkWidget *clock_left_command, *clock_right_command;
|
||||
GtkWidget *clock_mclick_command, *clock_rclick_command, *clock_uwheel_command, *clock_dwheel_command;
|
||||
GtkWidget *clock_padding_x, *clock_padding_y, *clock_font_line1, *clock_font_line2, *clock_font_color;
|
||||
GtkWidget *clock_background;
|
||||
|
||||
@@ -91,6 +92,7 @@ GtkWidget *clock_background;
|
||||
GtkWidget *battery_hide_if_higher, *battery_alert_if_lower, *battery_alert_cmd;
|
||||
GtkWidget *battery_padding_x, *battery_padding_y, *battery_font_line1, *battery_font_line2, *battery_font_color;
|
||||
GtkWidget *battery_background;
|
||||
GtkWidget *battery_left_command, *battery_mclick_command, *battery_right_command, *battery_uwheel_command, *battery_dwheel_command;
|
||||
|
||||
// systray
|
||||
GtkWidget *systray_icon_order, *systray_padding_x, *systray_padding_y, *systray_spacing;
|
||||
@@ -3316,7 +3318,7 @@ void create_clock(GtkWidget *parent)
|
||||
gtk_widget_show(label);
|
||||
gtk_box_pack_start(GTK_BOX(parent), label, FALSE, FALSE, 0);
|
||||
|
||||
table = gtk_table_new(2, 10, FALSE);
|
||||
table = gtk_table_new(5, 10, FALSE);
|
||||
gtk_widget_show(table);
|
||||
gtk_box_pack_start(GTK_BOX(parent), table, FALSE, FALSE, 0);
|
||||
gtk_table_set_row_spacings(GTK_TABLE(table), ROW_SPACING);
|
||||
@@ -3352,6 +3354,51 @@ void create_clock(GtkWidget *parent)
|
||||
gtk_tooltips_set_tip(tooltips, clock_right_command,
|
||||
_("Specifies a command that will be executed when the clock receives a right click."), NULL);
|
||||
|
||||
row++, col = 2;
|
||||
label = gtk_label_new(_("Middle click command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
clock_mclick_command = gtk_entry_new();
|
||||
gtk_widget_show(clock_mclick_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(clock_mclick_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), clock_mclick_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, clock_mclick_command,
|
||||
_("Specifies a command that will be executed when the clock receives a middle click."), NULL);
|
||||
|
||||
row++, col = 2;
|
||||
label = gtk_label_new(_("Wheel scroll up command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
clock_uwheel_command = gtk_entry_new();
|
||||
gtk_widget_show(clock_uwheel_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(clock_uwheel_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), clock_uwheel_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, clock_uwheel_command,
|
||||
_("Specifies a command that will be executed when the clock receives a mouse scroll up."), NULL);
|
||||
|
||||
row++, col = 2;
|
||||
label = gtk_label_new(_("Wheel scroll down command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
clock_dwheel_command = gtk_entry_new();
|
||||
gtk_widget_show(clock_dwheel_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(clock_dwheel_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), clock_dwheel_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, clock_dwheel_command,
|
||||
_("Specifies a command that will be executed when the clock receives a mouse scroll down."), NULL);
|
||||
|
||||
change_paragraph(parent);
|
||||
|
||||
label = gtk_label_new(_("<b>Appearance</b>"));
|
||||
@@ -3769,6 +3816,95 @@ void create_battery(GtkWidget *parent)
|
||||
|
||||
change_paragraph(parent);
|
||||
|
||||
label = gtk_label_new(_("<b>Mouse events</b>"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
|
||||
gtk_widget_show(label);
|
||||
gtk_box_pack_start(GTK_BOX(parent), label, FALSE, FALSE, 0);
|
||||
|
||||
table = gtk_table_new(5, 10, FALSE);
|
||||
gtk_widget_show(table);
|
||||
gtk_box_pack_start(GTK_BOX(parent), table, FALSE, FALSE, 0);
|
||||
gtk_table_set_row_spacings(GTK_TABLE(table), ROW_SPACING);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(table), COL_SPACING);
|
||||
row = 0, col = 2;
|
||||
|
||||
label = gtk_label_new(_("Left click command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
battery_left_command = gtk_entry_new();
|
||||
gtk_widget_show(battery_left_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(battery_left_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), battery_left_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, battery_left_command,
|
||||
_("Specifies a command that will be executed when the battery receives a left click."), NULL);
|
||||
|
||||
row++, col = 2;
|
||||
label = gtk_label_new(_("Right click command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
battery_right_command = gtk_entry_new();
|
||||
gtk_widget_show(battery_right_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(battery_right_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), battery_right_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, battery_right_command,
|
||||
_("Specifies a command that will be executed when the battery receives a right click."), NULL);
|
||||
|
||||
row++, col = 2;
|
||||
label = gtk_label_new(_("Middle click command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
battery_mclick_command = gtk_entry_new();
|
||||
gtk_widget_show(battery_mclick_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(battery_mclick_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), battery_mclick_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, battery_mclick_command,
|
||||
_("Specifies a command that will be executed when the battery receives a middle click."), NULL);
|
||||
|
||||
row++, col = 2;
|
||||
label = gtk_label_new(_("Wheel scroll up command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
battery_uwheel_command = gtk_entry_new();
|
||||
gtk_widget_show(battery_uwheel_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(battery_uwheel_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), battery_uwheel_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, battery_uwheel_command,
|
||||
_("Specifies a command that will be executed when the battery receives a mouse scroll up."), NULL);
|
||||
|
||||
row++, col = 2;
|
||||
label = gtk_label_new(_("Wheel scroll down command"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_widget_show(label);
|
||||
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
|
||||
battery_dwheel_command = gtk_entry_new();
|
||||
gtk_widget_show(battery_dwheel_command);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(battery_dwheel_command), 50);
|
||||
gtk_table_attach(GTK_TABLE(table), battery_dwheel_command, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
|
||||
col++;
|
||||
gtk_tooltips_set_tip(tooltips, battery_dwheel_command,
|
||||
_("Specifies a command that will be executed when the battery receives a mouse scroll down."), NULL);
|
||||
|
||||
change_paragraph(parent);
|
||||
|
||||
label = gtk_label_new(_("<b>Appearance</b>"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
||||
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
|
||||
|
||||
@@ -87,6 +87,7 @@ extern GtkWidget *task_iconified_color, *task_iconified_color_set,
|
||||
// clock
|
||||
extern GtkWidget *clock_format_line1, *clock_format_line2, *clock_tmz_line1, *clock_tmz_line2;
|
||||
extern GtkWidget *clock_left_command, *clock_right_command;
|
||||
extern GtkWidget *clock_mclick_command, *clock_rclick_command, *clock_uwheel_command, *clock_dwheel_command;
|
||||
extern GtkWidget *clock_padding_x, *clock_padding_y, *clock_font_line1, *clock_font_line2, *clock_font_color;
|
||||
extern GtkWidget *clock_background;
|
||||
|
||||
@@ -94,6 +95,7 @@ extern GtkWidget *clock_background;
|
||||
extern GtkWidget *battery_hide_if_higher, *battery_alert_if_lower, *battery_alert_cmd;
|
||||
extern GtkWidget *battery_padding_x, *battery_padding_y, *battery_font_line1, *battery_font_line2, *battery_font_color;
|
||||
extern GtkWidget *battery_background;
|
||||
extern GtkWidget *battery_left_command, *battery_mclick_command, *battery_right_command, *battery_uwheel_command, *battery_dwheel_command;
|
||||
|
||||
// systray
|
||||
extern GtkWidget *systray_icon_order, *systray_padding_x, *systray_padding_y, *systray_spacing;
|
||||
|
||||
@@ -548,6 +548,9 @@ void config_write_clock(FILE *fp)
|
||||
fprintf(fp, "clock_tooltip_timezone = %s\n", gtk_entry_get_text(GTK_ENTRY(clock_tmz_tooltip)));
|
||||
fprintf(fp, "clock_lclick_command = %s\n", gtk_entry_get_text(GTK_ENTRY(clock_left_command)));
|
||||
fprintf(fp, "clock_rclick_command = %s\n", gtk_entry_get_text(GTK_ENTRY(clock_right_command)));
|
||||
fprintf(fp, "clock_mclick_command = %s\n", gtk_entry_get_text(GTK_ENTRY(clock_mclick_command)));
|
||||
fprintf(fp, "clock_uwheel_command = %s\n", gtk_entry_get_text(GTK_ENTRY(clock_uwheel_command)));
|
||||
fprintf(fp, "clock_dwheel_command = %s\n", gtk_entry_get_text(GTK_ENTRY(clock_dwheel_command)));
|
||||
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
@@ -573,6 +576,11 @@ void config_write_battery(FILE *fp)
|
||||
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(battery_padding_y)));
|
||||
fprintf(fp, "battery_background_id = %d\n", gtk_combo_box_get_active(GTK_COMBO_BOX(battery_background)));
|
||||
fprintf(fp, "battery_hide = %d\n", (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(battery_hide_if_higher)));
|
||||
fprintf(fp, "battery_lclick_command = %s\n", gtk_entry_get_text(GTK_ENTRY(battery_left_command)));
|
||||
fprintf(fp, "battery_rclick_command = %s\n", gtk_entry_get_text(GTK_ENTRY(battery_right_command)));
|
||||
fprintf(fp, "battery_mclick_command = %s\n", gtk_entry_get_text(GTK_ENTRY(battery_mclick_command)));
|
||||
fprintf(fp, "battery_uwheel_command = %s\n", gtk_entry_get_text(GTK_ENTRY(battery_uwheel_command)));
|
||||
fprintf(fp, "battery_dwheel_command = %s\n", gtk_entry_get_text(GTK_ENTRY(battery_dwheel_command)));
|
||||
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
@@ -747,7 +755,7 @@ void add_entry(char *key, char *value)
|
||||
else if (strcmp(key, "panel_margin") == 0) {
|
||||
extract_values(value, &value1, &value2, &value3);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(panel_margin_x), atoi(value1));
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(panel_margin_y), atoi(value1));
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(panel_margin_y), atoi(value2));
|
||||
}
|
||||
else if (strcmp(key, "panel_padding") == 0) {
|
||||
extract_values(value, &value1, &value2, &value3);
|
||||
@@ -935,6 +943,21 @@ void add_entry(char *key, char *value)
|
||||
else
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(battery_hide_if_higher), atoi(value));
|
||||
}
|
||||
else if (strcmp(key, "battery_lclick_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(battery_left_command), value);
|
||||
}
|
||||
else if (strcmp(key, "battery_rclick_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(battery_right_command), value);
|
||||
}
|
||||
else if (strcmp(key, "battery_mclick_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(battery_mclick_command), value);
|
||||
}
|
||||
else if (strcmp(key, "battery_uwheel_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(battery_uwheel_command), value);
|
||||
}
|
||||
else if (strcmp(key, "battery_dwheel_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(battery_dwheel_command), value);
|
||||
}
|
||||
|
||||
/* Clock */
|
||||
else if (strcmp(key, "time1_format") == 0) {
|
||||
@@ -987,6 +1010,15 @@ void add_entry(char *key, char *value)
|
||||
else if (strcmp(key, "clock_rclick_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(clock_right_command), value);
|
||||
}
|
||||
else if (strcmp(key, "clock_mclick_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(clock_mclick_command), value);
|
||||
}
|
||||
else if (strcmp(key, "clock_uwheel_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(clock_uwheel_command), value);
|
||||
}
|
||||
else if (strcmp(key, "clock_dwheel_command") == 0) {
|
||||
gtk_entry_set_text(GTK_ENTRY(clock_dwheel_command), value);
|
||||
}
|
||||
|
||||
/* Taskbar */
|
||||
else if (strcmp(key, "taskbar_mode") == 0) {
|
||||
|
||||
@@ -404,6 +404,13 @@ int imageEmpty(DATA32* data, int w, int h)
|
||||
|
||||
void render_image(Drawable d, int x, int y)
|
||||
{
|
||||
if (!server.real_transparency) {
|
||||
imlib_context_set_blend(1);
|
||||
imlib_context_set_drawable(d);
|
||||
imlib_render_image_on_drawable(x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
int w = imlib_image_get_width(), h = imlib_image_get_height();
|
||||
|
||||
Pixmap pixmap = XCreatePixmap(server.dsp, server.root_win, w, h, 32);
|
||||
|
||||
@@ -131,17 +131,28 @@ int window_get_monitor (Window win)
|
||||
Window src;
|
||||
|
||||
XTranslateCoordinates(server.dsp, win, server.root_win, 0, 0, &x, &y, &src);
|
||||
x += 2;
|
||||
y += 2;
|
||||
int best_match = -1;
|
||||
int match_right = 0;
|
||||
int match_bottom = 0;
|
||||
// There is an ambiguity when a window is right on the edge between screens.
|
||||
// In that case, prefer the monitor which is on the right and bottom of the window's top-left corner.
|
||||
for (i = 0; i < server.nb_monitor; i++) {
|
||||
if (x >= server.monitor[i].x && x <= (server.monitor[i].x + server.monitor[i].width))
|
||||
if (y >= server.monitor[i].y && y <= (server.monitor[i].y + server.monitor[i].height))
|
||||
break;
|
||||
if (y >= server.monitor[i].y && y <= (server.monitor[i].y + server.monitor[i].height)) {
|
||||
int current_right = x < (server.monitor[i].x + server.monitor[i].width);
|
||||
int current_bottom = y < (server.monitor[i].y + server.monitor[i].height);
|
||||
if (best_match < 0 ||
|
||||
(!match_right && current_right) ||
|
||||
(!match_bottom && current_bottom)) {
|
||||
best_match = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("window %lx : ecran %d, (%d, %d)\n", win, i, x, y);
|
||||
if (i == server.nb_monitor) return 0;
|
||||
else return i;
|
||||
if (best_match < 0)
|
||||
best_match = 0;
|
||||
// printf("window %lx : ecran %d, (%d, %d)\n", win, best_match+1, x, y);
|
||||
return best_match;
|
||||
}
|
||||
|
||||
void window_get_coordinates (Window win, int *x, int *y, int *w, int *h)
|
||||
|
||||
Reference in New Issue
Block a user