Browse Source

Change Event Handling methods, other fixes

Run lglw_events in effEditIdle (debug plugin)
Run lglw_events in effEditIdle (VSR plugin)
Run effEditIdle loop in debug host if no _XEventProc
Temporarily swap lglw_log for printf (needs fixing)
Suppress most mouse event messages
Bring back sending of child events to parent (rare occurence)
Cleanup some lglw_window_open code
lglw_window_open event mask setup to receive events for itself
Comment the setting of _XEventProc (to get to effEditIdle loop)
NoEventMask on mouse grabbing, possible fix for grabbing issues
Setup working and non-blocking lglw_events
pull/1639/head
Cameron Leger 6 years ago
parent
commit
aa4e2d0532
4 changed files with 71 additions and 95 deletions
  1. +25
    -79
      dep/lglw/lglw_linux.c
  2. +33
    -13
      other/vst2_debug_host/vst2_debug_host.cpp
  3. +2
    -2
      other/vst2_lglw_debug_plugin/plugin.cpp
  4. +11
    -1
      src/vst2_main.cpp

+ 25
- 79
dep/lglw/lglw_linux.c View File

@@ -38,6 +38,7 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/Xos.h> #include <X11/Xos.h>
#include <X11/Xatom.h>


#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glx.h> #include <GL/glx.h>
@@ -50,26 +51,26 @@
// //
// Regular log entry (low frequency) // Regular log entry (low frequency)
// //
// #define Dlog_verbose if(1);else lglw_log
#define Dlog if(0);else lglw_log
// #define Dlog_verbose if(1);else printf
#define Dlog if(0);else printf


// //
// Verbose log entry // Verbose log entry
// //
// #define Dlog_v if(1);else lglw_log
#define Dlog_v if(0);else lglw_log
// #define Dlog_v if(1);else printf
#define Dlog_v if(0);else printf


// //
// Very-verbose log entry // Very-verbose log entry
// //
// #define Dlog_vv if(1);else lglw_log
#define Dlog_vv if(0);else lglw_log
// #define Dlog_vv if(1);else printf
#define Dlog_vv if(0);else printf


// //
// Very-very-verbose log entry // Very-very-verbose log entry
// //
#define Dlog_vvv if(1);else lglw_log
// #define Dlog_vvv if(0);else lglw_log
#define Dlog_vvv if(1);else printf
// #define Dlog_vvv if(0);else printf


// //
// Print to stdout // Print to stdout
@@ -253,7 +254,7 @@ lglw_t lglw_init(int32_t _w, int32_t _h) {
logfile = fopen("/tmp/lglw_log.txt", "w"); logfile = fopen("/tmp/lglw_log.txt", "w");
XSetErrorHandler(xerror_handler); XSetErrorHandler(xerror_handler);
XInitThreads(); // fix GL crash, see <https://forum.juce.com/t/linux-vst-opengl-crash-because-xinitthreads-not-called/22821> XInitThreads(); // fix GL crash, see <https://forum.juce.com/t/linux-vst-opengl-crash-because-xinitthreads-not-called/22821>
loc_millisec_init(lglw); loc_millisec_init(lglw);


if(NULL != lglw) if(NULL != lglw)
@@ -490,7 +491,7 @@ static void loc_eventProc(XEvent *xev, lglw_int_t *lglw) {
break; break;


case MotionNotify: case MotionNotify:
Dlog_v("lglw:loc_eventProc: xev MotionNotify\n");
Dlog_vvv("lglw:loc_eventProc: xev MotionNotify\n");
; // empty statement ; // empty statement
XMotionEvent *motion = (XMotionEvent*)xev; XMotionEvent *motion = (XMotionEvent*)xev;


@@ -943,23 +944,19 @@ static void loc_eventProc(XEvent *xev, lglw_int_t *lglw) {
break; break;
} }


#if 0
// (note) this causes a feedback loop in the VST2 debug host
if(LGLW_FALSE == eventHandled) if(LGLW_FALSE == eventHandled)
{ {
if(0 == lglw->parent_xwnd) if(0 == lglw->parent_xwnd)
{ {
Dlog("lglw:loc_eventProc: no parent window to send events to");
Dlog("lglw:loc_eventProc: no parent window to send events to\n");
XSendEvent(lglw->xdsp, InputFocus, True/*propgate*/, NoEventMask, xev); XSendEvent(lglw->xdsp, InputFocus, True/*propgate*/, NoEventMask, xev);
} }
else else
{ {
Dlog("lglw:loc_eventProc: sending event %i to parent\n", xev->type);
XSendEvent(lglw->xdsp, lglw->parent_xwnd, True/*propgate*/, NoEventMask, xev); XSendEvent(lglw->xdsp, lglw->parent_xwnd, True/*propgate*/, NoEventMask, xev);
} }
} }
#else
(void)eventHandled;
#endif
} }
} }


@@ -1190,16 +1187,12 @@ lglw_bool_t lglw_window_open (lglw_t _lglw, void *_parentHWNDOrNull, int32_t _x,


Dlog_v("lglw:lglw_window_open: 4\n"); Dlog_v("lglw:lglw_window_open: 4\n");
XSetWindowAttributes swa; XSetWindowAttributes swa;
// // XEvent event;
XSync(lglw->xdsp, False); XSync(lglw->xdsp, False);


#if 1
Dlog_v("lglw:lglw_window_open: 5\n"); Dlog_v("lglw:lglw_window_open: 5\n");
swa.border_pixel = 0; swa.border_pixel = 0;
swa.colormap = lglw->cmap; swa.colormap = lglw->cmap;
// (note) [bsp] setting this to NoEventMask causes all events to be propagated to the parent (host) window.
// The host then reports the event to the plugin by calling its eventProc function (set via "_XEventProc").
swa.event_mask = NoEventMask;/////ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | FocusChangeMask;
swa.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | ExposureMask | FocusChangeMask; // NoEventMask to bubble-up to parent
lglw->win.xwnd = XCreateWindow(lglw->xdsp/*display*/, lglw->win.xwnd = XCreateWindow(lglw->xdsp/*display*/,
DefaultRootWindow(lglw->xdsp)/*parent. see Cameron's comment below.*/, DefaultRootWindow(lglw->xdsp)/*parent. see Cameron's comment below.*/,
0/*x*/, 0/*x*/,
@@ -1225,34 +1218,26 @@ lglw_bool_t lglw_window_open (lglw_t _lglw, void *_parentHWNDOrNull, int32_t _x,
NULL/*XSizeHints*/ NULL/*XSizeHints*/
); );


// Setup the event proc now, on the parent window as well just for the debug host
// It was simpler to do this than check in the debug host for the reparent event
Dlog_v("lglw:lglw_window_open: 7\n"); Dlog_v("lglw:lglw_window_open: 7\n");
loc_setEventProc(lglw->xdsp, lglw->win.xwnd);
// loc_setEventProc(lglw->xdsp, lglw->win.xwnd);
loc_setProperty(lglw->xdsp, lglw->win.xwnd, "_lglw", (void*)lglw); // set instance pointer loc_setProperty(lglw->xdsp, lglw->win.xwnd, "_lglw", (void*)lglw); // set instance pointer


if(0 != _parentHWNDOrNull) if(0 != _parentHWNDOrNull)
{ {
loc_setEventProc(lglw->xdsp, lglw->parent_xwnd);
// loc_setEventProc(lglw->xdsp, lglw->parent_xwnd);
loc_setProperty(lglw->xdsp, lglw->parent_xwnd, "_lglw", (void*)lglw); // set instance pointer loc_setProperty(lglw->xdsp, lglw->parent_xwnd, "_lglw", (void*)lglw); // set instance pointer
} }


// Some hosts only check and store the callback when the Window is reparented // Some hosts only check and store the callback when the Window is reparented
// Since creating the Window with a Parent may or may not do that, but the callback is not set, // Since creating the Window with a Parent may or may not do that, but the callback is not set,
// ... it's created as a root window, the callback is set, and then it's reparented // ... it's created as a root window, the callback is set, and then it's reparented
#if 1
// (note) [cameronleger] In Ardour's code-base, the only time it looks for the _XEventProc is during a ReparentNotify event
if (0 != _parentHWNDOrNull) if (0 != _parentHWNDOrNull)
{ {
Dlog_v("lglw:lglw_window_open: 8\n"); Dlog_v("lglw:lglw_window_open: 8\n");
XReparentWindow(lglw->xdsp, lglw->win.xwnd, lglw->parent_xwnd, 0, 0); XReparentWindow(lglw->xdsp, lglw->win.xwnd, lglw->parent_xwnd, 0, 0);
} }
#endif
lglw->win.b_owner = LGLW_TRUE; lglw->win.b_owner = LGLW_TRUE;
#else
lglw->win.xwnd = (Window)_parentHWNDOrNull;
lglw->win.b_owner = LGLW_FALSE;
#endif


Dlog_v("lglw:lglw_window_open: 9\n"); Dlog_v("lglw:lglw_window_open: 9\n");
if(lglw->win.b_owner) if(lglw->win.b_owner)
@@ -1261,26 +1246,6 @@ lglw_bool_t lglw_window_open (lglw_t _lglw, void *_parentHWNDOrNull, int32_t _x,
XMapWindow(lglw->xdsp, lglw->win.xwnd); XMapWindow(lglw->xdsp, lglw->win.xwnd);
} }


#if 0
XSelectInput(lglw->xdsp, lglw->win.xwnd,
ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | FocusChangeMask
);
XGrabKeyboard(lglw->xdsp, lglw->win.xwnd,
False/*owner_events*/,
GrabModeAsync/*pointer_mode*/,
GrabModeAsync/*keyboard_mode*/,
CurrentTime/*time*/
);
#endif

#if 0
XSetInputFocus(lglw->xdsp/*display*/,
PointerRoot/*focus*/,
RevertToPointerRoot/*revert_to*/,
CurrentTime
);
#endif

XSync(lglw->xdsp, False); XSync(lglw->xdsp, False);
lglw->win.mapped = LGLW_TRUE; lglw->win.mapped = LGLW_TRUE;


@@ -1460,13 +1425,10 @@ void lglw_window_size_get(lglw_t _lglw, int32_t *_retX, int32_t *_retY) {
void lglw_redraw(lglw_t _lglw) { void lglw_redraw(lglw_t _lglw) {
LGLW(_lglw); LGLW(_lglw);


// (todo) implement me

if(NULL != lglw) if(NULL != lglw)
{ {
if(0 != lglw->win.xwnd) if(0 != lglw->win.xwnd)
{ {
// TODO Event Loop
Dlog_vvv("lglw:lglw_redraw: 1\n"); Dlog_vvv("lglw:lglw_redraw: 1\n");
XEvent xev; XEvent xev;
xev.xany.type = Expose; xev.xany.type = Expose;
@@ -1751,7 +1713,7 @@ void lglw_mouse_grab(lglw_t _lglw, uint32_t _grabMode) {
case LGLW_MOUSE_GRAB_CAPTURE: case LGLW_MOUSE_GRAB_CAPTURE:
result = XGrabPointer(lglw->xdsp, lglw->win.xwnd, result = XGrabPointer(lglw->xdsp, lglw->win.xwnd,
True/*owner_events*/, True/*owner_events*/,
ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | PointerMotionHintMask | ButtonMotionMask | KeymapStateMask/*event_mask*/,
NoEventMask/*event_mask*/,
GrabModeAsync/*pointer_mode*/, GrabModeAsync/*pointer_mode*/,
GrabModeAsync/*keyboard_mode*/, GrabModeAsync/*keyboard_mode*/,
lglw->win.xwnd/*confine_to*/, lglw->win.xwnd/*confine_to*/,
@@ -1770,7 +1732,7 @@ void lglw_mouse_grab(lglw_t _lglw, uint32_t _grabMode) {
case LGLW_MOUSE_GRAB_WARP: case LGLW_MOUSE_GRAB_WARP:
result = XGrabPointer(lglw->xdsp, lglw->win.xwnd, result = XGrabPointer(lglw->xdsp, lglw->win.xwnd,
True/*owner_events*/, True/*owner_events*/,
ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | PointerMotionHintMask | ButtonMotionMask | KeymapStateMask/*event_mask*/,
NoEventMask/*event_mask*/,
GrabModeAsync/*pointer_mode*/, GrabModeAsync/*pointer_mode*/,
GrabModeAsync/*keyboard_mode*/, GrabModeAsync/*keyboard_mode*/,
lglw->win.xwnd/*confine_to*/, lglw->win.xwnd/*confine_to*/,
@@ -2169,6 +2131,7 @@ void lglw_clipboard_text_get(lglw_t _lglw, uint32_t _maxChars, uint32_t *_retNum
} }
} }



// ---------------------------------------------------------------------------- lglw_events // ---------------------------------------------------------------------------- lglw_events
void lglw_events(lglw_t _lglw) { void lglw_events(lglw_t _lglw) {
LGLW(_lglw); LGLW(_lglw);
@@ -2177,34 +2140,17 @@ void lglw_events(lglw_t _lglw) {
{ {
if(0 != lglw->win.xwnd) if(0 != lglw->win.xwnd)
{ {
#if 0
//int numEv = XEventsQueued(lglw->xdsp, QueuedAlready);
int numEv = XEventsQueued(lglw->xdsp, QueuedAfterReading);
// => numEv is always 0
int evIdx = 0;
Dlog_v("xxx lglw_events: numEv=%d\n", numEv);

//for(; evIdx < numEv; evIdx++)
for(;;)
XEvent xev;
int queued = XPending(lglw->xdsp);
Dlog_v("lglw:lglw_events: (events: %i)\n", queued);
while(queued)
{ {
XEvent xev;
XNextEvent(lglw->xdsp, &xev); XNextEvent(lglw->xdsp, &xev);
Dlog_v("xxx lglw_events: XNextEvent[%d]\n", evIdx++);
loc_eventProc(&xev, lglw); loc_eventProc(&xev, lglw);
queued--;
} }
#else
// // int evIdx = 0;
// // for(;;)
// // {
// // XEvent xev;
// // // => blocks forever
// // XNextEvent(lglw->xdsp, &xev);
// // Dlog_v("xxx XNextEvent[%d]\n", evIdx++);
// // }


loc_process_timer(lglw); loc_process_timer(lglw);
#endif
} }
} }
} }

+ 33
- 13
other/vst2_debug_host/vst2_debug_host.cpp View File

@@ -237,6 +237,7 @@ void open_and_close(void) {
VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, NULL/*hWnd*/, 0.0f); VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, NULL/*hWnd*/, 0.0f);
#else #else
VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, (void*)(w)/*hWnd*/, 0.0f); VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, (void*)(w)/*hWnd*/, 0.0f);
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f); // test feedback loop
#endif #endif
(void)ip; (void)ip;
sleep(2); sleep(2);
@@ -245,7 +246,35 @@ void open_and_close(void) {
void *result = loc_getProperty(d, w, "_XEventProc"); void *result = loc_getProperty(d, w, "_XEventProc");
if(result == 0) if(result == 0)
{ {
printf("xxx no XEventProc found\n");
printf("xxx no XEventProc found, running effEditIdle instead\n");
for(;;)
{
XEvent xev;
int queued = XPending(d);
printf("xxx =====================================================\n");
printf("xxx checking host queue before effEditIdle (events: %i)\n", queued);
while(queued)
{
XNextEvent(d, &xev);
printf("xxx event type: %i\n", xev.type);
queued--;
}

// printf("xxx calling effect->dispatcher<effEditIdle>\n");
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);

queued = XPending(d);
printf("xxx checking host queue after effEditIdle (events: %i)\n", queued);
while(queued)
{
XNextEvent(d, &xev);
if(MotionNotify != xev.type)
printf("xxx event type: %i\n", xev.type);
queued--;
}

// sleep(1); // can be helpful when viewing print statements
}
} }
else else
{ {
@@ -253,7 +282,7 @@ void open_and_close(void) {
int evIdx = 0; int evIdx = 0;
eventProc = (void (*) (void* event))result; eventProc = (void (*) (void* event))result;
printf("xxx XEventProc found\n"); printf("xxx XEventProc found\n");
#if 1
for(;;) for(;;)
{ {
XEvent xev; XEvent xev;
@@ -261,21 +290,12 @@ void open_and_close(void) {
Dprintf_verbose("xxx call XEventProc[%d]\n", evIdx++); Dprintf_verbose("xxx call XEventProc[%d]\n", evIdx++);
eventProc(&xev); eventProc(&xev);


Dprintf_verbose("xxx calling effect->dispatcher<effEditIdle>\n");
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
// Dprintf_verbose("xxx calling effect->dispatcher<effEditIdle>\n");
// effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
} }
#endif
} }
#endif #endif


#if 0
for(;;)
#endif
{
printf("xxx calling effect->dispatcher<effEditIdle>\n");
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
}

sleep(1); sleep(1);
printf("xxx calling effect->dispatcher<effEditClose>\n"); printf("xxx calling effect->dispatcher<effEditClose>\n");
effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f); effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f);


+ 2
- 2
other/vst2_lglw_debug_plugin/plugin.cpp View File

@@ -496,8 +496,8 @@ VstIntPtr VSTPluginDispatcher(VSTPlugin *vstPlugin, VstInt32 opCode, VstInt32 in
#ifdef USE_LGLW #ifdef USE_LGLW
if(lglw_window_is_visible(wrapper->lglw)) if(lglw_window_is_visible(wrapper->lglw))
{ {
// lglw_events(wrapper->lglw);
// wrapper->redrawWindow(); // redraw is triggered by timer_cbk instead // wrapper->redrawWindow(); // redraw is triggered by timer_cbk instead
lglw_events(wrapper->lglw);
} }
#endif // USE_LGLW #endif // USE_LGLW
break; break;
@@ -683,7 +683,7 @@ VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback)
// simply create our plugin C++ class // simply create our plugin C++ class
VSTPluginWrapper *plugin = VSTPluginWrapper *plugin =
new VSTPluginWrapper(vstHostCallback, new VSTPluginWrapper(vstHostCallback,
//CCONST('u', 's', 'a', '§'), // registered with Steinberg (http://service.steinberg.de/databases/plugin.nsf/plugIn?openForm)
//CCONST('u', 's', 'a', '�'), // registered with Steinberg (http://service.steinberg.de/databases/plugin.nsf/plugIn?openForm)
CCONST('t', 'e', 's', 't'), // unregistered CCONST('t', 'e', 's', 't'), // unregistered
PLUGIN_VERSION, // version PLUGIN_VERSION, // version
0, // no params 0, // no params


+ 11
- 1
src/vst2_main.cpp View File

@@ -1117,6 +1117,15 @@ public:
} }
} }


void events(void) {
setGlobals();

if(lglw_window_is_visible(rack::global_ui->window.lglw))
{
lglw_events(rack::global_ui->window.lglw);
}
}

private: private:
// the host callback (a function pointer) // the host callback (a function pointer)
VSTHostCallback _vstHostCallback; VSTHostCallback _vstHostCallback;
@@ -1798,9 +1807,10 @@ VstIntPtr VSTPluginDispatcher(VSTPlugin *vstPlugin,
#endif #endif


case effEditIdle: case effEditIdle:
if(0 == wrapper->redraw_ival_ms)
// if(0 == wrapper->redraw_ival_ms)
{ {
wrapper->queueRedraw(); wrapper->queueRedraw();
wrapper->events();
} }
break; break;




Loading…
Cancel
Save