You are not logged in.
upload your dwm.c and config.h, and put a link here.. and i'll try to make that updates for you.
Arch64/DWM || My Dropbox referral link
Offline
Offline
JokerBoy - this thread is to share patches and tips, not a drop-off repair and clean service. If xxsahixx wants to show some intiative and attempt to learn dwm, then fine - otherwise please do not spoon feed him.
Offline
jwr - you're right.. sorry.
Arch64/DWM || My Dropbox referral link
Offline
Part 1/2
I made two little hacks to DWM that I would like to share. This is part one. Just so people know I'm not an experienced programmer or a software developer, and I just pieced this together from other sources (mostly wmfs source), so please excuse my bad coding manners.
The first one is program launcher that is similar to what you find in awesome or in wmfs. This is by default handled in dwm by launching an external program (dmenu), but with this hack, you don't need to install dmenu. This is done by adding these two functions in dwm.c:
void launcher(const Arg *arg){
int x, pos;
unsigned int i;
const char prompt[] = "Run: ";
char tmp[32];
char buf[256];
Bool grabbing = True;
KeySym ks;
XEvent ev;
// Clear the array
memset(tmp, 0, sizeof(tmp));
memset(buf, 0, sizeof(buf));
pos = 0;
// Initial x position
x = 0;
for(i = 0; i < LENGTH(tags); i++) x+= TEXTW(tags[i]);
x += TEXTW(selmon->ltsymbol);
dc.x = x;
dc.w = selmon->ww - x - TEXTW(stext);
if(selmon->primary==1) dc.w -= systray_get_width(); // primary monitor has systray
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
drawtext(prompt, dc.norm, False);
dc.x += TEXTW(prompt);
XDrawLine(dpy, dc.drawable, dc.gc, dc.x, 3, dc.x, bh-3);
XCopyArea(dpy, dc.drawable, selmon -> barwin, dc.gc, x, 0, dc.w, bh, x, 0);
XSync(dpy, False);
while(grabbing){
if(ev.type == KeyPress) {
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
switch(ks){
case XK_Return:
shexec(buf);
grabbing = False;
break;
case XK_BackSpace:
if(pos) buf[--pos] = 0;
break;
case XK_Escape:
grabbing = False;
break;
default:
strncat(buf, tmp, sizeof(tmp));
++pos;
break;
}
drawtext(buf, dc.norm, False);
XDrawLine(dpy, dc.drawable, dc.gc, dc.x+TEXTW(buf), 3, dc.x+TEXTW(buf), bh-3);
XCopyArea(dpy, dc.drawable, selmon->barwin, dc.gc, dc.x, 0, dc.w-TEXTW(prompt), bh, dc.x, 0);
XSync(dpy, False);
}
XNextEvent(dpy, &ev);
}
// Restore bar
drawbar(selmon);
XUngrabKeyboard(dpy, CurrentTime);
return;
}
pid_t shexec(const char *cmd){
char *sh = NULL;
pid_t pid;
if(!(sh = getenv("SHELL"))) sh = "/bin/sh";
if((pid = fork()) == 0){
if(dpy) close(ConnectionNumber(dpy));
setsid();
execl(sh, sh, "-c", cmd, (char*)NULL);
err(1, "execl(%s)", cmd);
}
if (pid == -1)
warn("fork()");
return pid;
}
and adding a key shortcut to envoke launcher in config.h (I mapped it to Mod+r):
{ MODKEY, XK_r, launcher, {0} },
The function is very minimal (no history, tab completion, etc...) because I have no need for them, but these can easily be done (look at launcher.c in wmfs source for inspiration!)
To be continued...
Offline
Part 2/2
Again, please excuse me for being ignorant in coding manners... Also I'm not providing diff patches because my dwm.c is beyond recognition from the vanilla code (and I'm too lazy to learn how to make it work).
Anyway, this is simply to provide systray to DWM without using external programs such as trayer or stalonetray. The problem with using external programs is that the status text doesn't automatically position as the systray grows/shrinks. This is a little bit more complicated than the previous hack I posted (launcher), but hopefully this will make sense... If not, I'll try to learn to make a diff patch :-)
First: add this in heading section of dwm.c (before "/* function implementations */":
#define XEMBED_EMBEDDED_NOTIFY 0
#define IFREE(x) if(x) free(x)
#define zcalloc(size) calloc(1, (size))
typedef struct Systray Systray;
struct Systray {
Window win;
XRectangle geo;
Systray *next, *prev;
};
Systray *trayicons;
Window traywin;
and add
NetSystemTray
to the EWMH atoms enums
Then add these functions in the body:
Bool systray_acquire(void) {
XSetWindowAttributes wattr;
if(!systray_enable || traywin) return False;
if(XGetSelectionOwner(dpy, netatom[NetSystemTray]) != None) {
fprintf(stderr, "Can't initialize system tray: owned by another process\n");
return False;
}
// Init traywin window
wattr.event_mask = ButtonPressMask | ExposureMask;
wattr.override_redirect = True;
wattr.background_pixmap = ParentRelative;
wattr.background_pixel = dc.norm[ColBG];
traywin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, dc.norm[ColBG]);
XChangeWindowAttributes(dpy, traywin, CWEventMask | CWOverrideRedirect | CWBackPixel, &wattr);
XSelectInput(dpy, traywin, KeyPressMask | ButtonPressMask);
XMapRaised(dpy, traywin);
XSetSelectionOwner(dpy, netatom[NetSystemTray], traywin, CurrentTime);
if(XGetSelectionOwner(dpy, netatom[NetSystemTray]) != traywin) {
systray_freeicons();
fprintf(stderr, "System tray: can't get systray manager\n");
return False;
}
XSync(dpy, False);
return True;
}
void systray_add(Window win) {
Systray *s;
if(!systray_enable) return;
s = zcalloc(sizeof(Systray));
s->win = win;
s->geo.height = bh;
s->geo.width = bh;
XSelectInput(dpy, s->win, StructureNotifyMask | PropertyChangeMask| EnterWindowMask | FocusChangeMask);
XReparentWindow(dpy, s->win, traywin, 0, 0);
// Attach
if(trayicons) trayicons->prev = s;
s->next = trayicons;
trayicons = s;
return;
}
void systray_del(Systray *s) {
Systray **ss;
if(!systray_enable) return;
for(ss = &trayicons; *ss && *ss != s; ss = &(*ss)->next);
*ss = s->next;
IFREE(s);
return;
}
void systray_freeicons(void) {
Systray *i;
if(!systray_enable) return;
for(i = trayicons; i; i = i->next) {
XUnmapWindow(dpy, i->win);
XReparentWindow(dpy, i->win, ROOT, 0, 0);
IFREE(i);
}
XSetSelectionOwner(dpy, netatom[NetSystemTray], None, CurrentTime);
XDestroyWindow(dpy, traywin);
XSync(dpy, 0);
return;
}
Systray* systray_find(Window win) {
Systray *i;
if(!systray_enable) 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(!systray_enable) return 0;
for(i = trayicons; i; i = i->next)
w += i->geo.width + systray_spacing + 1;
return w;
}
void systray_update(void) {
Systray *i;
Monitor *m;
int x = 1;
int pos = blw;
if(!systray_enable) return;
for(m = mons; m; m = m -> next){
if(m->primary == 1) pos = m -> ww;
}
if(!trayicons) {
pos -= 1;
XMoveResizeWindow(dpy, traywin, pos, 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 + systray_spacing;
}
pos -= x;
XMoveResizeWindow(dpy, traywin, pos, 0, x, bh);
return;
}
Now we need to have DWM handle the events:
Edit destroynotify:
void destroynotify(XEvent *e) {
Client *c;
Systray *s;
XDestroyWindowEvent *ev = &e->xdestroywindow;
if((c = wintoclient(ev->window))) unmanage(c, True);
else if((s = systray_find(ev->window))){
systray_del(s);
systray_update();
}
}
Edit clientmessage:
void clientmessage(XEvent *e) {
...
resizeclient(c, c->x, c->y, c->w, c->h);
arrange(c->mon);
}
}
// begin edit
if(cme->window == traywin) {
if(cme->data.l[1] == XEMBED_EMBEDDED_NOTIFY){
systray_add(cme->data.l[2]);
systray_update();
}
}
// end edit
}
in setup, add this line under /* init atoms */:
netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
and just after updatebars(); and updatestatus();, add:
systray_acquire();
It should work after all this is done, although it is very likely that I forgot something. If something doesn't work, please let me know.
EDIT #1: Please add the following in config.h:
static const Bool systray_enable = True;
static const int systray_spacing = 1;
Also, I forgot about primary monitor test. which done by doing the following:
add in struct Monitor:
struct Monitor{
...
int primary;
};
Change the function createmon(void) to:
Monitor * createmon(int primary){
...
m->primary = primary; // Add this
return m;
}
Find in the function updategeom(void):
for(i = 0; i < (nn - n); i++) { /* new monitors available */
for(m = mons; m && m->next; m = m->next);
if(m)
m->next = createmon();
else
mons = createmon();
}
replace with
/* first = primary monitor */
for(m = mons; m && m->next; m = m->next);
if(m) m->next = createmon(1);
else mons = createmon(1);
for(i = 0; i < (nn - n -1); i++) { /* new monitors available */
for(m = mons; m && m->next; m = m->next);
if(m) m->next = createmon(0);
else mons = createmon(0);
}
And find:
/* default monitor setup */
{
if(!mons)
mons = createmon();
if(mons->mw != sw || mons->mh != sh) {
dirty = True;
mons->mw = mons->ww = sw;
mons->mh = mons->wh = sh;
updatebarpos(mons);
}
}
replace
mons = createmon();
with
mons = createmon(1);
I'm sorry this is becoming really long and hard to read.
Last edited by kcirick (2011-01-10 00:27:55)
Offline
@ kcirick
Trying to get your launcher
I defined a function as static void then I used the code, but it still won't compile, am I supposed to be adding something else as well?
Offline
@ kcirick
Trying to get your launcher
I defined a function as static void then I used the code, but it still won't compile, am I supposed to be adding something else as well?
What does the compiler say?
Offline
xxsashixx wrote:@ kcirick
Trying to get your launcher
I defined a function as static void then I used the code, but it still won't compile, am I supposed to be adding something else as well?What does the compiler say?
dwm.c: In function 'launcher':
dwm.c:307:14: error: 'Monitor' has no member named 'primary'
dwm.c:307:5: warning: implicit declaration of function 'systray_get_width'
dwm.c:309:24: error: 'ROOT' undeclared (first use in this function)
dwm.c:309:24: note: each undeclared identifier is reported only once for each function it appears in
Offline
Comment the line
if(selmon->primary==1) dc.w -= systray_get_width(); // primary monitor has systray
This line is uncommented only with systray use.
define below in with the other definitions
#define ROOT RootWindow(dpy, DefaultScreen(dpy))
That should work. Let me know if there are other problems!
Offline
Ah cool cool didn't even read the code
Offline
...
Hi,
thanks for sharing!
Had to make some minor adjustments afterwards:
static Monitor *createmon(int);
also createmon has still to return m(?!) and systray_freeicons has to be declared before systray_acquire. Also ROOT has to be defined as you already said.
Don't know if I messed something up, as I roughly know any C. Yet it works, but how do you arrange the space with the xsetroot output?
Offline
Hi,
thanks for sharing!
Thanks for looking and trying out the systray mod. You are brave :-P
Had to make some minor adjustments afterwards:
static Monitor *createmon(int);
also createmon has still to return m(?!) and systray_freeicons has to be declared before systray_acquire. Also ROOT has to be defined as you already said.
Yes, the createmon function still returns m, sorry my mistake. The only thing I changed in that function call is added to the Monitor class "int primary" (which could be a boolean) whether the monitor is a primary monitor or not. The function order shouldn't matter as long as they are declared first (beginning from around line 110...)
Don't know if I messed something up, as I roughly know any C. Yet it works, but how do you arrange the space with the xsetroot output?
I'm not quite sure what you mean by "arrange the space"?
Offline
E.g. for me the systray overlaps with the date.
Offline
I sure forgot one little minor detail (again). You need to add one line in darbar() function in dwm.c:
void drawbar(Monitor *m) {
...
if(m == selmon) { /* status is only drawn on selected monitor */
dc.w = TEXTW(stext);
dc.x = m->ww - dc.w;
if(m->primary == 1) dc.x -= systray_get_width(); // subtract systray width
if(dc.x < x) {
dc.x = x;
dc.w = m->ww - x;
}
drawcoloredtext(stext);
} else
...
}
That should fix the problem
Offline
please, make a patch for this and put it somewhere.. or upload your dwm.c..
diff -u original-dwm.c modified-dwm.c > dwm-5.8.2-systray.diff
until now nothing works for me..
dwm.c: In function 'destroynotify':
dwm.c:681:2: warning: implicit declaration of function 'systray_find'
dwm.c:681:13: warning: assignment makes pointer from integer without a cast
dwm.c:682:3: warning: implicit declaration of function 'systray_del'
dwm.c:683:3: warning: implicit declaration of function 'systray_update'
dwm.c: In function 'clientmessage':
dwm.c:1409:4: warning: implicit declaration of function 'systray_add'
dwm.c: In function 'setup':
dwm.c:1653:2: warning: implicit declaration of function 'systray_acquire'
dwm.c: At top level:
dwm.c:2517:6: warning: conflicting types for 'systray_add'
dwm.c:1409:4: note: previous implicit declaration of 'systray_add' was here
dwm.c:2540:6: warning: conflicting types for 'systray_del'
dwm.c:682:3: note: previous implicit declaration of 'systray_del' was here
dwm.c:2555:1: error: conflicting types for 'systray_find'
dwm.c:681:15: note: previous implicit declaration of 'systray_find' was here
dwm.c:2578:6: warning: conflicting types for 'systray_update'
dwm.c:683:3: note: previous implicit declaration of 'systray_update' was here
Arch64/DWM || My Dropbox referral link
Offline
I sure forgot one little minor detail (again). You need to add one line in darbar() function in dwm.c:
void drawbar(Monitor *m) { ... if(m == selmon) { /* status is only drawn on selected monitor */ dc.w = TEXTW(stext); dc.x = m->ww - dc.w; if(m->primary == 1) dc.x -= systray_get_width(); // subtract systray width if(dc.x < x) { dc.x = x; dc.w = m->ww - x; } drawcoloredtext(stext); } else ... }
That should fix the problem
Yup, did it for me. Thanks.
Though overall xmodmap via xinitrc isn't working anymore and any attempt to start quake results in a crash of X.
Offline
please, make a patch for this and put it somewhere.. or upload your dwm.c..
diff -u original-dwm.c modified-dwm.c > dwm-5.8.2-systray.diff
Ok, I made a diff patch, so I will upload it onto my git and will post it tonight (I need to set up a git but I forgot my password). I applied the diff patch that I made to vanilla code, and it works, so I know I did it right.
Stay tuned...
EDIT:
OK. So I made the diff patches which can be downloaded from below. The naming scheme is self-explanatory. Please ignore the config.h, it is really old and doesn't really belong there.
https://github.com/kcirick/dwm
After applying the patches, you need to still update the config.h. If you patched launcher, then you need to add the following (mapping MOD+r to bring up launcher):
{ MODKEY, XK_r, launcher, {0} },
and if you patched systray, then you need to add the following:
static const Bool systray_enable = True;
static const int systray_spacing = 1;
Please let me know if there are still problems.
Last edited by kcirick (2011-01-10 22:58:45)
Offline
Yup, did it for me. Thanks.
Though overall xmodmap via xinitrc isn't working anymore and any attempt to start quake results in a crash of X.
I'm not surprised that it breaks X under some circumstances... It was very quick and dirty way, and mostly cutting and pasting from WMFS without deep knowledge of what each line of code does. It doesn't crash for what I'm using for (nm-applet, scim, pidgin are all that's ever there), but feel free to improve upon this!
Offline
OK. So I made the diff patches which can be downloaded from below. The naming scheme is self-explanatory. Please ignore the config.h, it is really old and doesn't really belong there.
I used your patch on a fresh dwm install and it works perfectly.
Thanks!
Lenovo X201T
Arch x86_64
Offline
yes, it works.. but not perfectly.. keep in mind that is taken from an another WM...
i tested it, it works.. thanks for sharing.. but after a while i got used to a non-systray WM
Arch64/DWM || My Dropbox referral link
Offline
yes, it works.. but not perfectly.. keep in mind that is taken from an another WM...
i tested it, it works.. thanks for sharing.. but after a while i got used to a non-systray WM
Yes, I agree that it works, and I agree that it doesn't work perfectly, but I don't think the reason why it doesn't work perfectly is because it is taken from another WM. It has no dependency of any other components of WMFS. It's purely the lack of my complete understanding of Xlib.
I feel like this could be improved to be a native patch for DWM. I personally don't have time or motivation to do it, but others might be interested.
Cheers,
P.S. @JokerBoy: What exactly isn't working in your case? I probably won't be able to fix it, but I was just curious...
Last edited by kcirick (2011-01-12 04:37:12)
Offline
i use already 15 patches, and it seems to be a conflict between pertag initlayouts patch and systray patch.. i guess it's related to createmon, void vs int primary. i don't know C, so i don't really know what's the problem..
Arch64/DWM || My Dropbox referral link
Offline
Kcirick, I'm trying to use your systray patch, and Xorg outputs a BadAtom error when I try to start dwm. I using almost vanilla DWM, with the only patch being your systray patch. I have no idea what could be the problem. Here's the output when I run 'xinit /usr/bin/dwm':
_XSERVTransSocketOpenCOTSServer: Unable to open socket for inet6
_XSERVTransOpen: transport open failed for inet6/adetque-desktop:0
_XSERVTransMakeAllCOTSServerListeners: failed to open listener for inet6
X.Org X Server 1.9.2
Release Date: 2010-10-30
X Protocol Version 11, Revision 0
Build Operating System: Linux 2.6.35-ARCH i686
Current Operating System: Linux adetque-desktop 2.6.36-adetque #4 SMP Mon Jan 10 16:15:52 EST 2011 i686
Kernel command line: root=/dev/sda1 ro nomodeset vga=870 fastboot logo.nologo ipv6.disable=1
Build Date: 01 November 2010 10:35:30PM
Current version of pixman: 0.20.0
Before reporting problems, check http://wiki.x.org
to make sure that you have the latest version.
Markers: (--) probed, (**) from config file, (==) default setting,
(++) from command line, (!!) notice, (II) informational,
(WW) warning, (EE) error, (NI) not implemented, (??) unknown.
(==) Log file: "/var/log/Xorg.0.log", Time: Thu Jan 13 13:51:28 2011
(==) Using config file: "/etc/X11/xorg.conf"
(==) Using config directory: "/etc/X11/xorg.conf.d"
(WW) fglrx: No matching Device section for instance (BusID PCI:0@1:0:1) found
dwm: missing fontset: ISO10646-1
dwm: missing fontset: JISX0201.1976-0
dwm: missing fontset: GB2312.1980-0
dwm: missing fontset: KSC5601.1987-0
dwm: missing fontset: JISX0208.1983-0
dwm: missing fontset: ISO8859-15
dwm: missing fontset: ISO8859-14
dwm: missing fontset: ISO8859-13
dwm: missing fontset: ISO8859-9
dwm: missing fontset: ISO8859-7
dwm: missing fontset: KOI8-R
dwm: missing fontset: ISO8859-5
dwm: missing fontset: ISO8859-4
dwm: missing fontset: ISO8859-3
dwm: missing fontset: ISO8859-2
dwm: fatal error: request code=23, error code=5
X Error of failed request: BadAtom (invalid Atom parameter)
Major opcode of failed request: 23 (X_GetSelectionOwner)
Atom id in failed request: 0x400005
Serial number of failed request: 164
Current serial number in output stream: 164
xinit: connection to X server lost
waiting for X server to shut down
Thanks if you decide to help.
Offline
Kcirick, I'm trying to use your systray patch, and Xorg outputs a BadAtom error when I try to start dwm. I using almost vanilla DWM, with the only patch being your systray patch. I have no idea what could be the problem. Here's the output when I run 'xinit /usr/bin/dwm':
...
Thanks if you decide to help.
What application do you run that would go into the systray? Does it work if you don't open any applications?
Long story short, I have no idea what the error message is talking about.
Offline