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

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