From d214e8a02ab5d2e8dbb88b8019915b6246c0530f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 14 Feb 2015 01:40:40 +0000 Subject: Various Windows fixes (patches from Robin Gareus). git-svn-id: http://svn.drobilla.net/lad/trunk/suil@5556 a436a847-0d15-0410-975c-d299462d15a1 --- src/instance.c | 6 ++- src/win_in_gtk2.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 115 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/instance.c b/src/instance.c index e5cf54d..0c27ad7 100644 --- a/src/instance.c +++ b/src/instance.c @@ -292,12 +292,16 @@ suil_instance_free(SuilInstance* instance) instance->descriptor->cleanup(instance->handle); } + dlclose(instance->lib_handle); + // Close libraries and free everything if (instance->wrapper) { +#ifndef _WIN32 + // Never unload modules on windows, causes mysterious segfaults dlclose(instance->wrapper->lib); +#endif free(instance->wrapper); } - dlclose(instance->lib_handle); free(instance); } } diff --git a/src/win_in_gtk2.cpp b/src/win_in_gtk2.cpp index a4466ce..e702d85 100644 --- a/src/win_in_gtk2.cpp +++ b/src/win_in_gtk2.cpp @@ -21,6 +21,11 @@ #include "./suil_internal.h" +#ifdef HAVE_LV2_1_6_0 +# include "lv2/lv2plug.in/ns/ext/options/options.h" +# include "lv2/lv2plug.in/ns/ext/urid/urid.h" +#endif + extern "C" { #define SUIL_TYPE_WIN_WRAPPER (suil_win_wrapper_get_type()) @@ -33,6 +38,12 @@ struct _SuilWinWrapper { GtkDrawingArea area; SuilWrapper* wrapper; SuilInstance* instance; + GdkWindow* flt_win; +#ifdef HAVE_LV2_1_6_0 + const LV2UI_Idle_Interface* idle_iface; + guint idle_id; + guint idle_ms; +#endif }; struct _SuilWinWrapperClass { @@ -49,23 +60,64 @@ suil_win_wrapper_finalize(GObject* gobject) SuilWinWrapper* const self = SUIL_WIN_WRAPPER(gobject); self->wrapper->impl = NULL; + self->instance = NULL; G_OBJECT_CLASS(suil_win_wrapper_parent_class)->finalize(gobject); } +static void +suil_win_size_allocate(GtkWidget* widget, GtkAllocation* allocation) +{ + SuilWinWrapper* const self = SUIL_WIN_WRAPPER(widget); + g_return_if_fail(self != NULL); + + widget->allocation = *allocation; + if (gtk_widget_get_realized(widget)) { + gdk_window_move_resize(widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + + RECT wr = { 0, 0, (long)allocation->width, (long)allocation->height }; + AdjustWindowRectEx(&wr, WS_CHILD, FALSE, WS_EX_TOPMOST); + + SetWindowPos((HWND)self->instance->ui_widget, HWND_NOTOPMOST, + 0, 0, wr.right - wr.left, wr.bottom - wr.top, + SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + UpdateWindow((HWND)self->instance->ui_widget); + PostMessage((HWND)self->instance->ui_widget, WM_PAINT, 0, 0); + } +} + static void suil_win_wrapper_class_init(SuilWinWrapperClass* klass) { - GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GtkWidgetClass* const widget_class = (GtkWidgetClass*)(klass); - gobject_class->finalize = suil_win_wrapper_finalize; + widget_class->size_allocate = suil_win_size_allocate; + gobject_class->finalize = suil_win_wrapper_finalize; } static void suil_win_wrapper_init(SuilWinWrapper* self) { - self->instance = NULL; + self->instance = NULL; + self->flt_win = NULL; +#ifdef HAVE_LV2_1_6_0 + self->idle_iface = NULL; + self->idle_ms = 1000 / 30; // 30 Hz default +#endif +} + +#ifdef HAVE_LV2_1_6_0 +static gboolean +suil_win_wrapper_idle(void* data) +{ + SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(data); + wrap->idle_iface->idle(wrap->instance->handle); + return TRUE; // Continue calling } +#endif static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) @@ -84,16 +136,18 @@ wrapper_wrap(SuilWrapper* wrapper, wrap->wrapper = wrapper; wrap->instance = instance; - return 0; -} - -static void -wrapper_free(SuilWrapper* wrapper) -{ - if (wrapper->impl) { - SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(wrapper->impl); - gtk_object_destroy(GTK_OBJECT(wrap)); +#ifdef HAVE_LV2_1_6_0 + const LV2UI_Idle_Interface* idle_iface = NULL; + if (instance->descriptor->extension_data) { + idle_iface = (const LV2UI_Idle_Interface*) + instance->descriptor->extension_data(LV2_UI__idleInterface); } + if (idle_iface) { + wrap->idle_iface = idle_iface; + wrap->idle_id = g_timeout_add (wrap->idle_ms, suil_win_wrapper_idle, wrap); + } +#endif + return 0; } static GdkFilterReturn @@ -109,6 +163,22 @@ event_filter(GdkXEvent* xevent, GdkEvent* event, gpointer data) return GDK_FILTER_CONTINUE; } +static void +wrapper_free(SuilWrapper* wrapper) +{ + if (wrapper->impl) { + SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(wrapper->impl); +#ifdef HAVE_LV2_1_6_0 + if (wrap->idle_id) { + g_source_remove(wrap->idle_id); + wrap->idle_id = 0; + } +#endif + gdk_window_remove_filter(wrap->flt_win, event_filter, wrapper->impl); + gtk_object_destroy(GTK_OBJECT(wrap)); + } +} + SUIL_LIB_EXPORT SuilWrapper* suil_wrapper_new(SuilHost* host, @@ -149,9 +219,9 @@ suil_wrapper_new(SuilHost* host, gtk_widget_realize(GTK_WIDGET(wrap)); GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap)); - GdkWindow* parent_window = gtk_widget_get_window(parent); - gdk_window_add_filter(parent_window, event_filter, wrap); - gdk_window_add_filter(window, event_filter, wrap); + + wrap->flt_win = gtk_widget_get_window(parent); + gdk_window_add_filter(wrap->flt_win, event_filter, wrap); suil_add_feature(features, &n_features, LV2_UI__parent, GDK_WINDOW_HWND(window)); @@ -159,6 +229,31 @@ suil_wrapper_new(SuilHost* host, suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); +#ifdef HAVE_LV2_1_6_0 + suil_add_feature(features, &n_features, LV2_UI__idleInterface, NULL); + + // Scan for URID map and options + LV2_URID_Map* map = NULL; + LV2_Options_Option* options = NULL; + for (LV2_Feature** f = *features; *f && (!map || !options); ++f) { + if (!strcmp((*f)->URI, LV2_OPTIONS__options)) { + options = (LV2_Options_Option *)(*f)->data; + } else if (!strcmp((*f)->URI, LV2_URID__map)) { + map = (LV2_URID_Map *)(*f)->data; + } + } + + if (map && options) { + // Set UI update rate if given + LV2_URID ui_updateRate = map->map(map->handle, LV2_UI__updateRate); + for (LV2_Options_Option* o = options; o->key; ++o) { + if (o->key == ui_updateRate) { + wrap->idle_ms = 1000.0f / *(const float*)o->value; + break; + } + } + } +#endif return wrapper; } -- cgit v1.2.1