diff --git a/haiku/button.cpp b/haiku/button.cpp index a58cb781..ff65bbc2 100644 --- a/haiku/button.cpp +++ b/haiku/button.cpp @@ -16,6 +16,17 @@ uiHaikuDefineControl( #define mButtonClicked 0x4E754E75 +static void onClicked(BMessage *msg) +{ + void *bb; + uiButton *b; + + // TODO error check + msg->FindPointer(mControlField, &bb); + b = uiButton(bb); + (*(b->onClicked))(b, b->onClickedData); +} + static void defaultOnClicked(uiButton *b, void *data) { // do nothing @@ -40,10 +51,15 @@ void uiButtonOnClicked(uiButton *b, void (*f)(uiButton *b, void *data), void *da uiButton *uiNewButton(const char *text) { uiButton *b; + BMessage *msg; b = (uiButton *) uiNewControl(uiButtonType()); - b->button = new BButton(text, new BMessage(mButtonClicked)); + uiHaikuRegisterEventHandler(mButtonClicked, onClicked); + msg = new BMessage(mButtonClicked); + msg->AddPointer(mControlField, b); + + b->button = new BButton(text, msg); // TODO hook up events uiButtonOnClicked(b, defaultOnClicked, NULL); diff --git a/haiku/main.cpp b/haiku/main.cpp index e341913b..3e2bfdae 100644 --- a/haiku/main.cpp +++ b/haiku/main.cpp @@ -11,6 +11,7 @@ const char *uiInit(uiInitOptions *o) options = *o; // TODO properly set the MIME type + // TODO andlabs-libui? app = new BApplication("application/x-vnd.andlabs.libui", &err); if (err != B_NO_ERROR) { delete app; diff --git a/haiku/uipriv_haiku.hpp b/haiku/uipriv_haiku.hpp index 9b6c3466..801b651d 100644 --- a/haiku/uipriv_haiku.hpp +++ b/haiku/uipriv_haiku.hpp @@ -18,3 +18,7 @@ extern void singleChildDestroy(struct singleChild *s); extern BLayoutItem *singleChildLayoutItem(struct singleChild *s); extern void singleChildUpdateState(struct singleChild *s); extern void singleChildSetMargined(struct singleChild *s, float inset); + +// TODO make this public? +#define mControlField "libui_uiControl" +// TODO write helper functions? diff --git a/haiku/window.cpp b/haiku/window.cpp index b45f12c3..eadfe83b 100644 --- a/haiku/window.cpp +++ b/haiku/window.cpp @@ -1,11 +1,15 @@ // 18 november 2015 +#include #include "uipriv_haiku.hpp" +using namespace std; class libuiBWindow : public BWindow { public: // C++11! Inherit constructors. using BWindow::BWindow; + virtual void MessageReceived(BMessage *); + uiWindow *w; virtual bool QuitRequested(); }; @@ -31,6 +35,37 @@ uiHaikuDefineControlWithOnDestroy( complain("attempt to use default CommitDestroy() code for uiWindow on Haiku"); // on destroy ) +static map eventHandlers; +typedef map::const_iterator eventHandlerIter; + +void uiHaikuRegisterEventHandler(uint32 what, void (*handler)(BMessage *)) +{ + eventHandlerIter iter; + + // TODO decide a convention for libui internal messages + iter = eventHandlers.find(what); + if (iter == eventHandlers.end()) { // new entry + eventHandlers[what] = handler; + return; + } + if (iter->second != handler) // mismatch + complain("attempt to clobber BMessage::what 0x%08X in uiHaikuRegisterEventHandler()", what); +} + +void libuiBWindow::MessageReceived(BMessage *msg) +{ + eventHandlerIter iter; + + // handle registered events + iter = eventHandlers.find(msg->what); + if (iter != eventHandlers.end()) { + (*(iter->second))(msg); + return; + } + // no event found; defer to BWindow + this->BWindow::MessageReceived(msg); +} + bool libuiBWindow::QuitRequested() { // manually destroy the window ourselves; don't let the default BWindow code do it directly diff --git a/ui_haiku.hpp b/ui_haiku.hpp index db0e0f2b..246d377d 100644 --- a/ui_haiku.hpp +++ b/ui_haiku.hpp @@ -57,6 +57,9 @@ _UI_EXTERN uintmax_t uiHaikuControlType(void); // Don't call it directly; use uiHaikuFinishNewControl() instead. _UI_EXTERN void uiHaikuFinishControl(uiControl *c); +// TODO document this +_UI_EXTERN void uiHaikuRegisterEventHandler(uint32 what, void (*handler)(BMessage *)); + // uiHaikuStrdupText() takes the given string and produces a copy of it suitable for being freed by uiFreeText(). _UI_EXTERN char *uiHaikuStrdupText(const char *);