xe::ui control for hosting a turbobadger UI.

This commit is contained in:
Ben Vanik
2015-07-01 15:58:04 -07:00
parent dec0d12cc9
commit 4ec0655751
19 changed files with 1069 additions and 13 deletions

View File

@@ -77,10 +77,11 @@ LRESULT WGLControl::WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam) {
switch (message) {
case WM_PAINT: {
invalidated_ = false;
ValidateRect(hWnd, nullptr);
SCOPE_profile_cpu_i("gpu", "xe::gpu::gl4::WGLControl::WM_PAINT");
{
GLContextLock context_lock(&context_);
wglSwapIntervalEXT(0);
float clear_color[] = {rand() / (float)RAND_MAX, 1.0f, 0, 1.0f};
glClearNamedFramebufferfv(0, GL_COLOR, 0, clear_color);
@@ -100,6 +101,7 @@ LRESULT WGLControl::WndProc(HWND hWnd, UINT message, WPARAM wParam,
SCOPE_profile_cpu_i("gpu", "xe::gpu::gl4::WGLControl::SwapBuffers");
SwapBuffers(context_.dc());
}
return 0;
} break;
}
return Win32Control::WndProc(hWnd, message, wParam, lParam);

View File

@@ -21,6 +21,7 @@ class Loop {
virtual ~Loop() = default;
virtual void Post(std::function<void()> fn) = 0;
virtual void PostDelayed(std::function<void()> fn, uint64_t delay_millis) = 0;
virtual void Quit() = 0;
virtual void AwaitQuit() = 0;

View File

@@ -121,10 +121,13 @@ void Win32Control::OnResize(UIEvent& e) {
}
void Win32Control::Invalidate() {
if (invalidated_) {
return;
}
invalidated_ = true;
InvalidateRect(hwnd_, nullptr, FALSE);
for (auto& child_control : children_) {
auto win32_control = static_cast<Win32Control*>(child_control.get());
win32_control->Invalidate();
child_control->Invalidate();
}
}
@@ -234,8 +237,15 @@ LRESULT Win32Control::WndProc(HWND hWnd, UINT message, WPARAM wParam,
break;
}
case WM_PAINT:
case WM_PAINT: {
if (flags_ & kFlagOwnPaint) {
return 0; // ignore
}
invalidated_ = false;
auto e = UIEvent(this);
OnPaint(e);
break;
}
case WM_ERASEBKGND:
if (flags_ & kFlagOwnPaint) {
return 0; // ignore

View File

@@ -54,7 +54,8 @@ class Win32Control : public Control {
virtual LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam);
HWND hwnd_;
HWND hwnd_ = nullptr;
bool invalidated_ = true;
private:
bool HandleMouse(UINT message, WPARAM wParam, LPARAM lParam);

View File

@@ -28,6 +28,8 @@ class PostedFn {
};
Win32Loop::Win32Loop() : thread_id_(0) {
timer_queue_ = CreateTimerQueue();
xe::threading::Fence init_fence;
thread_ = std::thread([&init_fence, this]() {
xe::threading::set_name("Win32 Loop");
@@ -49,6 +51,14 @@ Win32Loop::Win32Loop() : thread_id_(0) {
Win32Loop::~Win32Loop() {
Quit();
thread_.join();
DeleteTimerQueueEx(timer_queue_, INVALID_HANDLE_VALUE);
std::lock_guard<xe::mutex> lock(pending_timers_mutex_);
while (!pending_timers_.empty()) {
auto timer = pending_timers_.back();
pending_timers_.pop_back();
delete timer;
}
}
void Win32Loop::ThreadMain() {
@@ -82,6 +92,38 @@ void Win32Loop::Post(std::function<void()> fn) {
}
}
void Win32Loop::TimerQueueCallback(void* context, uint8_t) {
auto timer = reinterpret_cast<PendingTimer*>(context);
auto loop = timer->loop;
auto fn = std::move(timer->fn);
DeleteTimerQueueTimer(timer->timer_queue, timer->timer_handle, NULL);
{
std::lock_guard<xe::mutex> lock(loop->pending_timers_mutex_);
loop->pending_timers_.remove(timer);
}
delete timer;
loop->Post(std::move(fn));
}
void Win32Loop::PostDelayed(std::function<void()> fn, uint64_t delay_millis) {
if (!delay_millis) {
Post(std::move(fn));
return;
}
auto timer = new PendingTimer();
timer->loop = this;
timer->timer_queue = timer_queue_;
timer->fn = std::move(fn);
{
std::lock_guard<xe::mutex> lock(pending_timers_mutex_);
pending_timers_.push_back(timer);
}
CreateTimerQueueTimer(&timer->timer_handle, timer_queue_,
WAITORTIMERCALLBACK(TimerQueueCallback), timer,
DWORD(delay_millis), 0,
WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE);
}
void Win32Loop::Quit() {
assert_true(thread_id_ != 0);
PostThreadMessage(thread_id_, kWmWin32LoopQuit,

View File

@@ -10,11 +10,11 @@
#ifndef XENIA_UI_WIN32_WIN32_LOOP_H_
#define XENIA_UI_WIN32_WIN32_LOOP_H_
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <list>
#include <thread>
#include "xenia/base/mutex.h"
#include "xenia/base/platform.h"
#include "xenia/base/threading.h"
#include "xenia/ui/loop.h"
@@ -29,16 +29,30 @@ class Win32Loop : public Loop {
~Win32Loop() override;
void Post(std::function<void()> fn) override;
void PostDelayed(std::function<void()> fn, uint64_t delay_millis) override;
void Quit() override;
void AwaitQuit() override;
private:
struct PendingTimer {
Win32Loop* loop;
HANDLE timer_queue;
HANDLE timer_handle;
std::function<void()> fn;
};
void ThreadMain();
static void TimerQueueCallback(void* context, uint8_t);
std::thread thread_;
DWORD thread_id_;
xe::threading::Fence quit_fence_;
HANDLE timer_queue_;
xe::mutex pending_timers_mutex_;
std::list<PendingTimer*> pending_timers_;
};
} // namespace win32