From: Thierry Lorthiois Date: Tue, 10 Feb 2009 23:16:10 +0000 (+0000) Subject: fixed bug : clock resize when date changed, number of desktop changed X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=bf2fd3cf8c96d2a747ba4ea3bd8bd9b0a0d7e0e7;p=chaz%2Ftint2 fixed bug : clock resize when date changed, number of desktop changed --- diff --git a/ChangeLog b/ChangeLog index 9cce93f..1a94a50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-02-11 +- fixed bug with number of desktop changed +- fixed clock resize when date changed + 2009-02-08 - backward compatibility with tint-0.6 (convert config file) feature freeze until next release. need bug correction. diff --git a/src/Makefile b/src/Makefile index 63d4bd2..c31fc32 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/clock/clock.c b/src/clock/clock.c index 64ac1ba..e7bb32f 100644 --- a/src/clock/clock.c +++ b/src/clock/clock.c @@ -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 @@ void init_clock(Clock *clock, Area *parent) 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)); @@ -82,12 +83,45 @@ void init_clock(Clock *clock, Area *parent) 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 @@ void draw_foreground_clock (void *obj, cairo_t *c, int active) 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 @@ redraw: 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); + 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; - - 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); } diff --git a/src/clock/clock.h b/src/clock/clock.h index a074797..613c40d 100644 --- a/src/clock/clock.h +++ b/src/clock/clock.h @@ -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 diff --git a/src/config.c b/src/config.c index 6f7d42a..f423654 100644 --- a/src/config.c +++ b/src/config.c @@ -38,6 +38,7 @@ #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 @@ void add_entry (char *key, char *value) 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 @@ void config_finish () 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 @@ void config_finish () init_taskbar(); visible_object(); - task_refresh_tasklist(); - panel_refresh = 1; - 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(); } diff --git a/src/panel.c b/src/panel.c index 3e2d76e..881fdaf 100644 --- a/src/panel.c +++ b/src/panel.c @@ -115,6 +115,7 @@ void init_panel() init_clock(&p->clock, &p->area); } + panel_refresh = 1; } @@ -129,10 +130,17 @@ void cleanup_panel() 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 @@ void visual_refresh (Panel *p) // 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); @@ -244,6 +253,8 @@ void visible_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++) { taskbar = &panel->taskbar[j]; diff --git a/src/panel.h b/src/panel.h index 5992f7a..3a4b6dd 100644 --- a/src/panel.h +++ b/src/panel.h @@ -61,7 +61,7 @@ typedef struct { 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 @@ typedef struct { // -------------------------------------------------- // systray - Systraybar systraybar; + Systraybar trayer; + + // global taskbar parameter + //Area g_systraybar; } Panel; diff --git a/src/server.c b/src/server.c index 65d1099..1fccd6e 100644 --- a/src/server.c +++ b/src/server.c @@ -28,6 +28,8 @@ void server_catch_error (Display *d, XErrorEvent *ev){} +static char *name_trayer = 0; + void server_init_atoms () { @@ -68,6 +70,19 @@ void server_init_atoms () 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); } diff --git a/src/server.h b/src/server.h index b8014e6..2d0aacb 100644 --- a/src/server.h +++ b/src/server.h @@ -53,6 +53,10 @@ typedef struct Global_atom 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; diff --git a/src/systray/docker.c b/src/systray/docker.c index 091c62e..a2e6152 100644 --- a/src/systray/docker.c +++ b/src/systray/docker.c @@ -28,85 +28,6 @@ int icon_size = 24; /* width and height of systray icons */ 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 \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 @@ void create_main_window() 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 @@ void create_main_window() else win = XCreateSimpleWindow(display, root, 0, 0, 64, 64, 0, 0, 0); - + assert(win); XStringListToTextProperty(&name, 1, &text); @@ -154,21 +75,21 @@ void create_main_window() 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 @@ void fix_geometry() 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 @@ int main(int c, char **v) 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); diff --git a/src/systray/net.c b/src/systray/net.c index 9f0c94a..8591834 100644 --- a/src/systray/net.c +++ b/src/systray/net.c @@ -14,7 +14,7 @@ static Atom net_message_data_atom; #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 @@ static void net_destroy_selection_window() 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 @@ 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); -} diff --git a/src/systray/systraybar.c b/src/systray/systraybar.c index a6b3767..0c515e9 100644 --- a/src/systray/systraybar.c +++ b/src/systray/systraybar.c @@ -27,9 +27,43 @@ #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 @@ 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); + } +} +*/ + diff --git a/src/systray/systraybar.h b/src/systray/systraybar.h index 7fd8c9e..761bda6 100644 --- a/src/systray/systraybar.h +++ b/src/systray/systraybar.h @@ -18,11 +18,15 @@ typedef struct { } 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); diff --git a/src/systray/tint_merge.h b/src/systray/tint_merge.h index 475ebac..2cfbff5 100644 --- a/src/systray/tint_merge.h +++ b/src/systray/tint_merge.h @@ -8,7 +8,7 @@ #ifndef TINT_MERGE_H #define TINT_MERGE_H - +/* #define display server.dsp #define root server.root_win diff --git a/src/taskbar/task.c b/src/taskbar/task.c index 839f6f5..2ec873f 100644 --- a/src/taskbar/task.c +++ b/src/taskbar/task.c @@ -91,6 +91,7 @@ void remove_task (Task *tsk) 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 @@ void remove_task (Task *tsk) 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]; diff --git a/src/taskbar/taskbar.c b/src/taskbar/taskbar.c index 2044912..45d3b3d 100644 --- a/src/taskbar/taskbar.c +++ b/src/taskbar/taskbar.c @@ -43,12 +43,13 @@ void init_taskbar() 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 @@ void init_taskbar() memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area)); tskbar->desktop = j; } - - resize_taskbar(panel); } - } @@ -115,8 +113,10 @@ void cleanup_taskbar() 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 @@ void task_refresh_tasklist () 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 @@ int resize_tasks (Taskbar *taskbar) // 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 @@ int resize_tasks (Taskbar *taskbar) // 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 @@ void resize_taskbar(void *p) 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 @@ void resize_taskbar(void *p) modulo--; } + set_redraw (&panel->taskbar[i].area); resize_tasks(&panel->taskbar[i]); } } diff --git a/src/taskbar/taskbar.h b/src/taskbar/taskbar.h index 881eab2..807e285 100644 --- a/src/taskbar/taskbar.h +++ b/src/taskbar/taskbar.h @@ -34,7 +34,7 @@ void task_refresh_tasklist (); // return 1 if task_width changed int resize_tasks (Taskbar *tskbar); -void resize_taskbar(void *panel); +void resize_taskbar(void *obj); #endif diff --git a/src/tint.c b/src/tint.c index 10ccb36..b84ee18 100644 --- a/src/tint.c +++ b/src/tint.c @@ -35,10 +35,8 @@ #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) @@ -74,14 +72,6 @@ void init () 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); imlib_context_set_colormap (DefaultColormap (server.dsp, server.screen)); @@ -138,7 +128,7 @@ void event_button_press (XEvent *e) 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 @@ 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 - //XLowerWindow (server.dsp, panel.main_win); + XLowerWindow (server.dsp, panel->main_win); task_drag = 0; return; @@ -238,7 +228,7 @@ suite: } // 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(); 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 @@ void event_timer() 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 @@ load_config: } 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 @@ load_config: break; case PropertyNotify: - //printf("PropertyNotify %lx\n", e.xproperty.window); event_property_notify (e.xproperty.window, e.xproperty.atom); break; @@ -509,6 +497,25 @@ load_config: 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 @@ load_config: } 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; } diff --git a/src/tint2 b/src/tint2 index e7365a7..91ceff4 100755 Binary files a/src/tint2 and b/src/tint2 differ diff --git a/src/util/area.c b/src/util/area.c index bd6cf95..7606679 100644 --- a/src/util/area.c +++ b/src/util/area.c @@ -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 @@ 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) { 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); - 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 @@ void free_area (Area *a) 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); } diff --git a/src/util/area.h b/src/util/area.h index b03b2d1..708c033 100644 --- a/src/util/area.h +++ b/src/util/area.h @@ -60,8 +60,6 @@ typedef struct } 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 @@ typedef struct { // 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 @@ typedef struct { 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;