From c7e86733c6d75a55a075458da3e90ed2dc236e9b Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Fri, 1 Jun 2007 17:01:31 +0000 Subject: [PATCH] first steps to making rspanel not useless for anyone but me --- rspanel.c | 160 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 115 insertions(+), 45 deletions(-) diff --git a/rspanel.c b/rspanel.c index 47d4303..bbb8513 100644 --- a/rspanel.c +++ b/rspanel.c @@ -41,6 +41,9 @@ int WINWIDTH = 827; //#define PAGER /* use a desktop pager? */ #define PAGER_DIGIT_WIDTH 6 #define PAGER_BUTTON_WIDTH 20 +#ifdef PAGER +#undef PANGO +#endif /* don't edit these */ #define TEXTPAD 6 @@ -122,12 +125,44 @@ char *atom_names[] = { "_NET_WM_NAME", "UTF8_STRING", "_NET_ACTIVE_WINDOW", + "_NET_RESTACK_WINDOW", }; #define ATOM_COUNT (sizeof (atom_names) / sizeof (atom_names[0])) Atom atoms[ATOM_COUNT]; +typedef enum { +KWM_WIN_ICON, +WM_STATE, +_MOTIF_WM_HINTS, +_NET_WM_STATE, +_NET_WM_STATE_SKIP_TASKBAR, +_NET_WM_STATE_SHADED, +_NET_WM_STATE_BELOW, +_NET_WM_STATE_HIDDEN, +_NET_WM_DESKTOP, +_NET_WM_WINDOW_TYPE, +_NET_WM_WINDOW_TYPE_DOCK, +_NET_WM_STRUT, +_WIN_HINTS, +_NET_CLIENT_LIST, +_NET_CLIENT_LIST_STACKING, +_NET_NUMBER_OF_DESKTOPS, +_NET_CURRENT_DESKTOP, +_OB_WM_ACTION, +_NET_WM_NAME, +STRING_UTF8, +_NET_ACTIVE_WINDOW, +_NET_RESTACK_WINDOW, +} atom_t; + +enum { + REMOVE = 0, + ADD, + TOGGLE +}; + #define atom_KWM_WIN_ICON atoms[0] #define atom_WM_STATE atoms[1] #define atom__MOTIF_WM_HINTS atoms[2] @@ -265,7 +300,7 @@ void get_task_kdeicon(task * tk) { unsigned long *data; - data = get_prop_data(tk->win, atom_KWM_WIN_ICON, atom_KWM_WIN_ICON, 0); + data = get_prop_data(tk->win, atoms[KWM_WIN_ICON], atoms[KWM_WIN_ICON], 0); if (data) { tk->icon = data[0]; tk->mask = data[1]; @@ -288,7 +323,7 @@ int generic_get_int(Window win, Atom at) int find_desktop(Window win) { - return generic_get_int(win, atom__NET_WM_DESKTOP); + return generic_get_int(win, atoms[_NET_WM_DESKTOP]); } int is_hidden(Window win) @@ -297,11 +332,11 @@ int is_hidden(Window win) int ret = 0; int num; - data = get_prop_data(win, atom__NET_WM_STATE, XA_ATOM, &num); + data = get_prop_data(win, atoms[_NET_WM_STATE], XA_ATOM, &num); if (data) { while (num) { num--; - if ((data[num]) == atom__NET_WM_STATE_SKIP_TASKBAR) + if ((data[num]) == atoms[_NET_WM_STATE_SKIP_TASKBAR]) ret = 1; } XFree(data); @@ -315,11 +350,11 @@ int is_iconified(Window win) int ret = 0; int num; - data = get_prop_data(win, atom__NET_WM_STATE, XA_ATOM, &num); + data = get_prop_data(win, atoms[_NET_WM_STATE], XA_ATOM, &num); if (data) { while (num) { num--; - if ((data[num]) == atom__NET_WM_STATE_HIDDEN) + if ((data[num]) == atoms[_NET_WM_STATE_HIDDEN]) ret = 1; } XFree(data); @@ -333,11 +368,11 @@ int is_shaded(Window win) int ret = 0; int num; - data = get_prop_data(win, atom__NET_WM_STATE, XA_ATOM, &num); + data = get_prop_data(win, atoms[_NET_WM_STATE], XA_ATOM, &num); if (data) { while (num) { num--; - if ((data[num]) == atom__NET_WM_STATE_SHADED) + if ((data[num]) == atoms[_NET_WM_STATE_SHADED]) ret = 1; } XFree(data); @@ -347,12 +382,12 @@ int is_shaded(Window win) int get_current_desktop(void) { - return generic_get_int(root_win, atom__NET_CURRENT_DESKTOP); + return generic_get_int(root_win, atoms[_NET_CURRENT_DESKTOP]); } int get_number_of_desktops(void) { - return generic_get_int(root_win, atom__NET_NUMBER_OF_DESKTOPS); + return generic_get_int(root_win, atoms[_NET_NUMBER_OF_DESKTOPS]); } void add_task(Window win, int focus) @@ -371,7 +406,7 @@ void add_task(Window win, int focus) tk = calloc(1, sizeof(task)); tk->win = win; tk->focused = focus; - tk->name = get_prop_data(tk->win, atom__NET_WM_NAME, atom_STRING_UTF8, 0) ?: + tk->name = get_prop_data(tk->win, atoms[_NET_WM_NAME], atoms[STRING_UTF8], 0) ?: get_prop_data(tk->win, XA_WM_NAME, XA_STRING, 0); // tk->name = get_prop_data(win, XA_WM_NAME, XA_STRING, 0); //tk->locale = get_prop_data(win, XA_WM_LOCALE_NAME, XA_STRING, 0); @@ -439,12 +474,12 @@ Window gui_create_taskbar(void) /* attribs */ &att); /* reside on ALL desktops */ - set_prop(win, atom__NET_WM_DESKTOP, XA_CARDINAL, 0xFFFFFFFF); - set_prop(win, atom__NET_WM_WINDOW_TYPE, XA_ATOM, - atom__NET_WM_WINDOW_TYPE_DOCK); - set_prop(win, atom__NET_WM_STATE, XA_ATOM, atom__NET_WM_STATE_BELOW); + set_prop(win, atoms[_NET_WM_DESKTOP], XA_CARDINAL, 0xFFFFFFFF); + set_prop(win, atoms[_NET_WM_WINDOW_TYPE], XA_ATOM, + atoms[_NET_WM_WINDOW_TYPE_DOCK]); + set_prop(win, atoms[_NET_WM_STATE], XA_ATOM, atoms[_NET_WM_STATE_BELOW]); /* use old gnome hint since sawfish doesn't support _NET_WM_STRUT */ - set_prop(win, atom__WIN_HINTS, XA_CARDINAL, + set_prop(win, atoms[_WIN_HINTS], XA_CARDINAL, WIN_HINTS_SKIP_FOCUS | WIN_HINTS_SKIP_WINLIST | WIN_HINTS_SKIP_TASKBAR | WIN_HINTS_DO_NOT_COVER); XChangeProperty(dd, win, XA_WM_NAME, XA_STRING, 8, PropModeReplace, @@ -453,7 +488,7 @@ Window gui_create_taskbar(void) /* borderless motif hint */ bzero(&mwm, sizeof(mwm)); mwm.flags = MWM_HINTS_DECORATIONS; - XChangeProperty(dd, win, atom__MOTIF_WM_HINTS, atom__MOTIF_WM_HINTS, 32, + XChangeProperty(dd, win, atoms[_MOTIF_WM_HINTS], atoms[_MOTIF_WM_HINTS], 32, PropModeReplace, (unsigned char *)&mwm, sizeof(MWMHints) / 4); @@ -724,28 +759,51 @@ void ob_action(Window win, char *action) xev.type = ClientMessage; xev.window = win; - xev.message_type = atom__OB_WM_ACTION; + xev.message_type = atoms[_OB_WM_ACTION]; xev.format = 32; /*strncpy(xev.data.b, action, 20);*/ xev.data.l[0] = XInternAtom(dd, act_name, False); XSendEvent(dd, root_win, False, SubstructureRedirectMask, (XEvent *)&xev); } +void netwm_action(Window win, atom_t atom, Time time, long l) +{ + XClientMessageEvent xev = { + .type = ClientMessage, + .window = win, + .format = 32, + .data.l = {0}, + .message_type = atoms[atom] + }; + + if (atom == _NET_ACTIVE_WINDOW) { + xev.data.l[0] = 2; + xev.data.l[1] = time; + xev.data.l[2] = 0; + } else if (atom == _NET_CURRENT_DESKTOP) { + xev.data.l[0] = l; + xev.data.l[1] = time; + } else if (atom == _NET_RESTACK_WINDOW) { + xev.data.l[0] = 2; + xev.data.l[2] = l; + } else { + xev.message_type = atoms[_NET_WM_STATE]; + xev.data.l[0] = l; + xev.data.l[1] = atoms[atom]; + xev.data.l[3] = 2; + } + + XSendEvent(dd, root_win, False, SubstructureNotifyMask|SubstructureRedirectMask, (XEvent *)&xev); +} + #ifdef PAGER -void switch_desk(int new_desk) +void switch_desk(int new_desk, Time time) { - XClientMessageEvent xev; - if (get_number_of_desktops() <= new_desk) return; - xev.type = ClientMessage; - xev.window = root_win; - xev.message_type = atom__NET_CURRENT_DESKTOP; - xev.format = 32; - xev.data.l[0] = new_desk; - XSendEvent(dd, root_win, False, SubstructureRedirectMask, (XEvent *)&xev); + netwm_action(None, _NET_CURRENT_DESKTOP, time, new_desk); } void pager_draw_button(int x, int num) @@ -917,11 +975,11 @@ void taskbar_read_clientlist(void) tb.my_desktop = desk; } - win = get_prop_data(root_win, atom__NET_ACTIVE_WINDOW, XA_WINDOW, &num); + win = get_prop_data(root_win, atoms[_NET_ACTIVE_WINDOW], XA_WINDOW, &num); if (win && num > 0) focus_win = win[0]; - win = get_prop_data(root_win, atom__NET_CLIENT_LIST, XA_WINDOW, &num); + win = get_prop_data(root_win, atoms[_NET_CLIENT_LIST], XA_WINDOW, &num); if (!win) return; @@ -950,13 +1008,13 @@ dontdel: XFree(win); } -void handle_press(int x, int y, int button) +void handle_press(int x, int y, int button, Time time) { task *tk; #ifdef PAGER if ((y > 2 && y < WINHEIGHT - 2 && x > GRILL_WIDTH) && button == 1) - switch_desk((x - GRILL_WIDTH) / PAGER_BUTTON_WIDTH); + switch_desk((x - GRILL_WIDTH) / PAGER_BUTTON_WIDTH, time); else #endif /* clicked left grill */ @@ -988,34 +1046,46 @@ void handle_press(int x, int y, int button) case 1: if (tk->iconified && tk->shaded) ob_action(tk->win, "unshade"); - ob_action(tk->win, "activate"); + //ob_action(tk->win, "activate"); + netwm_action(tk->win, _NET_ACTIVE_WINDOW, time, 0); break; case 2: if (tk->iconified) - ob_action(tk->win, "deiconify"); + //ob_action(tk->win, "deiconify"); + netwm_action(tk->win, _NET_WM_STATE_HIDDEN, time, REMOVE); else - ob_action(tk->win, "iconify"); + netwm_action(tk->win, _NET_WM_STATE_HIDDEN, time, ADD); + //ob_action(tk->win, "iconify"); break; case 3: ob_action(tk->win, "raiselower"); break; case 4: - ob_action(tk->win, "shadelower"); + if (is_shaded(tk->win)) + netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Below); + else + netwm_action(tk->win, _NET_WM_STATE_SHADED, time, ADD); break; case 5: - ob_action(tk->win, "unshaderaise"); + if (is_shaded(tk->win)) + netwm_action(tk->win, _NET_WM_STATE_SHADED, time, REMOVE); + else + netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Above); break; case 9: if (tk->iconified) - ob_action(tk->win, "deiconify"); + netwm_action(tk->win, _NET_WM_STATE_SHADED, time, REMOVE); + //ob_action(tk->win, "deiconify"); else ob_action(tk->win, "focus"); break; case 6: - ob_action(tk->win, "lower"); +// ob_action(tk->win, "lower"); + netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Below); break; case 7: - ob_action(tk->win, "raise"); +// ob_action(tk->win, "raise"); + netwm_action(tk->win, _NET_RESTACK_WINDOW, time, Above); break; } return; @@ -1070,7 +1140,7 @@ void handle_propertynotify(Window win, Atom at) task *tk; if (win == root_win) { - if (at == atom__NET_CLIENT_LIST || at == atom__NET_CURRENT_DESKTOP || at == atom__NET_CLIENT_LIST_STACKING) { + if (at == atoms[_NET_CLIENT_LIST] || at == atoms[_NET_CURRENT_DESKTOP] || at == atoms[_NET_CLIENT_LIST_STACKING]) { taskbar_read_clientlist(); gui_draw_taskbar(); } @@ -1081,10 +1151,10 @@ void handle_propertynotify(Window win, Atom at) if (!tk) return; - if (at == XA_WM_NAME || at == atom__NET_WM_NAME) { + if (at == XA_WM_NAME || at == atoms[_NET_WM_NAME]) { /* window's title changed */ char *newname; - newname = get_prop_data(tk->win, atom__NET_WM_NAME, atom_STRING_UTF8, 0) ?: + newname = get_prop_data(tk->win, atoms[_NET_WM_NAME], atoms[STRING_UTF8], 0) ?: get_prop_data(tk->win, XA_WM_NAME, XA_STRING, 0); if (newname) { if (tk->name && !strcmp(newname, tk->name)) { @@ -1096,7 +1166,7 @@ void handle_propertynotify(Window win, Atom at) XFree(tk->name); tk->name = newname; gui_draw_task(tk); - } else if (at == atom__NET_WM_STATE) { + } else if (at == atoms[_NET_WM_STATE]) { /* iconified state changed? */ if (is_iconified(tk->win) != tk->iconified) { tk->iconified = !tk->iconified; @@ -1113,7 +1183,7 @@ void handle_propertynotify(Window win, Atom at) get_task_hinticon(tk); gui_draw_task(tk); //} - } else if (at == atom__NET_WM_DESKTOP) { + } else if (at == atoms[_NET_WM_DESKTOP]) { if (find_desktop(win) != get_current_desktop()) del_task(tk->win); } @@ -1165,7 +1235,7 @@ main(int argc, char *argv[]) XNextEvent(dd, &ev); switch (ev.type) { case ButtonPress: - handle_press(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button); + handle_press(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.time); break; case DestroyNotify: del_task(ev.xdestroywindow.window); -- 2.39.2