Browse Source

Update dgl

tags/1.9.6
falkTX 9 years ago
parent
commit
92ce3c06df
8 changed files with 2846 additions and 18 deletions
  1. +43
    -0
      source/modules/dgl/Window.hpp
  2. +105
    -1
      source/modules/dgl/src/Window.cpp
  3. +14
    -0
      source/modules/dgl/src/pugl/pugl.h
  4. +7
    -0
      source/modules/dgl/src/pugl/pugl_internal.h
  5. +46
    -16
      source/modules/dgl/src/pugl/pugl_osx.m
  6. +25
    -1
      source/modules/dgl/src/pugl/pugl_x11.c
  7. +2431
    -0
      source/modules/dgl/src/sofd/libsofd.c
  8. +175
    -0
      source/modules/dgl/src/sofd/libsofd.h

+ 43
- 0
source/modules/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;


+ 105
- 1
source/modules/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)
@@ -143,7 +147,7 @@ struct Window::PrivateData {
xDisplay(nullptr),
xWindow(0),
#elif defined(DISTRHO_OS_MAC)
fNeedsIdle(false),
fNeedsIdle(parentId == 0),
mView(nullptr),
mWindow(nullptr),
#endif
@@ -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,78 @@ 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)
{
#ifdef SOFD_HAVE_X11
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);
#else
// not implemented
return false;
#endif
}

bool Window::isVisible() const noexcept
{
return pData->fVisible;
@@ -1022,6 +1117,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 +1201,10 @@ void Window::onClose()
{
}

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

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

END_NAMESPACE_DGL


+ 14
- 0
source/modules/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
source/modules/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;
}

+ 46
- 16
source/modules/dgl/src/pugl/pugl_osx.m View File

@@ -35,6 +35,7 @@
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag;
- (void) setPuglview:(PuglView*)view;
- (BOOL) canBecomeKeyWindow;
- (BOOL) windowShouldClose:(id)sender;
@end

@@ -66,6 +67,11 @@
[self setContentSize:NSMakeSize(view->width, view->height)];
}

- (BOOL)canBecomeKeyWindow
{
return YES;
}

- (BOOL)windowShouldClose:(id)sender
{
if (puglview->closeFunc)
@@ -81,6 +87,7 @@
static void
puglDisplay(PuglView* view)
{
view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
}
@@ -91,15 +98,17 @@ puglDisplay(PuglView* view)
@public
PuglView* puglview;
NSTrackingArea* trackingArea;
bool doubleBuffered;
}

- (BOOL) acceptsFirstMouse:(NSEvent*)e;
- (BOOL) acceptsFirstResponder;
- (BOOL) isFlipped;
- (BOOL) isOpaque;
- (BOOL) preservesContentInLiveResize;
- (id) initWithFrame:(NSRect)frame;
- (void) reshape;
- (void) drawRect:(NSRect)rect;
- (void) drawRect:(NSRect)r;
- (void) cursorUpdate:(NSEvent*)e;
- (void) updateTrackingAreas;
- (void) viewWillMoveToWindow:(NSWindow*)newWindow;
@@ -130,6 +139,11 @@ puglDisplay(PuglView* view)
(void)e;
}

- (BOOL) acceptsFirstResponder
{
return YES;
}

- (BOOL) isFlipped
{
return YES;
@@ -147,16 +161,16 @@ puglDisplay(PuglView* view)

- (id) initWithFrame:(NSRect)frame
{
puglview = nil;
trackingArea = nil;
puglview = nil;
trackingArea = nil;
doubleBuffered = true;

NSOpenGLPixelFormatAttribute pixelAttribs[16] = {
NSOpenGLPixelFormatAttribute pixelAttribs[] = {
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 16,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAColorSize,
8,
NSOpenGLPFADepthSize,
8,
0
};

@@ -166,12 +180,20 @@ puglDisplay(PuglView* view)
if (pixelFormat) {
self = [super initWithFrame:frame pixelFormat:pixelFormat];
[pixelFormat release];
printf("Is doubleBuffered? TRUE\n");
} else {
self = [super initWithFrame:frame];
doubleBuffered = false;
printf("Is doubleBuffered? FALSE\n");
}

if (self) {
[[self openGLContext] makeCurrentContext];
if (self) {
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];

GLint swapInterval = 1;
[context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];

[self reshape];
}

@@ -204,13 +226,19 @@ puglDisplay(PuglView* view)
puglview->height = height;
}

- (void) drawRect:(NSRect)rect
- (void) drawRect:(NSRect)r
{
puglDisplay(puglview);
glFlush();
glSwapAPPLE();

[super drawRect:rect];
if (doubleBuffered) {
[[self openGLContext] flushBuffer];
} else {
glFlush();
//glSwapAPPLE();
}

// unused
return; (void)r;
}

- (void) cursorUpdate:(NSEvent*)e
@@ -421,6 +449,7 @@ puglCreateWindow(PuglView* view, const char* title)
}

if (view->parent) {
[impl->glview retain];
NSView* pview = (NSView*)view->parent;
[pview addSubview:impl->glview];
return 0;
@@ -497,9 +526,10 @@ puglDestroy(PuglView* view)
PuglStatus
puglProcessEvents(PuglView* view)
{
[view->impl->glview setNeedsDisplay:YES];
view->redisplay = false;
return PUGL_SUCCESS;

// unused
(void)view;
}

void


+ 25
- 1
source/modules/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);


+ 2431
- 0
source/modules/dgl/src/sofd/libsofd.c
File diff suppressed because it is too large
View File


+ 175
- 0
source/modules/dgl/src/sofd/libsofd.h View File

@@ -0,0 +1,175 @@
/* libSOFD - Simple Open File Dialog [for X11 without toolkit]
*
* Copyright (C) 2014 Robin Gareus <robin@gareus.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifdef SOFD_HAVE_X11
#include <X11/Xlib.h>

///////////////////////////////////////////////////////////////////////////////
/* public API */

typedef struct FibInternalsImpl FibInternals;

/** open a file select dialog
* @param dpy X Display connection
* @param parent (optional) if not NULL, become transient for given window
* @param x if >0 set explict initial width of the window
* @param y if >0 set explict initial height of the window
* @return 0 on success
*/
int x_fib_show (Display *dpy, Window parent, int x, int y);

/** force close the dialog.
* This is normally not needed, the dialog closes itself
* when a file is selected or the user cancels selection.
* @param dpy X Display connection
*/
void x_fib_close (Display *dpy);

/** non-blocking X11 event handler.
* It is safe to run this function even if the dialog is
* closed or was not initialized.
*
* @param dpy X Display connection
* @param event the XEvent to process
* @return status
* 0: the event was not for this window, or file-dialog still
* active, or the dialog window is not displayed.
* >0: file was selected, dialog closed
* <0: file selection was cancelled.
*/
int x_fib_handle_events (Display *dpy, XEvent *event);

/** last status of the dialog
* @return >0: file was selected, <0: canceled or inactive. 0: active
*/
int x_fib_status ();

/** query the selected filename
* @return NULL if none set, or allocated string to be free()ed by the called
*/
char *x_fib_filename ();

/** customize/configure the dialog before calling \ref x_fib_show
* changes only have any effect if the dialog is not visible.
* @param k key to change
* 0: set current dir to display (must end with slash)
* 1: set title of dialog window
* 2: specify a custom X11 font to use
* 3: specify a custom 'places' file to include
* (following gtk-bookmark convention)
* @param v value
* @return 0 on success.
*/
int x_fib_configure (int k, const char *v);

/** customize/configure the dialog before calling \ref x_fib_show
* changes only have any effect if the dialog is not visible.
*
* @param k button to change:
* 1: show hidden files
* 2: show places
* 3: show filter/list all (automatically hidden if there is no
* filter function)
* @param v <0 to hide the button >=0 show button,
* 0: set button-state to not-checked
* 1: set button-state to checked
* >1: retain current state
* @return 0 on success.
*/
int x_fib_cfg_buttons (int k, int v);

/** set custom callback to filter file-names.
* NULL will disable the filter and hide the 'show all' button.
* changes only have any effect if the dialog is not visible.
*
* @param cb callback function to check file
* the callback function is called with the file name (basename only)
* and is expected to return 1 if the file passes the filter
* and 0 if the file should not be listed by default.
* @return 0 on success.
*/
int x_fib_cfg_filter_callback (int (*cb)(const char*));

#endif /* END X11 specific functions */

/* 'recently used' API. x-platform
* NOTE: all functions use a static cache and are not reentrant.
* It is expected that none of these functions are called in
* parallel from different threads.
*/

/** release static resources of 'recently used files'
*/
void x_fib_free_recent ();

/** add an entry to the recently used list
*
* The dialog does not add files automatically on open,
* if the application succeeds to open a selected file,
* this function should be called.
*
* @param path complete path to file
* @param atime time of last use, 0: NOW
* @return -1 on error, number of current entries otherwise
*/
int x_fib_add_recent (const char *path, time_t atime);

/** get a platform specific path to a good location for
* saving the recently used file list.
* (follows XDG_DATA_HOME on Unix, and CSIDL_LOCAL_APPDATA spec)
*
* @param application-name to use to include in file
* @return pointer to static path or NULL
*/
const char *x_fib_recent_file(const char *appname);

/** save the current list of recently used files to the given filename
* (the format is one file per line, filename URL encoded and space separated
* with last-used timestamp)
*
* This function tries to creates the containing directory if it does
* not exist.
*
* @param fn file to save the list to
* @return 0: on success
*/
int x_fib_save_recent (const char *fn);

/** load a recently used file list.
*
* @param fn file to load the list from
* @return 0: on success
*/
int x_fib_load_recent (const char *fn);

/** get number of entries in the current list
* @return number of entries in the recently used list
*/
unsigned int x_fib_recent_count ();

/** get recently used entry at given position
*
* @param i entry to query
* @return pointer to static string
*/
const char *x_fib_recent_at (unsigned int i);

Loading…
Cancel
Save