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
jump to
@@ -1,8 +1,8 @@
CFLAGS= -O2 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 -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 PREFIX
@@ -37,18 +37,19 @@ struct timeval time_clock;
int time_precision; PangoFontDescription *time1_font_desc; PangoFontDescription *time2_font_desc; +static char buf_time[40]; +static char buf_date[40]; void init_clock(Clock *clock, Area *parent) { Panel *panel = (Panel *)parent; - char buf_time[40]; - char buf_date[40]; int time_height, time_height_ink, date_height, date_height_ink; clock->area.parent = parent; 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 (strchr(time1_format, 'S') == NULL) time_precision = 60;@@ -62,7 +63,7 @@ time_clock.tv_sec -= time_clock.tv_sec % time_precision;
clock->area.posy = parent->pix.border.width + parent->paddingy; 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; strftime(buf_time, sizeof(buf_time), time1_format, localtime(&time_clock.tv_sec));@@ -83,11 +84,44 @@
void draw_foreground_clock (void *obj, cairo_t *c, int active) { + Clock *clock = obj; + PangoLayout *layout; + + //printf(" draw_foreground_clock : %s en (%d, %d)\n", buf_time, clock->area.posx, clock->area.width); + layout = pango_cairo_create_layout (c); + + // draw layout + pango_layout_set_font_description (layout, time1_font_desc); + pango_layout_set_width (layout, clock->area.width * PANGO_SCALE); + pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); + pango_layout_set_text (layout, buf_time, strlen(buf_time)); + + cairo_set_source_rgba (c, clock->font.color[0], clock->font.color[1], clock->font.color[2], clock->font.alpha); + + pango_cairo_update_layout (c, layout); + cairo_move_to (c, 0, clock->time1_posy); + pango_cairo_show_layout (c, layout); + + 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_set_width (layout, clock->area.width * PANGO_SCALE); + + pango_cairo_update_layout (c, layout); + cairo_move_to (c, 0, clock->time2_posy); + pango_cairo_show_layout (c, layout); + } + + g_object_unref (layout); +} + + +void resize_clock (void *obj) +{ Area *parent = ((Area*)obj)->parent; Clock *clock = obj; PangoLayout *layout; - char buf_time[40]; - char buf_date[40]; int time_width, date_width, new_width; time_width = date_width = 0;@@ -95,8 +129,14 @@ 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: + //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@@ -110,44 +150,22 @@ 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)) { + 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); - // 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 - pango_layout_set_font_description (layout, time1_font_desc); - pango_layout_set_width (layout, clock->area.width * PANGO_SCALE); - pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); - pango_layout_set_text (layout, buf_time, strlen(buf_time)); - - cairo_set_source_rgba (c, clock->font.color[0], clock->font.color[1], clock->font.color[2], clock->font.alpha); - - pango_cairo_update_layout (c, layout); - cairo_move_to (c, 0, clock->time1_posy); - pango_cairo_show_layout (c, layout); - - 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_set_width (layout, clock->area.width * PANGO_SCALE); - - pango_cairo_update_layout (c, layout); - cairo_move_to (c, 0, clock->time2_posy); - pango_cairo_show_layout (c, layout); + set_resize(parent); } g_object_unref (layout); + cairo_destroy (c); + cairo_surface_destroy (cs); + XFreePixmap (server.dsp, pmap); }
@@ -37,5 +37,6 @@ void init_clock(Clock *clock, Area *parent);
void draw_foreground_clock (void *obj, cairo_t *c, int active); +void resize_clock (void *obj); #endif
@@ -38,6 +38,7 @@ #include "common.h"
#include "server.h" #include "task.h" #include "taskbar.h" +#include "systraybar.h" #include "clock.h" #include "panel.h" #include "config.h"@@ -409,6 +410,14 @@ memcpy(&panel_config->g_task.area.pix_active.back, &a->pix.back, sizeof(Color));
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 */ else if (strcmp (key, "mouse_middle") == 0) get_action (value, &mouse_middle);@@ -539,20 +548,18 @@ if (panel_config->monitor > (server.nb_monitor-1)) {
fprintf(stderr, "tint2 exit : monitor %d not found.\n", panel_config->monitor+1); 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 int i; if (panel_config->monitor >= 0) { + // just one monitor nb_panel = 1; panel1 = calloc(nb_panel, sizeof(Panel)); memcpy(panel1, panel_config, sizeof(Panel)); + panel1->monitor = panel_config->monitor; } else { - // multi monitor + // all monitors nb_panel = server.nb_monitor; panel1 = calloc(nb_panel, sizeof(Panel));@@ -566,10 +573,14 @@ init_panel();
init_taskbar(); 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(); }
@@ -115,6 +115,7 @@ XMapWindow (server.dsp, p->main_win);
init_clock(&p->clock, &p->area); } + panel_refresh = 1; }@@ -129,10 +130,17 @@ Panel *p;
for (i=0 ; i < nb_panel ; 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_taskbar); 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->main_win) XDestroyWindow(server.dsp, p->main_win); }@@ -154,8 +162,9 @@ XCopyArea (server.dsp, p->area.pix.pmap, p->root_pmap, server.gc, 0, 0, p->area.width, p->area.height, 0, 0);
// draw child object GSList *l = p->area.list; - for (; l ; l = l->next) + for (; l ; l = l->next) { refresh (l->data); + } XCopyArea(server.dsp, p->root_pmap, p->main_win, server.gc, 0, 0, p->area.width, p->area.height, 0, 0);@@ -243,6 +252,8 @@ // list of visible objects
// start with clock because draw(clock) can resize others object if (time1_format) panel->area.list = g_slist_append(panel->area.list, &panel->clock); + + //panel->area.list = g_slist_append(panel->area.list, &panel->trayer); Taskbar *taskbar; for (j=0 ; j < panel->nb_desktop ; j++) {
@@ -61,7 +61,7 @@ // location of the panel (monitor number)
int monitor; // -------------------------------------------------- - // task annd taskbar parameter per panel + // task and taskbar parameter per panel Area g_taskbar; Global_task g_task;@@ -77,7 +77,10 @@ Clock clock;
// -------------------------------------------------- // systray - Systraybar systraybar; + Systraybar trayer; + + // global taskbar parameter + //Area g_systraybar; } Panel;
@@ -28,6 +28,8 @@ #include "window.h"
void server_catch_error (Display *d, XErrorEvent *ev){} +static char *name_trayer = 0; + void server_init_atoms () {@@ -68,6 +70,19 @@ server.atom._NET_WM_STRUT_PARTIAL = XInternAtom (server.dsp, "_NET_WM_STRUT_PARTIAL", False);
server.atom.WM_NAME = XInternAtom(server.dsp, "WM_NAME", False); server.atom.__SWM_VROOT = XInternAtom(server.dsp, "__SWM_VROOT", 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); }
@@ -53,6 +53,10 @@ Atom _NET_WM_STRUT_PARTIAL;
Atom WM_NAME; Atom __SWM_VROOT; Atom _MOTIF_WM_HINTS; + Atom _NET_SYSTEM_TRAY; + Atom _NET_SYSTEM_TRAY_OPCODE; + Atom MANAGER; + Atom _NET_SYSTEM_TRAY_MESSAGE_DATA; } Global_atom;
@@ -28,85 +28,6 @@ /* excluding the border. sum of all child apps */
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() { XWMHints hints;@@ -136,7 +57,7 @@ XWMHints hints;
XTextProperty text; 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); if (!wmaker)@@ -145,7 +66,7 @@ border * 2, border * 2, 0, 0, 0);
else win = XCreateSimpleWindow(display, root, 0, 0, 64, 64, 0, 0, 0); - + assert(win); XStringListToTextProperty(&name, 1, &text);@@ -154,21 +75,21 @@
hints.flags = StateHint; hints.initial_state = WithdrawnState; XSetWMHints(display, win, &hints); - + create_hint_win(); - + XSync(display, False); XSetWindowBackgroundPixmap(display, win, ParentRelative); XClearWindow(display, win); } - +*/ void reposition_icons() { int x = border + ((width % icon_size) / 2), y = border + ((height % icon_size) / 2); GSList *it; - + for (it = icons; it != NULL; it = g_slist_next(it)) { TrayWindow *traywin = it->data; traywin->x = x;@@ -193,10 +114,10 @@ void fix_geometry()
{ GSList *it; - /* in wmaker mode we're a fixed size */ + // in wmaker mode we're a fixed size if (wmaker) return; - - /* find the proper width and height */ + + //* find the proper width and height width = horizontal ? 0 : icon_size; height = horizontal ? icon_size : 0; for (it = icons; it != NULL; it = g_slist_next(it)) {@@ -209,100 +130,13 @@
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) { struct sigaction act; - + argc = c; argv = v; - + act.sa_handler = signal_handler; act.sa_flags = 0; sigaction(SIGSEGV, &act, NULL);@@ -325,18 +159,18 @@ assert(root);
if (wmaker) width = height = 64 - border * 2; - + create_main_window(); - // set up to find KDE systray icons, and get any that already exist + // set up to find KDE systray icons, and get any that already exist kde_init(); net_init(); // we want to get ConfigureNotify events, and assume our parent's background - // has changed when we do, so we need to refresh ourself to match + // has changed when we do, so we need to refresh ourself to match XSelectInput(display, win, StructureNotifyMask); - + event_loop(); XCloseDisplay(display);
@@ -14,7 +14,7 @@ /* defined in the systray spec */
#define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 - + static void net_create_selection_window() { net_sel_win = XCreateSimpleWindow(display, root, -1, -1, 1, 1, 0, 0, 0);@@ -28,38 +28,11 @@ XDestroyWindow(display, net_sel_win);
net_sel_win = None; } - -void net_init() +void net_icon_remove(TrayWindow *traywin) { - char *name; - XEvent m; - - name = g_strdup_printf("_NET_SYSTEM_TRAY_S%d", DefaultScreen(display)); - 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 */ + assert(traywin); - 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); + XSelectInput(display, traywin->id, NoEventMask); }@@ -69,51 +42,3 @@ net_destroy_selection_window();
} -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); -}
@@ -27,9 +27,43 @@ #include <Imlib2.h>
#include "systraybar.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) {@@ -38,3 +72,254 @@ }
+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); + } +} +*/ +
@@ -18,10 +18,14 @@
} Systraybar; -// -------------------------------------------------- -// global taskbar parameter -Area g_systraybar; +typedef struct +{ + Window id; + int x, y; +} TrayWindow; + +void init_systray(Systraybar *sysbar, Area *parent); // return 1 if task_width changed int resize_systray (Systraybar *sysbar);
@@ -8,7 +8,7 @@ **************************************************************************/
#ifndef TINT_MERGE_H #define TINT_MERGE_H - +/* #define display server.dsp #define root server.root_win
@@ -91,6 +91,7 @@ {
if (!tsk) return; Window win = tsk->win; + int desktop = tsk->desktop; // free title and icon just for the first task // even with task_on_all_desktop and with task_on_all_panel@@ -106,8 +107,7 @@ Task *tsk2;
Taskbar *tskbar; for (i=0 ; i < nb_panel ; i++) { for (j=0 ; j < panel1[i].nb_desktop ; j++) { - if (tsk->desktop != ALLDESKTOP && tsk->desktop != j) continue; - //if (!panel1[i].taskbar) continue; + if (desktop != ALLDESKTOP && desktop != j) continue; GSList *l0; tskbar = &panel1[i].taskbar[j];
@@ -43,12 +43,13 @@ for (i=0 ; i < nb_panel ; i++) {
panel = &panel1[i]; // taskbar + panel->g_taskbar._resize = resize_taskbar; 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.redraw = 1; // 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.height = panel->area.height - (2 * panel->g_task.area.posy); panel->g_task.area.use_active = 1;@@ -84,10 +85,7 @@ tskbar = &panel->taskbar[j];
memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area)); tskbar->desktop = j; } - - resize_taskbar(panel); } - }@@ -115,8 +113,10 @@ }
for (i=0 ; i < nb_panel ; i++) { panel = &panel1[i]; - free(panel->taskbar); - panel->taskbar = 0; + if (panel->taskbar) { + free(panel->taskbar); + panel->taskbar = 0; + } } }@@ -174,7 +174,7 @@ for (k = 0; k < num_results; k++) {
if (tsk->win == win[k]) break; } // 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 @@ GSList *l;
// new task width for 'desktop' task_count = g_slist_length(taskbar->area.list); + if (!task_count) pixel_width = panel->g_task.maximum_width; else { taskbar_width = taskbar->area.width - (2 * panel->g_taskbar.pix.border.width) - (2 * panel->g_taskbar.paddingxlr);@@ -239,9 +240,9 @@ }
// 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; if (panel_mode == MULTI_DESKTOP) taskbar_on_screen = panel->nb_desktop;@@ -250,6 +251,8 @@
taskbar_width = panel->area.width - (2 * panel->area.paddingxlr) - (2 * panel->area.pix.border.width); if (time1_format) 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; if (taskbar_on_screen > 1)@@ -272,6 +275,7 @@ panel->taskbar[i].area.width++;
modulo--; } + set_redraw (&panel->taskbar[i].area); resize_tasks(&panel->taskbar[i]); } }
@@ -34,7 +34,7 @@
// return 1 if task_width changed int resize_tasks (Taskbar *tskbar); -void resize_taskbar(void *panel); +void resize_taskbar(void *obj); #endif
@@ -35,10 +35,8 @@ #include "window.h"
#include "config.h" #include "task.h" #include "taskbar.h" +#include "systraybar.h" #include "panel.h" -#include "docker.h" -#include "net.h" -#include "kde.h" void signal_handler(int sig)@@ -73,14 +71,6 @@ XGCValues gcv;
server.gc = XCreateGC (server.dsp, server.root_win, (unsigned long)0, &gcv) ; 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_visual (server.visual);@@ -138,7 +128,7 @@ if (!panel) return;
if (panel_mode != MULTI_DESKTOP) { // drag and drop disabled - //XLowerWindow (server.dsp, panel.main_win); + XLowerWindow (server.dsp, panel->main_win); return; }@@ -163,7 +153,7 @@ }
} } - //XLowerWindow (server.dsp, panel.main_win); + XLowerWindow (server.dsp, panel->main_win); }@@ -202,7 +192,7 @@ goto suite;
} // TODO: check better solution to keep window below - //XLowerWindow (server.dsp, panel.main_win); + XLowerWindow (server.dsp, panel->main_win); task_drag = 0; return;@@ -238,7 +228,7 @@ }
} // to keep window below - //XLowerWindow (server.dsp, panel.main_win); + XLowerWindow (server.dsp, panel->main_win); }@@ -259,6 +249,9 @@ server.nb_desktop = server_get_number_of_desktop ();
cleanup_taskbar(); init_taskbar(); visible_object(); + for (i=0 ; i < nb_panel ; i++) { + set_resize(&panel1[i]); + } task_refresh_tasklist(); panel_refresh = 1; }@@ -429,6 +422,7 @@
int i; for (i=0 ; i < nb_panel ; i++) { panel1[i].clock.area.redraw = 1; + panel1[i].clock.area.resize = 1; } panel_refresh = 1; }@@ -459,11 +453,6 @@ exit(1);
} 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); XSync(server.dsp, False);@@ -500,7 +489,6 @@ XCopyArea (server.dsp, panel->root_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0);
break; case PropertyNotify: - //printf("PropertyNotify %lx\n", e.xproperty.window); event_property_notify (e.xproperty.window, e.xproperty.atom); break;@@ -510,6 +498,25 @@ goto load_config;
else 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; } } }@@ -525,8 +532,10 @@ return 0;
} if (panel_refresh) { - for (i=0 ; i < nb_panel ; i++) + for (i=0 ; i < nb_panel ; i++) { visual_refresh(&panel1[i]); + } + XFlush (server.dsp); panel_refresh = 0; }
@@ -32,6 +32,13 @@
void refresh (Area *a) { + if (a->resize) { + // resize can generate a redraw + if (a->_resize) + a->_resize(a); + a->resize = 0; + } + if (a->redraw) { //printf("draw pix\n"); draw(a, 0);@@ -61,6 +68,16 @@ set_redraw(l->data);
} +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) { Pixmap *pmap = (active == 0) ? (&a->pix.pmap) : (&a->pix_active.pmap);@@ -80,8 +97,8 @@ c = cairo_create (cs);
draw_background (a, c, active); - if (a->draw_foreground) - a->draw_foreground(a, c, active); + if (a->_draw_foreground) + a->_draw_foreground(a, c, active); cairo_destroy (c); cairo_surface_destroy (cs);@@ -180,6 +197,8 @@ if (a->list) {
g_slist_free(a->list); 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); }
@@ -60,8 +60,6 @@ Border border;
} Pmap; -// TODO: isoler 'draw' de 'refresh' -// TODO: isoler les données locales des données communes aux freres typedef struct { // absolute coordinate in panel int posx, posy;@@ -72,6 +70,8 @@
// list of child : Area object GSList *list; + // need compute position and width + int resize; // need redraw Pixmap int redraw; int use_active, is_active;@@ -84,9 +84,10 @@ // panel
void *panel; // each object can overwrite following function - void (*draw_foreground)(void *obj, cairo_t *c, int active); - void (*add_child)(void *obj); - int (*remove_child)(void *obj); + void (*_draw_foreground)(void *obj, cairo_t *c, int active); + void (*_resize)(void *obj); + void (*_add_child)(void *obj); + int (*_remove_child)(void *obj); } Area;