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

Last change on this file since 3992 was 3992, checked in by jylam, 5 years ago
  • Fixed refresh in card mode, which caused selected window to be transparent if not updated regulary
  • Property svn:keywords set to Id
File size: 13.6 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 3992 2009-11-21 16:48:13Z 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    case WM_CUBE:
80    default:
81        update_windows_props_full(screen_list);
82        break;
83    }
84}
85
86void update_windows_props_hsplit(struct screen_list *screen_list)
87{
88    int i;
89    int w = (screen_list->width / screen_list->count) - 1;
90    int h = screen_list->height - 2;
91
92    for (i = 0; i < screen_list->count; i++)
93    {
94        screen_list->screen[i]->x = (i * w) + 1;
95        screen_list->screen[i]->y = 1;
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 - 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 = 1;
118        screen_list->screen[i]->y = (i * h) + 1;
119        screen_list->screen[i]->visible = 1;
120        if (i != screen_list->count - 1)
121        {
122            resize_screen(screen_list->screen[i], w, h - 2);
123        }
124        else
125        {
126            resize_screen(screen_list->screen[i],
127                          w, screen_list->height - i * h - 2);
128        }
129    }
130}
131
132
133void update_windows_props_full(struct screen_list *screen_list)
134{
135    int i;
136    int w = screen_list->width - 2;
137    int h = screen_list->height - 2;
138
139    for (i = 0; i < screen_list->count; i++)
140    {
141        screen_list->screen[i]->visible = 0;
142        screen_list->screen[i]->x = 1;
143        screen_list->screen[i]->y = 1;
144
145        resize_screen(screen_list->screen[i], w, h);
146    }
147    screen_list->screen[screen_list->pty]->visible = 1;
148}
149
150
151void update_windows_props_cards(struct screen_list *screen_list)
152{
153    int i;
154    int w = (screen_list->width - screen_list->count * 3) + 1;
155    int h = (screen_list->height - screen_list->count) - 1;
156    int x = 1;
157    int y = screen_list->count;
158
159    for (i = 0; i < screen_list->count; i++)
160    {
161        screen_list->screen[i]->visible = 1;
162        screen_list->screen[i]->x = x;
163        screen_list->screen[i]->y = y;
164
165        resize_screen(screen_list->screen[i], w, h);
166        x += 3;
167        y--;
168    }
169}
170
171/* Window managers refresh */
172
173void wm_refresh(struct screen_list *screen_list)
174{
175    switch (screen_list->wm_type)
176    {
177    case WM_CARD:
178        wm_refresh_card(screen_list);
179        break;
180    case WM_FULL:
181        wm_refresh_full(screen_list);
182        break;
183    case WM_HSPLIT:
184        wm_refresh_hsplit(screen_list);
185        break;
186    case WM_VSPLIT:
187        wm_refresh_hsplit(screen_list);
188        break;
189    case WM_CUBE:
190        wm_refresh_cube(screen_list);
191        break;
192    default:
193        wm_refresh_full(screen_list);
194        break;
195    }
196}
197
198static void wm_bell(struct screen_list *screen_list)
199{
200    if (screen_list->screen[screen_list->pty]->bell)
201    {
202        caca_set_color_ansi(screen_list->cv, CACA_RED, CACA_BLACK);
203        screen_list->screen[screen_list->pty]->bell = 0;
204        screen_list->in_bell--;
205    }
206    else
207    {
208        caca_set_color_ansi(screen_list->cv, CACA_LIGHTGREEN, CACA_BLACK);
209    }
210}
211
212static void wm_box(struct screen_list *screen_list, int pty)
213{
214    caca_draw_cp437_box(screen_list->cv,
215                        screen_list->screen[pty]->x - 1,
216                        screen_list->screen[pty]->y - 1,
217                        screen_list->screen[pty]->w + 2,
218                        screen_list->screen[pty]->h + 2);
219
220    if (screen_list->screen[screen_list->pty]->title)
221    {
222        caca_printf(screen_list->cv,
223                    screen_list->screen[pty]->x,
224                    screen_list->screen[pty]->y - 1,
225                    " %.*s ",
226                    screen_list->screen[pty]->w - 3,
227                    screen_list->screen[pty]->title);
228    }
229}
230
231static void wm_blit_current_screen(struct screen_list *screen_list)
232{
233    if (screen_list->screen[screen_list->pty]->changed || screen_list->changed)
234        caca_blit(screen_list->cv,
235                  screen_list->screen[screen_list->pty]->x,
236                  screen_list->screen[screen_list->pty]->y,
237                  screen_list->screen[screen_list->pty]->cv, NULL);
238}
239
240void wm_refresh_card(struct screen_list *screen_list)
241{
242    int i;
243
244    for (i = screen_list->count - 1; i >= 0; i--)
245    {
246        if (i != screen_list->pty && screen_list->screen[i]->visible &&
247            (screen_list->screen[i]->changed || screen_list->changed))
248        {
249            caca_blit(screen_list->cv,
250                      screen_list->screen[i]->x,
251                      screen_list->screen[i]->y,
252                      screen_list->screen[i]->cv, NULL);
253
254            wm_box(screen_list, i);
255        }
256    }
257       
258    /* Force 'changed' to force redraw */
259    screen_list->screen[screen_list->pty]->changed = 1;
260    wm_blit_current_screen(screen_list);
261    wm_bell(screen_list);
262    wm_box(screen_list, screen_list->pty);
263}
264
265void wm_refresh_full(struct screen_list *screen_list)
266{
267    wm_blit_current_screen(screen_list);
268    wm_bell(screen_list);
269    wm_box(screen_list, screen_list->pty);
270}
271
272void wm_refresh_vsplit(struct screen_list *screen_list)
273{
274    int i;
275
276    for (i = screen_list->count - 1; i >= 0; i--)
277    {
278        if (i != screen_list->pty && screen_list->screen[i]->visible &&
279            (screen_list->screen[i]->changed || screen_list->changed))
280        {
281            caca_blit(screen_list->cv,
282                      screen_list->screen[i]->x,
283                      screen_list->screen[i]->y,
284                      screen_list->screen[i]->cv, NULL);
285
286            wm_box(screen_list, i);
287        }
288    }
289
290    wm_blit_current_screen(screen_list);
291    wm_bell(screen_list);
292    wm_box(screen_list, screen_list->pty);
293}
294
295void wm_refresh_hsplit(struct screen_list *screen_list)
296{
297    int i;
298
299    for (i = screen_list->count - 1; i >= 0; i--)
300    {
301        if (i != screen_list->pty && screen_list->screen[i]->visible &&
302            (screen_list->screen[i]->changed || screen_list->changed))
303        {
304            caca_blit(screen_list->cv,
305                      screen_list->screen[i]->x,
306                      screen_list->screen[i]->y,
307                      screen_list->screen[i]->cv, NULL);
308
309            wm_box(screen_list, i);
310        }
311    }
312
313    wm_blit_current_screen(screen_list);
314    wm_bell(screen_list);
315    wm_box(screen_list, screen_list->pty);
316}
317
318
319static float
320get_direction(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y)
321{
322    float d1x, d1y, d2x, d2y;
323
324    d1x = p3x - p1x;
325    d1y = p3y - p1y;
326    d2x = p3x - p2x;
327    d2y = p3y - p2y;
328    return (d1x * d2y) - (d1y * d2x);
329}
330
331
332/* 3D Cube. Yeah I know, it's a mess. Just look anywhere else. */
333static void draw_face(caca_canvas_t * cv,
334                      int p1x, int p1y,
335                      int p2x, int p2y,
336                      int p3x, int p3y,
337                      int p4x, int p4y, caca_canvas_t * tex, int color)
338{
339    if (get_direction(p1x, p1y, p2x, p2y, p3x, p3y) >= 0)
340    {
341        int coords[6];
342        float uv[6];
343        coords[0] = p1x;
344        coords[1] = p1y;
345        coords[2] = p2x;
346        coords[3] = p2y;
347        coords[4] = p3x;
348        coords[5] = p3y;
349        uv[0] = 1;
350        uv[1] = 1;
351        uv[2] = 0;
352        uv[3] = 1;
353        uv[4] = 0;
354        uv[5] = 0;
355#if defined HAVE_CACA_TRIANGLE_TEXTURING
356        caca_fill_triangle_textured(cv, coords, tex, uv);
357#endif
358        coords[0] = p1x;
359        coords[1] = p1y;
360        coords[2] = p3x;
361        coords[3] = p3y;
362        coords[4] = p4x;
363        coords[5] = p4y;
364        uv[0] = 1;
365        uv[1] = 1;
366        uv[2] = 0;
367        uv[3] = 0;
368        uv[4] = 1;
369        uv[5] = 0;
370#if defined HAVE_CACA_TRIANGLE_TEXTURING
371        caca_fill_triangle_textured(cv, coords, tex, uv);
372#endif
373        caca_set_color_ansi(cv, color, CACA_BLACK);
374        caca_draw_thin_line(cv, p1x, p1y, p2x, p2y);
375        caca_draw_thin_line(cv, p2x, p2y, p3x, p3y);
376        caca_draw_thin_line(cv, p3x, p3y, p4x, p4y);
377        caca_draw_thin_line(cv, p4x, p4y, p1x, p1y);
378    }
379}
380
381
382void wm_refresh_cube(struct screen_list *screen_list)
383{
384    int i;
385
386    if (!screen_list->cube.in_switch)
387    {
388        wm_refresh_full(screen_list);
389        screen_list->force_refresh = 0;
390    }
391    else
392    {
393        long long unsigned int cur_time = get_us() - screen_list->last_switch;
394
395        if (cur_time >= screen_list->cube.duration || screen_list->count == 1)
396        {
397            screen_list->changed = 1;
398            screen_list->force_refresh = 1;
399            screen_list->cube.in_switch = 0;
400        }
401        else
402        {
403            float cube[12][3] = {
404                {-1, -1, 1},
405                {1, -1, 1},
406                {1, 1, 1},
407                {-1, 1, 1},
408
409                {1, -1, 1},
410                {1, -1, -1},
411                {1, 1, -1},
412                {1, 1, 1},
413
414                {-1, -1, -1},
415                {-1, -1, 1},
416                {-1, 1, 1},
417                {-1, 1, -1},
418            };
419
420            float cube_transformed[12][3];
421            float cube_projected[12][2];
422            float fov = 0.5f;
423            float angle =
424                90.0f * ((float)cur_time / (float)screen_list->cube.duration);
425
426            angle *= (M_PI / 180.0f);
427
428            if (screen_list->cube.side == 1)
429                angle = -angle;
430
431            float sina = sin(angle);
432            float cosa = cos(angle);
433
434            for (i = 0; i < 12; i++)
435            {
436                cube_transformed[i][2] = cube[i][2] * cosa - cube[i][0] * sina;
437                cube_transformed[i][0] = cube[i][2] * sina + cube[i][0] * cosa;
438                cube_transformed[i][1] = cube[i][1];
439
440                cube_transformed[i][2] -= 3;
441
442                cube_projected[i][0] =
443                    cube_transformed[i][0] / (cube_transformed[i][2] * fov);
444                cube_projected[i][1] =
445                    cube_transformed[i][1] / (cube_transformed[i][2] * fov);
446
447                cube_projected[i][0] /= 2.0f;
448                cube_projected[i][1] /= 2.0f;
449                cube_projected[i][0] += 0.5f;
450                cube_projected[i][1] += 0.5f;
451
452                cube_projected[i][0] *= screen_list->width;
453                cube_projected[i][1] *= screen_list->height;
454            }
455
456            caca_set_color_ansi(screen_list->cv, CACA_WHITE, CACA_BLACK);
457            caca_clear_canvas(screen_list->cv);
458
459            caca_canvas_t *first =
460                screen_list->screen[screen_list->prevpty]->cv;
461            caca_canvas_t *second = screen_list->screen[screen_list->pty]->cv;
462
463            draw_face(screen_list->cv,
464                      cube_projected[0][0], cube_projected[0][1],
465                      cube_projected[1][0], cube_projected[1][1],
466                      cube_projected[2][0], cube_projected[2][1],
467                      cube_projected[3][0], cube_projected[3][1],
468                      first, CACA_LIGHTGREEN);
469
470
471            if (screen_list->cube.side)
472            {
473                draw_face(screen_list->cv,
474                          cube_projected[4][0], cube_projected[4][1],
475                          cube_projected[5][0], cube_projected[5][1],
476                          cube_projected[6][0], cube_projected[6][1],
477                          cube_projected[7][0], cube_projected[7][1],
478                          second, CACA_RED);
479            }
480            else
481            {
482                draw_face(screen_list->cv,
483                          cube_projected[8][0], cube_projected[8][1],
484                          cube_projected[9][0], cube_projected[9][1],
485                          cube_projected[10][0], cube_projected[10][1],
486                          cube_projected[11][0], cube_projected[11][1],
487                          second, CACA_RED);
488            }
489
490            screen_list->changed = 1;
491            screen_list->force_refresh = 1;
492            screen_list->cube.in_switch = 1;
493        }
494    }
495}
Note: See TracBrowser for help on using the repository browser.