1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
#include "effect_editor_vst2.h"
//keep this for order
#include "audio_effect_provider_vst2.h"
#include "effect_editor_x11.h"
#ifdef WINDOWS_ENABLED
void EffectPlaceholderVST2Win32::_vst_resize(void *self, int w, int h) {
EffectPlaceholderVST2Win32 *ph = (EffectPlaceholderVST2Win32 *)self;
return;
}
void EffectPlaceholderVST2Win32::resize_editor(int left, int top, int right, int bottom) {
if (vst_window) {
RECT rc;
rc.left = left;
rc.right = right;
rc.bottom = bottom;
rc.top = top;
const auto style = GetWindowLongPtr(vst_window, GWL_STYLE);
const auto exStyle = GetWindowLongPtr(vst_window, GWL_EXSTYLE);
const BOOL fMenu = GetMenu(vst_window) != nullptr;
AdjustWindowRectEx(&rc, style, fMenu, exStyle);
MoveWindow(vst_window, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}
}
void EffectPlaceholderVST2Win32::on_size_allocate(Gtk::Allocation &allocation) {
// Do something with the space that we have actually been given:
//(We will not be given heights or widths less than we have requested, though
// we might get more)
// Use the offered allocation for this container:
set_allocation(allocation);
if (m_refGdkWindow) {
m_refGdkWindow->move_resize(allocation.get_x(), allocation.get_y(),
allocation.get_width(),
allocation.get_height());
}
}
bool EffectPlaceholderVST2Win32::_update_window_position() {
bool visible = is_visible();
if (visible) {
//make sure it really is..
GtkWidget *p = gobj();
GtkWidget *w = gtk_widget_get_parent(p);
while (w) {
if (GTK_IS_NOTEBOOK(w)) {
GtkNotebook *notebook = GTK_NOTEBOOK(w);
int cpage = gtk_notebook_get_current_page(notebook);
if (p != gtk_notebook_get_nth_page(notebook, cpage)) {
visible = false;
break;
}
}
p = w;
w = gtk_widget_get_parent(p);
}
}
GtkWidget *toplevel = gtk_widget_get_toplevel(gobj());
ERR_FAIL_COND_V(!GTK_IS_WINDOW(toplevel), false);
int root_x, root_y;
//gtk_window_get_position(GTK_WINDOW(toplevel), &root_x, &root_y);
HWND hwnd = gdk_win32_window_get_impl_hwnd(gtk_widget_get_window(gobj()));
/* RECT r;
GetWindowRect(hwnd, &r);
root_x = r.left;
root_y = r.top;
*/
POINT p;
p.x = 0;
p.y = 0;
ClientToScreen(hwnd, &p);
root_x = p.x;
root_y = p.y;
//method below is not compatible with multiple monitors
{
int widget_x, widget_y;
gdk_window_get_origin(gtk_widget_get_window(gobj()), &widget_x, &widget_y);
int toplevel_x, toplevel_y;
gdk_window_get_origin(gtk_widget_get_window(toplevel), &toplevel_x, &toplevel_y);
root_x += widget_x - toplevel_x;
root_y += widget_y - toplevel_y;
}
//gdk_window_get_origin(gtk_widget_get_window(gobj()), &root_x, &root_y);
int tlx = 0, tly = 0;
/*gtk_widget_translate_coordinates(gobj(), gtk_widget_get_toplevel(gobj()), 0, 0, &tlx, &tly);
root_x += tlx;
root_y += tlx;*/
if (root_x != prev_x || root_y != prev_y || prev_w != vst_w || prev_h != vst_h) {
resize_editor(root_x, root_y, root_x + vst_w, root_y + vst_h);
prev_x = root_x;
prev_y = root_y;
prev_w = vst_w;
prev_h = vst_h;
}
if (prev_visible != visible) {
ShowWindow(vst_window, visible ? SW_SHOW : SW_HIDE);
prev_visible = visible;
}
if (visible) {
vst_effect->process_user_interface();
}
return true;
}
void EffectPlaceholderVST2Win32::on_realize() {
// Do not call base class Gtk::Widget::on_realize().
// It's intended only for widgets that set_has_window(false).
set_realized();
if (!m_refGdkWindow) {
// Create the GdkWindow:
GdkWindowAttr attributes;
memset(&attributes, 0, sizeof(attributes));
Gtk::Allocation allocation = get_allocation();
// Set initial position and size of the Gdk::Window:
attributes.x = allocation.get_x();
attributes.y = allocation.get_y();
attributes.width = allocation.get_width();
attributes.height = allocation.get_height();
attributes.event_mask = get_events() | /* Gdk::EXPOSURE_MASK |*/
Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
Gdk::BUTTON1_MOTION_MASK | Gdk::KEY_PRESS_MASK |
Gdk::KEY_RELEASE_MASK;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.wclass = GDK_INPUT_OUTPUT;
m_refGdkWindow = Gdk::Window::create(get_parent_window(), &attributes,
GDK_WA_X | GDK_WA_Y);
set_window(m_refGdkWindow);
// make the widget receive expose events
m_refGdkWindow->set_user_data(gobj());
/* Set the Window Parentship and update timer */
}
if (m_refGdkWindow) {
//hwnd for gtk window
HWND hwnd = gdk_win32_window_get_impl_hwnd(m_refGdkWindow->gobj());
//set as parent. This works, while SetParent DOES NOT.
SetWindowLongPtr(vst_window, GWLP_HWNDPARENT, (LONG_PTR)hwnd);
/*SetParent((HWND)vst_window, (HWND)hwnd);*/
//turn on update timer to reposition the Window
//sorry, this is the only way I found..
update_timer = Glib::signal_timeout().connect(sigc::mem_fun(*this, &EffectPlaceholderVST2Win32::_update_window_position),
50, Glib::PRIORITY_DEFAULT);
//Show the Window
ShowWindow(vst_window, SW_SHOW);
prev_visible = true;
}
}
void EffectPlaceholderVST2Win32::on_unrealize() {
//clear the window
if (m_refGdkWindow) {
//clear parenthood
SetWindowLongPtr(vst_window, GWLP_HWNDPARENT, (LONG_PTR)NULL);
//disconnect timer
update_timer.disconnect();
//Hide the Window
ShowWindow(vst_window, SW_HIDE);
prev_visible = false;
}
m_refGdkWindow.reset();
// Call base class:
Gtk::Widget::on_unrealize();
}
bool EffectPlaceholderVST2Win32::on_visibility_notify_event(GdkEventVisibility *visibility_event) {
/*
if (m_refGdkWindow) {
if (visibility_event->state == GDK_VISIBILITY_FULLY_OBSCURED) {
ShowWindow(vst_window, SW_HIDE);
} else {
ShowWindow(vst_window, SW_SHOW);
}
}
*/
return false;
}
bool EffectPlaceholderVST2Win32::on_draw(const Cairo::RefPtr<Cairo::Context> &cr) {
const Gtk::Allocation allocation = get_allocation();
return false;
Gdk::RGBA rgba;
rgba.set_red(0);
rgba.set_green(0);
rgba.set_blue(0);
rgba.set_alpha(1);
Gdk::Cairo::set_source_rgba(cr, rgba);
cr->rectangle(0, 0, allocation.get_width(), allocation.get_height());
cr->fill();
}
EffectPlaceholderVST2Win32::EffectPlaceholderVST2Win32(AudioEffectVST2 *p_vst_effect) :
// The GType name will actually be gtkmm__CustomObject_mywidget
Glib::ObjectBase("filler"),
Gtk::Widget() {
vst_effect = p_vst_effect;
vst_w = 1;
vst_h = 1;
vst_window = NULL;
//create the window, but don't use it.
const auto style = WS_POPUP;
vst_window = CreateWindowExW(0, L"VST_HOST", vst_effect->get_path().c_str(), style, 0, 0, 0, 0, NULL, 0, 0, 0);
//open the user interface (it won't be visible though.
vst_effect->open_user_interface(vst_window);
//allocate size for this VST here
vst_effect->get_user_interface_size(vst_w, vst_h);
set_size_request(vst_w, vst_h);
prev_x = prev_y = prev_w = prev_h = -1;
prev_visible = false;
}
EffectPlaceholderVST2Win32::~EffectPlaceholderVST2Win32() {
vst_effect->close_user_interface();
DestroyWindow(vst_window);
}
#endif
void initialize_vst2_editor() {
#ifdef WINDOWS_ENABLED
HMODULE hInst = GetModuleHandleA(NULL);
ERR_FAIL_COND(!hInst);
WNDCLASSEXW wcex{ sizeof(wcex) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpfnWndProc = DefWindowProc;
wcex.hInstance = GetModuleHandle(0);
wcex.lpszClassName = L"VST_HOST";
if (!RegisterClassExW(&wcex)) {
ERR_PRINT("Error in initialize_vst2_editor(): (class registration failed");
return;
}
#endif
#ifdef FREEDESKTOP_ENABLED
vstfx_init();
#endif
}
void finalize_vst2_editor() {
#ifdef FREEDESKTOP_ENABLED
vstfx_exit();
#endif
}
bool EffectEditorVST2::initialize() {
#ifdef FREEDESKTOP_ENABLED
socket.add_id(xid);
int w, h;
vstfx_get_window_size(vst_effect, &w, &h);
socket.set_size_request(w, h);
#endif
return false;
}
EffectEditorVST2::EffectEditorVST2(AudioEffectVST2 *p_vst, EffectEditor *p_editor) :
effect_editor_midi(p_vst, p_editor)
#ifdef WINDOWS_ENABLED
,
vst_placeholder(p_vst)
#endif
{
vst_effect = p_vst;
#ifdef WINDOWS_ENABLED
effect_editor_midi.prepend_page(vst_placeholder, "VST2 Plugin");
#endif
pack_start(effect_editor_midi, Gtk::PACK_EXPAND_WIDGET);
#ifdef FREEDESKTOP_ENABLED
effect_editor_midi.prepend_page(socket, "VST2 Plugin");
xid = vstfx_run_editor(p_vst, this);
#endif
//need window to be mapped, so wait
init_timer = Glib::signal_timeout().connect(sigc::mem_fun(*this, &EffectEditorVST2::initialize),
50, Glib::PRIORITY_DEFAULT);
show_all_children();
}
EffectEditorVST2::~EffectEditorVST2() {
#ifdef FREEDESKTOP_ENABLED
vstfx_destroy_editor(vst_effect);
#endif
}
|