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

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