source: trunk/tools/neercs/old/wm.cpp @ 1657

Last change on this file since 1657 was 1657, checked in by sam, 10 years ago

neercs: be sure to include C headers inside extern "C" in cpp files.

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