From: "Andreas Färber" <andreas.faerber@web.de>
To: qemu-devel@nongnu.org
Cc: haikuports-devs@ports.haiku-files.org,
"Blue Swirl" <blauwirbel@gmail.com>,
"Andreas Färber" <andreas.faerber@web.de>,
"Michael Lotz" <mmlr@mlotz.ch>
Subject: [Qemu-devel] [FYI 8/8] ui: Haiku frontend
Date: Mon, 20 Sep 2010 00:50:50 +0200 [thread overview]
Message-ID: <1284936650-1203-9-git-send-email-andreas.faerber@web.de> (raw)
In-Reply-To: <1284936650-1203-8-git-send-email-andreas.faerber@web.de>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 23820 bytes --]
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 <mmlr@mlotz.ch>
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 <blauwirbel@gmail.com>
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
next prev parent reply other threads:[~2010-09-19 22:51 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-18 13:46 [Qemu-devel] Native Port of QEMU to Haiku Michael Lotz
2009-05-19 8:32 ` Stefan Weil
2009-05-19 8:48 ` Avi Kivity
2009-05-19 12:56 ` Anthony Liguori
2009-05-19 13:54 ` François Revol
2009-05-19 16:56 ` Andreas Färber
2009-05-21 1:04 ` Ingo Weinhold
2010-09-19 22:50 ` [Qemu-devel] [PATCH 0/8] Add Haiku host support Andreas Färber
2010-09-19 22:50 ` [Qemu-devel] [PATCH 1/8] configure: Add basic support for Haiku Andreas Färber
2010-09-19 22:50 ` [Qemu-devel] [PATCH 2/8] configure: Don't rely on special pthreads library Andreas Färber
2010-09-19 22:50 ` [Qemu-devel] [PATCH 3/8] Haiku doesn't have libm Andreas Färber
2010-09-19 22:50 ` [Qemu-devel] [PATCH 4/8] nbd: Haiku has _IO() in its BSD compatibility layer Andreas Färber
2010-09-19 22:50 ` [Qemu-devel] [PATCH 5/8] tap: Add stub for Haiku Andreas Färber
2010-09-19 22:50 ` [Qemu-devel] [PATCH 6/8] slirp: Silence warning on Haiku Andreas Färber
2010-09-19 22:50 ` [Qemu-devel] [FYI 7/8] qemu_malloc: Use areas on Haiku for sizes > 1 MiB Andreas Färber
2010-09-19 22:50 ` Andreas Färber [this message]
2010-09-20 12:26 ` [Qemu-devel] Re: [HaikuPorts-devs] " Oliver Tappe
2010-09-21 22:29 ` Andreas Färber
2010-09-20 19:04 ` [Qemu-devel] Re: [HaikuPorts-devs] [PATCH 0/8] Add Haiku host support Ingo Weinhold
2010-09-21 20:54 ` Andreas Färber
2010-10-03 7:47 ` [Qemu-devel] " Blue Swirl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1284936650-1203-9-git-send-email-andreas.faerber@web.de \
--to=andreas.faerber@web.de \
--cc=blauwirbel@gmail.com \
--cc=haikuports-devs@ports.haiku-files.org \
--cc=mmlr@mlotz.ch \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.