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

Last change on this file since 1890 was 1890, checked in by sam, 7 years ago

neercs: fix Windows build.

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