1 /*
2  *  Window Maker window manager
3  *
4  *  Copyright (c) 1997-2003 Alfredo K. Kojima
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "wconfig.h"
22 
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25 #include <X11/Xatom.h>
26 #include <string.h>
27 #include <stdlib.h>
28 
29 #include "WindowMaker.h"
30 #include "window.h"
31 #include "GNUstep.h"
32 #include "properties.h"
33 
34 
PropGetNormalHints(Window window,XSizeHints * size_hints,int * pre_iccm)35 int PropGetNormalHints(Window window, XSizeHints * size_hints, int *pre_iccm)
36 {
37 	long supplied_hints;
38 
39 	if (!XGetWMNormalHints(dpy, window, size_hints, &supplied_hints)) {
40 		return False;
41 	}
42 	if (supplied_hints == (USPosition | USSize | PPosition | PSize | PMinSize | PMaxSize
43 			       | PResizeInc | PAspect)) {
44 		*pre_iccm = 1;
45 	} else {
46 		*pre_iccm = 0;
47 	}
48 	return True;
49 }
50 
PropGetWMClass(Window window,char ** wm_class,char ** wm_instance)51 int PropGetWMClass(Window window, char **wm_class, char **wm_instance)
52 {
53 	XClassHint *class_hint;
54 
55 	class_hint = XAllocClassHint();
56 	if (XGetClassHint(dpy, window, class_hint) == 0) {
57 		*wm_class = strdup("default");
58 		*wm_instance = strdup("default");
59 		XFree(class_hint);
60 		return False;
61 	}
62 	*wm_instance = strdup(class_hint->res_name);
63 	*wm_class = strdup(class_hint->res_class);
64 
65 	XFree(class_hint->res_name);
66 	XFree(class_hint->res_class);
67 	XFree(class_hint);
68 
69 	return True;
70 }
71 
PropGetProtocols(Window window,WProtocols * prots)72 void PropGetProtocols(Window window, WProtocols * prots)
73 {
74 	Atom *protocols;
75 	int count, i;
76 
77 	memset(prots, 0, sizeof(WProtocols));
78 	if (!XGetWMProtocols(dpy, window, &protocols, &count)) {
79 		return;
80 	}
81 	for (i = 0; i < count; i++) {
82 		if (protocols[i] == w_global.atom.wm.take_focus)
83 			prots->TAKE_FOCUS = 1;
84 		else if (protocols[i] == w_global.atom.wm.delete_window)
85 			prots->DELETE_WINDOW = 1;
86 		else if (protocols[i] == w_global.atom.wm.save_yourself)
87 			prots->SAVE_YOURSELF = 1;
88 		else if (protocols[i] == w_global.atom.gnustep.wm_miniaturize_window)
89 			prots->MINIATURIZE_WINDOW = 1;
90 	}
91 	XFree(protocols);
92 }
93 
PropGetCheckProperty(Window window,Atom hint,Atom type,int format,int count,int * retCount)94 unsigned char *PropGetCheckProperty(Window window, Atom hint, Atom type, int format, int count, int *retCount)
95 {
96 	Atom type_ret;
97 	int fmt_ret;
98 	unsigned long nitems_ret;
99 	unsigned long bytes_after_ret;
100 	unsigned char *data;
101 	int tmp;
102 
103 	if (count <= 0)
104 		tmp = 0xffffff;
105 	else
106 		tmp = count;
107 
108 	if (XGetWindowProperty(dpy, window, hint, 0, tmp, False, type,
109 			       &type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
110 			       (unsigned char **)&data) != Success || !data)
111 		return NULL;
112 
113 	if ((type != AnyPropertyType && type != type_ret)
114 	    || (count > 0 && nitems_ret != count)
115 	    || (format != 0 && format != fmt_ret)) {
116 		XFree(data);
117 		return NULL;
118 	}
119 
120 	if (retCount)
121 		*retCount = nitems_ret;
122 
123 	return data;
124 }
125 
PropGetGNUstepWMAttr(Window window,GNUstepWMAttributes ** attr)126 int PropGetGNUstepWMAttr(Window window, GNUstepWMAttributes ** attr)
127 {
128 	unsigned long *data;
129 
130 	data = (unsigned long *)PropGetCheckProperty(window, w_global.atom.gnustep.wm_attr,
131 						     w_global.atom.gnustep.wm_attr, 32, 9, NULL);
132 
133 	if (!data)
134 		return False;
135 
136 	*attr = malloc(sizeof(GNUstepWMAttributes));
137 	if (!*attr) {
138 		XFree(data);
139 		return False;
140 	}
141 	(*attr)->flags = data[0];
142 	(*attr)->window_style = data[1];
143 	(*attr)->window_level = data[2];
144 	(*attr)->reserved = data[3];
145 	(*attr)->miniaturize_pixmap = data[4];
146 	(*attr)->close_pixmap = data[5];
147 	(*attr)->miniaturize_mask = data[6];
148 	(*attr)->close_mask = data[7];
149 	(*attr)->extra_flags = data[8];
150 
151 	XFree(data);
152 
153 	return True;
154 }
155 
PropSetWMakerProtocols(Window root)156 void PropSetWMakerProtocols(Window root)
157 {
158 	Atom protocols[3];
159 	int count = 0;
160 
161 	protocols[count++] = w_global.atom.wmaker.menu;
162 	protocols[count++] = w_global.atom.wmaker.wm_function;
163 	protocols[count++] = w_global.atom.wmaker.noticeboard;
164 
165 	XChangeProperty(dpy, root, w_global.atom.wmaker.wm_protocols, XA_ATOM,
166 			32, PropModeReplace, (unsigned char *)protocols, count);
167 }
168 
PropSetIconTileHint(WScreen * scr,RImage * image)169 void PropSetIconTileHint(WScreen * scr, RImage * image)
170 {
171 	static Atom imageAtom = 0;
172 	unsigned char *tmp;
173 	int x, y;
174 
175 	if (scr->info_window == None)
176 		return;
177 
178 	if (!imageAtom) {
179 		/*
180 		 * WIDTH, HEIGHT (16 bits, MSB First)
181 		 * array of R,G,B,A bytes
182 		 */
183 		imageAtom = XInternAtom(dpy, "_RGBA_IMAGE", False);
184 	}
185 
186 	tmp = malloc(image->width * image->height * 4 + 4);
187 	if (!tmp) {
188 		wwarning("could not allocate memory to set _WINDOWMAKER_ICON_TILE hint");
189 		return;
190 	}
191 
192 	tmp[0] = image->width >> 8;
193 	tmp[1] = image->width & 0xff;
194 	tmp[2] = image->height >> 8;
195 	tmp[3] = image->height & 0xff;
196 
197 	if (image->format == RRGBAFormat) {
198 		memcpy(&tmp[4], image->data, image->width * image->height * 4);
199 	} else {
200 		char *ptr = (char *)(tmp + 4);
201 		char *src = (char *)image->data;
202 
203 		for (y = 0; y < image->height; y++) {
204 			for (x = 0; x < image->width; x++) {
205 				*ptr++ = *src++;
206 				*ptr++ = *src++;
207 				*ptr++ = *src++;
208 				*ptr++ = 255;
209 			}
210 		}
211 	}
212 
213 	XChangeProperty(dpy, scr->info_window, w_global.atom.wmaker.icon_tile,
214 			imageAtom, 8, PropModeReplace, tmp, image->width * image->height * 4 + 4);
215 	wfree(tmp);
216 
217 }
218 
PropGetClientLeader(Window window)219 Window PropGetClientLeader(Window window)
220 {
221 	Window *win;
222 	Window leader;
223 
224 	win = (Window *) PropGetCheckProperty(window, w_global.atom.wm.client_leader, XA_WINDOW, 32, 1, NULL);
225 
226 	if (!win)
227 		return None;
228 
229 	leader = (Window) * win;
230 	XFree(win);
231 
232 	return leader;
233 }
234 
PropGetWindowState(Window window)235 int PropGetWindowState(Window window)
236 {
237 	long *data;
238 	long state;
239 
240 	data = (long *)PropGetCheckProperty(window, w_global.atom.wm.state,
241 				w_global.atom.wm.state, 32, 1, NULL);
242 
243 	if (!data)
244 		return -1;
245 
246 	state = *data;
247 	XFree(data);
248 
249 	return state;
250 }
251 
PropCleanUp(Window root)252 void PropCleanUp(Window root)
253 {
254 	XDeleteProperty(dpy, root, w_global.atom.wmaker.wm_protocols);
255 	XDeleteProperty(dpy, root, w_global.atom.wmaker.noticeboard);
256 	XDeleteProperty(dpy, root, XA_WM_ICON_SIZE);
257 }
258