Update qemacs port

Keyboard input now works.
This commit is contained in:
François Revol
2013-03-08 15:33:48 +00:00
parent f4abc79521
commit 87af85b48d

View File

@@ -151,8 +151,8 @@ diff -urN qemacs-0.3.3.org/fbfrender.c qemacs-0.3.3/fbfrender.c
return font;
diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
--- qemacs-0.3.3.org/haiku.cpp 1970-01-01 01:00:00.000000000 +0100
+++ qemacs-0.3.3/haiku.cpp 2013-03-08 02:01:26.908853248 +0100
@@ -0,0 +1,518 @@
+++ qemacs-0.3.3/haiku.cpp 2013-03-08 16:13:59.829947904 +0100
@@ -0,0 +1,864 @@
+/*
+ * Haiku driver for QEmacs
+ * Copyright (c) 2013 François Revol.
@@ -181,33 +181,156 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+
+#include <Application.h>
+#include <Font.h>
+#include <String.h>
+#include <View.h>
+#include <Window.h>
+
+extern QEDisplay haiku_dpy;
+
+static int force_tty = 0;
+
+static int font_xsize;
+
+class QEWindow;
+class QEView;
+
+/* state of a single window */
+typedef struct WindowState {
+ BWindow *w;
+ BView *v;
+ BFont font;
+ int events_rd;
+ int events_wr;
+} WindowState;
+
+typedef struct QEEventQ {
+ QEEvent ev;
+ struct QEEventQ *next;
+} QEEventQ;
+
+QEEventQ *first_event, *last_event;
+WindowState haiku_ctx;
+static thread_id bapp_thid;
+static int bapp_ref_count = 0;
+static int events_wr;
+
+static void haiku_handle_event(void *opaque);
+
+static status_t bmessage_input(QEWindow *win, QEView *view, BMessage *message)
+{
+ if (!message)
+ return EINVAL;
+ /* push the message into the pipe */
+ if (write(events_wr, &message, sizeof(BMessage *)) < 0)
+ return errno;
+ return B_OK;
+}
+
+class QEWindow: public BWindow
+{
+public:
+ QEWindow(BRect frame, const char *name, QEView *view)
+ :BWindow(frame, name, B_TITLED_WINDOW, 0)
+ ,fView(view)
+ {}
+
+ virtual ~QEWindow() {}
+
+//virtual void Show();
+//virtual void Hide();
+//virtual void Minimize(bool minimize);
+virtual bool QuitRequested();
+virtual void DispatchMessage(BMessage *message, BHandler *handler);
+
+private:
+ QEView *fView;
+};
+
+class QEView: public BView
+{
+public:
+ QEView(BRect frame, const char *name);
+ virtual ~QEView();
+
+#if 0
+virtual void MouseDown(BPoint where);
+virtual void MouseUp(BPoint where);
+virtual void MouseMoved(BPoint where, uint32 code, const BMessage *a_message);
+#endif
+virtual void KeyDown(const char *bytes, int32 numBytes);
+virtual void KeyUp(const char *bytes, int32 numBytes);
+virtual void Draw(BRect updateRect);
+#if 0
+virtual void WindowActivated(bool state);
+virtual void FrameResized(float new_width, float new_height);
+virtual void MessageReceived(BMessage *message);
+#endif
+};
+
+
+bool QEWindow::QuitRequested()
+{
+ BMessage *message = new BMessage(B_QUIT_REQUESTED);
+ bmessage_input(this, NULL, message);
+ return false;
+}
+
+void QEWindow::DispatchMessage(BMessage *message, BHandler *handler)
+{
+ uint32 mods;
+ switch (message->what) {
+ case B_KEY_DOWN:
+ if ((message->FindInt32("modifiers", (int32 *)&mods) == B_OK) &&
+ (mods & B_COMMAND_KEY)) {
+ /* BWindow swallows KEY_DOWN when ALT is down...
+ * so this hack is needed.
+ */
+ fView->KeyDown(NULL, 0);
+ return;
+ }
+ break;
+ case B_UNMAPPED_KEY_DOWN:
+ case B_UNMAPPED_KEY_UP:
+ case B_KEY_UP:
+ //message->PrintToStream();
+ break;
+ }
+ BWindow::DispatchMessage(message, handler);
+}
+
+QEView::QEView(BRect frame, const char *name)
+ :BView(frame, name, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_FRAME_EVENTS)
+{
+ SetViewColor(0,255,0);
+}
+
+QEView::~QEView()
+{
+}
+
+void QEView::KeyDown(const char *bytes, int32 numBytes)
+{
+ BMessage *message = Window()->DetachCurrentMessage();
+ //message->PrintToStream();
+ bmessage_input(NULL, this, message);
+}
+
+void QEView::KeyUp(const char *bytes, int32 numBytes)
+{
+ uint32 mods;
+ BMessage *message = Window()->DetachCurrentMessage();
+ //message->PrintToStream();
+ bmessage_input(NULL, this, message);
+}
+
+void QEView::Draw(BRect updateRect)
+{
+ BMessage *message;
+ message = new BMessage(_UPDATE_);
+ message->AddRect("update_rect", updateRect);
+ bmessage_input(NULL, this, message);
+}
+
+
+
+static int haiku_probe(void)
+{
+ if (force_tty)
+ return 0;
+ return 1;
+}
+
@@ -277,17 +400,32 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+ s->priv_data = ctx;
+ s->media = CSS_MEDIA_SCREEN;
+
+ int event_pipe[2];
+ if (pipe(event_pipe) < 0)
+ return -1;
+ fcntl(event_pipe[0], F_SETFD, FD_CLOEXEC);
+ fcntl(event_pipe[1], F_SETFD, FD_CLOEXEC);
+
+ ctx->events_rd = event_pipe[0];
+ ctx->events_wr = events_wr = event_pipe[1];
+
+ set_read_handler(event_pipe[0], haiku_handle_event, s);
+
+
+ ctx->font = BFont(be_fixed_font);
+
+ font_height height;
+ ctx->font.GetHeight(&height);
+
+ font_xsize = (int)ctx->font.StringWidth("n");
+printf("sw(n) = %f sz = %f\n", ctx->font.StringWidth("n"), ctx->font.Size());
+ font_ysize = (int)(height.ascent + height.descent + 1);
+ font_ysize = (int)(height.ascent + height.descent + height.leading);
+
+ xsize = 80 * font_xsize;
+ ysize = 25 * font_ysize;
+ if (w == 0)
+ w = 80;
+ if (h == 0)
+ h = 25;
+ xsize = w * font_xsize;
+ ysize = h * font_ysize;
+
+ s->width = xsize;
+ s->height = ysize;
@@ -300,13 +438,16 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+
+ BRect frame(0, 0, s->width - 1, s->height - 1);
+
+ ctx->v = new BView(frame, "qemacs", B_FOLLOW_ALL, B_WILL_DRAW);
+ QEView *v = new QEView(frame, "qemacs");
+ ctx->v = v;
+
+ frame.OffsetTo(200, 200);
+
+ ctx->w = new BWindow(frame, "qemacs", B_TITLED_WINDOW, 0);
+ ctx->w = new QEWindow(frame, "qemacs", v);
+ ctx->w->AddChild(ctx->v);
+ ctx->v->MakeFocus();
+ ctx->v->SetViewColor(B_TRANSPARENT_COLOR);
+ ctx->v->SetDrawingMode(B_OP_OVER);
+
+ ctx->w->Show();
+
@@ -540,11 +681,206 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+}
+#endif
+
+/* called when an BMessage is forwarded. dispatch events to qe_handle_event() */
+static void haiku_handle_event(void *opaque)
+{
+ QEditScreen *s = (QEditScreen *)opaque;
+ WindowState *ctx = (WindowState *)s->priv_data;
+ unsigned char buf[16];
+ bigtime_t timestamp_ms;
+ BMessage *event;
+ //fprintf(stderr, "%s()\n", __FUNCTION__);
+/*
+ KeySym keysym;
+*/
+ int shift, ctrl, meta, len, key = 0;
+ QEEvent ev1, *ev = &ev1;
+
+ if (read(ctx->events_rd, &event, sizeof(BMessage *)) < sizeof(BMessage *))
+ return;
+ //event->PrintToStream();
+
+ switch(event->what) {
+ case B_QUIT_REQUESTED:
+
+ // cancel pending operation
+ ev->key_event.type = QE_KEY_EVENT;
+ ev->key_event.key = KEY_CTRL('g');
+ qe_handle_event(ev);
+
+ // simulate C-x C-c
+ ev->key_event.type = QE_KEY_EVENT;
+ ev->key_event.key = KEY_CTRL('x');
+ qe_handle_event(ev);
+ ev->key_event.type = QE_KEY_EVENT;
+ ev->key_event.key = KEY_CTRL('c');
+ qe_handle_event(ev);
+ break;
+
+ case _UPDATE_:
+ // TODO: flush queued
+ ev->expose_event.type = QE_EXPOSE_EVENT;
+ qe_handle_event(ev);
+ break;
+
+ case B_KEY_UP:
+ break;
+
+ case B_KEY_DOWN:
+ {
+ unsigned int mods = 0;
+ uint32 state;
+ //event->PrintToStream();
+ uint32 scancode;
+ uint32 raw_char;
+ const char *bytes;
+ char buff[6];
+ int numbytes = 0;
+ int i;
+
+ if (event->FindInt64("when", &timestamp_ms) < B_OK)
+ timestamp_ms = 0LL;
+ if (event->FindInt32("modifiers", (int32 *)&state) < B_OK)
+ state = modifiers();
+ if (event->FindInt32("key", (int32 *)&scancode) < B_OK)
+ scancode = 0;
+ if (event->FindInt32("raw_char", (int32 *)&raw_char) < B_OK)
+ raw_char = 0;
+
+ /* check for byte[] first,
+ because C-space gives bytes="" (and byte[0] = '\0') */
+ for (i = 0; i < 5; i++) {
+ buff[i] = '\0';
+ if (event->FindInt8("byte", i, (int8 *)&buff[i]) < B_OK)
+ break;
+ }
+
+ if (i) {
+ bytes = buff;
+ numbytes = i;
+ } else if (event->FindString("bytes", &bytes) < B_OK)
+ bytes = "";
+
+ if (!numbytes)
+ numbytes = strlen(bytes);
+
+ shift = (state & B_SHIFT_KEY);
+ ctrl = (state & B_CONTROL_KEY);
+ meta = (state & (B_LEFT_OPTION_KEY | B_COMMAND_KEY));
+
+ //fprintf(stderr, "%cshift %cctrl %cmeta numbytes %d \n", shift ? ' ' : '!', ctrl ? ' ' : '!', meta ? ' ' : '!', numbytes);
+
+ char byte = 0;
+ if (numbytes == 1) {
+ byte = bytes[0];
+ if (state & B_CONTROL_KEY)
+ byte = (char)raw_char;
+ switch (byte) {
+ case B_BACKSPACE:
+ key = KEY_BACKSPACE;
+ if (meta)
+ key = KEY_META(KEY_BACKSPACE);
+ break;
+ case B_TAB:
+ key = KEY_TAB;
+ break;
+ case B_ENTER:
+ key = KEY_RET;
+ break;
+ case B_ESCAPE:
+ key = KEY_ESC;
+ break;
+ case B_SPACE:
+ key = KEY_SPC;
+ break;
+ case B_DELETE:
+ key = KEY_DELETE;
+ break;
+ case B_INSERT:
+ key = KEY_INSERT;
+ break;
+ case B_HOME:
+ key = ctrl ? KEY_CTRL_HOME : KEY_HOME;
+ break;
+ case B_END:
+ key = ctrl ? KEY_CTRL_END : KEY_END;
+ break;
+ case B_PAGE_UP:
+ key = KEY_PAGEUP;
+ break;
+ case B_PAGE_DOWN:
+ key = KEY_PAGEDOWN;
+ break;
+ case B_LEFT_ARROW:
+ key = ctrl ? KEY_CTRL_LEFT : KEY_LEFT;
+ break;
+ case B_RIGHT_ARROW:
+ key = ctrl ? KEY_CTRL_RIGHT : KEY_RIGHT;
+ break;
+ case B_UP_ARROW:
+ key = KEY_UP;
+ break;
+ case B_DOWN_ARROW:
+ key = KEY_DOWN;
+ break;
+ case B_FUNCTION_KEY:
+ switch (scancode) {
+ case B_F1_KEY:
+ case B_F2_KEY:
+ case B_F3_KEY:
+ case B_F4_KEY:
+ case B_F5_KEY:
+ case B_F6_KEY:
+ case B_F7_KEY:
+ case B_F8_KEY:
+ case B_F9_KEY:
+ case B_F10_KEY:
+ case B_F11_KEY:
+ case B_F12_KEY:
+ key = KEY_F1 + scancode - B_F1_KEY;
+ break;
+ case B_PRINT_KEY:
+ case B_SCROLL_KEY:
+ case B_PAUSE_KEY:
+ default:
+ break;
+ }
+ break;
+ case 0:
+ break;
+ default:
+ if (byte >= ' ' && byte <= '~')
+ if (meta)
+ key = KEY_META(' ') + byte - ' ';
+ else if (ctrl)
+ key = KEY_CTRL(byte);
+ else
+ key = byte;
+
+ }
+ } else {
+ const char *p = bytes;
+ key = utf8_decode(&p);
+ }
+
+ got_key:
+ if (key) {
+ ev->key_event.type = QE_KEY_EVENT;
+ ev->key_event.key = key;
+ qe_handle_event(ev);
+ }
+ }
+ break;
+ }
+
+ delete event;
+}
+
+static void haiku_fill_rectangle(QEditScreen *s,
+ int x1, int y1, int w, int h, QEColor color)
+{
+ WindowState *ctx = (WindowState *)s->priv_data;
+ fprintf(stderr, "%s()\n", __FUNCTION__);
+ //fprintf(stderr, "%s()\n", __FUNCTION__);
+
+ /* XXX: suppress XOR mode */
+ if (color == QECOLOR_XOR)
@@ -565,7 +901,7 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+static QEFont *haiku_open_font(QEditScreen *s, int style, int size)
+{
+ WindowState *ctx = (WindowState *)s->priv_data;
+ fprintf(stderr, "%s()\n", __FUNCTION__);
+ //fprintf(stderr, "%s()\n", __FUNCTION__);
+ QEFont *font;
+
+ font = (QEFont *)malloc(sizeof(QEFont));
@@ -578,7 +914,7 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+ font_height height;
+ f->GetHeight(&height);
+ font->ascent = (int)height.ascent;
+ font->descent = (int)height.descent;
+ font->descent = (int)(height.descent + height.leading);
+ font->priv_data = f;
+ return font;
+}
@@ -611,7 +947,7 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+ WindowState *ctx = (WindowState *)s->priv_data;
+ BFont *f = (BFont *)(font->priv_data);
+ int i;
+ fprintf(stderr, "%s()\n", __FUNCTION__);
+ //fprintf(stderr, "%s()\n", __FUNCTION__);
+
+ /* XXX: suppress XOR mode */
+ if (color == QECOLOR_XOR)
@@ -625,16 +961,19 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+ ctx->v->SetHighColor(c);
+ ctx->v->SetLowColor(B_TRANSPARENT_COLOR);
+ ctx->v->SetFont(f);
+ ctx->v->MovePenTo(x1, y);
+ ctx->v->MovePenTo(x1, y - 1);
+
+ char buf[10];
+ unsigned int cc;
+
+ BString text;
+ for(i=0;i<len;i++) {
+ cc = str[i];
+ unicode_to_charset((unsigned char *)buf, cc, &charset_utf8);
+ ctx->v->DrawString(buf);
+ text << buf;
+ //ctx->v->DrawString(buf);
+ }
+ ctx->v->DrawString(text.String());
+
+ ctx->v->UnlockLooper();
+
@@ -665,8 +1004,15 @@ diff -urN qemacs-0.3.3.org/haiku.cpp qemacs-0.3.3/haiku.cpp
+ NULL, /* no selection handling */
+};
+
+static CmdOptionDef cmd_options[] = {
+ { "nw", NULL, CMD_OPT_BOOL, "force tty terminal usage",
+ {int_ptr: &force_tty} },
+ { NULL },
+};
+
+int haiku_init(void)
+{
+ qe_register_cmd_line_options(cmd_options);
+ return qe_register_display(&haiku_dpy);
+}
+