Fix bug when the focused window deinitialized
[notion.git] / mod_notionflux / notionflux / notionflux.c
blob88d0c1676d3d0cc4789f7278f55451de6fc680eb
1 /*
2 * mod_notionflux/notionflux/notionflux.c
4 * Copyright (c) Tuomo Valkonen 2004-2005.
6 * This is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
12 #include <X11/Xlib.h>
13 #include <X11/Xatom.h>
15 #include <libtu/types.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
25 #include "../notionflux.h"
27 static void die(const char *s)
29 fprintf(stderr, "%s\n", s);
30 exit(1);
34 static void die_e(const char *s)
36 perror(s);
37 exit(1);
40 static void mywrite(int fd, const char *buf, int n)
42 while(n>0){
43 int k;
44 k=write(fd, buf, n);
45 if(k<0 && (errno!=EAGAIN && errno!=EINTR))
46 die_e("Writing");
47 if(k>0){
48 n-=k;
49 buf+=k;
55 static int myread(int fd, char *buf, int n)
57 int left=n;
59 while(left>0){
60 int k;
61 k=read(fd, buf, left);
62 if(k<0 && (errno!=EAGAIN && errno!=EINTR))
63 die_e("Writing");
64 if(k==0)
65 break;
66 if(k>0){
67 left-=k;
68 buf+=k;
71 return n-left;
75 static char buf[MAX_DATA];
78 /*{{{ X */
81 static Display *dpy=NULL;
84 static ulong xwindow_get_property_(Window win, Atom atom, Atom type,
85 ulong n32expected, bool more, uchar **p,
86 int *format)
88 Atom real_type;
89 ulong n=-1, extra=0;
90 int status;
92 do{
93 status=XGetWindowProperty(dpy, win, atom, 0L, n32expected,
94 False, type, &real_type, format, &n,
95 &extra, p);
97 if(status!=Success || *p==NULL)
98 return -1;
100 if(extra==0 || !more)
101 break;
103 XFree((void*)*p);
104 n32expected+=(extra+4)/4;
105 more=FALSE;
106 }while(1);
108 if(n==0){
109 XFree((void*)*p);
110 *p=NULL;
111 return -1;
114 return n;
118 ulong xwindow_get_property(Window win, Atom atom, Atom type,
119 ulong n32expected, bool more, uchar **p)
121 int format=0;
122 return xwindow_get_property_(win, atom, type, n32expected, more, p,
123 &format);
127 char *xwindow_get_string_property(Window win, Atom a, int *nret)
129 char *p;
130 int n;
132 n=xwindow_get_property(win, a, XA_STRING, 64L, TRUE, (uchar**)&p);
134 if(nret!=NULL)
135 *nret=n;
137 return (n<=0 ? NULL : p);
141 void xwindow_set_string_property(Window win, Atom a, const char *value)
143 if(value==NULL){
144 XDeleteProperty(dpy, win, a);
145 }else{
146 XChangeProperty(dpy, win, a, XA_STRING,
147 8, PropModeReplace, (uchar*)value, strlen(value));
152 static char *get_socket()
154 Atom a;
155 char *s;
157 dpy=XOpenDisplay(NULL);
159 if(dpy==NULL)
160 die_e("Unable to open display.");
162 a=XInternAtom(dpy, "_NOTION_MOD_NOTIONFLUX_SOCKET", True);
164 if(a==None)
165 die_e("Missing atom. Notion not running?");
167 s=xwindow_get_string_property(DefaultRootWindow(dpy), a, NULL);
169 XCloseDisplay(dpy);
171 return s;
175 /*}}}*/
178 int main(int argc, char *argv[])
180 int sock;
181 struct sockaddr_un serv;
182 const char *sockname;
183 int use_stdin=1;
184 char res;
185 int n;
187 if(argc>1){
188 if(argc!=3 || strcmp(argv[1], "-e")!=0)
189 die("Usage: ionflux [-e code]");
191 if(strlen(argv[2])>=MAX_DATA)
192 die("Too much data.");
194 use_stdin=0;
197 sockname=get_socket();
198 if(sockname==NULL)
199 die("No socket.");
201 if(strlen(sockname)>SOCK_MAX)
202 die("Socket name too long.");
204 sock=socket(AF_UNIX, SOCK_STREAM, 0);
205 if(sock<0)
206 die_e("Opening socket");
208 serv.sun_family=AF_UNIX;
209 strcpy(serv.sun_path, sockname);
211 if(connect(sock, (struct sockaddr*)&serv, sizeof(struct sockaddr_un))<0)
212 die_e("Connecting socket");
214 if(!use_stdin){
215 mywrite(sock, argv[2], strlen(argv[2])+1);
216 }else{
217 char c='\0';
218 while(1){
219 if(fgets(buf, MAX_DATA, stdin)==NULL)
220 break;
221 mywrite(sock, buf, strlen(buf));
223 mywrite(sock, &c, 1);
226 n=myread(sock, &res, 1);
228 if(n!=1 || (res!='E' && res!='S'))
229 die("Invalid response");
231 while(1){
232 n=myread(sock, buf, MAX_DATA);
234 if(n==0)
235 break;
237 if(res=='S')
238 mywrite(1, buf, n);
239 else /* res=='E' */
240 mywrite(2, buf, n);
242 if(n<MAX_DATA)
243 break;
246 return 0;