source: neercs/trunk/src/wm.c @ 4366

Last change on this file since 4366 was 4366, checked in by Sam Hocevar, 8 years ago

Clean up source code, copyright information, author names, SVN keywords...

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