mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-30 17:39:51 +02:00
Update to v094r25 release.
byuu says: Windows port should run mostly well now, although exiting fullscreen breaks the application in a really bizarre way. (clicking on the window makes it sink to background rather than come to the foreground o_O) I also need to add the doModalChange => audio.clear() thing for the accursed menu stuttering with DirectSound. I also finished porting all of the ruby drivers over to the newer API changes from nall. Since I can't compile the Linux or OS X drivers, I have no idea if there are any typos that will result in compilation errors. If so, please let me know where they're at and I'll try and fix them. If they're simple, please try and fix them on your end to test further if you can. I'm hopeful the udev crash will be gone now that nall::string checks for null char* values passed to its stringify function. Of course, it's a problem it's getting a null value in the first place, so it may not work at all. If you can compile on Linux (or by some miracle, OS X), please test each video/audio/input driver if you don't mind, to make sure there's no "compiles okay but still typos exist" bugs.
This commit is contained in:
@@ -136,24 +136,30 @@ auto pApplication::initialize() -> void {
|
||||
static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> bool {
|
||||
if(msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN && msg != WM_KEYUP && msg != WM_SYSKEYUP) return false;
|
||||
|
||||
GUITHREADINFO info;
|
||||
memset(&info, 0, sizeof(GUITHREADINFO));
|
||||
info.cbSize = sizeof(GUITHREADINFO);
|
||||
GUITHREADINFO info{sizeof(GUITHREADINFO)};
|
||||
GetGUIThreadInfo(GetCurrentThreadId(), &info);
|
||||
|
||||
auto object = (mObject*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
|
||||
if(!object) return false;
|
||||
|
||||
if(auto window = dynamic_cast<mWindow*>(object)) {
|
||||
if(pWindow::modal && !pWindow::modal.find(window->self())) return false;
|
||||
|
||||
if(auto code = pKeyboard::_translate(wparam, lparam)) {
|
||||
if(msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) window->doKeyPress(code);
|
||||
if(msg == WM_KEYUP || msg == WM_SYSKEYUP) window->doKeyRelease(code);
|
||||
if(auto self = window->self()) {
|
||||
if(!self->_modalityDisabled()) {
|
||||
if(auto code = pKeyboard::_translate(wparam, lparam)) {
|
||||
if(msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) window->doKeyPress(code);
|
||||
if(msg == WM_KEYUP || msg == WM_SYSKEYUP) window->doKeyRelease(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(auto window = object->parentWindow(true)) {
|
||||
if(auto self = window->self()) {
|
||||
if(self->_modalityDisabled()) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(msg == WM_KEYDOWN) {
|
||||
if(0);
|
||||
|
||||
@@ -225,23 +231,26 @@ case WM_GETMINMAXINFO: {
|
||||
*/
|
||||
|
||||
static auto CALLBACK Application_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
||||
if(Application::state.quit) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
|
||||
auto object = (mObject*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if(!object) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
auto& window = dynamic_cast<mWindow*>(object) ? (mWindow&)*object : *object->parentWindow(true);
|
||||
auto window = dynamic_cast<mWindow*>(object);
|
||||
if(!window) window = object->parentWindow(true);
|
||||
if(!window) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
auto pWindow = window->self();
|
||||
if(!pWindow) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
|
||||
bool process = true;
|
||||
if(pWindow::modal && !pWindow::modal.find(window.self())) process = false;
|
||||
if(Application::state.quit) process = false;
|
||||
if(!process) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
if(pWindow->_modalityDisabled()) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
|
||||
switch(msg) {
|
||||
case WM_CLOSE: window.self()->onClose(); return TRUE;
|
||||
case WM_MOVE: window.self()->onMove(); break;
|
||||
case WM_SIZE: window.self()->onSize(); break;
|
||||
case WM_DROPFILES: window.self()->onDrop(wparam); return FALSE;
|
||||
case WM_ERASEBKGND: if(window.self()->onEraseBackground()) return true; break;
|
||||
case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: window.self()->onModalBegin(); return FALSE;
|
||||
case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: window.self()->onModalEnd(); return FALSE;
|
||||
case WM_CLOSE: pWindow->onClose(); return true;
|
||||
case WM_MOVE: pWindow->onMove(); break;
|
||||
case WM_SIZE: pWindow->onSize(); break;
|
||||
case WM_DROPFILES: pWindow->onDrop(wparam); return false;
|
||||
case WM_ERASEBKGND: if(pWindow->onEraseBackground()) return true; break;
|
||||
case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: pWindow->onModalBegin(); return false;
|
||||
case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: pWindow->onModalEnd(); return false;
|
||||
}
|
||||
|
||||
return Shared_windowProc(DefWindowProc, hwnd, msg, wparam, lparam);
|
||||
|
@@ -17,6 +17,8 @@ struct AppMessage {
|
||||
|
||||
using WindowProc = auto CALLBACK (*)(HWND, UINT, WPARAM, LPARAM) -> LRESULT;
|
||||
|
||||
static vector<wObject> windows;
|
||||
|
||||
}
|
||||
|
||||
#define Declare(Name, Base) \
|
||||
|
@@ -145,16 +145,17 @@ static auto CALLBACK Menu_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
||||
}
|
||||
|
||||
static auto CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
||||
if(Application::state.quit) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
|
||||
auto object = (mObject*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if(!object) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
auto window = dynamic_cast<mWindow*>(object);
|
||||
if(!window) window = object->parentWindow(true);
|
||||
if(!window) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
auto pWindow = window->self();
|
||||
if(!pWindow) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
|
||||
bool process = true;
|
||||
if(pWindow::modal && !pWindow::modal.find(window->self())) process = false;
|
||||
if(Application::state.quit) process = false;
|
||||
if(!process) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
if(pWindow->_modalityDisabled()) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
|
||||
switch(msg) {
|
||||
case WM_CTLCOLORBTN:
|
||||
|
@@ -2,6 +2,25 @@
|
||||
|
||||
namespace hiro {
|
||||
|
||||
static auto CALLBACK ListView_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
||||
if(auto object = (mObject*)GetWindowLongPtr(hwnd, GWLP_USERDATA)) {
|
||||
if(auto listView = dynamic_cast<mListView*>(object)) {
|
||||
if(auto self = listView->self()) {
|
||||
if(!listView->enabled(true)) {
|
||||
if(msg == WM_KEYDOWN || msg == WM_KEYUP || msg == WM_SYSKEYDOWN || msg == WM_SYSKEYUP) {
|
||||
//WC_LISTVIEW responds to key messages even when its HWND is disabled
|
||||
//the control should be inactive when disabled; so we intercept the messages here
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return self->windowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
auto pListView::construct() -> void {
|
||||
hwnd = CreateWindowEx(
|
||||
WS_EX_CLIENTEDGE, WC_LISTVIEW, L"",
|
||||
@@ -9,6 +28,8 @@ auto pListView::construct() -> void {
|
||||
0, 0, 0, 0, _parentHandle(), nullptr, GetModuleHandle(0), 0
|
||||
);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
|
||||
windowProc = (WindowProc)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)&ListView_windowProc);
|
||||
ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES);
|
||||
pWidget::_setState();
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
|
@@ -38,6 +38,7 @@ struct pListView : pWidget {
|
||||
auto _setIcons() -> void;
|
||||
auto _width(unsigned column) -> unsigned;
|
||||
|
||||
WindowProc windowProc = nullptr;
|
||||
HIMAGELIST imageList = 0;
|
||||
vector<image> icons;
|
||||
};
|
||||
|
@@ -5,9 +5,12 @@ namespace hiro {
|
||||
static auto CALLBACK TabFrame_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
||||
if(auto object = (mObject*)GetWindowLongPtr(hwnd, GWLP_USERDATA)) {
|
||||
if(auto tabFrame = dynamic_cast<mTabFrame*>(object)) {
|
||||
return Shared_windowProc(tabFrame->self()->windowProc, hwnd, msg, wparam, lparam);
|
||||
if(auto self = tabFrame->self()) {
|
||||
return Shared_windowProc(self->windowProc, hwnd, msg, wparam, lparam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
|
@@ -15,8 +15,9 @@ auto pWidget::destruct() -> void {
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
auto pWidget::focused() -> bool {
|
||||
return GetFocus() == hwnd;
|
||||
auto pWidget::focused() const -> bool {
|
||||
auto focused = GetFocus();
|
||||
return hwnd == focused || IsChild(hwnd, focused);
|
||||
}
|
||||
|
||||
auto pWidget::minimumSize() -> Size {
|
||||
@@ -44,11 +45,11 @@ auto pWidget::setFont(const string&) -> void {
|
||||
|
||||
auto pWidget::setGeometry(Geometry geometry) -> void {
|
||||
if(auto parent = _parentWidget()) {
|
||||
Position displacement = parent->geometry().position();
|
||||
auto displacement = parent->self().geometry().position();
|
||||
geometry.setX(geometry.x() - displacement.x());
|
||||
geometry.setY(geometry.y() - displacement.y());
|
||||
}
|
||||
SetWindowPos(hwnd, NULL, geometry.x(), geometry.y(), geometry.width(), geometry.height(), SWP_NOZORDER);
|
||||
SetWindowPos(hwnd, nullptr, geometry.x(), geometry.y(), geometry.width(), geometry.height(), SWP_NOZORDER);
|
||||
self().doSize();
|
||||
}
|
||||
|
||||
@@ -62,20 +63,24 @@ auto pWidget::setVisible(bool visible) -> void {
|
||||
//
|
||||
|
||||
auto pWidget::_parentHandle() -> HWND {
|
||||
if(auto parent = _parentWidget()) return parent->self()->hwnd;
|
||||
if(auto parent = _parentWindow()) return parent->self()->hwnd;
|
||||
return 0;
|
||||
if(auto parent = _parentWidget()) return parent->hwnd;
|
||||
if(auto parent = _parentWindow()) return parent->hwnd;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pWidget::_parentWidget() -> maybe<mWidget&> {
|
||||
auto pWidget::_parentWidget() -> maybe<pWidget&> {
|
||||
#if defined(Hiro_TabFrame)
|
||||
if(auto parent = self().parentTabFrame(true)) return *parent;
|
||||
if(auto parent = self().parentTabFrame(true)) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
#endif
|
||||
return nothing;
|
||||
}
|
||||
|
||||
auto pWidget::_parentWindow() -> maybe<mWindow&> {
|
||||
if(auto parent = self().parentWindow(true)) return *parent;
|
||||
auto pWidget::_parentWindow() -> maybe<pWindow&> {
|
||||
if(auto parent = self().parentWindow(true)) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,7 @@ namespace hiro {
|
||||
struct pWidget : pSizable {
|
||||
Declare(Widget, Sizable)
|
||||
|
||||
auto focused() -> bool;
|
||||
auto focused() const -> bool override;
|
||||
virtual auto minimumSize() -> Size;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFocused() -> void;
|
||||
@@ -14,8 +14,8 @@ struct pWidget : pSizable {
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _parentHandle() -> HWND;
|
||||
auto _parentWidget() -> maybe<mWidget&>;
|
||||
auto _parentWindow() -> maybe<mWindow&>;
|
||||
auto _parentWidget() -> maybe<pWidget&>;
|
||||
auto _parentWindow() -> maybe<pWindow&>;
|
||||
auto _setState() -> void;
|
||||
|
||||
bool abstract = false;
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace hiro {
|
||||
|
||||
vector<pWindow*> pWindow::modal;
|
||||
|
||||
static const unsigned FixedStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_BORDER;
|
||||
static const unsigned ResizableStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
|
||||
|
||||
@@ -12,9 +10,13 @@ auto pWindow::construct() -> void {
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
|
||||
setDroppable(state().droppable);
|
||||
setGeometry({128, 128, 256, 256});
|
||||
|
||||
windows.append(self().instance);
|
||||
}
|
||||
|
||||
auto pWindow::destruct() -> void {
|
||||
if(auto position = windows.find(self().instance)) windows.remove(*position);
|
||||
|
||||
if(hbrush) { DeleteObject(hbrush); hbrush = nullptr; }
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
@@ -28,7 +30,7 @@ auto pWindow::append(sMenuBar menuBar) -> void {
|
||||
auto pWindow::append(sStatusBar statusBar) -> void {
|
||||
}
|
||||
|
||||
auto pWindow::focused() const -> bool override {
|
||||
auto pWindow::focused() const -> bool {
|
||||
return (GetForegroundWindow() == hwnd);
|
||||
}
|
||||
|
||||
@@ -122,7 +124,7 @@ auto pWindow::setGeometry(Geometry geometry) -> void {
|
||||
|
||||
auto pWindow::setModal(bool modality) -> void {
|
||||
if(modality) {
|
||||
modal.appendOnce(this);
|
||||
_modalityUpdate();
|
||||
while(state().modal) {
|
||||
Application::processEvents();
|
||||
if(Application::state.onMain) {
|
||||
@@ -131,7 +133,7 @@ auto pWindow::setModal(bool modality) -> void {
|
||||
usleep(20 * 1000);
|
||||
}
|
||||
}
|
||||
if(auto position = modal.find(this)) modal.remove(position());
|
||||
_modalityUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +227,39 @@ auto pWindow::_geometry() -> Geometry {
|
||||
return {x, y, width, height};
|
||||
}
|
||||
|
||||
auto pWindow::_modalityCount() -> unsigned {
|
||||
unsigned modalWindows = 0;
|
||||
for(auto& weak : windows) {
|
||||
if(auto object = weak.acquire()) {
|
||||
if(auto window = dynamic_cast<mWindow*>(object.data())) {
|
||||
if(window->modal()) modalWindows++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return modalWindows;
|
||||
}
|
||||
|
||||
auto pWindow::_modalityDisabled() -> bool {
|
||||
if(_modalityCount() == 0) return false;
|
||||
return !state().modal;
|
||||
}
|
||||
|
||||
auto pWindow::_modalityUpdate() -> void {
|
||||
unsigned modalWindows = _modalityCount();
|
||||
for(auto& weak : windows) {
|
||||
if(auto object = weak.acquire()) {
|
||||
if(auto window = dynamic_cast<mWindow*>(object.data())) {
|
||||
if(auto self = window->self()) {
|
||||
bool enabled = !modalWindows || window->modal();
|
||||
if(IsWindowEnabled(self->hwnd) != enabled) {
|
||||
EnableWindow(self->hwnd, enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -33,13 +33,14 @@ struct pWindow : pObject {
|
||||
auto onSize() -> void;
|
||||
|
||||
auto _geometry() -> Geometry;
|
||||
auto _modalityCount() -> unsigned;
|
||||
auto _modalityDisabled() -> bool;
|
||||
auto _modalityUpdate() -> void;
|
||||
|
||||
HWND hwnd = nullptr;
|
||||
HFONT hstatusfont = nullptr;
|
||||
HBRUSH hbrush = nullptr;
|
||||
COLORREF hbrushColor = 0;
|
||||
|
||||
static vector<pWindow*> modal;
|
||||
};
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user