💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Menkar › files › e29c0e5f4489f2691b16fd6fc0b… captured on 2023-03-20 at 18:09:52. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

➡️ Next capture (2023-09-08)

🚧 View Differences

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

0 /*

1 * resizer.c - resizable window borders

2 */

3

4 /*

5 * Copyright 2006-2008 Johan Veenhuizen

6 *

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

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

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

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

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

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

13 *

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

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

16 *

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

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

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

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

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

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

23 * DEALINGS IN THE SOFTWARE.

24 */

25

26 #include <assert.h>

27 #include <stdio.h>

28 #include <stdlib.h>

29 #include <string.h>

30

31 #include <X11/cursorfont.h>

32 #include <X11/Xlib.h>

33 #include <X11/Xutil.h>

34

35 #include "global.h"

36 #include "lib.h"

37 #include "menu.h"

38 #include "resizer.h"

39 #include "window.h"

40

41 #define PADDING MAX(1, (font->ascent + font->descent) / 4)

42

43 static Cursor c1, c2, c3, c4, c5, c6, c7, c8;

44

45 struct sizewin { struct widget widget;

46 struct window *window;

47 GC gc;

48 };

49

50 static void update_sizewin(struct sizewin *sizewin, int xdim, int ydim)

51 {

52 static char buf[256];

53 struct widget *widget;

54 struct window *win;

55 int width, height;

56

57 widget = (struct widget *)sizewin;

58 win = sizewin->window;

59

60 sprintf(buf, "%dx%d", xdim, ydim);

61 width = 2 * (PADDING + font->descent) + stringwidth(buf);

62 height = 2 * PADDING + font->ascent + font->descent;

63 moveresize_widget(widget,

64 WIDGET_X(win) + WIDGET_WIDTH(win) / 2 - (width + 2) / 2,

65 WIDGET_Y(win) + (border_width + button_size)*win->decoration

66 + (WIDGET_HEIGHT(win) - 2*border_width - button_size) / 2 * win->decoration

67 - (height + 2) / 2,

68 width, height);

69 if (!WIDGET_MAPPED(sizewin))

70 map_widget(&sizewin->widget);

71 XClearWindow(display, WIDGET_XWINDOW(sizewin));

72 XSetForeground(display, sizewin->gc, color_title_active_fg.normal);

73 XDrawString(display, WIDGET_XWINDOW(sizewin), sizewin->gc,

74 PADDING + font->descent, PADDING + font->ascent,

75 buf, strlen(buf));

76 drawraised(WIDGET_XWINDOW(sizewin), sizewin->gc,

77 &color_title_active_bg,

78 0, 0, WIDGET_WIDTH(sizewin), WIDGET_HEIGHT(sizewin));

79 }

80

81 static struct sizewin *create_sizewin(struct window *win, int xdim, int ydim)

82 {

83 XSetWindowAttributes attr;

84 XGCValues gcval;

85 struct sizewin *sizewin;

86

87 sizewin = MALLOC(sizeof *sizewin);

88 create_widget(&sizewin->widget, WIDGET_SIZEWIN,

89 root, InputOutput, 0, 0, 1, 1);

90 XSetWindowBackground(display, WIDGET_XWINDOW(sizewin),

91 color_title_active_bg.normal);

92 attr.save_under = True;

93 XChangeWindowAttributes(display, WIDGET_XWINDOW(sizewin),

94 CWSaveUnder, &attr);

95 gcval.font = font->fid;

96 sizewin->gc = XCreateGC(display, WIDGET_XWINDOW(sizewin),

97 GCFont, &gcval);

98 sizewin->window = win;

99 update_sizewin(sizewin, xdim, ydim);

100 return sizewin;

101 }

102

103 static void destroy_sizewin(struct sizewin *sizewin)

104 {

105 XFreeGC(display, sizewin->gc);

106 destroy_widget(&sizewin->widget);

107 FREE(sizewin);

108 }

109

110 static void press(struct resizer *resizer, XButtonEvent *ep)

111 {

112 struct window *win = resizer->window;

113 int xdim, ydim;

114

115 if (ep->button == Button1) {

116 set_active_window(win);

117 window_calcsize(win, WIDGET_WIDTH(win), WIDGET_HEIGHT(win),

118 NULL, NULL, &xdim, &ydim);

119 if (resizer->sizewin != NULL)

120 destroy_sizewin(resizer->sizewin);

121 resizer->sizewin = create_sizewin(win, xdim, ydim);

122 } else if (ep->button == Button3) {

123 if (resizer->sizewin != NULL) {

124 destroy_sizewin(resizer->sizewin);

125 resizer->sizewin = NULL;

126 }

127 show_menu(winmenu, ep->x_root, ep->y_root, ep->button);

128 }

129 }

130

131 static void release(struct resizer *resizer, XButtonEvent *ep)

132 {

133 if (ep->button == Button1 && resizer->sizewin != NULL) {

134 destroy_sizewin(resizer->sizewin);

135 resizer->sizewin = NULL;

136 }

137 }

138

139 static void motion(struct resizer *resizer, XMotionEvent *ep)

140 {

141 struct window *win = resizer->window;

142 int x, y;

143 int width, height;

144 int rwidth, rheight;

145 int xdim, ydim;

146

147 if (resizer->sizewin == NULL)

148 return;

149

150 switch (resizer->dir) {

151 case NORTHWEST:

152 width = WIDGET_X(win) + WIDGET_WIDTH(win) - ep->x_root;

153 height = WIDGET_Y(win) + WIDGET_HEIGHT(win) - ep->y_root;

154 break;

155 case NORTH:

156 if(win->maximized) {

157 return;

158 }

159 width = WIDGET_WIDTH(win);

160 height = WIDGET_Y(win) + WIDGET_HEIGHT(win) - ep->y_root;

161 break;

162 case NORTHEAST:

163 width = 1 + ep->x_root - WIDGET_X(win);

164 height = WIDGET_Y(win) + WIDGET_HEIGHT(win) - ep->y_root;

165 break;

166 case WEST:

167 width = WIDGET_X(win) + WIDGET_WIDTH(win) - ep->x_root;

168 height = WIDGET_HEIGHT(win);

169 break;

170 case EAST:

171 width = 1 + ep->x_root - WIDGET_X(win);

172 height = WIDGET_HEIGHT(win);

173 break;

174 case SOUTHWEST:

175 width = WIDGET_X(win) + WIDGET_WIDTH(win) - ep->x_root;

176 height = 1 + ep->y_root - WIDGET_Y(win);

177 break;

178 case SOUTH:

179 width = WIDGET_WIDTH(win);

180 height = 1 + ep->y_root - WIDGET_Y(win);

181 break;

182 case SOUTHEAST:

183 width = 1 + ep->x_root - WIDGET_X(win);

184 height = 1 + ep->y_root - WIDGET_Y(win);

185 break;

186 default:

187 abort();

188 break;

189 }

190

191 window_calcsize(win, width, height, &rwidth, &rheight, &xdim, &ydim);

192

193 switch (resizer->dir) {

194 case NORTHWEST:

195 x = WIDGET_X(win) + WIDGET_WIDTH(win) - rwidth;

196 y = WIDGET_Y(win) + WIDGET_HEIGHT(win) - rheight;

197 break;

198 case NORTHEAST:

199 x = WIDGET_X(win);

200 y = WIDGET_Y(win) + WIDGET_HEIGHT(win) - rheight;

201 break;

202 case NORTH:

203 x = WIDGET_X(win);

204 y = WIDGET_Y(win) + WIDGET_HEIGHT(win) - rheight;

205 break;

206 case WEST:

207 x = WIDGET_X(win) + WIDGET_WIDTH(win) - rwidth;

208 y = WIDGET_Y(win);

209 break;

210 case SOUTHWEST:

211 x = WIDGET_X(win) + WIDGET_WIDTH(win) - rwidth;

212 y = WIDGET_Y(win);

213 break;

214 default:

215 x = WIDGET_X(win);

216 y = WIDGET_Y(win);

217 break;

218 }

219

220 if (rwidth != WIDGET_WIDTH(win) || rheight != WIDGET_HEIGHT(win)) {

221 resizer->window->maximized = 0;

222 moveresize_window(resizer->window, x, y, rwidth, rheight);

223 update_sizewin(resizer->sizewin, xdim, ydim);

224 }

225 }

226

227 static void resizerevent(struct widget *widget, XEvent *ep)

228 {

229 switch (ep->type) {

230 case ButtonPress:

231 press((struct resizer *)widget, &ep->xbutton);

232 break;

233 case ButtonRelease:

234 release((struct resizer *)widget, &ep->xbutton);

235 break;

236 case MotionNotify:

237 motion((struct resizer *)widget, &ep->xmotion);

238 break;

239 }

240 }

241

242 struct resizer *create_resizer(struct window *win, int dir)

243 {

244 if (win->maximized&&dir==NORTH) return NULL;

245

246 struct resizer *resizer;

247 static int initialized = 0;

248

249 if (!initialized) {

250 initialized = 1;

251 c1 = XCreateFontCursor(display, XC_top_left_corner);

252 c2 = XCreateFontCursor(display, XC_top_side);

253 c3 = XCreateFontCursor(display, XC_top_right_corner);

254 c4 = XCreateFontCursor(display, XC_left_side);

255 c5 = XCreateFontCursor(display, XC_right_side);

256 c6 = XCreateFontCursor(display, XC_bottom_left_corner);

257 c7 = XCreateFontCursor(display, XC_bottom_side);

258 c8 = XCreateFontCursor(display, XC_bottom_right_corner);

259 }

260

261 resizer = MALLOC(sizeof (struct resizer));

262 create_widget(&resizer->widget, WIDGET_RESIZER,

263 WIDGET_XWINDOW(win), InputOnly, 0, 0, 1, 1);

264 resizer->widget.event = resizerevent;

265 XSelectInput(display, WIDGET_XWINDOW(resizer),

266 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);

267 resizer->window = win;

268 resizer->sizewin = NULL;

269 resizer->dir = dir;

270 fit_resizer(resizer);

271

272 switch (resizer->dir) {

273 case NORTHWEST:

274 XDefineCursor(display, WIDGET_XWINDOW(resizer), c1);

275 break;

276 case NORTH:

277 XDefineCursor(display, WIDGET_XWINDOW(resizer), c2);

278 break;

279 case NORTHEAST:

280 XDefineCursor(display, WIDGET_XWINDOW(resizer), c3);

281 break;

282 case WEST:

283 XDefineCursor(display, WIDGET_XWINDOW(resizer), c4);

284 break;

285 case EAST:

286 XDefineCursor(display, WIDGET_XWINDOW(resizer), c5);

287 break;

288 case SOUTHWEST:

289 XDefineCursor(display, WIDGET_XWINDOW(resizer), c6);

290 break;

291 case SOUTH:

292 XDefineCursor(display, WIDGET_XWINDOW(resizer), c7);

293 break;

294 case SOUTHEAST:

295 XDefineCursor(display, WIDGET_XWINDOW(resizer), c8);

296 break;

297 default:

298 abort();

299 }

300

301 XLowerWindow(display, WIDGET_XWINDOW(resizer));

302 map_widget(&resizer->widget);

303 return resizer;

304 }

305

306 void destroy_resizer(struct resizer *resizer)

307 {

308 if (resizer->sizewin != NULL)

309 destroy_sizewin(resizer->sizewin);

310 destroy_widget(&resizer->widget);

311 FREE(resizer);

312 }

313

314 void fit_resizer(struct resizer *resizer)

315 {

316 struct window *window = resizer->window;

317 int x, y;

318 int ux, uy;

319 int width, height;

320

321 ux = MIN(button_size, WIDGET_WIDTH(window) / 3);

322 uy = MIN(button_size, WIDGET_HEIGHT(window) / 3);

323

324 switch (resizer->dir) {

325 case NORTHWEST:

326 x = 0;

327 y = 0;

328 width = ux;

329 height = uy;

330 break;

331 case NORTH:

332 x = ux;

333 y = 0;

334 width = WIDGET_WIDTH(window) - 2 * ux;

335 height = border_width;

336 break;

337 case NORTHEAST:

338 x = WIDGET_WIDTH(window) - ux;

339 y = 0;

340 width = ux;

341 height = uy;

342 break;

343 case WEST:

344 x = 0;

345 y = uy;

346 width = border_width;

347 height = WIDGET_HEIGHT(window) - 2 * uy;

348 break;

349 case EAST:

350 x = WIDGET_WIDTH(window) - border_width;

351 y = uy;

352 width = border_width;

353 height = WIDGET_HEIGHT(window) - 2 * uy;

354 break;

355 case SOUTHWEST:

356 x = 0;

357 y = WIDGET_HEIGHT(window) - uy;

358 width = ux;

359 height = uy;

360 break;

361 case SOUTH:

362 x = ux;

363 y = WIDGET_HEIGHT(window) - border_width;

364 width = WIDGET_WIDTH(window) - 2 * ux;

365 height = border_width;

366 break;

367 case SOUTHEAST:

368 x = WIDGET_WIDTH(window) - ux;

369 y = WIDGET_HEIGHT(window) - uy;

370 width = ux;

371 height = uy;

372 break;

373 default:

374 abort();

375 }

376 moveresize_widget(&resizer->widget, x, y, width, height);

377 }

378