Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/zwidget/core/widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ enum class WidgetType
{
Child,
Window,
Popup
Popup,
Utility
};

enum class WidgetEvent
Expand Down Expand Up @@ -192,6 +193,9 @@ class Widget : DisplayWindowHost
virtual void OnSetFocus() { }
virtual void OnLostFocus() { }
virtual void OnEnableChanged() { }
void OnWindowNotified() override {};

void NotifyWindow(); // used to wake up a window from another thread

virtual void Notify(Widget* source, const WidgetEvent type) { };

Expand Down
7 changes: 5 additions & 2 deletions include/zwidget/window/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,14 @@ class DisplayWindowHost
virtual void OnWindowActivated() = 0;
virtual void OnWindowDeactivated() = 0;
virtual void OnWindowDpiScaleChanged() = 0;
virtual void OnWindowNotified() = 0;
virtual bool OnFileDrop(std::string path) = 0;
};

class DisplayWindow
{
public:
static std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable);
static std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility);

static void ProcessEvents();
static void RunLoop();
Expand Down Expand Up @@ -209,6 +210,8 @@ class DisplayWindow

virtual std::vector<std::string> GetVulkanInstanceExtensions() = 0;
virtual VkSurfaceKHR CreateVulkanSurface(VkInstance instance) = 0;

virtual void NotifyWindow() = 0;
};

class DisplayBackend
Expand All @@ -227,7 +230,7 @@ class DisplayBackend
virtual bool IsWin32() { return false; }
virtual bool IsSDL2() { return false; }

virtual std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable) = 0;
virtual std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility) = 0;
virtual void ProcessEvents() = 0;
virtual void RunLoop() = 0;
virtual void ExitLoop() = 0;
Expand Down
9 changes: 8 additions & 1 deletion src/core/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Widget::Widget(Widget* parent, WidgetType type, RenderAPI renderAPI, bool window
if (type != WidgetType::Child)
{
Widget* owner = parent ? parent->Window() : nullptr;
DispWindow = DisplayWindow::Create(this, type == WidgetType::Popup, owner ? owner->DispWindow.get() : nullptr, renderAPI, windowResizable);
DispWindow = DisplayWindow::Create(this, type == WidgetType::Popup, owner ? owner->DispWindow.get() : nullptr, renderAPI, windowResizable, type == WidgetType::Utility);
if (renderAPI == RenderAPI::Unspecified || renderAPI == RenderAPI::Bitmap)
{
DispCanvas = Canvas::create();
Expand Down Expand Up @@ -1051,3 +1051,10 @@ Colorf Widget::GetStyleColor(const std::string& propertyName) const
WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass);
return style ? style->GetColor(StyleState, propertyName) : Colorf::transparent();
}

void Widget::NotifyWindow()
{
Widget* w = Window();
if (w && w->DispWindow)
w->DispWindow->NotifyWindow();
}
4 changes: 2 additions & 2 deletions src/window/sdl2/sdl2_display_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ SDL2DisplayBackend::SDL2DisplayBackend()
}
}

std::unique_ptr<DisplayWindow> SDL2DisplayBackend::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable)
std::unique_ptr<DisplayWindow> SDL2DisplayBackend::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility)
{
return std::make_unique<SDL2DisplayWindow>(windowHost, popupWindow, static_cast<SDL2DisplayWindow*>(owner), renderAPI, UIScale, resizable);
return std::make_unique<SDL2DisplayWindow>(windowHost, popupWindow, static_cast<SDL2DisplayWindow*>(owner), renderAPI, UIScale, resizable, utility);
}

void SDL2DisplayBackend::ProcessEvents()
Expand Down
2 changes: 1 addition & 1 deletion src/window/sdl2/sdl2_display_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class SDL2DisplayBackend : public DisplayBackend
public:
SDL2DisplayBackend();

std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable) override;
std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility) override;
void ProcessEvents() override;
void RunLoop() override;
void ExitLoop() override;
Expand Down
75 changes: 62 additions & 13 deletions src/window/sdl2/sdl2_display_window.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#include "sdl2_display_window.h"
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_video.h>
#include <stdexcept>
#include <SDL2/SDL_vulkan.h>
#include <SDL2/SDL_hints.h>

#define EVENT_NOTIFY_WINDOW SDL_USEREVENT + 100

Uint32 SDL2DisplayWindow::PaintEventNumber = 0xffffffff;
bool SDL2DisplayWindow::ExitRunLoop;
std::unordered_map<int, SDL2DisplayWindow*> SDL2DisplayWindow::WindowList;

SDL2DisplayWindow::SDL2DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, SDL2DisplayWindow* owner, RenderAPI renderAPI, double uiscale, bool resizable) : WindowHost(windowHost), UIScale(uiscale)
SDL2DisplayWindow::SDL2DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, SDL2DisplayWindow* owner, RenderAPI renderAPI, double uiscale, bool resizable, bool utility) : WindowHost(windowHost), UIScale(uiscale)
{
unsigned int flags = resizable ? (SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE) : SDL_WINDOW_HIDDEN /*| SDL_WINDOW_ALLOW_HIGHDPI*/;
unsigned int flags = SDL_WINDOW_HIDDEN /*| SDL_WINDOW_ALLOW_HIGHDPI*/;
if (renderAPI == RenderAPI::Vulkan)
flags |= SDL_WINDOW_VULKAN;
else if (renderAPI == RenderAPI::OpenGL)
Expand All @@ -18,20 +22,34 @@ SDL2DisplayWindow::SDL2DisplayWindow(DisplayWindowHost* windowHost, bool popupWi
else if (renderAPI == RenderAPI::Metal)
flags |= SDL_WINDOW_METAL;
#endif

if (resizable)
flags |= SDL_WINDOW_RESIZABLE;
if (popupWindow)
flags |= SDL_WINDOW_BORDERLESS;

if (renderAPI == RenderAPI::Vulkan || renderAPI == RenderAPI::OpenGL || renderAPI == RenderAPI::Metal)
if (utility)
{
Handle.window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 200, flags);
if (!Handle.window)
throw std::runtime_error(std::string("Unable to create SDL window:") + SDL_GetError());
Owner = owner;
flags |= (SDL_WINDOW_UTILITY | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR);
}
else

Handle.window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 200, flags);
if (!Handle.window)
throw std::runtime_error(std::string("Unable to create SDL window:") + SDL_GetError());

switch (renderAPI)
{
int result = SDL_CreateWindowAndRenderer(320, 200, flags, &Handle.window, &RendererHandle);
if (result != 0)
throw std::runtime_error(std::string("Unable to create SDL window:") + SDL_GetError());
case RenderAPI::Vulkan:
case RenderAPI::OpenGL:
case RenderAPI::Metal:
break;
default: {
RendererHandle = SDL_CreateRenderer(Handle.window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (!RendererHandle)
RendererHandle = SDL_CreateRenderer(Handle.window, -1, SDL_RENDERER_SOFTWARE);
if (!RendererHandle)
throw std::runtime_error(std::string("Unable to create renderer: ") + SDL_GetError());
}
}

WindowList[SDL_GetWindowID(Handle.window)] = this;
Expand Down Expand Up @@ -78,6 +96,14 @@ VkSurfaceKHR SDL2DisplayWindow::CreateVulkanSurface(VkInstance instance)
return surfaceHandle;
}

void SDL2DisplayWindow::NotifyWindow()
{
SDL_Event e;
SDL_zero(e);
e.type = EVENT_NOTIFY_WINDOW;
SDL_PushEvent(&e);
}

void SDL2DisplayWindow::SetWindowTitle(const std::string& text)
{
SDL_SetWindowTitle(Handle.window, text.c_str());
Expand Down Expand Up @@ -112,7 +138,21 @@ void SDL2DisplayWindow::SetClientFrame(const Rect& box)

void SDL2DisplayWindow::Show()
{
if (Owner)
{
SDL_SetWindowModalFor(Handle.window, Owner->Handle.window);
SDL_SetWindowAlwaysOnTop(Handle.window, SDL_TRUE);
}

// this is a hack, but it seems to prevent unpainted windows on my pc
SDL_ShowWindow(Handle.window);
SDL_RaiseWindow(Handle.window);
SDL_Delay(10);
WindowHost->OnWindowGeometryChanged();
WindowHost->OnWindowPaint();
SDL_Delay(10);
Update();
ProcessEvents();
}

void SDL2DisplayWindow::Restore()
Expand Down Expand Up @@ -210,8 +250,14 @@ bool SDL2DisplayWindow::GetKeyState(InputKey key)
const Uint8* state = SDL_GetKeyboardState(&numkeys);
if (!state) return false;

SDL_Scancode index = InputKeyToScancode(key);
return (index < numkeys) ? state[index] != 0 : false;
auto test = [numkeys, state](InputKey key) {
SDL_Scancode index = InputKeyToScancode(key);
return (index < numkeys) ? state[index] != 0 : false;
};

if (key == InputKey::Ctrl) return test(key) || test(InputKey::LControl) || test(InputKey::RControl);
if (key == InputKey::Shift) return test(key) || test(InputKey::LShift) || test(InputKey::RShift);
return test(key);
}

Rect SDL2DisplayWindow::GetWindowFrame() const
Expand Down Expand Up @@ -495,6 +541,9 @@ void SDL2DisplayWindow::OnWindowEvent(const SDL_WindowEvent& event)
{
switch (event.event)
{
case EVENT_NOTIFY_WINDOW:
WindowHost->OnWindowNotified();
break;
case SDL_WINDOWEVENT_CLOSE:
WindowHost->OnWindowClose();
break;
Expand Down
5 changes: 4 additions & 1 deletion src/window/sdl2/sdl2_display_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class SDL2DisplayWindow : public DisplayWindow
{
public:
SDL2DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, SDL2DisplayWindow* owner, RenderAPI renderAPI, double uiscale, bool resizable);
SDL2DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, SDL2DisplayWindow* owner, RenderAPI renderAPI, double uiscale, bool resizable, bool utility);
~SDL2DisplayWindow();

void SetWindowTitle(const std::string& text) override;
Expand Down Expand Up @@ -55,6 +55,8 @@ class SDL2DisplayWindow : public DisplayWindow

std::vector<std::string> GetVulkanInstanceExtensions() override;
VkSurfaceKHR CreateVulkanSurface(VkInstance instance) override;

virtual void NotifyWindow() override;

static void DispatchEvent(const SDL_Event& event);
static SDL2DisplayWindow* FindEventWindow(const SDL_Event& event);
Expand Down Expand Up @@ -95,6 +97,7 @@ class SDL2DisplayWindow : public DisplayWindow
static Uint32 ExecTimer(Uint32 interval, void* id);

DisplayWindowHost* WindowHost = nullptr;
SDL2DisplayWindow* Owner = nullptr;
SDL2NativeHandle Handle;
SDL_Renderer* RendererHandle = nullptr;
SDL_Texture* BackBufferTexture = nullptr;
Expand Down
4 changes: 2 additions & 2 deletions src/window/win32/win32_display_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
#include "win32_save_file_dialog.h"
#include "win32_open_folder_dialog.h"

std::unique_ptr<DisplayWindow> Win32DisplayBackend::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable)
std::unique_ptr<DisplayWindow> Win32DisplayBackend::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility)
{
return std::make_unique<Win32DisplayWindow>(windowHost, popupWindow, static_cast<Win32DisplayWindow*>(owner), renderAPI, resizable);
return std::make_unique<Win32DisplayWindow>(windowHost, popupWindow, static_cast<Win32DisplayWindow*>(owner), renderAPI, resizable, utility);
}

void Win32DisplayBackend::ProcessEvents()
Expand Down
2 changes: 1 addition & 1 deletion src/window/win32/win32_display_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class Win32DisplayBackend : public DisplayBackend
{
public:
std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable) override;
std::unique_ptr<DisplayWindow> Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility) override;
void ProcessEvents() override;
void RunLoop() override;
void ExitLoop() override;
Expand Down
13 changes: 12 additions & 1 deletion src/window/win32/win32_display_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#pragma comment(lib, "dwmapi.lib")

#define MESSAGE_NOTIFY_WINDOW (WM_APP + 100)

#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
Expand Down Expand Up @@ -78,7 +80,7 @@ static double DelayLoadGetDpiScale(HWND hwnd)
}
}

Win32DisplayWindow::Win32DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, Win32DisplayWindow* owner, RenderAPI renderAPI, bool resizable) : WindowHost(windowHost), PopupWindow(popupWindow)
Win32DisplayWindow::Win32DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, Win32DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility) : WindowHost(windowHost), PopupWindow(popupWindow)
{
Windows.push_front(this);
WindowsIterator = Windows.begin();
Expand Down Expand Up @@ -585,6 +587,10 @@ LRESULT Win32DisplayWindow::OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lpar
}
return 0;
}
else if (msg == MESSAGE_NOTIFY_WINDOW)
{
WindowHost->OnWindowNotified();
}
else if (msg == WM_ACTIVATE)
{
WindowHost->OnWindowActivated();
Expand Down Expand Up @@ -949,6 +955,11 @@ VkSurfaceKHR Win32DisplayWindow::CreateVulkanSurface(VkInstance instance)
return surface;
}

void Win32DisplayWindow::NotifyWindow()
{
PostMessageA(WindowHandle.hwnd, MESSAGE_NOTIFY_WINDOW, 0, 0);
}

std::vector<std::string> Win32DisplayWindow::GetVulkanInstanceExtensions()
{
return { "VK_KHR_surface", "VK_KHR_win32_surface" };
Expand Down
4 changes: 3 additions & 1 deletion src/window/win32/win32_display_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class Win32DisplayWindow : public DisplayWindow
{
public:
Win32DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, Win32DisplayWindow* owner, RenderAPI renderAPI, bool resizable);
Win32DisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, Win32DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility);
~Win32DisplayWindow();

void SetWindowTitle(const std::string& text) override;
Expand Down Expand Up @@ -62,6 +62,8 @@ class Win32DisplayWindow : public DisplayWindow
std::vector<std::string> GetVulkanInstanceExtensions() override;
VkSurfaceKHR CreateVulkanSurface(VkInstance instance) override;

virtual void NotifyWindow() override;

static void ProcessEvents();
static void RunLoop();
static void ExitLoop();
Expand Down
4 changes: 2 additions & 2 deletions src/window/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#include "core/widget.h"
#include <stdexcept>

std::unique_ptr<DisplayWindow> DisplayWindow::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable)
std::unique_ptr<DisplayWindow> DisplayWindow::Create(DisplayWindowHost* windowHost, bool popupWindow, DisplayWindow* owner, RenderAPI renderAPI, bool resizable, bool utility)
{
return DisplayBackend::Get()->Create(windowHost, popupWindow, owner, renderAPI, resizable);
return DisplayBackend::Get()->Create(windowHost, popupWindow, owner, renderAPI, resizable, utility);
}

void DisplayWindow::ProcessEvents()
Expand Down