1 #include "drawinfo.h"
2 #include "screen.h"
3 #include "icc.h"
4 #include "icon.h"
5 #include "style.h"
6 #include "prefs.h"
7 
8 #include <string.h>
9 
10 #ifdef AMIGAOS
11 #include <pragmas/xlib_pragmas.h>
12 extern struct Library *XLibBase;
13 #endif
14 
15 extern void redraw(Client *, Window);
16 
17 Atom wm_state, wm_change_state, wm_protocols, wm_delete, wm_take_focus;
18 Atom wm_colormaps, wm_name, wm_normal_hints, wm_hints, wm_icon_name, wm_class;
19 Atom amiwm_screen, swm_vroot, amiwm_wflags, amiwm_appiconmsg, amiwm_appwindowmsg;
20 
21 extern Display *dpy;
22 
init_atoms()23 void init_atoms()
24 {
25   wm_state = XInternAtom(dpy, "WM_STATE", False);
26   wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
27   wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
28   wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
29   wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
30   wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
31   wm_name = XInternAtom(dpy, "WM_NAME", False);
32   wm_normal_hints = XInternAtom(dpy, "WM_NORMAL_HINTS", False);
33   wm_hints = XInternAtom(dpy, "WM_HINTS", False);
34   wm_icon_name = XInternAtom(dpy, "WM_ICON_NAME", False);
35   wm_class = XInternAtom(dpy, "WM_CLASS", False);
36   amiwm_screen = XInternAtom(dpy, "AMIWM_SCREEN", False);
37   swm_vroot = XInternAtom(dpy, "__SWM_VROOT", False);
38   amiwm_wflags = XInternAtom(dpy, "AMIWM_WFLAGS", False);
39   amiwm_appiconmsg = XInternAtom(dpy, "AMIWM_APPICONMSG", False);
40   amiwm_appwindowmsg = XInternAtom(dpy, "AMIWM_APPWINDOWMSG", False);
41 }
42 
setstringprop(Window w,Atom a,char * str)43 void setstringprop(Window w, Atom a, char *str)
44 {
45     XTextProperty txtp;
46 
47     txtp.value=(unsigned char *)str;
48     txtp.encoding=XA_STRING;
49     txtp.format=8;
50     txtp.nitems=strlen(str);
51     XSetTextProperty(dpy, w, &txtp, a);
52 }
53 
mkcmessage(Window w,Atom a,long x)54 XEvent *mkcmessage(Window w, Atom a, long x)
55 {
56   static XEvent ev;
57 
58   memset(&ev, 0, sizeof(ev));
59   ev.xclient.type = ClientMessage;
60   ev.xclient.window = w;
61   ev.xclient.message_type = a;
62   ev.xclient.format = 32;
63   ev.xclient.data.l[0] = x;
64   ev.xclient.data.l[1] = CurrentTime;
65   return &ev;
66 }
67 
sendcmessage(Window w,Atom a,long x)68 void sendcmessage(Window w, Atom a, long x)
69 {
70   if(!(XSendEvent(dpy, w, False, 0L, mkcmessage(w, a, x))))
71     XBell(dpy, 100);
72 }
73 
_getprop(Window w,Atom a,Atom type,long len,char ** p)74 long _getprop(Window w, Atom a, Atom type, long len, char **p)
75 {
76   Atom real_type;
77   int format;
78   unsigned long n, extra;
79   int status;
80 
81   status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format,
82 			      &n, &extra, (unsigned char **)p);
83   if (status != Success || *p == 0)
84     return -1;
85   if (n == 0)
86     XFree((void*) *p);
87   return n;
88 }
89 
getwflags(Client * c)90 void getwflags(Client *c)
91 {
92   BITS32 *p;
93   long n;
94 
95   c->wflags = 0;
96   if ((n = _getprop(c->window, amiwm_wflags, amiwm_wflags, 1L, (char**)&p)) <= 0)
97     return;
98 
99   c->wflags = p[0];
100 
101   XFree((char *) p);
102 }
103 
getproto(Client * c)104 void getproto(Client *c)
105 {
106   Atom *p;
107   int i;
108   long n;
109   Window w;
110 
111   w = c->window;
112   c->proto &= ~(Pdelete|Ptakefocus);
113   if ((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (char**)&p)) <= 0)
114     return;
115 
116   for (i = 0; i < n; i++)
117     if (p[i] == wm_delete)
118       c->proto |= Pdelete;
119     else if (p[i] == wm_take_focus)
120       c->proto |= Ptakefocus;
121 
122   XFree((char *) p);
123 }
124 
stylematch_low(char * p,int l,char * m)125 static int stylematch_low(char *p, int l, char *m)
126 {
127   char *lf;
128   int ml;
129   --m;
130   do {
131     lf = strchr(++m, '\n');
132     ml = (lf? lf-m:strlen(m));
133     if(ml == l && !strncmp(m, p, ml))
134       return 1;
135   } while((m=lf));
136   return 0;
137 }
138 
stylematch_tprop(XTextProperty * p,char * m)139 static int stylematch_tprop(XTextProperty *p, char *m)
140 {
141   return stylematch_low((char *)p->value, p->nitems, m);
142 }
143 
144 #ifdef USE_FONTSETS
stylematch_str(char * p,char * m)145 static int stylematch_str(char *p, char *m)
146 {
147   return stylematch_low(p, strlen(p), m);
148 }
149 #endif
150 
checkstyle(Client * c)151 void checkstyle(Client *c)
152 {
153   XTextProperty icon_name, class_name;
154   Style *style;
155 
156   if(prefs.firststyle==NULL)
157     return;
158 
159   if(!XGetTextProperty(dpy, c->window, &class_name, wm_class))
160     class_name.value=NULL;
161   else
162     /* This value seems to be 2x it's correct value always... */
163     class_name.nitems=strlen((char *)class_name.value);
164   if(!XGetWMIconName(dpy, c->window, &icon_name))
165     icon_name.value=NULL;
166 
167   for(style=prefs.firststyle; style!=NULL; style=style->next)
168     if((class_name.value!=NULL && style->style_class!=NULL &&
169 	stylematch_tprop(&class_name, style->style_class)) ||
170 #ifdef USE_FONTSETS
171        (c->title!=NULL && style->style_title!=NULL &&
172 	stylematch_str(c->title, style->style_title)) ||
173 #else
174        (c->title.value!=NULL && style->style_title!=NULL &&
175 	stylematch_tprop(&c->title, style->style_title)) ||
176 #endif
177        (icon_name.value!=NULL && style->style_icon_title!=NULL &&
178 	stylematch_tprop(&icon_name, style->style_icon_title))) {
179       c->style = style;
180       break;
181     }
182 
183   if(icon_name.value)
184     XFree(icon_name.value);
185   if(class_name.value)
186     XFree(class_name.value);
187 }
188 
propertychange(Client * c,Atom a)189 void propertychange(Client *c, Atom a)
190 {
191   extern void checksizehints(Client *);
192   extern void newicontitle(Client *);
193 
194   if(a==wm_name) {
195 #ifdef USE_FONTSETS
196     XTextProperty prop;
197     if(c->title) {
198       free(c->title);
199       c->title = NULL;
200     }
201     if(XGetWMName(dpy, c->window, &prop) && prop.value) {
202       char **list;
203       int n;
204       if(XmbTextPropertyToTextList(dpy, &prop, &list, &n) >= Success) {
205 	if(n > 0)
206 	  c->title = strdup(list[0]);
207 	XFreeStringList(list);
208       }
209       XFree(prop.value);
210     }
211 #else
212     if(c->title.value)
213       XFree(c->title.value);
214     XGetWMName(dpy, c->window, &c->title);
215 #endif
216     if(c->style==NULL)
217       checkstyle(c);
218     if(c->drag) {
219       XClearWindow(dpy, c->drag);
220       redraw(c, c->drag);
221     }
222   } else if(a==wm_normal_hints) {
223     checksizehints(c);
224   } else if(a==wm_hints) {
225     XWMHints *xwmh;
226     if((xwmh=XGetWMHints(dpy, c->window))) {
227       if((xwmh->flags&(IconWindowHint|IconPixmapHint))&&c->icon) {
228 	destroyiconicon(c->icon);
229 	createiconicon(c->icon, xwmh);
230       }
231       if((xwmh->flags&IconPositionHint)&&c->icon&&c->icon->window) {
232 	XMoveWindow(dpy, c->icon->window, c->icon->x=xwmh->icon_x,
233 		    c->icon->y=xwmh->icon_y);
234 	adjusticon(c->icon);
235       }
236       XFree(xwmh);
237     }
238   } else if(a==wm_protocols) {
239     getproto(c);
240   } else if(a==wm_icon_name) {
241     if(c->style==NULL)
242       checkstyle(c);
243     if(c->icon) newicontitle(c);
244   } else if(a==wm_state) {
245     if(c->parent==c->scr->root) {
246       getstate(c);
247       if(c->state==NormalState)
248 	c->state=WithdrawnState;
249     }
250   } else if(a==wm_class && c->style==NULL)
251     checkstyle(c);
252 }
253 
handle_client_message(Client * c,XClientMessageEvent * xcme)254 void handle_client_message(Client *c, XClientMessageEvent *xcme)
255 {
256   if(xcme->message_type == wm_change_state) {
257     int state=xcme->data.l[0];
258     if(state==IconicState)
259       if(c->state!=IconicState) {
260 	if(!(c->icon))
261 	  createicon(c);
262 	XUnmapWindow(dpy, c->parent);
263 	/*	XUnmapWindow(dpy, c->window); */
264 	adjusticon(c->icon);
265 	XMapWindow(dpy, c->icon->window);
266 	if(c->icon->labelwidth)
267 	  XMapWindow(dpy, c->icon->labelwin);
268 	c->icon->mapped=1;
269 	setclientstate(c, IconicState);
270       } else ;
271     else
272       if(c->state==IconicState && c->icon) {
273 	Icon *i=c->icon;
274 	if(i->labelwin)
275 	  XUnmapWindow(dpy, i->labelwin);
276 	if(i->window)
277 	  XUnmapWindow(dpy, i->window);
278 	i->mapped=0;
279 	deselecticon(i);
280 	XMapWindow(dpy, c->window);
281 	if(c->parent!=c->scr->root)
282 	  XMapRaised(dpy, c->parent);
283 	setclientstate(c, NormalState);
284       }
285   }
286 }
287