[Top][All Lists]
[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(¤t);
+ 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
- [Qemu-devel] [PATCH 0/8] Add Haiku host support, Andreas Färber, 2010/09/19
- [Qemu-devel] [PATCH 1/8] configure: Add basic support for Haiku, Andreas Färber, 2010/09/19
- [Qemu-devel] [PATCH 2/8] configure: Don't rely on special pthreads library, Andreas Färber, 2010/09/19
- [Qemu-devel] [PATCH 3/8] Haiku doesn't have libm, Andreas Färber, 2010/09/19
- [Qemu-devel] [PATCH 4/8] nbd: Haiku has _IO() in its BSD compatibility layer, Andreas Färber, 2010/09/19
- [Qemu-devel] [PATCH 5/8] tap: Add stub for Haiku, Andreas Färber, 2010/09/19
- [Qemu-devel] [PATCH 6/8] slirp: Silence warning on Haiku, Andreas Färber, 2010/09/19
- [Qemu-devel] [FYI 7/8] qemu_malloc: Use areas on Haiku for sizes > 1 MiB, Andreas Färber, 2010/09/19
- [Qemu-devel] [FYI 8/8] ui: Haiku frontend,
Andreas Färber <=
- [Qemu-devel] Re: [HaikuPorts-devs] [FYI 7/8] qemu_malloc: Use areas on Haiku for sizes > 1 MiB, Oliver Tappe, 2010/09/20
- [Qemu-devel] Re: [HaikuPorts-devs] [FYI 7/8] qemu_malloc: Use areas on Haiku for sizes > 1 MiB, Andreas Färber, 2010/09/21
[Qemu-devel] Re: [HaikuPorts-devs] [PATCH 0/8] Add Haiku host support, Ingo Weinhold, 2010/09/20