You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

528 lines
15 KiB

  1. /*
  2. * neercs console-based window manager
  3. * Copyright (c) 2006-2010 Sam Hocevar <sam@hocevar.net>
  4. * 2008-2010 Jean-Yves Lamoureux <jylam@lnxscene.org>
  5. * All Rights Reserved
  6. *
  7. * This program is free software. It comes without any warranty, to
  8. * the extent permitted by applicable law. You can redistribute it
  9. * and/or modify it under the terms of the Do What The Fuck You Want
  10. * To Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. #if defined HAVE_CONFIG_H
  14. # include "config.h"
  15. #endif
  16. #if defined _XBOX
  17. # define _USE_MATH_DEFINES /* for M_PI */
  18. # include <xtl.h>
  19. # undef near /* Fuck Microsoft */
  20. # undef far /* Fuck Microsoft again */
  21. #elif defined _WIN32
  22. # define _USE_MATH_DEFINES /* for M_PI */
  23. # define WIN32_LEAN_AND_MEAN
  24. # include <windows.h>
  25. #endif
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <math.h>
  29. #include <caca.h>
  30. #include "core.h"
  31. #include "neercs.h"
  32. void resize_screen(struct screen *s, int w, int h)
  33. {
  34. caca_canvas_t *oldc, *newc;
  35. if (w == s->w && h == s->h)
  36. return;
  37. if (w <= 0 || h <= 0)
  38. return;
  39. s->changed = 1;
  40. s->w = w;
  41. s->h = h;
  42. /*
  43. * caca_set_canvas_boundaries() is bugged as hell, so let's resize it by
  44. * hands
  45. */
  46. oldc = s->cv;
  47. newc = caca_create_canvas(w, h);
  48. caca_blit(newc, 0, 0, oldc, NULL);
  49. s->cv = newc;
  50. caca_gotoxy(newc, caca_get_cursor_x(oldc), caca_get_cursor_y(oldc));
  51. caca_free_canvas(oldc);
  52. set_tty_size(s->fd, w, h);
  53. s->orig_w = s->w;
  54. s->orig_h = s->h;
  55. s->orig_x = s->x;
  56. s->orig_y = s->y;
  57. }
  58. void update_windows_props(struct screen_list *screen_list)
  59. {
  60. debug("%s, %d screens, type %d\n", __FUNCTION__, screen_list->count,
  61. screen_list->wm_type);
  62. if (!screen_list->count)
  63. return;
  64. switch (screen_list->wm_type)
  65. {
  66. case WM_CARD:
  67. update_windows_props_cards(screen_list);
  68. break;
  69. case WM_HSPLIT:
  70. update_windows_props_hsplit(screen_list);
  71. break;
  72. case WM_VSPLIT:
  73. update_windows_props_vsplit(screen_list);
  74. break;
  75. case WM_FULL:
  76. default:
  77. update_windows_props_full(screen_list);
  78. break;
  79. }
  80. }
  81. void update_windows_props_hsplit(struct screen_list *screen_list)
  82. {
  83. int i;
  84. int w =
  85. (screen_list->width / screen_list->count) -
  86. (screen_list->border_size * 2);
  87. int h = screen_list->height - (screen_list->border_size * 2);
  88. for (i = 0; i < screen_list->count; i++)
  89. {
  90. screen_list->screen[i]->x = (i * w) + screen_list->border_size;
  91. screen_list->screen[i]->y = screen_list->border_size;
  92. screen_list->screen[i]->visible = 1;
  93. if (i != screen_list->count - 1)
  94. {
  95. resize_screen(screen_list->screen[i], w - 1, h);
  96. }
  97. else
  98. {
  99. resize_screen(screen_list->screen[i],
  100. screen_list->width - i * w - 2, h);
  101. }
  102. }
  103. }
  104. void update_windows_props_vsplit(struct screen_list *screen_list)
  105. {
  106. int i;
  107. int w = screen_list->width - (screen_list->border_size * 2);
  108. int h = (screen_list->height) / screen_list->count;
  109. for (i = 0; i < screen_list->count; i++)
  110. {
  111. screen_list->screen[i]->x = screen_list->border_size;
  112. screen_list->screen[i]->y = (i * h) + (screen_list->border_size);
  113. screen_list->screen[i]->visible = 1;
  114. if (i != screen_list->count - 1)
  115. {
  116. resize_screen(screen_list->screen[i], w,
  117. h - (screen_list->border_size * 2));
  118. }
  119. else
  120. {
  121. resize_screen(screen_list->screen[i],
  122. w,
  123. screen_list->height - i * h -
  124. (screen_list->border_size * 2));
  125. }
  126. }
  127. }
  128. void update_windows_props_full(struct screen_list *screen_list)
  129. {
  130. int i;
  131. int w = screen_list->width - (screen_list->border_size * 2);
  132. int h = screen_list->height - (screen_list->border_size * 2);
  133. for (i = 0; i < screen_list->count; i++)
  134. {
  135. screen_list->screen[i]->visible = 0;
  136. screen_list->screen[i]->x = screen_list->border_size;
  137. screen_list->screen[i]->y = screen_list->border_size;
  138. resize_screen(screen_list->screen[i], w, h);
  139. }
  140. screen_list->screen[screen_list->pty]->visible = 1;
  141. }
  142. void update_windows_props_cards(struct screen_list *screen_list)
  143. {
  144. int i;
  145. int w = (screen_list->width - screen_list->count * 3) + 1;
  146. int h = (screen_list->height - screen_list->count) - 1;
  147. int x = 1;
  148. int y = screen_list->count;
  149. for (i = 0; i < screen_list->count; i++)
  150. {
  151. screen_list->screen[i]->visible = 1;
  152. screen_list->screen[i]->x = x;
  153. screen_list->screen[i]->y = y;
  154. resize_screen(screen_list->screen[i], w, h);
  155. x += 3;
  156. y--;
  157. }
  158. }
  159. /* Window managers refresh */
  160. void wm_refresh(struct screen_list *screen_list)
  161. {
  162. /* FIXME : move set_color to a relevant place */
  163. caca_set_color_ansi(screen_list->cv, CACA_LIGHTRED, CACA_BLACK);
  164. switch (screen_list->wm_type)
  165. {
  166. case WM_CARD:
  167. wm_refresh_card(screen_list);
  168. break;
  169. case WM_HSPLIT:
  170. wm_refresh_hsplit(screen_list);
  171. break;
  172. case WM_VSPLIT:
  173. wm_refresh_hsplit(screen_list);
  174. break;
  175. case WM_FULL:
  176. default:
  177. wm_refresh_cube(screen_list);
  178. break;
  179. }
  180. }
  181. static void wm_bell(struct screen_list *screen_list)
  182. {
  183. if (screen_list->screen[screen_list->pty]->bell)
  184. {
  185. caca_set_color_ansi(screen_list->cv, CACA_RED, CACA_BLACK);
  186. screen_list->in_bell--;
  187. screen_list->force_refresh = 1;
  188. if (!screen_list->in_bell)
  189. {
  190. screen_list->was_in_bell = 1;
  191. screen_list->screen[screen_list->pty]->bell = 0;
  192. }
  193. }
  194. else
  195. {
  196. if (screen_list->was_in_bell)
  197. {
  198. screen_list->screen[screen_list->pty]->bell = 0;
  199. screen_list->force_refresh = 1;
  200. screen_list->was_in_bell = 0;
  201. screen_list->changed = 1;
  202. }
  203. caca_set_color_ansi(screen_list->cv, CACA_LIGHTGREEN, CACA_BLACK);
  204. }
  205. }
  206. static void wm_box(struct screen_list *screen_list, int pty)
  207. {
  208. if (!screen_list->screen[pty]->changed && !screen_list->changed)
  209. return;
  210. if (!screen_list->border_size)
  211. return;
  212. /* Color determined by wm_bell() */
  213. caca_draw_cp437_box(screen_list->cv,
  214. screen_list->screen[pty]->x - 1,
  215. screen_list->screen[pty]->y - 1,
  216. screen_list->screen[pty]->w + 2,
  217. screen_list->screen[pty]->h + 2);
  218. if (screen_list->screen[pty]->title)
  219. {
  220. caca_printf(screen_list->cv,
  221. screen_list->screen[pty]->x,
  222. screen_list->screen[pty]->y - 1,
  223. " %.*s ",
  224. screen_list->screen[pty]->w - 3,
  225. screen_list->screen[pty]->title);
  226. }
  227. }
  228. static void wm_blit_current_screen(struct screen_list *screen_list)
  229. {
  230. if (screen_list->screen[screen_list->pty]->changed || screen_list->changed)
  231. caca_blit(screen_list->cv,
  232. screen_list->screen[screen_list->pty]->x,
  233. screen_list->screen[screen_list->pty]->y,
  234. screen_list->screen[screen_list->pty]->cv, NULL);
  235. }
  236. void wm_refresh_card(struct screen_list *screen_list)
  237. {
  238. int i;
  239. for (i = screen_list->count - 1; i >= 0; i--)
  240. {
  241. if (i != screen_list->pty && screen_list->screen[i]->visible &&
  242. (screen_list->screen[i]->changed || screen_list->changed))
  243. {
  244. caca_blit(screen_list->cv,
  245. screen_list->screen[i]->x,
  246. screen_list->screen[i]->y,
  247. screen_list->screen[i]->cv, NULL);
  248. wm_box(screen_list, i);
  249. }
  250. }
  251. /* Force 'changed' to force redraw */
  252. screen_list->screen[screen_list->pty]->changed = 1;
  253. wm_blit_current_screen(screen_list);
  254. wm_bell(screen_list);
  255. wm_box(screen_list, screen_list->pty);
  256. }
  257. void wm_refresh_full(struct screen_list *screen_list)
  258. {
  259. wm_blit_current_screen(screen_list);
  260. wm_bell(screen_list);
  261. wm_box(screen_list, screen_list->pty);
  262. }
  263. void wm_refresh_vsplit(struct screen_list *screen_list)
  264. {
  265. int i;
  266. for (i = screen_list->count - 1; i >= 0; i--)
  267. {
  268. if (i != screen_list->pty && screen_list->screen[i]->visible &&
  269. (screen_list->screen[i]->changed || screen_list->changed))
  270. {
  271. caca_blit(screen_list->cv,
  272. screen_list->screen[i]->x,
  273. screen_list->screen[i]->y,
  274. screen_list->screen[i]->cv, NULL);
  275. wm_box(screen_list, i);
  276. }
  277. }
  278. wm_blit_current_screen(screen_list);
  279. wm_bell(screen_list);
  280. wm_box(screen_list, screen_list->pty);
  281. }
  282. void wm_refresh_hsplit(struct screen_list *screen_list)
  283. {
  284. int i;
  285. for (i = screen_list->count - 1; i >= 0; i--)
  286. {
  287. if (i != screen_list->pty && screen_list->screen[i]->visible &&
  288. (screen_list->screen[i]->changed || screen_list->changed))
  289. {
  290. caca_blit(screen_list->cv,
  291. screen_list->screen[i]->x,
  292. screen_list->screen[i]->y,
  293. screen_list->screen[i]->cv, NULL);
  294. wm_box(screen_list, i);
  295. }
  296. }
  297. wm_blit_current_screen(screen_list);
  298. wm_bell(screen_list);
  299. wm_box(screen_list, screen_list->pty);
  300. }
  301. static float
  302. get_direction(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y)
  303. {
  304. float d1x, d1y, d2x, d2y;
  305. d1x = p3x - p1x;
  306. d1y = p3y - p1y;
  307. d2x = p3x - p2x;
  308. d2y = p3y - p2y;
  309. return (d1x * d2y) - (d1y * d2x);
  310. }
  311. /* 3D Cube. Yeah I know, it's a mess. Just look anywhere else. */
  312. static void draw_face(caca_canvas_t * cv,
  313. int p1x, int p1y,
  314. int p2x, int p2y,
  315. int p3x, int p3y,
  316. int p4x, int p4y, caca_canvas_t * tex,
  317. int color, int borders)
  318. {
  319. if (get_direction(p1x, p1y, p2x, p2y, p3x, p3y) >= 0)
  320. {
  321. int coords[6];
  322. float uv[6];
  323. coords[0] = p1x;
  324. coords[1] = p1y;
  325. coords[2] = p2x;
  326. coords[3] = p2y;
  327. coords[4] = p3x;
  328. coords[5] = p3y;
  329. uv[0] = 1;
  330. uv[1] = 1;
  331. uv[2] = 0;
  332. uv[3] = 1;
  333. uv[4] = 0;
  334. uv[5] = 0;
  335. caca_fill_triangle_textured(cv, coords, tex, uv);
  336. coords[0] = p1x;
  337. coords[1] = p1y;
  338. coords[2] = p3x;
  339. coords[3] = p3y;
  340. coords[4] = p4x;
  341. coords[5] = p4y;
  342. uv[0] = 1;
  343. uv[1] = 1;
  344. uv[2] = 0;
  345. uv[3] = 0;
  346. uv[4] = 1;
  347. uv[5] = 0;
  348. caca_fill_triangle_textured(cv, coords, tex, uv);
  349. caca_set_color_ansi(cv, color, CACA_BLACK);
  350. if (borders)
  351. {
  352. caca_draw_thin_line(cv, p1x, p1y, p2x, p2y);
  353. caca_draw_thin_line(cv, p2x, p2y, p3x, p3y);
  354. caca_draw_thin_line(cv, p3x, p3y, p4x, p4y);
  355. caca_draw_thin_line(cv, p4x, p4y, p1x, p1y);
  356. }
  357. }
  358. }
  359. void wm_refresh_cube(struct screen_list *screen_list)
  360. {
  361. int i;
  362. if (!screen_list->cube.in_switch || !screen_list->eyecandy)
  363. {
  364. wm_refresh_full(screen_list);
  365. // screen_list->force_refresh = 0;
  366. }
  367. else
  368. {
  369. long long unsigned int cur_time = get_us() - screen_list->last_switch;
  370. if (cur_time >= screen_list->cube.duration || screen_list->count == 1)
  371. {
  372. screen_list->changed = 1;
  373. screen_list->force_refresh = 1;
  374. screen_list->cube.in_switch = 0;
  375. }
  376. else
  377. {
  378. float cube[12][3] = {
  379. {-1, -1, 1},
  380. {1, -1, 1},
  381. {1, 1, 1},
  382. {-1, 1, 1},
  383. {1, -1, 1},
  384. {1, -1, -1},
  385. {1, 1, -1},
  386. {1, 1, 1},
  387. {-1, -1, -1},
  388. {-1, -1, 1},
  389. {-1, 1, 1},
  390. {-1, 1, -1},
  391. };
  392. float cube_transformed[12][3];
  393. float cube_projected[12][2];
  394. float fov = 0.5f;
  395. float angle =
  396. 90.0f * ((float)cur_time / (float)screen_list->cube.duration);
  397. angle *= (M_PI / 180.0f);
  398. if (screen_list->cube.side == 1)
  399. angle = -angle;
  400. float sina = lol::sin(angle);
  401. float cosa = lol::cos(angle);
  402. for (i = 0; i < 12; i++)
  403. {
  404. cube_transformed[i][2] = cube[i][2] * cosa - cube[i][0] * sina;
  405. cube_transformed[i][0] = cube[i][2] * sina + cube[i][0] * cosa;
  406. cube_transformed[i][1] = cube[i][1];
  407. cube_transformed[i][2] -= 3;
  408. cube_projected[i][0] =
  409. cube_transformed[i][0] / (cube_transformed[i][2] * fov);
  410. cube_projected[i][1] =
  411. cube_transformed[i][1] / (cube_transformed[i][2] * fov);
  412. cube_projected[i][0] /= 2.0f;
  413. cube_projected[i][1] /= 2.0f;
  414. cube_projected[i][0] += 0.5f;
  415. cube_projected[i][1] += 0.5f;
  416. cube_projected[i][0] *= screen_list->width;
  417. cube_projected[i][1] *= screen_list->height;
  418. }
  419. caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLACK);
  420. caca_clear_canvas(screen_list->cv);
  421. caca_canvas_t *first =
  422. screen_list->screen[screen_list->prevpty]->cv;
  423. caca_canvas_t *second = screen_list->screen[screen_list->pty]->cv;
  424. draw_face(screen_list->cv,
  425. cube_projected[0][0], cube_projected[0][1],
  426. cube_projected[1][0], cube_projected[1][1],
  427. cube_projected[2][0], cube_projected[2][1],
  428. cube_projected[3][0], cube_projected[3][1],
  429. first, CACA_LIGHTGREEN, screen_list->border_size);
  430. if (screen_list->cube.side)
  431. {
  432. draw_face(screen_list->cv,
  433. cube_projected[4][0], cube_projected[4][1],
  434. cube_projected[5][0], cube_projected[5][1],
  435. cube_projected[6][0], cube_projected[6][1],
  436. cube_projected[7][0], cube_projected[7][1],
  437. second, CACA_LIGHTGREEN, screen_list->border_size);
  438. }
  439. else
  440. {
  441. draw_face(screen_list->cv,
  442. cube_projected[8][0], cube_projected[8][1],
  443. cube_projected[9][0], cube_projected[9][1],
  444. cube_projected[10][0], cube_projected[10][1],
  445. cube_projected[11][0], cube_projected[11][1],
  446. second, CACA_LIGHTGREEN, screen_list->border_size);
  447. }
  448. screen_list->changed = 1;
  449. screen_list->force_refresh = 1;
  450. screen_list->cube.in_switch = 1;
  451. }
  452. }
  453. }