Go Back

0 /*

1 * Inter-Client Communication Conventions Manual (ICCCM) hints

2 *

3 * NOTE: Since the ICCCM is so closely tied to window management, much

4 * of the standard is hardwired into "window.c".

5 */

6

7 /*

8 * Copyright 2006 Johan Veenhuizen

9 *

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

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

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

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

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

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

16 *

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

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

19 *

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

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

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

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

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

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

26 * DEALINGS IN THE SOFTWARE.

27 */

28

29 #include <assert.h>

30 #include <stdio.h>

31 #include <string.h>

32 #include <unistd.h>

33

34 #include <X11/Xatom.h>

35 #include <X11/Xlib.h>

36 #include <X11/Xutil.h>

37

38 #include "global.h"

39 #include "hints.h"

40 #include "lib.h"

41 #include "window.h"

42 #include "ewmh.h"

43

44 static Atom WM_CHANGE_STATE;

45 static Atom WM_DELETE_WINDOW;

46 static Atom WM_PROTOCOLS;

47 static Atom WM_STATE;

48 //static Atom WM_MOTIF;

49

50 static void icccm_init(void);

51 static void icccm_manage(struct window *);

52 static void icccm_map(struct window *);

53 static void icccm_unmap(struct window *);

54 static void icccm_withdraw(struct window *);

55 static void icccm_activate(struct window *);

56 static void icccm_deactivate(struct window *);

57 static void icccm_move(struct window *);

58 static int icccm_clientmessage(struct window *, XClientMessageEvent *);

59 static int icccm_propertynotify(struct window *, XPropertyEvent *);

60 static int icccm_delete(struct window *);

61 static int knowsproto(struct window *, Atom);

62 static void sendmesg(struct window *, Atom, long);

63 static void sendconf(struct window *);

64 static void setwmstate(struct window *, long);

65

66 struct hints icccm_hints = {

67 .name = "Inter-Client Communication Conventions Manual (ICCCM)",

68

69 .init = icccm_init,

70 .manage = icccm_manage,

71 .map = icccm_map,

72 .unmap = icccm_unmap,

73 .withdraw = icccm_withdraw,

74 .activate = icccm_activate,

75 .deactivate = icccm_deactivate,

76 .move = icccm_move,

77 .clientmessage = icccm_clientmessage,

78 .propertynotify = icccm_propertynotify,

79 .delete = icccm_delete,

80 };

81

82 static void icccm_init(void)

83 {

84 WM_CHANGE_STATE = XInternAtom(display, "WM_CHANGE_STATE", False);

85 WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", False);

86 WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", False);

87 WM_STATE = XInternAtom(display, "WM_STATE", False);

88 //WM_MOTIF = XInternAtom(display, "MOTIF_WM_HINTS", False);

89 }

90

91 static void icccm_manage(struct window *win)

92 {

93 sendconf(win);

94 }

95

96 static void icccm_map(struct window *win)

97 {

98 setwmstate(win, NormalState);

99 }

100

101 static void icccm_unmap(struct window *win)

102 {

103 setwmstate(win, IconicState);

104 }

105

106 static void icccm_withdraw(struct window *win)

107 {

108 setwmstate(win, WithdrawnState);

109 }

110

111 static void icccm_activate(struct window *win)

112 {

113 if (win == NULL)

114 XInstallColormap(display, DefaultColormap(display, screen));

115 else

116 XInstallColormap(display, win->colormap);

117 }

118

119 static void icccm_deactivate(struct window *win)

120 {

121 XUninstallColormap(display, win->colormap);

122 }

123

124 static void icccm_move(struct window *win)

125 {

126 sendconf(win);

127 }

128

129 static int icccm_clientmessage(struct window *win, XClientMessageEvent *ep)

130 {

131 if (ep->message_type == WM_CHANGE_STATE && ep->format == 32) {

132 switch (ep->data.l[0]) {

133 case IconicState:

134 unmap_window(win);

135 return 1;

136 case NormalState:

137 map_window(win);

138 return 1;

139 }

140 }

141 if (ep->message_type == atom[NET_WM_STATE]) {

142 if (ep->data.l[1] == atom[NET_WM_STATE_FULLSCREEN] || ep->data.l[2] == atom[NET_WM_STATE_FULLSCREEN]) {

143 window_set_fullscreen(win, (ep->data.l[0] == 1 || (ep->data.l[0] == 2 && !win->fullscreen)));

144 return 1;

145 }

146 }

147 return 0;

148 }

149

150 static int icccm_propertynotify(struct window *win, XPropertyEvent *ep)

151 {

152 switch (ep->atom) {

153 case XA_WM_NAME:

154 if (ep->state != PropertyDelete)

155 fetch_window_name(win);

156 return 1;

157 case XA_WM_ICON_NAME:

158 if (ep->state != PropertyDelete)

159 fetch_icon_name(win);

160 return 1;

161 case XA_WM_NORMAL_HINTS:

162 fetch_wm_normal_hints(win);

163 return 1;

164 case XA_WM_HINTS:

165 fetch_wm_hints(win);

166 return 1;

167 case XA_WM_TRANSIENT_FOR:

168 fetch_wm_transient_for_hint(win);

169 return 1;

170 }

171 if (ep->atom == atom[NET_WM_WINDOW_TYPE]) {

172 update_window_type(win);

173 return 1;

174 }

175 return 0;

176 }

177

178 static int icccm_delete(struct window *win)

179 {

180 if (knowsproto(win, WM_DELETE_WINDOW)) {

181 sendmesg(win, WM_PROTOCOLS, WM_DELETE_WINDOW);

182 return 1;

183 } else

184 return 0;

185 }

186

187 static int knowsproto(struct window *win, Atom proto)

188 {

189 Atom *protocols;

190 int i, n;

191 int found;

192

193 found = 0;

194 clerr();

195 if (XGetWMProtocols(display, win->client, &protocols, &n)) {

196 for (i = 0; !found && i < n; i++) {

197 if (protocols[i] == proto)

198 found = 1;

199 }

200 if (protocols != NULL)

201 XFree(protocols);

202 }

203 sterr();

204 return found;

205 }

206

207 static void sendmesg(struct window *win, Atom type, long value)

208 {

209 XEvent ev;

210

211 memset(&ev, 0, sizeof ev);

212 ev.xclient.type = ClientMessage;

213 ev.xclient.window = win->client;

214 ev.xclient.message_type = type;

215 ev.xclient.format = 32;

216 ev.xclient.data.l[0] = value;

217 ev.xclient.data.l[1] = CurrentTime;

218

219 clerr();

220 XSendEvent(display, win->client, False, 0L, &ev);

221 sterr();

222 }

223

224 static void sendconf(struct window *win)

225 {

226 XConfigureEvent conf;

227

228 conf.type = ConfigureNotify;

229 conf.event = win->client;

230 conf.window = win->client;

231 conf.x = WIDGET_X(win) + border_width - win->cborder;

232 conf.y = WIDGET_Y(win) + border_width + button_size - win->cborder;

233 conf.width = WIDGET_WIDTH(win) - win->decoration*(2 * border_width);

234 conf.height = WIDGET_HEIGHT(win) - win->decoration*(2 * border_width + button_size);

235 conf.border_width = win->cborder;

236 conf.above = None;

237 conf.override_redirect = False;

238

239 clerr();

240 XSendEvent(display, win->client, False, StructureNotifyMask,

241 (XEvent *)&conf);

242 sterr();

243 }

244

245 static void setwmstate(struct window *win, long state)

246 {

247 long data[2];

248

249 data[0] = state;

250 data[1] = (long)None;

251

252 clerr();

253 XChangeProperty(display, win->client, WM_STATE, WM_STATE, 32,

254 PropModeReplace, (unsigned char *)data, 2);

255 sterr();

256 }

257