2009-01-20 21:16:54 +00:00
/**************************************************************************
* Tint2 : systraybar
*
2010-11-02 11:40:50 +00:00
* Copyright ( C ) 2009 thierry lorthiois ( lorthiois @ bbsoft . fr ) from Omega distribution
2009-06-19 21:08:34 +00:00
* based on ' docker - 1.5 ' from Ben Jansens .
2009-01-20 21:16:54 +00:00
*
* 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 <X11/Xlib.h>
# include <X11/Xutil.h>
# include <X11/Xatom.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <glib.h>
# include <Imlib2.h>
2010-01-03 00:33:07 +00:00
# include <X11/extensions/Xdamage.h>
# include <X11/extensions/Xcomposite.h>
2010-01-31 14:04:58 +00:00
# include <X11/extensions/Xrender.h>
2015-05-30 11:23:20 +00:00
2009-01-20 21:16:54 +00:00
# include "systraybar.h"
# include "server.h"
2009-02-10 23:16:10 +00:00
# include "panel.h"
2009-01-20 21:16:54 +00:00
2009-02-10 23:16:10 +00:00
GSList * icons ;
2009-01-20 21:16:54 +00:00
2009-02-10 23:16:10 +00:00
/* defined in the systray spec */
# define SYSTEM_TRAY_REQUEST_DOCK 0
# define SYSTEM_TRAY_BEGIN_MESSAGE 1
# define SYSTEM_TRAY_CANCEL_MESSAGE 2
2009-02-25 20:04:43 +00:00
// selection window
2010-01-07 21:23:15 +00:00
Window net_sel_win = None ;
2009-02-10 23:16:10 +00:00
2009-02-27 22:18:30 +00:00
// freedesktop specification doesn't allow multi systray
Systraybar systray ;
2009-06-20 15:08:33 +00:00
int refresh_systray ;
2009-10-30 17:18:44 +00:00
int systray_enabled ;
2010-04-16 18:50:03 +00:00
int systray_max_icon_size ;
2015-01-23 18:40:31 +00:00
int systray_monitor ;
2015-05-13 19:17:02 +00:00
int chrono ;
2015-06-07 09:44:43 +00:00
int systray_composited ;
2015-06-19 08:46:29 +00:00
int systray_profile ;
2010-01-06 19:30:55 +00:00
// background pixmap if we render ourselves the icons
2010-04-18 12:07:36 +00:00
static Pixmap render_background ;
2010-01-06 19:30:55 +00:00
2015-06-21 12:50:08 +00:00
const int min_refresh_period = 50 ;
const int max_fast_refreshes = 5 ;
2015-07-19 14:49:05 +00:00
const int min_resize_period = 1000 ;
const int slow_resize_period = 30000 ;
const int max_bad_resize_events = 8 ;
2009-02-10 23:16:10 +00:00
2010-04-18 12:07:36 +00:00
void default_systray ( )
{
memset ( & systray , 0 , sizeof ( Systraybar ) ) ;
render_background = 0 ;
2015-05-13 19:17:02 +00:00
chrono = 0 ;
2010-04-18 12:07:36 +00:00
systray . alpha = 100 ;
2015-05-13 19:17:02 +00:00
systray . sort = SYSTRAY_SORT_LEFT2RIGHT ;
2010-04-18 12:07:36 +00:00
systray . area . _draw_foreground = draw_systray ;
2010-09-25 21:18:47 +00:00
systray . area . _on_change_layout = on_change_systray ;
2010-08-08 14:06:15 +00:00
systray . area . size_mode = SIZE_BY_CONTENT ;
2010-04-18 12:07:36 +00:00
systray . area . _resize = resize_systray ;
2015-06-19 08:46:29 +00:00
systray_profile = getenv ( " SYSTRAY_PROFILING " ) ! = NULL ;
2010-04-18 12:07:36 +00:00
}
void cleanup_systray ( )
{
2010-04-22 15:08:21 +00:00
stop_net ( ) ;
2010-04-18 12:07:36 +00:00
systray_enabled = 0 ;
systray_max_icon_size = 0 ;
2015-01-23 18:40:31 +00:00
systray_monitor = 0 ;
2010-04-18 12:07:36 +00:00
systray . area . on_screen = 0 ;
free_area ( & systray . area ) ;
if ( render_background ) {
XFreePixmap ( server . dsp , render_background ) ;
render_background = 0 ;
}
}
2009-02-15 17:22:48 +00:00
void init_systray ( )
2009-02-10 23:16:10 +00:00
{
2009-10-30 17:18:44 +00:00
if ( ! systray_enabled )
2009-02-27 22:18:30 +00:00
return ;
2009-02-15 17:22:48 +00:00
2015-06-12 10:24:19 +00:00
systray_composited = ! server . disable_transparency & & server . visual32 & & server . colormap32 ;
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " Systray composited rendering %s \n " , systray_composited ? " on " : " off " ) ;
2015-06-07 09:44:43 +00:00
if ( ! systray_composited ) {
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " systray_asb forced to 100 0 0 \n " ) ;
2010-02-28 07:58:50 +00:00
systray . alpha = 100 ;
systray . brightness = systray . saturation = 0 ;
}
2015-06-07 09:44:43 +00:00
start_net ( ) ;
2009-10-18 17:54:09 +00:00
}
void init_systray_panel ( void * p )
{
systray . area . parent = p ;
systray . area . panel = p ;
2015-04-11 09:51:10 +00:00
if ( ! systray . area . bg )
2011-01-06 23:28:16 +00:00
systray . area . bg = & g_array_index ( backgrounds , Background , 0 ) ;
2010-09-18 18:06:29 +00:00
GSList * l ;
int count = 0 ;
for ( l = systray . list_icons ; l ; l = l - > next ) {
2015-05-11 19:19:36 +00:00
if ( ( ( TrayWindow * ) l - > data ) - > hide )
continue ;
count + + ;
2010-09-18 18:06:29 +00:00
}
if ( count = = 0 )
2010-09-22 19:33:10 +00:00
hide ( & systray . area ) ;
2015-06-07 09:44:43 +00:00
else
2010-09-22 19:33:10 +00:00
show ( & systray . area ) ;
2010-09-18 18:06:29 +00:00
refresh_systray = 0 ;
2009-02-15 17:22:48 +00:00
}
2009-02-10 23:16:10 +00:00
2010-01-09 00:11:01 +00:00
void draw_systray ( void * obj , cairo_t * c )
2009-06-20 15:08:33 +00:00
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , BLUE " [%f] %s:%d \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2015-06-07 09:44:43 +00:00
if ( systray_composited ) {
2015-06-07 10:58:29 +00:00
if ( render_background )
XFreePixmap ( server . dsp , render_background ) ;
2010-01-06 19:30:55 +00:00
render_background = XCreatePixmap ( server . dsp , server . root_win , systray . area . width , systray . area . height , server . depth ) ;
2010-01-09 00:11:01 +00:00
XCopyArea ( server . dsp , systray . area . pix , render_background , server . gc , 0 , 0 , systray . area . width , systray . area . height , 0 , 0 ) ;
2010-01-06 19:30:55 +00:00
}
2009-06-20 15:08:33 +00:00
refresh_systray = 1 ;
}
2010-09-16 23:24:25 +00:00
int resize_systray ( void * obj )
2009-02-28 23:04:53 +00:00
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2009-02-28 23:04:53 +00:00
Systraybar * sysbar = obj ;
GSList * l ;
2010-09-18 22:00:16 +00:00
int count ;
2009-02-28 23:04:53 +00:00
2009-06-24 20:17:57 +00:00
if ( panel_horizontal )
2010-09-18 22:00:16 +00:00
sysbar - > icon_size = sysbar - > area . height ;
2009-06-24 20:17:57 +00:00
else
2010-09-18 22:00:16 +00:00
sysbar - > icon_size = sysbar - > area . width ;
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 ;
2009-09-27 21:33:44 +00:00
count = 0 ;
for ( l = systray . list_icons ; l ; l = l - > next ) {
2015-05-13 20:58:58 +00:00
if ( ( ( TrayWindow * ) l - > data ) - > hide )
2015-05-11 19:19:36 +00:00
continue ;
count + + ;
2009-09-27 21:33:44 +00:00
}
2015-06-21 12:50:08 +00:00
fprintf ( stderr , BLUE " %s:%d number of icons = %d \n " RESET , __FUNCTION__ , __LINE__ , count ) ;
2009-02-28 23:04:53 +00:00
2009-06-24 20:17:57 +00:00
if ( panel_horizontal ) {
2010-09-18 18:06:29 +00:00
int height = sysbar - > area . height - 2 * sysbar - > area . bg - > border . width - 2 * sysbar - > area . paddingy ;
// here icons_per_column always higher than 0
2010-09-18 22:00:16 +00:00
sysbar - > icons_per_column = ( height + sysbar - > area . paddingx ) / ( sysbar - > icon_size + sysbar - > area . paddingx ) ;
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 ) ;
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 ) ;
2015-06-07 10:58:29 +00:00
} else {
2010-09-18 18:06:29 +00:00
int width = sysbar - > area . width - 2 * sysbar - > area . bg - > border . width - 2 * sysbar - > area . paddingy ;
// here icons_per_row always higher than 0
2010-09-18 22:00:16 +00:00
sysbar - > icons_per_row = ( width + sysbar - > area . paddingx ) / ( sysbar - > icon_size + sysbar - > area . paddingx ) ;
sysbar - > marging = width - ( sysbar - > icons_per_row - 1 ) * ( sysbar - > icon_size + sysbar - > area . paddingx ) - sysbar - > icon_size ;
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 ) ;
2009-06-19 21:08:34 +00:00
}
2010-09-16 23:24:25 +00:00
return 1 ;
2009-02-28 23:04:53 +00:00
}
2009-04-01 20:19:09 +00:00
2010-09-25 21:18:47 +00:00
void on_change_systray ( void * obj )
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2010-11-07 17:43:14 +00:00
// here, systray.area.posx/posy are defined by rendering engine. so we can calculate position of tray icon.
2010-09-25 21:18:47 +00:00
Systraybar * sysbar = obj ;
2015-01-22 17:31:56 +00:00
if ( sysbar - > icons_per_column = = 0 | | sysbar - > icons_per_row = = 0 )
return ;
2010-11-09 19:32:45 +00:00
Panel * panel = sysbar - > area . panel ;
2010-09-25 21:18:47 +00:00
int i , posx , posy ;
2010-11-09 19:32:45 +00:00
int start = panel - > area . bg - > border . width + panel - > area . paddingy + systray . area . bg - > border . width + systray . area . paddingy + sysbar - > marging / 2 ;
2010-09-25 21:18:47 +00:00
if ( panel_horizontal ) {
posy = start ;
posx = systray . area . posx + systray . area . bg - > border . width + systray . area . paddingxlr ;
2015-06-07 10:58:29 +00:00
} else {
2010-09-25 21:18:47 +00:00
posx = start ;
posy = systray . area . posy + systray . area . bg - > border . width + systray . area . paddingxlr ;
}
TrayWindow * traywin ;
GSList * l ;
2015-06-07 10:58:29 +00:00
for ( i = 1 , l = systray . list_icons ; l ; i + + , l = l - > next ) {
2010-09-25 21:18:47 +00:00
traywin = ( TrayWindow * ) l - > data ;
2015-05-11 19:19:36 +00:00
if ( traywin - > hide )
continue ;
2010-09-25 21:18:47 +00:00
traywin - > y = posy ;
traywin - > x = posx ;
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " %s:%d win = %lu (%s), parent = %lu, x = %d, y = %d \n " , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name , traywin - > parent , posx , posy ) ;
2010-09-25 21:18:47 +00:00
traywin - > width = sysbar - > icon_size ;
traywin - > height = sysbar - > icon_size ;
if ( panel_horizontal ) {
2015-06-07 10:58:29 +00:00
if ( i % sysbar - > icons_per_column ) {
2010-09-25 21:18:47 +00:00
posy + = sysbar - > icon_size + sysbar - > area . paddingx ;
2015-06-07 10:58:29 +00:00
} else {
2010-09-25 21:18:47 +00:00
posy = start ;
posx + = ( sysbar - > icon_size + systray . area . paddingx ) ;
}
2015-06-07 10:58:29 +00:00
} else {
if ( i % sysbar - > icons_per_row ) {
2010-09-25 21:18:47 +00:00
posx + = sysbar - > icon_size + systray . area . paddingx ;
2015-06-07 10:58:29 +00:00
} else {
2010-09-25 21:18:47 +00:00
posx = start ;
posy + = ( sysbar - > icon_size + systray . area . paddingx ) ;
}
}
// position and size the icon window
2015-07-16 07:02:13 +00:00
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 ) {
2015-07-16 06:53:25 +00:00
if ( systray_profile )
2015-07-16 07:02:13 +00:00
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 ) ;
}
2015-07-19 14:12:02 +00:00
if ( ! traywin - > reparented )
reparent_icon ( traywin ) ;
2010-09-25 21:18:47 +00:00
}
2015-06-07 09:44:43 +00:00
refresh_systray = 1 ;
2010-09-25 21:18:47 +00:00
}
2009-06-29 18:39:44 +00:00
// ***********************************************
// systray protocol
2009-02-28 23:04:53 +00:00
2009-10-30 17:18:44 +00:00
void start_net ( )
2009-02-25 20:04:43 +00:00
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2009-10-30 17:18:44 +00:00
if ( net_sel_win ) {
// protocol already started
if ( ! systray_enabled )
stop_net ( ) ;
return ;
2015-06-07 10:58:29 +00:00
} else {
2009-10-30 17:18:44 +00:00
if ( ! systray_enabled )
return ;
2015-06-07 10:58:29 +00:00
}
2009-10-30 17:18:44 +00:00
2009-08-30 16:20:44 +00:00
Window win = XGetSelectionOwner ( server . dsp , server . atom . _NET_SYSTEM_TRAY_SCREEN ) ;
2009-06-29 18:39:44 +00:00
// freedesktop systray specification
2009-08-30 16:20:44 +00:00
if ( win ! = None ) {
// search pid
Atom _NET_WM_PID , actual_type ;
int actual_format ;
unsigned long nitems ;
unsigned long bytes_after ;
2009-09-25 19:11:50 +00:00
unsigned char * prop = 0 ;
2009-08-30 16:20:44 +00:00
int pid ;
_NET_WM_PID = XInternAtom ( server . dsp , " _NET_WM_PID " , True ) ;
int ret = XGetWindowProperty ( server . dsp , win , _NET_WM_PID , 0 , 1024 , False , AnyPropertyType , & actual_type , & actual_format , & nitems , & bytes_after , & prop ) ;
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " tint2 : another systray is running " ) ;
2009-09-25 19:11:50 +00:00
if ( ret = = Success & & prop ) {
2009-08-30 16:20:44 +00:00
pid = prop [ 1 ] * 256 ;
pid + = prop [ 0 ] ;
fprintf ( stderr , " pid=%d " , pid ) ;
}
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " \n " RESET ) ;
2009-10-30 17:18:44 +00:00
return ;
2009-03-07 10:05:15 +00:00
}
2009-02-25 20:04:43 +00:00
// init systray protocol
2009-09-07 21:41:21 +00:00
net_sel_win = XCreateSimpleWindow ( server . dsp , server . root_win , - 1 , - 1 , 1 , 1 , 0 , 0 , 0 ) ;
2009-02-25 20:04:43 +00:00
2010-01-07 21:23:15 +00:00
// v0.3 trayer specification. tint2 always horizontal.
2009-09-27 21:33:44 +00:00
// Vertical panel will draw the systray horizontal.
2010-09-12 22:00:00 +00:00
long orient = 0 ;
2009-02-25 20:04:43 +00:00
XChangeProperty ( server . dsp , net_sel_win , server . atom . _NET_SYSTEM_TRAY_ORIENTATION , XA_CARDINAL , 32 , PropModeReplace , ( unsigned char * ) & orient , 1 ) ;
2010-02-28 07:58:50 +00:00
VisualID vid ;
2015-06-07 09:44:43 +00:00
if ( systray_composited )
2010-02-28 07:58:50 +00:00
vid = XVisualIDFromVisual ( server . visual32 ) ;
else
vid = XVisualIDFromVisual ( server . visual ) ;
2009-12-30 23:27:31 +00:00
XChangeProperty ( server . dsp , net_sel_win , XInternAtom ( server . dsp , " _NET_SYSTEM_TRAY_VISUAL " , False ) , XA_VISUALID , 32 , PropModeReplace , ( unsigned char * ) & vid , 1 ) ;
2009-02-25 20:04:43 +00:00
XSetSelectionOwner ( server . dsp , server . atom . _NET_SYSTEM_TRAY_SCREEN , net_sel_win , CurrentTime ) ;
if ( XGetSelectionOwner ( server . dsp , server . atom . _NET_SYSTEM_TRAY_SCREEN ) ! = net_sel_win ) {
2009-10-30 17:18:44 +00:00
stop_net ( ) ;
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " tint2 : can't get systray manager \n " RESET ) ;
2009-10-30 17:18:44 +00:00
return ;
2009-09-07 21:41:21 +00:00
}
2009-02-25 20:04:43 +00:00
2015-06-21 12:50:08 +00:00
fprintf ( stderr , GREEN " tint2 : systray started \n " RESET ) ;
if ( systray_profile )
fprintf ( stderr , " [%f] %s:%d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2009-09-07 21:41:21 +00:00
XClientMessageEvent ev ;
2009-02-25 20:04:43 +00:00
ev . type = ClientMessage ;
2009-09-07 21:41:21 +00:00
ev . window = server . root_win ;
2009-02-25 20:04:43 +00:00
ev . message_type = server . atom . MANAGER ;
ev . format = 32 ;
ev . data . l [ 0 ] = CurrentTime ;
ev . data . l [ 1 ] = server . atom . _NET_SYSTEM_TRAY_SCREEN ;
ev . data . l [ 2 ] = net_sel_win ;
ev . data . l [ 3 ] = 0 ;
ev . data . l [ 4 ] = 0 ;
2009-02-27 22:18:30 +00:00
XSendEvent ( server . dsp , server . root_win , False , StructureNotifyMask , ( XEvent * ) & ev ) ;
2009-02-25 20:04:43 +00:00
}
2015-06-14 09:21:42 +00:00
void net_message ( XClientMessageEvent * e )
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2015-06-14 09:21:42 +00:00
unsigned long opcode ;
Window win ;
opcode = e - > data . l [ 1 ] ;
switch ( opcode ) {
case SYSTEM_TRAY_REQUEST_DOCK :
win = e - > data . l [ 2 ] ;
if ( win )
add_icon ( win ) ;
break ;
case SYSTEM_TRAY_BEGIN_MESSAGE :
case SYSTEM_TRAY_CANCEL_MESSAGE :
// we don't show baloons messages.
break ;
default :
if ( opcode = = server . atom . _NET_SYSTEM_TRAY_MESSAGE_DATA )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " message from dockapp: %s \n " , e - > data . b ) ;
2015-06-14 09:21:42 +00:00
else
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " SYSTEM_TRAY : unknown message type \n " RESET ) ;
2015-06-14 09:21:42 +00:00
break ;
}
}
2009-10-30 17:18:44 +00:00
void stop_net ( )
2009-03-07 10:05:15 +00:00
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2009-10-30 17:18:44 +00:00
if ( systray . list_icons ) {
// remove_icon change systray.list_icons
while ( systray . list_icons )
remove_icon ( ( TrayWindow * ) systray . list_icons - > data ) ;
g_slist_free ( systray . list_icons ) ;
2015-04-11 09:51:10 +00:00
systray . list_icons = NULL ;
2009-10-30 17:18:44 +00:00
}
2009-03-07 10:05:15 +00:00
if ( net_sel_win ! = None ) {
2009-09-07 21:41:21 +00:00
XDestroyWindow ( server . dsp , net_sel_win ) ;
net_sel_win = None ;
2009-03-07 10:05:15 +00:00
}
}
2009-02-10 23:16:10 +00:00
2009-04-01 20:19:09 +00:00
2009-02-10 23:16:10 +00:00
gboolean error ;
int window_error_handler ( Display * d , XErrorEvent * e )
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " [%f] %s:%d \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2009-06-18 20:26:40 +00:00
error = TRUE ;
if ( e - > error_code ! = BadWindow ) {
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " systray: error code %d \n " RESET , e - > error_code ) ;
2009-06-18 20:26:40 +00:00
}
return 0 ;
2009-02-10 23:16:10 +00:00
}
2009-08-29 22:09:29 +00:00
static gint compare_traywindows ( gconstpointer a , gconstpointer b )
{
const TrayWindow * traywin_a = ( TrayWindow * ) a ;
const TrayWindow * traywin_b = ( TrayWindow * ) b ;
2015-05-11 19:19:36 +00:00
if ( traywin_a - > empty & & ! traywin_b - > empty )
2015-05-30 11:33:44 +00:00
return 1 * ( systray . sort = = SYSTRAY_SORT_RIGHT2LEFT ? - 1 : 1 ) ;
2015-05-11 19:19:36 +00:00
if ( ! traywin_a - > empty & & traywin_b - > empty )
2015-05-30 11:33:44 +00:00
return - 1 * ( systray . sort = = SYSTRAY_SORT_RIGHT2LEFT ? - 1 : 1 ) ;
2015-05-11 19:19:36 +00:00
2015-05-13 19:17:02 +00:00
if ( systray . sort = = SYSTRAY_SORT_ASCENDING | |
systray . sort = = SYSTRAY_SORT_DESCENDING ) {
2015-06-21 12:50:08 +00:00
return g_ascii_strncasecmp ( traywin_a - > name , traywin_b - > name , - 1 ) *
( systray . sort = = SYSTRAY_SORT_ASCENDING ? 1 : - 1 ) ;
2009-08-29 22:09:29 +00:00
}
2015-05-13 19:17:02 +00:00
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 ) ;
2009-08-29 22:09:29 +00:00
}
2015-05-13 19:17:02 +00:00
return 0 ;
2009-08-29 22:09:29 +00:00
}
2015-06-07 10:58:29 +00:00
gboolean add_icon ( Window win )
2009-02-10 23:16:10 +00:00
{
2015-06-21 12:50:08 +00:00
XTextProperty xname ;
char * name ;
if ( XGetWMName ( server . dsp , win , & xname ) ) {
name = strdup ( ( char * ) xname . value ) ;
XFree ( xname . value ) ;
} else {
name = strdup ( " " ) ;
}
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , win , name ) ;
2009-06-18 20:26:40 +00:00
Panel * panel = systray . area . panel ;
2009-09-27 21:33:44 +00:00
int hide = 0 ;
2009-02-10 23:16:10 +00:00
2015-06-07 10:45:48 +00:00
// Get the process ID of the application that created the window
2015-05-11 19:19:36 +00:00
int pid = 0 ;
{
Atom actual_type ;
int actual_format ;
unsigned long nitems ;
unsigned long bytes_after ;
unsigned char * prop = 0 ;
2015-06-07 10:58:29 +00:00
int ret = XGetWindowProperty ( server . dsp , win , server . atom . _NET_WM_PID , 0 , 1024 , False , AnyPropertyType , & actual_type , & actual_format , & nitems , & bytes_after , & prop ) ;
2015-05-11 19:19:36 +00:00
if ( ret = = Success & & prop ) {
pid = prop [ 1 ] * 256 ;
pid + = prop [ 0 ] ;
}
}
2015-06-07 10:45:48 +00:00
// Check if the application leaves behind empty icons
2015-02-04 23:15:57 +00:00
GSList * l ;
2015-05-11 19:19:36 +00:00
int num_empty_same_pid = 0 ;
2015-02-04 23:15:57 +00:00
for ( l = systray . list_icons ; l ; l = l - > next ) {
2015-06-21 12:50:08 +00:00
TrayWindow * other = ( TrayWindow * ) l - > data ;
if ( other - > win = = win ) {
free ( name ) ;
2015-02-04 23:15:57 +00:00
return FALSE ;
2015-06-21 12:50:08 +00:00
}
2015-06-21 13:23:09 +00:00
if ( ! systray_composited ) {
// Empty icon detection: we compare the contents of the icon with the contents of the panel pixmap.
// If any pixel is different, the icon is not empty.
imlib_context_set_visual ( server . visual ) ;
imlib_context_set_colormap ( server . colormap ) ;
imlib_context_set_drawable ( other - > win ) ;
Imlib_Image image = imlib_create_image_from_drawable ( 0 , 0 , 0 , other - > width , other - > height , 1 ) ;
if ( image ) {
imlib_context_set_drawable ( panel - > temp_pmap ) ;
Imlib_Image bg = imlib_create_image_from_drawable ( 0 , other - > x , other - > y , other - > width , other - > height , 1 ) ;
imlib_context_set_image ( bg ) ;
DATA32 * data_bg = imlib_image_get_data_for_reading_only ( ) ;
imlib_context_set_image ( image ) ;
imlib_image_set_has_alpha ( other - > depth > 24 ) ;
DATA32 * data = imlib_image_get_data_for_reading_only ( ) ;
int x , y ;
int empty = 1 ;
for ( x = 0 ; x < other - > width & & empty ; x + + ) {
for ( y = 0 ; y < other - > height & & empty ; y + + ) {
DATA32 pixel = data [ y * other - > width + x ] ;
DATA32 a = ( pixel > > 24 ) & 0xff ;
if ( a = = 0 )
continue ;
DATA32 rgb = pixel & 0xffFFff ;
DATA32 pixel_bg = data_bg [ y * other - > width + x ] ;
DATA32 rgb_bg = pixel_bg & 0xffFFff ;
if ( rgb ! = rgb_bg ) {
fprintf ( stderr , " Pixel: %x different from bg %x at pos %d %d \n " , pixel , pixel_bg , x , y ) ;
empty = 0 ;
2015-06-21 12:50:08 +00:00
}
}
}
2015-06-21 13:23:09 +00:00
other - > empty = empty ;
imlib_free_image_and_decache ( ) ;
imlib_context_set_image ( bg ) ;
imlib_free_image_and_decache ( ) ;
if ( systray_profile )
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) empty = %d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , other - > win , other - > name , other - > empty ) ;
2015-06-21 12:50:08 +00:00
}
2015-06-21 13:23:09 +00:00
}
if ( pid & & other - > pid = = pid ) {
2015-06-21 12:50:08 +00:00
if ( other - > empty )
num_empty_same_pid + + ;
}
2015-05-11 19:19:36 +00:00
}
2015-06-07 10:45:48 +00:00
// Remove empty icons if the application leaves behind more than 1
2015-05-11 19:19:36 +00:00
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 + + ;
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " Removing tray icon %lu (%s) from misbehaving application with pid=%d (too many icons) \n " RESET , ( ( TrayWindow * ) l - > data ) - > win , ( ( TrayWindow * ) l - > data ) - > name , pid ) ;
2015-05-11 19:19:36 +00:00
remove_icon ( ( TrayWindow * ) l - > data ) ;
break ;
}
}
2015-02-04 23:15:57 +00:00
}
2015-06-07 10:45:48 +00:00
// Create the parent window that will embed the icon
2009-12-31 14:20:32 +00:00
XWindowAttributes attr ;
2015-07-16 06:53:25 +00:00
if ( systray_profile )
fprintf ( stderr , " XGetWindowAttributes(server.dsp, win = %ld, &attr) \n " , win ) ;
2015-06-21 12:50:08 +00:00
if ( XGetWindowAttributes ( server . dsp , win , & attr ) = = False ) {
free ( name ) ;
2015-06-07 10:45:48 +00:00
return FALSE ;
2015-06-21 12:50:08 +00:00
}
2010-01-03 20:17:46 +00:00
unsigned long mask = 0 ;
2010-01-03 00:33:07 +00:00
XSetWindowAttributes set_attr ;
2010-08-18 12:32:08 +00:00
Visual * visual = server . visual ;
2015-06-21 12:50:08 +00:00
fprintf ( stderr , GREEN " add_icon: %lu (%s), pid %d, %d, visual %p, colormap %lu, depth %d, width %d, height %d \n " RESET ,
win , name , pid , num_empty_same_pid , attr . visual , attr . colormap , attr . depth , attr . width , attr . height ) ;
if ( server . disable_transparency ) {
2010-01-03 20:17:46 +00:00
set_attr . background_pixmap = ParentRelative ;
mask = CWBackPixmap ;
2015-06-21 12:50:08 +00:00
if ( systray_composited | | attr . depth ! = server . depth ) {
visual = attr . visual ;
set_attr . colormap = attr . colormap ;
mask | = CWColormap ;
}
} else {
if ( systray_composited | | attr . depth ! = server . depth ) {
visual = attr . visual ;
set_attr . background_pixel = 0 ;
set_attr . border_pixel = 0 ;
set_attr . colormap = attr . colormap ;
mask = CWColormap | CWBackPixel | CWBorderPixel ;
} else {
set_attr . background_pixmap = ParentRelative ;
mask = CWBackPixmap ;
}
2010-01-03 20:17:46 +00:00
}
2015-07-16 06:53:25 +00:00
if ( systray_profile )
fprintf ( stderr , " XCreateWindow(...) \n " ) ;
2015-06-07 10:58:29 +00:00
Window parent = XCreateWindow ( server . dsp , panel - > main_win , 0 , 0 , 30 , 30 , 0 , attr . depth , InputOutput , visual , mask , & set_attr ) ;
2015-06-07 10:45:48 +00:00
// Add the icon to the list
2015-06-21 12:50:08 +00:00
TrayWindow * traywin = g_new0 ( TrayWindow , 1 ) ;
2015-06-07 10:58:29 +00:00
traywin - > parent = parent ;
traywin - > win = win ;
2009-09-27 21:33:44 +00:00
traywin - > hide = hide ;
2010-01-03 20:17:46 +00:00
traywin - > depth = attr . depth ;
2015-06-07 10:45:48 +00:00
// 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
2015-05-11 19:19:36 +00:00
traywin - > pid = pid ;
2015-06-21 12:50:08 +00:00
traywin - > name = name ;
2015-05-13 19:17:02 +00:00
traywin - > chrono = chrono ;
chrono + + ;
2009-02-10 23:16:10 +00:00
2010-09-18 18:06:29 +00:00
if ( systray . area . on_screen = = 0 )
2010-09-22 19:33:10 +00:00
show ( & systray . area ) ;
2010-09-18 18:06:29 +00:00
2015-05-13 19:17:02 +00:00
if ( systray . sort = = SYSTRAY_SORT_RIGHT2LEFT )
2009-09-27 19:52:25 +00:00
systray . list_icons = g_slist_prepend ( systray . list_icons , traywin ) ;
else
2015-05-13 19:02:40 +00:00
systray . list_icons = g_slist_append ( systray . list_icons , traywin ) ;
systray . list_icons = g_slist_sort ( systray . list_icons , compare_traywindows ) ;
2015-06-07 10:45:48 +00:00
2015-07-16 06:53:25 +00:00
if ( ! traywin - > hide & & ! panel - > is_hidden ) {
if ( systray_profile )
fprintf ( stderr , " XMapRaised(server.dsp, traywin->parent) \n " ) ;
2015-06-14 08:51:30 +00:00
XMapRaised ( server . dsp , traywin - > parent ) ;
2015-07-16 06:53:25 +00:00
}
2015-06-14 08:51:30 +00:00
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2015-06-19 08:46:29 +00:00
2015-06-07 10:45:48 +00:00
// Resize and redraw the systray
2015-06-21 12:50:08 +00:00
if ( systray_profile )
fprintf ( stderr , BLUE " [%f] %s:%d trigger resize & redraw \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2015-06-07 10:45:48 +00:00
systray . area . resize = 1 ;
2015-06-12 00:09:43 +00:00
systray . area . redraw = 1 ;
2015-06-12 09:57:05 +00:00
panel - > area . resize = 1 ;
2015-06-07 10:45:48 +00:00
panel_refresh = 1 ;
2015-06-14 09:39:51 +00:00
refresh_systray = 1 ;
2015-06-07 10:45:48 +00:00
return TRUE ;
}
gboolean reparent_icon ( TrayWindow * traywin )
{
2015-07-19 14:12:02 +00:00
fprintf ( stderr , " reparenting tray icon \n " ) ;
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-06-07 10:45:48 +00:00
if ( traywin - > reparented )
return TRUE ;
2015-07-16 18:20:23 +00:00
// Watch for the icon trying to resize itself / closing again
error = FALSE ;
XErrorHandler old = XSetErrorHandler ( window_error_handler ) ;
if ( systray_profile )
2015-07-16 20:25:18 +00:00
fprintf ( stderr , " XSelectInput(server.dsp, traywin->win, StructureNotifyMask) \n " ) ;
2015-07-16 18:20:23 +00:00
XSelectInput ( server . dsp , traywin - > win , StructureNotifyMask | PropertyChangeMask ) ;
2015-07-16 20:25:18 +00:00
XWithdrawWindow ( server . dsp , traywin - > win , server . screen ) ;
2015-07-16 18:20:23 +00:00
XReparentWindow ( server . dsp , traywin - > win , traywin - > parent , 0 , 0 ) ;
2015-07-19 14:12:02 +00:00
// 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 ;
if ( systray_profile )
fprintf ( stderr , " XSendEvent(server.dsp, traywin->win, False, 0xFFFFFF, &e) \n " ) ;
XSendEvent ( server . dsp , traywin - > win , False , 0xFFFFFF , & e ) ;
}
2015-07-16 18:20:23 +00:00
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 ) ;
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 ;
}
2015-07-16 20:25:18 +00:00
gboolean embed_icon ( TrayWindow * traywin )
2015-07-16 18:20:23 +00:00
{
2015-07-19 14:12:02 +00:00
fprintf ( stderr , " embedding tray icon \n " ) ;
2015-07-16 18:20:23 +00:00
if ( systray_profile )
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-07-16 20:25:18 +00:00
if ( traywin - > embedded )
2015-07-16 18:20:23 +00:00
return TRUE ;
2015-07-16 20:25:18 +00:00
Panel * panel = systray . area . panel ;
2015-06-07 10:58:29 +00:00
error = FALSE ;
2015-06-07 10:45:48 +00:00
XErrorHandler old = XSetErrorHandler ( window_error_handler ) ;
2015-07-19 14:12:02 +00:00
if ( 0 ) {
2015-07-16 20:25:18 +00:00
Atom acttype ;
int actfmt ;
unsigned long nbitem , bytes ;
unsigned char * data = 0 ;
int ret ;
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 , & 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.
// Race can be triggered with PyGtk(2) apps.
//fprintf(stderr, RED "tint2: window refused embedding\n" RESET);
//remove_icon(traywin);
//XFree(data);
//return FALSE;
}
}
XFree ( data ) ;
2015-06-07 10:45:48 +00:00
}
2015-07-16 20:25:18 +00:00
} else {
fprintf ( stderr , RED " tint2 : xembed error \n " RESET ) ;
remove_icon ( traywin ) ;
return FALSE ;
2015-06-07 10:45:48 +00:00
}
}
2015-07-16 20:25:18 +00:00
// 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 ) ;
}
2015-06-12 09:57:05 +00:00
2015-07-19 14:12:02 +00:00
XRaiseWindow ( server . dsp , traywin - > win ) ;
2015-07-16 20:25:18 +00:00
// Make the icon visible
if ( ! traywin - > hide ) {
if ( systray_profile )
fprintf ( stderr , " XMapWindow(server.dsp, traywin->win) \n " ) ;
XMapWindow ( server . dsp , traywin - > win ) ;
2015-07-16 19:08:29 +00:00
}
2015-07-16 20:25:18 +00:00
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 , " 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 ( systray_profile )
fprintf ( stderr , " XSync(server.dsp, False) \n " ) ;
XSync ( server . dsp , False ) ;
2015-07-19 14:12:02 +00:00
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 ;
}
2015-06-12 09:57:05 +00:00
2015-07-16 20:25:18 +00:00
traywin - > embedded = 1 ;
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-06-19 08:46:29 +00:00
2009-02-25 20:04:43 +00:00
return TRUE ;
2009-02-10 23:16:10 +00:00
}
2009-03-01 19:18:35 +00:00
void remove_icon ( TrayWindow * traywin )
2009-02-27 22:18:30 +00:00
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-06-14 09:39:51 +00:00
Panel * panel = systray . area . panel ;
2009-06-29 18:39:44 +00:00
// remove from our list
systray . list_icons = g_slist_remove ( systray . list_icons , traywin ) ;
2015-06-21 12:50:08 +00:00
fprintf ( stderr , YELLOW " remove_icon: %lu (%s) \n " RESET , traywin - > win , traywin - > name ) ;
2009-06-29 18:39:44 +00:00
2015-06-07 10:58:29 +00:00
XSelectInput ( server . dsp , traywin - > win , NoEventMask ) ;
2010-01-03 20:17:46 +00:00
if ( traywin - > damage )
XDamageDestroy ( server . dsp , traywin - > damage ) ;
2009-02-27 22:18:30 +00:00
2009-03-01 19:18:35 +00:00
// reparent to root
2015-06-12 09:39:36 +00:00
XSync ( server . dsp , False ) ;
2009-03-01 19:18:35 +00:00
error = FALSE ;
2015-06-12 10:24:19 +00:00
XErrorHandler old = XSetErrorHandler ( window_error_handler ) ;
2009-09-27 21:33:44 +00:00
if ( ! traywin - > hide )
2015-06-07 10:58:29 +00:00
XUnmapWindow ( server . dsp , traywin - > win ) ;
XReparentWindow ( server . dsp , traywin - > win , server . root_win , 0 , 0 ) ;
XDestroyWindow ( server . dsp , traywin - > parent ) ;
2009-03-01 19:18:35 +00:00
XSync ( server . dsp , False ) ;
XSetErrorHandler ( old ) ;
2015-04-17 20:17:25 +00:00
stop_timeout ( traywin - > render_timeout ) ;
2015-07-19 14:49:05 +00:00
stop_timeout ( traywin - > resize_timeout ) ;
2015-06-21 12:50:08 +00:00
free ( traywin - > name ) ;
2015-07-19 14:49:05 +00:00
if ( traywin - > image ) {
imlib_context_set_image ( traywin - > image ) ;
imlib_free_image_and_decache ( ) ;
}
2009-10-30 20:54:29 +00:00
g_free ( traywin ) ;
2009-03-01 19:18:35 +00:00
2010-09-18 18:06:29 +00:00
// check empty systray
int count = 0 ;
GSList * l ;
2015-04-11 09:51:10 +00:00
for ( l = systray . list_icons ; l ; l = l - > next ) {
2015-05-13 20:58:58 +00:00
if ( ( ( TrayWindow * ) l - > data ) - > hide )
2015-05-11 19:19:36 +00:00
continue ;
count + + ;
2010-09-18 18:06:29 +00:00
}
2010-09-22 19:33:10 +00:00
if ( count = = 0 )
hide ( & systray . area ) ;
2015-06-07 09:44:43 +00:00
2015-06-14 09:39:51 +00:00
// Resize and redraw the systray
2015-06-21 12:50:08 +00:00
if ( systray_profile )
fprintf ( stderr , BLUE " [%f] %s:%d trigger resize & redraw \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2010-09-21 09:54:19 +00:00
systray . area . resize = 1 ;
2015-06-14 09:39:51 +00:00
systray . area . redraw = 1 ;
panel - > area . resize = 1 ;
2009-02-27 22:18:30 +00:00
panel_refresh = 1 ;
2015-06-14 09:39:51 +00:00
refresh_systray = 1 ;
2009-02-27 22:18:30 +00:00
}
2015-07-19 14:49:05 +00:00
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 ( 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 ) ;
XMoveResizeWindow ( server . dsp , traywin - > win , 0 , 0 , traywin - > width , traywin - > height ) ;
}
}
}
2015-06-21 12:50:08 +00:00
void systray_reconfigure_event ( TrayWindow * traywin , XEvent * e )
2009-02-10 23:16:10 +00:00
{
2015-07-19 14:12:02 +00:00
if ( 1 | | systray_profile )
2015-06-21 12:50:08 +00:00
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 ) ;
2015-06-14 09:39:51 +00:00
Panel * panel = systray . area . panel ;
2015-06-21 12:50:08 +00:00
//fprintf(stderr, "move tray %d\n", traywin->x);
2015-07-15 07:53:09 +00:00
2015-07-19 14:49:05 +00:00
if ( ! traywin - > reparented )
return ;
2015-07-15 07:53:09 +00:00
if ( e - > xconfigure . width ! = traywin - > width | | e - > xconfigure . height ! = traywin - > height | | e - > xconfigure . x ! = 0 | | e - > xconfigure . y ! = 0 ) {
2015-07-19 14:49:05 +00:00
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 , min_resize_period ) ;
if ( compare_timespecs ( & earliest_resize , & now ) > 0 ) {
// Fast resize, but below the threshold
traywin - > bad_size_counter + + ;
2015-07-19 14:12:02 +00:00
} else {
2015-07-19 14:49:05 +00:00
// 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 ;
2015-07-19 14:12:02 +00:00
}
2015-07-19 14:49:05 +00:00
systray_resize_icon ( traywin ) ;
} 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 ;
2015-07-15 07:53:09 +00:00
}
2015-07-19 14:49:05 +00:00
} else {
// Correct size
stop_timeout ( traywin - > resize_timeout ) ;
2009-02-25 20:04:43 +00:00
}
2015-07-15 07:53:09 +00:00
2015-06-14 09:39:51 +00:00
// Resize and redraw the systray
2015-06-21 12:50:08 +00:00
if ( systray_profile )
fprintf ( stderr , BLUE " [%f] %s:%d trigger resize & redraw \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2015-06-14 09:39:51 +00:00
systray . area . resize = 1 ;
systray . area . redraw = 1 ;
panel - > area . resize = 1 ;
2015-06-14 09:21:42 +00:00
panel_refresh = 1 ;
refresh_systray = 1 ;
}
void systray_destroy_event ( TrayWindow * traywin )
{
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-06-14 09:21:42 +00:00
remove_icon ( traywin ) ;
2009-02-10 23:16:10 +00:00
}
2015-06-14 09:21:42 +00:00
2015-07-19 14:49:05 +00:00
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 ) ;
}
2015-06-07 10:45:48 +00:00
void systray_render_icon_composited ( void * t )
2010-01-03 00:33:07 +00:00
{
2010-02-20 10:08:56 +00:00
// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0
2010-02-28 07:58:50 +00:00
// we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here
2010-01-07 19:51:00 +00:00
TrayWindow * traywin = t ;
2015-05-11 19:19:36 +00:00
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-06-19 08:46:29 +00:00
2015-06-07 09:44:43 +00:00
// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
struct timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
2015-06-21 12:50:08 +00:00
struct timespec earliest_render = add_msec_to_timespec ( traywin - > time_last_render , min_refresh_period ) ;
if ( compare_timespecs ( & earliest_render , & now ) > min_refresh_period ) {
traywin - > num_fast_renders + + ;
if ( traywin - > num_fast_renders > max_fast_refreshes ) {
traywin - > render_timeout = add_timeout ( min_refresh_period , 0 , systray_render_icon_composited , traywin , & traywin - > render_timeout ) ;
if ( systray_profile )
fprintf ( stderr , YELLOW " [%f] %s:%d win = %lu (%s) delaying rendering \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
return ;
}
} else {
traywin - > time_last_render . tv_sec = now . tv_sec ;
traywin - > time_last_render . tv_nsec = now . tv_nsec ;
traywin - > num_fast_renders = 0 ;
2015-06-07 09:44:43 +00:00
}
2015-05-30 11:41:29 +00:00
2015-06-14 08:51:30 +00:00
if ( traywin - > width = = 0 | | traywin - > height = = 0 ) {
2010-10-08 21:45:14 +00:00
// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
2015-06-21 12:50:08 +00:00
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 ) ;
2010-10-08 21:45:14 +00:00
return ;
}
2010-01-06 19:47:12 +00:00
2015-06-07 09:44:43 +00:00
if ( traywin - > render_timeout ) {
stop_timeout ( traywin - > render_timeout ) ;
traywin - > render_timeout = NULL ;
}
2015-05-30 12:22:40 +00:00
2010-01-03 20:17:46 +00:00
// good systray icons support 32 bit depth, but some icons are still 24 bit.
2010-01-03 00:33:07 +00:00
// 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
Panel * panel = systray . area . panel ;
2010-01-31 14:04:58 +00:00
// 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
// drawable. If someone knows why it does not work with the traywindow itself, please tell me ;)
2015-06-12 19:13:20 +00:00
Pixmap tmp_pmap = XCreatePixmap ( server . dsp , traywin - > win , traywin - > width , traywin - > height , 32 ) ;
2015-06-12 10:24:19 +00:00
if ( ! tmp_pmap ) {
2015-06-13 09:32:22 +00:00
goto on_systray_error ;
2015-06-12 10:24:19 +00:00
}
XRenderPictFormat * f ;
2015-06-07 10:58:29 +00:00
if ( traywin - > depth = = 24 ) {
2010-01-31 16:56:54 +00:00
f = XRenderFindStandardFormat ( server . dsp , PictStandardRGB24 ) ;
2015-06-07 10:58:29 +00:00
} else if ( traywin - > depth = = 32 ) {
2010-01-31 15:10:38 +00:00
f = XRenderFindStandardFormat ( server . dsp , PictStandardARGB32 ) ;
2015-06-07 10:58:29 +00:00
} else {
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " Strange tray icon found with depth: %d \n " RESET , traywin - > depth ) ;
2015-06-12 19:13:20 +00:00
XFreePixmap ( server . dsp , tmp_pmap ) ;
2010-01-31 16:56:54 +00:00
return ;
}
2015-06-12 10:24:19 +00:00
XRenderPictFormat * f32 = XRenderFindVisualFormat ( server . dsp , server . visual32 ) ;
if ( ! f | | ! f32 ) {
XFreePixmap ( server . dsp , tmp_pmap ) ;
2015-06-13 09:32:22 +00:00
goto on_systray_error ;
2015-06-12 10:24:19 +00:00
}
XSync ( server . dsp , False ) ;
error = FALSE ;
XErrorHandler old = XSetErrorHandler ( window_error_handler ) ;
2010-04-20 15:14:37 +00:00
//if (server.real_transparency)
2015-06-12 10:24:19 +00:00
//Picture pict_image = XRenderCreatePicture(server.dsp, traywin->parent, f, 0, 0);
2010-04-20 15:14:37 +00:00
// reverted Rev 407 because here it's breaking alls icon with systray + xcompmgr
2015-06-12 10:24:19 +00:00
Picture pict_image = XRenderCreatePicture ( server . dsp , traywin - > win , f , 0 , 0 ) ;
if ( ! pict_image ) {
XFreePixmap ( server . dsp , tmp_pmap ) ;
XSetErrorHandler ( old ) ;
goto on_error ;
}
2010-02-28 07:58:50 +00:00
Picture pict_drawable = XRenderCreatePicture ( server . dsp , tmp_pmap , XRenderFindVisualFormat ( server . dsp , server . visual32 ) , 0 , 0 ) ;
2015-06-12 10:24:19 +00:00
if ( ! pict_drawable ) {
XRenderFreePicture ( server . dsp , pict_image ) ;
XFreePixmap ( server . dsp , tmp_pmap ) ;
XSetErrorHandler ( old ) ;
goto on_error ;
}
2010-01-31 14:04:58 +00:00
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_drawable ) ;
// end of the ugly hack and we can continue as before
2010-02-28 07:58:50 +00:00
imlib_context_set_visual ( server . visual32 ) ;
imlib_context_set_colormap ( server . colormap32 ) ;
2010-01-31 14:04:58 +00:00
imlib_context_set_drawable ( tmp_pmap ) ;
Imlib_Image image = imlib_create_image_from_drawable ( 0 , 0 , 0 , traywin - > width , traywin - > height , 1 ) ;
2015-07-19 14:49:05 +00:00
imlib_context_set_visual ( server . visual ) ;
imlib_context_set_colormap ( server . colormap ) ;
XFreePixmap ( server . dsp , tmp_pmap ) ;
2015-06-12 10:24:19 +00:00
if ( ! image ) {
imlib_context_set_visual ( server . visual ) ;
imlib_context_set_colormap ( server . colormap ) ;
XSetErrorHandler ( old ) ;
goto on_error ;
2015-07-19 14:49:05 +00:00
} else {
if ( traywin - > image ) {
imlib_context_set_image ( traywin - > image ) ;
imlib_free_image_and_decache ( ) ;
}
traywin - > image = image ;
2015-06-12 10:24:19 +00:00
}
2010-01-06 19:30:55 +00:00
2015-07-19 14:49:05 +00:00
imlib_context_set_image ( traywin - > image ) ;
2010-04-22 15:08:21 +00:00
//if (traywin->depth == 24)
2015-06-07 09:44:43 +00:00
//imlib_save_image("/home/thil77/test.jpg");
2010-01-03 20:17:46 +00:00
imlib_image_set_has_alpha ( 1 ) ;
DATA32 * data = imlib_image_get_data ( ) ;
2010-02-28 07:58:50 +00:00
if ( traywin - > depth = = 24 ) {
2010-01-03 00:33:07 +00:00
createHeuristicMask ( data , traywin - > width , traywin - > height ) ;
}
2015-06-14 08:51:30 +00:00
int empty = imageEmpty ( data , traywin - > width , traywin - > height ) ;
2010-01-03 20:17:46 +00:00
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 ) ;
2015-07-19 14:49:05 +00:00
systray_render_icon_from_image ( traywin ) ;
2010-01-06 19:47:12 +00:00
2010-01-26 18:32:00 +00:00
if ( traywin - > damage )
XDamageSubtract ( server . dsp , traywin - > damage , None , None ) ;
2015-06-12 10:24:19 +00:00
XSync ( server . dsp , False ) ;
XSetErrorHandler ( old ) ;
if ( error )
goto on_error ;
2015-06-14 08:51:30 +00:00
if ( traywin - > empty ! = empty ) {
traywin - > empty = empty ;
2015-06-14 09:39:51 +00:00
systray . list_icons = g_slist_sort ( systray . list_icons , compare_traywindows ) ;
// Resize and redraw the systray
2015-06-21 12:50:08 +00:00
if ( systray_profile )
fprintf ( stderr , BLUE " [%f] %s:%d trigger resize & redraw \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2015-06-14 08:51:30 +00:00
systray . area . resize = 1 ;
2015-06-14 09:39:51 +00:00
systray . area . redraw = 1 ;
panel - > area . resize = 1 ;
2015-06-14 08:51:30 +00:00
panel_refresh = 1 ;
2015-06-14 09:39:51 +00:00
refresh_systray = 1 ;
2015-06-14 08:51:30 +00:00
}
2015-07-16 12:01:57 +00:00
panel_refresh = 1 ;
2015-06-14 08:51:30 +00:00
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-06-19 08:46:29 +00:00
2015-06-12 10:24:19 +00:00
return ;
on_error :
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " systray %d: rendering error for icon %lu (%s) pid %d \n " RESET , __LINE__ , traywin - > win , traywin - > name , traywin - > pid ) ;
2015-06-13 09:32:22 +00:00
return ;
on_systray_error :
2015-06-21 12:50:08 +00:00
fprintf ( stderr , RED " systray %d: rendering error for icon %lu (%s) pid %d. "
" Disabling compositing and restarting systray... \n " RESET , __LINE__ , traywin - > win , traywin - > name , traywin - > pid ) ;
2015-06-12 10:24:19 +00:00
systray_composited = 0 ;
stop_net ( ) ;
start_net ( ) ;
return ;
2010-01-06 19:47:12 +00:00
}
2010-01-07 21:23:15 +00:00
2015-06-14 09:21:42 +00:00
void systray_render_icon ( void * t )
2010-01-06 19:47:12 +00:00
{
2015-06-14 09:21:42 +00:00
TrayWindow * traywin = t ;
2015-06-19 08:46:29 +00:00
if ( systray_profile )
2015-06-21 12:50:08 +00:00
fprintf ( stderr , " [%f] %s:%d win = %lu (%s) \n " , profiling_get_time ( ) , __FUNCTION__ , __LINE__ , traywin - > win , traywin - > name ) ;
2015-07-19 14:12:02 +00:00
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 ;
}
{
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 ) ) {
2015-06-14 08:51:30 +00:00
stop_timeout ( traywin - > render_timeout ) ;
2015-07-19 14:49:05 +00:00
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 ) ;
2015-07-19 14:12:02 +00:00
XSetErrorHandler ( old ) ;
2015-06-14 08:51:30 +00:00
return ;
2015-07-19 14:12:02 +00:00
} else {
if ( xpos ! = 0 | | ypos ! = 0 | | width ! = traywin - > width | | height ! = traywin - > height ) {
stop_timeout ( traywin - > render_timeout ) ;
2015-07-19 14:49:05 +00:00
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 ) ;
2015-07-19 14:12:02 +00:00
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 ;
}
2015-06-14 08:51:30 +00:00
}
2015-07-19 14:12:02 +00:00
XSetErrorHandler ( old ) ;
2015-06-14 08:51:30 +00:00
}
2015-06-07 10:45:48 +00:00
2015-07-19 14:12:02 +00:00
fprintf ( stderr , " rendering tray icon \n " ) ;
2015-06-07 09:44:43 +00:00
if ( systray_composited ) {
2015-06-14 09:21:42 +00:00
systray_render_icon_composited ( traywin ) ;
2015-06-07 10:45:48 +00:00
} else {
// Trigger window repaint
2015-07-16 06:53:25 +00:00
if ( systray_profile )
fprintf ( stderr , " XClearArea(server.dsp, traywin->parent = %ld, 0, 0, traywin->width, traywin->height, True) \n " , traywin - > parent ) ;
2015-07-16 18:04:25 +00:00
XClearArea ( server . dsp , traywin - > parent , 0 , 0 , 0 , 0 , True ) ;
2015-07-16 06:53:25 +00:00
if ( systray_profile )
fprintf ( stderr , " XClearArea(server.dsp, traywin->win = %ld, 0, 0, traywin->width, traywin->height, True) \n " , traywin - > win ) ;
2015-07-16 18:04:25 +00:00
XClearArea ( server . dsp , traywin - > win , 0 , 0 , 0 , 0 , True ) ;
2010-01-30 23:06:07 +00:00
}
2010-01-03 00:33:07 +00:00
}
2015-06-21 12:50:08 +00:00
void refresh_systray_icons ( )
2009-06-13 19:39:41 +00:00
{
2015-06-21 12:50:08 +00:00
if ( systray_profile )
fprintf ( stderr , BLUE " [%f] %s:%d \n " RESET , profiling_get_time ( ) , __FUNCTION__ , __LINE__ ) ;
2009-06-13 19:39:41 +00:00
TrayWindow * traywin ;
GSList * l ;
for ( l = systray . list_icons ; l ; l = l - > next ) {
traywin = ( TrayWindow * ) l - > data ;
2015-05-11 19:19:36 +00:00
if ( traywin - > hide )
continue ;
2010-01-30 23:06:07 +00:00
systray_render_icon ( traywin ) ;
2009-06-13 19:39:41 +00:00
}
}
2015-01-31 11:02:35 +00:00
int systray_on_monitor ( int i_monitor , int nb_panels )
{
return ( i_monitor = = systray_monitor ) | |
( i_monitor = = 0 & & ( systray_monitor > = nb_panels | | systray_monitor < 0 ) ) ;
}