fixed bug : clock resize when date changed, number of desktop changed

git-svn-id: http://tint2.googlecode.com/svn/trunk@51 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
This commit is contained in:
lorthiois@bbsoft.fr 2009-02-10 23:16:10 +00:00
parent b73b15d4be
commit 6c57698291
21 changed files with 509 additions and 361 deletions

View file

@ -1,3 +1,7 @@
2009-02-11
- fixed bug with number of desktop changed
- fixed clock resize when date changed
2009-02-08 2009-02-08
- backward compatibility with tint-0.6 (convert config file) - backward compatibility with tint-0.6 (convert config file)
feature freeze until next release. need bug correction. feature freeze until next release. need bug correction.

View file

@ -1,8 +1,8 @@
CFLAGS= -O2 CFLAGS= -O2
CC = gcc CC = gcc
FLAGS=-W -Wall -g `pkg-config --cflags --libs cairo pangocairo x11 xinerama imlib2 glib-2.0` FLAGS=-W -g `pkg-config --cflags --libs cairo pangocairo x11 xinerama imlib2 glib-2.0`
PROGNAME=tint2 PROGNAME=tint2
FILES=tint.c server.c panel.c config.c taskbar/task.c taskbar/taskbar.c clock/clock.c systray/systraybar.c systray/docker.c systray/icons.c systray/kde.c systray/net.c systray/xproperty.c util/window.c util/area.c FILES=tint.c server.c panel.c config.c taskbar/task.c taskbar/taskbar.c clock/clock.c systray/systraybar.c util/window.c util/area.c
ifndef DESTDIR ifndef DESTDIR
ifndef PREFIX ifndef PREFIX

View file

@ -37,18 +37,19 @@ struct timeval time_clock;
int time_precision; int time_precision;
PangoFontDescription *time1_font_desc; PangoFontDescription *time1_font_desc;
PangoFontDescription *time2_font_desc; PangoFontDescription *time2_font_desc;
static char buf_time[40];
static char buf_date[40];
void init_clock(Clock *clock, Area *parent) void init_clock(Clock *clock, Area *parent)
{ {
Panel *panel = (Panel *)parent; Panel *panel = (Panel *)parent;
char buf_time[40];
char buf_date[40];
int time_height, time_height_ink, date_height, date_height_ink; int time_height, time_height_ink, date_height, date_height_ink;
clock->area.parent = parent; clock->area.parent = parent;
clock->area.panel = panel; clock->area.panel = panel;
clock->area.draw_foreground = draw_foreground_clock; clock->area._draw_foreground = draw_foreground_clock;
clock->area._resize = resize_clock;
if (!time1_format) return; if (!time1_format) return;
if (strchr(time1_format, 'S') == NULL) time_precision = 60; if (strchr(time1_format, 'S') == NULL) time_precision = 60;
@ -62,7 +63,7 @@ void init_clock(Clock *clock, Area *parent)
clock->area.posy = parent->pix.border.width + parent->paddingy; clock->area.posy = parent->pix.border.width + parent->paddingy;
clock->area.height = parent->height - (2 * clock->area.posy); clock->area.height = parent->height - (2 * clock->area.posy);
clock->area.width = 0; // force posx and width detection clock->area.resize = 1;
clock->area.redraw = 1; clock->area.redraw = 1;
strftime(buf_time, sizeof(buf_time), time1_format, localtime(&time_clock.tv_sec)); strftime(buf_time, sizeof(buf_time), time1_format, localtime(&time_clock.tv_sec));
@ -83,48 +84,12 @@ void init_clock(Clock *clock, Area *parent)
void draw_foreground_clock (void *obj, cairo_t *c, int active) void draw_foreground_clock (void *obj, cairo_t *c, int active)
{ {
Area *parent = ((Area*)obj)->parent;
Clock *clock = obj; Clock *clock = obj;
PangoLayout *layout; PangoLayout *layout;
char buf_time[40];
char buf_date[40];
int time_width, date_width, new_width;
time_width = date_width = 0; //printf(" draw_foreground_clock : %s en (%d, %d)\n", buf_time, clock->area.posx, clock->area.width);
strftime(buf_time, sizeof(buf_time), time1_format, localtime(&time_clock.tv_sec));
if (time2_format)
strftime(buf_date, sizeof(buf_date), time2_format, localtime(&time_clock.tv_sec));
//printf(" draw_foreground_clock : %s\n", buf_time);
redraw:
layout = pango_cairo_create_layout (c); layout = pango_cairo_create_layout (c);
// check width
pango_layout_set_font_description (layout, time1_font_desc);
pango_layout_set_indent(layout, 0);
pango_layout_set_text (layout, buf_time, strlen(buf_time));
pango_layout_get_pixel_size (layout, &time_width, NULL);
if (time2_format) {
pango_layout_set_font_description (layout, time2_font_desc);
pango_layout_set_indent(layout, 0);
pango_layout_set_text (layout, buf_date, strlen(buf_date));
pango_layout_get_pixel_size (layout, &date_width, NULL);
}
if (time_width > date_width) new_width = time_width;
else new_width = date_width;
new_width += (2*clock->area.paddingxlr) + (2*clock->area.pix.border.width);
if (new_width > clock->area.width || (new_width != clock->area.width && date_width > time_width)) {
//printf("clock_width %d, new_width %d\n", clock->area.width, new_width);
// resize clock
clock->area.width = new_width;
clock->area.posx = parent->width - clock->area.width - parent->paddingxlr - parent->pix.border.width;
g_object_unref (layout);
resize_taskbar(parent);
goto redraw;
}
// draw layout // draw layout
pango_layout_set_font_description (layout, time1_font_desc); pango_layout_set_font_description (layout, time1_font_desc);
pango_layout_set_width (layout, clock->area.width * PANGO_SCALE); pango_layout_set_width (layout, clock->area.width * PANGO_SCALE);
@ -151,3 +116,56 @@ redraw:
g_object_unref (layout); g_object_unref (layout);
} }
void resize_clock (void *obj)
{
Area *parent = ((Area*)obj)->parent;
Clock *clock = obj;
PangoLayout *layout;
int time_width, date_width, new_width;
time_width = date_width = 0;
strftime(buf_time, sizeof(buf_time), time1_format, localtime(&time_clock.tv_sec));
if (time2_format)
strftime(buf_date, sizeof(buf_date), time2_format, localtime(&time_clock.tv_sec));
//printf(" resize_clock\n");
cairo_surface_t *cs;
cairo_t *c;
Pixmap pmap;
pmap = XCreatePixmap (server.dsp, server.root_win, clock->area.width, clock->area.height, server.depth);
cs = cairo_xlib_surface_create (server.dsp, pmap, server.visual, clock->area.width, clock->area.height);
c = cairo_create (cs);
layout = pango_cairo_create_layout (c);
// check width
pango_layout_set_font_description (layout, time1_font_desc);
pango_layout_set_indent(layout, 0);
pango_layout_set_text (layout, buf_time, strlen(buf_time));
pango_layout_get_pixel_size (layout, &time_width, NULL);
if (time2_format) {
pango_layout_set_font_description (layout, time2_font_desc);
pango_layout_set_indent(layout, 0);
pango_layout_set_text (layout, buf_date, strlen(buf_date));
pango_layout_get_pixel_size (layout, &date_width, NULL);
}
if (time_width > date_width) new_width = time_width;
else new_width = date_width;
new_width += (2*clock->area.paddingxlr) + (2*clock->area.pix.border.width);
if (new_width > clock->area.width || new_width < (clock->area.width-3)) {
// resize clock
//printf("clock_width %d, new_width %d\n", clock->area.width, new_width);
clock->area.width = new_width;
clock->area.posx = parent->width - clock->area.width - parent->paddingxlr - parent->pix.border.width;
set_resize(parent);
}
g_object_unref (layout);
cairo_destroy (c);
cairo_surface_destroy (cs);
XFreePixmap (server.dsp, pmap);
}

View file

@ -37,5 +37,6 @@ void init_clock(Clock *clock, Area *parent);
void draw_foreground_clock (void *obj, cairo_t *c, int active); void draw_foreground_clock (void *obj, cairo_t *c, int active);
void resize_clock (void *obj);
#endif #endif

View file

@ -38,6 +38,7 @@
#include "server.h" #include "server.h"
#include "task.h" #include "task.h"
#include "taskbar.h" #include "taskbar.h"
#include "systraybar.h"
#include "clock.h" #include "clock.h"
#include "panel.h" #include "panel.h"
#include "config.h" #include "config.h"
@ -409,6 +410,14 @@ void add_entry (char *key, char *value)
memcpy(&panel_config->g_task.area.pix_active.border, &a->pix.border, sizeof(Border)); memcpy(&panel_config->g_task.area.pix_active.border, &a->pix.border, sizeof(Border));
} }
/* Trayer */
else if (strcmp (key, "trayer_background_id") == 0) {
int id = atoi (value);
Area *a = g_slist_nth_data(list_back, id);
memcpy(&panel_config->trayer.area.pix.back, &a->pix.back, sizeof(Color));
memcpy(&panel_config->trayer.area.pix.border, &a->pix.border, sizeof(Border));
}
/* Mouse actions */ /* Mouse actions */
else if (strcmp (key, "mouse_middle") == 0) else if (strcmp (key, "mouse_middle") == 0)
get_action (value, &mouse_middle); get_action (value, &mouse_middle);
@ -539,20 +548,18 @@ void config_finish ()
fprintf(stderr, "tint2 exit : monitor %d not found.\n", panel_config->monitor+1); fprintf(stderr, "tint2 exit : monitor %d not found.\n", panel_config->monitor+1);
exit(0); exit(0);
} }
else {
if (!server.monitor[panel_config->monitor].width || !server.monitor[panel_config->monitor].height)
fprintf(stderr, "tint2 error : invalid monitor size.\n");
}
// alloc panels // alloc panels
int i; int i;
if (panel_config->monitor >= 0) { if (panel_config->monitor >= 0) {
// just one monitor
nb_panel = 1; nb_panel = 1;
panel1 = calloc(nb_panel, sizeof(Panel)); panel1 = calloc(nb_panel, sizeof(Panel));
memcpy(panel1, panel_config, sizeof(Panel)); memcpy(panel1, panel_config, sizeof(Panel));
panel1->monitor = panel_config->monitor;
} }
else { else {
// multi monitor // all monitors
nb_panel = server.nb_monitor; nb_panel = server.nb_monitor;
panel1 = calloc(nb_panel, sizeof(Panel)); panel1 = calloc(nb_panel, sizeof(Panel));
@ -566,10 +573,14 @@ void config_finish ()
init_taskbar(); init_taskbar();
visible_object(); visible_object();
task_refresh_tasklist();
panel_refresh = 1;
cleanup_config(); cleanup_config();
// force the resize (using visible_object() order)
for (i=0 ; i < nb_panel ; i++) {
//init_systray(&panel1[i].trayer, &panel1[i].area);
set_resize(&panel1[i]);
}
task_refresh_tasklist();
} }

View file

@ -115,6 +115,7 @@ void init_panel()
init_clock(&p->clock, &p->area); init_clock(&p->clock, &p->area);
} }
panel_refresh = 1;
} }
@ -129,10 +130,17 @@ void cleanup_panel()
for (i=0 ; i < nb_panel ; i++) { for (i=0 ; i < nb_panel ; i++) {
p = &panel1[i]; p = &panel1[i];
free_area(&p->area); // no free_area(&p->area) because it's the list of visible objects
if (p->area.list) {
g_slist_free(p->area.list);
p->area.list = 0;
}
free_area(&p->g_task.area); free_area(&p->g_task.area);
free_area(&p->g_taskbar); free_area(&p->g_taskbar);
free_area(&p->clock.area); free_area(&p->clock.area);
if (p->area.pix.pmap) XFreePixmap(server.dsp, p->area.pix.pmap);
if (p->area.pix_active.pmap) XFreePixmap(server.dsp, p->area.pix_active.pmap);
if (p->root_pmap) XFreePixmap(server.dsp, p->root_pmap); if (p->root_pmap) XFreePixmap(server.dsp, p->root_pmap);
if (p->main_win) XDestroyWindow(server.dsp, p->main_win); if (p->main_win) XDestroyWindow(server.dsp, p->main_win);
} }
@ -154,8 +162,9 @@ void visual_refresh (Panel *p)
// draw child object // draw child object
GSList *l = p->area.list; GSList *l = p->area.list;
for (; l ; l = l->next) for (; l ; l = l->next) {
refresh (l->data); refresh (l->data);
}
XCopyArea(server.dsp, p->root_pmap, p->main_win, server.gc, 0, 0, p->area.width, p->area.height, 0, 0); XCopyArea(server.dsp, p->root_pmap, p->main_win, server.gc, 0, 0, p->area.width, p->area.height, 0, 0);
@ -244,6 +253,8 @@ void visible_object()
if (time1_format) if (time1_format)
panel->area.list = g_slist_append(panel->area.list, &panel->clock); panel->area.list = g_slist_append(panel->area.list, &panel->clock);
//panel->area.list = g_slist_append(panel->area.list, &panel->trayer);
Taskbar *taskbar; Taskbar *taskbar;
for (j=0 ; j < panel->nb_desktop ; j++) { for (j=0 ; j < panel->nb_desktop ; j++) {
taskbar = &panel->taskbar[j]; taskbar = &panel->taskbar[j];

View file

@ -61,7 +61,7 @@ typedef struct {
int monitor; int monitor;
// -------------------------------------------------- // --------------------------------------------------
// task annd taskbar parameter per panel // task and taskbar parameter per panel
Area g_taskbar; Area g_taskbar;
Global_task g_task; Global_task g_task;
@ -77,7 +77,10 @@ typedef struct {
// -------------------------------------------------- // --------------------------------------------------
// systray // systray
Systraybar systraybar; Systraybar trayer;
// global taskbar parameter
//Area g_systraybar;
} Panel; } Panel;

View file

@ -28,6 +28,8 @@
void server_catch_error (Display *d, XErrorEvent *ev){} void server_catch_error (Display *d, XErrorEvent *ev){}
static char *name_trayer = 0;
void server_init_atoms () void server_init_atoms ()
{ {
@ -68,6 +70,19 @@ void server_init_atoms ()
server.atom.WM_NAME = XInternAtom(server.dsp, "WM_NAME", False); server.atom.WM_NAME = XInternAtom(server.dsp, "WM_NAME", False);
server.atom.__SWM_VROOT = XInternAtom(server.dsp, "__SWM_VROOT", False); server.atom.__SWM_VROOT = XInternAtom(server.dsp, "__SWM_VROOT", False);
server.atom._MOTIF_WM_HINTS = XInternAtom(server.dsp, "_MOTIF_WM_HINTS", False); server.atom._MOTIF_WM_HINTS = XInternAtom(server.dsp, "_MOTIF_WM_HINTS", False);
// systray protocol
name_trayer = g_strdup_printf("_NET_SYSTEM_TRAY_S%d", DefaultScreen(server.dsp));
server.atom._NET_SYSTEM_TRAY = XInternAtom(server.dsp, name_trayer, False);
server.atom._NET_SYSTEM_TRAY_OPCODE = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_OPCODE", False);
server.atom.MANAGER = XInternAtom(server.dsp, "MANAGER", False);
server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
}
void cleanup_server()
{
if (name_trayer) free(name_trayer);
} }

View file

@ -53,6 +53,10 @@ typedef struct Global_atom
Atom WM_NAME; Atom WM_NAME;
Atom __SWM_VROOT; Atom __SWM_VROOT;
Atom _MOTIF_WM_HINTS; Atom _MOTIF_WM_HINTS;
Atom _NET_SYSTEM_TRAY;
Atom _NET_SYSTEM_TRAY_OPCODE;
Atom MANAGER;
Atom _NET_SYSTEM_TRAY_MESSAGE_DATA;
} Global_atom; } Global_atom;

View file

@ -28,85 +28,6 @@ int icon_size = 24; /* width and height of systray icons */
static gboolean exit_app = FALSE; static gboolean exit_app = FALSE;
/* /*
void parse_cmd_line()
{
int i;
gboolean help = FALSE;
for (i = 1; i < argc; i++) {
if (0 == strcasecmp(argv[i], "-display")) {
++i;
if (i < argc) {
display_string = argv[i];
} else {
g_printerr("-display requires a parameter\n");
help = TRUE;
}
} else if (0 == strcasecmp(argv[i], "-wmaker")) {
wmaker = TRUE;
} else if (0 == strcasecmp(argv[i], "-vertical")) {
horizontal = FALSE;
} else if (0 == strcasecmp(argv[i], "-border")) {
++i;
if (i < argc) {
int b = atoi(argv[i]);
if (b > 0) {
border = b;
} else {
g_printerr("-border must be a value greater than 0\n");
help = TRUE;
}
} else {
g_printerr("-border requires a parameter\n");
help = TRUE;
}
} else if (0 == strcasecmp(argv[i], "-iconsize")) {
++i;
if (i < argc) {
int s = atoi(argv[i]);
if (s > 0) {
icon_size = s;
} else {
g_printerr("-iconsize must be a value greater than 0\n");
help = TRUE;
}
} else {
g_printerr("-iconsize requires a parameter\n");
help = TRUE;
}
} else {
if (argv[i][0] == '-')
help = TRUE;
}
if (help) {
g_print("%s - version %s\n", argv[0], VERSION);
g_print("Copyright 2003, Ben Jansens <ben@orodu.net>\n\n");
g_print("Usage: %s [OPTIONS]\n\n", argv[0]);
g_print("Options:\n");
g_print(" -help Show this help.\n");
g_print(" -display DISLPAY The X display to connect to.\n");
g_print(" -border The width of the border to put around the\n"
" system tray icons. Defaults to 1.\n");
g_print(" -vertical Line up the icons vertically. Defaults to\n"
" horizontally.\n");
g_print(" -wmaker WindowMaker mode. This makes docker a\n"
" fixed size (64x64) to appear nicely in\n"
" in WindowMaker.\n"
" Note: In this mode, you have a fixed\n"
" number of icons that docker can hold.\n");
g_print(" -iconsize SIZE The size (width and height) to display\n"
" icons as in the system tray. Defaults to\n"
" 24.\n");
exit(1);
}
}
}
*/
void create_hint_win() void create_hint_win()
{ {
XWMHints hints; XWMHints hints;
@ -136,7 +57,7 @@ void create_main_window()
XTextProperty text; XTextProperty text;
char *name = "Docker"; char *name = "Docker";
/* the border must be > 0 if not in wmaker mode */ // the border must be > 0 if not in wmaker mode
assert(wmaker || border > 0); assert(wmaker || border > 0);
if (!wmaker) if (!wmaker)
@ -161,7 +82,7 @@ void create_main_window()
XSetWindowBackgroundPixmap(display, win, ParentRelative); XSetWindowBackgroundPixmap(display, win, ParentRelative);
XClearWindow(display, win); XClearWindow(display, win);
} }
*/
void reposition_icons() void reposition_icons()
{ {
@ -193,10 +114,10 @@ void fix_geometry()
{ {
GSList *it; GSList *it;
/* in wmaker mode we're a fixed size */ // in wmaker mode we're a fixed size
if (wmaker) return; if (wmaker) return;
/* find the proper width and height */ //* find the proper width and height
width = horizontal ? 0 : icon_size; width = horizontal ? 0 : icon_size;
height = horizontal ? icon_size : 0; height = horizontal ? icon_size : 0;
for (it = icons; it != NULL; it = g_slist_next(it)) { for (it = icons; it != NULL; it = g_slist_next(it)) {
@ -209,93 +130,6 @@ void fix_geometry()
XResizeWindow(display, win, width + border * 2, height + border * 2); XResizeWindow(display, win, width + border * 2, height + border * 2);
} }
void event_loop()
{
XEvent e;
Window cover;
GSList *it;
while (!exit_app) {
while (XPending(display)) {
XNextEvent(display, &e);
switch (e.type)
{
case PropertyNotify:
/* systray window list has changed? */
if (e.xproperty.atom == kde_systray_prop) {
XSelectInput(display, win, NoEventMask);
kde_update_icons();
XSelectInput(display, win, StructureNotifyMask);
while (XCheckTypedEvent(display, PropertyNotify, &e));
}
break;
case ConfigureNotify:
if (e.xany.window != win) {
/* find the icon it pertains to and beat it into submission */
GSList *it;
for (it = icons; it != NULL; it = g_slist_next(it)) {
TrayWindow *traywin = it->data;
if (traywin->id == e.xany.window) {
XMoveResizeWindow(display, traywin->id, traywin->x, traywin->y,
icon_size, icon_size);
break;
}
}
break;
}
/* briefly cover the entire containing window, which causes it and
all of the icons to refresh their windows. finally, they update
themselves when the background of the main window's parent changes.
*/
cover = XCreateSimpleWindow(display, win, 0, 0,
border * 2 + width, border * 2 + height,
0, 0, 0);
XMapWindow(display, cover);
XDestroyWindow(display, cover);
break;
case ReparentNotify:
if (e.xany.window == win) /* reparented to us */
break;
case UnmapNotify:
case DestroyNotify:
for (it = icons; it; it = g_slist_next(it)) {
if (((TrayWindow*)it->data)->id == e.xany.window) {
icon_remove(it);
break;
}
}
break;
case ClientMessage:
if (e.xclient.message_type == net_opcode_atom &&
e.xclient.format == 32 &&
e.xclient.window == net_sel_win)
net_message(&e.xclient);
default:
break;
}
}
usleep(500000);
}
/* remove/unparent all the icons */
while (icons) {
/* do the remove here explicitly, cuz the event handler isn't going to
happen anymore. */
icon_remove(icons);
}
}
/* /*
int main(int c, char **v) int main(int c, char **v)
{ {

View file

@ -28,38 +28,11 @@ static void net_destroy_selection_window()
net_sel_win = None; net_sel_win = None;
} }
void net_icon_remove(TrayWindow *traywin)
void net_init()
{ {
char *name; assert(traywin);
XEvent m;
name = g_strdup_printf("_NET_SYSTEM_TRAY_S%d", DefaultScreen(display)); XSelectInput(display, traywin->id, NoEventMask);
net_sel_atom = XInternAtom(display, name, False);
assert(net_sel_atom);
net_opcode_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False);
assert(net_opcode_atom);
net_manager_atom = XInternAtom(display, "MANAGER", False);
assert(net_manager_atom);
net_message_data_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_MESSAGE_DATA",
False);
assert(net_message_data_atom);
net_create_selection_window();
XSetSelectionOwner(display, net_sel_atom, net_sel_win, CurrentTime);
if (XGetSelectionOwner(display, net_sel_atom) != net_sel_win)
return; /* we don't get the selection */
m.type = ClientMessage;
m.xclient.message_type = net_manager_atom;
m.xclient.format = 32;
m.xclient.data.l[0] = CurrentTime;
m.xclient.data.l[1] = net_sel_atom;
m.xclient.data.l[2] = net_sel_win;
m.xclient.data.l[3] = 0;
m.xclient.data.l[4] = 0;
XSendEvent(display, root, False, StructureNotifyMask, &m);
} }
@ -69,51 +42,3 @@ void net_destroy()
} }
void net_message(XClientMessageEvent *e)
{
unsigned long opcode;
Window id;
assert(e);
opcode = e->data.l[1];
switch (opcode)
{
case SYSTEM_TRAY_REQUEST_DOCK: /* dock a new icon */
id = e->data.l[2];
if (id && icon_add(id, NET))
XSelectInput(display, id, StructureNotifyMask);
break;
case SYSTEM_TRAY_BEGIN_MESSAGE:
g_printerr("Message From Dockapp\n");
id = e->window;
break;
case SYSTEM_TRAY_CANCEL_MESSAGE:
g_printerr("Message Cancelled\n");
id = e->window;
break;
default:
if (opcode == net_message_data_atom) {
g_printerr("Text For Message From Dockapp:\n%s\n", e->data.b);
id = e->window;
break;
}
/* unknown message type. not in the spec. */
g_printerr("Warning: Received unknown client message to System Tray "
"selection window.\n");
break;
}
}
void net_icon_remove(TrayWindow *traywin)
{
assert(traywin);
XSelectInput(display, traywin->id, NoEventMask);
}

View file

@ -27,9 +27,43 @@
#include "systraybar.h" #include "systraybar.h"
#include "server.h" #include "server.h"
#include "window.h" #include "panel.h"
GSList *icons;
/* defined in the systray spec */
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
Window net_sel_win;
void init_systray(Systraybar *sysbar, Area *parent)
{
Panel *panel = (Panel *)parent;
sysbar->area.parent = parent;
sysbar->area.panel = panel;
sysbar->area.posy = parent->pix.border.width + parent->paddingy;
sysbar->area.height = parent->height - (2 * sysbar->area.posy);
sysbar->area.width = 100;
sysbar->area.posx = panel->area.width - panel->clock.area.width - panel->area.paddingxlr - panel->area.pix.border.width - panel->area.paddingx - sysbar->area.width;
sysbar->area.redraw = 1;
printf("init_systray");
net_init();
}
// net_sel_atom == server.atom._NET_SYSTEM_TRAY
// net_opcode_atom == server.atom._NET_SYSTEM_TRAY_OPCODE
// net_manager_atom == server.atom.MANAGER
// net_message_data_atom == server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA
int resize_systray (Systraybar *sysbar) int resize_systray (Systraybar *sysbar)
{ {
@ -38,3 +72,254 @@ int resize_systray (Systraybar *sysbar)
Window win, root;
int width, height;
int border;
int icon_size;
void fix_geometry()
{
GSList *it;
//* find the proper width and height
width = 0;
height = icon_size;
for (it = icons; it != NULL; it = g_slist_next(it)) {
width += icon_size;
}
XResizeWindow(server.dsp, win, width + border * 2, height + border * 2);
}
static void net_create_selection_window()
{
net_sel_win = XCreateSimpleWindow(server.dsp, root, -1, -1, 1, 1, 0, 0, 0);
}
gboolean error;
int window_error_handler(Display *d, XErrorEvent *e)
{
d=d;e=e;
if (e->error_code == BadWindow) {
error = TRUE;
} else {
//g_printerr("X ERROR NOT BAD WINDOW!\n");
abort();
}
return 0;
}
gboolean icon_swallow(TrayWindow *traywin)
{
XErrorHandler old;
error = FALSE;
old = XSetErrorHandler(window_error_handler);
XReparentWindow(server.dsp, traywin->id, win, 0, 0);
XSync(server.dsp, False);
XSetErrorHandler(old);
return !error;
}
// The traywin must have its id and type set.
gboolean icon_add(Window id)
{
TrayWindow *traywin;
traywin = g_new0(TrayWindow, 1);
traywin->id = id;
if (!icon_swallow(traywin)) {
g_free(traywin);
return FALSE;
}
// find the positon for the systray app window
int count = g_slist_length(icons);
traywin->x = border + ((width % icon_size) / 2) +
(count % (width / icon_size)) * icon_size;
traywin->y = border + ((height % icon_size) / 2) +
(count / (height / icon_size)) * icon_size;
// add the new icon to the list
icons = g_slist_append(icons, traywin);
// watch for the icon trying to resize itself!
XSelectInput(server.dsp, traywin->id, StructureNotifyMask);
// position and size the icon window
XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, icon_size, icon_size);
// resize our window so that the new window can fit in it
fix_geometry();
// flush before clearing, otherwise the clear isn't effective.
XFlush(server.dsp);
// make sure the new child will get the right stuff in its background
// for ParentRelative.
XClearWindow(server.dsp, win);
// show the window
XMapRaised(server.dsp, traywin->id);
return TRUE;
}
void net_init()
{
// init systray protocol
net_sel_win = XCreateSimpleWindow(server.dsp, server.root_win, -1, -1, 1, 1, 0, 0, 0);
XSetSelectionOwner(server.dsp, server.atom._NET_SYSTEM_TRAY, net_sel_win, CurrentTime);
if (XGetSelectionOwner(server.dsp, server.atom._NET_SYSTEM_TRAY) != net_sel_win) {
fprintf(stderr, "tint error : can't get trayer selection");
return;
}
XEvent m;
m.type = ClientMessage;
m.xclient.message_type = server.atom.MANAGER;
m.xclient.format = 32;
m.xclient.data.l[0] = CurrentTime;
m.xclient.data.l[1] = server.atom._NET_SYSTEM_TRAY;
m.xclient.data.l[2] = net_sel_win;
m.xclient.data.l[3] = 0;
m.xclient.data.l[4] = 0;
XSendEvent(server.dsp, server.root_win, False, StructureNotifyMask, &m);
}
void net_message(XClientMessageEvent *e)
{
unsigned long opcode;
Window id;
opcode = e->data.l[1];
switch (opcode)
{
case SYSTEM_TRAY_REQUEST_DOCK: /* dock a new icon */
id = e->data.l[2];
if (id && icon_add(id))
XSelectInput(server.dsp, id, StructureNotifyMask);
break;
case SYSTEM_TRAY_BEGIN_MESSAGE:
//g_printerr("Message From Dockapp\n");
id = e->window;
break;
case SYSTEM_TRAY_CANCEL_MESSAGE:
//g_printerr("Message Cancelled\n");
id = e->window;
break;
default:
if (opcode == server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA) {
//g_printerr("Text For Message From Dockapp:\n%s\n", e->data.b);
id = e->window;
break;
}
/* unknown message type. not in the spec. */
//g_printerr("Warning: Received unknown client message to System Tray selection window.\n");
break;
}
}
/*
void event_loop()
{
XEvent e;
Window cover;
GSList *it;
while (!exit_app) {
while (XPending(server.dsp)) {
XNextEvent(display, &e);
switch (e.type)
{
case PropertyNotify:
// systray window list has changed?
if (e.xproperty.atom == kde_systray_prop) {
XSelectInput(display, win, NoEventMask);
kde_update_icons();
XSelectInput(display, win, StructureNotifyMask);
while (XCheckTypedEvent(display, PropertyNotify, &e));
}
break;
case ConfigureNotify:
if (e.xany.window != win) {
// find the icon it pertains to and beat it into submission
GSList *it;
for (it = icons; it != NULL; it = g_slist_next(it)) {
TrayWindow *traywin = it->data;
if (traywin->id == e.xany.window) {
XMoveResizeWindow(display, traywin->id, traywin->x, traywin->y,
icon_size, icon_size);
break;
}
}
break;
}
// briefly cover the entire containing window, which causes it and
// all of the icons to refresh their windows. finally, they update
// themselves when the background of the main window's parent changes.
cover = XCreateSimpleWindow(display, win, 0, 0,
border * 2 + width, border * 2 + height,
0, 0, 0);
XMapWindow(display, cover);
XDestroyWindow(display, cover);
break;
case ReparentNotify:
if (e.xany.window == win) // reparented to us
break;
case UnmapNotify:
case DestroyNotify:
for (it = icons; it; it = g_slist_next(it)) {
if (((TrayWindow*)it->data)->id == e.xany.window) {
icon_remove(it);
break;
}
}
break;
case ClientMessage:
if (e.xclient.message_type == net_opcode_atom &&
e.xclient.format == 32 &&
e.xclient.window == net_sel_win)
net_message(&e.xclient);
default:
break;
}
}
usleep(500000);
}
// remove/unparent all the icons
while (icons) {
// do the remove here explicitly, cuz the event handler isn't going to
// happen anymore.
icon_remove(icons);
}
}
*/

View file

@ -18,11 +18,15 @@ typedef struct {
} Systraybar; } Systraybar;
// -------------------------------------------------- typedef struct
// global taskbar parameter {
Area g_systraybar; Window id;
int x, y;
} TrayWindow;
void init_systray(Systraybar *sysbar, Area *parent);
// return 1 if task_width changed // return 1 if task_width changed
int resize_systray (Systraybar *sysbar); int resize_systray (Systraybar *sysbar);

View file

@ -8,7 +8,7 @@
#ifndef TINT_MERGE_H #ifndef TINT_MERGE_H
#define TINT_MERGE_H #define TINT_MERGE_H
/*
#define display server.dsp #define display server.dsp
#define root server.root_win #define root server.root_win

View file

@ -91,6 +91,7 @@ void remove_task (Task *tsk)
if (!tsk) return; if (!tsk) return;
Window win = tsk->win; Window win = tsk->win;
int desktop = tsk->desktop;
// free title and icon just for the first task // free title and icon just for the first task
// even with task_on_all_desktop and with task_on_all_panel // even with task_on_all_desktop and with task_on_all_panel
@ -106,8 +107,7 @@ void remove_task (Task *tsk)
Taskbar *tskbar; Taskbar *tskbar;
for (i=0 ; i < nb_panel ; i++) { for (i=0 ; i < nb_panel ; i++) {
for (j=0 ; j < panel1[i].nb_desktop ; j++) { for (j=0 ; j < panel1[i].nb_desktop ; j++) {
if (tsk->desktop != ALLDESKTOP && tsk->desktop != j) continue; if (desktop != ALLDESKTOP && desktop != j) continue;
//if (!panel1[i].taskbar) continue;
GSList *l0; GSList *l0;
tskbar = &panel1[i].taskbar[j]; tskbar = &panel1[i].taskbar[j];

View file

@ -43,12 +43,13 @@ void init_taskbar()
panel = &panel1[i]; panel = &panel1[i];
// taskbar // taskbar
panel->g_taskbar._resize = resize_taskbar;
panel->g_taskbar.posy = panel->area.pix.border.width + panel->area.paddingy; panel->g_taskbar.posy = panel->area.pix.border.width + panel->area.paddingy;
panel->g_taskbar.height = panel->area.height - (2 * panel->g_taskbar.posy); panel->g_taskbar.height = panel->area.height - (2 * panel->g_taskbar.posy);
panel->g_taskbar.redraw = 1; panel->g_taskbar.redraw = 1;
// task // task
panel->g_task.area.draw_foreground = draw_foreground_task; panel->g_task.area._draw_foreground = draw_foreground_task;
panel->g_task.area.posy = panel->g_taskbar.posy + panel->g_taskbar.pix.border.width + panel->g_taskbar.paddingy; panel->g_task.area.posy = panel->g_taskbar.posy + panel->g_taskbar.pix.border.width + panel->g_taskbar.paddingy;
panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy); panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy);
panel->g_task.area.use_active = 1; panel->g_task.area.use_active = 1;
@ -84,10 +85,7 @@ void init_taskbar()
memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area)); memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area));
tskbar->desktop = j; tskbar->desktop = j;
} }
resize_taskbar(panel);
} }
} }
@ -115,9 +113,11 @@ void cleanup_taskbar()
for (i=0 ; i < nb_panel ; i++) { for (i=0 ; i < nb_panel ; i++) {
panel = &panel1[i]; panel = &panel1[i];
if (panel->taskbar) {
free(panel->taskbar); free(panel->taskbar);
panel->taskbar = 0; panel->taskbar = 0;
} }
}
} }
@ -174,7 +174,7 @@ void task_refresh_tasklist ()
if (tsk->win == win[k]) break; if (tsk->win == win[k]) break;
} }
// careful : remove_task change l0->next // careful : remove_task change l0->next
if (tsk->win != win[k]) remove_task (tsk); if (k == num_results) remove_task (tsk);
} }
} }
} }
@ -198,6 +198,7 @@ int resize_tasks (Taskbar *taskbar)
// new task width for 'desktop' // new task width for 'desktop'
task_count = g_slist_length(taskbar->area.list); task_count = g_slist_length(taskbar->area.list);
if (!task_count) pixel_width = panel->g_task.maximum_width; if (!task_count) pixel_width = panel->g_task.maximum_width;
else { else {
taskbar_width = taskbar->area.width - (2 * panel->g_taskbar.pix.border.width) - (2 * panel->g_taskbar.paddingxlr); taskbar_width = taskbar->area.width - (2 * panel->g_taskbar.pix.border.width) - (2 * panel->g_taskbar.paddingxlr);
@ -239,9 +240,9 @@ int resize_tasks (Taskbar *taskbar)
// initialise taskbar posx and width // initialise taskbar posx and width
void resize_taskbar(void *p) void resize_taskbar(void *obj)
{ {
Panel *panel = p; Panel *panel = ((Area*)obj)->panel;
int taskbar_width, modulo_width, taskbar_on_screen; int taskbar_width, modulo_width, taskbar_on_screen;
if (panel_mode == MULTI_DESKTOP) taskbar_on_screen = panel->nb_desktop; if (panel_mode == MULTI_DESKTOP) taskbar_on_screen = panel->nb_desktop;
@ -250,6 +251,8 @@ void resize_taskbar(void *p)
taskbar_width = panel->area.width - (2 * panel->area.paddingxlr) - (2 * panel->area.pix.border.width); taskbar_width = panel->area.width - (2 * panel->area.paddingxlr) - (2 * panel->area.pix.border.width);
if (time1_format) if (time1_format)
taskbar_width -= (panel->clock.area.width + panel->area.paddingx); taskbar_width -= (panel->clock.area.width + panel->area.paddingx);
//taskbar_width -= (panel->trayer.area.width + panel->area.paddingx);
taskbar_width = (taskbar_width - ((taskbar_on_screen-1) * panel->area.paddingx)) / taskbar_on_screen; taskbar_width = (taskbar_width - ((taskbar_on_screen-1) * panel->area.paddingx)) / taskbar_on_screen;
if (taskbar_on_screen > 1) if (taskbar_on_screen > 1)
@ -272,6 +275,7 @@ void resize_taskbar(void *p)
modulo--; modulo--;
} }
set_redraw (&panel->taskbar[i].area);
resize_tasks(&panel->taskbar[i]); resize_tasks(&panel->taskbar[i]);
} }
} }

View file

@ -34,7 +34,7 @@ void task_refresh_tasklist ();
// return 1 if task_width changed // return 1 if task_width changed
int resize_tasks (Taskbar *tskbar); int resize_tasks (Taskbar *tskbar);
void resize_taskbar(void *panel); void resize_taskbar(void *obj);
#endif #endif

View file

@ -35,10 +35,8 @@
#include "config.h" #include "config.h"
#include "task.h" #include "task.h"
#include "taskbar.h" #include "taskbar.h"
#include "systraybar.h"
#include "panel.h" #include "panel.h"
#include "docker.h"
#include "net.h"
#include "kde.h"
void signal_handler(int sig) void signal_handler(int sig)
@ -74,14 +72,6 @@ void init ()
XSetErrorHandler ((XErrorHandler) server_catch_error); XSetErrorHandler ((XErrorHandler) server_catch_error);
// init systray
//display = server.dsp;
//root = RootWindow(display, DefaultScreen(display));
//create_main_window();
//kde_init();
//net_init();
//printf("ici 4\n");
imlib_context_set_display (server.dsp); imlib_context_set_display (server.dsp);
imlib_context_set_visual (server.visual); imlib_context_set_visual (server.visual);
imlib_context_set_colormap (DefaultColormap (server.dsp, server.screen)); imlib_context_set_colormap (DefaultColormap (server.dsp, server.screen));
@ -138,7 +128,7 @@ void event_button_press (XEvent *e)
if (panel_mode != MULTI_DESKTOP) { if (panel_mode != MULTI_DESKTOP) {
// drag and drop disabled // drag and drop disabled
//XLowerWindow (server.dsp, panel.main_win); XLowerWindow (server.dsp, panel->main_win);
return; return;
} }
@ -163,7 +153,7 @@ void event_button_press (XEvent *e)
} }
} }
//XLowerWindow (server.dsp, panel.main_win); XLowerWindow (server.dsp, panel->main_win);
} }
@ -202,7 +192,7 @@ void event_button_release (XEvent *e)
} }
// TODO: check better solution to keep window below // TODO: check better solution to keep window below
//XLowerWindow (server.dsp, panel.main_win); XLowerWindow (server.dsp, panel->main_win);
task_drag = 0; task_drag = 0;
return; return;
@ -238,7 +228,7 @@ suite:
} }
// to keep window below // to keep window below
//XLowerWindow (server.dsp, panel.main_win); XLowerWindow (server.dsp, panel->main_win);
} }
@ -259,6 +249,9 @@ void event_property_notify (Window win, Atom at)
cleanup_taskbar(); cleanup_taskbar();
init_taskbar(); init_taskbar();
visible_object(); visible_object();
for (i=0 ; i < nb_panel ; i++) {
set_resize(&panel1[i]);
}
task_refresh_tasklist(); task_refresh_tasklist();
panel_refresh = 1; panel_refresh = 1;
} }
@ -429,6 +422,7 @@ void event_timer()
int i; int i;
for (i=0 ; i < nb_panel ; i++) { for (i=0 ; i < nb_panel ; i++) {
panel1[i].clock.area.redraw = 1; panel1[i].clock.area.redraw = 1;
panel1[i].clock.area.resize = 1;
} }
panel_refresh = 1; panel_refresh = 1;
} }
@ -459,11 +453,6 @@ load_config:
} }
config_finish(); config_finish();
// BUG: refresh(clock) is needed here, but 'on the paper' it's not necessary.
for (i=0 ; i < nb_panel ; i++) {
refresh(&panel1[i].clock.area);
}
x11_fd = ConnectionNumber(server.dsp); x11_fd = ConnectionNumber(server.dsp);
XSync(server.dsp, False); XSync(server.dsp, False);
@ -500,7 +489,6 @@ load_config:
break; break;
case PropertyNotify: case PropertyNotify:
//printf("PropertyNotify %lx\n", e.xproperty.window);
event_property_notify (e.xproperty.window, e.xproperty.atom); event_property_notify (e.xproperty.window, e.xproperty.atom);
break; break;
@ -509,6 +497,25 @@ load_config:
goto load_config; goto load_config;
else else
event_configure_notify (e.xconfigure.window); event_configure_notify (e.xconfigure.window);
break;
case UnmapNotify:
case DestroyNotify:
/*
GSList *it;
for (it = icons; it; it = g_slist_next(it)) {
if (((TrayWindow*)it->data)->id == e.xany.window) {
icon_remove(it);
break;
}
}*/
break;
case ClientMessage:
break;
if (e.xclient.message_type == server.atom._NET_SYSTEM_TRAY_OPCODE && e.xclient.format == 32)
// && e.xclient.window == net_sel_win)
net_message(&e.xclient);
break; break;
} }
} }
@ -525,8 +532,10 @@ load_config:
} }
if (panel_refresh) { if (panel_refresh) {
for (i=0 ; i < nb_panel ; i++) for (i=0 ; i < nb_panel ; i++) {
visual_refresh(&panel1[i]); visual_refresh(&panel1[i]);
}
XFlush (server.dsp); XFlush (server.dsp);
panel_refresh = 0; panel_refresh = 0;
} }

BIN
src/tint2

Binary file not shown.

View file

@ -32,6 +32,13 @@
void refresh (Area *a) void refresh (Area *a)
{ {
if (a->resize) {
// resize can generate a redraw
if (a->_resize)
a->_resize(a);
a->resize = 0;
}
if (a->redraw) { if (a->redraw) {
//printf("draw pix\n"); //printf("draw pix\n");
draw(a, 0); draw(a, 0);
@ -61,6 +68,16 @@ void set_redraw (Area *a)
} }
void set_resize (Area *a)
{
a->resize = 1;
GSList *l;
for (l = a->list ; l ; l = l->next)
set_resize(l->data);
}
void draw (Area *a, int active) void draw (Area *a, int active)
{ {
Pixmap *pmap = (active == 0) ? (&a->pix.pmap) : (&a->pix_active.pmap); Pixmap *pmap = (active == 0) ? (&a->pix.pmap) : (&a->pix_active.pmap);
@ -80,8 +97,8 @@ void draw (Area *a, int active)
draw_background (a, c, active); draw_background (a, c, active);
if (a->draw_foreground) if (a->_draw_foreground)
a->draw_foreground(a, c, active); a->_draw_foreground(a, c, active);
cairo_destroy (c); cairo_destroy (c);
cairo_surface_destroy (cs); cairo_surface_destroy (cs);
@ -180,6 +197,8 @@ void free_area (Area *a)
g_slist_free(a->list); g_slist_free(a->list);
a->list = 0; a->list = 0;
} }
if (a->pix.pmap) XFreePixmap (server.dsp, a->pix.pmap);
if (a->pix_active.pmap) XFreePixmap (server.dsp, a->pix_active.pmap);
} }

View file

@ -60,8 +60,6 @@ typedef struct
} Pmap; } Pmap;
// TODO: isoler 'draw' de 'refresh'
// TODO: isoler les données locales des données communes aux freres
typedef struct { typedef struct {
// absolute coordinate in panel // absolute coordinate in panel
int posx, posy; int posx, posy;
@ -72,6 +70,8 @@ typedef struct {
// list of child : Area object // list of child : Area object
GSList *list; GSList *list;
// need compute position and width
int resize;
// need redraw Pixmap // need redraw Pixmap
int redraw; int redraw;
int use_active, is_active; int use_active, is_active;
@ -84,9 +84,10 @@ typedef struct {
void *panel; void *panel;
// each object can overwrite following function // each object can overwrite following function
void (*draw_foreground)(void *obj, cairo_t *c, int active); void (*_draw_foreground)(void *obj, cairo_t *c, int active);
void (*add_child)(void *obj); void (*_resize)(void *obj);
int (*remove_child)(void *obj); void (*_add_child)(void *obj);
int (*_remove_child)(void *obj);
} Area; } Area;