Browse Source

Use win32 thread API for file browser, not pthreads; Cleanup

Signed-off-by: falkTX <falktx@falktx.com>
pull/349/head
falkTX 3 years ago
parent
commit
d7abd3e1d5
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
3 changed files with 97 additions and 171 deletions
  1. +1
    -0
      Makefile.base.mk
  2. +90
    -37
      dgl/src/WindowPrivateData.cpp
  3. +6
    -134
      dgl/src/WindowPrivateData.hpp

+ 1
- 0
Makefile.base.mk View File

@@ -280,6 +280,7 @@ endif

ifeq ($(WINDOWS),true)
DGL_SYSTEM_LIBS += -lgdi32 -lcomdlg32
# -lole32
endif

ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)


+ 90
- 37
dgl/src/WindowPrivateData.cpp View File

@@ -23,6 +23,7 @@

#ifdef DISTRHO_OS_WINDOWS
# include <direct.h>
# include <process.h>
# include <winsock2.h>
# include <windows.h>
# include <vector>
@@ -30,7 +31,7 @@
# include <unistd.h>
#endif

#define DGL_DEBUG_EVENTS
// #define DGL_DEBUG_EVENTS

#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS)
# ifdef DISTRHO_PROPER_CPP11_SUPPORT
@@ -82,15 +83,23 @@ static double getDesktopScaleFactor(const PuglView* const view)

// -----------------------------------------------------------------------

#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
#ifdef DISTRHO_OS_WINDOWS
struct FileBrowserThread::PrivateData {
OPENFILENAMEW ofn;
volatile bool threadCancelled;
uintptr_t threadHandle;
std::vector<WCHAR> fileNameW;
std::vector<WCHAR> startDirW;
std::vector<WCHAR> titleW;

PrivateData()
: fileNameW(32768)
const bool isEmbed;
const char*& win32SelectedFile;

PrivateData(const bool embed, const char*& file)
: threadCancelled(false),
threadHandle(0),
fileNameW(32768),
isEmbed(embed),
win32SelectedFile(file)
{
std::memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
@@ -105,7 +114,7 @@ struct FileBrowserThread::PrivateData {
{
ofn.hwndOwner = (HWND)winId;

ofn.Flags = OFN_PATHMUSTEXIST;
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (options.buttons.showHidden == Window::FileBrowserOptions::kButtonVisibleChecked)
ofn.Flags |= OFN_FORCESHOWHIDDEN;

@@ -122,56 +131,102 @@ struct FileBrowserThread::PrivateData {
ofn.lpstrTitle = titleW.data();
}

const char* run()
void run()
{
const char* nextFile = nullptr;

if (GetOpenFileNameW(&ofn))
{
if (threadCancelled)
{
threadHandle = 0;
return;
}

// back to UTF-8
std::vector<char> fileNameA(4 * 32768);
if (WideCharToMultiByte(CP_UTF8, 0, fileNameW.data(), -1,
fileNameA.data(), (int)fileNameA.size(),
nullptr, nullptr))
{
return strdup(fileNameA.data());
nextFile = strdup(fileNameA.data());
}
}

return nullptr;
if (threadCancelled)
{
threadHandle = 0;
return;
}

if (nextFile == nullptr)
nextFile = kWin32SelectedFileCancelled;

win32SelectedFile = nextFile;
threadHandle = 0;
}
};

FileBrowserThread::FileBrowserThread(const char*& file)
: pData(new PrivateData()),
win32SelectedFile(file) {}
FileBrowserThread::FileBrowserThread(const bool isEmbed, const char*& file)
: pData(new PrivateData(isEmbed, file)) {}

FileBrowserThread::~FileBrowserThread()
{
stopThread(5000);
stop();
delete pData;
}

unsigned __stdcall FileBrowserThread__run(void* const arg)
{
// CoInitializeEx(nullptr, COINIT_MULTITHREADED);
static_cast<FileBrowserThread*>(arg)->pData->run();
// CoUninitialize();
_endthreadex(0);
return 0;
}

void FileBrowserThread::start(const char* const startDir,
const char* const title,
const uintptr_t winId,
const Window::FileBrowserOptions options)
{
pData->setup(startDir, title, winId, options);
startThread();

uint threadId;
pData->threadCancelled = false;
pData->threadHandle = _beginthreadex(nullptr, 0, FileBrowserThread__run, this, 0, &threadId);
}

void FileBrowserThread::run()
void FileBrowserThread::stop()
{
const char* nextFile = pData->run();
pData->threadCancelled = true;

if (shouldThreadExit())
if (pData->threadHandle == 0)
return;

if (nextFile == nullptr)
nextFile = kWin32SelectedFileCancelled;
// if previous dialog running, carefully close its window
const HWND owner = pData->isEmbed ? GetParent(pData->ofn.hwndOwner) : pData->ofn.hwndOwner;

d_stdout("WThread finished, final file '%s'", nextFile);
win32SelectedFile = nextFile;
if (owner != nullptr && owner != INVALID_HANDLE_VALUE)
{
const HWND window = GetWindow(owner, GW_HWNDFIRST);

if (window != nullptr && window != INVALID_HANDLE_VALUE)
{
SendMessage(window, WM_SYSCOMMAND, SC_CLOSE, 0);
SendMessage(window, WM_CLOSE, 0, 0);
WaitForSingleObject((HANDLE)pData->threadHandle, 5000);
}
}

// not good if thread still running, but let's close the handle anyway
if (pData->threadHandle != 0)
{
CloseHandle((HANDLE)pData->threadHandle);
pData->threadHandle = 0;
}
}

#endif // DISTRHO_OS_WINDOWS && !_MSC_VER

// -----------------------------------------------------------------------
@@ -194,9 +249,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s)
keepAspectRatio(false),
ignoreIdleCallbacks(false),
filenameToRenderInto(nullptr),
#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
win32FileThread(win32SelectedFile),
win32FileThread(false, win32SelectedFile),
#endif
modal()
{
@@ -221,9 +276,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c
keepAspectRatio(false),
ignoreIdleCallbacks(false),
filenameToRenderInto(nullptr),
#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
win32FileThread(win32SelectedFile),
win32FileThread(false, win32SelectedFile),
#endif
modal(ppData)
{
@@ -252,9 +307,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
keepAspectRatio(false),
ignoreIdleCallbacks(false),
filenameToRenderInto(nullptr),
#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
win32FileThread(win32SelectedFile),
win32FileThread(isEmbed, win32SelectedFile),
#endif
modal()
{
@@ -285,9 +340,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
keepAspectRatio(false),
ignoreIdleCallbacks(false),
filenameToRenderInto(nullptr),
#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
#ifdef DISTRHO_OS_WINDOWS
win32SelectedFile(nullptr),
win32FileThread(win32SelectedFile),
win32FileThread(isEmbed, win32SelectedFile),
#endif
modal()
{
@@ -317,9 +372,8 @@ Window::PrivateData::~PrivateData()
isVisible = false;
}

#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
if (win32FileThread.isThreadRunning())
win32FileThread.stopThread(2000);
#ifdef DISTRHO_OS_WINDOWS
win32FileThread.stop();

if (win32SelectedFile != nullptr && win32SelectedFile != kWin32SelectedFileCancelled)
std::free(const_cast<char*>(win32SelectedFile));
@@ -512,7 +566,7 @@ void Window::PrivateData::setResizable(const bool resizable)
void Window::PrivateData::idleCallback()
{
#ifndef DGL_FILE_BROWSER_DISABLED
# if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
# ifdef DISTRHO_OS_WINDOWS
if (const char* path = win32SelectedFile)
{
win32SelectedFile = nullptr;
@@ -637,10 +691,9 @@ bool Window::PrivateData::openFileBrowser(const Window::FileBrowserOptions& opti
return puglMacOSFilePanelOpen(view, startDir, title, flags, openPanelCallback);
# endif

# if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
// TODO signal to close
if (win32FileThread.isThreadRunning())
win32FileThread.stopThread(1000);
# ifdef DISTRHO_OS_WINDOWS
// only one possible at a time
DISTRHO_SAFE_ASSERT_RETURN(win32FileThread.pData->threadHandle == 0, false);

if (win32SelectedFile != nullptr && win32SelectedFile != kWin32SelectedFileCancelled)
std::free(const_cast<char*>(win32SelectedFile));


+ 6
- 134
dgl/src/WindowPrivateData.hpp View File

@@ -25,30 +25,22 @@

#include <list>

#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
# include "../distrho/extra/Thread.hpp"
#endif

START_NAMESPACE_DGL

class TopLevelWidget;

// -----------------------------------------------------------------------

#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
class FileBrowserThread : public Thread
#ifdef DISTRHO_OS_WINDOWS
struct FileBrowserThread
{
struct PrivateData;
PrivateData* const pData;
const char*& win32SelectedFile;

public:
FileBrowserThread(const char*& win32SelectedFile);
~FileBrowserThread() override;
FileBrowserThread(bool isEmbed, const char*& win32SelectedFile);
~FileBrowserThread();
void start(const char* startDir, const char* title, uintptr_t winId, Window::FileBrowserOptions options);

protected:
void run() override;
void stop();
};
#endif

@@ -103,7 +95,7 @@ struct Window::PrivateData : IdleCallback {
/** Render to a picture file when non-null, automatically free+unset after saving. */
char* filenameToRenderInto;

#if defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER)
#ifdef DISTRHO_OS_WINDOWS
/** Selected file for openFileBrowser on windows, stored for fake async operation. */
const char* win32SelectedFile;
/** Thread where the openFileBrowser runs. */
@@ -218,124 +210,4 @@ struct Window::PrivateData : IdleCallback {

END_NAMESPACE_DGL

#if 0
// #if defined(DISTRHO_OS_HAIKU)
// BApplication* bApplication;
// BView* bView;
// BWindow* bWindow;
#if defined(DISTRHO_OS_MAC)
// NSView<PuglGenericView>* mView;
// id mWindow;
// id mParentWindow;
# ifndef DGL_FILE_BROWSER_DISABLED
NSOpenPanel* fOpenFilePanel;
id fFilePanelDelegate;
# endif
#elif defined(DISTRHO_OS_WINDOWS)
// HWND hwnd;
// HWND hwndParent;
# ifndef DGL_FILE_BROWSER_DISABLED
String fSelectedFile;
# endif
#endif
#endif

#if 0
// -----------------------------------------------------------------------
// Window Private

struct Window::PrivateData {
// -------------------------------------------------------------------

bool handlePluginSpecial(const bool press, const Key key)
{
DBGp("PUGL: handlePluginSpecial : %i %i\n", press, key);

if (fModal.childFocus != nullptr)
{
fModal.childFocus->focus();
return true;
}

int mods = 0x0;

switch (key)
{
case kKeyShift:
mods |= kModifierShift;
break;
case kKeyControl:
mods |= kModifierControl;
break;
case kKeyAlt:
mods |= kModifierAlt;
break;
default:
break;
}

if (mods != 0x0)
{
if (press)
fView->mods |= mods;
else
fView->mods &= ~(mods);
}

Widget::SpecialEvent ev;
ev.press = press;
ev.key = key;
ev.mod = static_cast<Modifier>(fView->mods);
ev.time = 0;

FOR_EACH_WIDGET_INV(rit)
{
Widget* const widget(*rit);

if (widget->isVisible() && widget->onSpecial(ev))
return true;
}

return false;
}

#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED)
static void openPanelDidEnd(NSOpenPanel* panel, int returnCode, void *userData)
{
PrivateData* pData = (PrivateData*)userData;

if (returnCode == NSOKButton)
{
NSArray* urls = [panel URLs];
NSURL* fileUrl = nullptr;

for (NSUInteger i = 0, n = [urls count]; i < n && !fileUrl; ++i)
{
NSURL* url = (NSURL*)[urls objectAtIndex:i];
if ([url isFileURL])
fileUrl = url;
}

if (fileUrl)
{
PuglView* view = pData->fView;
if (view->fileSelectedFunc)
{
const char* fileName = [fileUrl.path UTF8String];
view->fileSelectedFunc(view, fileName);
}
}
}

[pData->fOpenFilePanel release];
pData->fOpenFilePanel = nullptr;
}
#endif

// -------------------------------------------------------------------

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
};
#endif

#endif // DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED

Loading…
Cancel
Save