1 /*
2  * Copyright (C) 2020 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifdef WAF_BUILD
20 #include "gtk2ardour-config.h"
21 #endif
22 
23 #include <glibmm/main.h>
24 
25 #include "pbd/unwind.h"
26 
27 #include "ardour/plugin_insert.h"
28 #include "ardour/vst3_plugin.h"
29 
30 #include "gtkmm2ext/gui_thread.h"
31 
32 #include "vst3_hwnd_plugin_ui.h"
33 
34 #include <gdk/gdkwin32.h>
35 
36 using namespace ARDOUR;
37 using namespace Steinberg;
38 
39 
VST3HWNDPluginUI(boost::shared_ptr<PluginInsert> pi,boost::shared_ptr<VST3Plugin> vst3)40 VST3HWNDPluginUI::VST3HWNDPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<VST3Plugin> vst3)
41 	: VST3PluginUI (pi, vst3)
42 {
43 	/* TODO register window class, implement wndproc etc */
44 
45 	pack_start (_gui_widget, true, true);
46 
47 	_gui_widget.signal_realize().connect (mem_fun (this, &VST3HWNDPluginUI::view_realized));
48 	_gui_widget.signal_size_request ().connect (mem_fun (this, &VST3HWNDPluginUI::view_size_request));
49 	_gui_widget.signal_size_allocate ().connect (mem_fun (this, &VST3HWNDPluginUI::view_size_allocate));
50 	_gui_widget.signal_scroll_event ().connect (sigc::mem_fun (*this, &VST3HWNDPluginUI::forward_scroll_event), false);
51 
52 	_gui_widget.show ();
53 }
54 
~VST3HWNDPluginUI()55 VST3HWNDPluginUI::~VST3HWNDPluginUI ()
56 {
57 	assert (_view_realized);
58 	_vst3->close_view ();
59 }
60 
61 void
view_realized()62 VST3HWNDPluginUI::view_realized ()
63 {
64 	IPlugView* view = _vst3->view ();
65 	HWND hwnd = (HWND) gdk_win32_drawable_get_handle (GTK_WIDGET(_gui_widget.gobj())->window);
66 	// SetWindowLongPtr (hwnd, GWLP_USERDATA, (__int3264) (LONG_PTR)this);
67 	if (kResultOk != view->attached (reinterpret_cast<void*> (hwnd), Steinberg::kPlatformTypeHWND)) {
68 		assert (0);
69 	}
70 	_view_realized = true;
71 
72 	ViewRect rect;
73 	if (view->getSize (&rect) == kResultOk) {
74 		_req_width  = rect.right - rect.left;
75 		_req_height = rect.bottom - rect.top;
76 	}
77 
78 	_gui_widget.queue_resize ();
79 }
80 
81 void
view_size_request(GtkRequisition * requisition)82 VST3HWNDPluginUI::view_size_request (GtkRequisition* requisition)
83 {
84 	requisition->width  = _req_width;
85 	requisition->height = _req_height;
86 }
87 
88 void
view_size_allocate(Gtk::Allocation & allocation)89 VST3HWNDPluginUI::view_size_allocate (Gtk::Allocation& allocation)
90 {
91 	IPlugView* view = _vst3->view ();
92 	if (!view || !_view_realized) {
93 		return;
94 	}
95 	PBD::Unwinder<bool> uw (_resize_in_progress, true);
96 	ViewRect rect;
97 	if (view->getSize (&rect) == kResultOk
98 	    && ! (rect.right - rect.left == allocation.get_width () && rect.bottom - rect.top ==  allocation.get_height ()))
99 	{
100 		rect.right = rect.left + allocation.get_width ();
101 		rect.bottom = rect.top + allocation.get_height ();
102 #if 0
103 		if (view->checkSizeConstraint (&rect) != kResultTrue) {
104 			view->getSize (&rect);
105 		}
106 		allocation.set_width (rect.right - rect.left);
107 		allocation.set_height (rect.bottom - rect.top);
108 #endif
109 		if (view->canResize() == kResultTrue) {
110 			view->onSize (&rect);
111 		}
112 	}
113 }
114 
115 void
resize_callback(int width,int height)116 VST3HWNDPluginUI::resize_callback (int width, int height)
117 {
118 	//printf ("VST3HWNDPluginUI::resize_callback %d x %d\n", width, height);
119 	IPlugView* view = _vst3->view ();
120 	if (!view || _resize_in_progress) {
121 		return;
122 	}
123 	if (view->canResize() == kResultTrue) {
124 		gint xx, yy;
125 		if (gtk_widget_translate_coordinates (
126 		    GTK_WIDGET(_gui_widget.gobj()),
127 		    GTK_WIDGET(get_toplevel()->gobj()),
128 		    0, 0, &xx, &yy))
129 		{
130 			get_window()->resize (width + xx, height + yy);
131 		}
132 	} else {
133 		_req_width  = width;
134 		_req_height = height;
135 		_gui_widget.queue_resize ();
136 	}
137 }
138 
139 bool
on_window_show(const std::string &)140 VST3HWNDPluginUI::on_window_show (const std::string& /*title*/)
141 {
142 	IPlugView* view = _vst3->view ();
143 	if (!view) {
144 		return false;
145 	}
146 
147 	gtk_widget_realize (GTK_WIDGET(_gui_widget.gobj()));
148 	_gui_widget.show_all ();
149 	_gui_widget.queue_resize ();
150 	return true;
151 }
152 
153 void
on_window_hide()154 VST3HWNDPluginUI::on_window_hide ()
155 {
156 	_gui_widget.hide ();
157 }
158 
159 void
grab_focus()160 VST3HWNDPluginUI::grab_focus ()
161 {
162 #if 0
163 	IPlugView* view = _vst3->view ();
164 	if (view) {
165 		view->onFocus (true);
166 	}
167 #endif
168 }
169