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