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

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