+ Added the CACA_EVENT_RESIZE event. + Added caca_get_mouse_x() and caca_get_mouse_y(). * src/graphics.c: + Window resize handling in the X11 driver. * examples/aafire.c: + Fixed a bad assumption in the resize handling code.tags/v0.99.beta14
@@ -219,8 +219,8 @@ drawfire (void) | |||||
caca_draw_bitmap(0, 0, caca_get_width() - 1, caca_get_height() - 1, | caca_draw_bitmap(0, 0, caca_get_width() - 1, caca_get_height() - 1, | ||||
caca_bitmap, bitmap); | caca_bitmap, bitmap); | ||||
caca_refresh(); | caca_refresh(); | ||||
XSIZ = caca_get_width() * 2; | |||||
YSIZ = caca_get_height() * 2 - 4; | |||||
/*XSIZ = caca_get_width() * 2; | |||||
YSIZ = caca_get_height() * 2 - 4;*/ | |||||
#else | #else | ||||
aa_renderpalette (context, palette, params, 0, 0, aa_scrwidth (context), | aa_renderpalette (context, palette, params, 0, 0, aa_scrwidth (context), | ||||
aa_scrheight (context)); | aa_scrheight (context)); | ||||
@@ -181,6 +181,7 @@ enum caca_event | |||||
CACA_EVENT_MOUSE_PRESS = 0x04000000, /**< A mouse button was pressed. */ | CACA_EVENT_MOUSE_PRESS = 0x04000000, /**< A mouse button was pressed. */ | ||||
CACA_EVENT_MOUSE_RELEASE = 0x08000000, /**< A mouse button was released. */ | CACA_EVENT_MOUSE_RELEASE = 0x08000000, /**< A mouse button was released. */ | ||||
CACA_EVENT_MOUSE_MOTION = 0x10000000, /**< The mouse was moved. */ | CACA_EVENT_MOUSE_MOTION = 0x10000000, /**< The mouse was moved. */ | ||||
CACA_EVENT_RESIZE = 0x20000000, /**< The window was resized. */ | |||||
CACA_EVENT_ANY = 0xff000000 /**< Bitmask for any event. */ | CACA_EVENT_ANY = 0xff000000 /**< Bitmask for any event. */ | ||||
}; | }; | ||||
@@ -258,6 +259,8 @@ void caca_end(void); | |||||
* @{ */ | * @{ */ | ||||
unsigned int caca_get_event(unsigned int); | unsigned int caca_get_event(unsigned int); | ||||
unsigned int caca_wait_event(unsigned int); | unsigned int caca_wait_event(unsigned int); | ||||
unsigned int caca_get_mouse_x(void); | |||||
unsigned int caca_get_mouse_y(void); | |||||
/* @} */ | /* @} */ | ||||
/** \defgroup char Character printing | /** \defgroup char Character printing | ||||
@@ -73,6 +73,8 @@ extern unsigned int _caca_getticks(struct caca_timer *); | |||||
/* Cached screen size */ | /* Cached screen size */ | ||||
extern unsigned int _caca_width; | extern unsigned int _caca_width; | ||||
extern unsigned int _caca_height; | extern unsigned int _caca_height; | ||||
extern unsigned int _caca_new_width; | |||||
extern unsigned int _caca_new_height; | |||||
/* Internal libcaca features */ | /* Internal libcaca features */ | ||||
extern enum caca_feature _caca_background; | extern enum caca_feature _caca_background; | ||||
@@ -83,6 +85,7 @@ extern enum caca_feature _caca_antialiasing; | |||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
extern Display *x11_dpy; | extern Display *x11_dpy; | ||||
extern Window x11_window; | extern Window x11_window; | ||||
extern long int x11_event_mask; | |||||
extern int x11_font_width, x11_font_height; | extern int x11_font_width, x11_font_height; | ||||
#endif | #endif | ||||
@@ -69,6 +69,8 @@ static unsigned int eventbuf[EVENTBUF_LEN]; | |||||
static int events = 0; | static int events = 0; | ||||
#endif | #endif | ||||
static unsigned int mouse_x = 0, mouse_y = 0; | |||||
#if !defined(_DOXYGEN_SKIP_ME) | #if !defined(_DOXYGEN_SKIP_ME) | ||||
/* If no new key was pressed after AUTOREPEAT_THRESHOLD usec, assume the | /* If no new key was pressed after AUTOREPEAT_THRESHOLD usec, assume the | ||||
* key was released */ | * key was released */ | ||||
@@ -130,6 +132,34 @@ unsigned int caca_wait_event(unsigned int event_mask) | |||||
} | } | ||||
} | } | ||||
/** \brief Return the X mouse coordinate. | |||||
* | |||||
* This function returns the X coordinate of the mouse position last time | |||||
* it was detected. This function is not reliable if the ncurses or S-Lang | |||||
* drivers are being used, because mouse position is only detected when | |||||
* the mouse is clicked. Other drivers such as X11 work well. | |||||
* | |||||
* \return The X mouse coordinate. | |||||
*/ | |||||
unsigned int caca_get_mouse_x(void) | |||||
{ | |||||
return mouse_x; | |||||
} | |||||
/** \brief Return the Y mouse coordinate. | |||||
* | |||||
* This function returns the Y coordinate of the mouse position last time | |||||
* it was detected. This function is not reliable if the ncurses or S-Lang | |||||
* drivers are being used, because mouse position is only detected when | |||||
* the mouse is clicked. Other drivers such as X11 work well. | |||||
* | |||||
* \return The Y mouse coordinate. | |||||
*/ | |||||
unsigned int caca_get_mouse_y(void) | |||||
{ | |||||
return mouse_y; | |||||
} | |||||
/* | /* | ||||
* XXX: The following functions are local. | * XXX: The following functions are local. | ||||
*/ | */ | ||||
@@ -216,16 +246,28 @@ static unsigned int _lowlevel_event(void) | |||||
if(_caca_driver == CACA_DRIVER_X11) | if(_caca_driver == CACA_DRIVER_X11) | ||||
{ | { | ||||
XEvent xevent; | XEvent xevent; | ||||
static unsigned int x11_x = 0, x11_y = 0; | |||||
long int xevent_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | |||||
| ButtonReleaseMask | PointerMotionMask; | |||||
char key; | char key; | ||||
while(XCheckWindowEvent(x11_dpy, x11_window, xevent_mask, &xevent) | |||||
while(XCheckWindowEvent(x11_dpy, x11_window, x11_event_mask, &xevent) | |||||
== True) | == True) | ||||
{ | { | ||||
KeySym keysym; | KeySym keysym; | ||||
/* Resize event */ | |||||
if(xevent.type == ConfigureNotify) | |||||
{ | |||||
unsigned int w = xevent.xconfigure.width / x11_font_width; | |||||
unsigned int h = xevent.xconfigure.height / x11_font_height; | |||||
if(w == _caca_width && h == _caca_height) | |||||
continue; | |||||
_caca_new_width = w; | |||||
_caca_new_height = h; | |||||
return CACA_EVENT_RESIZE; | |||||
} | |||||
/* Check for mouse motion events */ | /* Check for mouse motion events */ | ||||
if(xevent.type == MotionNotify) | if(xevent.type == MotionNotify) | ||||
{ | { | ||||
@@ -237,13 +279,13 @@ static unsigned int _lowlevel_event(void) | |||||
if(newy >= _caca_height) | if(newy >= _caca_height) | ||||
newy = _caca_height - 1; | newy = _caca_height - 1; | ||||
if(x11_x == newx && x11_y == newy) | |||||
if(mouse_x == newx && mouse_y == newy) | |||||
continue; | continue; | ||||
x11_x = newx & 0xfff; | |||||
x11_y = newy & 0xfff; | |||||
mouse_x = newx; | |||||
mouse_y = newy; | |||||
return CACA_EVENT_MOUSE_MOTION | (newx << 12) | (newy << 0); | |||||
return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y; | |||||
} | } | ||||
/* Check for mouse press and release events */ | /* Check for mouse press and release events */ | ||||
@@ -427,7 +469,14 @@ static unsigned int _lowlevel_event(void) | |||||
break; | break; | ||||
} | } | ||||
return CACA_EVENT_MOUSE_MOTION | (mevent.x << 12) | mevent.y; | |||||
if(mouse_x == (unsigned int)mevent.x && | |||||
mouse_y == (unsigned int)mevent.y) | |||||
return _pop_event(); | |||||
mouse_x = mevent.x; | |||||
mouse_y = mevent.y; | |||||
return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y; | |||||
} | } | ||||
event = CACA_EVENT_KEY_PRESS; | event = CACA_EVENT_KEY_PRESS; | ||||
@@ -492,11 +541,18 @@ static unsigned int _lowlevel_event(void) | |||||
if(intkey == 0x3e9) | if(intkey == 0x3e9) | ||||
{ | { | ||||
int button = (SLang_getkey() - ' ' + 1) & 0xf; | int button = (SLang_getkey() - ' ' + 1) & 0xf; | ||||
int x = SLang_getkey() - '!'; | |||||
int y = SLang_getkey() - '!'; | |||||
unsigned int x = SLang_getkey() - '!'; | |||||
unsigned int y = SLang_getkey() - '!'; | |||||
_push_event(CACA_EVENT_MOUSE_PRESS | button); | _push_event(CACA_EVENT_MOUSE_PRESS | button); | ||||
_push_event(CACA_EVENT_MOUSE_RELEASE | button); | _push_event(CACA_EVENT_MOUSE_RELEASE | button); | ||||
return CACA_EVENT_MOUSE_MOTION | (x << 12) | (y << 0); | |||||
if(mouse_x == x && mouse_y == y) | |||||
return _pop_event(); | |||||
mouse_x = x; | |||||
mouse_y = y; | |||||
return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y; | |||||
} | } | ||||
event = CACA_EVENT_KEY_PRESS; | event = CACA_EVENT_KEY_PRESS; | ||||
@@ -551,55 +607,70 @@ static unsigned int _lowlevel_event(void) | |||||
INPUT_RECORD rec; | INPUT_RECORD rec; | ||||
DWORD num; | DWORD num; | ||||
GetNumberOfConsoleInputEvents(win32_hin, &num); | |||||
if(num == 0) | |||||
return CACA_EVENT_NONE; | |||||
ReadConsoleInput(win32_hin, &rec, 1, &num); | |||||
if(rec.EventType == KEY_EVENT) | |||||
for( ; ; ) | |||||
{ | { | ||||
if(rec.Event.KeyEvent.bKeyDown) | |||||
event = CACA_EVENT_KEY_PRESS; | |||||
else | |||||
event = CACA_EVENT_KEY_RELEASE; | |||||
GetNumberOfConsoleInputEvents(win32_hin, &num); | |||||
if(num == 0) | |||||
break; | |||||
if(rec.Event.KeyEvent.uChar.AsciiChar) | |||||
return event | rec.Event.KeyEvent.uChar.AsciiChar; | |||||
} | |||||
else if(rec.EventType == MOUSE_EVENT) | |||||
{ | |||||
if(rec.Event.MouseEvent.dwEventFlags == 0) | |||||
ReadConsoleInput(win32_hin, &rec, 1, &num); | |||||
if(rec.EventType == KEY_EVENT) | |||||
{ | { | ||||
if(rec.Event.MouseEvent.dwButtonState & 0x01) | |||||
return CACA_EVENT_MOUSE_PRESS | 0x000001; | |||||
if(rec.Event.KeyEvent.bKeyDown) | |||||
event = CACA_EVENT_KEY_PRESS; | |||||
else | |||||
event = CACA_EVENT_KEY_RELEASE; | |||||
if(rec.Event.MouseEvent.dwButtonState & 0x02) | |||||
return CACA_EVENT_MOUSE_PRESS | 0x000002; | |||||
if(rec.Event.KeyEvent.uChar.AsciiChar) | |||||
return event | rec.Event.KeyEvent.uChar.AsciiChar; | |||||
} | } | ||||
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED) | |||||
if(rec.EventType == MOUSE_EVENT) | |||||
{ | { | ||||
return CACA_EVENT_MOUSE_MOTION | |||||
| (rec.Event.MouseEvent.dwMousePosition.X << 12) | |||||
| (rec.Event.MouseEvent.dwMousePosition.Y); | |||||
} | |||||
if(rec.Event.MouseEvent.dwEventFlags == 0) | |||||
{ | |||||
if(rec.Event.MouseEvent.dwButtonState & 0x01) | |||||
return CACA_EVENT_MOUSE_PRESS | 0x000001; | |||||
if(rec.Event.MouseEvent.dwButtonState & 0x02) | |||||
return CACA_EVENT_MOUSE_PRESS | 0x000002; | |||||
} | |||||
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED) | |||||
{ | |||||
COORD pos = rec.Event.MouseEvent.dwMousePosition; | |||||
if(mouse_x == (unsigned int)pos.X && | |||||
mouse_y == (unsigned int)pos.Y) | |||||
continue; | |||||
mouse_x = pos.X; | |||||
mouse_y = pos.Y; | |||||
return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y; | |||||
} | |||||
#if 0 | #if 0 | ||||
else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) | |||||
{ | |||||
cout << rec.Event.MouseEvent.dwMousePosition.X << "," << | |||||
rec.Event.MouseEvent.dwMousePosition.Y << " " << flush; | |||||
} | |||||
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED) | |||||
{ | |||||
SetConsoleCursorPosition(hOut, | |||||
WheelWhere); | |||||
if(rec.Event.MouseEvent.dwButtonState & 0xFF000000) | |||||
cout << "Down" << flush; | |||||
else | |||||
cout << "Up " << flush; | |||||
} | |||||
else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) | |||||
{ | |||||
cout << rec.Event.MouseEvent.dwMousePosition.X << "," << | |||||
rec.Event.MouseEvent.dwMousePosition.Y << " " << flush; | |||||
} | |||||
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED) | |||||
{ | |||||
SetConsoleCursorPosition(hOut, | |||||
WheelWhere); | |||||
if(rec.Event.MouseEvent.dwButtonState & 0xFF000000) | |||||
cout << "Down" << flush; | |||||
else | |||||
cout << "Up " << flush; | |||||
} | |||||
#endif | #endif | ||||
} | |||||
/* Unknown event */ | |||||
return CACA_EVENT_NONE; | |||||
} | } | ||||
/* No event */ | |||||
return CACA_EVENT_NONE; | return CACA_EVENT_NONE; | ||||
} | } | ||||
else | else | ||||
@@ -78,6 +78,8 @@ typedef unsigned char uint8_t; | |||||
#if !defined(_DOXYGEN_SKIP_ME) | #if !defined(_DOXYGEN_SKIP_ME) | ||||
unsigned int _caca_width = 0; | unsigned int _caca_width = 0; | ||||
unsigned int _caca_height = 0; | unsigned int _caca_height = 0; | ||||
unsigned int _caca_new_width = 0; | |||||
unsigned int _caca_new_height = 0; | |||||
#endif | #endif | ||||
/* | /* | ||||
@@ -154,6 +156,8 @@ static char *conio_screen; | |||||
#if defined(USE_X11) && !defined(_DOXYGEN_SKIP_ME) | #if defined(USE_X11) && !defined(_DOXYGEN_SKIP_ME) | ||||
Display *x11_dpy; | Display *x11_dpy; | ||||
Window x11_window; | Window x11_window; | ||||
long int x11_event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | |||||
| ButtonReleaseMask | PointerMotionMask | StructureNotifyMask; | |||||
int x11_font_width, x11_font_height; | int x11_font_width, x11_font_height; | ||||
static GC x11_gc; | static GC x11_gc; | ||||
static Pixmap x11_pixmap; | static Pixmap x11_pixmap; | ||||
@@ -229,6 +233,8 @@ static enum caca_color _caca_bgcolor = CACA_COLOR_BLACK; | |||||
/* | /* | ||||
* Local functions | * Local functions | ||||
*/ | */ | ||||
static void caca_handle_resize(void); | |||||
#if defined(USE_SLANG) | #if defined(USE_SLANG) | ||||
static void slang_init_palette(void); | static void slang_init_palette(void); | ||||
#endif | #endif | ||||
@@ -796,9 +802,7 @@ int _caca_init_graphics(void) | |||||
XAutoRepeatOff(x11_dpy); | XAutoRepeatOff(x11_dpy); | ||||
#endif | #endif | ||||
XSelectInput(x11_dpy, x11_window, | |||||
KeyPressMask | KeyReleaseMask | ButtonPressMask | |||||
| ButtonReleaseMask | PointerMotionMask); | |||||
XSelectInput(x11_dpy, x11_window, x11_event_mask); | |||||
XSync(x11_dpy, False); | XSync(x11_dpy, False); | ||||
@@ -888,6 +892,9 @@ int _caca_init_graphics(void) | |||||
_caca_scratch_line = malloc(_caca_width + 1); | _caca_scratch_line = malloc(_caca_width + 1); | ||||
_caca_new_width = _caca_width; | |||||
_caca_new_height = _caca_height; | |||||
_caca_delay = 0; | _caca_delay = 0; | ||||
_caca_rendertime = 0; | _caca_rendertime = 0; | ||||
@@ -1162,6 +1169,9 @@ void caca_refresh(void) | |||||
/* Dummy */ | /* Dummy */ | ||||
} | } | ||||
if(_caca_width != _caca_new_width || _caca_height != _caca_new_height) | |||||
caca_handle_resize(); | |||||
/* Wait until _caca_delay + time of last call */ | /* Wait until _caca_delay + time of last call */ | ||||
ticks += _caca_getticks(&timer); | ticks += _caca_getticks(&timer); | ||||
for(ticks += _caca_getticks(&timer); | for(ticks += _caca_getticks(&timer); | ||||
@@ -1181,6 +1191,73 @@ void caca_refresh(void) | |||||
lastticks = 0; | lastticks = 0; | ||||
} | } | ||||
/* | |||||
* XXX: following functions are loca | |||||
*/ | |||||
static void caca_handle_resize(void) | |||||
{ | |||||
unsigned int old_width = _caca_width; | |||||
unsigned int old_height = _caca_height; | |||||
_caca_width = _caca_new_width; | |||||
_caca_height = _caca_new_height; | |||||
free(_caca_empty_line); | |||||
_caca_empty_line = malloc(_caca_width + 1); | |||||
memset(_caca_empty_line, ' ', _caca_width); | |||||
_caca_empty_line[_caca_width] = '\0'; | |||||
free(_caca_scratch_line); | |||||
_caca_scratch_line = malloc(_caca_width + 1); | |||||
#if defined(USE_SLANG) | |||||
if(_caca_driver == CACA_DRIVER_SLANG) | |||||
{ | |||||
} | |||||
else | |||||
#endif | |||||
#if defined(USE_NCURSES) | |||||
if(_caca_driver == CACA_DRIVER_NCURSES) | |||||
{ | |||||
} | |||||
else | |||||
#endif | |||||
#if defined(USE_CONIO) | |||||
if(_caca_driver == CACA_DRIVER_CONIO) | |||||
{ | |||||
} | |||||
else | |||||
#endif | |||||
#if defined(USE_X11) | |||||
if(_caca_driver == CACA_DRIVER_X11) | |||||
{ | |||||
XFreePixmap(x11_dpy, x11_pixmap); | |||||
free(x11_char); | |||||
free(x11_attr); | |||||
x11_pixmap = XCreatePixmap(x11_dpy, x11_window, | |||||
_caca_width * x11_font_width, | |||||
_caca_height * x11_font_height, | |||||
DefaultDepth(x11_dpy, | |||||
DefaultScreen(x11_dpy))); | |||||
x11_char = malloc(_caca_width * _caca_height * sizeof(int)); | |||||
memset(x11_char, 0, _caca_width * _caca_height * sizeof(int)); | |||||
x11_attr = malloc(_caca_width * _caca_height * sizeof(int)); | |||||
memset(x11_attr, 0, _caca_width * _caca_height * sizeof(int)); | |||||
} | |||||
else | |||||
#endif | |||||
#if defined(USE_WIN32) | |||||
if(_caca_driver == CACA_DRIVER_WIN32) | |||||
{ | |||||
} | |||||
else | |||||
#endif | |||||
{ | |||||
/* Dummy */ | |||||
} | |||||
} | |||||
#if defined(USE_SLANG) | #if defined(USE_SLANG) | ||||
static void slang_init_palette(void) | static void slang_init_palette(void) | ||||
{ | { | ||||
@@ -1229,6 +1306,7 @@ static void slang_init_palette(void) | |||||
#if defined(USE_X11) | #if defined(USE_X11) | ||||
static int x11_error_handler(Display *dpy, XErrorEvent *event) | static int x11_error_handler(Display *dpy, XErrorEvent *event) | ||||
{ | { | ||||
/* Ignore the error */ | |||||
return 0; | return 0; | ||||
} | } | ||||
#endif | #endif | ||||