Update to v094r42 release.

byuu says:

I imagine you guys will like this WIP very much.

Changelog:
- ListView check boxes on Windows
- ListView removal of columns on reset (changing input dropdowns)
- DirectSound audio duplication on latency change
- DirectSound crash on 20ms latency
- Fullscreen window sizing in multi-monitor setups
- Allow joypad bindings of hotkeys
- Allow triggers to be mapped (Xbox 360 / XInput / Windows only)
- Support joypad rumble for Game Boy Player
- Video scale settings modified from {1x,2x,3x} to {2x,3x,4x}
- System menu now renames to active emulation core
- Added fast forward hotkey

Not changing for v095:
- not adding input focus settings yet
- not adding shaders yet

Not changing at all:
- not implementing maximize
This commit is contained in:
Tim Allen
2015-08-24 19:42:11 +10:00
parent 7081f46e45
commit c45633550e
21 changed files with 136 additions and 75 deletions

View File

@@ -219,8 +219,10 @@ auto mWindow::setFrameSize(Size size) -> type& {
}
auto mWindow::setFullScreen(bool fullScreen) -> type& {
state.fullScreen = fullScreen;
signal(setFullScreen, fullScreen);
if(fullScreen != state.fullScreen) {
state.fullScreen = fullScreen;
signal(setFullScreen, fullScreen);
}
return *this;
}

View File

@@ -65,8 +65,7 @@ static auto Window_configure(GtkWidget* widget, GdkEvent* event, pWindow* p) ->
//move
if(geometry.x() != p->state().geometry.x() || geometry.y() != p->state().geometry.y()) {
if(!p->state().fullScreen) {
p->state().geometry.setX(geometry.x());
p->state().geometry.setY(geometry.y());
p->state().geometry.setPosition({geometry.x(), geometry.y()});
}
if(!p->locked()) p->self().doMove();
}
@@ -106,8 +105,9 @@ static auto Window_sizeAllocate(GtkWidget* widget, GtkAllocation* allocation, pW
if(allocation->width == p->lastAllocation.width
&& allocation->height == p->lastAllocation.height) return;
p->state().geometry.setWidth(allocation->width);
p->state().geometry.setHeight(allocation->height);
if(!p->state().fullScreen) {
p->state().geometry.setSize({allocation->width, allocation->height});
}
if(auto& layout = p->state().layout) {
layout->setGeometry(p->self().geometry().setPosition(0, 0));
@@ -259,10 +259,13 @@ auto pWindow::setFocused() -> void {
}
auto pWindow::setFullScreen(bool fullScreen) -> void {
if(fullScreen == false) {
gtk_window_unfullscreen(GTK_WINDOW(widget));
} else {
if(fullScreen) {
windowedGeometry = state().geometry;
gtk_window_fullscreen(GTK_WINDOW(widget));
state().geometry = Monitor::geometry(Monitor::primary());
} else {
gtk_window_unfullscreen(GTK_WINDOW(widget));
state().geometry = windowedGeometry;
}
}

View File

@@ -5,15 +5,6 @@ namespace hiro {
struct pWindow : pObject {
Declare(Window, Object)
GtkWidget* widget = nullptr;
GtkWidget* menuContainer = nullptr;
GtkWidget* formContainer = nullptr;
GtkWidget* statusContainer = nullptr;
GtkWidget* gtkMenu = nullptr;
GtkWidget* gtkStatus = nullptr;
GtkAllocation lastAllocation = {0};
bool onSizePending = false;
auto append(sLayout layout) -> void;
auto append(sMenuBar menuBar) -> void;
auto append(sStatusBar statusBar) -> void;
@@ -45,6 +36,16 @@ struct pWindow : pObject {
auto _setStatusText(const string& text) -> void;
auto _setStatusVisible(bool visible) -> void;
auto _statusHeight() const -> signed;
GtkWidget* widget = nullptr;
GtkWidget* menuContainer = nullptr;
GtkWidget* formContainer = nullptr;
GtkWidget* statusContainer = nullptr;
GtkWidget* gtkMenu = nullptr;
GtkWidget* gtkStatus = nullptr;
GtkAllocation lastAllocation = {0};
bool onSizePending = false;
Geometry windowedGeometry{128, 128, 256, 256};
};
}

View File

@@ -89,13 +89,6 @@ auto pWindow::remove(sMenuBar menuBar) -> void {
auto pWindow::remove(sStatusBar statusBar) -> void {
}
/*
//orphan() destroys and recreates widgets (to disassociate them from their parent);
//attempting to create widget again after QApplication::quit() crashes libQtGui
if(qtApplication) widget.p.orphan();
}
*/
auto pWindow::setBackgroundColor(Color color) -> void {
if(color) {
QPalette palette;
@@ -120,15 +113,20 @@ auto pWindow::setFocused() -> void {
}
auto pWindow::setFullScreen(bool fullScreen) -> void {
if(!fullScreen) {
setResizable(state().resizable);
qtWindow->showNormal();
qtWindow->adjustSize();
} else {
lock();
if(fullScreen) {
windowedGeometry = state().geometry;
qtLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
qtContainer->setFixedSize(Desktop::size().width() - frameMargin().width(), Desktop::size().height() - frameMargin().height());
qtWindow->showFullScreen();
state().geometry = Monitor::geometry(Monitor::primary());
} else {
setResizable(state().resizable);
qtWindow->showNormal();
qtWindow->adjustSize();
self().setGeometry(windowedGeometry);
}
unlock();
}
auto pWindow::setGeometry(Geometry geometry) -> void {
@@ -256,8 +254,10 @@ auto QtWindow::closeEvent(QCloseEvent* event) -> void {
auto QtWindow::moveEvent(QMoveEvent* event) -> void {
if(!p.locked() && !p.state().fullScreen && p.qtWindow->isVisible()) {
p.state().geometry.setX(p.state().geometry.x() + event->pos().x() - event->oldPos().x());
p.state().geometry.setY(p.state().geometry.y() + event->pos().y() - event->oldPos().y());
p.state().geometry.setPosition({
p.state().geometry.x() + event->pos().x() - event->oldPos().x(),
p.state().geometry.y() + event->pos().y() - event->oldPos().y()
});
}
if(!p.locked()) {
@@ -287,8 +287,10 @@ auto QtWindow::keyReleaseEvent(QKeyEvent* event) -> void {
auto QtWindow::resizeEvent(QResizeEvent*) -> void {
if(!p.locked() && !p.state().fullScreen && p.qtWindow->isVisible()) {
p.state().geometry.setWidth(p.qtContainer->geometry().width());
p.state().geometry.setHeight(p.qtContainer->geometry().height());
p.state().geometry.setSize({
p.qtContainer->geometry().width(),
p.qtContainer->geometry().height()
});
}
if(auto& layout = p.state().layout) {

View File

@@ -34,6 +34,7 @@ struct pWindow : pObject {
QMenuBar* qtMenuBar = nullptr;
QStatusBar* qtStatusBar = nullptr;
QWidget* qtContainer = nullptr;
Geometry windowedGeometry{128, 128, 256, 256};
};
}

View File

@@ -6,7 +6,7 @@ static const unsigned WindowsVista = 0x0600;
static const unsigned Windows7 = 0x0601;
static auto OsVersion() -> unsigned {
OSVERSIONINFO versionInfo = {0};
OSVERSIONINFO versionInfo{0};
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&versionInfo);
return (versionInfo.dwMajorVersion << 8) + (versionInfo.dwMajorVersion << 0);
@@ -283,6 +283,20 @@ static auto CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT ms
}
case WM_NOTIFY: {
//WC_TABCONTROL requires parenting widgets to it; rather than the WINDOW
//without doing this; backgrounds on transparent controls (eg STATIC) are painted wrong
//this causes some WC_LISTVIEW WM_NOTIFY messages to only go to the WC_TABCONTROL WNDPROC
//all other controls also send their messages to the WC_TABCONTROL WNDPROC
//to avoid duplicating all message logic, hiro shares a WNDPROC with Window and TabFrame
//LVN_ITEM(ACTIVATE,CHANGED) are only sent to the TabFrame, as expected
//yet for unknown reasons, LVN_COLUMNCLICK and NM_(CLICK,DBLCLK,RCLICK) are
//sent to both the TabFrame, and then again to the Window's WNDPROC
//this causes on(Sort,Toggle,Context) to trigger callbacks twice
//if we try to block propagation to the Window (via return instead of break); then
//this will result in the LVN_ITEM(ACTIVATE,CHANGED) never being invoked (unsure why)
//as a workaround; we must detect these message to the Windows' WNDPROC, and block them
bool isWindowCallback = (object == window);
auto header = (LPNMHDR)lparam;
auto object = (mObject*)GetWindowLongPtr((HWND)header->hwndFrom, GWLP_USERDATA);
if(!object) break;
@@ -298,15 +312,16 @@ static auto CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT ms
break;
}
if(header->code == LVN_COLUMNCLICK) {
listView->self()->onSort(lparam);
if(!isWindowCallback) listView->self()->onSort(lparam);
break;
}
if(header->code == NM_CLICK || header->code == NM_DBLCLK) {
listView->self()->onToggle(lparam);
//onToggle performs the test to ensure the ListViewItem clicked was checkable
if(!isWindowCallback) listView->self()->onToggle(lparam);
break;
}
if(header->code == NM_RCLICK) {
listView->self()->onContext(lparam);
if(!isWindowCallback) listView->self()->onContext(lparam);
break;
}
if(header->code == NM_CUSTOMDRAW) {

View File

@@ -52,6 +52,10 @@ auto pListView::append(sListViewItem item) -> void {
}
auto pListView::remove(sListViewHeader header) -> void {
LVCOLUMN lvColumn{LVCF_WIDTH};
while(ListView_GetColumn(hwnd, 0, &lvColumn)) {
ListView_DeleteColumn(hwnd, 0);
}
}
auto pListView::remove(sListViewItem item) -> void {

View File

@@ -91,10 +91,8 @@ auto pWindow::setFont(const string& font) -> void {
auto pWindow::setFullScreen(bool fullScreen) -> void {
auto style = GetWindowLongPtr(hwnd, GWL_STYLE) & WS_VISIBLE;
lock();
if(fullScreen == false) {
SetWindowLongPtr(hwnd, GWL_STYLE, style | (state().resizable ? ResizableStyle : FixedStyle));
setGeometry(state().geometry);
} else {
if(fullScreen) {
windowedGeometry = self().geometry();
HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX info;
memset(&info, 0, sizeof(MONITORINFOEX));
@@ -104,10 +102,13 @@ auto pWindow::setFullScreen(bool fullScreen) -> void {
Geometry geometry = {rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top};
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_POPUP);
Geometry margin = frameMargin();
setGeometry({
self().setGeometry({
geometry.x() + margin.x(), geometry.y() + margin.y(),
geometry.width() - margin.width(), geometry.height() - margin.height()
});
} else {
SetWindowLongPtr(hwnd, GWL_STYLE, style | (state().resizable ? ResizableStyle : FixedStyle));
self().setGeometry(windowedGeometry);
}
unlock();
}
@@ -116,7 +117,7 @@ auto pWindow::setGeometry(Geometry geometry) -> void {
lock();
Geometry margin = frameMargin();
SetWindowPos(
hwnd, NULL,
hwnd, nullptr,
geometry.x() - margin.x(), geometry.y() - margin.y(),
geometry.width() + margin.width(), geometry.height() + margin.height(),
SWP_NOZORDER | SWP_FRAMECHANGED

View File

@@ -42,6 +42,7 @@ struct pWindow : pObject {
HFONT hstatusfont = nullptr;
HBRUSH hbrush = nullptr;
COLORREF hbrushColor = 0;
Geometry windowedGeometry{128, 128, 256, 256};
};
}