Merge branch 'master' into bacardi55

This commit is contained in:
Raphael Khaiat
2010-08-03 00:08:52 +02:00
18 changed files with 593 additions and 125 deletions

View File

@@ -340,6 +340,7 @@ client_above(Client *c)
void
client_focus(Client *c)
{
Client *cc;
Window w;
int d;
@@ -365,6 +366,14 @@ client_focus(Client *c)
c->colors.frame = conf.client.borderfocus;
c->colors.fg = conf.titlebar.fg_focus;
c->colors.resizecorner = conf.client.resizecorner_focus;
/* Set focusontag option */
for(cc = clients; cc; cc = cc->next)
if(cc->focusontag == c->tag)
cc->focusontag = -1;
c->focusontag = seltag[selscreen];
if(TBARH - BORDH && c->titlebar->stipple)
c->titlebar->stipple_color = conf.titlebar.stipple.colors.focus;
frame_update(c);
@@ -616,7 +625,7 @@ client_map(Client *c)
{
CHECK(c);
if(c->flags & FSSFlag)
if(c->flags & FSSFlag || c->flags & DockFlag)
XMapWindow(dpy, c->win);
else
{
@@ -689,10 +698,10 @@ client_manage(Window w, XWindowAttributes *wa, Bool ar)
c->ogeo.height = c->geo.height = wa->height;
c->free_geo = c->geo;
c->tag = seltag[c->screen];
c->focusontag = -1;
c->layer = (sel && sel->layer > 0) ? sel->layer : 1;
at.event_mask = PropertyChangeMask;
frame_create(c);
@@ -725,9 +734,9 @@ client_manage(Window w, XWindowAttributes *wa, Bool ar)
client_raise(c);
setwinstate(c->win, NormalState);
ewmh_get_client_list();
ewmh_manage_window_type(c);
client_update_attributes(c);
client_map(c);
ewmh_manage_window_type(c);
client_focus(c);
if(ar)
@@ -833,8 +842,8 @@ client_moveresize(Client *c, XRectangle geo, Bool r)
XMoveResizeWindow(dpy, c->win, BORDH, TBARH, c->geo.width, c->geo.height);
client_configure(c);
client_update_attributes(c);
client_configure(c);
return;
}
@@ -949,7 +958,7 @@ client_swap(Client *c1, Client *c2)
CHECK(!(c1->flags & FreeFlag));
CHECK(!(c2->flags & FreeFlag));
if(c1 == c2 || (c1->screen == c2->screen && c1->tag != c2->tag))
if(c1 == c2)
return;
/* Swap only the windows */
@@ -1092,13 +1101,34 @@ client_unhide(Client *c)
return;
}
/** Select next or previous client to don't lose focus
* \param c Client pointer
*/
void
client_focus_next(Client *c)
{
Client *c_next = NULL;
for(c_next = clients;
c_next && c_next != c->prev
&& c_next->tag != c->tag
&& c_next->screen != c->screen;
c_next = c_next->next);
if(c_next && c_next->tag == seltag[selscreen]
&& c_next->screen == selscreen)
client_focus(c_next);
return;
}
/** Unmanage a client
* \param c Client pointer
*/
void
client_unmanage(Client *c)
{
Client *c_next = NULL;
Bool b = False;
int i;
@@ -1122,7 +1152,7 @@ client_unmanage(Client *c)
/* Arrange */
for(i = 0; i < screen_count() && !b; ++i)
if(c->tag == seltag[i])
if(c->tag == seltag[i] || tags[i][seltag[i]].tagad & TagFlag(c->tag))
b = True;
if(b)
@@ -1135,16 +1165,7 @@ client_unmanage(Client *c)
XFree(c->title);
/* To focus the previous client */
for(c_next = clients;
c_next && c_next != c->prev
&& c_next->tag != c->tag
&& c_next->screen != c->screen;
c_next = c_next->next);
if(c_next && c_next->tag == seltag[selscreen]
&& c_next->screen == selscreen)
client_focus(c_next);
client_focus_next(c);
free(c);

View File

@@ -182,8 +182,8 @@ conf_misc_section(void)
void
conf_bar_section(void)
{
struct conf_sec *bar, **mouse, *selbar;
char *barbg;
struct conf_sec *bar, **mouse, *selbar, *systray;
char *barbg, sc = screen_count();
bar = fetch_section_first(NULL, "bar");
@@ -202,6 +202,20 @@ conf_bar_section(void)
free(mouse);
if((systray = fetch_section_first(bar, "systray")))
{
conf.systray.active = fetch_opt_first(systray, "true", "active").bool;
if((conf.systray.screen = fetch_opt_first(systray, "0", "screen").num) < 0
|| conf.systray.screen >= sc)
conf.systray.screen = 0;
if((conf.systray.spacing = fetch_opt_first(systray, "3", "spacing").num) < 0)
conf.systray.spacing = 0;
}
else
conf.systray.active = False;
selbar = fetch_section_first(bar, "selbar");
conf.bars.selbar = selbar ? True : False;
@@ -462,28 +476,28 @@ conf_tag_section(void)
conf.border.tag = fetch_opt_first(sec, "false", "border").bool;
conf.tagautohide = fetch_opt_first(sec, "false", "autohide").bool;
conf.tagnamecount = fetch_opt_first(sec, "false", "name_count").bool;
def_tag = fetch_section_first(sec, "default_tag");
position = fetch_opt_first(def_tag, "top", "infobar_position").str;
if(!strcmp(position, "none")
|| !strcmp(position, "hide")
if(!strcmp(position, "none")
|| !strcmp(position, "hide")
|| !strcmp(position, "hidden"))
bar_pos = IB_Hide;
else if(!strcmp(position, "bottom")
else if(!strcmp(position, "bottom")
|| !strcmp(position, "down"))
bar_pos = IB_Bottom;
else
bar_pos = IB_Top;
/* If there is no tag in the conf or more than
* MAXTAG (36) print an error and create only one.
*/
Tag default_tag = { fetch_opt_first(def_tag, "new tag", "name").str, NULL, 0, 1,
fetch_opt_first(def_tag, "0.5", "mwfact").fnum,
fetch_opt_first(def_tag, "1", "nmaster").num,
False, fetch_opt_first(def_tag, "false", "resizehint").bool,
fetch_opt_first(def_tag, "0.5", "mwfact").fnum,
fetch_opt_first(def_tag, "1", "nmaster").num,
False, fetch_opt_first(def_tag, "false", "resizehint").bool,
False, False, bar_pos,
layout_name_to_struct(conf.layout, fetch_opt_first(def_tag, "title_right", "layout").str, conf.nlayout, layout_list),
0, NULL, 0 };

View File

@@ -52,7 +52,7 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
/* To draw image everywhere we can draw text */
#ifdef HAVE_IMLIB
char *ostr = NULL;
int i, ni;
int i, ni, sw = 0;
ImageAttr im[128];
ostr = _strdup(str);
@@ -61,8 +61,11 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
{
ni = parse_image_block(im, str);
if(infobar[conf.systray.screen].bar && d == infobar[conf.systray.screen].bar->dr)
sw = systray_get_width();
for(i = 0; i < ni; ++i)
draw_image(d, im[i].x, im[i].y, im[i].w, im[i].h, im[i].name);
draw_image(d, im[i].x - sw, im[i].y, im[i].w, im[i].h, im[i].name);
}
#endif /* HAVE_IMLIB */
@@ -156,7 +159,7 @@ draw_image(Drawable dr, int x, int y, int w, int h, char *name)
imlib_context_set_colormap(DefaultColormap(dpy, DefaultScreen(dpy)));
imlib_context_set_drawable(dr);
image = imlib_load_image(name);
image = imlib_load_image(patht(name));
imlib_context_set_image(image);
if(w <= 0)

View File

@@ -77,6 +77,7 @@ buttonpress(XButtonEvent *ev)
if(ev->button == conf.client.mouse[i].button)
if(conf.client.mouse[i].func)
conf.client.mouse[i].func(conf.client.mouse[i].cmd);
/* Root */
if(ev->window == ROOT)
for(i = 0; i < conf.root.nmouse; ++i)
@@ -162,6 +163,7 @@ void
clientmessageevent(XClientMessageEvent *ev)
{
Client *c;
Systray *sy;
int s, i, mess_t = 0;
Atom rt;
int rf;
@@ -195,8 +197,28 @@ clientmessageevent(XClientMessageEvent *ev)
/* Manage _NET_ACTIVE_WINDOW */
else if(mess_t == net_active_window)
{
if((c = client_gb_win(ev->window)))
client_focus(c);
else if((sy = systray_find(ev->data.l[0])))
XSetInputFocus(dpy, sy->win, RevertToNone, CurrentTime);
}
}
else if(ev->window == traywin)
{
/* Manage _NET_WM_SYSTEM_TRAY_OPCODE */
if(mess_t == net_wm_system_tray_opcode)
{
if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY)
{
systray_add(ev->data.l[2]);
systray_update();
}
else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS)
if((sy = systray_find(ev->data.l[2])))
ewmh_send_message(sy->win, sy->win, "_XEMBED",
XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, 0);
}
}
/* Manage _NET_WM_STATE */
@@ -211,7 +233,7 @@ clientmessageevent(XClientMessageEvent *ev)
/* Manage _NET_WM_DESKTOP */
if(mess_t == net_wm_desktop)
if((c = client_gb_win(ev->window)))
if((c = client_gb_win(ev->window)) && ev->data.l[0] != 0xFFFFFFFF)
tag_transfert(c, ev->data.l[0]);
/* Manage _WMFS_STATUSTEXT_x */
@@ -262,8 +284,8 @@ clientmessageevent(XClientMessageEvent *ev)
return;
}
/** ConfigureRequest & ConfigureNotify handle events
* \param ev XEvent pointer
/** ConfigureRequesthandle events
* \param ev XConfigureRequestEvent pointer
*/
void
configureevent(XConfigureRequestEvent *ev)
@@ -275,7 +297,6 @@ configureevent(XConfigureRequestEvent *ev)
if((c = client_gb_win(ev->window))
|| (c = client_gb_win(ev->window)))
{
CHECK(!(c->flags & TileFlag));
CHECK(!(c->flags & LMaxFlag));
CHECK(!(c->flags & MaxFlag));
CHECK(!(c->flags & FSSFlag));
@@ -292,8 +313,13 @@ configureevent(XConfigureRequestEvent *ev)
if(ev->value_mask & CWHeight)
c->geo.height = ev->height;
if(c->flags & FreeFlag)
if(c->flags & FreeFlag || !(c->flags & (TileFlag | LMaxFlag)))
client_moveresize(c, c->geo, False);
else
{
client_configure(c);
arrange(c->screen, True);
}
}
else
{
@@ -318,12 +344,19 @@ void
destroynotify(XDestroyWindowEvent *ev)
{
Client *c;
Systray *s;
if((c = client_gb_win(ev->window)))
{
client_unmanage(c);
XSetErrorHandler(errorhandler);
}
else if((s = systray_find(ev->window)))
{
setwinstate(s->win, WithdrawnState);
systray_del(s);
systray_update();
}
return;
}
@@ -335,6 +368,7 @@ void
enternotify(XCrossingEvent *ev)
{
Client *c;
Systray *s;
int n;
if((ev->mode != NotifyNormal
@@ -342,6 +376,10 @@ enternotify(XCrossingEvent *ev)
&& ev->window != ROOT)
return;
/* Don't handle EnterNotify event if it's about systray */
if((s = systray_find(ev->window)) || ev->window == traywin)
return;
if(conf.focus_fmouse)
{
if((c = client_gb_win(ev->window))
@@ -441,7 +479,7 @@ keypress(XKeyPressedEvent *ev)
return;
}
/** MapNotify handle event
/** MappingNotify handle event
* \param ev XMappingEvent pointer
*/
void
@@ -455,6 +493,29 @@ mappingnotify(XMappingEvent *ev)
return;
}
/** MapNotify handle event
* \param ev XMapEvent pointer
*/
void
mapnotify(XMapEvent *ev)
{
Client *c;
Systray *s;
if(ev->window != ev->event && !ev->send_event)
return;
if((c = client_gb_win(ev->window)))
setwinstate(c->win, NormalState);
else if((s = systray_find(ev->window)))
{
setwinstate(s->win, NormalState);
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
}
return;
}
/** MapRequest handle event
* \param ev XMapRequestEvent pointer
*/
@@ -463,11 +524,17 @@ maprequest(XMapRequestEvent *ev)
{
XWindowAttributes at;
Client *c;
Systray *s;
CHECK(XGetWindowAttributes(dpy, ev->window, &at));
CHECK(!at.override_redirect);
if(!(c = client_gb_win(ev->window)))
if((s = systray_find(ev->window)))
{
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
systray_update();
}
else if(!(c = client_gb_win(ev->window)))
client_manage(ev->window, &at, True);
return;
@@ -480,12 +547,19 @@ void
propertynotify(XPropertyEvent *ev)
{
Client *c;
Systray *s;
Window trans;
XWMHints *h;
if(ev->state == PropertyDelete)
return;
if((s = systray_find(ev->window)))
{
systray_state(s);
systray_update();
}
if((c = client_gb_win(ev->window)))
{
switch(ev->atom)
@@ -494,7 +568,7 @@ propertynotify(XPropertyEvent *ev)
XGetTransientForHint(dpy, c->win, &trans);
if((c->flags & TileFlag || c->flags & MaxFlag))
if(((c->flags & HintFlag && (client_gb_win(trans) != NULL)))
|| (!(c->flags & HintFlag && (client_gb_win(trans) != NULL))))
|| (!(c->flags & HintFlag && (client_gb_win(trans) != NULL))))
arrange(c->screen, True);
break;
case XA_WM_NORMAL_HINTS:
@@ -524,6 +598,33 @@ propertynotify(XPropertyEvent *ev)
return;
}
/** XReparentEvent handle event
* \param ev XReparentEvent pointer
*/
void
reparentnotify(XReparentEvent *ev)
{
return;
}
/** SelectionClearEvent handle event
* \param ev XSelectionClearEvent pointer
*/
void
selectionclearevent(XSelectionClearEvent *ev)
{
/* Getting selection if lost it */
if(ev->window == traywin)
systray_acquire();
systray_update();
return;
}
/** UnmapNotify handle event
* \param ev XUnmapEvent pointer
*/
@@ -531,6 +632,7 @@ void
unmapnotify(XUnmapEvent *ev)
{
Client *c;
Systray *s;
if((c = client_gb_win(ev->window))
&& ev->send_event
@@ -540,31 +642,11 @@ unmapnotify(XUnmapEvent *ev)
XSetErrorHandler(errorhandler);
}
return;
}
/** Send a client event
*\param data Event data
*\param atom_name Event atom name
*/
void
send_client_event(long data[5], char *atom_name)
{
XEvent ev;
int i;
ev.xclient.type = ClientMessage;
ev.xclient.serial = 0;
ev.xclient.send_event = True;
ev.xclient.message_type = ATOM(atom_name);
ev.xclient.window = ROOT;
ev.xclient.format = 32;
for(i = 0; i < 5; ++i, ev.xclient.data.l[i] = data[i]);
XSendEvent(dpy, ROOT, False, SubstructureRedirectMask | SubstructureNotifyMask, &ev);
XSync(dpy, False);
if((s = systray_find(ev->window)))
{
systray_del(s);
systray_update();
}
return;
}
@@ -579,18 +661,21 @@ getevent(XEvent ev)
switch(ev.type)
{
case ButtonPress: buttonpress(&ev.xbutton); break;
case ClientMessage: clientmessageevent(&ev.xclient); break;
case ConfigureRequest: configureevent(&ev.xconfigurerequest); break;
case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
case EnterNotify: enternotify(&ev.xcrossing); break;
case Expose: expose(&ev.xexpose); break;
case FocusIn: focusin(&ev.xfocus); break;
case KeyPress: keypress(&ev.xkey); break;
case MapRequest: maprequest(&ev.xmaprequest); break;
case MappingNotify: mappingnotify(&ev.xmapping); break;
case PropertyNotify: propertynotify(&ev.xproperty); break;
case UnmapNotify: unmapnotify(&ev.xunmap); break;
case ButtonPress: buttonpress(&ev.xbutton); break;
case ClientMessage: clientmessageevent(&ev.xclient); break;
case ConfigureRequest: configureevent(&ev.xconfigurerequest); break;
case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
case EnterNotify: enternotify(&ev.xcrossing); break;
case Expose: expose(&ev.xexpose); break;
case FocusIn: focusin(&ev.xfocus); break;
case KeyPress: keypress(&ev.xkey); break;
case MapNotify: mapnotify(&ev.xmap); break;
case MapRequest: maprequest(&ev.xmaprequest); break;
case MappingNotify: mappingnotify(&ev.xmapping); break;
case PropertyNotify: propertynotify(&ev.xproperty); break;
case ReparentNotify: reparentnotify(&ev.xreparent); break;
case SelectionClear: selectionclearevent(&ev.xselectionclear); break;
case UnmapNotify: unmapnotify(&ev.xunmap); break;
default:
#ifdef HAVE_XRANDR

View File

@@ -46,6 +46,8 @@ ewmh_init_hints(void)
char root_name[] = WMFS_VERSION;
char class[] = "wmfs", st[64];
long pid = (long)getpid();
char systray_atom[48];
s = screen_count();
net_atom = emalloc(net_last + s, sizeof(Atom));
@@ -77,6 +79,17 @@ ewmh_init_hints(void)
net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
net_atom[net_wm_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
snprintf(systray_atom, sizeof(systray_atom), "_NET_SYSTEM_TRAY_S%d", 0/*SCREEN*/);
net_atom[net_system_tray_s] = ATOM(systray_atom);
net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
net_atom[xembed] = ATOM("_XEMBED");
net_atom[xembedinfo] = ATOM("_XEMBED_INFO");
net_atom[manager] = ATOM("MANAGER");
net_atom[utf8_string] = ATOM("UTF8_STRING");
/* WMFS hints */
@@ -128,6 +141,54 @@ ewmh_init_hints(void)
return;
}
/** Send ewmh message
*/
void
ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4)
{
XClientMessageEvent e;
e.type = ClientMessage;
e.message_type = ATOM(atom);
e.window = w;
e.format = 32;
e.data.l[0] = d0;
e.data.l[1] = d1;
e.data.l[2] = d2;
e.data.l[3] = d3;
e.data.l[4] = d4;
XSendEvent(dpy, d, False, StructureNotifyMask, (XEvent*)&e);
XSync(dpy, False);
return;
}
/** Get xembed state
*/
long
ewmh_get_xembed_state(Window win)
{
Atom rf;
int f;
ulong n, il;
long ret = 0;
uchar *data = NULL;
if(XGetWindowProperty(dpy, win, net_atom[xembedinfo], 0L, 2, False,
net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success)
return 0;
if(rf == net_atom[xembedinfo] && n == 2)
ret = (long)data[1];
if(n && data)
XFree(data);
return ret;
}
/** Get the number of desktop (tag)
*/
void
@@ -380,6 +441,8 @@ ewmh_manage_window_type(Client *c)
/* Reparent it to ROOT win */
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
XRaiseWindow(dpy, c->win);
c->flags |= DockFlag;
}
/* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */
else if(atom[i] == net_atom[net_wm_window_type_dialog])
@@ -406,7 +469,6 @@ ewmh_manage_window_type(Client *c)
ldata[1] = atom[i];
ewmh_manage_net_wm_state(ldata, c);
}
XFree(data);
}

View File

@@ -222,7 +222,8 @@ frame_update(Client *c)
XClearWindow(dpy, c->button[i]);
if((!conf.titlebar.button[i].flags)
|| ((conf.titlebar.button[i].flags & FreeFlag) && (c->flags & FreeFlag))
|| ((conf.titlebar.button[i].flags & FreeFlag)
&& ((c->flags & FreeFlag) || !(c->flags & (TileFlag | LMaxFlag))))
|| ((conf.titlebar.button[i].flags & MaxFlag) && (c->flags & MaxFlag))
|| ((conf.titlebar.button[i].flags & TileFlag) && (c->flags & TileFlag)))
{

View File

@@ -173,14 +173,10 @@ getinfo_nmaster(void)
void
getinfo(char *info)
{
long data[5];
if(!check_wmfs_running())
return;
data[4] = True;
send_client_event(data, "_WMFS_UPDATE_HINTS");
ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_HINTS", 0, 0, 0, 0, True);
if(!strcmp(info, "tag"))
getinfo_tag();

View File

@@ -71,6 +71,7 @@ init(void)
init_root();
screen_init_geo();
infobar_init();
systray_acquire();
init_status();
ewmh_update_current_tag_prop();
grabkeys();
@@ -200,16 +201,16 @@ init_status(void)
sprintf(conf.status_path, "%s/"DEF_STATUS, home);
}
if (stat(conf.status_path, &st) == -1)
if (stat(patht(conf.status_path), &st) == -1)
{
warn("%s", conf.status_path);
warn("%s", patht(conf.status_path));
return;
}
if(st.st_size && st.st_mode & S_IXUSR)
estatus = True;
else
warnx("status file specified in configuratin (status_path) or present in wmfs directory can't be executed, try 'chmod +x %s'.", conf.status_path);
warnx("status file specified in configuratin (status_path) or present in wmfs directory can't be executed, try 'chmod +x %s'.", patht(conf.status_path));
return;
}

View File

@@ -102,6 +102,8 @@ mouse_move_tag_client(Client *c)
arrange(c->screen, True);
}
client_focus_next(c);
return;
}

View File

@@ -520,7 +520,7 @@ fetch_section_first(struct conf_sec *s, char *name)
if (!s)
{
TAILQ_FOREACH(sec, &config, entry)
if (!strcmp(sec->name, name)) {
if(sec->name && !strcmp(sec->name, name)) {
ret = sec;
break;
}
@@ -528,7 +528,7 @@ fetch_section_first(struct conf_sec *s, char *name)
else
{
TAILQ_FOREACH(sec, &s->sub, entry)
if (!strcmp(sec->name, name)) {
if (sec->name && !strcmp(sec->name, name)) {
ret = sec;
break;
}

View File

@@ -141,7 +141,10 @@ statustext_normal(int sc, char *str)
char strwc[MAXSTATUS] = { 0 };
char buf[MAXSTATUS] = { 0 };
char col[8] = { 0 };
int n, i, j, k;
int n, i, j, k, sw = 0;
if(sc == conf.systray.screen)
sw = systray_get_width();
for(i = j = n = 0; i < strlen(str); ++i, ++j)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
@@ -154,7 +157,7 @@ statustext_normal(int sc, char *str)
strwc[j] = str[i];
/* Draw normal text without any blocks */
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(strwc),
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - (textw(strwc) + sw),
FHINFOBAR, infobar[sc].bar->fg, 0, strwc);
if(n)
@@ -168,12 +171,12 @@ statustext_normal(int sc, char *str)
for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
/* Draw a rectangle with the bar color to draw the text properly */
draw_rectangle(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(&buf[k]),
draw_rectangle(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - (textw(&buf[k]) + sw),
0, INFOBARH - (sgeo[sc].width - SHADH) - textw(&buf[k]),
INFOBARH, conf.colors.bar);
/* Draw text with its color */
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(&buf[k]),
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - (textw(&buf[k]) + sw),
FHINFOBAR, col, 0, &buf[k]);
strcpy(buf, strwc);
@@ -192,7 +195,7 @@ void
statustext_handle(int sc, char *str)
{
char *lastst;
int i, nr, ng, ns, len;
int i, nr, ng, ns, len, sw = 0;
StatusRec r[128];
StatusGraph g[128];
StatusText s[128];
@@ -201,6 +204,9 @@ statustext_handle(int sc, char *str)
if(!str)
return;
if(sc == conf.systray.screen)
sw = systray_get_width();
barwin_refresh_color(infobar[sc].bar);
/* save last status text address (for free at the end) */
@@ -219,15 +225,15 @@ statustext_handle(int sc, char *str)
/* Draw rectangles with stored properties. */
for(i = 0; i < nr; ++i)
draw_rectangle(infobar[sc].bar->dr, r[i].x, r[i].y, r[i].w, r[i].h, r[i].color);
draw_rectangle(infobar[sc].bar->dr, r[i].x - sw, r[i].y, r[i].w, r[i].h, r[i].color);
/* Draw graphs with stored properties. */
for(i = 0; i < ng; ++i)
draw_graph(infobar[sc].bar->dr, g[i].x, g[i].y, g[i].w, g[i].h, g[i].color, g[i].data);
draw_graph(infobar[sc].bar->dr, g[i].x - sw, g[i].y, g[i].w, g[i].h, g[i].color, g[i].data);
/* Draw located text with stored properties. */
for(i = 0; i < ns; ++i)
draw_text(infobar[sc].bar->dr, s[i].x, s[i].y, s[i].color, 0, s[i].text);
draw_text(infobar[sc].bar->dr, s[i].x - sw, s[i].y, s[i].color, 0, s[i].text);
barwin_refresh(infobar[sc].bar);

View File

@@ -52,6 +52,7 @@
#define AboveFlag (1 << 9)
#define UrgentFlag (1 << 10)
#define FLayFlag (1 << 11)
#define DockFlag (1 << 12)
#define TagFlag(t) (1 << (t))
@@ -125,6 +126,14 @@ enum
net_wm_state_fullscreen,
net_wm_state_sticky,
net_wm_state_demands_attention,
net_wm_system_tray_opcode,
net_system_tray_message_data,
net_system_tray_s,
net_system_tray_visual,
net_system_tray_orientation,
xembed,
xembedinfo,
manager,
utf8_string,
/* WMFS HINTS */
wmfs_running,
@@ -175,6 +184,7 @@ struct Client
char *title;
/* Tag num */
uint tag;
int focusontag;
/* Screen */
int screen;
/* Layer */
@@ -252,6 +262,15 @@ typedef struct
void (*func)(int screen);
} Layout;
/* Systray Structure */
typedef struct Systray Systray;
struct Systray
{
Window win;
XRectangle geo;
Systray *next, *prev;
};
/* Tag Structure */
typedef struct
{
@@ -430,6 +449,12 @@ typedef struct
Bool tag;
Bool layout;
} border;
struct
{
Bool active;
int screen;
int spacing;
} systray;
Alias alias[256];
uint mouse_tag_action[TagActionLast];
Layout layout[NUM_OF_LAYOUT];
@@ -500,4 +525,10 @@ typedef struct
char *uicb;
} vicmd_to_uicb;
typedef struct
{
int version;
int flags;
} xembed_info;
#endif /* STRUCTS_H */

View File

@@ -32,3 +32,203 @@
#include "wmfs.h"
#define TRAY_DWIDTH (infobar[conf.systray.screen].bar->geo.height + conf.systray.spacing)
Bool
systray_acquire(void)
{
XSetWindowAttributes wattr;
if(!conf.systray.active || traywin)
return False;
if(XGetSelectionOwner(dpy, net_atom[net_system_tray_s]) != None)
{
warnx("Can't initialize system tray: owned by another process");
return False;
}
/* Init traywin window */
wattr.event_mask = ButtonPressMask | ExposureMask;
wattr.override_redirect = True;
wattr.background_pixmap = ParentRelative;
wattr.background_pixel = conf.colors.bar;
traywin = XCreateSimpleWindow(dpy, infobar[conf.systray.screen].bar->win, -1, -1, 1, 1, 0, 0, conf.colors.bar);
XChangeWindowAttributes(dpy, traywin, CWEventMask | CWOverrideRedirect | CWBackPixel, &wattr);
XSelectInput(dpy, traywin, KeyPressMask | ButtonPressMask);
XMapRaised(dpy, traywin);
XSetSelectionOwner(dpy, net_atom[net_system_tray_s], traywin, CurrentTime);
if(XGetSelectionOwner(dpy, net_atom[net_system_tray_s]) != traywin)
{
systray_freeicons();
warnx("System tray: can't get systray manager");
return False;
}
ewmh_send_message(ROOT, ROOT, "MANAGER", CurrentTime, net_atom[net_system_tray_s], traywin, 0, 0);
XSync(dpy, False);
return True;
}
void
systray_add(Window win)
{
Systray *s;
if(!conf.systray.active)
return;
s = emalloc(1, sizeof(Systray));
s->win = win;
s->geo.height = infobar[conf.systray.screen].bar->geo.height;
s->geo.width = TRAY_DWIDTH;
setwinstate(s->win, WithdrawnState);
XSelectInput(dpy, s->win, StructureNotifyMask | PropertyChangeMask| EnterWindowMask | FocusChangeMask);
XReparentWindow(dpy, s->win, traywin, 0, 0);
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0, traywin, 0);
/* Attach */
if(trayicons)
trayicons->prev = s;
s->next = trayicons;
trayicons = s;
return;
}
void
systray_del(Systray *s)
{
Systray **ss;
if(!conf.systray.active)
return;
for(ss = &trayicons; *ss && *ss != s; ss = &(*ss)->next);
*ss = s->next;
IFREE(s);
return;
}
void
systray_state(Systray *s)
{
long flags;
int code = 0;
if(!(flags = ewmh_get_xembed_state(s->win)) || !conf.systray.active)
return;
if(flags & XEMBED_MAPPED)
{
code = XEMBED_WINDOW_ACTIVATE;
XMapRaised(dpy, s->win);
setwinstate(s->win, NormalState);
}
else
{
code = XEMBED_WINDOW_DEACTIVATE;
XUnmapWindow(dpy, s->win);
setwinstate(s->win, WithdrawnState);
}
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, code, 0, 0, 0);
return;
}
void
systray_freeicons(void)
{
Systray *i;
if(!conf.systray.active)
return;
for(i = trayicons; i; i = i->next)
{
XUnmapWindow(dpy, i->win);
XReparentWindow(dpy, i->win, ROOT, 0, 0);
IFREE(i);
}
XSetSelectionOwner(dpy, net_atom[net_system_tray_s], None, CurrentTime);
XDestroyWindow(dpy, traywin);
XSync(dpy, 0);
return;
}
Systray*
systray_find(Window win)
{
Systray *i;
if(!conf.systray.active)
return NULL;
for(i = trayicons; i; i = i->next)
if(i->win == win)
return i;
return NULL;
}
int
systray_get_width(void)
{
int w = 0;
Systray *i;
if(!conf.systray.active)
return 0;
for(i = trayicons; i; i = i->next)
w += i->geo.width + conf.systray.spacing + 1;
return w;
}
void
systray_update(void)
{
Systray *i;
int x = 1;
if(!conf.systray.active)
return;
if(!trayicons)
{
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - 1, 0, 1, 1);
return;
}
for(i = trayicons; i; i = i->next)
{
XMapWindow(dpy, i->win);
XMoveResizeWindow(dpy, i->win, (i->geo.x = x), 0, i->geo.width, i->geo.height);
x += i->geo.width + conf.systray.spacing;
}
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - x,
0, x, infobar[conf.systray.screen].bar->geo.height);
return;
}

View File

@@ -42,6 +42,9 @@ tag_set(int tag)
Bool al = False;
int i;
if(tag < 0 || tag > MAXTAG)
return;
screen_get_sel();
prevseltag[selscreen] = seltag[selscreen];
@@ -102,11 +105,17 @@ tag_set(int tag)
tags[selscreen][tag].request_update = False;
}
/* To focus the first client in the new tag */
/* To focus selected client of the via focusontag option */
for(c = clients; c; c = c->next)
if(c->tag == seltag[selscreen] && c->screen == selscreen)
if(c->focusontag == tag && c->screen == selscreen)
break;
/* No focusontag option found on any client, try to find the first of the tag */
if(!c)
for(c = clients; c; c = c->next)
if(c->tag == seltag[selscreen] && c->screen == selscreen)
break;
client_focus((c) ? c : NULL);
return;
@@ -123,7 +132,7 @@ tag_transfert(Client *c, int tag)
CHECK(c);
if(!tag)
if(tag <= 0)
tag = 1;
if(tag > conf.ntag[selscreen])
@@ -134,8 +143,7 @@ tag_transfert(Client *c, int tag)
arrange(c->screen, True);
if(c == sel && c->tag != tag)
client_focus(NULL);
client_focus_next(c);
client_update_attributes(c);
@@ -502,9 +510,9 @@ tag_new(int s, char *name)
displayedName = name;
Tag t = { displayedName, NULL, 0, 0,
conf.default_tag.mwfact, conf.default_tag.nmaster,
conf.default_tag.mwfact, conf.default_tag.nmaster,
False, conf.default_tag.resizehint, False, False,
conf.default_tag.barpos, conf.default_tag.layout,
conf.default_tag.barpos, conf.default_tag.layout,
0, NULL, 0 };

View File

@@ -340,3 +340,19 @@ clean_value(char *str)
return p;
}
/* To use ~/ shortcut.. */
char*
patht(char *path)
{
static char ret[512];
if(!path)
return NULL;
strcpy(ret, path);
if(strstr(path, "~/"))
sprintf(ret, "%s/%s", getenv("HOME"), path + 2);
return ret;
}

View File

@@ -92,6 +92,8 @@ quit(void)
IFREE(tags);
IFREE(seltag);
systray_freeicons();
XftFontClose(dpy, font);
for(i = 0; i < CurLast; ++i)
XFreeCursor(dpy, cursor[i]);
@@ -214,26 +216,27 @@ scan(void)
if(XQueryTree(dpy, ROOT, &usl, &usl2, &w, &n))
for(i = n - 1; i != -1; --i)
if(XGetWindowAttributes(dpy, w[i], &wa)
&& !(wa.override_redirect || XGetTransientForHint(dpy, w[i], &usl))
&& wa.map_state == IsViewable)
{
XGetWindowAttributes(dpy, w[i], &wa);
if(!wa.override_redirect && wa.map_state == IsViewable)
{
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_TAG"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
tag = *ret;
XFree(ret);
}
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_SCREEN"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
screen = *ret;
XFree(ret);
}
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_ISFREE"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
free = *ret;
XFree(ret);
@@ -250,6 +253,7 @@ scan(void)
client_update_attributes(c);
}
}
/* Set update layout request */
for(c = clients; c; c = c->next)
@@ -319,15 +323,11 @@ check_wmfs_running(void)
void
exec_uicb_function(char *func, char *cmd)
{
long data[5];
/* Check if wmfs is running (this function is executed when wmfs
is already running normally...) */
if(!check_wmfs_running())
return;
data[4] = True;
XChangeProperty(dpy, ROOT, ATOM("_WMFS_FUNCTION"), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)func, strlen(func));
@@ -337,7 +337,7 @@ exec_uicb_function(char *func, char *cmd)
XChangeProperty(dpy, ROOT, ATOM("_WMFS_CMD"), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)cmd, strlen(cmd));
send_client_event(data, "_WMFS_FUNCTION");
ewmh_send_message(ROOT, ROOT, "_WMFS_FUNCTION", 0, 0, 0, 0, True);
return;
}
@@ -349,11 +349,8 @@ void
set_statustext(int s, char *str)
{
int i;
long data[5];
char atom_name[64];
data[4] = True;
if(!str)
return;
@@ -366,7 +363,7 @@ set_statustext(int s, char *str)
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)str, strlen(str));
send_client_event(data, atom_name);
ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
}
}
else
@@ -376,7 +373,7 @@ set_statustext(int s, char *str)
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)str, strlen(str));
send_client_event(data, atom_name);
ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
}
return;
@@ -387,14 +384,10 @@ set_statustext(int s, char *str)
void
update_status(void)
{
long data[5];
if(!check_wmfs_running())
return;
data[4] = True;
send_client_event(data, "_WMFS_UPDATE_STATUS");
ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_STATUS", 0, 0, 0, 0, True);
return;
}

View File

@@ -185,6 +185,7 @@ void client_size_hints(Client *c);
void client_swap(Client *c1, Client *c2);
void client_raise(Client *c);
void client_unhide(Client *c);
void client_focus_next(Client *c);
void client_unmanage(Client *c);
void client_unmap(Client *c);
void client_set_rules(Client *c);
@@ -211,6 +212,8 @@ void uicb_client_ignore_tag(uicb_t);
/* ewmh.c */
void ewmh_init_hints(void);
void ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4);
long ewmh_get_xembed_state(Window win);
void ewmh_get_number_of_desktop(void);
void ewmh_update_current_tag_prop(void);
void ewmh_get_client_list(void);
@@ -240,10 +243,12 @@ void focusin(XFocusChangeEvent *ev);
void grabkeys(void);
void keypress(XKeyPressedEvent *ev);
void mappingnotify(XMappingEvent *ev);
void mapnotify(XMapEvent *ev);
void maprequest(XMapRequestEvent *ev);
void reparentnotify(XReparentEvent *ev);
void selectionclearevent(XSelectionClearEvent *ev);
void propertynotify(XPropertyEvent *ev);
void unmapnotify(XUnmapEvent *ev);
void send_client_event(long data[5], char *atom_name);
void getevent(XEvent ev);
/* menu.c */
@@ -291,6 +296,8 @@ int spawn(const char *str, ...);
void swap_ptr(void **x, void **y);
void uicb_spawn(uicb_t);
char *clean_value(char *str);
char* patht(char *path);
#ifdef HAVE_IMLIB
int parse_image_block(ImageAttr *im, char *str);
@@ -341,7 +348,14 @@ void statustext_normal(int sc, char *str);
void statustext_handle(int sc, char *str);
/* systray.c */
Bool systray_acquire(void);
void systray_add(Window win);
void systray_del(Systray *s);
void systray_state(Systray *s);
void systray_freeicons(void);
Systray* systray_find(Window win);
int systray_get_width(void);
void systray_update(void);
/* layout.c */
void arrange(int screen, Bool update_layout);
@@ -435,6 +449,7 @@ XftFont *font;
/* Atoms list */
Atom *net_atom;
Atom trayatom;
/* InfoBar/Tags */
InfoBar *infobar;
@@ -458,6 +473,9 @@ Client *sel;
func_name_list_t *func_list;
extern const func_name_list_t layout_list[];
uint numlockmask;
Systray *trayicons;
Window traywin;
int tray_width;
#endif /* WMFS_H */