2002-04-18 04:22:20 +04:00
|
|
|
/////////////////////////////////////////////////////////////////
|
2002-12-12 01:55:18 +03:00
|
|
|
// $Id: wx.cc,v 1.52 2002-12-11 22:55:14 bdenney Exp $
|
- I've added lots of comments in siminterface.h, and tried to clean up
the terminology a bit. In particular, the term "gui" has started
to mean different things in different contexts, so I've defined
some more specific names for the parts of the user interface, and
updated comments and some variable names to reflect it. See
siminterface.h for a more complete description of all of these.
VGAW: VGA display window and toolbar buttons, the traditional Bochs
display which is ported to X, win32, MacOS X, etc. Implemented
in gui/gui.* and platform dependent gui/*.cc files.
CI: configuration interface that lets the user change settings such
as floppy disk image, ne2k settings, log options. The CI consists
of two parts: configuration user interface (CUI) which does the
actual rendering to the screen and handles key/mouse/menu events,
and the siminterface object.
CUI: configuration user interface. This handles the user interactions
that allow the user to configure Bochs. To actually change any
values it talks to the siminterface object. One implementation of
the CUI is the text-mode menus in gui/control.cc. Another
implementation is (will be) the wxWindows menus and dialogs in
gui/wxmain.cc.
siminterface: the glue between the CUI and the simulation code,
accessible throughout the code by the global variable
bx_simulator_interface_c *SIM;
Among other things, siminterface methods allow the simulator to ask the
CUI to display things or ask for user input, and allows the CUI
to query and modify variables in the simulation code.
GUI: Literally, "graphical user interface". Until the configuration menus
and wxWindows came along, everyone understood that "gui" referred to the
VGA display window and the toolbar buttons because that's all there
was. Now that we have the wxWindows code, which implements both the VGAW
and the CUI, while all other platforms implement only the VGAW, it's not
so clear. So, I'm trying to use VGAW, CI, and CUI consistently since
they are more specific.
control panel: This has been used as another name for the configuration
interface. "control panel" is also somewhat unspecific and it sounds
like it would be graphical with buttons and sliders, but our text-mode
thing is not graphical at all. I've replaced "control panel" with
"configuration interface" wherever I could find it. In configure script,
the --disable-control-panel option is still supported, but it politely
suggests that you use --disable-config-interface instead.
- clean up comments in siminterface,wx* code
- add comments and examples for bx_param_* and BxEvents
- remove some obsolete stuff: notify_*_args,
bx_simulator_interface_c::[sg]et_enabled() methods
- in siminterface.cc, move a few bx_real_sim_c methods to where they belong,
with the rest of the methods. No changes to the actual methods.
- remove some DOS ^M's which crept in and confused my editor.
2002-08-26 19:31:23 +04:00
|
|
|
/////////////////////////////////////////////////////////////////
|
2002-04-18 04:22:20 +04:00
|
|
|
//
|
|
|
|
// wxWindows VGA display for Bochs. wx.cc implements a custom
|
|
|
|
// wxPanel called a MyPanel, which has methods to display
|
|
|
|
// text and VGA graphics on the panel. Normally, a MyPanel
|
|
|
|
// is instantiated within a MyFrame created by wxmain.cc, but
|
|
|
|
// this is not a requirement.
|
|
|
|
//
|
|
|
|
// The separation between wxmain.cc and wx.cc is as follows:
|
2002-08-29 18:59:37 +04:00
|
|
|
// - wxmain.cc implements a Bochs configuration interface (CI),
|
- I've added lots of comments in siminterface.h, and tried to clean up
the terminology a bit. In particular, the term "gui" has started
to mean different things in different contexts, so I've defined
some more specific names for the parts of the user interface, and
updated comments and some variable names to reflect it. See
siminterface.h for a more complete description of all of these.
VGAW: VGA display window and toolbar buttons, the traditional Bochs
display which is ported to X, win32, MacOS X, etc. Implemented
in gui/gui.* and platform dependent gui/*.cc files.
CI: configuration interface that lets the user change settings such
as floppy disk image, ne2k settings, log options. The CI consists
of two parts: configuration user interface (CUI) which does the
actual rendering to the screen and handles key/mouse/menu events,
and the siminterface object.
CUI: configuration user interface. This handles the user interactions
that allow the user to configure Bochs. To actually change any
values it talks to the siminterface object. One implementation of
the CUI is the text-mode menus in gui/control.cc. Another
implementation is (will be) the wxWindows menus and dialogs in
gui/wxmain.cc.
siminterface: the glue between the CUI and the simulation code,
accessible throughout the code by the global variable
bx_simulator_interface_c *SIM;
Among other things, siminterface methods allow the simulator to ask the
CUI to display things or ask for user input, and allows the CUI
to query and modify variables in the simulation code.
GUI: Literally, "graphical user interface". Until the configuration menus
and wxWindows came along, everyone understood that "gui" referred to the
VGA display window and the toolbar buttons because that's all there
was. Now that we have the wxWindows code, which implements both the VGAW
and the CUI, while all other platforms implement only the VGAW, it's not
so clear. So, I'm trying to use VGAW, CI, and CUI consistently since
they are more specific.
control panel: This has been used as another name for the configuration
interface. "control panel" is also somewhat unspecific and it sounds
like it would be graphical with buttons and sliders, but our text-mode
thing is not graphical at all. I've replaced "control panel" with
"configuration interface" wherever I could find it. In configure script,
the --disable-control-panel option is still supported, but it politely
suggests that you use --disable-config-interface instead.
- clean up comments in siminterface,wx* code
- add comments and examples for bx_param_* and BxEvents
- remove some obsolete stuff: notify_*_args,
bx_simulator_interface_c::[sg]et_enabled() methods
- in siminterface.cc, move a few bx_real_sim_c methods to where they belong,
with the rest of the methods. No changes to the actual methods.
- remove some DOS ^M's which crept in and confused my editor.
2002-08-26 19:31:23 +04:00
|
|
|
// which is the wxWindows equivalent of control.cc. wxmain creates
|
|
|
|
// a frame with several menus and a toolbar, and allows the user to
|
|
|
|
// choose the machine configuration and start the simulation. Note
|
|
|
|
// that wxmain.cc does NOT include bochs.h. All interactions
|
2002-08-29 18:59:37 +04:00
|
|
|
// between the CI and the simulator are through the siminterface
|
- I've added lots of comments in siminterface.h, and tried to clean up
the terminology a bit. In particular, the term "gui" has started
to mean different things in different contexts, so I've defined
some more specific names for the parts of the user interface, and
updated comments and some variable names to reflect it. See
siminterface.h for a more complete description of all of these.
VGAW: VGA display window and toolbar buttons, the traditional Bochs
display which is ported to X, win32, MacOS X, etc. Implemented
in gui/gui.* and platform dependent gui/*.cc files.
CI: configuration interface that lets the user change settings such
as floppy disk image, ne2k settings, log options. The CI consists
of two parts: configuration user interface (CUI) which does the
actual rendering to the screen and handles key/mouse/menu events,
and the siminterface object.
CUI: configuration user interface. This handles the user interactions
that allow the user to configure Bochs. To actually change any
values it talks to the siminterface object. One implementation of
the CUI is the text-mode menus in gui/control.cc. Another
implementation is (will be) the wxWindows menus and dialogs in
gui/wxmain.cc.
siminterface: the glue between the CUI and the simulation code,
accessible throughout the code by the global variable
bx_simulator_interface_c *SIM;
Among other things, siminterface methods allow the simulator to ask the
CUI to display things or ask for user input, and allows the CUI
to query and modify variables in the simulation code.
GUI: Literally, "graphical user interface". Until the configuration menus
and wxWindows came along, everyone understood that "gui" referred to the
VGA display window and the toolbar buttons because that's all there
was. Now that we have the wxWindows code, which implements both the VGAW
and the CUI, while all other platforms implement only the VGAW, it's not
so clear. So, I'm trying to use VGAW, CI, and CUI consistently since
they are more specific.
control panel: This has been used as another name for the configuration
interface. "control panel" is also somewhat unspecific and it sounds
like it would be graphical with buttons and sliders, but our text-mode
thing is not graphical at all. I've replaced "control panel" with
"configuration interface" wherever I could find it. In configure script,
the --disable-control-panel option is still supported, but it politely
suggests that you use --disable-config-interface instead.
- clean up comments in siminterface,wx* code
- add comments and examples for bx_param_* and BxEvents
- remove some obsolete stuff: notify_*_args,
bx_simulator_interface_c::[sg]et_enabled() methods
- in siminterface.cc, move a few bx_real_sim_c methods to where they belong,
with the rest of the methods. No changes to the actual methods.
- remove some DOS ^M's which crept in and confused my editor.
2002-08-26 19:31:23 +04:00
|
|
|
// object.
|
2002-04-18 04:22:20 +04:00
|
|
|
// - wx.cc implements a VGA display screen using wxWindows. It is
|
|
|
|
// is the wxWindows equivalent of x.cc, win32.cc, macos.cc, etc.
|
|
|
|
// wx.cc includes bochs.h and has access to all Bochs devices.
|
|
|
|
// The VGA panel accepts only paint, key, and mouse events. As it
|
|
|
|
// receives events, it builds BxEvents and places them into a
|
|
|
|
// thread-safe BxEvent queue. The simulation thread periodically
|
2002-10-25 01:07:56 +04:00
|
|
|
// processes events from the BxEvent queue (bx_wx_gui_c::handle_events)
|
2002-04-18 04:22:20 +04:00
|
|
|
// and notifies the appropriate emulated I/O device.
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// includes
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
2002-11-14 08:13:40 +03:00
|
|
|
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
|
|
|
|
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
|
|
|
|
// is used to know when we are exporting symbols and when we are importing.
|
|
|
|
#define BX_PLUGGABLE
|
|
|
|
|
2002-11-19 08:47:45 +03:00
|
|
|
#include "bochs.h"
|
|
|
|
#if BX_WITH_WX
|
|
|
|
|
2002-08-30 11:03:50 +04:00
|
|
|
// For compilers that support precompilation, includes <wx/wx.h>.
|
|
|
|
#include <wx/wxprec.h>
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef __BORLANDC__
|
|
|
|
#pragma hdrstop
|
|
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
2002-08-30 11:03:50 +04:00
|
|
|
#include <wx/wx.h>
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-08-30 11:03:50 +04:00
|
|
|
#include <wx/image.h>
|
2002-09-05 17:38:44 +04:00
|
|
|
#include <wx/clipbrd.h>
|
2002-04-18 04:22:20 +04:00
|
|
|
|
|
|
|
#include "gui/icon_bochs.h"
|
|
|
|
#include "osdep.h"
|
|
|
|
#include "font/vga.bitmap.h"
|
|
|
|
|
2002-09-06 18:40:22 +04:00
|
|
|
#include "wxdialog.h"
|
2002-04-18 04:22:20 +04:00
|
|
|
// shared elements between wxmain.cc and this file
|
|
|
|
#include "wxmain.h"
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2002-04-18 04:22:20 +04:00
|
|
|
//////////////////////////////////////////////////////////////
|
2002-10-25 01:07:56 +04:00
|
|
|
// plugin support
|
2002-04-18 04:22:20 +04:00
|
|
|
//////////////////////////////////////////////////////////////
|
2002-10-25 01:07:56 +04:00
|
|
|
class bx_wx_gui_c : public bx_gui_c {
|
|
|
|
public:
|
|
|
|
bx_wx_gui_c (void) {}
|
|
|
|
DECLARE_GUI_VIRTUAL_METHODS()
|
|
|
|
};
|
|
|
|
|
|
|
|
// declare one instance of the gui object and call macro to insert the
|
|
|
|
// plugin code
|
|
|
|
static bx_wx_gui_c *theGui = NULL;
|
|
|
|
|
|
|
|
void MyPanel::OnPluginInit () {
|
|
|
|
theGui = new bx_wx_gui_c ();
|
|
|
|
bx_gui = theGui;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define LOG_THIS theGui->
|
2002-04-18 04:22:20 +04:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// data for wx gui
|
|
|
|
//////////////////////////////////////////////////////////////
|
2002-10-05 21:45:48 +04:00
|
|
|
// The bits to be displayed on the VGA screen are stored in wxScreen.
|
|
|
|
// wxScreen is an array (size=width*height*3) of RGB values. Each
|
|
|
|
// pixel is represented by three bytes, one for red, green, and blue.
|
2002-04-18 04:22:20 +04:00
|
|
|
static char *wxScreen = NULL;
|
|
|
|
wxCriticalSection wxScreen_lock;
|
|
|
|
static long wxScreenX = 0;
|
|
|
|
static long wxScreenY = 0;
|
|
|
|
static long wxTileX = 0;
|
|
|
|
static long wxTileY = 0;
|
|
|
|
static unsigned long wxCursorX = 0;
|
|
|
|
static unsigned long wxCursorY = 0;
|
2002-09-08 13:23:45 +04:00
|
|
|
static unsigned long wxFontY = 0;
|
2002-04-18 04:22:20 +04:00
|
|
|
struct {
|
2002-10-05 16:40:34 +04:00
|
|
|
unsigned char red;
|
|
|
|
unsigned char green;
|
|
|
|
unsigned char blue;
|
2002-04-18 04:22:20 +04:00
|
|
|
} wxBochsPalette[256];
|
|
|
|
wxCriticalSection event_thread_lock;
|
|
|
|
BxEvent event_queue[MAX_EVENTS];
|
|
|
|
unsigned long num_events = 0;
|
2002-10-15 20:48:10 +04:00
|
|
|
static Bit32u convertStringToGDKKey (const char *string);
|
2002-04-18 04:22:20 +04:00
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// and now, the code
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// define the MyPanel which implements the VGA screen
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
BEGIN_EVENT_TABLE(MyPanel, wxPanel)
|
|
|
|
EVT_KEY_DOWN(MyPanel::OnKeyDown)
|
|
|
|
EVT_KEY_UP(MyPanel::OnKeyUp)
|
2002-09-19 00:59:35 +04:00
|
|
|
EVT_TIMER(-1, MyPanel::OnTimer)
|
2002-09-19 02:44:02 +04:00
|
|
|
EVT_PAINT(MyPanel::OnPaint)
|
|
|
|
EVT_MOUSE_EVENTS(MyPanel::OnMouse)
|
2002-04-18 04:22:20 +04:00
|
|
|
END_EVENT_TABLE()
|
|
|
|
|
2002-09-19 00:59:35 +04:00
|
|
|
MyPanel::MyPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
|
|
|
|
: wxPanel (parent, id, pos, size, style, name)
|
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("MyPanel constructor"));
|
2002-09-19 00:59:35 +04:00
|
|
|
refreshTimer.SetOwner (this);
|
|
|
|
refreshTimer.Start (100);
|
|
|
|
needRefresh = true;
|
2002-09-19 04:43:32 +04:00
|
|
|
const char bits[1] = { 0 };
|
|
|
|
blankCursor = new wxCursor (bits, 1, 1, -1, -1, bits);
|
2002-09-21 01:25:09 +04:00
|
|
|
thePanel = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyPanel::~MyPanel ()
|
|
|
|
{
|
|
|
|
delete blankCursor;
|
|
|
|
thePanel = NULL;
|
2002-09-19 00:59:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyPanel::OnTimer(wxCommandEvent& WXUNUSED(event))
|
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("timer")));
|
2002-09-19 00:59:35 +04:00
|
|
|
if (needRefresh) {
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("calling refresh")));
|
2002-09-25 09:35:36 +04:00
|
|
|
Refresh (FALSE);
|
2002-09-19 00:59:35 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-18 04:22:20 +04:00
|
|
|
void MyPanel::OnPaint(wxPaintEvent& WXUNUSED(event))
|
|
|
|
{
|
2002-10-05 16:40:34 +04:00
|
|
|
wxPaintDC dc(this);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA (wxLogDebug (wxT ("OnPaint")));
|
2002-10-05 16:40:34 +04:00
|
|
|
//PrepareDC(dc);
|
|
|
|
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::OnPaint trying to get lock. wxScreen=%p", wxScreen)));
|
2002-10-05 16:40:34 +04:00
|
|
|
wxCriticalSectionLocker lock(wxScreen_lock);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::OnPaint got lock. wxScreen=%p", wxScreen)));
|
2002-10-05 16:40:34 +04:00
|
|
|
if(wxScreen != NULL) {
|
|
|
|
wxPoint pt = GetClientAreaOrigin();
|
|
|
|
wxImage screenImage(wxScreenX, wxScreenY, (unsigned char *)wxScreen, TRUE);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("drawBitmap")));
|
2002-10-05 16:40:34 +04:00
|
|
|
dc.DrawBitmap(screenImage.ConvertToBitmap(), pt.x, pt.y, FALSE);
|
|
|
|
}
|
|
|
|
needRefresh = false;
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
2002-10-07 08:49:50 +04:00
|
|
|
void MyPanel::ToggleMouse (bool fromToolbar)
|
2002-09-19 02:44:02 +04:00
|
|
|
{
|
2002-10-07 08:49:50 +04:00
|
|
|
static bool first_enable = true;
|
2002-09-19 02:44:02 +04:00
|
|
|
bx_param_bool_c *enable = SIM->get_param_bool (BXP_MOUSE_ENABLED);
|
|
|
|
bool en = ! enable->get ();
|
2002-12-12 01:55:18 +03:00
|
|
|
bool is_main_thread = wxThread::IsMain ();
|
|
|
|
bool needmutex = !is_main_thread && SIM->is_sim_thread ();
|
2002-10-07 08:49:50 +04:00
|
|
|
if (needmutex) wxMutexGuiEnter();
|
|
|
|
if (fromToolbar && first_enable && en) {
|
|
|
|
// only show this help if you click on the toolbar. If they already
|
|
|
|
// know the shortcut, don't annoy them with the message.
|
|
|
|
wxString msg =
|
|
|
|
"You have enabled the mouse in Bochs, so now your mouse actions will\n"
|
|
|
|
"be sent into the simulator. The usual mouse cursor will be trapped\n"
|
|
|
|
"inside the Bochs window until you press F12 or press the middle button\n"
|
|
|
|
"to turn mouse capture off.";
|
|
|
|
wxMessageBox(msg, "Mouse Capture Enabled", wxOK | wxICON_INFORMATION);
|
|
|
|
first_enable = false;
|
|
|
|
}
|
2002-09-19 02:44:02 +04:00
|
|
|
enable->set (en);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_MOUSE (wxLogDebug (wxT ("now mouse is %sabled", en ? "en" : "dis")));
|
2002-09-19 02:44:02 +04:00
|
|
|
if (en) {
|
|
|
|
mouseSavedX = wxScreenX / 2;
|
|
|
|
mouseSavedY = wxScreenY / 2;
|
|
|
|
WarpPointer (mouseSavedX, mouseSavedY);
|
2002-09-19 04:43:32 +04:00
|
|
|
SetCursor (*blankCursor);
|
|
|
|
} else {
|
|
|
|
SetCursor (wxNullCursor);
|
2002-09-19 02:44:02 +04:00
|
|
|
}
|
2002-10-07 08:49:50 +04:00
|
|
|
if (needmutex) wxMutexGuiLeave();
|
2002-09-19 02:44:02 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyPanel::OnMouse(wxMouseEvent& event)
|
|
|
|
{
|
|
|
|
long x,y;
|
|
|
|
event.GetPosition (&x, &y);
|
|
|
|
IFDBG_MOUSE (
|
|
|
|
if (event.IsButton ()) {
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("mouse button event at %d,%d", x, y));
|
2002-09-19 02:44:02 +04:00
|
|
|
} else if (event.Entering ()) {
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("mouse entering at %d,%d", x, y));
|
2002-09-19 02:44:02 +04:00
|
|
|
} else if (event.Leaving ()) {
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("mouse leaving at %d,%d", x, y));
|
2002-09-19 02:44:02 +04:00
|
|
|
} else if (event.Moving() || event.Dragging ()) {
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("mouse moved to %d,%d", x, y));
|
2002-09-19 02:44:02 +04:00
|
|
|
} else {
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("other mouse event at %d,%d", x, y));
|
2002-09-19 02:44:02 +04:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
if (event.MiddleDown ()) {
|
2002-10-07 08:49:50 +04:00
|
|
|
ToggleMouse (false);
|
2002-09-19 02:44:02 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SIM->get_param_bool(BXP_MOUSE_ENABLED)->get ())
|
|
|
|
return; // mouse disabled, ignore the event
|
|
|
|
|
|
|
|
// process buttons and motion together
|
|
|
|
Bit32u buttons;
|
|
|
|
buttons = event.LeftIsDown () ? 1 : 0;
|
|
|
|
buttons |= event.RightIsDown () ? 2 : 0;
|
|
|
|
if (x==mouseSavedX && y==mouseSavedY && !event.IsButton ()) {
|
|
|
|
// nothing happened. This could have been generated by the WarpPointer.
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if(num_events < MAX_EVENTS) {
|
|
|
|
wxCriticalSectionLocker lock(event_thread_lock);
|
|
|
|
Bit16s dx = x - mouseSavedX;
|
|
|
|
Bit16s dy = y - mouseSavedY;
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_MOUSE (wxLogDebug (wxT ("mouse moved by delta %d,%d", dx, dy)));
|
2002-09-19 02:44:02 +04:00
|
|
|
event_queue[num_events].type = BX_ASYNC_EVT_MOUSE;
|
|
|
|
event_queue[num_events].u.mouse.dx = dx;
|
|
|
|
event_queue[num_events].u.mouse.dy = -dy;
|
|
|
|
event_queue[num_events].u.mouse.buttons = buttons;
|
|
|
|
num_events++;
|
|
|
|
mouseSavedX = x;
|
|
|
|
mouseSavedY = y;
|
|
|
|
} else {
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("mouse event skipped because event queue full"));
|
2002-09-19 02:44:02 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseSavedX = wxScreenX / 2;
|
|
|
|
mouseSavedY = wxScreenY / 2;
|
|
|
|
WarpPointer (mouseSavedX, mouseSavedY);
|
|
|
|
// The WarpPointer moves the pointer back to the middle of the
|
|
|
|
// screen. This WILL produce another mouse motion event, which needs
|
|
|
|
// to be ignored. It will be ignored because the new motion event
|
|
|
|
// will move the cursor to (mouseSavedX, mouseSavedY).
|
|
|
|
}
|
|
|
|
|
2002-04-18 04:22:20 +04:00
|
|
|
void
|
|
|
|
MyPanel::MyRefresh ()
|
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA (wxLogDebug (wxT ("set needRefresh=true")));
|
2002-09-19 00:59:35 +04:00
|
|
|
needRefresh = true;
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyPanel::OnKeyDown(wxKeyEvent& event)
|
|
|
|
{
|
2002-10-05 16:40:34 +04:00
|
|
|
if(event.GetKeyCode() == WXK_F12) {
|
2002-10-07 08:49:50 +04:00
|
|
|
ToggleMouse (false);
|
2002-10-05 16:40:34 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
wxCriticalSectionLocker lock(event_thread_lock);
|
|
|
|
if(num_events < MAX_EVENTS) {
|
|
|
|
event_queue[num_events].type = BX_ASYNC_EVT_KEY;
|
|
|
|
fillBxKeyEvent (event, event_queue[num_events].u.key, false);
|
|
|
|
num_events++;
|
|
|
|
}
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MyPanel::OnKeyUp(wxKeyEvent& event)
|
|
|
|
{
|
2002-10-05 16:40:34 +04:00
|
|
|
wxCriticalSectionLocker lock(event_thread_lock);
|
|
|
|
if(num_events < MAX_EVENTS) {
|
|
|
|
event_queue[num_events].type = BX_ASYNC_EVT_KEY;
|
|
|
|
fillBxKeyEvent (event, event_queue[num_events].u.key, true);
|
|
|
|
num_events++;
|
|
|
|
}
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// copied right out of gui/x.cc
|
|
|
|
static char
|
|
|
|
wxAsciiKey[0x5f] = {
|
|
|
|
// !"#$%&'
|
|
|
|
BX_KEY_SPACE,
|
|
|
|
BX_KEY_1,
|
|
|
|
BX_KEY_SINGLE_QUOTE,
|
|
|
|
BX_KEY_3,
|
|
|
|
BX_KEY_4,
|
|
|
|
BX_KEY_5,
|
|
|
|
BX_KEY_7,
|
|
|
|
BX_KEY_SINGLE_QUOTE,
|
|
|
|
|
|
|
|
// ()*+,-./
|
|
|
|
BX_KEY_9,
|
|
|
|
BX_KEY_0,
|
|
|
|
BX_KEY_8,
|
|
|
|
BX_KEY_EQUALS,
|
|
|
|
BX_KEY_COMMA,
|
|
|
|
BX_KEY_MINUS,
|
|
|
|
BX_KEY_PERIOD,
|
|
|
|
BX_KEY_SLASH,
|
|
|
|
|
|
|
|
// 01234567
|
|
|
|
BX_KEY_0,
|
|
|
|
BX_KEY_1,
|
|
|
|
BX_KEY_2,
|
|
|
|
BX_KEY_3,
|
|
|
|
BX_KEY_4,
|
|
|
|
BX_KEY_5,
|
|
|
|
BX_KEY_6,
|
|
|
|
BX_KEY_7,
|
|
|
|
|
|
|
|
// 89:;<=>?
|
|
|
|
BX_KEY_8,
|
|
|
|
BX_KEY_9,
|
|
|
|
BX_KEY_SEMICOLON,
|
|
|
|
BX_KEY_SEMICOLON,
|
|
|
|
BX_KEY_COMMA,
|
|
|
|
BX_KEY_EQUALS,
|
|
|
|
BX_KEY_PERIOD,
|
|
|
|
BX_KEY_SLASH,
|
|
|
|
|
|
|
|
// @ABCDEFG
|
|
|
|
BX_KEY_2,
|
|
|
|
BX_KEY_A,
|
|
|
|
BX_KEY_B,
|
|
|
|
BX_KEY_C,
|
|
|
|
BX_KEY_D,
|
|
|
|
BX_KEY_E,
|
|
|
|
BX_KEY_F,
|
|
|
|
BX_KEY_G,
|
|
|
|
|
|
|
|
|
|
|
|
// HIJKLMNO
|
|
|
|
BX_KEY_H,
|
|
|
|
BX_KEY_I,
|
|
|
|
BX_KEY_J,
|
|
|
|
BX_KEY_K,
|
|
|
|
BX_KEY_L,
|
|
|
|
BX_KEY_M,
|
|
|
|
BX_KEY_N,
|
|
|
|
BX_KEY_O,
|
|
|
|
|
|
|
|
|
|
|
|
// PQRSTUVW
|
|
|
|
BX_KEY_P,
|
|
|
|
BX_KEY_Q,
|
|
|
|
BX_KEY_R,
|
|
|
|
BX_KEY_S,
|
|
|
|
BX_KEY_T,
|
|
|
|
BX_KEY_U,
|
|
|
|
BX_KEY_V,
|
|
|
|
BX_KEY_W,
|
|
|
|
|
|
|
|
// XYZ[\]^_
|
|
|
|
BX_KEY_X,
|
|
|
|
BX_KEY_Y,
|
|
|
|
BX_KEY_Z,
|
|
|
|
BX_KEY_LEFT_BRACKET,
|
|
|
|
BX_KEY_BACKSLASH,
|
|
|
|
BX_KEY_RIGHT_BRACKET,
|
|
|
|
BX_KEY_6,
|
|
|
|
BX_KEY_MINUS,
|
|
|
|
|
|
|
|
// `abcdefg
|
|
|
|
BX_KEY_GRAVE,
|
|
|
|
BX_KEY_A,
|
|
|
|
BX_KEY_B,
|
|
|
|
BX_KEY_C,
|
|
|
|
BX_KEY_D,
|
|
|
|
BX_KEY_E,
|
|
|
|
BX_KEY_F,
|
|
|
|
BX_KEY_G,
|
|
|
|
|
|
|
|
// hijklmno
|
|
|
|
BX_KEY_H,
|
|
|
|
BX_KEY_I,
|
|
|
|
BX_KEY_J,
|
|
|
|
BX_KEY_K,
|
|
|
|
BX_KEY_L,
|
|
|
|
BX_KEY_M,
|
|
|
|
BX_KEY_N,
|
|
|
|
BX_KEY_O,
|
|
|
|
|
|
|
|
// pqrstuvw
|
|
|
|
BX_KEY_P,
|
|
|
|
BX_KEY_Q,
|
|
|
|
BX_KEY_R,
|
|
|
|
BX_KEY_S,
|
|
|
|
BX_KEY_T,
|
|
|
|
BX_KEY_U,
|
|
|
|
BX_KEY_V,
|
|
|
|
BX_KEY_W,
|
|
|
|
|
|
|
|
// xyz{|}~
|
|
|
|
BX_KEY_X,
|
|
|
|
BX_KEY_Y,
|
|
|
|
BX_KEY_Z,
|
|
|
|
BX_KEY_LEFT_BRACKET,
|
|
|
|
BX_KEY_BACKSLASH,
|
|
|
|
BX_KEY_RIGHT_BRACKET,
|
|
|
|
BX_KEY_GRAVE
|
|
|
|
};
|
|
|
|
|
2002-09-26 23:34:44 +04:00
|
|
|
#if defined (wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
|
|
|
|
// get windows specific definitions. At present the only thing needed
|
|
|
|
// is the definition of HIWORD.
|
2002-10-04 01:07:04 +04:00
|
|
|
|
|
|
|
// windows.h included by bochs.h, so nothing extra is required here.
|
2002-09-26 23:34:44 +04:00
|
|
|
#endif
|
2002-04-18 04:22:20 +04:00
|
|
|
|
|
|
|
// MS Windows specific key mapping, which uses wxKeyEvent::m_rawCode & 2.
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool
|
|
|
|
MyPanel::fillBxKeyEvent_MSW (wxKeyEvent& wxev, BxKeyEvent& bxev, bx_bool release)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
#if defined(wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_KEY(wxLogDebug (wxT ("fillBxKeyEvent_MSW. key code %d, raw codes %d %d", wxev.m_keyCode, wxev.m_rawCode, wxev.m_rawFlags)));
|
2002-04-18 04:22:20 +04:00
|
|
|
// this code was grabbed from gui/win32.cpp
|
|
|
|
Bit32u lParam = wxev.m_rawFlags;
|
|
|
|
Bit32u key = HIWORD (lParam) & 0x01FF;
|
|
|
|
bxev.bx_key = 0x0000;
|
2002-08-30 21:39:14 +04:00
|
|
|
// Swap the scancodes of "numlock" and "pause"
|
|
|
|
if ((key & 0xff)==0x45) key ^= 0x100;
|
|
|
|
if (key & 0x0100) {
|
2002-10-12 13:04:50 +04:00
|
|
|
// Its an extended key
|
|
|
|
bxev.bx_key = 0xE000;
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
// Its a key
|
|
|
|
bxev.bx_key |= (key & 0x00FF) | (release? 0x80 : 0x00);
|
|
|
|
bxev.raw_scancode = true;
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
|
|
|
|
// get those keysym definitions
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// GTK specific key mapping, which uses wxKeyEvent::m_rawCode.
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool
|
|
|
|
MyPanel::fillBxKeyEvent_GTK (wxKeyEvent& wxev, BxKeyEvent& bxev, bx_bool release)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
#if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_KEY(wxLogDebug (wxT ("fillBxKeyEvent_GTK. key code %ld, raw codes %d %d", wxev.m_keyCode, wxev.m_rawCode, wxev.m_rawFlags)));
|
2002-04-18 04:22:20 +04:00
|
|
|
// GTK has only 16bit key codes
|
|
|
|
Bit16u keysym = (Bit32u) wxev.m_rawCode;
|
2002-09-25 09:35:36 +04:00
|
|
|
Bit32u key_event = 0;
|
2002-04-18 04:22:20 +04:00
|
|
|
// since the GDK_* symbols are very much like the X11 symbols (possibly
|
|
|
|
// identical), I'm using code that is copied from gui/x.cc.
|
2002-10-15 20:48:10 +04:00
|
|
|
if(!bx_options.keyboard.OuseMapping->get()) {
|
|
|
|
if (keysym >= GDK_space && keysym < GDK_asciitilde) {
|
|
|
|
// use nice ASCII conversion table, based on x.cc
|
|
|
|
key_event = wxAsciiKey[keysym - GDK_space];
|
|
|
|
} else switch (keysym) {
|
|
|
|
case GDK_KP_1:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_End
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_End:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_END; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_2:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Down
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Down:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_DOWN; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_3:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Page_Down
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Page_Down:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_PAGE_DOWN; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_4:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Left
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Left:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_LEFT; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_5:
|
2002-09-25 11:21:38 +04:00
|
|
|
#ifdef GDK_KP_Begin
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Begin:
|
2002-09-25 11:21:38 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_5; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_6:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Right
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Right:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_RIGHT; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_7:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Home
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Home:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_HOME; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_8:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Up
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Up:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_UP; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_9:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Page_Up
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Page_Up:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_PAGE_UP; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_0:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Insert
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Insert:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_INSERT; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Decimal:
|
2002-04-18 04:22:20 +04:00
|
|
|
#ifdef GDK_KP_Delete
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Delete:
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
key_event = BX_KEY_KP_DELETE; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
|
|
|
#ifdef GDK_KP_Enter
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Enter: key_event = BX_KEY_KP_ENTER; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
#endif
|
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Subtract: key_event = BX_KEY_KP_SUBTRACT; break;
|
|
|
|
case GDK_KP_Add: key_event = BX_KEY_KP_ADD; break;
|
2002-09-25 09:35:36 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_KP_Multiply: key_event = BX_KEY_KP_MULTIPLY; break;
|
|
|
|
case GDK_KP_Divide: key_event = BX_KEY_KP_DIVIDE; break;
|
2002-09-25 09:35:36 +04:00
|
|
|
|
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Up: key_event = BX_KEY_UP; break;
|
|
|
|
case GDK_Down: key_event = BX_KEY_DOWN; break;
|
|
|
|
case GDK_Left: key_event = BX_KEY_LEFT; break;
|
|
|
|
case GDK_Right: key_event = BX_KEY_RIGHT; break;
|
2002-09-25 09:35:36 +04:00
|
|
|
|
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Delete: key_event = BX_KEY_DELETE; break;
|
|
|
|
case GDK_BackSpace: key_event = BX_KEY_BACKSPACE; break;
|
|
|
|
case GDK_Tab: key_event = BX_KEY_TAB; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#ifdef GDK_ISO_Left_Tab
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_ISO_Left_Tab: key_event = BX_KEY_TAB; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Return: key_event = BX_KEY_ENTER; break;
|
|
|
|
case GDK_Escape: key_event = BX_KEY_ESC; break;
|
|
|
|
case GDK_F1: key_event = BX_KEY_F1; break;
|
|
|
|
case GDK_F2: key_event = BX_KEY_F2; break;
|
|
|
|
case GDK_F3: key_event = BX_KEY_F3; break;
|
|
|
|
case GDK_F4: key_event = BX_KEY_F4; break;
|
|
|
|
case GDK_F5: key_event = BX_KEY_F5; break;
|
|
|
|
case GDK_F6: key_event = BX_KEY_F6; break;
|
|
|
|
case GDK_F7: key_event = BX_KEY_F7; break;
|
|
|
|
case GDK_F8: key_event = BX_KEY_F8; break;
|
|
|
|
case GDK_F9: key_event = BX_KEY_F9; break;
|
|
|
|
case GDK_F10: key_event = BX_KEY_F10; break;
|
|
|
|
case GDK_F11: key_event = BX_KEY_F11; break;
|
|
|
|
case GDK_F12: key_event = BX_KEY_F12; break;
|
|
|
|
case GDK_Control_L: key_event = BX_KEY_CTRL_L; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#ifdef GDK_Control_R
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Control_R: key_event = BX_KEY_CTRL_R; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Shift_L: key_event = BX_KEY_SHIFT_L; break;
|
|
|
|
case GDK_Shift_R: key_event = BX_KEY_SHIFT_R; break;
|
|
|
|
case GDK_Alt_L: key_event = BX_KEY_ALT_L; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#ifdef GDK_Alt_R
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Alt_R: key_event = BX_KEY_ALT_R; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#endif
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Caps_Lock: key_event = BX_KEY_CAPS_LOCK; break;
|
|
|
|
case GDK_Num_Lock: key_event = BX_KEY_NUM_LOCK; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#ifdef GDK_Scroll_Lock
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Scroll_Lock: key_event = BX_KEY_SCRL_LOCK; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#endif
|
|
|
|
#ifdef GDK_Print
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Print: key_event = BX_KEY_PRINT; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#endif
|
|
|
|
#ifdef GDK_Pause
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Pause: key_event = BX_KEY_PAUSE; break;
|
2002-09-25 11:21:38 +04:00
|
|
|
#endif
|
2002-09-25 09:35:36 +04:00
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Insert: key_event = BX_KEY_INSERT; break;
|
|
|
|
case GDK_Home: key_event = BX_KEY_HOME; break;
|
|
|
|
case GDK_End: key_event = BX_KEY_END; break;
|
|
|
|
case GDK_Page_Up: key_event = BX_KEY_PAGE_UP; break;
|
|
|
|
case GDK_Page_Down: key_event = BX_KEY_PAGE_DOWN; break;
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-13 15:07:44 +04:00
|
|
|
#ifdef GDK_Menu
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Menu: key_event = BX_KEY_MENU; break;
|
2002-10-13 15:07:44 +04:00
|
|
|
#endif
|
|
|
|
#ifdef GDK_Super_L
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Super_L: key_event = BX_KEY_WIN_L; break;
|
2002-10-13 15:07:44 +04:00
|
|
|
#endif
|
|
|
|
#ifdef GDK_Super_R
|
2002-10-15 20:48:10 +04:00
|
|
|
case GDK_Super_R: key_event = BX_KEY_WIN_R; break;
|
2002-10-13 15:07:44 +04:00
|
|
|
#endif
|
|
|
|
|
2002-10-15 20:48:10 +04:00
|
|
|
default:
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogError(wxT ("fillBxKeyEvent_GTK(): keysym %x unhandled!"), (unsigned) keysym );
|
2002-10-15 20:48:10 +04:00
|
|
|
return BX_KEY_UNHANDLED;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* use mapping */
|
|
|
|
BXKeyEntry *entry = bx_keymap.findHostKey (keysym);
|
|
|
|
if (!entry) {
|
|
|
|
BX_ERROR(( "fillBxKeyEvent_GTK(): keysym %x unhandled!", (unsigned) keysym ));
|
|
|
|
return BX_KEY_UNHANDLED;
|
|
|
|
}
|
|
|
|
key_event = entry->baseKey;
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
2002-09-25 09:35:36 +04:00
|
|
|
bxev.bx_key = key_event | (release? BX_KEY_RELEASED : BX_KEY_PRESSED);
|
2002-04-18 04:22:20 +04:00
|
|
|
bxev.raw_scancode = false;
|
|
|
|
return true;
|
|
|
|
#else // if GTK toolkit
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool
|
|
|
|
MyPanel::fillBxKeyEvent (wxKeyEvent& wxev, BxKeyEvent& bxev, bx_bool release)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
// Use raw codes if they are available. Raw codes are a nonstandard addition
|
|
|
|
// to the wxWindows library. At present, the only way to use the "RAW_CODES"
|
|
|
|
// mode is to apply Bryce's "patch.wx-raw-keycodes" patch to the wxWindows
|
|
|
|
// sources and recompile. This patch, or something like it, should appear in
|
|
|
|
// future wxWindows versions.
|
|
|
|
|
|
|
|
#if defined (wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
|
|
|
|
return fillBxKeyEvent_MSW (wxev, bxev, release);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
|
|
|
|
return fillBxKeyEvent_GTK (wxev, bxev, release);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// otherwise fall back to using portable WXK_* keycodes. Not all keys
|
|
|
|
// can be mapped correctly using WXK_* codes but it should be usable.
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_KEY (wxLogDebug (wxT ("fillBxKeyEvent. key code %ld", wxev.m_keyCode)));
|
2002-04-18 04:22:20 +04:00
|
|
|
Bit32u key = wxev.m_keyCode;
|
|
|
|
Bit32u bx_key;
|
|
|
|
|
|
|
|
if(key >= WXK_SPACE && key < WXK_DELETE) {
|
2002-10-05 16:40:34 +04:00
|
|
|
bx_key = wxAsciiKey[key - WXK_SPACE];
|
2002-04-18 04:22:20 +04:00
|
|
|
} else {
|
2002-10-05 16:40:34 +04:00
|
|
|
// handle extended keys here
|
|
|
|
switch(key) {
|
|
|
|
case WXK_BACK: bx_key = BX_KEY_BACKSPACE; break;
|
|
|
|
case WXK_TAB: bx_key = BX_KEY_TAB; break;
|
|
|
|
case WXK_RETURN: bx_key = BX_KEY_ENTER; break;
|
|
|
|
case WXK_ESCAPE: bx_key = BX_KEY_ESC; break;
|
|
|
|
case WXK_DELETE: bx_key = BX_KEY_DELETE; break;
|
|
|
|
case WXK_SHIFT: bx_key = BX_KEY_SHIFT_L; break;
|
|
|
|
case WXK_CONTROL: bx_key = BX_KEY_CTRL_L; break;
|
|
|
|
case WXK_ALT: bx_key = BX_KEY_ALT_L; break;
|
|
|
|
case WXK_MENU: bx_key = BX_KEY_MENU; break;
|
|
|
|
case WXK_PAUSE: bx_key = BX_KEY_PAUSE; break;
|
|
|
|
case WXK_PRIOR: bx_key = BX_KEY_PAGE_UP; break;
|
|
|
|
case WXK_NEXT: bx_key = BX_KEY_PAGE_DOWN; break;
|
|
|
|
case WXK_END: bx_key = BX_KEY_END; break;
|
|
|
|
case WXK_HOME: bx_key = BX_KEY_HOME; break;
|
|
|
|
case WXK_LEFT: bx_key = BX_KEY_LEFT; break;
|
|
|
|
case WXK_UP: bx_key = BX_KEY_UP; break;
|
|
|
|
case WXK_RIGHT: bx_key = BX_KEY_RIGHT; break;
|
|
|
|
case WXK_DOWN: bx_key = BX_KEY_DOWN; break;
|
|
|
|
case WXK_INSERT: bx_key = BX_KEY_INSERT; break;
|
|
|
|
case WXK_NUMPAD0: bx_key = BX_KEY_KP_INSERT; break;
|
|
|
|
case WXK_NUMPAD1: bx_key = BX_KEY_KP_END; break;
|
|
|
|
case WXK_NUMPAD2: bx_key = BX_KEY_KP_DOWN; break;
|
|
|
|
case WXK_NUMPAD3: bx_key = BX_KEY_KP_PAGE_DOWN; break;
|
|
|
|
case WXK_NUMPAD4: bx_key = BX_KEY_KP_LEFT; break;
|
|
|
|
case WXK_NUMPAD5: bx_key = BX_KEY_KP_5; break;
|
|
|
|
case WXK_NUMPAD6: bx_key = BX_KEY_KP_RIGHT; break;
|
|
|
|
case WXK_NUMPAD7: bx_key = BX_KEY_KP_HOME; break;
|
|
|
|
case WXK_NUMPAD8: bx_key = BX_KEY_KP_UP; break;
|
|
|
|
case WXK_NUMPAD9: bx_key = BX_KEY_KP_PAGE_UP; break;
|
|
|
|
case WXK_F1: bx_key = BX_KEY_F1; break;
|
|
|
|
case WXK_F2: bx_key = BX_KEY_F2; break;
|
|
|
|
case WXK_F3: bx_key = BX_KEY_F3; break;
|
|
|
|
case WXK_F4: bx_key = BX_KEY_F4; break;
|
|
|
|
case WXK_F5: bx_key = BX_KEY_F5; break;
|
|
|
|
case WXK_F6: bx_key = BX_KEY_F6; break;
|
|
|
|
case WXK_F7: bx_key = BX_KEY_F7; break;
|
|
|
|
case WXK_F8: bx_key = BX_KEY_F8; break;
|
|
|
|
case WXK_F9: bx_key = BX_KEY_F9; break;
|
|
|
|
case WXK_F10: bx_key = BX_KEY_F10; break;
|
|
|
|
case WXK_F11: bx_key = BX_KEY_F11; break;
|
|
|
|
case WXK_F12: bx_key = BX_KEY_F12; break;
|
|
|
|
case WXK_NUMLOCK: bx_key = BX_KEY_NUM_LOCK; break;
|
|
|
|
case WXK_SCROLL: bx_key = BX_KEY_SCRL_LOCK; break;
|
|
|
|
case WXK_DECIMAL: bx_key = BX_KEY_PERIOD; break;
|
|
|
|
case WXK_SUBTRACT: bx_key = BX_KEY_MINUS; break;
|
|
|
|
case WXK_ADD: bx_key = BX_KEY_EQUALS; break;
|
|
|
|
case WXK_MULTIPLY: bx_key = BX_KEY_KP_MULTIPLY; break;
|
|
|
|
case WXK_DIVIDE: bx_key = BX_KEY_KP_DIVIDE; break;
|
|
|
|
|
|
|
|
case WXK_NUMPAD_ENTER: bx_key = BX_KEY_KP_ENTER; break;
|
|
|
|
case WXK_NUMPAD_HOME: bx_key = BX_KEY_KP_HOME; break;
|
|
|
|
case WXK_NUMPAD_LEFT: bx_key = BX_KEY_KP_LEFT; break;
|
|
|
|
case WXK_NUMPAD_UP: bx_key = BX_KEY_KP_UP; break;
|
|
|
|
case WXK_NUMPAD_RIGHT: bx_key = BX_KEY_KP_RIGHT; break;
|
|
|
|
case WXK_NUMPAD_DOWN: bx_key = BX_KEY_KP_DOWN; break;
|
|
|
|
case WXK_NUMPAD_PRIOR: bx_key = BX_KEY_KP_PAGE_UP; break;
|
|
|
|
case WXK_NUMPAD_PAGEUP: bx_key = BX_KEY_KP_PAGE_UP; break;
|
|
|
|
case WXK_NUMPAD_NEXT: bx_key = BX_KEY_KP_PAGE_DOWN; break;
|
|
|
|
case WXK_NUMPAD_PAGEDOWN: bx_key = BX_KEY_KP_PAGE_DOWN; break;
|
|
|
|
case WXK_NUMPAD_END: bx_key = BX_KEY_KP_END; break;
|
|
|
|
case WXK_NUMPAD_BEGIN: bx_key = BX_KEY_KP_HOME; break;
|
|
|
|
case WXK_NUMPAD_INSERT: bx_key = BX_KEY_KP_INSERT; break;
|
|
|
|
case WXK_NUMPAD_DELETE: bx_key = BX_KEY_KP_DELETE; break;
|
|
|
|
case WXK_NUMPAD_EQUAL: bx_key = BX_KEY_KP_ENTER; break;
|
|
|
|
case WXK_NUMPAD_MULTIPLY: bx_key = BX_KEY_KP_MULTIPLY; break;
|
|
|
|
case WXK_NUMPAD_SUBTRACT: bx_key = BX_KEY_KP_SUBTRACT; break;
|
|
|
|
case WXK_NUMPAD_DECIMAL: bx_key = BX_KEY_KP_DELETE; break;
|
|
|
|
case WXK_NUMPAD_DIVIDE: bx_key = BX_KEY_KP_DIVIDE; break;
|
|
|
|
|
|
|
|
// Keys not handled by wxMSW
|
|
|
|
case 20: bx_key = BX_KEY_CAPS_LOCK; break; // =+
|
|
|
|
case 186: bx_key = BX_KEY_SEMICOLON; break; // ;:
|
|
|
|
case 187: bx_key = BX_KEY_EQUALS; break; // =+
|
|
|
|
case 188: bx_key = BX_KEY_COMMA; break; // ,<
|
|
|
|
case 189: bx_key = BX_KEY_MINUS; break; // -_
|
|
|
|
case 190: bx_key = BX_KEY_PERIOD; break; // .>
|
|
|
|
case 191: bx_key = BX_KEY_SLASH; break; // /?
|
|
|
|
case 192: bx_key = BX_KEY_GRAVE; break; // `~
|
|
|
|
case 219: bx_key = BX_KEY_LEFT_BRACKET; break; // [{
|
|
|
|
case 221: bx_key = BX_KEY_RIGHT_BRACKET; break; // ]}
|
|
|
|
case 220: bx_key = BX_KEY_BACKSLASH; break; // \|
|
|
|
|
case 222: bx_key = BX_KEY_SINGLE_QUOTE; break; // '"
|
|
|
|
case 305: bx_key = BX_KEY_KP_5; break; // keypad 5
|
|
|
|
case 392: bx_key = BX_KEY_KP_ADD; break; // keypad plus
|
|
|
|
|
|
|
|
default:
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogMessage(wxT ("Unhandled key event: %i (0x%x)"), key, key);
|
2002-10-05 16:40:34 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_KEY (wxLogDebug (wxT ("fillBxKeyEvent: after remapping, key=%d"), bx_key));
|
2002-04-18 04:22:20 +04:00
|
|
|
bxev.bx_key = bx_key | (release? BX_KEY_RELEASED : BX_KEY_PRESSED);
|
|
|
|
bxev.raw_scancode = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// fill in methods of bx_gui
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight,
|
2002-04-18 04:22:20 +04:00
|
|
|
unsigned headerbar_y)
|
|
|
|
{
|
2002-09-08 13:23:45 +04:00
|
|
|
int b,i,j;
|
|
|
|
unsigned char fc, vc;
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
put("WX ");
|
2002-04-18 04:22:20 +04:00
|
|
|
if (bx_options.Oprivate_colormap->get ()) {
|
|
|
|
BX_INFO(("private_colormap option ignored."));
|
|
|
|
}
|
|
|
|
|
2002-09-08 13:23:45 +04:00
|
|
|
for(i = 0; i < 256; i++) {
|
2002-10-05 16:40:34 +04:00
|
|
|
wxBochsPalette[i].red = 0;
|
|
|
|
wxBochsPalette[i].green = 0;
|
|
|
|
wxBochsPalette[i].blue = 0;
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
2002-09-08 13:23:45 +04:00
|
|
|
for(i = 0; i < 256; i++) {
|
|
|
|
for(j = 0; j < 16; j++) {
|
|
|
|
vc = bx_vgafont[i].data[j];
|
|
|
|
fc = 0;
|
|
|
|
for (b = 0; b < 8; b++) {
|
|
|
|
fc |= (vc & 0x01) << (7 - b);
|
|
|
|
vc >>= 1;
|
|
|
|
}
|
2002-10-25 01:07:56 +04:00
|
|
|
vga_charmap[i*32+j] = fc;
|
2002-09-08 13:23:45 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-18 04:22:20 +04:00
|
|
|
wxScreenX = 640;
|
|
|
|
wxScreenY = 480;
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::specific_init trying to get lock. wxScreen=%p", wxScreen)));
|
2002-04-18 04:22:20 +04:00
|
|
|
wxCriticalSectionLocker lock(wxScreen_lock);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::specific_init got lock. wxScreen=%p", wxScreen)));
|
2002-04-18 04:22:20 +04:00
|
|
|
wxScreen = (char *)malloc(wxScreenX * wxScreenY * 3);
|
|
|
|
memset(wxScreen, 0, wxScreenX * wxScreenY * 3);
|
|
|
|
|
|
|
|
wxTileX = tilewidth;
|
|
|
|
wxTileY = tileheight;
|
2002-09-05 17:38:44 +04:00
|
|
|
|
|
|
|
// load keymap tables
|
|
|
|
if(bx_options.keyboard.OuseMapping->get())
|
2002-10-15 20:48:10 +04:00
|
|
|
#if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
|
|
|
|
bx_keymap.loadKeymap(convertStringToGDKKey);
|
|
|
|
#else
|
2002-09-05 17:38:44 +04:00
|
|
|
bx_keymap.loadKeymap(NULL);
|
2002-10-15 20:48:10 +04:00
|
|
|
#endif
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// ::HANDLE_EVENTS()
|
|
|
|
//
|
|
|
|
// Called periodically (vga_update_interval in .bochsrc) so the
|
|
|
|
// the gui code can poll for keyboard, mouse, and other
|
|
|
|
// relevant events.
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
void bx_wx_gui_c::handle_events(void)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
wxCriticalSectionLocker lock(event_thread_lock);
|
|
|
|
Bit32u bx_key = 0;
|
|
|
|
for(unsigned int i = 0; i < num_events; i++) {
|
|
|
|
switch(event_queue[i].type) {
|
|
|
|
case BX_ASYNC_EVT_TOOLBAR:
|
|
|
|
switch (event_queue[i].u.toolbar.button) {
|
|
|
|
case BX_TOOLBAR_FLOPPYA: floppyA_handler (); break;
|
|
|
|
case BX_TOOLBAR_FLOPPYB: floppyB_handler (); break;
|
|
|
|
case BX_TOOLBAR_CDROMD: cdromD_handler (); break;
|
|
|
|
case BX_TOOLBAR_RESET: reset_handler (); break;
|
|
|
|
case BX_TOOLBAR_POWER: power_handler (); break;
|
|
|
|
case BX_TOOLBAR_COPY: copy_handler (); break;
|
|
|
|
case BX_TOOLBAR_PASTE: paste_handler (); break;
|
|
|
|
case BX_TOOLBAR_SNAPSHOT: snapshot_handler (); break;
|
|
|
|
case BX_TOOLBAR_CONFIG: config_handler (); break;
|
2002-10-07 08:49:50 +04:00
|
|
|
case BX_TOOLBAR_MOUSE_EN: thePanel->ToggleMouse (true); break;
|
2002-08-09 10:16:43 +04:00
|
|
|
case BX_TOOLBAR_USER: userbutton_handler (); break;
|
2002-04-18 04:22:20 +04:00
|
|
|
default:
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogDebug (wxT ("unknown toolbar id %d"), event_queue[i].u.toolbar.button);
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BX_ASYNC_EVT_KEY:
|
|
|
|
bx_key = event_queue[i].u.key.bx_key;
|
2002-10-25 01:07:56 +04:00
|
|
|
if (event_queue[i].u.key.raw_scancode) {
|
|
|
|
// event contains raw scancodes: use put_scancode
|
|
|
|
Bit8u scancode;
|
|
|
|
if (bx_key & 0xFF00) { // for extended keys
|
|
|
|
// This makes the "AltGr" key on European keyboards work
|
|
|
|
if (bx_key==0xE038) {
|
|
|
|
scancode = 0x9d; // left control key released
|
|
|
|
DEV_kbd_put_scancode (&scancode, 1);
|
|
|
|
}
|
|
|
|
scancode = 0xFF & (bx_key>>8);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_KEY (wxLogDebug (wxT ("sending raw scancode 0x%02x (extended key))", (int)scancode)));
|
2002-10-25 01:07:56 +04:00
|
|
|
DEV_kbd_put_scancode(&scancode, 1);
|
|
|
|
}
|
|
|
|
scancode = 0xFF & bx_key;
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_KEY (wxLogDebug (wxT ("sending raw scancode 0x%02x", (int))scancode));
|
2002-10-25 01:07:56 +04:00
|
|
|
DEV_kbd_put_scancode(&scancode, 1);
|
|
|
|
} else {
|
|
|
|
// event contains BX_KEY_* codes: use gen_scancode
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_KEY (wxLogDebug (wxT ("sending key event 0x%02x", bx_key)));
|
2002-10-25 01:07:56 +04:00
|
|
|
DEV_kbd_gen_scancode(bx_key);
|
2002-10-12 13:04:50 +04:00
|
|
|
}
|
2002-04-18 04:22:20 +04:00
|
|
|
break;
|
2002-09-19 02:44:02 +04:00
|
|
|
case BX_ASYNC_EVT_MOUSE:
|
2002-10-25 01:07:56 +04:00
|
|
|
DEV_mouse_motion(
|
|
|
|
event_queue[i].u.mouse.dx,
|
|
|
|
event_queue[i].u.mouse.dy,
|
|
|
|
event_queue[i].u.mouse.buttons);
|
|
|
|
break;
|
2002-04-18 04:22:20 +04:00
|
|
|
default:
|
2002-11-18 05:40:31 +03:00
|
|
|
wxLogError (wxT ("handle_events received unhandled event type %d in queue"), (int)event_queue[i].type);
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
num_events = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ::FLUSH()
|
|
|
|
//
|
|
|
|
// Called periodically, requesting that the gui code flush all pending
|
|
|
|
// screen update requests.
|
|
|
|
|
|
|
|
void
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::flush(void)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::CLEAR_SCREEN()
|
|
|
|
//
|
|
|
|
// Called to request that the VGA region is cleared. Don't
|
|
|
|
// clear the area that defines the headerbar.
|
|
|
|
|
|
|
|
void
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::clear_screen(void)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::clear_screen trying to get lock. wxScreen=%p", wxScreen)));
|
2002-04-18 04:22:20 +04:00
|
|
|
wxCriticalSectionLocker lock(wxScreen_lock);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::clear_screen got lock. wxScreen=%p", wxScreen)));
|
2002-04-18 04:22:20 +04:00
|
|
|
memset(wxScreen, 0, wxScreenX * wxScreenY * 3);
|
2002-09-19 00:59:35 +04:00
|
|
|
thePanel->MyRefresh ();
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2002-10-05 22:15:00 +04:00
|
|
|
UpdateScreen(unsigned char *newBits, int x, int y, int width, int height)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::UpdateScreen trying to get lock. wxScreen=%p", wxScreen)));
|
2002-10-05 16:40:34 +04:00
|
|
|
wxCriticalSectionLocker lock(wxScreen_lock);
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::UpdateScreen got lock. wxScreen=%p", wxScreen)));
|
2002-10-05 16:40:34 +04:00
|
|
|
if(wxScreen != NULL) {
|
|
|
|
for(int i = 0; i < height; i++) {
|
|
|
|
for(int c = 0; c < width; c++) {
|
|
|
|
wxScreen[(y * wxScreenX * 3) + ((x+c) * 3)] = wxBochsPalette[newBits[(i * width) + c]].red;
|
|
|
|
wxScreen[(y * wxScreenX * 3) + ((x+c) * 3) + 1] = wxBochsPalette[newBits[(i * width) + c]].green;
|
|
|
|
wxScreen[(y * wxScreenX * 3) + ((x+c) * 3) + 2] = wxBochsPalette[newBits[(i * width) + c]].blue;
|
|
|
|
}
|
|
|
|
y++;
|
|
|
|
if(y >= wxScreenY) break;
|
|
|
|
}
|
|
|
|
} else {
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA (wxLogDebug (wxT ("UpdateScreen with null wxScreen")));
|
2002-10-05 16:40:34 +04:00
|
|
|
}
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2002-09-01 11:32:03 +04:00
|
|
|
DrawBochsBitmap(int x, int y, int width, int height, char *bmap, char color, int cs_start, int cs_end)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-10-05 16:40:34 +04:00
|
|
|
int j = 0;
|
|
|
|
char bgcolor = (color >> 4) & 0xF;
|
|
|
|
char fgcolor = color & 0xF;
|
|
|
|
|
|
|
|
if (cs_start <= cs_end) {
|
|
|
|
height = cs_end - cs_start + 1;
|
|
|
|
y += cs_start;
|
|
|
|
j = cs_start * ((width - 1) / 8 + 1);
|
|
|
|
}
|
2002-10-05 22:15:00 +04:00
|
|
|
unsigned char *newBits = (unsigned char *)malloc(width * height);
|
2002-10-05 16:40:34 +04:00
|
|
|
memset(newBits, 0, (width * height));
|
|
|
|
for(int i = 0; i < (width * height) / 8; i++) {
|
|
|
|
newBits[i * 8 + 0] = (bmap[j] & 0x80) ? fgcolor : bgcolor;
|
|
|
|
newBits[i * 8 + 1] = (bmap[j] & 0x40) ? fgcolor : bgcolor;
|
|
|
|
newBits[i * 8 + 2] = (bmap[j] & 0x20) ? fgcolor : bgcolor;
|
|
|
|
newBits[i * 8 + 3] = (bmap[j] & 0x10) ? fgcolor : bgcolor;
|
|
|
|
newBits[i * 8 + 4] = (bmap[j] & 0x08) ? fgcolor : bgcolor;
|
|
|
|
newBits[i * 8 + 5] = (bmap[j] & 0x04) ? fgcolor : bgcolor;
|
|
|
|
newBits[i * 8 + 6] = (bmap[j] & 0x02) ? fgcolor : bgcolor;
|
|
|
|
newBits[i * 8 + 7] = (bmap[j] & 0x01) ? fgcolor : bgcolor;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
UpdateScreen(newBits, x, y, width, height);
|
|
|
|
free(newBits);
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::TEXT_UPDATE()
|
|
|
|
//
|
|
|
|
// Called in a VGA text mode, to update the screen with
|
|
|
|
// new content.
|
|
|
|
//
|
|
|
|
// old_text: array of character/attributes making up the contents
|
|
|
|
// of the screen from the last call. See below
|
|
|
|
// new_text: array of character/attributes making up the current
|
|
|
|
// contents, which should now be displayed. See below
|
|
|
|
//
|
|
|
|
// format of old_text & new_text: each is 4000 bytes long.
|
|
|
|
// This represents 80 characters wide by 25 high, with
|
|
|
|
// each character being 2 bytes. The first by is the
|
|
|
|
// character value, the second is the attribute byte.
|
|
|
|
// I currently don't handle the attribute byte.
|
|
|
|
//
|
|
|
|
// cursor_x: new x location of cursor
|
|
|
|
// cursor_y: new y location of cursor
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
void bx_wx_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
|
2002-04-18 04:22:20 +04:00
|
|
|
unsigned long cursor_x, unsigned long cursor_y,
|
2002-10-05 16:40:34 +04:00
|
|
|
Bit16u cursor_state, unsigned nrows)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("text_update")));
|
2002-09-19 00:59:35 +04:00
|
|
|
//static Bit32u counter = 0;
|
|
|
|
//BX_INFO (("text_update executed %d times", ++counter));
|
|
|
|
|
2002-10-05 16:40:34 +04:00
|
|
|
Bit8u cs_start = (cursor_state >> 8) & 0x3f;
|
|
|
|
Bit8u cs_end = cursor_state & 0x1f;
|
|
|
|
unsigned char cChar;
|
|
|
|
unsigned int ncols = wxScreenX / 8;
|
|
|
|
unsigned int nchars = ncols * nrows;
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool forceUpdate = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
if(charmap_updated) {
|
2002-10-05 16:40:34 +04:00
|
|
|
forceUpdate = 1;
|
2002-10-25 01:07:56 +04:00
|
|
|
charmap_updated = 0;
|
2002-10-05 16:40:34 +04:00
|
|
|
}
|
|
|
|
if((wxCursorY * ncols + wxCursorX) < nchars) {
|
|
|
|
cChar = new_text[(wxCursorY * ncols + wxCursorX) * 2];
|
2002-10-25 01:07:56 +04:00
|
|
|
DrawBochsBitmap(wxCursorX * 8, wxCursorY * wxFontY, 8, wxFontY, (char *)&vga_charmap[cChar<<5], new_text[((wxCursorY * ncols + wxCursorX) * 2) + 1], 1, 0);
|
2002-10-05 16:40:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < nchars * 2; i += 2) {
|
|
|
|
if(forceUpdate || (old_text[i] != new_text[i])
|
|
|
|
|| (old_text[i+1] != new_text[i+1])) {
|
|
|
|
cChar = new_text[i];
|
|
|
|
int x = (i / 2) % ncols;
|
|
|
|
int y = (i / 2) / ncols;
|
2002-10-25 01:07:56 +04:00
|
|
|
DrawBochsBitmap(x * 8, y * wxFontY, 8, wxFontY, (char *)&vga_charmap[cChar<<5], new_text[i+1], 1, 0);
|
2002-10-05 16:40:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
wxCursorX = cursor_x;
|
|
|
|
wxCursorY = cursor_y;
|
|
|
|
|
|
|
|
if(((cursor_y * ncols + cursor_x) < nchars) && (cs_start <= cs_end)) {
|
|
|
|
cChar = new_text[(cursor_y * ncols + cursor_x) * 2];
|
|
|
|
char cAttr = new_text[((cursor_y * ncols + cursor_x) * 2) + 1];
|
|
|
|
cAttr = ((cAttr >> 4) & 0xF) + ((cAttr & 0xF) << 4);
|
2002-10-25 01:07:56 +04:00
|
|
|
DrawBochsBitmap(wxCursorX * 8, wxCursorY * wxFontY, 8, wxFontY, (char *)&vga_charmap[cChar<<5], cAttr, cs_start, cs_end);
|
2002-10-05 16:40:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
thePanel->MyRefresh ();
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::PALETTE_CHANGE()
|
|
|
|
//
|
|
|
|
// Allocate a color in the native GUI, for this color, and put
|
|
|
|
// it in the colormap location 'index'.
|
|
|
|
// returns: 0=no screen update needed (color map change has direct effect)
|
2002-10-05 21:45:48 +04:00
|
|
|
// 1=screen update needed (redraw using current colormap)
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("palette_change")));
|
2002-04-18 04:22:20 +04:00
|
|
|
wxBochsPalette[index].red = red;
|
|
|
|
wxBochsPalette[index].green = green;
|
|
|
|
wxBochsPalette[index].blue = blue;
|
2002-10-05 21:45:48 +04:00
|
|
|
return(1); // screen update needed
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::GRAPHICS_TILE_UPDATE()
|
|
|
|
//
|
|
|
|
// Called to request that a tile of graphics be drawn to the
|
|
|
|
// screen, since info in this region has changed.
|
|
|
|
//
|
|
|
|
// tile: array of 8bit values representing a block of pixels with
|
|
|
|
// dimension equal to the 'tilewidth' & 'tileheight' parameters to
|
|
|
|
// ::specific_init(). Each value specifies an index into the
|
|
|
|
// array of colors you allocated for ::palette_change()
|
|
|
|
// x0: x origin of tile
|
|
|
|
// y0: y origin of tile
|
|
|
|
//
|
|
|
|
// note: origin of tile and of window based on (0,0) being in the upper
|
|
|
|
// left of the window.
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
void bx_wx_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA (wxLogDebug (wxT ("graphics_tile_update")));
|
2002-09-19 00:59:35 +04:00
|
|
|
//static Bit32u counter = 0;
|
|
|
|
//BX_INFO (("graphics_tile_update executed %d times", ++counter));
|
2002-10-05 22:15:00 +04:00
|
|
|
UpdateScreen(tile, x0, y0, wxTileX, wxTileY);
|
2002-09-19 00:59:35 +04:00
|
|
|
thePanel->MyRefresh ();
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// ::DIMENSION_UPDATE()
|
|
|
|
//
|
2002-09-04 19:51:04 +04:00
|
|
|
// Called from the simulator when the VGA mode changes it's X,Y dimensions.
|
2002-04-18 04:22:20 +04:00
|
|
|
// Resize the window to this size, but you need to add on
|
|
|
|
// the height of the headerbar to the Y value.
|
|
|
|
//
|
|
|
|
// x: new VGA x size
|
|
|
|
// y: new VGA y size (add headerbar_y parameter from ::specific_init().
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
void bx_wx_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::dimension_update trying to get lock. wxScreen=%p", wxScreen)));
|
2002-09-04 19:51:04 +04:00
|
|
|
wxScreen_lock.Enter ();
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::dimension_update got lock. wxScreen=%p", wxScreen)));
|
2002-10-05 22:27:24 +04:00
|
|
|
BX_INFO (("dimension update x=%d y=%d fontheight=%d", x, y, fheight));
|
2002-04-20 11:19:35 +04:00
|
|
|
if (fheight > 0) {
|
2002-10-05 16:40:34 +04:00
|
|
|
wxFontY = fheight;
|
2002-04-20 11:19:35 +04:00
|
|
|
}
|
2002-04-18 04:22:20 +04:00
|
|
|
wxScreenX = x;
|
|
|
|
wxScreenY = y;
|
|
|
|
wxScreen = (char *)realloc(wxScreen, wxScreenX * wxScreenY * 3);
|
|
|
|
wxASSERT (wxScreen != NULL);
|
2002-09-04 19:51:04 +04:00
|
|
|
wxScreen_lock.Leave ();
|
2002-11-18 05:40:31 +03:00
|
|
|
IFDBG_VGA(wxLogDebug (wxT ("MyPanel::dimension_update gave up lock. wxScreen=%p", wxScreen)));
|
2002-09-04 19:51:04 +04:00
|
|
|
// Note: give up wxScreen_lock before calling SetClientSize. I did
|
|
|
|
// this because I was sometimes seeing thread deadlock in win32, apparantly
|
|
|
|
// related to wxStreen_lock. The wxWindows GUI thread was sitting in OnPaint
|
|
|
|
// trying to get the wxScreen_lock, and the simulation thread was stuck in some
|
|
|
|
// native win32 function called by SetClientSize (below). As with many
|
|
|
|
// thread problems, it happened sporadically so it's hard to prove that this
|
|
|
|
// really fixed it. -bbd
|
2002-04-18 04:22:20 +04:00
|
|
|
|
2002-09-04 19:51:04 +04:00
|
|
|
// this method is called from the simulation thread, so we must get the GUI
|
|
|
|
// thread mutex first to be safe.
|
|
|
|
wxMutexGuiEnter ();
|
2002-04-18 04:22:20 +04:00
|
|
|
//theFrame->SetSize(-1, -1, wxScreenX + 6, wxScreenY + 100, 0);
|
|
|
|
//wxSize size = theFrame->GetToolBar()->GetToolSize();
|
|
|
|
theFrame->SetClientSize(wxScreenX, wxScreenY); // + size.GetHeight());
|
2002-09-04 19:51:04 +04:00
|
|
|
theFrame->Layout ();
|
|
|
|
wxMutexGuiLeave ();
|
2002-09-19 00:59:35 +04:00
|
|
|
thePanel->MyRefresh ();
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::CREATE_BITMAP()
|
|
|
|
//
|
|
|
|
// Create a monochrome bitmap of size 'xdim' by 'ydim', which will
|
|
|
|
// be drawn in the headerbar. Return an integer ID to the bitmap,
|
|
|
|
// with which the bitmap can be referenced later.
|
|
|
|
//
|
|
|
|
// bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
|
|
|
|
// bit0 is the left most pixel, bit7 is the right most pixel.
|
|
|
|
// xdim: x dimension of bitmap
|
|
|
|
// ydim: y dimension of bitmap
|
|
|
|
|
|
|
|
unsigned
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
UNUSED(bmap);
|
|
|
|
UNUSED(xdim);
|
|
|
|
UNUSED(ydim);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::HEADERBAR_BITMAP()
|
|
|
|
//
|
|
|
|
// Called to install a bitmap in the bochs headerbar (toolbar).
|
|
|
|
//
|
|
|
|
// bmap_id: will correspond to an ID returned from
|
|
|
|
// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
|
|
|
|
// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
|
|
|
|
// available leftmost or rightmost space.
|
|
|
|
// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
|
|
|
|
// meaning install the bitmap in the next
|
|
|
|
// available leftmost or rightmost space.
|
|
|
|
// f: a 'C' function pointer to callback when the mouse is clicked in
|
|
|
|
// the boundaries of this bitmap.
|
|
|
|
|
|
|
|
unsigned
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
UNUSED(bmap_id);
|
|
|
|
UNUSED(alignment);
|
|
|
|
UNUSED(f);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::SHOW_HEADERBAR()
|
|
|
|
//
|
|
|
|
// Show (redraw) the current headerbar, which is composed of
|
|
|
|
// currently installed bitmaps.
|
|
|
|
|
|
|
|
void
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::show_headerbar(void)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::REPLACE_BITMAP()
|
|
|
|
//
|
|
|
|
// Replace the bitmap installed in the headerbar ID slot 'hbar_id',
|
|
|
|
// with the one specified by 'bmap_id'. 'bmap_id' will have
|
|
|
|
// been generated by ::create_bitmap(). The old and new bitmap
|
|
|
|
// must be of the same size. This allows the bitmap the user
|
|
|
|
// sees to change, when some action occurs. For example when
|
|
|
|
// the user presses on the floppy icon, it then displays
|
|
|
|
// the ejected status.
|
|
|
|
//
|
|
|
|
// hbar_id: headerbar slot ID
|
|
|
|
// bmap_id: bitmap ID
|
|
|
|
|
|
|
|
void
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
UNUSED(hbar_id);
|
|
|
|
UNUSED(bmap_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ::EXIT()
|
|
|
|
//
|
|
|
|
// Called before bochs terminates, to allow for a graceful
|
|
|
|
// exit from the native GUI mechanism.
|
|
|
|
|
|
|
|
void
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::exit(void)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-10-25 01:07:56 +04:00
|
|
|
BX_INFO(("bx_wx_gui_c::exit() not implemented yet."));
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_wx_gui_c::mouse_enabled_changed_specific (bx_bool val)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-09-05 17:38:44 +04:00
|
|
|
int ret = 0;
|
|
|
|
wxMutexGuiEnter ();
|
|
|
|
if (wxTheClipboard->Open ()) {
|
|
|
|
if (wxTheClipboard->IsSupported (wxDF_TEXT)) {
|
|
|
|
wxTextDataObject data;
|
|
|
|
wxTheClipboard->GetData (data);
|
|
|
|
wxString str = data.GetText ();
|
|
|
|
int len = str.Len ();
|
2002-09-05 19:57:37 +04:00
|
|
|
Bit8u *buf = new Bit8u[len];
|
2002-09-05 17:38:44 +04:00
|
|
|
memcpy (buf, str.c_str (), len);
|
|
|
|
*bytes = buf;
|
|
|
|
*nbytes = len;
|
|
|
|
ret = 1;
|
2002-09-05 19:57:37 +04:00
|
|
|
// buf will be freed in bx_keyb_c::paste_bytes or
|
|
|
|
// bx_keyb_c::service_paste_buf, using delete [].
|
|
|
|
} else {
|
|
|
|
BX_ERROR (("paste: could not open wxWindows clipboard"));
|
2002-09-05 17:38:44 +04:00
|
|
|
}
|
|
|
|
wxTheClipboard->Close ();
|
|
|
|
}
|
|
|
|
wxMutexGuiLeave ();
|
|
|
|
return ret;
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2002-10-25 01:07:56 +04:00
|
|
|
bx_wx_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
|
2002-04-18 04:22:20 +04:00
|
|
|
{
|
2002-09-05 17:38:44 +04:00
|
|
|
wxMutexGuiEnter ();
|
|
|
|
int ret = 0;
|
|
|
|
if (wxTheClipboard->Open ()) {
|
|
|
|
wxString string (text_snapshot, len);
|
|
|
|
wxTheClipboard->SetData (new wxTextDataObject (string));
|
|
|
|
wxTheClipboard->Close ();
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
wxMutexGuiLeave ();
|
|
|
|
return ret;
|
2002-04-18 04:22:20 +04:00
|
|
|
}
|
2002-10-15 20:48:10 +04:00
|
|
|
|
|
|
|
#if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
|
2002-10-16 20:32:55 +04:00
|
|
|
/* we can use the X keysyms for GTK too */
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
/* convertStringToGDKKey is a keymap callback
|
|
|
|
* used when reading the keymap file.
|
|
|
|
* It converts a Symblic String to a GUI Constant
|
|
|
|
*
|
|
|
|
* It returns a Bit32u constant or BX_KEYMAP_UNKNOWN if it fails
|
|
|
|
*/
|
2002-10-15 20:48:10 +04:00
|
|
|
static Bit32u convertStringToGDKKey (const char *string)
|
|
|
|
{
|
2002-10-16 20:32:55 +04:00
|
|
|
if (strncmp ("XK_", string, 3) != 0)
|
|
|
|
return BX_KEYMAP_UNKNOWN;
|
|
|
|
KeySym keysym=XStringToKeysym(string+3);
|
|
|
|
|
|
|
|
// failure, return unknown
|
|
|
|
if(keysym==NoSymbol) return BX_KEYMAP_UNKNOWN;
|
|
|
|
|
|
|
|
return((Bit32u)keysym);
|
2002-10-15 20:48:10 +04:00
|
|
|
}
|
|
|
|
#endif
|
2002-11-19 08:47:45 +03:00
|
|
|
|
|
|
|
#endif /* if BX_WITH_WX */
|