import ctypes

from ctypes import WinDLL, byref, WinError

from ctypes.wintypes import MSG

_user32 = WinDLL("user32")



GetMessage = _user32.GetMessageA

GetMessage.argtypes = [

    ctypes.c_void_p,

    ctypes.c_void_p,

    ctypes.c_uint,

    ctypes.c_uint,

]

TranslateMessage = _user32.TranslateMessage

DispatchMessage = _user32.DispatchMessageA





class _MessageLoop(object):



    def __init__(self):

        self._filters = []



    def insert_filter(self, obj, index=-1):

        self._filters.insert(index, obj)



    def remove_filter(self, obj):

        self._filters.remove(obj)



    def run(self):

        msg = MSG()

        lpmsg = byref(msg)

        while 1:

            ret = GetMessage(lpmsg, 0, 0, 0)

            if ret == -1:

                raise WinError()

            elif ret == 0:

                return # got WM_QUIT

            if not self.filter_message(lpmsg):

                TranslateMessage(lpmsg)

                DispatchMessage(lpmsg)



    def filter_message(self, lpmsg):

        return any(list(filter(lpmsg)) for filter in self._filters)



_messageloop = _MessageLoop()



run = _messageloop.run

insert_filter = _messageloop.insert_filter

remove_filter = _messageloop.remove_filter



__all__ = ["run", "insert_filter", "remove_filter"]

