Browse Source

Initial code for file-browser support (X11 only)

gh-pages
falkTX 9 years ago
parent
commit
f84486802f
5 changed files with 188 additions and 1 deletions
  1. +43
    -0
      dgl/Window.hpp
  2. +99
    -0
      dgl/src/Window.cpp
  3. +14
    -0
      dgl/src/pugl/pugl.h
  4. +7
    -0
      dgl/src/pugl/pugl_internal.h
  5. +25
    -1
      dgl/src/pugl/pugl_x11.c

+ 43
- 0
dgl/Window.hpp View File

@@ -25,10 +25,48 @@ START_NAMESPACE_DGL

class App;
class Widget;
class StandaloneWindow;

class Window
{
public:
/**
File browser options.
*/
struct FileBrowserOptions {
const char* startDir;
const char* title;
uint width;
uint height;

/**
File browser buttons.

0 means hidden.
1 means visible and unchecked.
2 means visible and checked.
*/
struct Buttons {
uint listAllFiles;
uint showHidden;
uint showPlaces;

/** Constuctor for default values */
Buttons()
: listAllFiles(2),
showHidden(1),
showPlaces(1) {}
} buttons;

/** Constuctor for default values */
FileBrowserOptions()
: startDir(nullptr),
title(nullptr),
width(0),
height(0),
buttons() {}
};

explicit Window(App& app);
explicit Window(App& app, Window& parent);
explicit Window(App& app, intptr_t parentId);
@@ -42,6 +80,8 @@ public:
void focus();
void repaint() noexcept;

bool openFileBrowser(const FileBrowserOptions& options);

bool isVisible() const noexcept;
void setVisible(bool yesNo);

@@ -54,6 +94,7 @@ public:
void setSize(uint width, uint height);
void setSize(Size<uint> size);

const char* getTitle() const noexcept;
void setTitle(const char* title);

void setTransientWinId(uintptr_t winId);
@@ -70,6 +111,8 @@ protected:
virtual void onReshape(uint width, uint height);
virtual void onClose();

virtual void fileBrowserSelected(const char* filename);

private:
struct PrivateData;
PrivateData* const pData;


+ 99
- 0
dgl/src/Window.cpp View File

@@ -20,6 +20,7 @@
#include "AppPrivateData.hpp"
#include "../Widget.hpp"
#include "../Window.hpp"
#include "../../distrho/extra/d_string.hpp"

#include "pugl/pugl.h"

@@ -69,6 +70,7 @@ struct Window::PrivateData {
fUsingEmbed(false),
fWidth(1),
fHeight(1),
fTitle(nullptr),
fWidgets(),
fModal(),
#if defined(DISTRHO_OS_WINDOWS)
@@ -97,6 +99,7 @@ struct Window::PrivateData {
fUsingEmbed(false),
fWidth(1),
fHeight(1),
fTitle(nullptr),
fWidgets(),
fModal(parent.pData),
#if defined(DISTRHO_OS_WINDOWS)
@@ -135,6 +138,7 @@ struct Window::PrivateData {
fUsingEmbed(parentId != 0),
fWidth(1),
fHeight(1),
fTitle(nullptr),
fWidgets(),
fModal(),
#if defined(DISTRHO_OS_WINDOWS)
@@ -190,6 +194,7 @@ struct Window::PrivateData {
puglSetSpecialFunc(fView, onSpecialCallback);
puglSetReshapeFunc(fView, onReshapeCallback);
puglSetCloseFunc(fView, onCloseCallback);
puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback);

puglCreateWindow(fView, nullptr);

@@ -535,10 +540,22 @@ struct Window::PrivateData {

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

const char* getTitle() const noexcept
{
static const char* const kFallback = "";

return fTitle != nullptr ? fTitle : kFallback;
}

void setTitle(const char* const title)
{
DBGp("Window setTitle \"%s\"\n", title);

if (fTitle != nullptr)
std::free(fTitle);

fTitle = strdup(title);

#if defined(DISTRHO_OS_WINDOWS)
SetWindowTextA(hwnd, title);
#elif defined(DISTRHO_OS_MAC)
@@ -840,6 +857,7 @@ struct Window::PrivateData {
bool fUsingEmbed;
uint fWidth;
uint fHeight;
char* fTitle;
std::list<Widget*> fWidgets;

struct Modal {
@@ -922,6 +940,11 @@ struct Window::PrivateData {
handlePtr->onPuglClose();
}

static void fileBrowserSelectedCallback(PuglView* view, const char* filename)
{
handlePtr->fSelf->fileBrowserSelected(filename);
}

#undef handlePtr

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
@@ -977,6 +1000,73 @@ void Window::repaint() noexcept
puglPostRedisplay(pData->fView);
}

// static int fib_filter_filename_filter(const char* const name)
// {
// return 1;
// (void)name;
// }

bool Window::openFileBrowser(const FileBrowserOptions& options)
{
using DISTRHO_NAMESPACE::d_string;

// --------------------------------------------------------------------------
// configure start dir

// TODO: get abspath if needed
// TODO: cross-platform

d_string startDir(options.startDir);

if (startDir.isEmpty())
{
if (char* const dir_name = get_current_dir_name())
{
startDir = dir_name;
std::free(dir_name);
}
}

DISTRHO_SAFE_ASSERT_RETURN(startDir.isNotEmpty(), false);

if (! startDir.endsWith('/'))
startDir += "/";

DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(0, startDir) == 0, false);

// --------------------------------------------------------------------------
// configure title

d_string title(options.title);

if (title.isEmpty())
{
title = pData->getTitle();

if (title.isEmpty())
title = "FileBrowser";
}

DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(1, title) == 0, false);

// --------------------------------------------------------------------------
// configure filters

x_fib_cfg_filter_callback(nullptr); //fib_filter_filename_filter);

// --------------------------------------------------------------------------
// configure buttons

x_fib_cfg_buttons(3, options.buttons.listAllFiles-1);
x_fib_cfg_buttons(1, options.buttons.showHidden-1);
x_fib_cfg_buttons(2, options.buttons.showPlaces-1);

// --------------------------------------------------------------------------
// show

return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0);
}

bool Window::isVisible() const noexcept
{
return pData->fVisible;
@@ -1022,6 +1112,11 @@ void Window::setSize(Size<uint> size)
pData->setSize(size.getWidth(), size.getHeight());
}

const char* Window::getTitle() const noexcept
{
return pData->getTitle();
}

void Window::setTitle(const char* title)
{
pData->setTitle(title);
@@ -1101,6 +1196,10 @@ void Window::onClose()
{
}

void Window::fileBrowserSelected(const char*)
{
}

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

END_NAMESPACE_DGL


+ 14
- 0
dgl/src/pugl/pugl.h View File

@@ -219,6 +219,14 @@ typedef void (*PuglScrollFunc)(PuglView* view, int x, int y, float dx, float dy)
*/
typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key);

/**
A function called when a filename is selected via file-browser.

@param view The view the event occured in.
@param filename The selected file name or NULL if the dialog was canceled.
*/
typedef void (*PuglFileSelectedFunc)(PuglView* view, const char* filename);

/**
Create a Pugl context.

@@ -352,6 +360,12 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc);
PUGL_API void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc);

/**
Set the function to call on file-browser selections.
*/
PUGL_API void
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc);

/**
Return the native window handle.
*/


+ 7
- 0
dgl/src/pugl/pugl_internal.h View File

@@ -51,6 +51,7 @@ struct PuglViewImpl {
PuglReshapeFunc reshapeFunc;
PuglScrollFunc scrollFunc;
PuglSpecialFunc specialFunc;
PuglFileSelectedFunc fileSelectedFunc;

PuglInternals* impl;
PuglNativeWindow parent;
@@ -200,3 +201,9 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc)
{
view->specialFunc = specialFunc;
}

void
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc)
{
view->fileSelectedFunc = fileSelectedFunc;
}

+ 25
- 1
dgl/src/pugl/pugl_x11.c View File

@@ -32,6 +32,10 @@

#include "pugl_internal.h"

#define SOFD_HAVE_X11
#include "../sofd/libsofd.h"
#include "../sofd/libsofd.c"

struct PuglInternalsImpl {
Display* display;
int screen;
@@ -96,7 +100,7 @@ puglCreateWindow(PuglView* view, const char* title)
{
PuglInternals* impl = view->impl;

impl->display = XOpenDisplay(0);
impl->display = XOpenDisplay(NULL);
impl->screen = DefaultScreen(impl->display);
impl->doubleBuffered = True;

@@ -322,6 +326,26 @@ puglProcessEvents(PuglView* view)
XEvent event;
while (XPending(view->impl->display) > 0) {
XNextEvent(view->impl->display, &event);

if (x_fib_handle_events(view->impl->display, &event)) {
const int status = x_fib_status();

if (status > 0) {
char* const filename = x_fib_filename();
x_fib_close(view->impl->display);
if (view->fileSelectedFunc) {
view->fileSelectedFunc(view, filename);
}
free(filename);
} else if (status < 0) {
x_fib_close(view->impl->display);
if (view->fileSelectedFunc) {
view->fileSelectedFunc(view, NULL);
}
}
break;
}

switch (event.type) {
case MapNotify:
puglReshape(view, view->width, view->height);


Loading…
Cancel
Save