💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Menkar › files › 1225456d118fdf6f060e259171e… captured on 2023-09-08 at 16:35:46. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-03-20)

🚧 View Differences

-=-=-=-=-=-=-

Go Back

0 /*

1 * Support for Extended Window Manager Hints

2 * http://standards.freedesktop.org/wm-spec/wm-spec-latest.html

3 */

4

5 /*

6 * Copyright 2006-2007 Johan Veenhuizen

7 *

8 * Permission is hereby granted, free of charge, to any person obtaining a

9 * copy of this software and associated documentation files (the "Software"),

10 * to deal in the Software without restriction, including without limitation

11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,

12 * and/or sell copies of the Software, and to permit persons to whom the

13 * Software is furnished to do so, subject to the following conditions:

14 *

15 * The above copyright notice and this permission notice shall be included

16 * in all copies or substantial portions of the Software.

17 *

18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL

21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING

23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

24 * DEALINGS IN THE SOFTWARE.

25 */

26

27 #include <X11/Xatom.h>

28 #include <X11/Xlib.h>

29 #include <X11/Xutil.h>

30

31 #include "global.h"

32 #include "hints.h"

33 #include "lib.h"

34 #include "window.h"

35 #include "ewmh.h"

36

37 struct winlist {

38 long *win;

39 int len;

40 int lim;

41 };

42

43 /* EWMH atoms, indexed by the above enum */

44 Atom atom[NATOM];

45

46 /* The EWMH UTF-8 string type */

47 static Atom UTF8_STRING;

48

49 /* List of managed clients, oldest first */

50 static struct winlist clientlist = { NULL, 0, 0 };

51

52 /* Geometry of the workarea (x, y, width, height) */

53 static long workarea[4];

54

55 /* The window used for announcing EWMH support */

56 static Window supportwin = None;

57

58 static void ewmh_init(void);

59 static void ewmh_fini(void);

60 static void ewmh_manage(struct window *);

61 static void ewmh_unmanage(struct window *);

62 static void ewmh_activate(struct window *);

63 static void ewmh_restack(void);

64 static int ewmh_clientmessage(struct window *, XClientMessageEvent *);

65 static void addclient(Window);

66 static void delclient(Window);

67

68 struct hints ewmh_hints = {

69 .init = ewmh_init,

70 .fini = ewmh_fini,

71 .manage = ewmh_manage,

72 .unmanage = ewmh_unmanage,

73 .activate = ewmh_activate,

74 .restack = ewmh_restack,

75 .clientmessage = ewmh_clientmessage,

76 };

77

78 static void ewmh_init(void)

79 {

80 XSetWindowAttributes attr;

81 long ndesk;

82 long curdesk;

83 long geom[2];

84 long viewport[2];

85 long active;

86 long monitor;

87

88 attr.override_redirect = True;

89 supportwin = XCreateWindow(display, root, 0, 0, 1, 1, 0,

90 CopyFromParent, InputOnly, CopyFromParent,

91 CWOverrideRedirect, &attr);

92

93 ndesk = 1;

94 curdesk = 0;

95 geom[0] = DisplayWidth(display, screen);

96 geom[1] = DisplayHeight(display, screen);

97 viewport[0] = 0;

98 viewport[1] = 0;

99 active = None;

100 monitor = 0;

101 workarea[0] = 0; /* x */

102 workarea[1] = 0; /* y */

103 workarea[2] = DisplayWidth(display, screen);

104 workarea[3] = DisplayHeight(display, screen);

105

106 UTF8_STRING = XInternAtom(display, "UTF8_STRING", False);

107

108 atom[NET_SUPPORTED] = XInternAtom(display,

109 "_NET_SUPPORTED", False);

110 atom[NET_CLIENT_LIST] = XInternAtom(display,

111 "_NET_CLIENT_LIST", False);

112 atom[NET_CLIENT_LIST_STACKING] = XInternAtom(display,

113 "_NET_CLIENT_LIST_STACKING", False);

114 atom[NET_NUMBER_OF_DESKTOPS] = XInternAtom(display,

115 "_NET_NUMBER_OF_DESKTOPS", False);

116 atom[NET_DESKTOP_GEOMETRY] = XInternAtom(display,

117 "_NET_DESKTOP_GEOMETRY", False);

118 atom[NET_DESKTOP_VIEWPORT] = XInternAtom(display,

119 "_NET_DESKTOP_VIEWPORT", False);

120 atom[NET_CURRENT_DESKTOP] = XInternAtom(display,

121 "_NET_CURRENT_DESKTOP", False);

122 atom[NET_ACTIVE_WINDOW] = XInternAtom(display,

123 "_NET_ACTIVE_WINDOW", False);

124 atom[NET_WORKAREA] = XInternAtom(display,

125 "_NET_WORKAREA", False);

126 atom[NET_SUPPORTING_WM_CHECK] = XInternAtom(display,

127 "_NET_SUPPORTING_WM_CHECK", False);

128 atom[NET_WM_NAME] = XInternAtom(display,

129 "_NET_WM_NAME", False);

130 atom[NET_CLOSE_WINDOW] = XInternAtom(display,

131 "_NET_CLOSE_WINDOW", False);

132 //atom[NET_WM_FULLSCREEN_MONITORS] = XInternAtom(display,

133 // "_NET_WM_FULLSCREEN_MONITORS", False);

134 atom[NET_WM_WINDOW_TYPE] = XInternAtom(display,

135 "_NET_WM_WINDOW_TYPE", False);

136 atom[NET_WM_WINDOW_TYPE_DESKTOP] = XInternAtom(display,

137 "_NET_WM_WINDOW_TYPE_DESKTOP", False);

138 atom[NET_WM_WINDOW_TYPE_DIALOG] = XInternAtom(display,

139 "_NET_WM_WINDOW_TYPE_DIALOG", False);

140 atom[NET_WM_WINDOW_TYPE_DOCK] = XInternAtom(display,

141 "_NET_WM_WINDOW_TYPE_DOCK", False);

142 atom[NET_WM_WINDOW_TYPE_MENU] = XInternAtom(display,

143 "_NET_WM_WINDOW_TYPE_MENU", False);

144 atom[NET_WM_WINDOW_TYPE_NORMAL] = XInternAtom(display,

145 "_NET_WM_WINDOW_TYPE_NORMAL", False);

146 atom[NET_WM_WINDOW_TYPE_SPLASH] = XInternAtom(display,

147 "_NET_WM_WINDOW_TYPE_SPLASH", False);

148 atom[NET_WM_WINDOW_TYPE_TOOLBAR] = XInternAtom(display,

149 "_NET_WM_WINDOW_TYPE_TOOLBAR", False);

150 atom[NET_WM_WINDOW_TYPE_UTILITY] = XInternAtom(display,

151 "_NET_WM_WINDOW_TYPE_UTILITY", False);

152 atom[NET_WM_STATE] = XInternAtom(display,

153 "_NET_WM_STATE", False);

154 atom[NET_WM_STATE_FULLSCREEN] = XInternAtom(display,

155 "_NET_WM_STATE_FULLSCREEN", False);

156

157

158 XChangeProperty(display, root, atom[NET_CLIENT_LIST],

159 XA_WINDOW, 32, PropModeReplace, NULL, 0);

160 XChangeProperty(display, root, atom[NET_CLIENT_LIST_STACKING],

161 XA_WINDOW, 32, PropModeReplace, NULL, 0);

162 XChangeProperty(display, root, atom[NET_NUMBER_OF_DESKTOPS],

163 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&ndesk, 1);

164 XChangeProperty(display, root, atom[NET_DESKTOP_GEOMETRY],

165 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&geom, 2);

166 XChangeProperty(display, root, atom[NET_DESKTOP_VIEWPORT],

167 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&viewport, 2);

168 XChangeProperty(display, root, atom[NET_CURRENT_DESKTOP],

169 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&curdesk, 1);

170 XChangeProperty(display, root, atom[NET_ACTIVE_WINDOW],

171 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&active, 1);

172 //XChangeProperty(display, root, atom[NET_WM_FULLSCREEN_MONITORS],

173 // XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&monitor, 1);

174 XChangeProperty(display, root, atom[NET_WORKAREA],

175 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&workarea, 4);

176 XChangeProperty(display, root, atom[NET_SUPPORTING_WM_CHECK],

177 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&supportwin, 1);

178 XChangeProperty(display, supportwin, atom[NET_SUPPORTING_WM_CHECK],

179 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&supportwin, 1);

180 XChangeProperty(display, supportwin, atom[NET_WM_NAME],

181 UTF8_STRING, 8, PropModeReplace,

182 (unsigned char *)"Karmen", 7);

183

184 /* set this last, when everything is set up */

185 XChangeProperty(display, root, atom[NET_SUPPORTED], XA_ATOM, 32,

186 PropModeReplace, (unsigned char *)atom, NELEM(atom));

187 }

188

189 static void ewmh_fini(void)

190 {

191 /* delete this first, before we tear things down */

192 XDeleteProperty(display, root, atom[NET_SUPPORTED]);

193

194 XDeleteProperty(display, root, atom[NET_CLIENT_LIST]);

195 XDeleteProperty(display, root, atom[NET_CLIENT_LIST_STACKING]);

196 XDeleteProperty(display, root, atom[NET_NUMBER_OF_DESKTOPS]);

197 XDeleteProperty(display, root, atom[NET_DESKTOP_GEOMETRY]);

198 XDeleteProperty(display, root, atom[NET_DESKTOP_VIEWPORT]);

199 XDeleteProperty(display, root, atom[NET_CURRENT_DESKTOP]);

200 XDeleteProperty(display, root, atom[NET_ACTIVE_WINDOW]);

201 XDeleteProperty(display, root, atom[NET_WORKAREA]);

202 XDeleteProperty(display, root, atom[NET_SUPPORTING_WM_CHECK]);

203 XDeleteProperty(display, supportwin, atom[NET_SUPPORTING_WM_CHECK]);

204 XDeleteProperty(display, supportwin, atom[NET_WM_NAME]);

205

206 XDestroyWindow(display, supportwin);

207 }

208

209 static void ewmh_manage(struct window *win)

210 {

211 addclient(win->client);

212 XChangeProperty(display, root, atom[NET_CLIENT_LIST],

213 XA_WINDOW, 32, PropModeReplace,

214 (unsigned char *)clientlist.win, clientlist.len);

215 }

216

217 static void ewmh_unmanage(struct window *win)

218 {

219 delclient(win->client);

220 XChangeProperty(display, root, atom[NET_CLIENT_LIST],

221 XA_WINDOW, 32, PropModeReplace,

222 (unsigned char *)clientlist.win, clientlist.len);

223 }

224

225 static void ewmh_activate(struct window *win)

226 {

227 Window w;

228

229 w = win == NULL ? None : win->client;

230 XChangeProperty(display, root, atom[NET_ACTIVE_WINDOW],

231 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1);

232 }

233

234 static void ewmh_restack(void)

235 {

236 Window *stack, w;

237 int i, j, n;

238

239 get_client_stack(&stack, &n);

240

241 /* reverse the stack */

242 for (i = 0, j = n - 1; i < j; i++, j--) {

243 w = stack[i];

244 stack[i] = stack[j];

245 stack[j] = w;

246 }

247

248 XChangeProperty(display, root, atom[NET_CLIENT_LIST_STACKING],

249 XA_WINDOW, 32, PropModeReplace,

250 (unsigned char *)stack, n);

251

252 FREE(stack);

253 }

254

255 static int ewmh_clientmessage(struct window *win, XClientMessageEvent *ep)

256 {

257 int type = ep->message_type;

258 int format = ep->format;

259

260 if (type == atom[NET_ACTIVE_WINDOW] && format == 32) {

261 set_active_window(win);

262 } else if (type == atom[NET_CLOSE_WINDOW] && format == 32) {

263 delete_window(win);

264 } else

265 return 0;

266

267 return 1;

268 }

269

270 static void addclient(Window w)

271 {

272 if (clientlist.len == clientlist.lim) {

273 clientlist.lim += 32;

274 clientlist.win = REALLOC(clientlist.win,

275 clientlist.lim * sizeof (long));

276 }

277 clientlist.win[clientlist.len++] = (long)w;

278 }

279

280 static void delclient(Window w)

281 {

282 int i;

283

284 if (clientlist.len == 0)

285 return;

286

287 clientlist.len--;

288 for (i = 0; i < clientlist.len && clientlist.win[i] != (long)w; i++)

289 ;

290 if (i < clientlist.len) {

291 for (; i < clientlist.len; i++)

292 clientlist.win[i] = clientlist.win[i + 1];

293 }

294

295 if (clientlist.len == 0) {

296 FREE(clientlist.win);

297 clientlist.win = NULL;

298 clientlist.lim = 0;

299 }

300 }

301