1 /////////////////////////////////////////////////////////////////
2 // $Id: wx.cc,v 1.96 2008/11/16 21:01:09 vruppert Exp $
3 /////////////////////////////////////////////////////////////////
5 // wxWidgets VGA display for Bochs. wx.cc implements a custom
6 // wxPanel called a MyPanel, which has methods to display
7 // text and VGA graphics on the panel. Normally, a MyPanel
8 // is instantiated within a MyFrame created by wxmain.cc, but
9 // this is not a requirement.
11 // The separation between wxmain.cc and wx.cc is as follows:
12 // - wxmain.cc implements a Bochs configuration interface (CI),
13 // which is the wxWidgets equivalent of textconfig.cc. wxmain creates
14 // a frame with several menus and a toolbar, and allows the user to
15 // choose the machine configuration and start the simulation. Note
16 // that wxmain.cc does NOT include bochs.h. All interactions
17 // between the CI and the simulator are through the siminterface
19 // - wx.cc implements a VGA display screen using wxWidgets. It is
20 // is the wxWidgets equivalent of x.cc, win32.cc, macos.cc, etc.
21 // wx.cc includes bochs.h and has access to all Bochs devices.
22 // The VGA panel accepts only paint, key, and mouse events. As it
23 // receives events, it builds BxEvents and places them into a
24 // thread-safe BxEvent queue. The simulation thread periodically
25 // processes events from the BxEvent queue (bx_wx_gui_c::handle_events)
26 // and notifies the appropriate emulated I/O device.
28 /////////////////////////////////////////////////////////////////
30 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
31 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
32 // is used to know when we are exporting symbols and when we are importing.
39 // For compilers that support precompilation, includes <wx/wx.h>.
40 #include <wx/wxprec.h>
48 #include <wx/clipbrd.h>
50 //#include "gui/icon_bochs.h"
52 #include "font/vga.bitmap.h"
54 // shared elements between wxmain.cc and this file
58 //////////////////////////////////////////////////////////////
60 //////////////////////////////////////////////////////////////
61 class bx_wx_gui_c
: public bx_gui_c
{
64 DECLARE_GUI_VIRTUAL_METHODS()
65 DECLARE_GUI_NEW_VIRTUAL_METHODS()
66 void statusbar_setitem(int element
, bx_bool active
, bx_bool w
=0);
68 void show_ips(Bit32u ips_count
);
72 // declare one instance of the gui object and call macro to insert the
74 static bx_wx_gui_c
*theGui
= NULL
;
76 void MyPanel::OnPluginInit () {
77 theGui
= new bx_wx_gui_c ();
81 #define LOG_THIS theGui->
83 //////////////////////////////////////////////////////////////
85 //////////////////////////////////////////////////////////////
86 // The bits to be displayed on the VGA screen are stored in wxScreen.
87 // wxScreen is an array (size=width*height*3) of RGB values. Each
88 // pixel is represented by three bytes, one for red, green, and blue.
89 static char *wxScreen
= NULL
;
90 wxCriticalSection wxScreen_lock
;
91 static long wxScreenX
= 0;
92 static long wxScreenY
= 0;
93 static bx_bool wxScreenCheckSize
= 0;
94 static unsigned wxTileX
= 0;
95 static unsigned wxTileY
= 0;
96 static unsigned long wxCursorX
= 0;
97 static unsigned long wxCursorY
= 0;
98 static unsigned long wxFontX
= 0;
99 static unsigned long wxFontY
= 0;
100 static unsigned int text_rows
=25, text_cols
=80;
101 static Bit8u h_panning
= 0, v_panning
= 0;
102 static Bit16u line_compare
= 1023;
103 static unsigned vga_bpp
=8;
108 } wxBochsPalette
[256];
109 wxCriticalSection event_thread_lock
;
110 BxEvent event_queue
[MAX_EVENTS
];
111 unsigned long num_events
= 0;
112 static bx_bool mouse_captured
= 0;
113 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
114 static Bit32u
convertStringToGDKKey (const char *string
);
118 //////////////////////////////////////////////////////////////
120 //////////////////////////////////////////////////////////////
122 //////////////////////////////////////////////////////////////
123 // define the MyPanel which implements the VGA screen
124 //////////////////////////////////////////////////////////////
126 BEGIN_EVENT_TABLE(MyPanel
, wxPanel
)
127 EVT_KEY_DOWN(MyPanel::OnKeyDown
)
128 EVT_KEY_UP(MyPanel::OnKeyUp
)
129 EVT_TIMER(-1, MyPanel::OnTimer
)
130 EVT_PAINT(MyPanel::OnPaint
)
131 EVT_MOUSE_EVENTS(MyPanel::OnMouse
)
134 MyPanel::MyPanel(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
)
135 : wxPanel (parent
, id
, pos
, size
, style
, name
)
137 wxLogDebug (wxT ("MyPanel constructor"));
138 refreshTimer
.SetOwner (this);
139 refreshTimer
.Start (100);
141 const char bits
[1] = { 0 };
142 blankCursor
= new wxCursor (bits
, 1, 1, -1, -1, bits
);
152 void MyPanel::OnTimer(wxTimerEvent
& WXUNUSED(event
))
156 if (wxScreenCheckSize
) {
157 theFrame
->GetClientSize(&cx
, &cy
);
158 if ((cx
!= wxScreenX
) || (cy
!= wxScreenY
)) {
159 theFrame
->SetClientSize(wxScreenX
, wxScreenY
);
161 wxScreenCheckSize
= 0;
163 IFDBG_VGA(wxLogDebug(wxT("timer")));
165 IFDBG_VGA(wxLogDebug(wxT("calling refresh")));
170 void MyPanel::OnPaint(wxPaintEvent
& WXUNUSED(event
))
173 IFDBG_VGA (wxLogDebug (wxT ("OnPaint")));
176 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::OnPaint trying to get lock. wxScreen=%p", wxScreen
)));
177 wxCriticalSectionLocker
lock(wxScreen_lock
);
178 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::OnPaint got lock. wxScreen=%p", wxScreen
)));
179 if(wxScreen
!= NULL
) {
180 wxPoint pt
= GetClientAreaOrigin();
181 wxImage
screenImage(wxScreenX
, wxScreenY
, (unsigned char *)wxScreen
, TRUE
);
182 IFDBG_VGA(wxLogDebug (wxT ("drawBitmap")));
183 dc
.DrawBitmap(wxBitmap(screenImage
), pt
.x
, pt
.y
, FALSE
);
188 void MyPanel::ToggleMouse (bool fromToolbar
)
190 static bool first_enable
= true;
191 bx_param_bool_c
*enable
= SIM
->get_param_bool(BXPN_MOUSE_ENABLED
);
192 bool en
= ! enable
->get();
193 bool is_main_thread
= wxThread::IsMain ();
194 bool needmutex
= !is_main_thread
&& SIM
->is_sim_thread ();
195 if (needmutex
) wxMutexGuiEnter();
196 if (fromToolbar
&& first_enable
&& en
) {
197 // only show this help if you click on the toolbar. If they already
198 // know the shortcut, don't annoy them with the message.
200 "You have enabled the mouse in Bochs, so now your mouse actions will\n"
201 "be sent into the simulator. The usual mouse cursor will be trapped\n"
202 "inside the Bochs window until you press a CTRL key + the middle button\n"
203 "to turn mouse capture off.");
204 wxMessageBox(msg
, wxT("Mouse Capture Enabled"), wxOK
| wxICON_INFORMATION
);
205 first_enable
= false;
208 IFDBG_MOUSE (wxLogDebug (wxT ("now mouse is %sabled", en
? "en" : "dis")));
210 mouseSavedX
= wxScreenX
/ 2;
211 mouseSavedY
= wxScreenY
/ 2;
212 WarpPointer (mouseSavedX
, mouseSavedY
);
213 SetCursor (*blankCursor
);
215 SetCursor (wxNullCursor
);
217 if (needmutex
) wxMutexGuiLeave();
220 void MyPanel::OnMouse(wxMouseEvent
& event
)
223 event
.GetPosition (&x
, &y
);
225 if (event
.IsButton ()) {
226 wxLogDebug (wxT ("mouse button event at %d,%d", x
, y
));
227 } else if (event
.Entering ()) {
228 wxLogDebug (wxT ("mouse entering at %d,%d", x
, y
));
229 } else if (event
.Leaving ()) {
230 wxLogDebug (wxT ("mouse leaving at %d,%d", x
, y
));
231 } else if (event
.Moving() || event
.Dragging ()) {
232 wxLogDebug (wxT ("mouse moved to %d,%d", x
, y
));
234 wxLogDebug (wxT ("other mouse event at %d,%d", x
, y
));
238 if (event
.MiddleDown() && event
.ControlDown()) {
244 return; // mouse disabled, ignore the event
246 // process buttons and motion together
248 buttons
= event
.LeftIsDown() ? 1 : 0;
249 buttons
|= event
.RightIsDown() ? 2 : 0;
250 buttons
|= event
.MiddleIsDown() ? 4 : 0;
251 if (x
==mouseSavedX
&& y
==mouseSavedY
&& !event
.IsButton ()) {
252 // nothing happened. This could have been generated by the WarpPointer.
255 if(num_events
< MAX_EVENTS
) {
256 wxCriticalSectionLocker
lock(event_thread_lock
);
257 Bit16s dx
= x
- mouseSavedX
;
258 Bit16s dy
= y
- mouseSavedY
;
259 IFDBG_MOUSE (wxLogDebug (wxT ("mouse moved by delta %d,%d", dx
, dy
)));
260 event_queue
[num_events
].type
= BX_ASYNC_EVT_MOUSE
;
261 event_queue
[num_events
].u
.mouse
.dx
= dx
;
262 event_queue
[num_events
].u
.mouse
.dy
= -dy
;
263 event_queue
[num_events
].u
.mouse
.buttons
= buttons
;
268 wxLogDebug (wxT ("mouse event skipped because event queue full"));
272 mouseSavedX
= wxScreenX
/ 2;
273 mouseSavedY
= wxScreenY
/ 2;
274 WarpPointer (mouseSavedX
, mouseSavedY
);
275 // The WarpPointer moves the pointer back to the middle of the
276 // screen. This WILL produce another mouse motion event, which needs
277 // to be ignored. It will be ignored because the new motion event
278 // will move the cursor to (mouseSavedX, mouseSavedY).
281 void MyPanel::MyRefresh ()
283 IFDBG_VGA (wxLogDebug (wxT ("set needRefresh=true")));
287 void MyPanel::OnKeyDown(wxKeyEvent
& event
)
289 wxCriticalSectionLocker
lock(event_thread_lock
);
290 if(num_events
< MAX_EVENTS
) {
291 event_queue
[num_events
].type
= BX_ASYNC_EVT_KEY
;
292 fillBxKeyEvent (event
, event_queue
[num_events
].u
.key
, false);
298 void MyPanel::OnKeyUp(wxKeyEvent
& event
)
300 wxCriticalSectionLocker
lock(event_thread_lock
);
301 if(num_events
< MAX_EVENTS
) {
302 event_queue
[num_events
].type
= BX_ASYNC_EVT_KEY
;
303 fillBxKeyEvent (event
, event_queue
[num_events
].u
.key
, true);
308 /// copied right out of gui/x.cc
309 static char wxAsciiKey
[0x5f] = {
388 BX_KEY_RIGHT_BRACKET
,
428 BX_KEY_RIGHT_BRACKET
,
432 // copied from gui/win32.cc
433 Bit32u wxMSW_to_bx_key
[0x59] = {
463 BX_KEY_RIGHT_BRACKET
,
526 BX_KEY_LEFT_BACKSLASH
,
531 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
532 // get windows specific definitions. At present the only thing needed
533 // is the definition of HIWORD.
535 // windows.h included by bochs.h, so nothing extra is required here.
538 // MS Windows specific key mapping, which uses wxKeyEvent::m_rawCode & 2.
539 bx_bool
MyPanel::fillBxKeyEvent_MSW (wxKeyEvent
& wxev
, BxKeyEvent
& bxev
, bx_bool release
)
541 #if defined(wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
542 IFDBG_KEY(wxLogDebug (wxT ("fillBxKeyEvent_MSW. key code %d, raw codes %d %d", wxev
.m_keyCode
, wxev
.m_rawCode
, wxev
.m_rawFlags
)));
543 // this code was grabbed from gui/win32.cpp
544 Bit32u lParam
= wxev
.m_rawFlags
;
545 Bit32u key
= HIWORD (lParam
) & 0x01FF;
546 bxev
.bx_key
= 0x0000;
548 // Its an extended key
549 bxev
.bx_key
= 0xE000;
552 bxev
.bx_key
|= (key
& 0x00FF) | (release
? 0x80 : 0x00);
553 bxev
.raw_scancode
= true;
560 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
561 // get those keysym definitions
562 #include <gdk/gdkkeysyms.h>
565 // GTK specific key mapping, which uses wxKeyEvent::m_rawCode.
566 bx_bool
MyPanel::fillBxKeyEvent_GTK (wxKeyEvent
& wxev
, BxKeyEvent
& bxev
, bx_bool release
)
568 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
569 IFDBG_KEY(wxLogDebug (wxT ("fillBxKeyEvent_GTK. key code %ld, raw codes %d %d", wxev
.m_keyCode
, wxev
.m_rawCode
, wxev
.m_rawFlags
)));
570 // GTK has only 16bit key codes
571 Bit16u keysym
= (Bit32u
) wxev
.m_rawCode
;
572 Bit32u key_event
= 0;
573 // since the GDK_* symbols are very much like the X11 symbols (possibly
574 // identical), I'm using code that is copied from gui/x.cc.
575 if(!SIM
->get_param_bool(BXPN_KBD_USEMAPPING
)->get()) {
576 if (keysym
>= GDK_space
&& keysym
< GDK_asciitilde
) {
577 // use nice ASCII conversion table, based on x.cc
578 key_event
= wxAsciiKey
[keysym
- GDK_space
];
579 } else switch (keysym
) {
584 key_event
= BX_KEY_KP_END
; break;
590 key_event
= BX_KEY_KP_DOWN
; break;
593 #ifdef GDK_KP_Page_Down
594 case GDK_KP_Page_Down
:
596 key_event
= BX_KEY_KP_PAGE_DOWN
; break;
602 key_event
= BX_KEY_KP_LEFT
; break;
608 key_event
= BX_KEY_KP_5
; break;
614 key_event
= BX_KEY_KP_RIGHT
; break;
620 key_event
= BX_KEY_KP_HOME
; break;
626 key_event
= BX_KEY_KP_UP
; break;
629 #ifdef GDK_KP_Page_Up
632 key_event
= BX_KEY_KP_PAGE_UP
; break;
638 key_event
= BX_KEY_KP_INSERT
; break;
644 key_event
= BX_KEY_KP_DELETE
; break;
647 case GDK_KP_Enter
: key_event
= BX_KEY_KP_ENTER
; break;
650 case GDK_KP_Subtract
: key_event
= BX_KEY_KP_SUBTRACT
; break;
651 case GDK_KP_Add
: key_event
= BX_KEY_KP_ADD
; break;
653 case GDK_KP_Multiply
: key_event
= BX_KEY_KP_MULTIPLY
; break;
654 case GDK_KP_Divide
: key_event
= BX_KEY_KP_DIVIDE
; break;
657 case GDK_Up
: key_event
= BX_KEY_UP
; break;
658 case GDK_Down
: key_event
= BX_KEY_DOWN
; break;
659 case GDK_Left
: key_event
= BX_KEY_LEFT
; break;
660 case GDK_Right
: key_event
= BX_KEY_RIGHT
; break;
663 case GDK_Delete
: key_event
= BX_KEY_DELETE
; break;
664 case GDK_BackSpace
: key_event
= BX_KEY_BACKSPACE
; break;
665 case GDK_Tab
: key_event
= BX_KEY_TAB
; break;
666 #ifdef GDK_ISO_Left_Tab
667 case GDK_ISO_Left_Tab
: key_event
= BX_KEY_TAB
; break;
669 case GDK_Return
: key_event
= BX_KEY_ENTER
; break;
670 case GDK_Escape
: key_event
= BX_KEY_ESC
; break;
671 case GDK_F1
: key_event
= BX_KEY_F1
; break;
672 case GDK_F2
: key_event
= BX_KEY_F2
; break;
673 case GDK_F3
: key_event
= BX_KEY_F3
; break;
674 case GDK_F4
: key_event
= BX_KEY_F4
; break;
675 case GDK_F5
: key_event
= BX_KEY_F5
; break;
676 case GDK_F6
: key_event
= BX_KEY_F6
; break;
677 case GDK_F7
: key_event
= BX_KEY_F7
; break;
678 case GDK_F8
: key_event
= BX_KEY_F8
; break;
679 case GDK_F9
: key_event
= BX_KEY_F9
; break;
680 case GDK_F10
: key_event
= BX_KEY_F10
; break;
681 case GDK_F11
: key_event
= BX_KEY_F11
; break;
682 case GDK_F12
: key_event
= BX_KEY_F12
; break;
683 case GDK_Control_L
: key_event
= BX_KEY_CTRL_L
; break;
685 case GDK_Control_R
: key_event
= BX_KEY_CTRL_R
; break;
687 case GDK_Shift_L
: key_event
= BX_KEY_SHIFT_L
; break;
688 case GDK_Shift_R
: key_event
= BX_KEY_SHIFT_R
; break;
689 case GDK_Alt_L
: key_event
= BX_KEY_ALT_L
; break;
691 case GDK_Alt_R
: key_event
= BX_KEY_ALT_R
; break;
693 case GDK_Caps_Lock
: key_event
= BX_KEY_CAPS_LOCK
; break;
694 case GDK_Num_Lock
: key_event
= BX_KEY_NUM_LOCK
; break;
695 #ifdef GDK_Scroll_Lock
696 case GDK_Scroll_Lock
: key_event
= BX_KEY_SCRL_LOCK
; break;
699 case GDK_Print
: key_event
= BX_KEY_PRINT
; break;
702 case GDK_Pause
: key_event
= BX_KEY_PAUSE
; break;
705 case GDK_Insert
: key_event
= BX_KEY_INSERT
; break;
706 case GDK_Home
: key_event
= BX_KEY_HOME
; break;
707 case GDK_End
: key_event
= BX_KEY_END
; break;
708 case GDK_Page_Up
: key_event
= BX_KEY_PAGE_UP
; break;
709 case GDK_Page_Down
: key_event
= BX_KEY_PAGE_DOWN
; break;
712 case GDK_Menu
: key_event
= BX_KEY_MENU
; break;
715 case GDK_Super_L
: key_event
= BX_KEY_WIN_L
; break;
718 case GDK_Super_R
: key_event
= BX_KEY_WIN_R
; break;
722 wxLogError(wxT("fillBxKeyEvent_GTK(): keysym %x unhandled!"), (unsigned) keysym
);
723 return BX_KEY_UNHANDLED
;
727 BXKeyEntry
*entry
= bx_keymap
.findHostKey (keysym
);
729 BX_ERROR(("fillBxKeyEvent_GTK(): keysym %x unhandled!", (unsigned) keysym
));
730 return BX_KEY_UNHANDLED
;
732 key_event
= entry
->baseKey
;
734 bxev
.bx_key
= key_event
| (release
? BX_KEY_RELEASED
: BX_KEY_PRESSED
);
735 bxev
.raw_scancode
= false;
737 #else // if GTK toolkit
742 bx_bool
MyPanel::fillBxKeyEvent (wxKeyEvent
& wxev
, BxKeyEvent
& bxev
, bx_bool release
)
744 // Use raw codes if they are available. Raw codes are a nonstandard addition
745 // to the wxWidgets library. At present, the only way to use the "RAW_CODES"
746 // mode is to apply Bryce's "patch.wx-raw-keycodes" patch to the wxWidgets
747 // sources and recompile. This patch, or something like it, should appear in
748 // future wxWidgets versions.
750 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
751 return fillBxKeyEvent_MSW (wxev
, bxev
, release
);
754 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
755 return fillBxKeyEvent_GTK (wxev
, bxev
, release
);
758 // otherwise fall back to using portable WXK_* keycodes. Not all keys
759 // can be mapped correctly using WXK_* codes but it should be usable.
760 IFDBG_KEY (wxLogDebug (wxT ("fillBxKeyEvent. key code %ld", wxev
.m_keyCode
)));
761 Bit32u key
= wxev
.m_keyCode
;
764 if(key
>= WXK_SPACE
&& key
< WXK_DELETE
) {
765 bx_key
= wxAsciiKey
[key
- WXK_SPACE
];
767 // handle extended keys here
769 case WXK_BACK
: bx_key
= BX_KEY_BACKSPACE
; break;
770 case WXK_TAB
: bx_key
= BX_KEY_TAB
; break;
771 case WXK_RETURN
: bx_key
= BX_KEY_ENTER
; break;
772 case WXK_ESCAPE
: bx_key
= BX_KEY_ESC
; break;
773 case WXK_DELETE
: bx_key
= BX_KEY_DELETE
; break;
774 case WXK_SHIFT
: bx_key
= BX_KEY_SHIFT_L
; break;
775 case WXK_CONTROL
: bx_key
= BX_KEY_CTRL_L
; break;
776 case WXK_ALT
: bx_key
= BX_KEY_ALT_L
; break;
777 case WXK_MENU
: bx_key
= BX_KEY_MENU
; break;
778 case WXK_PAUSE
: bx_key
= BX_KEY_PAUSE
; break;
779 case WXK_PRIOR
: bx_key
= BX_KEY_PAGE_UP
; break;
780 case WXK_NEXT
: bx_key
= BX_KEY_PAGE_DOWN
; break;
781 case WXK_END
: bx_key
= BX_KEY_END
; break;
782 case WXK_HOME
: bx_key
= BX_KEY_HOME
; break;
783 case WXK_LEFT
: bx_key
= BX_KEY_LEFT
; break;
784 case WXK_UP
: bx_key
= BX_KEY_UP
; break;
785 case WXK_RIGHT
: bx_key
= BX_KEY_RIGHT
; break;
786 case WXK_DOWN
: bx_key
= BX_KEY_DOWN
; break;
787 case WXK_INSERT
: bx_key
= BX_KEY_INSERT
; break;
788 case WXK_NUMPAD0
: bx_key
= BX_KEY_KP_INSERT
; break;
789 case WXK_NUMPAD1
: bx_key
= BX_KEY_KP_END
; break;
790 case WXK_NUMPAD2
: bx_key
= BX_KEY_KP_DOWN
; break;
791 case WXK_NUMPAD3
: bx_key
= BX_KEY_KP_PAGE_DOWN
; break;
792 case WXK_NUMPAD4
: bx_key
= BX_KEY_KP_LEFT
; break;
793 case WXK_NUMPAD5
: bx_key
= BX_KEY_KP_5
; break;
794 case WXK_NUMPAD6
: bx_key
= BX_KEY_KP_RIGHT
; break;
795 case WXK_NUMPAD7
: bx_key
= BX_KEY_KP_HOME
; break;
796 case WXK_NUMPAD8
: bx_key
= BX_KEY_KP_UP
; break;
797 case WXK_NUMPAD9
: bx_key
= BX_KEY_KP_PAGE_UP
; break;
798 case WXK_F1
: bx_key
= BX_KEY_F1
; break;
799 case WXK_F2
: bx_key
= BX_KEY_F2
; break;
800 case WXK_F3
: bx_key
= BX_KEY_F3
; break;
801 case WXK_F4
: bx_key
= BX_KEY_F4
; break;
802 case WXK_F5
: bx_key
= BX_KEY_F5
; break;
803 case WXK_F6
: bx_key
= BX_KEY_F6
; break;
804 case WXK_F7
: bx_key
= BX_KEY_F7
; break;
805 case WXK_F8
: bx_key
= BX_KEY_F8
; break;
806 case WXK_F9
: bx_key
= BX_KEY_F9
; break;
807 case WXK_F10
: bx_key
= BX_KEY_F10
; break;
808 case WXK_F11
: bx_key
= BX_KEY_F11
; break;
809 case WXK_F12
: bx_key
= BX_KEY_F12
; break;
810 case WXK_NUMLOCK
: bx_key
= BX_KEY_NUM_LOCK
; break;
811 case WXK_SCROLL
: bx_key
= BX_KEY_SCRL_LOCK
; break;
812 case WXK_DECIMAL
: bx_key
= BX_KEY_PERIOD
; break;
813 case WXK_SUBTRACT
: bx_key
= BX_KEY_MINUS
; break;
814 case WXK_ADD
: bx_key
= BX_KEY_EQUALS
; break;
815 case WXK_MULTIPLY
: bx_key
= BX_KEY_KP_MULTIPLY
; break;
816 case WXK_DIVIDE
: bx_key
= BX_KEY_KP_DIVIDE
; break;
818 case WXK_NUMPAD_ENTER
: bx_key
= BX_KEY_KP_ENTER
; break;
819 case WXK_NUMPAD_HOME
: bx_key
= BX_KEY_KP_HOME
; break;
820 case WXK_NUMPAD_LEFT
: bx_key
= BX_KEY_KP_LEFT
; break;
821 case WXK_NUMPAD_UP
: bx_key
= BX_KEY_KP_UP
; break;
822 case WXK_NUMPAD_RIGHT
: bx_key
= BX_KEY_KP_RIGHT
; break;
823 case WXK_NUMPAD_DOWN
: bx_key
= BX_KEY_KP_DOWN
; break;
824 case WXK_NUMPAD_PRIOR
: bx_key
= BX_KEY_KP_PAGE_UP
; break;
825 case WXK_NUMPAD_PAGEUP
: bx_key
= BX_KEY_KP_PAGE_UP
; break;
826 case WXK_NUMPAD_NEXT
: bx_key
= BX_KEY_KP_PAGE_DOWN
; break;
827 case WXK_NUMPAD_PAGEDOWN
: bx_key
= BX_KEY_KP_PAGE_DOWN
; break;
828 case WXK_NUMPAD_END
: bx_key
= BX_KEY_KP_END
; break;
829 case WXK_NUMPAD_BEGIN
: bx_key
= BX_KEY_KP_HOME
; break;
830 case WXK_NUMPAD_INSERT
: bx_key
= BX_KEY_KP_INSERT
; break;
831 case WXK_NUMPAD_DELETE
: bx_key
= BX_KEY_KP_DELETE
; break;
832 case WXK_NUMPAD_EQUAL
: bx_key
= BX_KEY_KP_ENTER
; break;
833 case WXK_NUMPAD_MULTIPLY
: bx_key
= BX_KEY_KP_MULTIPLY
; break;
834 case WXK_NUMPAD_SUBTRACT
: bx_key
= BX_KEY_KP_SUBTRACT
; break;
835 case WXK_NUMPAD_DECIMAL
: bx_key
= BX_KEY_KP_DELETE
; break;
836 case WXK_NUMPAD_DIVIDE
: bx_key
= BX_KEY_KP_DIVIDE
; break;
838 // Keys not handled by wxMSW
839 case 20: bx_key
= BX_KEY_CAPS_LOCK
; break; // =+
840 case 186: bx_key
= BX_KEY_SEMICOLON
; break; // ;:
841 case 187: bx_key
= BX_KEY_EQUALS
; break; // =+
842 case 188: bx_key
= BX_KEY_COMMA
; break; // ,<
843 case 189: bx_key
= BX_KEY_MINUS
; break; // -_
844 case 190: bx_key
= BX_KEY_PERIOD
; break; // .>
845 case 191: bx_key
= BX_KEY_SLASH
; break; // /?
846 case 192: bx_key
= BX_KEY_GRAVE
; break; // `~
847 case 219: bx_key
= BX_KEY_LEFT_BRACKET
; break; // [{
848 case 221: bx_key
= BX_KEY_RIGHT_BRACKET
; break; // ]}
849 case 220: bx_key
= BX_KEY_BACKSLASH
; break; // \|
850 case 222: bx_key
= BX_KEY_SINGLE_QUOTE
; break; // '"
851 case 305: bx_key
= BX_KEY_KP_5
; break; // keypad 5
852 case 392: bx_key
= BX_KEY_KP_ADD
; break; // keypad plus
855 wxLogMessage(wxT ("Unhandled key event: %i (0x%x)"), key
, key
);
859 IFDBG_KEY (wxLogDebug (wxT ("fillBxKeyEvent: after remapping, key=%d"), bx_key
));
860 bxev
.bx_key
= bx_key
| (release
? BX_KEY_RELEASED
: BX_KEY_PRESSED
);
861 bxev
.raw_scancode
= false;
865 //////////////////////////////////////////////////////////////
866 // fill in methods of bx_gui
867 //////////////////////////////////////////////////////////////
869 void bx_wx_gui_c::specific_init(int argc
, char **argv
, unsigned tilewidth
, unsigned tileheight
,
870 unsigned headerbar_y
)
873 unsigned char fc
, vc
;
876 if (SIM
->get_param_bool(BXPN_PRIVATE_COLORMAP
)->get()) {
877 BX_INFO(("private_colormap option ignored."));
880 for(i
= 0; i
< 256; i
++) {
881 wxBochsPalette
[i
].red
= 0;
882 wxBochsPalette
[i
].green
= 0;
883 wxBochsPalette
[i
].blue
= 0;
886 for(i
= 0; i
< 256; i
++) {
887 for(j
= 0; j
< 16; j
++) {
888 vc
= bx_vgafont
[i
].data
[j
];
890 for (b
= 0; b
< 8; b
++) {
891 fc
|= (vc
& 0x01) << (7 - b
);
894 vga_charmap
[i
*32+j
] = fc
;
900 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::specific_init trying to get lock. wxScreen=%p", wxScreen
)));
901 wxCriticalSectionLocker
lock(wxScreen_lock
);
902 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::specific_init got lock. wxScreen=%p", wxScreen
)));
903 if (wxScreen
== NULL
) {
904 wxScreen
= (char *)malloc(wxScreenX
* wxScreenY
* 3);
906 wxScreen
= (char *)realloc(wxScreen
, wxScreenX
* wxScreenY
* 3);
908 memset(wxScreen
, 0, wxScreenX
* wxScreenY
* 3);
911 wxTileY
= tileheight
;
913 // load keymap tables
914 if (SIM
->get_param_bool(BXPN_KBD_USEMAPPING
)->get())
915 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
916 bx_keymap
.loadKeymap(convertStringToGDKKey
);
918 bx_keymap
.loadKeymap(NULL
);
922 dialog_caps
= BX_GUI_DLG_USER
| BX_GUI_DLG_SNAPSHOT
| BX_GUI_DLG_SAVE_RESTORE
;
927 // Called periodically (vga_update_interval in .bochsrc) so the
928 // the gui code can poll for keyboard, mouse, and other
931 void bx_wx_gui_c::handle_events(void)
933 wxCriticalSectionLocker
lock(event_thread_lock
);
935 for(unsigned int i
= 0; i
< num_events
; i
++) {
936 switch(event_queue
[i
].type
) {
937 case BX_ASYNC_EVT_TOOLBAR
:
938 switch (event_queue
[i
].u
.toolbar
.button
) {
939 case BX_TOOLBAR_FLOPPYA
: floppyA_handler(); break;
940 case BX_TOOLBAR_FLOPPYB
: floppyB_handler(); break;
941 case BX_TOOLBAR_CDROMD
: cdromD_handler(); break;
942 case BX_TOOLBAR_RESET
: reset_handler(); break;
943 case BX_TOOLBAR_POWER
: power_handler(); break;
944 case BX_TOOLBAR_SAVE_RESTORE
: save_restore_handler(); break;
945 case BX_TOOLBAR_COPY
: copy_handler(); break;
946 case BX_TOOLBAR_PASTE
: paste_handler(); break;
947 case BX_TOOLBAR_SNAPSHOT
: snapshot_handler(); break;
948 case BX_TOOLBAR_CONFIG
: config_handler(); break;
949 case BX_TOOLBAR_MOUSE_EN
: thePanel
->ToggleMouse(true); break;
950 case BX_TOOLBAR_USER
: userbutton_handler(); break;
952 wxLogDebug (wxT ("unknown toolbar id %d"), event_queue
[i
].u
.toolbar
.button
);
955 case BX_ASYNC_EVT_KEY
:
956 bx_key
= event_queue
[i
].u
.key
.bx_key
;
957 if (event_queue
[i
].u
.key
.raw_scancode
) {
958 // event contains raw scancodes: convert to BX_KEY values first
959 bx_bool released
= ((bx_key
& 0x80) > 0);
960 if (bx_key
& 0xFF00) { // for extended keys
961 switch (bx_key
& 0x7f) {
963 bx_key
= BX_KEY_KP_ENTER
;
966 bx_key
= BX_KEY_CTRL_R
;
969 bx_key
= BX_KEY_KP_DIVIDE
;
972 // This makes the "AltGr" key on European keyboards work
973 DEV_kbd_gen_scancode(BX_KEY_CTRL_L
| BX_KEY_RELEASED
);
974 bx_key
= BX_KEY_ALT_R
;
977 bx_key
= BX_KEY_NUM_LOCK
;
980 bx_key
= BX_KEY_HOME
;
986 bx_key
= BX_KEY_PAGE_UP
;
989 bx_key
= BX_KEY_LEFT
;
992 bx_key
= BX_KEY_RIGHT
;
998 bx_key
= BX_KEY_DOWN
;
1001 bx_key
= BX_KEY_PAGE_DOWN
;
1004 bx_key
= BX_KEY_INSERT
;
1007 bx_key
= BX_KEY_DELETE
;
1010 bx_key
= BX_KEY_WIN_L
;
1013 bx_key
= BX_KEY_WIN_R
;
1016 bx_key
= BX_KEY_MENU
;
1020 bx_key
= wxMSW_to_bx_key
[bx_key
& 0x7f];
1022 if (released
) bx_key
|= BX_KEY_RELEASED
;
1024 // event contains BX_KEY_* codes: use gen_scancode
1025 IFDBG_KEY (wxLogDebug (wxT ("sending key event 0x%02x", bx_key
)));
1026 DEV_kbd_gen_scancode(bx_key
);
1028 case BX_ASYNC_EVT_MOUSE
:
1030 event_queue
[i
].u
.mouse
.dx
,
1031 event_queue
[i
].u
.mouse
.dy
,
1032 event_queue
[i
].u
.mouse
.buttons
);
1035 wxLogError (wxT ("handle_events received unhandled event type %d in queue"), (int)event_queue
[i
].type
);
1041 void bx_wx_gui_c::statusbar_setitem(int element
, bx_bool active
, bx_bool w
)
1043 #if defined(__WXMSW__)
1044 char status_text
[10];
1049 for (unsigned i
= 0; i
< statusitem_count
; i
++) {
1051 #if defined(__WXMSW__)
1053 strcpy(status_text
+1, statusitem_text
[i
]);
1054 theFrame
->SetStatusText(status_text
, i
+1);
1056 theFrame
->SetStatusText(wxString(statusitem_text
[i
], wxConvUTF8
), i
+1);
1059 theFrame
->SetStatusText(wxT(""), i
+1);
1062 } else if ((unsigned)element
< statusitem_count
) {
1064 #if defined(__WXMSW__)
1066 strcpy(status_text
+1, statusitem_text
[element
]);
1067 theFrame
->SetStatusText(status_text
, element
+1);
1069 theFrame
->SetStatusText(wxString(statusitem_text
[element
], wxConvUTF8
),
1073 theFrame
->SetStatusText(wxT(""), element
+1);
1081 // Called periodically, requesting that the gui code flush all pending
1082 // screen update requests.
1084 void bx_wx_gui_c::flush(void)
1090 // Called to request that the VGA region is cleared. Don't
1091 // clear the area that defines the headerbar.
1093 void bx_wx_gui_c::clear_screen(void)
1095 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::clear_screen trying to get lock. wxScreen=%p", wxScreen
)));
1096 wxCriticalSectionLocker
lock(wxScreen_lock
);
1097 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::clear_screen got lock. wxScreen=%p", wxScreen
)));
1098 memset(wxScreen
, 0, wxScreenX
* wxScreenY
* 3);
1099 thePanel
->MyRefresh ();
1102 static void UpdateScreen(unsigned char *newBits
, int x
, int y
, int width
, int height
)
1104 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::UpdateScreen trying to get lock. wxScreen=%p", wxScreen
)));
1105 wxCriticalSectionLocker
lock(wxScreen_lock
);
1106 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::UpdateScreen got lock. wxScreen=%p", wxScreen
)));
1107 if(wxScreen
!= NULL
) {
1110 for(int i
= 0; i
< height
; i
++) {
1111 char *pwxScreen
= &wxScreen
[(y
* wxScreenX
* 3) + (x
* 3)];
1112 for(int c
= 0; c
< width
; c
++) {
1113 unsigned pixel
= (i
* width
) + c
;
1114 pwxScreen
[0] = wxBochsPalette
[newBits
[pixel
]].red
;
1115 pwxScreen
[1] = wxBochsPalette
[newBits
[pixel
]].green
;
1116 pwxScreen
[2] = wxBochsPalette
[newBits
[pixel
]].blue
;
1120 if(y
>= wxScreenY
) break;
1124 BX_PANIC(("%u bpp modes handled by new graphics API", vga_bpp
));
1128 IFDBG_VGA (wxLogDebug (wxT ("UpdateScreen with null wxScreen")));
1132 static void DrawBochsBitmap(int x
, int y
, int width
, int height
, char *bmap
, char color
, int fontx
, int fonty
, bx_bool gfxchar
)
1134 static unsigned char newBits
[9 * 32];
1136 int bytes
= width
* height
;
1137 char bgcolor
= DEV_vga_get_actl_pal_idx((color
>> 4) & 0xF);
1138 char fgcolor
= DEV_vga_get_actl_pal_idx(color
& 0xF);
1140 if (y
> wxScreenY
) return;
1142 for(int i
= 0; i
< bytes
; i
+=width
) {
1143 mask
= 0x80 >> fontx
;
1144 for(int j
= 0; j
< width
; j
++) {
1146 newBits
[i
+ j
] = (bmap
[fonty
] & mask
) ? fgcolor
: bgcolor
;
1149 newBits
[i
+ j
] = (bmap
[fonty
] & 0x01) ? fgcolor
: bgcolor
;
1151 newBits
[i
+ j
] = bgcolor
;
1158 UpdateScreen(newBits
, x
, y
, width
, height
);
1164 // Called in a VGA text mode, to update the screen with
1167 // old_text: array of character/attributes making up the contents
1168 // of the screen from the last call. See below
1169 // new_text: array of character/attributes making up the current
1170 // contents, which should now be displayed. See below
1172 // format of old_text & new_text: each is tm_info.line_offset*text_rows
1173 // bytes long. Each character consists of 2 bytes. The first by is
1174 // the character value, the second is the attribute byte.
1176 // cursor_x: new x location of cursor
1177 // cursor_y: new y location of cursor
1178 // tm_info: this structure contains information for additional
1179 // features in text mode (cursor shape, line offset,...)
1181 void bx_wx_gui_c::text_update(Bit8u
*old_text
, Bit8u
*new_text
,
1182 unsigned long cursor_x
, unsigned long cursor_y
,
1183 bx_vga_tminfo_t tm_info
)
1185 IFDBG_VGA(wxLogDebug (wxT ("text_update")));
1187 Bit8u
*old_line
, *new_line
, *text_base
;
1189 unsigned int curs
, hchars
, offset
, rows
, x
, y
, xc
, yc
, yc2
, cs_y
;
1190 Bit8u cfwidth
, cfheight
, cfheight2
, font_col
, font_row
, font_row2
;
1191 Bit8u split_textrow
, split_fontrows
;
1192 bx_bool forceUpdate
= 0, gfxchar
, split_screen
, blink_state
, blink_mode
;
1194 // first check if the screen needs to be redrawn completely
1195 blink_mode
= (tm_info
.blink_flags
& BX_TEXT_BLINK_MODE
) > 0;
1196 blink_state
= (tm_info
.blink_flags
& BX_TEXT_BLINK_STATE
) > 0;
1198 if (tm_info
.blink_flags
& BX_TEXT_BLINK_TOGGLE
)
1201 if(charmap_updated
) {
1203 charmap_updated
= 0;
1205 if((tm_info
.h_panning
!= h_panning
) || (tm_info
.v_panning
!= v_panning
)) {
1207 h_panning
= tm_info
.h_panning
;
1208 v_panning
= tm_info
.v_panning
;
1210 if(tm_info
.line_compare
!= line_compare
) {
1212 line_compare
= tm_info
.line_compare
;
1215 // invalidate character at previous and new cursor location
1216 if((wxCursorY
< text_rows
) && (wxCursorX
< text_cols
)) {
1217 curs
= wxCursorY
* tm_info
.line_offset
+ wxCursorX
* 2;
1218 old_text
[curs
] = ~new_text
[curs
];
1220 if((tm_info
.cs_start
<= tm_info
.cs_end
) && (tm_info
.cs_start
< wxFontY
) &&
1221 (cursor_y
< text_rows
) && (cursor_x
< text_cols
)) {
1222 curs
= cursor_y
* tm_info
.line_offset
+ cursor_x
* 2;
1223 old_text
[curs
] = ~new_text
[curs
];
1229 if (v_panning
) rows
++;
1232 text_base
= new_text
- tm_info
.start_address
;
1233 split_textrow
= (line_compare
+ v_panning
) / wxFontY
;
1234 split_fontrows
= ((line_compare
+ v_panning
) % wxFontY
) + 1;
1238 if (h_panning
) hchars
++;
1240 yc
= line_compare
+ cs_y
* wxFontY
+ 1;
1243 cfheight
= (wxScreenY
- line_compare
- 1) % wxFontY
;
1244 if (cfheight
== 0) cfheight
= wxFontY
;
1248 } else if (v_panning
) {
1251 font_row
= v_panning
;
1252 cfheight
= wxFontY
- v_panning
;
1254 yc
= y
* wxFontY
- v_panning
;
1257 cfheight
= v_panning
;
1267 if (!split_screen
&& (y
== split_textrow
)) {
1268 if (split_fontrows
< cfheight
) cfheight
= split_fontrows
;
1270 new_line
= new_text
;
1271 old_line
= old_text
;
1273 offset
= cs_y
* tm_info
.line_offset
;
1276 if (hchars
> text_cols
) {
1278 font_col
= h_panning
;
1279 cfwidth
= wxFontX
- h_panning
;
1281 xc
= x
* wxFontX
- h_panning
;
1284 cfwidth
= h_panning
;
1294 if(forceUpdate
|| (old_text
[0] != new_text
[0])
1295 || (old_text
[1] != new_text
[1])) {
1296 cChar
= new_text
[0];
1298 cAttr
= new_text
[1] & 0x7F;
1299 if (!blink_state
&& (new_text
[1] & 0x80))
1300 cAttr
= (cAttr
& 0x70) | (cAttr
>> 4);
1302 cAttr
= new_text
[1];
1304 gfxchar
= tm_info
.line_graphics
&& ((cChar
& 0xE0) == 0xC0);
1305 DrawBochsBitmap(xc
, yc
, cfwidth
, cfheight
, (char *)&vga_charmap
[cChar
<<5],
1306 cAttr
, font_col
, font_row
, gfxchar
);
1307 if (offset
== curs
) {
1308 if (font_row
== 0) {
1309 yc2
= yc
+ tm_info
.cs_start
;
1310 font_row2
= tm_info
.cs_start
;
1311 cfheight2
= tm_info
.cs_end
- tm_info
.cs_start
+ 1;
1313 if (v_panning
> tm_info
.cs_start
) {
1315 font_row2
= font_row
;
1316 cfheight2
= tm_info
.cs_end
- v_panning
+ 1;
1318 yc2
= yc
+ tm_info
.cs_start
- v_panning
;
1319 font_row2
= tm_info
.cs_start
;
1320 cfheight2
= tm_info
.cs_end
- tm_info
.cs_start
+ 1;
1323 cAttr
= ((cAttr
>> 4) & 0xF) + ((cAttr
& 0xF) << 4);
1324 DrawBochsBitmap(xc
, yc2
, cfwidth
, cfheight2
, (char *)&vga_charmap
[cChar
<<5],
1325 cAttr
, font_col
, font_row2
, gfxchar
);
1333 if (!split_screen
&& (y
== split_textrow
)) {
1334 new_text
= text_base
;
1337 if (tm_info
.split_hpanning
) h_panning
= 0;
1338 rows
= ((wxScreenY
- line_compare
+ wxFontY
- 2) / wxFontY
) + 1;
1343 new_text
= new_line
+ tm_info
.line_offset
;
1344 old_text
= old_line
+ tm_info
.line_offset
;
1348 h_panning
= tm_info
.h_panning
;
1349 wxCursorX
= cursor_x
;
1350 wxCursorY
= cursor_y
;
1352 thePanel
->MyRefresh();
1355 // ::PALETTE_CHANGE()
1357 // Allocate a color in the native GUI, for this color, and put
1358 // it in the colormap location 'index'.
1359 // returns: 0=no screen update needed (color map change has direct effect)
1360 // 1=screen update needed (redraw using current colormap)
1362 bx_bool
bx_wx_gui_c::palette_change(unsigned index
, unsigned red
, unsigned green
, unsigned blue
)
1364 IFDBG_VGA(wxLogDebug (wxT ("palette_change")));
1365 wxBochsPalette
[index
].red
= red
;
1366 wxBochsPalette
[index
].green
= green
;
1367 wxBochsPalette
[index
].blue
= blue
;
1368 return(1); // screen update needed
1372 // ::GRAPHICS_TILE_UPDATE()
1374 // Called to request that a tile of graphics be drawn to the
1375 // screen, since info in this region has changed.
1377 // tile: array of 8bit values representing a block of pixels with
1378 // dimension equal to the 'tilewidth' & 'tileheight' parameters to
1379 // ::specific_init(). Each value specifies an index into the
1380 // array of colors you allocated for ::palette_change()
1381 // x0: x origin of tile
1382 // y0: y origin of tile
1384 // note: origin of tile and of window based on (0,0) being in the upper
1385 // left of the window.
1387 void bx_wx_gui_c::graphics_tile_update(Bit8u
*tile
, unsigned x0
, unsigned y0
)
1389 IFDBG_VGA (wxLogDebug (wxT ("graphics_tile_update")));
1390 UpdateScreen(tile
, x0
, y0
, wxTileX
, wxTileY
);
1391 thePanel
->MyRefresh();
1394 bx_svga_tileinfo_t
*bx_wx_gui_c::graphics_tile_info(bx_svga_tileinfo_t
*info
)
1397 info
= (bx_svga_tileinfo_t
*)malloc(sizeof(bx_svga_tileinfo_t
));
1404 info
->pitch
= wxScreenX
* 3;
1405 info
->red_shift
= 8;
1406 info
->green_shift
= 16;
1407 info
->blue_shift
= 24;
1408 info
->red_mask
= 0x0000ff;
1409 info
->green_mask
= 0x00ff00;
1410 info
->blue_mask
= 0xff0000;
1411 info
->is_indexed
= 0;
1412 #ifdef BX_LITTLE_ENDIAN
1413 info
->is_little_endian
= 1;
1415 info
->is_little_endian
= 0;
1421 Bit8u
*bx_wx_gui_c::graphics_tile_get(unsigned x0
, unsigned y0
,
1422 unsigned *w
, unsigned *h
)
1424 if (x0
+wxTileX
> (unsigned)wxScreenX
) {
1425 *w
= wxScreenX
- x0
;
1431 if (y0
+wxTileY
> (unsigned)wxScreenY
) {
1432 *h
= wxScreenY
- y0
;
1438 return (Bit8u
*)wxScreen
+ y0
* wxScreenX
* 3 + x0
* 3;
1441 void bx_wx_gui_c::graphics_tile_update_in_place(unsigned x0
, unsigned y0
,
1442 unsigned w
, unsigned h
)
1444 thePanel
->MyRefresh();
1447 // ::DIMENSION_UPDATE()
1449 // Called from the simulator when the VGA mode changes it's X,Y dimensions.
1450 // Resize the window to this size, but you need to add on
1451 // the height of the headerbar to the Y value.
1453 // x: new VGA x size
1454 // y: new VGA y size
1455 // fheight: new VGA character height in text mode
1456 // fwidth : new VGA character width in text mode
1457 // bpp : bits per pixel in graphics mode
1459 void bx_wx_gui_c::dimension_update(unsigned x
, unsigned y
, unsigned fheight
, unsigned fwidth
, unsigned bpp
)
1461 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::dimension_update trying to get lock. wxScreen=%p", wxScreen
)));
1462 wxScreen_lock
.Enter ();
1463 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::dimension_update got lock. wxScreen=%p", wxScreen
)));
1464 BX_INFO (("dimension update x=%d y=%d fontheight=%d fontwidth=%d bpp=%d", x
, y
, fheight
, fwidth
, bpp
));
1465 if ((bpp
== 8) || (bpp
== 15) || (bpp
== 16) || (bpp
== 24) || (bpp
== 32)) {
1466 if (bpp
== 32) BX_INFO(("wxWidgets ignores bit 24..31 in 32bpp mode"));
1471 BX_PANIC(("%d bpp graphics mode not supported", bpp
));
1476 text_cols
= x
/ wxFontX
;
1477 text_rows
= y
/ wxFontY
;
1481 wxScreen
= (char *)realloc(wxScreen
, wxScreenX
* wxScreenY
* 3);
1482 wxASSERT (wxScreen
!= NULL
);
1483 wxScreen_lock
.Leave ();
1484 IFDBG_VGA(wxLogDebug (wxT ("MyPanel::dimension_update gave up lock. wxScreen=%p", wxScreen
)));
1485 // Note: give up wxScreen_lock before calling SetClientSize. I did
1486 // this because I was sometimes seeing thread deadlock in win32, apparantly
1487 // related to wxStreen_lock. The wxWidgets GUI thread was sitting in OnPaint
1488 // trying to get the wxScreen_lock, and the simulation thread was stuck in some
1489 // native win32 function called by SetClientSize (below). As with many
1490 // thread problems, it happened sporadically so it's hard to prove that this
1491 // really fixed it. -bbd
1493 // this method is called from the simulation thread, so we must get the GUI
1494 // thread mutex first to be safe.
1496 theFrame
->SetClientSize(wxScreenX
, wxScreenY
);
1499 thePanel
->MyRefresh();
1500 wxScreenCheckSize
= 1;
1504 // ::CREATE_BITMAP()
1506 // Create a monochrome bitmap of size 'xdim' by 'ydim', which will
1507 // be drawn in the headerbar. Return an integer ID to the bitmap,
1508 // with which the bitmap can be referenced later.
1510 // bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
1511 // bit0 is the left most pixel, bit7 is the right most pixel.
1512 // xdim: x dimension of bitmap
1513 // ydim: y dimension of bitmap
1515 unsigned bx_wx_gui_c::create_bitmap(const unsigned char *bmap
, unsigned xdim
, unsigned ydim
)
1524 // ::HEADERBAR_BITMAP()
1526 // Called to install a bitmap in the bochs headerbar (toolbar).
1528 // bmap_id: will correspond to an ID returned from
1529 // ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
1530 // or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
1531 // available leftmost or rightmost space.
1532 // alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
1533 // meaning install the bitmap in the next
1534 // available leftmost or rightmost space.
1535 // f: a 'C' function pointer to callback when the mouse is clicked in
1536 // the boundaries of this bitmap.
1538 unsigned bx_wx_gui_c::headerbar_bitmap(unsigned bmap_id
, unsigned alignment
, void (*f
)(void))
1546 // ::SHOW_HEADERBAR()
1548 // Show (redraw) the current headerbar, which is composed of
1549 // currently installed bitmaps.
1551 void bx_wx_gui_c::show_headerbar(void)
1555 // ::REPLACE_BITMAP()
1557 // Replace the bitmap installed in the headerbar ID slot 'hbar_id',
1558 // with the one specified by 'bmap_id'. 'bmap_id' will have
1559 // been generated by ::create_bitmap(). The old and new bitmap
1560 // must be of the same size. This allows the bitmap the user
1561 // sees to change, when some action occurs. For example when
1562 // the user presses on the floppy icon, it then displays
1563 // the ejected status.
1565 // hbar_id: headerbar slot ID
1566 // bmap_id: bitmap ID
1569 bx_wx_gui_c::replace_bitmap(unsigned hbar_id
, unsigned bmap_id
)
1578 // Called before bochs terminates, to allow for a graceful
1579 // exit from the native GUI mechanism.
1581 void bx_wx_gui_c::exit(void)
1586 void bx_wx_gui_c::mouse_enabled_changed_specific(bx_bool val
)
1588 mouse_captured
= val
;
1591 int bx_wx_gui_c::get_clipboard_text(Bit8u
**bytes
, Bit32s
*nbytes
)
1595 if (wxTheClipboard
->Open()) {
1596 if (wxTheClipboard
->IsSupported(wxDF_TEXT
)) {
1597 wxTextDataObject data
;
1598 wxTheClipboard
->GetData(data
);
1599 wxString str
= data
.GetText();
1600 int len
= str
.Len();
1601 Bit8u
*buf
= new Bit8u
[len
];
1602 memcpy(buf
, str
.mb_str(wxConvUTF8
), len
);
1606 // buf will be freed in bx_keyb_c::paste_bytes or
1607 // bx_keyb_c::service_paste_buf, using delete [].
1609 BX_ERROR (("paste: could not open wxWidgets clipboard"));
1611 wxTheClipboard
->Close();
1617 int bx_wx_gui_c::set_clipboard_text(char *text_snapshot
, Bit32u len
)
1621 if (wxTheClipboard
->Open()) {
1622 wxString
string(text_snapshot
, wxConvUTF8
, len
);
1623 wxTheClipboard
->SetData(new wxTextDataObject (string
));
1624 wxTheClipboard
->Close();
1632 void bx_wx_gui_c::show_ips(Bit32u ips_count
)
1636 sprintf(ips_text
, "IPS: %9u", ips_count
);
1637 theFrame
->SetStatusText(wxString(ips_text
, wxConvUTF8
), 0);
1642 #if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
1643 /* we can use the X keysyms for GTK too */
1644 #include <X11/Xlib.h>
1645 #include <X11/keysym.h>
1646 /* convertStringToGDKKey is a keymap callback
1647 * used when reading the keymap file.
1648 * It converts a Symblic String to a GUI Constant
1650 * It returns a Bit32u constant or BX_KEYMAP_UNKNOWN if it fails
1652 static Bit32u
convertStringToGDKKey (const char *string
)
1654 if (strncmp ("XK_", string
, 3) != 0)
1655 return BX_KEYMAP_UNKNOWN
;
1656 KeySym keysym
=XStringToKeysym(string
+3);
1658 // failure, return unknown
1659 if(keysym
==NoSymbol
) return BX_KEYMAP_UNKNOWN
;
1661 return((Bit32u
)keysym
);
1665 #endif /* if BX_WITH_WX */