Changeset 4852


Ignore:
Timestamp:
Nov 18, 2012, 7:34:14 PM (7 years ago)
Author:
Sam Hocevar
Message:

win32: improvements to the Win32 driver by Bastian Märkisch <bmaerkisch@web.de>:

  • Save and correctly restore console input mode, ie. do not change settings of the original console.
  • Fix hiding of cursor.
  • Free console again if the driver actually created a new one.
  • Default canvas size is current window size.
  • Base calculation on current font.
  • Properly handle press and release events of up to 5 mouse buttons.
  • Map right mouse button to button #3. This is a change in behaviour, which is desirable for cross-platform codes.
  • Generate two click events for double mouse clicks.
  • Mouse wheel support, creates button press events. Button numbers are identical to X11 mappings.
  • Handle window buffer resize events.
Location:
libcaca/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/THANKS

    r4333 r4852  
    55- Gildas Bazin <gbazin@netcourrier.com> - win32 driver improvements
    66- Jari Komppa <jari.komppa at gmail> - win32 speed improvements
     7- Bastian Märkisch <bmaerkisch@web.de> - bugfixes and win32 driver improvements
    78
    89\section thanks2 Reused code
  • libcaca/trunk/caca/driver/win32.c

    r4369 r4852  
    11/*
    22 *  libcaca       Colour ASCII-Art library
    3  *  Copyright (c) 2002-2010 Sam Hocevar <sam@hocevar.net>
     3 *  Copyright (c) 2002-2012 Sam Hocevar <sam@hocevar.net>
     4 *                2012 Bastian Märkisch <bmaerkisch@web.de>
    45 *                All Rights Reserved
    56 *
     
    1920#if defined(USE_WIN32)
    2021
     22#define _WIN32_WINNT 0x500 /* Require WinXP or later */
     23#define WIN32_LEAN_AND_MEAN
    2124#include <windows.h>
     25
     26#ifdef __MINGW32__
     27/* This is missing from the MinGW headers. */
     28#   if (_WIN32_WINNT >= 0x0500)
     29BOOL WINAPI GetCurrentConsoleFont(HANDLE hConsoleOutput, BOOL bMaximumWindow,
     30                                  PCONSOLE_FONT_INFO lpConsoleCurrentFont);
     31#   endif
     32#endif
     33#ifndef MOUSE_HWHEELED
     34#   define MOUSE_HWHEELED 0x0008
     35#endif
    2236
    2337#include <stdlib.h>
     
    7690    CHAR_INFO *buffer;
    7791    CONSOLE_CURSOR_INFO cci;
     92    DWORD mouse_state;
     93    DWORD mode;
     94    BOOL new_console;
    7895};
    7996
     
    83100    int height = caca_get_canvas_height(dp->cv);
    84101    CONSOLE_SCREEN_BUFFER_INFO csbi;
     102    CONSOLE_CURSOR_INFO cci_screen;
    85103    SMALL_RECT rect;
    86104    COORD size;
     
    88106    dp->drv.p = malloc(sizeof(struct driver_private));
    89107
    90     /* This call is allowed to fail in case we already have a console */
    91     AllocConsole();
     108    /* This call is allowed to fail in case we already have a console. */
     109    dp->drv.p->new_console = AllocConsole();
    92110
    93111    dp->drv.p->hin = GetStdHandle(STD_INPUT_HANDLE);
     
    98116        return -1;
    99117
     118    /* Preserve state information */
    100119    GetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
    101     dp->drv.p->cci.bVisible = FALSE;
    102     SetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
    103 
    104     SetConsoleMode(dp->drv.p->hout, ENABLE_MOUSE_INPUT);
    105120
    106121    dp->drv.p->screen =
     
    109124    if(!dp->drv.p->screen || dp->drv.p->screen == INVALID_HANDLE_VALUE)
    110125        return -1;
    111 
    112     /* Set the new console size */
     126    dp->drv.p->mouse_state = 0;
     127
     128    /* Set the new console size, default to current screen size. */
    113129    size.X = width ? width : 80;
    114130    size.Y = height ? height : 25;
     131    if ((width <= 0) && (height <= 0))
     132    {
     133        CONSOLE_SCREEN_BUFFER_INFO info;
     134
     135        if (GetConsoleScreenBufferInfo(dp->drv.p->hout, &info) != 0)
     136            size = info.dwSize;
     137    }
    115138    SetConsoleScreenBufferSize(dp->drv.p->screen, size);
    116139
     
    134157    SetConsoleMode(dp->drv.p->screen, 0);
    135158
    136     GetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci);
    137     dp->drv.p->cci.dwSize = 0;
    138     dp->drv.p->cci.bVisible = FALSE;
    139     SetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci);
     159    /* We want mouse and window resize events. */
     160    GetConsoleMode(dp->drv.p->hin, &dp->drv.p->mode);
     161    SetConsoleMode(dp->drv.p->hin, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
     162
     163    cci_screen.dwSize = 1;  /* must be > 0, see MSDN */
     164    cci_screen.bVisible = FALSE;
     165    SetConsoleCursorInfo(dp->drv.p->screen, &cci_screen);
    140166
    141167    SetConsoleActiveScreenBuffer(dp->drv.p->screen);
     
    154180    CloseHandle(dp->drv.p->screen);
    155181
    156     SetConsoleTextAttribute(dp->drv.p->hout, FOREGROUND_INTENSITY
    157                                              | FOREGROUND_RED
    158                                              | FOREGROUND_GREEN
    159                                              | FOREGROUND_BLUE);
    160     dp->drv.p->cci.bVisible = TRUE;
     182    /* Reset console parameters */
     183    SetConsoleMode(dp->drv.p->hin, dp->drv.p->mode);
    161184    SetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
    162185    CloseHandle(dp->drv.p->hout);
    163186
     187    /* We only free the console if we successfully created a new one before */
     188    if (dp->drv.p->new_console)
     189        FreeConsole();
     190
    164191    free(dp->drv.p);
    165192
     
    175202static int win32_get_display_width(caca_display_t const *dp)
    176203{
    177     /* FIXME */
    178 
    179204    /* Fallback to a 6x10 font */
    180     return caca_get_canvas_width(dp->cv) * 6;
     205    int font_width = 6;
     206
     207#if (_WIN32_WINNT >= 0x500)
     208    CONSOLE_FONT_INFO info;
     209    if (GetCurrentConsoleFont(dp->drv.p->screen, FALSE, &info) != 0)
     210        font_width = info.dwFontSize.X;
     211#endif
     212    return font_width * caca_get_canvas_width(dp->cv);
    181213}
    182214
    183215static int win32_get_display_height(caca_display_t const *dp)
    184216{
    185     /* FIXME */
    186 
    187217    /* Fallback to a 6x10 font */
    188     return caca_get_canvas_height(dp->cv) * 10;
     218    int font_height = 10;
     219
     220#if (_WIN32_WINNT >= 0x500)
     221    CONSOLE_FONT_INFO info;
     222    if (GetCurrentConsoleFont(dp->drv.p->screen, FALSE, &info) != 0)
     223        font_height = info.dwFontSize.Y;
     224#endif
     225    return font_height * caca_get_canvas_height(dp->cv);
    189226}
    190227
     
    245282static void win32_handle_resize(caca_display_t *dp)
    246283{
    247     /* FIXME: I don't know what to do here. */
    248     dp->resize.w = caca_get_canvas_width(dp->cv);
    249     dp->resize.h = caca_get_canvas_height(dp->cv);
     284    /* We only need to resize the internal buffer. */
     285    dp->drv.p->buffer = realloc(dp->drv.p->buffer,
     286                        dp->resize.w * dp->resize.h * sizeof(CHAR_INFO));
    250287}
    251288
     
    257294    for( ; ; )
    258295    {
    259         GetNumberOfConsoleInputEvents(dp->drv.p->hin, &num);
     296        HANDLE hin = GetStdHandle(STD_INPUT_HANDLE);
     297        if(hin == INVALID_HANDLE_VALUE)
     298            break;
     299
     300        GetNumberOfConsoleInputEvents(hin, &num);
    260301        if(num == 0)
    261302            break;
    262303
    263         ReadConsoleInput(dp->drv.p->hin, &rec, 1, &num);
     304        if(!ReadConsoleInput(hin, &rec, 1, &num) || (num == 0))
     305            break;
     306
    264307        if(rec.EventType == KEY_EVENT)
    265308        {
     
    335378                }
    336379
    337                 if ((ev->data.key.ch > 0)
     380                if((ev->data.key.ch > 0)
    338381                    &&
    339382                    (ev->data.key.ch <= 0x7f))
     
    352395            }
    353396        }
    354 
    355         if(rec.EventType == MOUSE_EVENT)
     397        else if(rec.EventType == MOUSE_EVENT)
    356398        {
    357             if(rec.Event.MouseEvent.dwEventFlags == 0)
     399            if((rec.Event.MouseEvent.dwEventFlags == 0) ||
     400               (rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
    358401            {
    359                 if(rec.Event.MouseEvent.dwButtonState & 0x01)
     402                DWORD mouse_state_changed =
     403                    dp->drv.p->mouse_state ^ rec.Event.MouseEvent.dwButtonState;
     404                int button;
     405                DWORD mask = 0x01;
     406                int const mapping[] = {1, 3, 2, 8, 9};
     407
     408                for (button = 1; button <= 5; button++)
    360409                {
    361                     ev->type = CACA_EVENT_MOUSE_PRESS;
    362                     ev->data.mouse.button = 1;
    363                     return 1;
    364                 }
    365 
    366                 if(rec.Event.MouseEvent.dwButtonState & 0x02)
    367                 {
    368                     ev->type = CACA_EVENT_MOUSE_PRESS;
    369                     ev->data.mouse.button = 2;
    370                     return 1;
     410                    if(mouse_state_changed == mask)
     411                    {
     412                        if(rec.Event.MouseEvent.dwButtonState & mask)
     413                            ev->type = CACA_EVENT_MOUSE_PRESS;
     414                        else
     415                            ev->type = CACA_EVENT_MOUSE_RELEASE;
     416                        ev->data.mouse.button = mapping[button - 1];
     417                        dp->drv.p->mouse_state = rec.Event.MouseEvent.dwButtonState;
     418                        return 1;
     419                    }
     420                    mask <<= 1;
    371421                }
    372422            }
     
    386436                return 1;
    387437            }
    388 #if 0
    389             else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
    390             {
    391                 cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
    392                         rec.Event.MouseEvent.dwMousePosition.Y << "  " << flush;
    393             }
    394438            else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
    395439            {
    396                 SetConsoleCursorPosition(hOut,
    397                                          WheelWhere);
    398                 if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
    399                     cout << "Down" << flush;
     440                ev->type = CACA_EVENT_MOUSE_PRESS;
     441                if((int16_t)HIWORD(rec.Event.MouseEvent.dwButtonState) > 0)
     442                    ev->data.mouse.button = 4; /* up */
    400443                else
    401                     cout << "Up  " << flush;
     444                    ev->data.mouse.button = 5; /* down */
     445                return 1;
    402446            }
    403 #endif
     447            else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_HWHEELED)
     448            {
     449                ev->type = CACA_EVENT_MOUSE_PRESS;
     450                if((int16_t)HIWORD(rec.Event.MouseEvent.dwButtonState) > 0)
     451                    ev->data.mouse.button = 7; /* right */
     452                else
     453                    ev->data.mouse.button = 6; /* left */
     454                return 1;
     455            }
     456        }
     457        else if(rec.EventType == WINDOW_BUFFER_SIZE_EVENT)
     458        {
     459            int width = caca_get_canvas_width(dp->cv);
     460            int height = caca_get_canvas_height(dp->cv);
     461            int w = rec.Event.WindowBufferSizeEvent.dwSize.X;
     462            int h = rec.Event.WindowBufferSizeEvent.dwSize.Y;
     463            if((w == 0) || (h == 0) || ((w == width) && (h == height)))
     464                continue;
     465
     466            /* resize the canvas accordingly */
     467            ev->type = CACA_EVENT_RESIZE;
     468            dp->resize.w = w;
     469            dp->resize.h = h;
     470            dp->resize.resized = 1;
     471            return 1;
    404472        }
    405473
Note: See TracChangeset for help on using the changeset viewer.