Browse Source

Initial code for file-browser support (X11 only)

gh-pages
falkTX 10 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 App;
class Widget; class Widget;
class StandaloneWindow;


class Window class Window
{ {
public: 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);
explicit Window(App& app, Window& parent); explicit Window(App& app, Window& parent);
explicit Window(App& app, intptr_t parentId); explicit Window(App& app, intptr_t parentId);
@@ -42,6 +80,8 @@ public:
void focus(); void focus();
void repaint() noexcept; void repaint() noexcept;


bool openFileBrowser(const FileBrowserOptions& options);

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


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


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


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


virtual void fileBrowserSelected(const char* filename);

private: private:
struct PrivateData; struct PrivateData;
PrivateData* const pData; PrivateData* const pData;


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

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


#include "pugl/pugl.h" #include "pugl/pugl.h"


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


puglCreateWindow(fView, nullptr); 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) void setTitle(const char* const title)
{ {
DBGp("Window setTitle \"%s\"\n", title); DBGp("Window setTitle \"%s\"\n", title);


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

fTitle = strdup(title);

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


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


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

#undef handlePtr #undef handlePtr


DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
@@ -977,6 +1000,73 @@ void Window::repaint() noexcept
puglPostRedisplay(pData->fView); 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 bool Window::isVisible() const noexcept
{ {
return pData->fVisible; return pData->fVisible;
@@ -1022,6 +1112,11 @@ void Window::setSize(Size<uint> size)
pData->setSize(size.getWidth(), size.getHeight()); pData->setSize(size.getWidth(), size.getHeight());
} }


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

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


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

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


END_NAMESPACE_DGL 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); 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. Create a Pugl context.


@@ -352,6 +360,12 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc);
PUGL_API void PUGL_API void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); 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. Return the native window handle.
*/ */


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

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


PuglInternals* impl; PuglInternals* impl;
PuglNativeWindow parent; PuglNativeWindow parent;
@@ -200,3 +201,9 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc)
{ {
view->specialFunc = 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" #include "pugl_internal.h"


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

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


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


@@ -322,6 +326,26 @@ puglProcessEvents(PuglView* view)
XEvent event; XEvent event;
while (XPending(view->impl->display) > 0) { while (XPending(view->impl->display) > 0) {
XNextEvent(view->impl->display, &event); 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) { switch (event.type) {
case MapNotify: case MapNotify:
puglReshape(view, view->width, view->height); puglReshape(view, view->width, view->height);


Loading…
Cancel
Save