qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [FYI 8/8] ui: Haiku frontend


From: Andreas Färber
Subject: [Qemu-devel] [FYI 8/8] ui: Haiku frontend
Date: Mon, 20 Sep 2010 00:50:50 +0200

Since Haiku is still in development and raw builds don't contain the
SDL or a VNC client, a native frontend is convenient. mmlr had maintained
a basic one for BeOS/Haiku until the kqemu drop. The code has been ported
to HEAD but is not yet fully updated to match CODING_STYLE.

Cc: Michael Lotz <address@hidden>

Haiku's native APIs are C++ based, so we need a new make rule.
Some enabled GCC warnings are not applicable to C++ code and cause warnings.

Cc: Blue Swirl <address@hidden>

Note that this frontend is another candidate user of a central qemu_main()
prototype, like Cocoa. It would also be candidate for a generic argv check
for non-graphic mode, to be shared with Cocoa.
---
 Makefile      |    2 +
 Makefile.objs |    1 +
 configure     |    1 +
 console.h     |    3 +
 rules.mak     |    6 +-
 ui/haiku.cpp  |  607 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ui/haiku.h    |   96 +++++++++
 vl.c          |   10 +-
 8 files changed, 724 insertions(+), 2 deletions(-)
 create mode 100644 ui/haiku.cpp
 create mode 100644 ui/haiku.h

diff --git a/Makefile b/Makefile
index ab91d42..64eea3e 100644
--- a/Makefile
+++ b/Makefile
@@ -98,6 +98,8 @@ QEMU_CFLAGS+=$(CURL_CFLAGS)
 
 ui/cocoa.o: ui/cocoa.m
 
+ui/haiku.o: ui/haiku.cpp
+
 ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
 
 ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/Makefile.objs b/Makefile.objs
index f702ad4..6ae0e14 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -112,6 +112,7 @@ ui-obj-y += vnc-enc-tight.o vnc-palette.o
 ui-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
 ui-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
 ui-obj-$(CONFIG_COCOA) += cocoa.o
+ui-obj-$(CONFIG_HAIKU) += haiku.o
 ifdef CONFIG_VNC_THREAD
 ui-obj-y += vnc-jobs-async.o
 else
diff --git a/configure b/configure
index 3a0d50e..b533990 100755
--- a/configure
+++ b/configure
@@ -454,6 +454,7 @@ Haiku)
   haiku="yes"
   QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS $QEMU_CFLAGS"
   LIBS="-lposix_error_mapper -lnetwork $LIBS"
+  LIBS="-lstdc++ -lbe -lgame $LIBS"
 ;;
 *)
   audio_drv_list="oss"
diff --git a/console.h b/console.h
index aafb031..9a8268a 100644
--- a/console.h
+++ b/console.h
@@ -364,6 +364,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, 
int no_frame);
 /* cocoa.m */
 void cocoa_display_init(DisplayState *ds, int full_screen);
 
+/* haiku.cpp */
+void haiku_display_init(DisplayState *ds, int full_screen);
+
 /* vnc.c */
 void vnc_display_init(DisplayState *ds);
 void vnc_display_close(DisplayState *ds);
diff --git a/rules.mak b/rules.mak
index c843a13..29481b9 100644
--- a/rules.mak
+++ b/rules.mak
@@ -8,6 +8,7 @@ MAKEFLAGS += -rR
 %.d:
 %.h:
 %.c:
+%.cpp:
 %.m:
 %.mak:
 
@@ -23,6 +24,9 @@ QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
 %.o: %.m
        $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c 
-o $@ $<,"  OBJC  $(TARGET_DIR)$@")
 
+%.o: %.cpp
+       $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c 
-o $@ $<,"  CXX   $(TARGET_DIR)$@")
+
 LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ 
$(1) $(LIBS),"  LINK  $(TARGET_DIR)$@")
 
 %$(EXESUF): %.o
@@ -39,7 +43,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
 cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi
+VPATH_SUFFIXES = %.c %.h %.S %.m %.cpp %.mak %.texi
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath 
$(PATTERN) $1)))
 
 # Generate timestamp files for .h include files
diff --git a/ui/haiku.cpp b/ui/haiku.cpp
new file mode 100644
index 0000000..37b9414
--- /dev/null
+++ b/ui/haiku.cpp
@@ -0,0 +1,607 @@
+/*
+ * QEMU Haiku display driver
+ *
+ * Copyright (c) 2010 Andreas Färber
+ * Copyright (c) 2005-2009 Michael Lotz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "haiku.h"
+
+#include <stdio.h>
+
+#include <Path.h>
+#include <Screen.h>
+#include <WindowScreen.h>
+
+
+extern "C" {
+
+#include "qemu-common.h"
+#include "console.h"
+#include "sysemu.h"
+
+int qemu_main(int argc, char **argv, char** envp);
+
+}
+
+
+QEMUApplication *gApplication;
+QEMUWindow *gWindow;
+QEMUView *gView;
+bool gFullScreen;
+int gWidth = 100;
+int gHeight = 100;
+BPoint gCenter;
+BPoint gPreviousLocation;
+
+
+// Haiku keycode to scancode table
+static const uint8
+haiku_to_pc_key[] = {
+       0x00,   /* 0x00 */                                              0x01,   
/* 0x01 Esc */
+       0x3b,   /* 0x02 F1 */                                   0x3c,   /* 0x03 
F2 */
+       0x3d,   /* 0x04 F3 */                                   0x3e,   /* 0x05 
F4 */
+       0x3f,   /* 0x06 F5 */                                   0x40,   /* 0x07 
F6 */
+       0x41,   /* 0x08 F7 */                                   0x42,   /* 0x09 
F8 */
+       0x43,   /* 0x0a F9 */                                   0x44,   /* 0x0b 
F10 */
+       0x57,   /* 0x0c F11 */                                  0x58,   /* 0x0d 
F12 */
+       0xb7,   /* 0x0e Print Screen */                 0x46,   /* 0x0f Scroll 
Lock */
+       0xc5,   /* 0x10 Pause */                                0x29,   /* 0x11 
Grave */
+       0x02,   /* 0x12 1 */                                    0x03,   /* 0x13 
2 */
+       0x04,   /* 0x14 3 */                                    0x05,   /* 0x15 
4 */
+       0x06,   /* 0x16 5 */                                    0x07,   /* 0x17 
6 */
+       0x08,   /* 0x18 7 */                                    0x09,   /* 0x19 
8 */
+       0x0a,   /* 0x1a 9 */                                    0x0b,   /* 0x1b 
0 */
+       0x0c,   /* 0x1c Minus */                                0x0d,   /* 0x1d 
Equals */
+       0x0e,   /* 0x1e Backspace */                    0xd2,   /* 0x1f Insert 
*/
+       0xc7,   /* 0x20 Home */                                 0xc9,   /* 0x21 
Page Up */
+       0x45,   /* 0x22 Num Lock */                             0xb5,   /* 0x23 
KP Divide */
+       0x37,   /* 0x24 KP Multiply */                  0x4a,   /* 0x25 KP 
Subtract */
+       0x0f,   /* 0x26 Tab */                                  0x10,   /* 0x27 
Q */
+       0x11,   /* 0x28 W */                                    0x12,   /* 0x29 
E */
+       0x13,   /* 0x2a R */                                    0x14,   /* 0x2b 
T */
+       0x15,   /* 0x2c Y */                                    0x16,   /* 0x2d 
U */
+       0x17,   /* 0x2e I */                                    0x18,   /* 0x2f 
O */
+       0x19,   /* 0x30 P */                                    0x1a,   /* 0x31 
Left Bracket */
+       0x1b,   /* 0x32 Right Bracket */                0x2b,   /* 0x33 
Backslash */
+       0xd3,   /* 0x34 Delete */                               0xcf,   /* 0x35 
End */
+       0xd1,   /* 0x36 Page Down */                    0x47,   /* 0x37 KP 7 */
+       0x48,   /* 0x38 KP 8 */                                 0x49,   /* 0x39 
KP 9 */
+       0x4e,   /* 0x3a KP Add */                               0x3a,   /* 0x3b 
Caps Lock */
+       0x1e,   /* 0x3c A */                                    0x1f,   /* 0x3d 
S */
+       0x20,   /* 0x3e D */                                    0x21,   /* 0x3f 
F */
+       0x22,   /* 0x40 G */                                    0x23,   /* 0x41 
H */
+       0x24,   /* 0x42 J */                                    0x25,   /* 0x43 
K */
+       0x26,   /* 0x44 L */                                    0x27,   /* 0x45 
Semicolon */
+       0x28,   /* 0x46 Single Quote */                 0x1c,   /* 0x47 Enter */
+       0x4b,   /* 0x48 KP 4 */                                 0x4c,   /* 0x49 
KP 5 */
+       0x4d,   /* 0x4a KP 6 */                                 0x2a,   /* 0x4b 
Left Shift */
+       0x2c,   /* 0x4c Z */                                    0x2d,   /* 0x4d 
X */
+       0x2e,   /* 0x4e C */                                    0x2f,   /* 0x4f 
V */
+       0x30,   /* 0x50 B */                                    0x31,   /* 0x51 
N */
+       0x32,   /* 0x52 M */                                    0x33,   /* 0x53 
Comma */
+       0x34,   /* 0x54 Period */                               0x35,   /* 0x55 
Slash */
+       0x36,   /* 0x56 Right Shift */                  0xc8,   /* 0x57 Up */
+       0x4f,   /* 0x58 KP 1 */                                 0x50,   /* 0x59 
KP 2 */
+       0x51,   /* 0x5a KP 3 */                                 0x9c,   /* 0x5b 
KP Enter */
+       0x1d,   /* 0x5c Left Control */                 0x38,   /* 0x5d Left 
Alt */
+       0x39,   /* 0x5e Space */                                0xb8,   /* 0x5f 
Right Alt */
+       0x9d,   /* 0x60 Right Control */                0xcb,   /* 0x61 Left */
+       0xd0,   /* 0x62 Down */                                 0xcd,   /* 0x63 
Right */
+       0x52,   /* 0x64 KP 0 */                                 0x53,   /* 0x65 
KP . */
+       0xdb,   /* 0x66 Left Windows */                 0xdc,   /* 0x67 Right 
Windows */
+       0xdd,   /* 0x68 Menu */                                 0x56,   /* 0x69 
*/
+       0x7d,   /* 0x6a Macron */                               0x73,   /* 0x6b 
Backslash */
+       0x7b,   /* 0x6c Muhenkan */                             0x79,   /* 0x6d 
Henkan */
+       0x70,   /* 0x6e Hiragana Katakana */    0x00,   /* 0x6f */
+       0x00,   /* 0x70 */                                              0x00,   
/* 0x71 */
+       0x00,   /* 0x72 */                                              0x00,   
/* 0x73 */
+       0x00,   /* 0x74 */                                              0x00,   
/* 0x75 */
+       0x00,   /* 0x76 */                                              0x00,   
/* 0x77 */
+       0x00,   /* 0x78 */                                              0x00,   
/* 0x79 */
+       0x00,   /* 0x7a */                                              0x00,   
/* 0x7b */
+       0x00,   /* 0x7c */                                              0x00,   
/* 0x7d */
+       0x54,   /* 0x7e Alt SysRq */                    0xc6,   /* 0x7f Control 
Break */
+};
+
+
+int
+main(int argc, char **argv)
+{
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-nographic") == 0 ||
+            strcmp(argv[i], "-curses") == 0 ||
+            strcmp(argv[i], "-vnc") == 0) {
+               return qemu_main(argc, argv, NULL);
+        }
+    }
+    QEMUApplication *app = new QEMUApplication(argc, argv);
+    app->Run();
+    delete app;
+    return 0;
+}
+
+
+QEMUApplication::QEMUApplication(int argc, char **argv)
+    :   BApplication("application/x-vnd.qemu.QEMU"),
+        fThread(0),
+        fWindow(NULL)
+{
+    gApplication = this;
+
+    fArgC = argc;
+    fArgV = argv;
+
+    fThread = spawn_thread(&RunQEMUMain, "qemu_main", B_LOW_PRIORITY, this);
+    resume_thread(fThread);
+}
+
+
+bool
+QEMUApplication::QuitRequested()
+{
+    qemu_system_shutdown_request();
+    return true;
+}
+
+
+void
+QEMUApplication::InitDisplay()
+{
+    fWindow = new QEMUWindow();
+    fWindow->Show();
+}
+
+
+int32
+QEMUApplication::RunQEMUMain(void *arg)
+{
+    QEMUApplication *app = (QEMUApplication *)arg;
+    qemu_main(app->fArgC, app->fArgV, NULL);
+    app->PostMessage(B_QUIT_REQUESTED);
+    return B_OK;
+}
+
+
+QEMUWindow::QEMUWindow()
+    :   BWindow(BRect(100, 100, 150, 150), "QEMU", B_TITLED_WINDOW,
+            B_QUIT_ON_WINDOW_CLOSE | B_NOT_RESIZABLE)
+{
+    gWindow = this;
+    fView = new QEMUView(Bounds());
+    AddChild(fView);
+    fView->MakeFocus();
+}
+
+
+QEMUView::QEMUView(BRect frame)
+    :   BView(frame, "fView", B_FOLLOW_ALL, B_WILL_DRAW),
+        fBitmap(NULL)
+{
+    gView = this;
+    fBitmap = new BBitmap(frame, 0, B_RGBA32);
+    AddFilter(new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, 
&MessageFilter));
+}
+
+
+QEMUView::~QEMUView()
+{
+    if (gFullScreen) {
+        BScreen().SetMode(&fDisplayMode);
+    }
+}
+
+
+void
+QEMUView::UpdateFullScreen()
+{
+    if (!gFullScreen) {
+        return;
+    }
+
+    BScreen screen;
+    display_mode current;
+    display_mode *modes;
+    display_mode *mode;
+    uint32 count;
+
+    screen.GetMode(&current);
+    screen.GetModeList(&modes, &count);
+
+    for (uint32 i = 0; i < count; i++) {
+        mode = &modes[i];
+        if (mode->virtual_width == gWidth
+            && mode->virtual_height == gHeight
+            && mode->space == current.space) {
+            screen.SetMode(mode);
+            break;
+        }
+    }
+
+    gWindow->MoveTo(0, 0);
+}
+
+
+void
+QEMUView::CenterMouse(bool &warp)
+{
+    BRect window = gWindow->Frame();
+    BPoint center = window.LeftTop() + gCenter;
+    set_mouse_position((int32)center.x, (int32)center.y);
+    warp = true;
+}
+
+
+void
+QEMUView::StartGrab(bool &grab)
+{
+    gApplication->HideCursor();
+    gWindow->SetTitle("QEMU - Press Ctrl-Alt to exit grab");
+    grab = true;
+}
+
+
+void
+QEMUView::EndGrab(bool &grab, int32 modifiers)
+{
+    gApplication->ShowCursor();
+    gWindow->SetTitle("QEMU");
+    grab = false;
+
+       // reset any set modifiers
+       if (modifiers & B_LEFT_SHIFT_KEY)
+               kbd_put_keycode(0xaa);
+       if (modifiers & B_RIGHT_SHIFT_KEY)
+               kbd_put_keycode(0xb6);
+
+       if (modifiers & B_LEFT_COMMAND_KEY)
+               kbd_put_keycode(0xb8);
+       if (modifiers & B_RIGHT_COMMAND_KEY) {
+               kbd_put_keycode(0xe0);
+               kbd_put_keycode(0xb8);
+       }
+
+       if (modifiers & B_LEFT_CONTROL_KEY)
+               kbd_put_keycode(0x9d);
+       if (modifiers & B_RIGHT_CONTROL_KEY) {
+               kbd_put_keycode(0xe0);
+               kbd_put_keycode(0x9d);
+       }
+
+       if (modifiers & B_LEFT_OPTION_KEY) {
+               kbd_put_keycode(0xe0);
+               kbd_put_keycode(0xdb);
+       }
+       if (modifiers & B_RIGHT_OPTION_KEY) {
+               kbd_put_keycode(0xe0);
+               kbd_put_keycode(0xdc);
+       }
+}
+
+
+filter_result
+QEMUView::MessageFilter(BMessage *message, BHandler **target,
+       BMessageFilter *filter)
+{
+       static bool sGrabInput = false;
+       static bool sMouseWarp = false;
+       static int32 sMouseButtons = 0;
+       bool keyDown = false;
+
+       switch (message->what) {
+               case B_KEY_DOWN:
+               case B_UNMAPPED_KEY_DOWN:
+                       keyDown = true;
+                       // fall
+
+               case B_KEY_UP:
+               case B_UNMAPPED_KEY_UP: {
+                       int32 modifiers;
+                       message->FindInt32("modifiers", &modifiers);
+
+                       int32 key;
+                       message->FindInt32("key", &key);
+                       uint8 keycode = haiku_to_pc_key[(uint8)key];
+
+                       int32 mask = (B_COMMAND_KEY | B_CONTROL_KEY);
+                       if (!keyDown && sGrabInput && (modifiers & mask)
+                               && (key == 0x5d || key == 0x5c)) {
+                                       EndGrab(sGrabInput, modifiers);
+                                       return B_SKIP_MESSAGE;
+                       }
+
+                       if (keyDown && (modifiers & mask) == mask) {
+                               switch (key) {
+                                       case 0x3f: { /* f - fullscreen */
+                                               BScreen screen;
+                                               if (!gFullScreen) {
+                                                       
screen.GetMode(&gView->fDisplayMode);
+                                                       gWindow->MoveTo(0, 0);
+                                                       gFullScreen = true;
+                                               } else {
+                                                       
screen.SetMode(&gView->fDisplayMode);
+                                                       
gWindow->MoveTo(gView->fWindowLocation);
+                                                       gFullScreen = false;
+                                               }
+
+                                               UpdateFullScreen();
+                                               if (is_graphic_console()) {
+                                                       vga_hw_invalidate();
+                                                       vga_hw_update();
+                                               }
+
+                                               return B_SKIP_MESSAGE;
+                                       } break;
+
+                                       case 0x52: { /* m - pseudo fullscreen */
+                                               BPoint location = 
gWindow->Frame().LeftTop();
+                                               if (location.x == 0 && 
location.y == 0)
+                                                       
gWindow->MoveTo(gPreviousLocation);
+                                               else {
+                                                       gPreviousLocation = 
location;
+                                                       gWindow->MoveTo(0, 0);
+                                               }
+
+                                               if (is_graphic_console()) {
+                                                       vga_hw_invalidate();
+                                                       vga_hw_update();
+                                               }
+
+                                               return B_SKIP_MESSAGE;
+                                       } break;
+
+                                       case 0x12 ... 0x1a: { /* 1 to 9 - 
switch console */
+                                               console_select(key - 0x12);
+                                               if (is_graphic_console()) {
+                                                       vga_hw_invalidate();
+                                                       vga_hw_update();
+                                               }
+
+                                               return B_SKIP_MESSAGE;
+                                       } break;
+                               }
+                       } else if (!is_graphic_console()) {
+                               if (!keyDown)
+                                       return B_SKIP_MESSAGE;
+
+                               int32 rawChar;
+                               message->FindInt32("raw_char", &rawChar);
+
+                               int keysym = 0;
+                               if (modifiers & (B_LEFT_CONTROL_KEY | 
B_RIGHT_CONTROL_KEY)) {
+                                       switch(rawChar) {
+                                               case B_UP_ARROW: keysym = 
QEMU_KEY_CTRL_UP; break;
+                                               case B_DOWN_ARROW: keysym = 
QEMU_KEY_CTRL_DOWN; break;
+                                               case B_LEFT_ARROW: keysym = 
QEMU_KEY_CTRL_LEFT; break;
+                                               case B_RIGHT_ARROW: keysym = 
QEMU_KEY_CTRL_RIGHT; break;
+                                               case B_HOME: keysym = 
QEMU_KEY_CTRL_HOME; break;
+                                               case B_END: keysym = 
QEMU_KEY_CTRL_END; break;
+                                               case B_PAGE_UP: keysym = 
QEMU_KEY_CTRL_PAGEUP; break;
+                                               case B_PAGE_DOWN: keysym = 
QEMU_KEY_CTRL_PAGEDOWN; break;
+                                       }
+                               } else {
+                                       switch(rawChar) {
+                                               case B_UP_ARROW: keysym = 
QEMU_KEY_UP; break;
+                                               case B_DOWN_ARROW: keysym = 
QEMU_KEY_DOWN; break;
+                                               case B_LEFT_ARROW: keysym = 
QEMU_KEY_LEFT; break;
+                                               case B_RIGHT_ARROW: keysym = 
QEMU_KEY_RIGHT; break;
+                                               case B_HOME: keysym = 
QEMU_KEY_HOME; break;
+                                               case B_END: keysym = 
QEMU_KEY_END; break;
+                                               case B_PAGE_UP: keysym = 
QEMU_KEY_PAGEUP; break;
+                                               case B_PAGE_DOWN: keysym = 
QEMU_KEY_PAGEDOWN; break;
+                                               case B_BACKSPACE: keysym = 
QEMU_KEY_BACKSPACE; break;
+                                               case B_DELETE: keysym = 
QEMU_KEY_DELETE; break;
+                                       }
+                               }
+
+                               if (keysym)
+                                       kbd_put_keysym(keysym);
+                               else {
+                                       const char *bytes;
+                                       if (message->FindString("bytes", 
&bytes) == B_OK && bytes[0] != 0)
+                                               kbd_put_keysym(bytes[0]);
+                               }
+                               return B_SKIP_MESSAGE;
+                       }
+
+                       if (keycode & 0x80)
+                               kbd_put_keycode(0xe0);
+
+                       if (keyDown)
+                               kbd_put_keycode(keycode & 0x7f);
+                       else
+                               kbd_put_keycode(keycode | 0x80);
+
+                       return B_SKIP_MESSAGE;
+               } break;
+
+               case B_MOUSE_MOVED: {
+                       if (!sGrabInput)
+                               break;
+
+                       if (sMouseWarp) {
+                               sMouseWarp = false;
+                               return B_SKIP_MESSAGE;
+                       }
+
+                       BPoint where;
+                       message->FindPoint("where", &where);
+                       BPoint delta = where - gCenter;
+
+                       // Haiku buttons are the same as QEMU
+                       kbd_mouse_event((int)delta.x, (int)delta.y, 0, 
sMouseButtons);
+
+                       CenterMouse(sMouseWarp);
+                       return B_SKIP_MESSAGE;
+               } break;
+
+               case B_MOUSE_DOWN:
+               case B_MOUSE_UP: {
+                       int32 buttons;
+                       message->FindInt32("buttons", &buttons);
+
+                       if (!sGrabInput) {
+                               if (message->what == B_MOUSE_DOWN
+                                       && (buttons & B_PRIMARY_MOUSE_BUTTON)) {
+                                       CenterMouse(sMouseWarp);
+                                       StartGrab(sGrabInput);
+                               }
+                               break;
+                       }
+
+                       sMouseButtons = buttons;
+                       // Haiku buttons are the same as QEMU
+                       kbd_mouse_event(0, 0, 0, sMouseButtons);
+                       return B_SKIP_MESSAGE;
+               } break;
+
+               case B_MOUSE_WHEEL_CHANGED: {
+                       if (!sGrabInput)
+                               break;
+
+                       float delta;
+                       message->FindFloat("be:wheel_delta_y", &delta);
+                       kbd_mouse_event(0, 0, (int)delta, sMouseButtons);
+                       return B_SKIP_MESSAGE;
+               } break;
+       }
+
+       return B_DISPATCH_MESSAGE;
+}
+
+
+void
+QEMUView::Update(BPoint point, int width, int height)
+{
+    LockLooper();
+    fBitmap->ImportBits(fFrameBuffer, fFrameBufferSize, fBytesPerRow,
+        fColorSpace, point, point, width, height);
+
+    Draw(BRect(point.x, point.y, point.x + width, point.y + height));
+    UnlockLooper();
+}
+
+
+void
+QEMUView::Draw(BRect updateRect)
+{
+    if (fBitmap == NULL) {
+        return;
+    }
+
+    DrawBitmap(fBitmap, updateRect, updateRect);
+}
+
+
+void
+QEMUView::UpdateFrameBuffer(int width, int height, uchar *bits,
+       int bytesPerRow, int bitsPerPixel)
+{
+       if (LockLooper()) {
+               delete fBitmap;
+               fBitmap = new BBitmap(BRect(0, 0, width - 1, height - 1), 0, 
B_RGBA32);
+               fFrameBuffer = bits;
+               fFrameBufferSize = bytesPerRow * height;
+               fBytesPerRow = bytesPerRow;
+
+               switch (bitsPerPixel) {
+                       case 32:
+                               fColorSpace = B_RGB32;
+                               break;
+                       case 24:
+                               fColorSpace = B_RGB24;
+                               break;
+                       case 16:
+                               fColorSpace = B_RGB16;
+                               break;
+                       case 15:
+                               fColorSpace = B_RGB15;
+                               break;
+                       case 8:
+                               fColorSpace = B_CMAP8;
+                               break;
+                       default:
+                               printf("unsupported display depth %d\n", 
bitsPerPixel);
+                               break;
+               }
+
+               UnlockLooper();
+       }
+}
+
+
+// QEMU C interface
+extern "C" {
+
+static void haiku_update(DisplayState *ds, int x, int y, int w, int h);
+static void haiku_resize(DisplayState *ds);
+static void haiku_refresh(DisplayState *ds);
+
+};
+
+
+static void
+haiku_update(DisplayState *ds, int x, int y, int w, int h)
+{
+    //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
+    gView->Update(BPoint(x, y), w, h);
+}
+
+
+static void
+haiku_resize(DisplayState *ds)
+{
+    //printf("resizing\n");
+    gWidth = ds_get_width(ds);
+    gHeight = ds_get_height(ds);
+    gCenter.x = (int32)(gWidth / 2);
+    gCenter.y = (int32)(gHeight / 2);
+    gWindow->ResizeTo(gWidth - 1, gHeight - 1);
+    gWindow->SetZoomLimits(gWidth, gHeight);
+    gView->UpdateFrameBuffer(ds_get_width(ds), ds_get_height(ds),
+        ds_get_data(ds), ds_get_linesize(ds), ds_get_bits_per_pixel(ds));
+    gView->UpdateFullScreen();
+}
+
+
+static void
+haiku_refresh(DisplayState *ds)
+{
+    //printf("refreshing\n");
+    if (is_graphic_console()) {
+        vga_hw_update();
+    }
+}
+
+
+void
+haiku_display_init(DisplayState *ds, int fullScreen)
+{
+    gApplication->InitDisplay();
+    gFullScreen = fullScreen != 0;
+
+    DisplayChangeListener *displayChangeListener
+        = (DisplayChangeListener *)qemu_mallocz(sizeof(DisplayChangeListener));
+    displayChangeListener->dpy_update = haiku_update;
+    displayChangeListener->dpy_resize = haiku_resize;
+    displayChangeListener->dpy_refresh = haiku_refresh;
+    register_displaychangelistener(ds, displayChangeListener);
+}
diff --git a/ui/haiku.h b/ui/haiku.h
new file mode 100644
index 0000000..2c342d2
--- /dev/null
+++ b/ui/haiku.h
@@ -0,0 +1,96 @@
+/*
+ * QEMU Haiku display driver
+ * 
+ * Copyright (c) 2005-2009 Michael Lotz
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _HAIKU_H_
+#define _HAIKU_H_
+
+#include <Accelerant.h>
+#include <Application.h>
+#include <Bitmap.h>
+#include <MessageFilter.h>
+#include <View.h>
+#include <Window.h>
+
+class QEMUWindow;
+class QEMUView;
+
+class QEMUApplication : public BApplication {
+public:
+                                                       QEMUApplication(int 
argc, char **argv);
+
+virtual        bool                            QuitRequested();
+               void                            InitDisplay();
+
+private:
+static int32                           RunQEMUMain(void *arg);
+
+               int                                     fArgC;
+               char **                         fArgV;
+
+               thread_id                       fThread;
+               QEMUWindow *            fWindow;
+};
+
+
+class QEMUWindow : public BWindow {
+public:
+                                                       QEMUWindow();
+
+private:
+               QEMUView *                      fView;
+};
+
+
+class QEMUView : public BView {
+public:
+                                                       QEMUView(BRect frame);
+virtual                                                ~QEMUView();
+
+               void                            Update(BPoint point, int width, 
int height);
+virtual        void                            Draw(BRect updateRect);
+
+               void                            UpdateFrameBuffer(int width, 
int height,
+                                                               uchar *bits, 
int bytesPerRow,
+                                                               int 
bitsPerPixel);
+
+static void                            UpdateFullScreen();
+static void                            CenterMouse(bool &warp);
+static void                            StartGrab(bool &grab);
+static void                            EndGrab(bool &grab, int32 modifiers);
+
+private:
+static filter_result           MessageFilter(BMessage *message, BHandler 
**target,
+                                                               BMessageFilter 
*filter);
+
+               BBitmap *                       fBitmap;
+               BPoint                          fWindowLocation;
+               display_mode            fDisplayMode;
+
+               uint8 *                         fFrameBuffer;
+               uint32                          fFrameBufferSize;
+               uint32                          fBytesPerRow;
+               color_space                     fColorSpace;
+};
+
+#endif
diff --git a/vl.c b/vl.c
index d352d18..7641763 100644
--- a/vl.c
+++ b/vl.c
@@ -1799,6 +1799,10 @@ static const QEMUOption *lookup_opt(int argc, char 
**argv,
     return popt;
 }
 
+#ifdef CONFIG_HAIKU
+#define main qemu_main
+#endif
+
 int main(int argc, char **argv, char **envp)
 {
     const char *gdbstub_dev = NULL;
@@ -2919,7 +2923,7 @@ int main(int argc, char **argv, char **envp)
     ds = get_displaystate();
 
     if (display_type == DT_DEFAULT) {
-#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
+#if defined(CONFIG_SDL) || defined(CONFIG_COCOA) || defined(CONFIG_HAIKU)
         display_type = DT_SDL;
 #else
         display_type = DT_VNC;
@@ -2945,6 +2949,10 @@ int main(int argc, char **argv, char **envp)
     case DT_SDL:
         cocoa_display_init(ds, full_screen);
         break;
+#elif defined(CONFIG_HAIKU)
+    case DT_SDL:
+        haiku_display_init(ds, full_screen);
+        break;
 #endif
     case DT_VNC:
         vnc_display_init(ds);
-- 
1.7.1.rc2.7.g3e7f1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]