VST UI sizeing rework

* prefer signal over timer-poll for VST size changes
* properly offset VST window (Windows)
* constrain window size (Windows)
* explicitly notify re-parent'ed child window (Linux)
This commit is contained in:
Robin Gareus 2017-03-07 18:38:01 +01:00
parent 4b982ef895
commit 819d9fa3cd
7 changed files with 103 additions and 64 deletions

View File

@ -33,6 +33,7 @@
#include <glibmm/timer.h>
#include "ardour/linux_vst_support.h"
#include "ardour/vst_plugin.h"
#include <X11/X.h>
#include <X11/Xlib.h>
@ -189,31 +190,37 @@ dispatch_x_events (XEvent* event, VSTState* vstfx)
int width = event->xconfigure.width;
int height = event->xconfigure.height;
/*If we get a config notify on the parent window XID then we need to see
if the size has been changed - some plugins re-size their UI window e.g.
when opening a preset manager (you might think that should be spawned as a new window...) */
/*if the size has changed, we flag this so that in lxvst_pluginui.cc we can make the
change to the GTK parent window in ardour, from its UI thread*/
/* If we get a config notify on the parent window XID then we need to see
* if the size has been changed - some plugins re-size their UI window e.g.
* when opening a preset manager.
*
* if the size has changed, we flag this so that in lxvst_pluginui.cc
* we can make the change to the GTK parent window in ardour, from its UI thread */
if (window == (Window) (vstfx->linux_window)) {
if (width != vstfx->width || height!=vstfx->height) {
#ifndef NDEBUG
printf("dispatch_x_events: ConfigureNotify cfg:(%d %d) plugin:(%d %d)\n",
width, height,
vstfx->width, vstfx->height
);
#endif
if (width != vstfx->width || height != vstfx->height) {
vstfx->width = width;
vstfx->height = height;
vstfx->want_resize = 1;
ARDOUR::VSTPlugin* plug = (ARDOUR::VSTPlugin *)(vstfx->plugin->user);
plug->VSTSizeWindow (); /* EMIT SIGNAL */
}
/*QUIRK : Loomer plugins not only resize the UI but throw it into some random
position at the same time. We need to re-position the window at the origin of
the parent window*/
/* QUIRK : Loomer plugins not only resize the UI but throw it into some random
* position at the same time. We need to re-position the window at the origin of
* the parent window*/
if (vstfx->linux_plugin_ui_window) {
XMoveWindow (LXVST_XDisplay, vstfx->linux_plugin_ui_window, 0, 0);
}
if (vstfx->linux_plugin_ui_window) {
XMoveWindow (LXVST_XDisplay, vstfx->linux_plugin_ui_window, 0, 0);
}
}
break;
}
/*Reparent Notify - when the plugin UI is reparented into

View File

@ -17,10 +17,10 @@
*/
#include "gtkmm2ext/gui_thread.h"
#include "ardour/lxvst_plugin.h"
#include "ardour/linux_vst_support.h"
#include "lxvst_plugin_ui.h"
#include "timers.h"
#include <gdk/gdkx.h>
#define LXVST_H_FIDDLE 40
@ -38,53 +38,31 @@ LXVSTPluginUI::LXVSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_
LXVSTPluginUI::~LXVSTPluginUI ()
{
_screen_update_connection.disconnect();
_resize_connection.disconnect();
// plugin destructor destroys the custom GUI, via the vstfx engine,
// and then our PluginUIWindow does the rest
}
bool
LXVSTPluginUI::start_updating (GdkEventAny*)
{
_screen_update_connection.disconnect();
_screen_update_connection = Timers::rapid_connect (mem_fun(*this, &LXVSTPluginUI::resize_callback));
return false;
}
bool
LXVSTPluginUI::stop_updating (GdkEventAny*)
{
_screen_update_connection.disconnect();
return false;
}
void
LXVSTPluginUI::resize_callback ()
{
/* We could maybe use this to resize the plugin GTK parent window
if required
*/
if (!_vst->state()->want_resize) {
return;
}
int new_height = _vst->state()->height;
int new_width = _vst->state()->width;
void* gtk_parent_window = _vst->state()->extra_data;
void* gtk_parent_window = _vst->state()->gtk_window_parent;
if (gtk_parent_window) {
int width = _vst->state()->width;
int height = _vst->state()->height;
#ifndef NDEBUG
printf ("LXVSTPluginUI::resize_callback %d x %d\n", width, height);
#endif
_socket.set_size_request(
new_width + _vst->state()->hoffset,
new_height + _vst->state()->voffset);
width + _vst->state()->hoffset,
height + _vst->state()->voffset);
((Gtk::Window*) gtk_parent_window)->resize (new_width, new_height + LXVST_H_FIDDLE);
((Gtk::Window*) gtk_parent_window)->resize (width, height + LXVST_H_FIDDLE);
if (_vst->state()->linux_plugin_ui_window) {
}
}
_vst->state()->want_resize = 0;
}
int
@ -106,15 +84,11 @@ int
LXVSTPluginUI::package (Gtk::Window& win)
{
VSTPluginUI::package (win);
_vst->state()->gtk_window_parent = (void*) (&win);
/* Map the UI start and stop updating events to 'Map' events on the Window */
win.signal_map_event().connect (mem_fun (*this, &LXVSTPluginUI::start_updating));
win.signal_unmap_event().connect (mem_fun (*this, &LXVSTPluginUI::stop_updating));
_vst->state()->extra_data = (void*) (&win);
_vst->state()->want_resize = 0;
_vst->VSTSizeWindow.connect (_resize_connection, invalidator (*this), boost::bind (&LXVSTPluginUI::resize_callback, this), gui_context());
return 0;
}
@ -181,4 +155,3 @@ gui_init (int* argc, char** argv[])
the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default());
gtk_error_handler = XSetErrorHandler (gtk_xerror_handler);
}

View File

@ -20,7 +20,7 @@
#ifndef __lxvst_plugin_ui_h__
#define __lxvst_plugin_ui_h__
#include <sigc++/signal.h>
#include "pbd/signals.h"
#include "vst_plugin_ui.h"
#ifdef LXVST_SUPPORT
@ -38,8 +38,8 @@ class LXVSTPluginUI : public VSTPluginUI
int get_preferred_height ();
bool start_updating (GdkEventAny *);
bool stop_updating (GdkEventAny *);
bool start_updating (GdkEventAny*) { return false; }
bool stop_updating (GdkEventAny*) { return false; }
int package (Gtk::Window&);
void forward_key_event (GdkEventKey *);
@ -49,7 +49,7 @@ private:
void resize_callback ();
int get_XID ();
sigc::connection _screen_update_connection;
PBD::ScopedConnection _resize_connection;
};
#endif //LXVST_SUPPORT

View File

@ -51,6 +51,7 @@ VSTPluginUI::VSTPluginUI (boost::shared_ptr<ARDOUR::PluginInsert> insert, boost:
bypass_button.set_active (!insert->active ());
pack_start (*box, false, false);
box->signal_size_allocate().connect (sigc::mem_fun (*this, &VSTPluginUI::top_box_allocated));
#ifdef GDK_WINDOWING_X11
pack_start (_socket, true, true);
_socket.set_border_width (0);
@ -122,6 +123,7 @@ VSTPluginUI::configure_handler (GdkEventConfigure*)
XEvent event;
gint x, y;
GdkWindow* w;
Window xw = _vst->state()->linux_plugin_ui_window;
if ((w = _socket.gobj()->plug_window) == 0) {
return false;
@ -150,8 +152,19 @@ VSTPluginUI::configure_handler (GdkEventConfigure*)
gdk_error_trap_push ();
XSendEvent (GDK_WINDOW_XDISPLAY (w), GDK_WINDOW_XWINDOW (w), False, StructureNotifyMask, &event);
/* if the plugin does adds itself to the parent,
* but ardour re-parents it, we have a pointer to
* the socket's child and need to resize the
* child window (e.g. JUCE, u-he)
*/
if (xw) {
XMoveResizeWindow (GDK_WINDOW_XDISPLAY (w), xw,
0, 0, _vst->state()->width, _vst->state()->height);
XMapRaised (GDK_WINDOW_XDISPLAY (w), xw);
XFlush (GDK_WINDOW_XDISPLAY (w));
}
gdk_error_trap_pop ();
#endif
return false;
}

View File

@ -48,6 +48,7 @@ protected:
boost::shared_ptr<ARDOUR::VSTPlugin> _vst;
Gtk::Socket _socket;
virtual void top_box_allocated (Gtk::Allocation&) {}
private:

View File

@ -20,7 +20,8 @@
#include <gtkmm.h>
#include <gtk/gtk.h>
#include <gtk/gtksocket.h>
#include <fst.h>
#include "gtkmm2ext/gui_thread.h"
#include "fst.h"
#include "ardour/plugin_insert.h"
#include "ardour/windows_vst_plugin.h"
@ -64,12 +65,48 @@ WindowsVSTPluginUI::~WindowsVSTPluginUI ()
// and then our PluginUIWindow does the rest
}
void
WindowsVSTPluginUI::top_box_allocated (Gtk::Allocation& a)
{
int h = a.get_height() + 12; // 2 * 6px spacing
if (_vst->state()->voffset != h) {
#ifndef NDEBUG
printf("WindowsVSTPluginUI:: update voffset to %d px\n", h);
#endif
_vst->state()->voffset = h;
resize_callback ();
}
}
void
WindowsVSTPluginUI::resize_callback ()
{
void* gtk_parent_window = _vst->state()->gtk_window_parent;
if (gtk_parent_window) {
int width = _vst->state()->width + _vst->state()->hoffset;
int height = _vst->state()->height + _vst->state()->voffset;
#ifndef NDEBUG
printf ("WindowsVSTPluginUI::resize_callback %d x %d\n", width, height);
#endif
set_size_request (width, height);
((Gtk::Window*) gtk_parent_window)->set_size_request (width, height);
((Gtk::Window*) gtk_parent_window)->resize (width, height);
fst_move_window_into_view (_vst->state ());
}
}
int
WindowsVSTPluginUI::package (Gtk::Window& win)
{
#ifndef NDEBUG
printf ("WindowsVSTPluginUI::package\n");
#endif
VSTPluginUI::package (win);
_vst->state()->gtk_window_parent = (void*) (&win);
fst_move_window_into_view (_vst->state ());
_vst->VSTSizeWindow.connect (_resize_connection, invalidator (*this), boost::bind (&WindowsVSTPluginUI::resize_callback, this), gui_context());
resize_callback ();
return 0;
}

View File

@ -17,6 +17,10 @@
*/
#ifndef __windows_vst_plugin_ui_h__
#define __windows_vst_plugin_ui_h__
#include "pbd/signals.h"
#include "vst_plugin_ui.h"
class WindowsVSTPluginUI : public VSTPluginUI
@ -34,6 +38,10 @@ public:
private:
void resize_callback ();
int get_XID ();
void top_box_allocated (Gtk::Allocation&);
PBD::ScopedConnection _resize_connection;
};
#endif