mudgangster

Log | Files | Refs

commit 30d4b625eafbc6264eee00aa41a4327c99d151ce
parent 6ec5c0dba5f5750a78d4e793d3a372b1ed9e1f24
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Thu,  6 Sep 2018 10:07:13 +0300

Handle X events entirely from C, use deferred double buffering

Diffstat:
src/lua/chat.lua | 1-
src/lua/main.lua | 5+----
src/lua/status.lua | 2--
src/lua/utils.lua | 2--
src/script.cc | 11+----------
src/textbox.cc | 2--
src/ui.h | 5-----
src/x11.cc | 133+++++++++++++++++++++++++++++++++++++++++--------------------------------------
8 files changed, 71 insertions(+), 90 deletions(-)

diff --git a/src/lua/chat.lua b/src/lua/chat.lua @@ -110,7 +110,6 @@ local function dataHandler( client, loop, watcher ) end assert( coroutine.resume( client.handler, data ) ) - mud.handleXEvents() end function mud.chatns( form, ... ) diff --git a/src/lua/main.lua b/src/lua/main.lua @@ -11,8 +11,7 @@ require( "event" ) local script = require( "script" ) local handlers = require( "handlers" ) -local handleXEvents, - printMain, newlineMain, drawMain, +local printMain, newlineMain, drawMain, printChat, newlineChat, drawChat, setHandlers, urgent, setStatus, sock_connect, sock_send, sock_close, @@ -44,6 +43,4 @@ require( "status" ).init( setStatus ) setHandlers( handlers.input, handlers.macro, handlers.close, socket_data_handler, handlers.interval ) -mud.handleXEvents = handleXEvents - script.load() diff --git a/src/lua/status.lua b/src/lua/status.lua @@ -35,8 +35,6 @@ local function drawBar() end setStatus( status ) - - mud.handleXEvents() end function mud.bar( priority ) diff --git a/src/lua/utils.lua b/src/lua/utils.lua @@ -141,8 +141,6 @@ local function genericPrint( message, main, chat ) if chat then mud.drawChat() end - - mud.handleXEvents() end function mud.print( form, ... ) diff --git a/src/script.cc b/src/script.cc @@ -88,11 +88,6 @@ void script_fire_intervals() { namespace { -extern "C" int mud_handleXEvents( lua_State * ) { - ui_handleXEvents(); - return 0; -} - template< typename F > static void generic_print( F * f, lua_State * L ) { const char * str = luaL_checkstring( L, 1 ); @@ -243,8 +238,6 @@ extern "C" int luaopen_lfs( lua_State * L ); #endif void script_init() { - mud_handleXEvents( NULL ); // TODO: why is this here? - lua = luaL_newstate(); luaL_openlibs( lua ); @@ -265,8 +258,6 @@ void script_init() { exit( 1 ); } - lua_pushcfunction( lua, mud_handleXEvents ); - lua_pushcfunction( lua, mud_printMain ); lua_pushcfunction( lua, mud_newlineMain ); lua_pushcfunction( lua, mud_drawMain ); @@ -287,7 +278,7 @@ void script_init() { lua_pushcfunction( lua, mud_now ); - pcall( 14, "Error running main.lua" ); + pcall( 13, "Error running main.lua" ); } void script_term() { diff --git a/src/textbox.cc b/src/textbox.cc @@ -194,6 +194,4 @@ void textbox_draw( const TextBox * tb ) { lines_drawn++; rows_drawn += line_rows; } - - ui_dirty( tb->x, tb->y, tb->w, tb->h ); } diff --git a/src/ui.h b/src/ui.h @@ -21,14 +21,10 @@ enum Colour { COLOUR_CURSOR, }; -void ui_handleXEvents(); // TODO: very x11 specific! - void ui_draw_status(); void ui_clear_status(); void ui_statusAdd( char c, Colour fg, bool bold ); -void ui_draw(); - void ui_main_draw(); void ui_main_newline(); void ui_main_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ); @@ -39,7 +35,6 @@ void ui_chat_print( const char * str, size_t len, Colour fg, Colour bg, bool bol void ui_fill_rect( int left, int top, int width, int height, Colour colour, bool bold ); void ui_draw_char( int left, int top, char c, Colour colour, bool bold, bool bold_font = false ); -void ui_dirty( int left, int top, int width, int height ); void ui_get_font_size( int * fw, int * fh ); diff --git a/src/x11.cc b/src/x11.cc @@ -92,8 +92,8 @@ struct { int max_width, max_height; int depth; - // bool dirty; - // int dirty_left, dirty_top, dirty_right, dirty_bottom; + bool dirty; + int dirty_left, dirty_top, dirty_right, dirty_bottom; bool has_focus; } UI; @@ -167,9 +167,29 @@ static void set_fg( Colour colour, bool bold ) { XSetForeground( UI.display, UI.gc, c ); } +static void make_dirty( int left, int top, int width, int height ) { + int right = left + width; + int bottom = top + height; + + if( !UI.dirty ) { + UI.dirty = true; + UI.dirty_left = left; + UI.dirty_top = top; + UI.dirty_right = right; + UI.dirty_bottom = bottom; + } + else { + UI.dirty_left = min( UI.dirty_left, left ); + UI.dirty_top = min( UI.dirty_top, top ); + UI.dirty_right = max( UI.dirty_right, right ); + UI.dirty_bottom = max( UI.dirty_bottom, bottom ); + } +} + void ui_fill_rect( int left, int top, int width, int height, Colour colour, bool bold ) { set_fg( colour, bold ); XFillRectangle( UI.display, UI.back_buffer, UI.gc, left, top, width, height ); + make_dirty( left, top, width, height ); } void ui_draw_char( int left, int top, char c, Colour colour, bool bold, bool bold_font ) { @@ -329,28 +349,8 @@ void ui_draw_char( int left, int top, char c, Colour colour, bool bold, bool bol XSetFont( UI.display, UI.gc, ( bold || bold_font ? Style.fontBold : Style.font ).font->fid ); set_fg( colour, bold ); XDrawString( UI.display, UI.back_buffer, UI.gc, left, top + Style.font.ascent + SPACING, &c, 1 ); -} - -void ui_dirty( int left, int top, int width, int height ) { - XCopyArea( UI.display, UI.back_buffer, UI.window, UI.gc, left, top, width, height, left, top ); - // int right = left + width; - // int bottom = top + height; - // - // printf( "make dirty %d %d %d %d\n", left, top, right, bottom ); - // if( !UI.dirty ) { - // UI.dirty = true; - // UI.dirty_left = left; - // UI.dirty_top = top; - // UI.dirty_right = right; - // UI.dirty_bottom = bottom; - // return; - // } - // - // UI.dirty_left = min( UI.dirty_left, left ); - // UI.dirty_top = min( UI.dirty_top, top ); - // UI.dirty_right = max( UI.dirty_right, right ); - // UI.dirty_bottom = max( UI.dirty_bottom, bottom ); + make_dirty( left, top, Style.font.width, Style.font.height + SPACING ); } static Atom wmDeleteWindow; @@ -395,15 +395,11 @@ void ui_draw_status() { int y = UI.height - ( PADDING * 3 ) - Style.font.height * 2 - SPACING; ui_draw_char( x, y, sc.c, sc.fg, sc.bold ); } - - ui_dirty( 0, UI.height - ( PADDING * 4 ) - ( Style.font.height * 2 ), UI.width, Style.font.height + ( PADDING * 2 ) ); } void draw_input() { InputBuffer input = input_get_buffer(); - XSetFont( UI.display, UI.gc, Style.font.font->fid ); - int top = UI.height - PADDING - Style.font.height; ui_fill_rect( PADDING, top, UI.width - PADDING * 2, Style.font.height, COLOUR_BG, false ); @@ -415,8 +411,6 @@ void draw_input() { if( input.cursor_pos < input.len ) { ui_draw_char( PADDING + input.cursor_pos * Style.font.width, top - SPACING, input.buf[ input.cursor_pos ], COLOUR_BG, false ); } - - ui_dirty( PADDING, UI.height - ( PADDING + Style.font.height ), UI.width - PADDING * 2, Style.font.height ); } void ui_draw() { @@ -430,8 +424,6 @@ void ui_draw() { int spacerY = ( 2 * PADDING ) + ( Style.font.height + SPACING ) * CHAT_ROWS; ui_fill_rect( 0, spacerY, UI.width, 1, COLOUR_STATUSBG, false ); - - ui_dirty( 0, 0, UI.width, UI.height ); } static void event_mouse_down( XEvent * xevent ) { @@ -734,20 +726,23 @@ void ui_handleXEvents() { event_names[ FocusOut ] = "FocusOut"; event_names[ FocusIn ] = "FocusIn"; - while( XPending( UI.display ) ) { - XEvent event; - XNextEvent( UI.display, &event ); + do { + while( XPending( UI.display ) ) { + XEvent event; + XNextEvent( UI.display, &event ); - if( event_handlers[ event.type ] != NULL ) { - // printf( "%s\n", event_names[ event.type ] ); - event_handlers[ event.type ]( &event ); + if( event_handlers[ event.type ] != NULL ) { + // printf( "%s\n", event_names[ event.type ] ); + event_handlers[ event.type ]( &event ); + } } - } - // if( UI.dirty ) { - // XCopyArea( UI.display, UI.back_buffer, UI.window, UI.gc, UI.dirty_left, UI.dirty_top, UI.dirty_right - UI.dirty_left, UI.dirty_bottom - UI.dirty_top, UI.dirty_left, UI.dirty_top ); - // UI.dirty = false; - // } + if( UI.dirty ) { + XCopyArea( UI.display, UI.back_buffer, UI.window, UI.gc, UI.dirty_left, UI.dirty_top, UI.dirty_right - UI.dirty_left, UI.dirty_bottom - UI.dirty_top, UI.dirty_left, UI.dirty_top ); + UI.dirty = false; + ui_handleXEvents(); + } + } while( UI.dirty ); } static MudFont loadFont( const char * fontStr ) { @@ -805,6 +800,9 @@ void ui_init() { s.in_use = false; } + int default_width = 800; + int default_height = 600; + UI = { }; textbox_init( &UI.main_text, SCROLLBACK_SIZE ); @@ -829,7 +827,7 @@ void ui_init() { attr.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; attr.colormap = UI.colorMap; - UI.window = XCreateWindow( UI.display, root, 0, 0, 800, 600, 0, UI.depth, InputOutput, visual, CWBackPixel | CWEventMask | CWColormap, &attr ); + UI.window = XCreateWindow( UI.display, root, 0, 0, default_height, default_width, 0, UI.depth, InputOutput, visual, CWBackPixel | CWEventMask | CWColormap, &attr ); UI.gc = XCreateGC( UI.display, UI.window, 0, NULL ); XWMHints * hints = XAllocWMHints(); @@ -844,6 +842,13 @@ void ui_init() { wmDeleteWindow = XInternAtom( UI.display, "WM_DELETE_WINDOW", false ); XSetWMProtocols( UI.display, UI.window, &wmDeleteWindow, 1 ); + + XEvent xev; + xev.xconfigure.width = default_width; + xev.xconfigure.height = default_height; + event_resize( &xev ); + + ui_handleXEvents(); } void ui_main_draw() { @@ -912,6 +917,8 @@ static Socket * socket_from_fd( int fd ) { } void event_loop() { + ui_handleXEvents(); + while( !closing ) { pollfd fds[ ARRAY_COUNT( sockets ) + 1 ] = { }; nfds_t num_fds = 1; @@ -933,31 +940,29 @@ void event_loop() { if( ok == 0 ) { script_fire_intervals(); - continue; } - - for( size_t i = 1; i < ARRAY_COUNT( fds ); i++ ) { - if( fds[ i ].revents & POLLIN ) { - Socket * sock = socket_from_fd( fds[ i ].fd ); - assert( sock != NULL ); - - char buf[ 8192 ]; - size_t n; - TCPRecvResult res = net_recv( sock->sock, buf, sizeof( buf ), &n ); - if( res == TCP_OK ) { - script_socketData( sock, buf, n ); - } - else if( res == TCP_CLOSED ) { - script_socketData( sock, NULL, 0 ); - } - else { - FATAL( "net_recv" ); + else { + for( size_t i = 1; i < ARRAY_COUNT( fds ); i++ ) { + if( fds[ i ].revents & POLLIN ) { + Socket * sock = socket_from_fd( fds[ i ].fd ); + assert( sock != NULL ); + + char buf[ 8192 ]; + size_t n; + TCPRecvResult res = net_recv( sock->sock, buf, sizeof( buf ), &n ); + if( res == TCP_OK ) { + script_socketData( sock, buf, n ); + } + else if( res == TCP_CLOSED ) { + script_socketData( sock, NULL, 0 ); + } + else { + FATAL( "net_recv" ); + } } } } - if( fds[ 0 ].events & POLLIN ) { - ui_handleXEvents(); - } + ui_handleXEvents(); } }