VST window does not receive mouse events on Linux

Hi,

While writing a small VST host for testing purposes on Linux, I've found something I cannot fully understand. The following code scans a directory for plugins, then loads the PLUGIN_TO_SHOW-th plugin (it's just a numeric constant, you should change it as needed). Finally it initializes a new X11 window and opens the plugin GUI passing a pointer to that window with ui->addToDesktop(0, (void*) w).


#include <X11/Xlib.h>
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#define JUCE_MODULE_AVAILABLE_juce_audio_basics          1
#define JUCE_MODULE_AVAILABLE_juce_audio_devices         1
#define JUCE_MODULE_AVAILABLE_juce_audio_formats         1
#define JUCE_MODULE_AVAILABLE_juce_audio_processors      1
#define JUCE_MODULE_AVAILABLE_juce_audio_utils           1
#define JUCE_MODULE_AVAILABLE_juce_core                  1
#define JUCE_MODULE_AVAILABLE_juce_cryptography          1
#define JUCE_MODULE_AVAILABLE_juce_data_structures       1
#define JUCE_MODULE_AVAILABLE_juce_events                1
#define JUCE_MODULE_AVAILABLE_juce_graphics              1
#define JUCE_MODULE_AVAILABLE_juce_gui_basics            1
#define JUCE_MODULE_AVAILABLE_juce_gui_extra             1
#define JUCE_MODULE_AVAILABLE_juce_opengl                1
#define JUCE_MODULE_AVAILABLE_juce_video                 1
#define JUCE_STANDALONE_APPLICATION 1
#define JUCE_ALSA 1
#define JUCE_USE_CDREADER 0
#define JUCE_USE_CDBURNER 0
#define JUCE_USE_FLAC 0
#define JUCE_USE_OGGVORBIS 0
#define JUCE_PLUGINHOST_VST 1
#define JUCE_PLUGINHOST_VST3 0
#define JUCE_PLUGINHOST_AU 1
#define JUCE_WEB_BROWSER 0
#define JUCE_QUICKTIME 0
#define JUCE_USE_CAMERA 0
#include "modules/juce_audio_basics/juce_audio_basics.h"
#include "modules/juce_audio_devices/juce_audio_devices.h"
#include "modules/juce_audio_formats/juce_audio_formats.h"
#include "modules/juce_audio_processors/juce_audio_processors.h"
#include "modules/juce_audio_utils/juce_audio_utils.h"
#include "modules/juce_core/juce_core.h"
#include "modules/juce_cryptography/juce_cryptography.h"
#include "modules/juce_data_structures/juce_data_structures.h"
#include "modules/juce_events/juce_events.h"
#include "modules/juce_graphics/juce_graphics.h"
#include "modules/juce_gui_basics/juce_gui_basics.h"
#include "modules/juce_gui_extra/juce_gui_extra.h"
#include "modules/juce_opengl/juce_opengl.h"
#include "modules/juce_video/juce_video.h"

#define PLUGIN_TO_SHOW 20
 
int main(int argc, char **argv)
{
  /* JUCE */
  
  juce::KnownPluginList pl;
  juce::VSTPluginFormat format;
  juce::FileSearchPath path("/path/to/your/vst/folder");
  juce::PluginDirectoryScanner scanner(pl, format, path, false, juce::File::nonexistent);
 
  /* scan dir */
  bool cont = true;
  juce::String name;
  while (cont) {
    cont = scanner.scanNextFile(false, name);
  }
  printf("%d element(s) found\n", pl.getNumTypes());
  /* get infos */
  juce::PluginDescription *descr;
  for (int i=0; i<pl.getNumTypes(); i++) {
    descr = pl.getType(i);
    printf("(%d)  %s\n", i, descr->name.toRawUTF8());
  }
  
  /* init a plugin */
  juce::VSTPluginFormat p;
  juce::AudioProcessor *proc;
  juce::AudioProcessorEditor *ui;
  proc = (juce::AudioProcessor*) p.createInstanceFromDescription(*pl.getType(PLUGIN_TO_SHOW), 44100, 1024);
  
  ui = proc->createEditor();
  ui->setOpaque(false);
  ui->setVisible(true);
  
  /* X11 */
  
  Display *d;
  Window w;
  XEvent e;
  int s;
  d = XOpenDisplay(NULL);
  s = DefaultScreen(d);
  w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1, BlackPixel(d, s), WhitePixel(d, s));
  XSelectInput(d, w, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask);
  XMapWindow(d, w);
  
  XNextEvent(d, &e);  // <- this "wakes up" the system
  ui->addToDesktop(0, (void*) w);

  while(1) {
    XNextEvent(d, &e);
    printf("X11 event: %d\n", e.type);
  }
  XCloseDisplay(d);
  return 0;
}

 

Surprisingly, almost all mouse-related events are not handled correctly by the VST window: you cannot interact with the plugin interface except for mouseEnter/mouseExit events (EnterNotify and LeaveNotify in X's domain). Given my overall lack of experience with JUCE, am I doing something wrong?

 

You're not using juce's runDispatchLoop(), so at least you need to call runDispatchLoopUntil() periodically.

Right now your juce gui code never gets a chance to do message-manager based stuff.

 

Hi falkTX, you're right: with runDispatchLoop() I'm able to send events to the child window, but of course that will block until the stop message. Actually my intent is to let the "parent" app take care of the event dispatching - that's what the while loop in my basic example does. Should I call runDispatchLoopUntil(n) periodically inside the parent event dispatcher? Am I off the track here?

Why are you going to all the effort of trying to write this bare X11 code? You're using juce anyway, so why not just let the normal juce app framework take care of all this stuff for you?

I'm trying to bring JUCE's VST hosting capabilities into an existing app, which has its own GUI framework with its internal event dispatcher. Unfortunately converting the whole app to JUCE is not an option at the moment: the ability to share a Window with addToDesktop(...) seems a great way to make the two toolkits talk each other...

Ok, well it's probably possible, but you may need to figure out some stuff yourself. Are you using ScopedJuceInitialiser_GUI?

First of all thank you for your help! No, I'm not using ScopedJuceInitialiser_GUI right now...

Well, what I meant was that maybe you should be!