Update to v082r05 release.

byuu says:

Okay, I fixed up many outstanding phoenix issues.
* Windows/GTK+ fixed by using processEvents instead of main(); Windows can run unthrottled, and GTK+ shows the window contents now
* fixed keyboard beeping once and for all on Windows: I now whitelist tabbable controls
* fixed main menubar setVisible calls
* Qt and GTK+ now allow you to resize windows smaller than they initially were

Both Qt and GTK+ still fuck up the geometry a bit when toggling fullscreen mode. I have tried, and tried, and tried and tried and tried to fix it all. Nothing works. I give up.
Easier to destroy and recreate the fucking window than figure out how to resize it on Linux (and no, I can't do that. ruby would not like the handle changing.)

As for the GUI:
* file browser is back in, still need remember place and open folder code; that needs to be extended to handle multiple systems now
* shrink window command added to tools menu.
This commit is contained in:
Tim Allen 2011-09-09 14:16:25 +10:00
parent ec7e4087fb
commit 8618334356
20 changed files with 240 additions and 64 deletions

View File

@ -125,7 +125,10 @@
}
inline char *getcwd(char *path) {
return getcwd(path, PATH_MAX);
auto unused = getcwd(path, PATH_MAX);
unsigned length = strlen(path);
if(path[length] != '/') strcpy(path + length, "/");
return path;
}
#endif

View File

@ -66,11 +66,13 @@ bool string::operator> (const char *str) const { return strcmp(data, str) > 0;
bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; }
string& string::operator=(const string &value) {
if(&value == this) return *this;
assign(value);
return *this;
}
string& string::operator=(string &&source) {
if(&source == this) return *this;
if(data) free(data);
size = source.size;
data = source.data;
@ -87,11 +89,13 @@ template<typename... Args> string::string(Args&&... args) {
}
string::string(const string &value) {
if(&value == this) return;
size = strlen(value);
data = strdup(value);
}
string::string(string &&source) {
if(&source == this) return;
size = source.size;
data = source.data;
source.data = 0;

View File

@ -306,6 +306,10 @@ Window::~Window() {
//Action
//======
bool Action::enabled() {
return state.enabled;
}
void Action::setEnabled(bool enabled) {
state.enabled = enabled;
return p.setEnabled(enabled);
@ -316,6 +320,10 @@ void Action::setVisible(bool visible) {
return p.setVisible(visible);
}
bool Action::visible() {
return state.visible;
}
Action::Action(pAction &p):
state(*new State),
Object(p),

View File

@ -162,8 +162,10 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
};
struct Action : Object {
bool enabled();
void setEnabled(bool enabled = true);
void setVisible(bool visible = true);
bool visible();
Action(pAction &p);
~Action();

View File

@ -31,16 +31,18 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win
if(gtk_widget_get_realized(window->p.widget) == false) return false;
GdkWindow *gdkWindow = gtk_widget_get_window(widget);
//update geometry settings
GdkRectangle border, client;
gdk_window_get_frame_extents(gdkWindow, &border);
gdk_window_get_geometry(gdkWindow, 0, 0, &client.width, &client.height, 0);
gdk_window_get_origin(gdkWindow, &client.x, &client.y);
if(window->state.fullScreen == false) {
//update geometry settings
settings.frameGeometryX = client.x - border.x;
settings.frameGeometryY = client.y - border.y;
settings.frameGeometryWidth = border.width - client.width;
settings.frameGeometryHeight = border.height - client.height;
}
//move
if(event->configure.x != window->p.lastConfigure.x
@ -167,10 +169,20 @@ void pWindow::setFullScreen(bool fullScreen) {
}
void pWindow::setGeometry(const Geometry &geometry) {
OS::processEvents();
Geometry margin = frameMargin();
gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y);
gtk_window_resize(GTK_WINDOW(widget), 1, 1);
//GdkGeometry geom;
//geom.min_width = 1;
//geom.min_height = 1;
//gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE);
gtk_window_set_policy(GTK_WINDOW(widget), true, true, false);
gtk_widget_set_size_request(formContainer, geometry.width, geometry.height);
gtk_window_resize(GTK_WINDOW(widget), geometry.width + margin.width, geometry.height + margin.height);
foreach(layout, window.state.layout) {
Geometry geometry = this->geometry();
geometry.x = geometry.y = 0;

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'platform.moc.hpp'
**
** Created: Tue Aug 30 09:38:15 2011
** Created: Thu Sep 8 17:34:23 2011
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
**
** WARNING! All changes made in this file will be lost!

View File

@ -97,6 +97,8 @@ void pWindow::setGeometry(const Geometry &geometry_) {
setResizable(window.state.resizable);
qtWindow->move(geometry.x - margin.x, geometry.y - margin.y);
qtWindow->adjustSize();
qtWindow->setMinimumSize(1u, 1u);
qtContainer->setMinimumSize(1u, 1u);
foreach(layout, window.state.layout) {
geometry = geometry_;

View File

@ -32,6 +32,7 @@
#include "widget/viewport.cpp"
static void OS_keyboardProc(HWND, UINT, WPARAM, LPARAM);
static void OS_processDialogMessage(MSG&);
static LRESULT CALLBACK OS_windowProc(HWND, UINT, WPARAM, LPARAM);
Geometry pOS::availableGeometry() {
@ -129,13 +130,7 @@ string pOS::folderSelect(Window &parent, const string &path) {
void pOS::main() {
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP) {
OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
}
if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
OS_processDialogMessage(msg);
}
}
@ -148,15 +143,33 @@ void pOS::processEvents() {
while(pendingEvents()) {
MSG msg;
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
OS_processDialogMessage(msg);
}
}
}
void OS_processDialogMessage(MSG &msg) {
if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP) {
OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
}
if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) {
wchar_t className[256];
GetClassName(msg.hwnd, className, 255);
//if this HWND accepts tabs to move between controls ...
if(!wcscmp(className, L"BUTTON") //Button, CheckBox, RadioBox
|| !wcscmp(className, L"COMBOBOX") //ComboBox
|| !wcscmp(className, L"EDIT") //HexEdit, LineEdit, TextEdit
|| !wcscmp(className, L"SCROLLBAR") //HorizontalScrollBar, VerticalScrollBar
|| !wcscmp(className, TRACKBAR_CLASS) //HorizontalSlider, VerticalSlider
|| !wcscmp(className, WC_LISTVIEW) //ListView
) {
//... return if the message is a dialog command
if(IsDialogMessage(msg.hwnd, &msg)) return;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
}
void pOS::quit() {

View File

@ -8,6 +8,7 @@ void pWindow::append(Layout &layout) {
}
void pWindow::append(Menu &menu) {
menu.p.parentWindow = &window;
updateMenu();
}
@ -192,8 +193,10 @@ void pWindow::updateMenu() {
foreach(menu, window.state.menu) {
menu.p.update(window);
if(menu.visible()) {
AppendMenu(hmenu, MF_STRING | MF_POPUP, (UINT_PTR)menu.p.hmenu, utf16_t(menu.state.text));
}
}
SetMenu(hwnd, window.state.menuVisible ? hmenu : 0);
}

View File

@ -4,7 +4,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "082.04";
static const char Version[] = "082.05";
static const unsigned SerializerVersion = 21;
}
}

View File

@ -24,12 +24,12 @@ using namespace ruby;
#include "general/general.hpp"
struct Application {
bool quit;
string title;
string normalFont;
string boldFont;
Timer timer;
void run();
Application(int argc, char **argv);
~Application();

View File

@ -0,0 +1,83 @@
FileBrowser *fileBrowser = 0;
FileBrowser::FileBrowser() {
setGeometry({ 128, 128, 640, 400 });
setWidgetFont(application->normalFont);
pathBrowse.setText("Browse ...");
pathUp.setText("..");
layout.setMargin(5);
append(layout);
layout.append(pathLayout, ~0, 0, 5);
pathLayout.append(pathEdit, ~0, 0, 5);
pathLayout.append(pathBrowse, 0, 0, 5);
pathLayout.append(pathUp, 0, 0);
layout.append(fileList, ~0, ~0);
pathEdit.onActivate = [&] {
string path = pathEdit.text();
path.transform("\\", "/");
if(path.endswith("/") == false) path.append("/");
setPath(path);
};
pathBrowse.onTick = [&] {
string path = OS::folderSelect(*this, activePath);
if(path != "") setPath(path);
};
pathUp.onTick = [&] {
if(activePath == "/") return;
string path = activePath;
path.rtrim<1>("/");
path = dir(path);
setPath(path);
};
fileList.onActivate = { &FileBrowser::fileListActivate, this };
char path[PATH_MAX];
auto unused = getcwd(path);
setPath(path);
}
void FileBrowser::open(const string &title, const lstring &filterList, function<void (string)> callback) {
this->callback = callback;
this->filterList = filterList;
setTitle(title);
setPath(activePath);
setVisible();
}
void FileBrowser::setPath(const string &path) {
activePath = path;
pathEdit.setText(activePath);
fileList.reset();
fileNameList.reset();
lstring contentsList = directory::contents(path);
foreach(fileName, contentsList) {
if(fileName.endswith("/")) {
fileNameList.append(fileName);
} else foreach(filter, filterList) {
if(fileName.wildcard(filter)) fileNameList.append(fileName);
}
}
foreach(fileName, fileNameList) fileList.append(fileName);
fileList.setSelection(0);
fileList.setFocused();
}
void FileBrowser::fileListActivate() {
unsigned selection = fileList.selection();
string fileName = fileNameList[selection];
if(fileName.endswith("/")) return setPath({ activePath, fileName });
if(callback) callback({ activePath, fileName });
setVisible(false);
}

View File

@ -0,0 +1,23 @@
struct FileBrowser : Window {
VerticalLayout layout;
HorizontalLayout pathLayout;
LineEdit pathEdit;
Button pathBrowse;
Button pathUp;
ListView fileList;
lstring fileNameList;
void open(const string &title, const lstring &filterList, function<void (string)> callback);
FileBrowser();
private:
string activePath;
lstring filterList;
function<void (string)> callback;
void setPath(const string &path);
void fileListActivate();
};
extern FileBrowser *fileBrowser;

View File

@ -1,2 +1,3 @@
#include "../base.hpp"
#include "main-window.cpp"
#include "file-browser.cpp"

View File

@ -1 +1,2 @@
#include "main-window.hpp"
#include "file-browser.hpp"

View File

@ -31,6 +31,9 @@ MainWindow::MainWindow() {
settingsSynchronizeAudio.setChecked();
settingsMuteAudio.setText("Mute Audio");
toolsMenu.setText("Tools");
toolsShrinkWindow.setText("Shrink Window");
helpMenu.setText("Help");
helpAbout.setText("About ...");
@ -61,6 +64,9 @@ MainWindow::MainWindow() {
settingsMenu.append(settingsSynchronizeAudio);
settingsMenu.append(settingsMuteAudio);
append(toolsMenu);
toolsMenu.append(toolsShrinkWindow);
append(helpMenu);
helpMenu.append(helpAbout);
@ -74,25 +80,25 @@ MainWindow::MainWindow() {
layout.append(viewport, { 0, 0, 512, 480 });
append(layout);
onClose = &OS::quit;
onSize = { &Utility::resizeMainWindow, utility };
cartridgeLoadSNES.onTick = [&] {
string filename = OS::fileLoad(*this, "/media/sdb1/root/snes_roms/", "SNES images (*.sfc)");
if(filename == "") return;
interface->loadCartridgeSNES(filename);
};
onClose = [&] { application->quit = true; };
onSize = [&] { utility->resizeMainWindow(); };
cartridgeLoadNES.onTick = [&] {
string filename = OS::fileLoad(*this, "/media/sdb1/root/nes_images/", "NES images (*.nes)");
if(filename == "") return;
fileBrowser->open("Load NES Cartridge", { "*.nes" }, [](string filename) {
interface->loadCartridgeNES(filename);
});
};
cartridgeLoadSNES.onTick = [&] {
fileBrowser->open("Load SNES Cartridge", { "*.sfc" }, [](string filename) {
interface->loadCartridgeSNES(filename);
});
};
cartridgeLoadGameBoy.onTick = [&] {
string filename = OS::fileLoad(*this, "/media/sdb1/root/gameboy_images/", "Game Boy images (*.gb, *.gbc)");
if(filename == "") return;
fileBrowser->open("Load Game Boy Cartridge", { "*.gb", "*.gbc" }, [](string filename) {
interface->loadCartridgeGameBoy(filename);
});
};
nesPower.onTick = { &Interface::power, interface };
@ -118,6 +124,8 @@ MainWindow::MainWindow() {
dspaudio.setVolume(settingsMuteAudio.checked() ? 0.0 : 1.0);
};
toolsShrinkWindow.onTick = [&] { utility->resizeMainWindow(true); };
helpAbout.onTick = [&] {
MessageWindow::information(*this, {
application->title, "\n\n",

View File

@ -29,6 +29,9 @@ struct MainWindow : Window {
CheckItem settingsSynchronizeAudio;
CheckItem settingsMuteAudio;
Menu toolsMenu;
Item toolsShrinkWindow;
Menu helpMenu;
Item helpAbout;

View File

@ -3,12 +3,23 @@
Application *application = 0;
nall::DSP dspaudio;
Application::Application(int argc, char **argv) {
void Application::run() {
interface->input_poll();
if(interface->loaded() == false) {
usleep(20 * 1000);
return;
}
interface->run();
}
Application::Application(int argc, char **argv) : quit(false) {
application = this;
interface = new Interface;
utility = new Utility;
title = "batch v000";
title = "batch";
#if defined(PLATFORM_WIN)
string videoDriver = "Direct3D", audioDriver = "XAudio2", inputDriver = "RawInput";
@ -21,6 +32,7 @@ Application::Application(int argc, char **argv) {
#endif
mainWindow = new MainWindow;
fileBrowser = new FileBrowser;
utility->setMode(Interface::Mode::None);
mainWindow->setVisible();
@ -47,30 +59,19 @@ Application::Application(int argc, char **argv) {
input.set(Input::Handle, mainWindow->viewport.handle());
input.init();
timer.onTimeout = { &Application::run, this };
timer.setInterval(0);
timer.setEnabled();
OS::main();
while(quit == false) {
OS::processEvents();
Application::run();
}
}
Application::~Application() {
delete fileBrowser;
delete mainWindow;
delete utility;
delete interface;
}
void Application::run() {
interface->input_poll();
if(interface->loaded() == false) {
usleep(20 * 1000);
return;
}
interface->run();
}
int main(int argc, char **argv) {
new Application(argc, argv);
delete application;

View File

@ -37,7 +37,7 @@ void Utility::setMode(Interface::Mode mode) {
resizeMainWindow();
}
void Utility::resizeMainWindow() {
void Utility::resizeMainWindow(bool shrink) {
Geometry geometry = mainWindow->geometry();
unsigned width = geometry.width, height = geometry.height;
@ -54,10 +54,18 @@ void Utility::resizeMainWindow() {
width = width * maxM;
height = height * maxM;
if(shrink == false) {
mainWindow->viewport.setGeometry({
(geometry.width - width) / 2, (geometry.height - height) / 2,
width, height
});
} else {
mainWindow->setGeometry({ geometry.x, geometry.y, width, height });
mainWindow->viewport.setGeometry({ 0, 0, width, height });
}
}
void Utility::shrinkMainWindow() {
}
void Utility::toggleFullScreen() {

View File

@ -1,6 +1,7 @@
struct Utility {
void setMode(Interface::Mode mode);
void resizeMainWindow();
void resizeMainWindow(bool shrink = false);
void shrinkMainWindow();
void toggleFullScreen();
};