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

@@ -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 <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 @@ 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);

View File

@@ -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;
assert(traywin);
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 */
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);
}

View File

@@ -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);
}
}
*/

View File

@@ -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);

View File

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