Results 1 to 8 of 8

Thread: poll event?

  1. #1

    Default poll event?

    Hi,
    I would like to know if there is a method to get events from a function call instead of from a callback?
    Callbacks are usually fine, and make things easy, but in some situations callbacks make things more complicated.
    Other multimedia libs like SDL and SFML provide a pollEvent function, it seems ClanLib do not.
    In case I'm wrong, could you tell me where is the equivalent for poll-event?
    In case I'm right, could you add a poll-event in a future release?

    Thanks

  2. #2
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Bergen, Norway
    Posts
    588

    Default

    http://clanlib.org/wiki/MainDocs:User_Input

    Polling a device is fairly simple and straight forward (just call the appropriate functions), but the actual state of an input device does not always update immediately - in some cases they are updated based on input messages received from the underlying windowing system, which means that they will not update until you have made a call to CL_KeepAlive:rocess(). The following code correctly polls for hitting escape to quit the loop:

    Code:
    CL_DisplayWindow window(640, 480, "Hello Input");
    CL_InputContext ic = window.get_ic();
    CL_InputDevice keyboard = ic.get_keyboard();
    while (true)
    {
    	bool escape_down = keyboard.get_keycode(CL_KEY_ESCAPE);
    	if (escape_down)
    		break;
     
    	CL_KeepAlive::process();
     
    	window.get_gc().clear(CL_Color::white);
    	window.flip();
    	CL_System::sleep(10);
    }

  3. #3

    Default

    No, your code does not get an event, it gets the current state.

    I want to get the events when there are some, and nothing if there are no new events.

  4. #4
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Do you mean like?

    Code:
    	CL_Slot slot_quit = window.sig_window_close().connect(this, &Basic2D::on_window_close);
    
    	// Connect a keyboard handler to on_key_up()
    	CL_Slot slot_input_up = (window.get_ic().get_keyboard()).sig_key_up().connect(this, &Basic2D::on_input_up);
    
    	while(!quit)
    	{
    			CL_KeepAlive::process(0);
    	}
    
    // A key was pressed
    void Basic2D::on_input_up(const CL_InputEvent &key, const CL_InputState &state)
    {
    	if(key.id == CL_KEY_ESCAPE)
    	{
    		quit = true;
    	}
    }
    
    // The window was closed
    void Basic2D::on_window_close()
    {
    	quit = true;
    }
    There are more events - See the Display/Thread example

    Also see CL_Event and inherit CL_EventProvider for advanced event handling
    eg accept_event = CL_Event(new CL_EventProvider_Win32Socket(&socket, CL_EventProvider_Win32Socket::socket_event_read));

    It would take a long time to explain all methods ... but every option is there

  5. #5
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    I believe he is thinking of a system like GetMessage where you get an event structure back, instead of KeepAlive.process dispatching the messages for you.

    There are some problems in adding such a system. First problem is that ClanLib does not internally have any such message structure (our targets dispatch directly). This could be solved by creating one, although I personally have a hard time seeing the advantage in doing manual message dispatching.

    The second problem is iOS and the NSRunLoop. I do not know if SDL supports iOS and if it does how it gets around certain limitations with iOS. The problem here is that iOS requires the application to call a function running the runloop, and this function then never returns. Internally this function dispatches all messages, kinda like having a KeepAlive.process function that never returns and now your app is entirely driven by handling callbacks.

  6. #6
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    Oh by the way. Maybe we should rename KeepAlive to RunLoop in 3.0? It seems a better name for it.

  7. #7

    Default

    Quote Originally Posted by rombust View Post
    Do you mean like?
    No, read again my question: I said without callbacks.

    The callback mechanism is indeed the problem.
    Well it is not a show-stopper, but it makes things far more complicated.

    Quote Originally Posted by Magnus Norddahl View Post
    I believe he is thinking of a system like GetMessage where you get an event structure back, instead of KeepAlive.process dispatching the messages for you.
    As I said I was looking for something equivalent to the pollEvent functions that are in SDL, SFML and other libs.
    I don't know about internals, but it would be more easy to use for me than a callback.

    Anyway I was just asking in case it was somewhere but I would just not find it in the doc. OK now I know that there is just no equivalent.

    Thanks for your answers.

  8. #8

    Default

    OK, so as a replacement I wrote this piece of code.
    As I'm a beginner in C++ could you have a look at it, and tell me how I could improve it?

    The file "CL_InputEventQueue.cpp":

    Code:
    /* This dirty code is in the public domain */
    
    #include <ClanLib/Display/Window/input_event.h>
    #include <ClanLib/Display/Window/input_device.h>
    
    #include <queue>
    #include <tuple>
    
    static std::queue<
        std::tuple<CL_InputEvent, int, CL_InputDevice::Type>> cl_event_queue;
    
    #define callbacks_for_device(dev) \
    static void cb_##dev##_on_key_down( \
        const CL_InputEvent &key, const CL_InputState &state, int dev_num) \
    { cl_event_queue.push(std::make_tuple(key, dev_num, CL_InputDevice::dev)); } \
    static void cb_##dev##_on_key_up( \
        const CL_InputEvent &key, const CL_InputState &state, int dev_num) \
    { cl_event_queue.push(std::make_tuple(key, dev_num, CL_InputDevice::dev)); } \
    static void cb_##dev##_on_pointer_move( \
        const CL_InputEvent &key, const CL_InputState &state, int dev_num) \
    { cl_event_queue.push(std::make_tuple(key, dev_num, CL_InputDevice::dev)); } \
    static void cb_##dev##_on_axis_move( \
        const CL_InputEvent &key, const CL_InputState &state, int dev_num) \
    { cl_event_queue.push(std::make_tuple(key, dev_num, CL_InputDevice::dev)); }
    
    callbacks_for_device(keyboard)
    callbacks_for_device(pointer)
    callbacks_for_device(joystick)
    callbacks_for_device(tablet)
    callbacks_for_device(unknown)
    
    /* TODO:
    static void cb_on_window_close() {}
      CL_Slot slot_quit = window.sig_window_close().connect(cb_on_window_close);
    */
    
    #include <map>
    static std::map<int, CL_Slot *> sig_conn_slots;
    
    #define SWITCH_CB(cb) \
        void (* cb_##cb)(const CL_InputEvent &key, \
                const CL_InputState &state, int dev_number); \
        switch (dev_t) \
        { \
        case CL_InputDevice::keyboard: cb_##cb = cb_keyboard_##cb; break; \
        case CL_InputDevice::pointer:  cb_##cb = cb_pointer_##cb;  break; \
        case CL_InputDevice::joystick: cb_##cb = cb_joystick_##cb; break; \
        case CL_InputDevice::tablet:   cb_##cb = cb_tablet_##cb;   break; \
        case CL_InputDevice::unknown:  cb_##cb = cb_unknown_##cb;  break; \
        }
    
    void
    CL_InputDevice_sig_key_down_connect(
            CL_InputDevice *inDev, int dev_number)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_input_down = new CL_Slot();
        SWITCH_CB(on_key_down)
        *slot_input_down = inDev->sig_key_down().connect(
                cb_on_key_down, dev_number);
        sig_conn_slots[id] = slot_input_down;
    }
    
    void
    CL_InputDevice_sig_key_down_disconnect(
            CL_InputDevice *inDev)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_input_down = sig_conn_slots[id];
        sig_conn_slots.erase(id);
        delete slot_input_down;
    }
    
    void
    CL_InputDevice_sig_key_up_connect(
            CL_InputDevice *inDev, int dev_number)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_input_up = new CL_Slot();
        SWITCH_CB(on_key_up)
        *slot_input_up = inDev->sig_key_up().connect(
                cb_on_key_up, dev_number);
        sig_conn_slots[id] = slot_input_up;
    }
    
    void
    CL_InputDevice_sig_key_up_disconnect(
            CL_InputDevice *inDev)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_input_up = sig_conn_slots[id];
        sig_conn_slots.erase(id);
        delete slot_input_up;
    }
    
    void
    CL_InputDevice_sig_pointer_move_connect(
            CL_InputDevice *inDev, int dev_number)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_pointer_move = new CL_Slot();
        SWITCH_CB(on_pointer_move)
        *slot_pointer_move = inDev->sig_pointer_move().connect(
                cb_on_pointer_move, dev_number);
        sig_conn_slots[id] = slot_pointer_move;
    }
    
    void
    CL_InputDevice_sig_pointer_move_disconnect(
            CL_InputDevice *inDev)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_pointer_move = sig_conn_slots[id];
        sig_conn_slots.erase(id);
        delete slot_pointer_move;
    }
    
    void
    CL_InputDevice_sig_axis_move_connect(
            CL_InputDevice *inDev, int dev_number)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_axis_move = new CL_Slot();
        SWITCH_CB(on_axis_move)
        *slot_axis_move = inDev->sig_axis_move().connect(
                cb_on_axis_move, dev_number);
        sig_conn_slots[id] = slot_axis_move;
    }
    
    void
    CL_InputDevice_sig_axis_move_disconnect(
            CL_InputDevice *inDev)
    {
        CL_InputDevice::Type dev_t = inDev->get_type();
        int id = static_cast<int>(dev_t);
        CL_Slot *slot_axis_move = sig_conn_slots[id];
        sig_conn_slots.erase(id);
        delete slot_axis_move;
    }
    
    bool
    CL_InputEventQueue_isEmpty()
    {
        return cl_event_queue.empty();
    }
    
    typedef struct {
        CL_InputEvent * input_event;
        int device_number;
        CL_InputDevice::Type device_type;
    } CL_polledEvent;
    
    bool
    CL_InputEventQueue_pollEvent(CL_polledEvent *pEv)
    {
        if (CL_InputEventQueue_isEmpty())
            return false;
    
        pEv->input_event = new CL_InputEvent();
    
        std::tie(
            *pEv->input_event,
            pEv->device_number,
            pEv->device_type) = cl_event_queue.front();
    
        cl_event_queue.pop();
    
        return true;
    }
    The file "CL_InputEventQueue.hpp":

    Code:
    #ifndef _CL_INPUTEVENT_QUEUE_INC
    #define _CL_INPUTEVENT_QUEUE_INC
    
    #include <ClanLib/Display/Window/input_device.h>
    #include <ClanLib/Display/Window/input_event.h>
    
    void CL_InputDevice_sig_key_down_connect(
            CL_InputDevice *inDev, int dev_number);
    
    void CL_InputDevice_sig_key_down_disconnect(
            CL_InputDevice *inDev);
    
    void CL_InputDevice_sig_key_up_connect(
            CL_InputDevice *inDev, int dev_number);
    
    void CL_InputDevice_sig_key_up_disconnect(
            CL_InputDevice *inDev);
    
    void CL_InputDevice_sig_pointer_move_connect(
            CL_InputDevice *inDev, int dev_number);
    
    void CL_InputDevice_sig_pointer_move_disconnect(
            CL_InputDevice *inDev);
    
    void CL_InputDevice_sig_axis_move_connect(
            CL_InputDevice *inDev, int dev_number);
    
    void CL_InputDevice_sig_axis_move_disconnect(
            CL_InputDevice *inDev);
    
    bool CL_InputEventQueue_isEmpty();
    
    typedef struct {
        CL_InputEvent * input_event;
        int device_number;
        CL_InputDevice::Type device_type;
    } CL_polledEvent;
    
    bool CL_InputEventQueue_pollEvent(CL_polledEvent *pEv);
    
    #endif // _CL_INPUTEVENT_QUEUE_INC

Similar Threads

  1. The new idea poll.
    By Nicolas1 in forum Tanked
    Replies: 20
    Last Post: 09-30-2012, 02:31 AM
  2. The banning poll....
    By tankdevil in forum Tanked
    Replies: 8
    Last Post: 06-17-2012, 08:09 PM
  3. Poll:
    By AnthonyS1C in forum Tanked
    Replies: 9
    Last Post: 06-17-2012, 12:56 PM
  4. Poll
    By Yill in forum Dink Smallwood HD
    Replies: 1
    Last Post: 09-02-2003, 10:06 AM
  5. A POLL....
    By Hori in forum Funeral Quest
    Replies: 5
    Last Post: 01-31-2003, 01:55 AM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •