Refactoring window stuff. Still needs some work.
This commit is contained in:
parent
e7d61f4b1f
commit
991e7d8ad3
|
@ -52,7 +52,7 @@ private:
|
||||||
class DebugEvent {
|
class DebugEvent {
|
||||||
public:
|
public:
|
||||||
DebugEvent(Debugger* debugger) :
|
DebugEvent(Debugger* debugger) :
|
||||||
debugger_(debugger) {}
|
debugger_(debugger) {}
|
||||||
virtual ~DebugEvent() {}
|
virtual ~DebugEvent() {}
|
||||||
Debugger* debugger() const { return debugger_; }
|
Debugger* debugger() const { return debugger_; }
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -27,10 +27,5 @@ namespace xe {
|
||||||
#include <xenia/core/run_loop.h>
|
#include <xenia/core/run_loop.h>
|
||||||
#include <xenia/core/socket.h>
|
#include <xenia/core/socket.h>
|
||||||
#include <xenia/core/thread.h>
|
#include <xenia/core/thread.h>
|
||||||
#include <xenia/core/window.h>
|
|
||||||
|
|
||||||
#if XE_PLATFORM_WIN32
|
|
||||||
#include <xenia/core/win32_window.h>
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
#endif // XENIA_CORE_H_
|
#endif // XENIA_CORE_H_
|
||||||
|
|
|
@ -59,7 +59,7 @@ int xe_run_loop_pump(xe_run_loop_ref run_loop) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_XE_RUN_LOOP_QUIT:
|
case WM_XE_RUN_LOOP_QUIT:
|
||||||
if (msg.lParam == (WPARAM)run_loop) {
|
if (msg.wParam == (WPARAM)run_loop) {
|
||||||
// Done!
|
// Done!
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ int xe_run_loop_pump(xe_run_loop_ref run_loop) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void xe_run_loop_quit(xe_run_loop_ref run_loop) {
|
void xe_run_loop_quit(xe_run_loop_ref run_loop) {
|
||||||
PostMessage(NULL, WM_XE_RUN_LOOP_QUIT, 0, (WPARAM)run_loop);
|
PostMessage(NULL, WM_XE_RUN_LOOP_QUIT, (WPARAM)run_loop, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xe_run_loop_call(xe_run_loop_ref run_loop,
|
void xe_run_loop_call(xe_run_loop_ref run_loop,
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
'socket.h',
|
'socket.h',
|
||||||
'thread.cc',
|
'thread.cc',
|
||||||
'thread.h',
|
'thread.h',
|
||||||
'window.cc',
|
|
||||||
'window.h',
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'conditions': [
|
'conditions': [
|
||||||
|
@ -49,8 +47,6 @@
|
||||||
'path_win.cc',
|
'path_win.cc',
|
||||||
'run_loop_win.cc',
|
'run_loop_win.cc',
|
||||||
'socket_win.cc',
|
'socket_win.cc',
|
||||||
'win32_window.cc',
|
|
||||||
'win32_window.h',
|
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
|
||||||
******************************************************************************
|
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef XENIA_CORE_WINDOW_H_
|
|
||||||
#define XENIA_CORE_WINDOW_H_
|
|
||||||
|
|
||||||
#include <xenia/common.h>
|
|
||||||
#include <xenia/core/pal.h>
|
|
||||||
#include <xenia/core/ref.h>
|
|
||||||
#include <xenia/core/run_loop.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
|
||||||
namespace core {
|
|
||||||
|
|
||||||
|
|
||||||
class Window {
|
|
||||||
public:
|
|
||||||
Window(xe_run_loop_ref run_loop);
|
|
||||||
virtual ~Window();
|
|
||||||
|
|
||||||
virtual void set_title(const xechar_t* title) = 0;
|
|
||||||
|
|
||||||
uint32_t width() const { return width_; }
|
|
||||||
uint32_t height() const { return height_; }
|
|
||||||
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
|
||||||
|
|
||||||
virtual void ShowError(const xechar_t* message) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void OnResize(uint32_t width, uint32_t height) {}
|
|
||||||
virtual void OnClose() {}
|
|
||||||
|
|
||||||
xe_run_loop_ref run_loop_;
|
|
||||||
|
|
||||||
uint32_t width_;
|
|
||||||
uint32_t height_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace core
|
|
||||||
} // namespace xe
|
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_CORE_WINDOW_H_
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <xenia/kernel/kernel_state.h>
|
#include <xenia/kernel/kernel_state.h>
|
||||||
#include <xenia/kernel/modules.h>
|
#include <xenia/kernel/modules.h>
|
||||||
#include <xenia/kernel/fs/filesystem.h>
|
#include <xenia/kernel/fs/filesystem.h>
|
||||||
|
#include <xenia/ui/window.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
|
@ -29,9 +30,11 @@ using namespace xe::gpu;
|
||||||
using namespace xe::hid;
|
using namespace xe::hid;
|
||||||
using namespace xe::kernel;
|
using namespace xe::kernel;
|
||||||
using namespace xe::kernel::fs;
|
using namespace xe::kernel::fs;
|
||||||
|
using namespace xe::ui;
|
||||||
|
|
||||||
|
|
||||||
Emulator::Emulator(const xechar_t* command_line) :
|
Emulator::Emulator(const xechar_t* command_line) :
|
||||||
|
main_window_(0),
|
||||||
memory_(0),
|
memory_(0),
|
||||||
debug_server_(0),
|
debug_server_(0),
|
||||||
processor_(0),
|
processor_(0),
|
||||||
|
@ -44,6 +47,10 @@ Emulator::Emulator(const xechar_t* command_line) :
|
||||||
Emulator::~Emulator() {
|
Emulator::~Emulator() {
|
||||||
// Note that we delete things in the reverse order they were initialized.
|
// Note that we delete things in the reverse order they were initialized.
|
||||||
|
|
||||||
|
if (main_window_) {
|
||||||
|
main_window_->Close();
|
||||||
|
}
|
||||||
|
|
||||||
// Disconnect all debug clients first.
|
// Disconnect all debug clients first.
|
||||||
if (debug_server_) {
|
if (debug_server_) {
|
||||||
debug_server_->Shutdown();
|
debug_server_->Shutdown();
|
||||||
|
|
|
@ -25,6 +25,7 @@ XEDECLARECLASS2(xe, kernel, KernelState);
|
||||||
XEDECLARECLASS2(xe, kernel, XamModule);
|
XEDECLARECLASS2(xe, kernel, XamModule);
|
||||||
XEDECLARECLASS2(xe, kernel, XboxkrnlModule);
|
XEDECLARECLASS2(xe, kernel, XboxkrnlModule);
|
||||||
XEDECLARECLASS3(xe, kernel, fs, FileSystem);
|
XEDECLARECLASS3(xe, kernel, fs, FileSystem);
|
||||||
|
XEDECLARECLASS2(xe, ui, Window);
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -36,6 +37,10 @@ public:
|
||||||
~Emulator();
|
~Emulator();
|
||||||
|
|
||||||
const xechar_t* command_line() const { return command_line_; }
|
const xechar_t* command_line() const { return command_line_; }
|
||||||
|
|
||||||
|
ui::Window* main_window() const { return main_window_; }
|
||||||
|
void set_main_window(ui::Window* window) { main_window_ = window; }
|
||||||
|
|
||||||
Memory* memory() const { return memory_; }
|
Memory* memory() const { return memory_; }
|
||||||
|
|
||||||
debug::DebugServer* debug_server() const { return debug_server_; }
|
debug::DebugServer* debug_server() const { return debug_server_; }
|
||||||
|
@ -58,8 +63,11 @@ public:
|
||||||
X_STATUS LaunchDiscImage(const xechar_t* path);
|
X_STATUS LaunchDiscImage(const xechar_t* path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
xechar_t command_line_[XE_MAX_PATH];
|
xechar_t command_line_[XE_MAX_PATH];
|
||||||
Memory* memory_;
|
|
||||||
|
ui::Window* main_window_;
|
||||||
|
|
||||||
|
Memory* memory_;
|
||||||
|
|
||||||
debug::DebugServer* debug_server_;
|
debug::DebugServer* debug_server_;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <xenia/gpu/d3d11/d3d11_graphics_system.h>
|
#include <xenia/gpu/d3d11/d3d11_graphics_system.h>
|
||||||
|
|
||||||
|
#include <xenia/emulator.h>
|
||||||
#include <xenia/gpu/gpu-private.h>
|
#include <xenia/gpu/gpu-private.h>
|
||||||
#include <xenia/gpu/d3d11/d3d11_graphics_driver.h>
|
#include <xenia/gpu/d3d11/d3d11_graphics_driver.h>
|
||||||
#include <xenia/gpu/d3d11/d3d11_window.h>
|
#include <xenia/gpu/d3d11/d3d11_window.h>
|
||||||
|
@ -122,7 +123,12 @@ void D3D11GraphicsSystem::Initialize() {
|
||||||
// will take place.
|
// will take place.
|
||||||
XEASSERTNULL(window_);
|
XEASSERTNULL(window_);
|
||||||
window_ = new D3D11Window(run_loop_, dxgi_factory_, device_);
|
window_ = new D3D11Window(run_loop_, dxgi_factory_, device_);
|
||||||
window_->set_title(XETEXT("Xenia D3D11"));
|
if (window_->Initialize("Xenia D3D11", 1280, 768)) {
|
||||||
|
XELOGE("Failed to create D3D11Window");
|
||||||
|
exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emulator_->set_main_window(window_);
|
||||||
|
|
||||||
// Listen for alt-enter/etc.
|
// Listen for alt-enter/etc.
|
||||||
dxgi_factory_->MakeWindowAssociation(window_->handle(), 0);
|
dxgi_factory_->MakeWindowAssociation(window_->handle(), 0);
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::core;
|
|
||||||
using namespace xe::gpu;
|
using namespace xe::gpu;
|
||||||
using namespace xe::gpu::d3d11;
|
using namespace xe::gpu::d3d11;
|
||||||
|
using namespace xe::ui;
|
||||||
|
using namespace xe::ui::win32;
|
||||||
|
|
||||||
|
|
||||||
D3D11Window::D3D11Window(
|
D3D11Window::D3D11Window(
|
||||||
|
@ -29,10 +30,33 @@ D3D11Window::D3D11Window(
|
||||||
swap_chain_ = 0;
|
swap_chain_ = 0;
|
||||||
render_target_view_ = 0;
|
render_target_view_ = 0;
|
||||||
|
|
||||||
|
// TODO(benvanik): move to emulator main window setter.
|
||||||
|
closing.AddListener([](UIEvent& e) {
|
||||||
|
xe_run_loop_quit(e.window()->run_loop());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11Window::~D3D11Window() {
|
||||||
|
if (context_) {
|
||||||
|
context_->ClearState();
|
||||||
|
}
|
||||||
|
XESAFERELEASE(render_target_view_);
|
||||||
|
XESAFERELEASE(context_);
|
||||||
|
XESAFERELEASE(swap_chain_);
|
||||||
|
XESAFERELEASE(device_);
|
||||||
|
XESAFERELEASE(dxgi_factory_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int D3D11Window::Initialize(const char* title, uint32_t width, uint32_t height) {
|
||||||
|
int result = Win32Window::Initialize(title, width, height);
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Setup swap chain.
|
// Setup swap chain.
|
||||||
DXGI_SWAP_CHAIN_DESC desc;
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
xe_zero_struct(&desc, sizeof(desc));
|
xe_zero_struct(&desc, sizeof(desc));
|
||||||
desc.OutputWindow = handle_;
|
desc.OutputWindow = handle();
|
||||||
desc.Windowed = TRUE;
|
desc.Windowed = TRUE;
|
||||||
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||||
|
@ -40,8 +64,8 @@ D3D11Window::D3D11Window(
|
||||||
// Setup buffers.
|
// Setup buffers.
|
||||||
desc.BufferCount = 1;
|
desc.BufferCount = 1;
|
||||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
desc.BufferDesc.Width = width_;
|
desc.BufferDesc.Width = width;
|
||||||
desc.BufferDesc.Height = height_;
|
desc.BufferDesc.Height = height;
|
||||||
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
desc.BufferDesc.RefreshRate.Numerator = 60;
|
desc.BufferDesc.RefreshRate.Numerator = 60;
|
||||||
desc.BufferDesc.RefreshRate.Denominator = 1;
|
desc.BufferDesc.RefreshRate.Denominator = 1;
|
||||||
|
@ -57,8 +81,7 @@ D3D11Window::D3D11Window(
|
||||||
&swap_chain_);
|
&swap_chain_);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
XELOGE("CreateSwapChain failed with %.8X", hr);
|
XELOGE("CreateSwapChain failed with %.8X", hr);
|
||||||
exit(1);
|
return 1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a render target view to draw into.
|
// Create a render target view to draw into.
|
||||||
|
@ -67,29 +90,18 @@ D3D11Window::D3D11Window(
|
||||||
0, __uuidof(ID3D11Texture2D), (void**)&back_buffer);
|
0, __uuidof(ID3D11Texture2D), (void**)&back_buffer);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
XELOGE("GetBuffer (back_buffer) failed with %.8X", hr);
|
XELOGE("GetBuffer (back_buffer) failed with %.8X", hr);
|
||||||
exit(1);
|
return 1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
hr = device_->CreateRenderTargetView(
|
hr = device_->CreateRenderTargetView(
|
||||||
back_buffer, NULL, &render_target_view_);
|
back_buffer, NULL, &render_target_view_);
|
||||||
back_buffer->Release();
|
back_buffer->Release();
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
XELOGE("CreateRenderTargetView (back_buffer) failed with %.8X", hr);
|
XELOGE("CreateRenderTargetView (back_buffer) failed with %.8X", hr);
|
||||||
exit(1);
|
return 1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
context_->OMSetRenderTargets(1, &render_target_view_, NULL);
|
context_->OMSetRenderTargets(1, &render_target_view_, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
D3D11Window::~D3D11Window() {
|
return 0;
|
||||||
if (context_) {
|
|
||||||
context_->ClearState();
|
|
||||||
}
|
|
||||||
XESAFERELEASE(render_target_view_);
|
|
||||||
XESAFERELEASE(context_);
|
|
||||||
XESAFERELEASE(swap_chain_);
|
|
||||||
XESAFERELEASE(device_);
|
|
||||||
XESAFERELEASE(dxgi_factory_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11Window::Swap() {
|
void D3D11Window::Swap() {
|
||||||
|
@ -102,13 +114,13 @@ void D3D11Window::Swap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11Window::OnResize(uint32_t width, uint32_t height) {
|
bool D3D11Window::OnResize(uint32_t width, uint32_t height) {
|
||||||
Win32Window::OnResize(width, height);
|
if (!Win32Window::OnResize(width, height)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(benvanik): resize swap buffers?
|
// TODO(benvanik): resize swap buffers?
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11Window::OnClose() {
|
|
||||||
// We are the master window - if they close us, quit!
|
|
||||||
xe_run_loop_quit(run_loop_);
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <xenia/core.h>
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/ui/win32/win32_window.h>
|
||||||
|
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,18 +22,19 @@ namespace gpu {
|
||||||
namespace d3d11 {
|
namespace d3d11 {
|
||||||
|
|
||||||
|
|
||||||
class D3D11Window : public xe::core::Win32Window {
|
class D3D11Window : public xe::ui::win32::Win32Window {
|
||||||
public:
|
public:
|
||||||
D3D11Window(
|
D3D11Window(
|
||||||
xe_run_loop_ref run_loop,
|
xe_run_loop_ref run_loop,
|
||||||
IDXGIFactory1* dxgi_factory, ID3D11Device* device);
|
IDXGIFactory1* dxgi_factory, ID3D11Device* device);
|
||||||
virtual ~D3D11Window();
|
virtual ~D3D11Window();
|
||||||
|
|
||||||
|
virtual int Initialize(const char* title, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
void Swap();
|
void Swap();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void OnResize(uint32_t width, uint32_t height);
|
virtual bool OnResize(uint32_t width, uint32_t height);
|
||||||
virtual void OnClose();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IDXGIFactory1* dxgi_factory_;
|
IDXGIFactory1* dxgi_factory_;
|
||||||
|
|
|
@ -93,7 +93,8 @@ void GraphicsSystem::ThreadStart() {
|
||||||
|
|
||||||
xe_run_loop_release(run_loop);
|
xe_run_loop_release(run_loop);
|
||||||
|
|
||||||
// TODO(benvanik): call module API to kill?
|
// TODO(benvanik): call module API to kill? this is a bad shutdown.
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsSystem::Initialize() {
|
void GraphicsSystem::Initialize() {
|
||||||
|
|
|
@ -33,5 +33,6 @@
|
||||||
'gpu/sources.gypi',
|
'gpu/sources.gypi',
|
||||||
'hid/sources.gypi',
|
'hid/sources.gypi',
|
||||||
'kernel/sources.gypi',
|
'kernel/sources.gypi',
|
||||||
|
'ui/sources.gypi',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xenia/core/window.h>
|
#include <xenia/ui/menu_item.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::core;
|
using namespace xe::ui;
|
||||||
|
|
||||||
|
|
||||||
Window::Window(xe_run_loop_ref run_loop) {
|
MenuItem::MenuItem(Window* window, MenuItem* parent_item) :
|
||||||
run_loop_ = xe_run_loop_retain(run_loop);
|
window_(window), parent_item_(parent_item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
MenuItem::~MenuItem() {
|
||||||
xe_run_loop_release(run_loop_);
|
}
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_UI_MENU_ITEM_H_
|
||||||
|
#define XENIA_UI_MENU_ITEM_H_
|
||||||
|
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class Window;
|
||||||
|
|
||||||
|
|
||||||
|
class MenuItem {
|
||||||
|
public:
|
||||||
|
MenuItem(Window* window, MenuItem* parent_item = NULL);
|
||||||
|
virtual ~MenuItem();
|
||||||
|
|
||||||
|
Window* window() const { return window_; }
|
||||||
|
MenuItem* parent_item() const { return parent_item_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Window* window_;
|
||||||
|
MenuItem* parent_item_;
|
||||||
|
// children
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_UI_MENU_ITEM_H_
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright 2014 Ben Vanik. All Rights Reserved.
|
||||||
|
{
|
||||||
|
'sources': [
|
||||||
|
'menu_item.cc',
|
||||||
|
'menu_item.h',
|
||||||
|
'ui_event.h',
|
||||||
|
'window.cc',
|
||||||
|
'window.h',
|
||||||
|
],
|
||||||
|
|
||||||
|
'conditions': [
|
||||||
|
['OS == "win"', {
|
||||||
|
'includes': [
|
||||||
|
'win32/sources.gypi',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_UI_UI_EVENT_H_
|
||||||
|
#define XENIA_UI_UI_EVENT_H_
|
||||||
|
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class App;
|
||||||
|
class Window;
|
||||||
|
|
||||||
|
|
||||||
|
class UIEvent {
|
||||||
|
public:
|
||||||
|
UIEvent(Window* window = NULL) :
|
||||||
|
window_(window) {}
|
||||||
|
virtual ~UIEvent() {}
|
||||||
|
|
||||||
|
Window* window() const { return window_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Window* window_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MouseEvent : public UIEvent {
|
||||||
|
public:
|
||||||
|
enum Button {
|
||||||
|
MOUSE_BUTTON_NONE = 0,
|
||||||
|
MOUSE_BUTTON_LEFT,
|
||||||
|
MOUSE_BUTTON_RIGHT,
|
||||||
|
MOUSE_BUTTON_MIDDLE,
|
||||||
|
MOUSE_BUTTON_X1,
|
||||||
|
MOUSE_BUTTON_X2,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
MouseEvent(Window* window,
|
||||||
|
Button button, int32_t x, int32_t y,
|
||||||
|
int32_t dx = 0, int32_t dy = 0) :
|
||||||
|
button_(button), x_(x), y_(y), dx_(dx), dy_(dy),
|
||||||
|
UIEvent(window) {}
|
||||||
|
virtual ~MouseEvent() {}
|
||||||
|
|
||||||
|
Button button() const { return button_; }
|
||||||
|
int32_t x() const { return x_; }
|
||||||
|
int32_t y() const { return y_; }
|
||||||
|
int32_t dx() const { return dx_; }
|
||||||
|
int32_t dy() const { return dy_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Button button_;
|
||||||
|
int32_t x_;
|
||||||
|
int32_t y_;
|
||||||
|
int32_t dx_;
|
||||||
|
int32_t dy_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_UI_UI_EVENT_H_
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright 2014 Ben Vanik. All Rights Reserved.
|
||||||
|
{
|
||||||
|
'sources': [
|
||||||
|
'win32_menu_item.cc',
|
||||||
|
'win32_menu_item.h',
|
||||||
|
'win32_window.cc',
|
||||||
|
'win32_window.h',
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xenia/ui/win32/win32_menu_item.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::ui;
|
||||||
|
using namespace xe::ui::win32;
|
||||||
|
|
||||||
|
|
||||||
|
Win32MenuItem::Win32MenuItem(Window* window, MenuItem* parent_item) :
|
||||||
|
MenuItem(window, parent_item) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Win32MenuItem::~Win32MenuItem() {
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_UI_WIN32_WIN32_MENU_ITEM_H_
|
||||||
|
#define XENIA_UI_WIN32_WIN32_MENU_ITEM_H_
|
||||||
|
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/ui/menu_item.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace win32 {
|
||||||
|
|
||||||
|
|
||||||
|
class Win32MenuItem : public MenuItem {
|
||||||
|
public:
|
||||||
|
Win32MenuItem(Window* window, MenuItem* parent_item = NULL);
|
||||||
|
virtual ~Win32MenuItem();
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace win32
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_UI_WIN32_WIN32_MENU_ITEM_H_
|
|
@ -1,244 +1,371 @@
|
||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xenia/core/win32_window.h>
|
#include <xenia/ui/win32/win32_window.h>
|
||||||
|
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
#include <tpcshrd.h>
|
#include <tpcshrd.h>
|
||||||
|
#include <windowsx.h>
|
||||||
|
|
||||||
using namespace xe;
|
|
||||||
using namespace xe::core;
|
using namespace xe;
|
||||||
|
using namespace xe::ui;
|
||||||
|
using namespace xe::ui::win32;
|
||||||
namespace {
|
|
||||||
|
|
||||||
static LRESULT CALLBACK Win32WindowWndProc(
|
namespace {
|
||||||
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
|
||||||
Win32Window* window = 0;
|
static LRESULT CALLBACK Win32WindowWndProc(
|
||||||
if (message == WM_NCCREATE) {
|
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||||
LPCREATESTRUCT create_struct = (LPCREATESTRUCT)lParam;
|
Win32Window* window = 0;
|
||||||
window = (Win32Window*)create_struct->lpCreateParams;
|
if (message == WM_NCCREATE) {
|
||||||
SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)window);
|
LPCREATESTRUCT create_struct = (LPCREATESTRUCT)lParam;
|
||||||
} else {
|
window = (Win32Window*)create_struct->lpCreateParams;
|
||||||
window = (Win32Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)window);
|
||||||
}
|
} else {
|
||||||
if (window) {
|
window = (Win32Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
||||||
return window->WndProc(hWnd, message, wParam, lParam);
|
}
|
||||||
} else {
|
if (window) {
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return window->WndProc(hWnd, message, wParam, lParam);
|
||||||
}
|
} else {
|
||||||
}
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
Win32Window::Win32Window(xe_run_loop_ref run_loop) :
|
|
||||||
handle_(0),
|
|
||||||
Window(run_loop) {
|
Win32Window::Win32Window(xe_run_loop_ref run_loop) :
|
||||||
Create();
|
handle_(0), closing_(false),
|
||||||
}
|
Window(run_loop) {
|
||||||
|
}
|
||||||
Win32Window::~Win32Window() {
|
|
||||||
if (handle_) {
|
Win32Window::~Win32Window() {
|
||||||
CloseWindow(handle_);
|
if (handle_) {
|
||||||
}
|
CloseWindow(handle_);
|
||||||
}
|
handle_ = NULL;
|
||||||
|
}
|
||||||
void Win32Window::Create() {
|
}
|
||||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
|
||||||
|
int Win32Window::Initialize(const char* title, uint32_t width, uint32_t height) {
|
||||||
width_ = 1280;
|
int result = Window::Initialize(title, width, height);
|
||||||
height_ = 720;
|
if (result) {
|
||||||
|
return result;
|
||||||
WNDCLASSEX wcex;
|
}
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||||
wcex.lpfnWndProc = Win32WindowWndProc;
|
|
||||||
wcex.cbClsExtra = 0;
|
WNDCLASSEX wcex;
|
||||||
wcex.cbWndExtra = 0;
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
wcex.hInstance = hInstance;
|
wcex.style = 0;
|
||||||
wcex.hIcon = NULL; // LoadIcon(hInstance, (LPCTSTR)IDI_TUTORIAL1);
|
wcex.lpfnWndProc = Win32WindowWndProc;
|
||||||
wcex.hIconSm = NULL; // LoadIcon(hInstance, (LPCTSTR)IDI_TUTORIAL1);
|
wcex.cbClsExtra = 0;
|
||||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
wcex.cbWndExtra = 0;
|
||||||
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
|
wcex.hInstance = hInstance;
|
||||||
wcex.lpszMenuName = NULL;
|
wcex.hIcon = NULL; // LoadIcon(hInstance, (LPCTSTR)IDI_TUTORIAL1);
|
||||||
wcex.lpszClassName = L"XeniaWindowClass";
|
wcex.hIconSm = NULL; // LoadIcon(hInstance, (LPCTSTR)IDI_TUTORIAL1);
|
||||||
if (!RegisterClassEx(&wcex)) {
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
XELOGE("RegisterClassEx failed");
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||||
exit(1);
|
wcex.lpszMenuName = NULL;
|
||||||
return;
|
wcex.lpszClassName = L"XeniaWindowClass";
|
||||||
}
|
if (!RegisterClassEx(&wcex)) {
|
||||||
|
XELOGE("RegisterClassEx failed");
|
||||||
// Setup initial size.
|
return 1;
|
||||||
DWORD window_style = WS_OVERLAPPEDWINDOW;
|
}
|
||||||
DWORD window_ex_style = WS_EX_APPWINDOW;
|
|
||||||
RECT rc = {
|
// Setup initial size.
|
||||||
0, 0,
|
DWORD window_style = WS_OVERLAPPEDWINDOW;
|
||||||
width_, height_
|
DWORD window_ex_style = WS_EX_APPWINDOW;
|
||||||
};
|
RECT rc = {
|
||||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
|
0, 0,
|
||||||
|
width, height
|
||||||
// Create window.
|
};
|
||||||
handle_ = CreateWindowEx(
|
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
|
||||||
window_ex_style,
|
|
||||||
L"XeniaWindowClass",
|
// Create window.
|
||||||
L"Xenia",
|
handle_ = CreateWindowEx(
|
||||||
window_style,
|
window_ex_style,
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
L"XeniaWindowClass",
|
||||||
rc.right - rc.left, rc.bottom - rc.top,
|
L"Xenia",
|
||||||
NULL,
|
window_style,
|
||||||
NULL,
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
hInstance,
|
rc.right - rc.left, rc.bottom - rc.top,
|
||||||
this);
|
NULL,
|
||||||
if (!handle_) {
|
NULL,
|
||||||
XELOGE("CreateWindow failed");
|
hInstance,
|
||||||
exit(1);
|
this);
|
||||||
return;
|
if (!handle_) {
|
||||||
}
|
XELOGE("CreateWindow failed");
|
||||||
|
return 1;
|
||||||
// Disable flicks.
|
}
|
||||||
ATOM atom = GlobalAddAtom(L"MicrosoftTabletPenServiceProperty");
|
|
||||||
const DWORD_PTR dwHwndTabletProperty =
|
// Disable flicks.
|
||||||
TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture
|
ATOM atom = GlobalAddAtom(L"MicrosoftTabletPenServiceProperty");
|
||||||
TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves)
|
const DWORD_PTR dwHwndTabletProperty =
|
||||||
TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle)
|
TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture
|
||||||
TABLET_DISABLE_FLICKS | // disables pen flicks (back, forward, drag down, drag up)
|
TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves)
|
||||||
TABLET_DISABLE_TOUCHSWITCH |
|
TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle)
|
||||||
TABLET_DISABLE_SMOOTHSCROLLING |
|
TABLET_DISABLE_FLICKS | // disables pen flicks (back, forward, drag down, drag up)
|
||||||
TABLET_DISABLE_TOUCHUIFORCEON |
|
TABLET_DISABLE_TOUCHSWITCH |
|
||||||
TABLET_ENABLE_MULTITOUCHDATA;
|
TABLET_DISABLE_SMOOTHSCROLLING |
|
||||||
SetProp(
|
TABLET_DISABLE_TOUCHUIFORCEON |
|
||||||
handle_,
|
TABLET_ENABLE_MULTITOUCHDATA;
|
||||||
L"MicrosoftTabletPenServiceProperty",
|
SetProp(
|
||||||
reinterpret_cast<HANDLE>(dwHwndTabletProperty));
|
handle_,
|
||||||
GlobalDeleteAtom(atom);
|
L"MicrosoftTabletPenServiceProperty",
|
||||||
|
reinterpret_cast<HANDLE>(dwHwndTabletProperty));
|
||||||
// Enable DWM elevation.
|
GlobalDeleteAtom(atom);
|
||||||
EnableMMCSS();
|
|
||||||
|
// Enable DWM elevation.
|
||||||
ShowWindow(handle_, SW_SHOWNORMAL);
|
EnableMMCSS();
|
||||||
UpdateWindow(handle_);
|
|
||||||
}
|
ShowWindow(handle_, SW_SHOWNORMAL);
|
||||||
|
UpdateWindow(handle_);
|
||||||
void Win32Window::EnableMMCSS() {
|
|
||||||
HMODULE hLibrary = LoadLibrary(L"DWMAPI.DLL");
|
return 0;
|
||||||
if (!hLibrary) {
|
}
|
||||||
return;
|
|
||||||
}
|
void Win32Window::EnableMMCSS() {
|
||||||
|
HMODULE hLibrary = LoadLibrary(L"DWMAPI.DLL");
|
||||||
typedef HRESULT (__stdcall *PDwmEnableMMCSS)(BOOL);
|
if (!hLibrary) {
|
||||||
PDwmEnableMMCSS pDwmEnableMMCSS =
|
return;
|
||||||
(PDwmEnableMMCSS)GetProcAddress(
|
}
|
||||||
hLibrary, "DwmEnableMMCSS");
|
|
||||||
if (pDwmEnableMMCSS) {
|
typedef HRESULT (__stdcall *PDwmEnableMMCSS)(BOOL);
|
||||||
pDwmEnableMMCSS(TRUE);
|
PDwmEnableMMCSS pDwmEnableMMCSS =
|
||||||
}
|
(PDwmEnableMMCSS)GetProcAddress(
|
||||||
|
hLibrary, "DwmEnableMMCSS");
|
||||||
typedef HRESULT (__stdcall *PDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS*);
|
if (pDwmEnableMMCSS) {
|
||||||
PDwmSetPresentParameters pDwmSetPresentParameters =
|
pDwmEnableMMCSS(TRUE);
|
||||||
(PDwmSetPresentParameters)GetProcAddress(
|
}
|
||||||
hLibrary, "DwmSetPresentParameters");
|
|
||||||
if (pDwmSetPresentParameters) {
|
typedef HRESULT (__stdcall *PDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS*);
|
||||||
DWM_PRESENT_PARAMETERS pp;
|
PDwmSetPresentParameters pDwmSetPresentParameters =
|
||||||
memset(&pp, 0, sizeof(DWM_PRESENT_PARAMETERS));
|
(PDwmSetPresentParameters)GetProcAddress(
|
||||||
pp.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
|
hLibrary, "DwmSetPresentParameters");
|
||||||
pp.fQueue = FALSE;
|
if (pDwmSetPresentParameters) {
|
||||||
pp.cBuffer = 2;
|
DWM_PRESENT_PARAMETERS pp;
|
||||||
pp.fUseSourceRate = FALSE;
|
memset(&pp, 0, sizeof(DWM_PRESENT_PARAMETERS));
|
||||||
pp.cRefreshesPerFrame = 1;
|
pp.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
|
||||||
pp.eSampling = DWM_SOURCE_FRAME_SAMPLING_POINT;
|
pp.fQueue = FALSE;
|
||||||
pDwmSetPresentParameters(handle_, &pp);
|
pp.cBuffer = 2;
|
||||||
}
|
pp.fUseSourceRate = FALSE;
|
||||||
|
pp.cRefreshesPerFrame = 1;
|
||||||
FreeLibrary( hLibrary );
|
pp.eSampling = DWM_SOURCE_FRAME_SAMPLING_POINT;
|
||||||
}
|
pDwmSetPresentParameters(handle_, &pp);
|
||||||
|
}
|
||||||
void Win32Window::set_title(const xechar_t* title) {
|
|
||||||
XEIGNORE(SetWindowText(handle_, title));
|
FreeLibrary(hLibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::Resize(uint32_t width, uint32_t height) {
|
bool Win32Window::set_title(const char* title) {
|
||||||
if (width == width_ && height == height_) {
|
if (!Window::set_title(title)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
width_ = width;
|
XEIGNORE(SetWindowTextA(handle_, title));
|
||||||
height_ = height;
|
return true;
|
||||||
|
}
|
||||||
RECT rc = {
|
|
||||||
0, 0,
|
bool Win32Window::set_cursor_visible(bool value) {
|
||||||
width_, height_
|
if (!Window::set_cursor_visible(value)) {
|
||||||
};
|
return false;
|
||||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
|
}
|
||||||
// TODO(benvanik): center.
|
if (value) {
|
||||||
MoveWindow(handle_, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE);
|
ShowCursor(TRUE);
|
||||||
|
SetCursor(NULL);
|
||||||
OnResize(width_, height_);
|
} else {
|
||||||
}
|
ShowCursor(FALSE);
|
||||||
|
}
|
||||||
void Win32Window::ShowError(const xechar_t* message) {
|
return true;
|
||||||
XEIGNORE(MessageBox(handle_, message, L"Xenia Error", MB_ICONERROR | MB_OK));
|
}
|
||||||
}
|
|
||||||
|
bool Win32Window::SetSize(uint32_t width, uint32_t height) {
|
||||||
LRESULT Win32Window::WndProc(HWND hWnd, UINT message,
|
RECT rc = {
|
||||||
WPARAM wParam, LPARAM lParam) {
|
0, 0,
|
||||||
switch (message) {
|
width, height
|
||||||
case WM_NCCREATE:
|
};
|
||||||
handle_ = hWnd;
|
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
// TODO(benvanik): center?
|
||||||
case WM_ACTIVATEAPP:
|
MoveWindow(handle_, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE);
|
||||||
if (wParam) {
|
return true;
|
||||||
// Made active.
|
}
|
||||||
} else {
|
|
||||||
// Made inactive.
|
void Win32Window::OnClose() {
|
||||||
}
|
if (!closing_ && handle_) {
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
closing_ = true;
|
||||||
case WM_CLOSE:
|
CloseWindow(handle_);
|
||||||
OnClose();
|
handle_ = NULL;
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
}
|
||||||
case WM_DESTROY:
|
}
|
||||||
PostQuitMessage(0);
|
|
||||||
return 0;
|
bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||||
|
int32_t x = GET_X_LPARAM(lParam);
|
||||||
case WM_PAINT:
|
int32_t y = GET_Y_LPARAM(lParam);
|
||||||
{
|
if (message == WM_MOUSEWHEEL) {
|
||||||
PAINTSTRUCT ps;
|
POINT pt = { x, y };
|
||||||
HDC hdc = BeginPaint(hWnd, &ps);
|
ScreenToClient(handle_, &pt);
|
||||||
EndPaint(hWnd, &ps);
|
x = pt.x;
|
||||||
}
|
y = pt.y;
|
||||||
return 0;
|
}
|
||||||
case WM_ERASEBKGND:
|
|
||||||
return 0; // ignore
|
MouseEvent::Button button = MouseEvent::MOUSE_BUTTON_NONE;
|
||||||
case WM_DISPLAYCHANGE:
|
int32_t dx = 0;
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
int32_t dy = 0;
|
||||||
|
switch (message) {
|
||||||
case WM_MOVE:
|
case WM_LBUTTONDOWN:
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
case WM_LBUTTONUP:
|
||||||
case WM_SIZE:
|
button = MouseEvent::MOUSE_BUTTON_LEFT;
|
||||||
{
|
break;
|
||||||
RECT frame;
|
case WM_RBUTTONDOWN:
|
||||||
GetClientRect(handle_, &frame);
|
case WM_RBUTTONUP:
|
||||||
OnResize(frame.right - frame.left, frame.bottom - frame.top);
|
button = MouseEvent::MOUSE_BUTTON_RIGHT;
|
||||||
}
|
break;
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
case WM_MBUTTONDOWN:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
|
button = MouseEvent::MOUSE_BUTTON_MIDDLE;
|
||||||
return
|
break;
|
||||||
TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture
|
case WM_XBUTTONDOWN:
|
||||||
TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves)
|
case WM_XBUTTONUP:
|
||||||
TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle)
|
switch (GET_XBUTTON_WPARAM(wParam)) {
|
||||||
TABLET_DISABLE_FLICKS | // disables pen flicks (back, forward, drag down, drag up)
|
case XBUTTON1:
|
||||||
TABLET_DISABLE_TOUCHSWITCH |
|
button = MouseEvent::MOUSE_BUTTON_X1;
|
||||||
TABLET_DISABLE_SMOOTHSCROLLING |
|
break;
|
||||||
TABLET_DISABLE_TOUCHUIFORCEON |
|
case XBUTTON2:
|
||||||
TABLET_ENABLE_MULTITOUCHDATA;
|
button = MouseEvent::MOUSE_BUTTON_X2;
|
||||||
default:
|
break;
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
default:
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
button = MouseEvent::MOUSE_BUTTON_NONE;
|
||||||
|
break;
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
button = MouseEvent::MOUSE_BUTTON_NONE;
|
||||||
|
dx = 0; // ?
|
||||||
|
dy = GET_WHEEL_DELTA_WPARAM(wParam);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Double click/etc?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto e = MouseEvent(this, button, x, y, dx, dy);
|
||||||
|
switch (message) {
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
case WM_XBUTTONDOWN:
|
||||||
|
mouse_down(e);
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
case WM_XBUTTONUP:
|
||||||
|
mouse_up(e);
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
mouse_move(e);
|
||||||
|
break;
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
mouse_wheel(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Win32Window::HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||||
|
switch (message) {
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
(byte)wParam;
|
||||||
|
return true;
|
||||||
|
case WM_KEYUP:
|
||||||
|
(byte)wParam;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT Win32Window::WndProc(HWND hWnd, UINT message,
|
||||||
|
WPARAM wParam, LPARAM lParam) {
|
||||||
|
if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) {
|
||||||
|
if (HandleMouse(message, wParam, lParam)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
} else if (message >= WM_KEYFIRST && message <= WM_KEYLAST) {
|
||||||
|
if (HandleKeyboard(message, wParam, lParam)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
case WM_NCCREATE:
|
||||||
|
handle_ = hWnd;
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
case WM_ACTIVATEAPP:
|
||||||
|
if (wParam) {
|
||||||
|
// Made active.
|
||||||
|
OnShow();
|
||||||
|
} else {
|
||||||
|
// Made inactive.
|
||||||
|
OnHide();
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
case WM_CLOSE:
|
||||||
|
closing_ = true;
|
||||||
|
Close();
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
case WM_DESTROY:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_PAINT:
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
HDC hdc = BeginPaint(hWnd, &ps);
|
||||||
|
EndPaint(hWnd, &ps);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case WM_ERASEBKGND:
|
||||||
|
return 0; // ignore
|
||||||
|
case WM_DISPLAYCHANGE:
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
|
||||||
|
case WM_MOVE:
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
case WM_SIZING:
|
||||||
|
BeginResizing();
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
RECT frame;
|
||||||
|
GetClientRect(handle_, &frame);
|
||||||
|
OnResize(frame.right - frame.left, frame.bottom - frame.top);
|
||||||
|
EndResizing();
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
|
||||||
|
case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
|
||||||
|
return
|
||||||
|
TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture
|
||||||
|
TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves)
|
||||||
|
TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle)
|
||||||
|
TABLET_DISABLE_FLICKS | // disables pen flicks (back, forward, drag down, drag up)
|
||||||
|
TABLET_DISABLE_TOUCHSWITCH |
|
||||||
|
TABLET_DISABLE_SMOOTHSCROLLING |
|
||||||
|
TABLET_DISABLE_TOUCHUIFORCEON |
|
||||||
|
TABLET_ENABLE_MULTITOUCHDATA;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,49 +1,55 @@
|
||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_CORE_WIN32_WINDOW_H_
|
#ifndef XENIA_UI_WIN32_WIN32_WINDOW_H_
|
||||||
#define XENIA_CORE_WIN32_WINDOW_H_
|
#define XENIA_UI_WIN32_WIN32_WINDOW_H_
|
||||||
|
|
||||||
#include <xenia/common.h>
|
#include <xenia/core.h>
|
||||||
#include <xenia/core/window.h>
|
|
||||||
|
#include <xenia/ui/window.h>
|
||||||
|
|
||||||
namespace xe {
|
|
||||||
namespace core {
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace win32 {
|
||||||
class Win32Window : public Window {
|
|
||||||
public:
|
|
||||||
Win32Window(xe_run_loop_ref run_loop);
|
class Win32Window : public Window {
|
||||||
virtual ~Win32Window();
|
public:
|
||||||
|
Win32Window(xe_run_loop_ref run_loop);
|
||||||
HWND handle() const { return handle_; }
|
virtual ~Win32Window();
|
||||||
|
|
||||||
virtual void set_title(const xechar_t* title);
|
virtual int Initialize(const char* title, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
virtual void Resize(uint32_t width, uint32_t height);
|
virtual bool set_title(const char* title);
|
||||||
|
virtual bool set_cursor_visible(bool value);
|
||||||
virtual void ShowError(const xechar_t* message);
|
HWND handle() const { return handle_; }
|
||||||
|
|
||||||
LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HWND handle_;
|
virtual bool SetSize(uint32_t width, uint32_t height);
|
||||||
|
virtual void OnClose();
|
||||||
private:
|
|
||||||
void Create();
|
private:
|
||||||
void EnableMMCSS();
|
void EnableMMCSS();
|
||||||
};
|
bool HandleMouse(UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
bool HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
} // namespace core
|
HWND handle_;
|
||||||
} // namespace xe
|
bool closing_;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // XENIA_CORE_WIN32_WINDOW_H_
|
|
||||||
|
} // namespace win32
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_UI_WIN32_WIN32_WINDOW_H_
|
|
@ -0,0 +1,120 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xenia/ui/window.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::ui;
|
||||||
|
|
||||||
|
|
||||||
|
Window::Window(xe_run_loop_ref run_loop) :
|
||||||
|
title_(0), is_visible_(true), is_cursor_visible_(true),
|
||||||
|
width_(0), height_(0) {
|
||||||
|
run_loop_ = xe_run_loop_retain(run_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window() {
|
||||||
|
if (title_) {
|
||||||
|
xe_free(title_);
|
||||||
|
}
|
||||||
|
xe_run_loop_release(run_loop_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Window::Initialize(const char* title, uint32_t width, uint32_t height) {
|
||||||
|
title_ = xestrdupa(title);
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Window::set_title(const char* title) {
|
||||||
|
if (title == title_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (title_) {
|
||||||
|
xe_free(title_);
|
||||||
|
}
|
||||||
|
title_ = xestrdupa(title);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Window::set_cursor_visible(bool value) {
|
||||||
|
if (value == is_cursor_visible_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
is_cursor_visible_ = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::OnShow() {
|
||||||
|
if (is_visible_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is_visible_ = true;
|
||||||
|
auto e = UIEvent(this);
|
||||||
|
shown(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::OnHide() {
|
||||||
|
if (!is_visible_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is_visible_ = false;
|
||||||
|
auto e = UIEvent(this);
|
||||||
|
hidden(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::Resize(uint32_t width, uint32_t height) {
|
||||||
|
BeginResizing();
|
||||||
|
SetSize(width, height);
|
||||||
|
OnResize(width, height); // redundant?
|
||||||
|
EndResizing();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::BeginResizing() {
|
||||||
|
if (resizing_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resizing_ = true;
|
||||||
|
auto e = UIEvent(this);
|
||||||
|
resizing(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Window::OnResize(uint32_t width, uint32_t height) {
|
||||||
|
if (!resizing_) {
|
||||||
|
BeginResizing();
|
||||||
|
}
|
||||||
|
if (width == width_ && height == height_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::EndResizing() {
|
||||||
|
XEASSERT(resizing_);
|
||||||
|
resizing_ = false;
|
||||||
|
auto e = UIEvent(this);
|
||||||
|
resized(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::Close() {
|
||||||
|
auto e = UIEvent(this);
|
||||||
|
closing(e);
|
||||||
|
|
||||||
|
OnClose();
|
||||||
|
|
||||||
|
e = UIEvent(this);
|
||||||
|
closed(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::OnClose() {
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_UI_WINDOW_H_
|
||||||
|
#define XENIA_UI_WINDOW_H_
|
||||||
|
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <alloy/delegate.h>
|
||||||
|
#include <xenia/ui/ui_event.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
|
||||||
|
class Window {
|
||||||
|
public:
|
||||||
|
Window(xe_run_loop_ref run_loop);
|
||||||
|
virtual ~Window();
|
||||||
|
|
||||||
|
virtual int Initialize(const char* title, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
|
xe_run_loop_ref run_loop() const { return run_loop_; }
|
||||||
|
|
||||||
|
const char* title() const { return title_; }
|
||||||
|
virtual bool set_title(const char* title);
|
||||||
|
bool is_visible() const { return is_visible_; }
|
||||||
|
bool is_cursor_visible() const { return is_cursor_visible_; }
|
||||||
|
virtual bool set_cursor_visible(bool value);
|
||||||
|
uint32_t width() const { return width_; }
|
||||||
|
uint32_t height() const { return height_; }
|
||||||
|
void Resize(uint32_t width, uint32_t height);
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
public:
|
||||||
|
alloy::Delegate<UIEvent> shown;
|
||||||
|
alloy::Delegate<UIEvent> hidden;
|
||||||
|
alloy::Delegate<UIEvent> resizing;
|
||||||
|
alloy::Delegate<UIEvent> resized;
|
||||||
|
alloy::Delegate<UIEvent> closing;
|
||||||
|
alloy::Delegate<UIEvent> closed;
|
||||||
|
|
||||||
|
alloy::Delegate<MouseEvent> mouse_down;
|
||||||
|
alloy::Delegate<MouseEvent> mouse_move;
|
||||||
|
alloy::Delegate<MouseEvent> mouse_up;
|
||||||
|
alloy::Delegate<MouseEvent> mouse_wheel;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void OnShow();
|
||||||
|
void OnHide();
|
||||||
|
|
||||||
|
void BeginResizing();
|
||||||
|
virtual bool OnResize(uint32_t width, uint32_t height);
|
||||||
|
void EndResizing();
|
||||||
|
virtual bool SetSize(uint32_t width, uint32_t height) = 0;
|
||||||
|
|
||||||
|
virtual void OnClose();
|
||||||
|
|
||||||
|
private:
|
||||||
|
xe_run_loop_ref run_loop_;
|
||||||
|
char* title_;
|
||||||
|
bool is_visible_;
|
||||||
|
bool is_cursor_visible_;
|
||||||
|
bool resizing_;
|
||||||
|
uint32_t width_;
|
||||||
|
uint32_t height_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_UI_WINDOW_H_
|
Loading…
Reference in New Issue