diff options
author | David Robillard <d@drobilla.net> | 2020-12-26 19:24:15 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-12-31 13:37:55 +0100 |
commit | 9f5fb1cf1b3df6a86d6571886169455d9d9ec393 (patch) | |
tree | 0e7515a3d319eb06b5450e3482055fc269503f1c | |
parent | 1fece68f494158fff81fd3dca5a928860d5a6376 (diff) | |
download | suil-9f5fb1cf1b3df6a86d6571886169455d9d9ec393.tar.gz suil-9f5fb1cf1b3df6a86d6571886169455d9d9ec393.tar.bz2 suil-9f5fb1cf1b3df6a86d6571886169455d9d9ec393.zip |
Format all code with clang-format
-rw-r--r-- | include/suil/suil.h | 79 | ||||
-rw-r--r-- | src/cocoa_in_gtk2.mm | 587 | ||||
-rw-r--r-- | src/cocoa_in_qt5.mm | 178 | ||||
-rw-r--r-- | src/dylib.h | 28 | ||||
-rw-r--r-- | src/gtk2_in_qt4.cpp | 142 | ||||
-rw-r--r-- | src/gtk2_in_qt5.cpp | 148 | ||||
-rw-r--r-- | src/host.c | 70 | ||||
-rw-r--r-- | src/instance.c | 579 | ||||
-rw-r--r-- | src/qt4_in_gtk2.cpp | 119 | ||||
-rw-r--r-- | src/qt5_in_gtk.cpp | 239 | ||||
-rw-r--r-- | src/suil_internal.h | 134 | ||||
-rw-r--r-- | src/win_in_gtk2.cpp | 321 | ||||
-rw-r--r-- | src/x11.c | 4 | ||||
-rw-r--r-- | src/x11_in_gtk2.c | 822 | ||||
-rw-r--r-- | src/x11_in_gtk3.c | 640 | ||||
-rw-r--r-- | src/x11_in_qt4.cpp | 157 | ||||
-rw-r--r-- | src/x11_in_qt5.cpp | 283 |
17 files changed, 2280 insertions, 2250 deletions
diff --git a/include/suil/suil.h b/include/suil/suil.h index 7be89bd..f838512 100644 --- a/include/suil/suil.h +++ b/include/suil/suil.h @@ -27,21 +27,21 @@ #include <stdint.h> #ifdef _WIN32 -# define SUIL_LIB_IMPORT __declspec(dllimport) -# define SUIL_LIB_EXPORT __declspec(dllexport) +# define SUIL_LIB_IMPORT __declspec(dllimport) +# define SUIL_LIB_EXPORT __declspec(dllexport) #else -# define SUIL_LIB_IMPORT __attribute__((visibility("default"))) -# define SUIL_LIB_EXPORT __attribute__((visibility("default"))) +# define SUIL_LIB_IMPORT __attribute__((visibility("default"))) +# define SUIL_LIB_EXPORT __attribute__((visibility("default"))) #endif #ifdef SUIL_SHARED -# ifdef SUIL_INTERNAL -# define SUIL_API SUIL_LIB_EXPORT -# else -# define SUIL_API SUIL_LIB_IMPORT -# endif +# ifdef SUIL_INTERNAL +# define SUIL_API SUIL_LIB_EXPORT +# else +# define SUIL_API SUIL_LIB_IMPORT +# endif #else -# define SUIL_API +# define SUIL_API #endif #ifdef __cplusplus @@ -82,42 +82,40 @@ typedef void* SuilWidget; typedef void* SuilController; /** Function to write/send a value to a port. */ -typedef void (*SuilPortWriteFunc)( - SuilController controller, - uint32_t port_index, - uint32_t buffer_size, - uint32_t protocol, - void const* buffer); +typedef void (*SuilPortWriteFunc)( // + SuilController controller, + uint32_t port_index, + uint32_t buffer_size, + uint32_t protocol, + void const* buffer); /** Function to return the index for a port by symbol. */ -typedef uint32_t (*SuilPortIndexFunc)( - SuilController controller, - const char* port_symbol); +typedef uint32_t (*SuilPortIndexFunc)( // + SuilController controller, + const char* port_symbol); /** Function to subscribe to notifications for a port. */ -typedef uint32_t (*SuilPortSubscribeFunc)( - SuilController controller, - uint32_t port_index, - uint32_t protocol, - const LV2_Feature* const* features); +typedef uint32_t (*SuilPortSubscribeFunc)( // + SuilController controller, + uint32_t port_index, + uint32_t protocol, + const LV2_Feature* const* features); /** Function to unsubscribe from notifications for a port. */ -typedef uint32_t (*SuilPortUnsubscribeFunc)( - SuilController controller, - uint32_t port_index, - uint32_t protocol, - const LV2_Feature* const* features); +typedef uint32_t (*SuilPortUnsubscribeFunc)( // + SuilController controller, + uint32_t port_index, + uint32_t protocol, + const LV2_Feature* const* features); /** Function called when a control is grabbed or released. */ -typedef void (*SuilTouchFunc)( - SuilController controller, - uint32_t port_index, - bool grabbed); +typedef void (*SuilTouchFunc)( // + SuilController controller, + uint32_t port_index, + bool grabbed); /** Initialization argument. */ -typedef enum { - SUIL_ARG_NONE -} SuilArg; +typedef enum { SUIL_ARG_NONE } SuilArg; /** Initialize suil. @@ -152,8 +150,7 @@ suil_host_new(SuilPortWriteFunc write_func, */ SUIL_API void -suil_host_set_touch_func(SuilHost* host, - SuilTouchFunc touch_func); +suil_host_set_touch_func(SuilHost* host, SuilTouchFunc touch_func); /** Free `host`. @@ -173,8 +170,7 @@ suil_host_free(SuilHost* host); */ SUIL_API unsigned -suil_ui_supported(const char* host_type_uri, - const char* ui_type_uri); +suil_ui_supported(const char* host_type_uri, const char* ui_type_uri); /** Instantiate a UI for an LV2 plugin. @@ -276,8 +272,7 @@ suil_instance_port_event(SuilInstance* instance, */ SUIL_API const void* -suil_instance_extension_data(SuilInstance* instance, - const char* uri); +suil_instance_extension_data(SuilInstance* instance, const char* uri); /** @} diff --git a/src/cocoa_in_gtk2.mm b/src/cocoa_in_gtk2.mm index 9c6314d..2052bc0 100644 --- a/src/cocoa_in_gtk2.mm +++ b/src/cocoa_in_gtk2.mm @@ -20,349 +20,357 @@ #include "lv2/options/options.h" #include "lv2/urid/urid.h" -#include <gtk/gtk.h> #include <gdk/gdkquartz.h> +#include <gtk/gtk.h> #include <string.h> #ifndef MAC_OS_X_VERSION_10_12 -#define MAC_OS_X_VERSION_10_12 101200 +# define MAC_OS_X_VERSION_10_12 101200 #endif #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 -#define NSEventTypeFlagsChanged NSFlagsChanged -#define NSEventTypeLeftMouseDown NSLeftMouseDown -#define NSEventTypeLeftMouseDragged NSLeftMouseDragged -#define NSEventTypeLeftMouseUp NSLeftMouseUp -#define NSEventTypeMouseEntered NSMouseEntered -#define NSEventTypeMouseExited NSMouseExited -#define NSEventTypeMouseMoved NSMouseMoved -#define NSEventTypeRightMouseDown NSRightMouseDown -#define NSEventTypeRightMouseUp NSRightMouseUp -#define NSEventTypeScrollWheel NSScrollWheel +# define NSEventTypeFlagsChanged NSFlagsChanged +# define NSEventTypeLeftMouseDown NSLeftMouseDown +# define NSEventTypeLeftMouseDragged NSLeftMouseDragged +# define NSEventTypeLeftMouseUp NSLeftMouseUp +# define NSEventTypeMouseEntered NSMouseEntered +# define NSEventTypeMouseExited NSMouseExited +# define NSEventTypeMouseMoved NSMouseMoved +# define NSEventTypeRightMouseDown NSRightMouseDown +# define NSEventTypeRightMouseUp NSRightMouseUp +# define NSEventTypeScrollWheel NSScrollWheel #endif extern "C" { #define SUIL_TYPE_COCOA_WRAPPER (suil_cocoa_wrapper_get_type()) -#define SUIL_COCOA_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_COCOA_WRAPPER, SuilCocoaWrapper)) +#define SUIL_COCOA_WRAPPER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_COCOA_WRAPPER, SuilCocoaWrapper)) typedef struct _SuilCocoaWrapper SuilCocoaWrapper; typedef struct _SuilCocoaWrapperClass SuilCocoaWrapperClass; struct _SuilCocoaWrapper { - GtkWidget widget; - SuilWrapper* wrapper; - SuilInstance* instance; - - GdkWindow* flt_win; - bool custom_size; - bool mapped; - int req_width; - int req_height; - int alo_width; - int alo_height; - - const LV2UI_Idle_Interface* idle_iface; - guint idle_id; - guint idle_ms; + GtkWidget widget; + SuilWrapper* wrapper; + SuilInstance* instance; + + GdkWindow* flt_win; + bool custom_size; + bool mapped; + int req_width; + int req_height; + int alo_width; + int alo_height; + + const LV2UI_Idle_Interface* idle_iface; + guint idle_id; + guint idle_ms; }; struct _SuilCocoaWrapperClass { - GtkWidgetClass parent_class; + GtkWidgetClass parent_class; }; -GType suil_cocoa_wrapper_get_type(void); // Accessor for SUIL_TYPE_COCOA_WRAPPER +GType +suil_cocoa_wrapper_get_type(void); // Accessor for SUIL_TYPE_COCOA_WRAPPER G_DEFINE_TYPE(SuilCocoaWrapper, suil_cocoa_wrapper, GTK_TYPE_WIDGET) static void suil_cocoa_wrapper_finalize(GObject* gobject) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(gobject); + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(gobject); - self->wrapper->impl = NULL; + self->wrapper->impl = NULL; - G_OBJECT_CLASS(suil_cocoa_wrapper_parent_class)->finalize(gobject); + G_OBJECT_CLASS(suil_cocoa_wrapper_parent_class)->finalize(gobject); } static void suil_cocoa_realize(GtkWidget* widget) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - g_return_if_fail(self != NULL); - - GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); - - GdkWindowAttr attrs; - attrs.x = widget->allocation.x; - attrs.y = widget->allocation.y; - attrs.width = widget->allocation.width; - attrs.height = widget->allocation.height; - attrs.wclass = GDK_INPUT_OUTPUT; - attrs.window_type = GDK_WINDOW_CHILD; - attrs.visual = gtk_widget_get_visual(widget); - attrs.colormap = gtk_widget_get_colormap(widget); - attrs.event_mask = gtk_widget_get_events(widget) | - GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | - GDK_POINTER_MOTION_HINT_MASK; - - widget->window = gdk_window_new( - widget->parent->window, - &attrs, - GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); - - widget->style = gtk_style_attach(widget->style, widget->window); - - gdk_window_set_user_data(widget->window, widget); - gtk_style_set_background(widget->style, widget->window, GTK_STATE_ACTIVE); - gtk_widget_queue_resize(widget); + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + g_return_if_fail(self != NULL); + + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); + + GdkWindowAttr attrs; + attrs.x = widget->allocation.x; + attrs.y = widget->allocation.y; + attrs.width = widget->allocation.width; + attrs.height = widget->allocation.height; + attrs.wclass = GDK_INPUT_OUTPUT; + attrs.window_type = GDK_WINDOW_CHILD; + attrs.visual = gtk_widget_get_visual(widget); + attrs.colormap = gtk_widget_get_colormap(widget); + attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK; + + widget->window = + gdk_window_new(widget->parent->window, + &attrs, + GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); + + widget->style = gtk_style_attach(widget->style, widget->window); + + gdk_window_set_user_data(widget->window, widget); + gtk_style_set_background(widget->style, widget->window, GTK_STATE_ACTIVE); + gtk_widget_queue_resize(widget); } static void suil_cocoa_size_request(GtkWidget* widget, GtkRequisition* requisition) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - if (self->custom_size) { - requisition->width = self->req_width; - requisition->height = self->req_height; - } else { - NSView* view = (NSView*)self->instance->ui_widget; - NSRect frame = [view frame]; - requisition->width = CGRectGetWidth(NSRectToCGRect(frame)); - requisition->height = CGRectGetHeight(NSRectToCGRect(frame)); - } + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + if (self->custom_size) { + requisition->width = self->req_width; + requisition->height = self->req_height; + } else { + NSView* view = (NSView*)self->instance->ui_widget; + NSRect frame = [view frame]; + requisition->width = CGRectGetWidth(NSRectToCGRect(frame)); + requisition->height = CGRectGetHeight(NSRectToCGRect(frame)); + } } static void suil_cocoa_size_allocate(GtkWidget* widget, GtkAllocation* allocation) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - self->alo_width = allocation->width; - self->alo_height = allocation->height; + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + self->alo_width = allocation->width; + self->alo_height = allocation->height; - if (!self->mapped) { - return; - } + if (!self->mapped) { + return; + } - gint xx, yy; - gtk_widget_translate_coordinates( - gtk_widget_get_parent(widget), widget, 0, 0, &xx, &yy); + gint xx, yy; + gtk_widget_translate_coordinates( + gtk_widget_get_parent(widget), widget, 0, 0, &xx, &yy); - NSView* view = (NSView*)self->instance->ui_widget; - [view setFrame:NSMakeRect(xx, yy, self->alo_width, self->alo_height)]; + NSView* view = (NSView*)self->instance->ui_widget; + [view setFrame:NSMakeRect(xx, yy, self->alo_width, self->alo_height)]; } static void suil_cocoa_map(GtkWidget* widget) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - self->mapped = true; + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + self->mapped = true; - if (self->alo_width == 0 || self->alo_height ==0) { - return; - } + if (self->alo_width == 0 || self->alo_height == 0) { + return; + } - gint xx, yy; - gtk_widget_translate_coordinates( - gtk_widget_get_parent(widget), widget, 0, 0, &xx, &yy); + gint xx, yy; + gtk_widget_translate_coordinates( + gtk_widget_get_parent(widget), widget, 0, 0, &xx, &yy); - NSView* view = (NSView*)self->instance->ui_widget; - [view setHidden:NO]; - [view setFrame:NSMakeRect(xx, yy, self->alo_width, self->alo_height)]; + NSView* view = (NSView*)self->instance->ui_widget; + [view setHidden:NO]; + [view setFrame:NSMakeRect(xx, yy, self->alo_width, self->alo_height)]; } static void suil_cocoa_unmap(GtkWidget* widget) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - NSView* view = (NSView*)self->instance->ui_widget; + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + NSView* view = (NSView*)self->instance->ui_widget; - self->mapped = false; - [view setHidden:YES]; + self->mapped = false; + [view setHidden:YES]; } static gboolean suil_cocoa_key_press(GtkWidget* widget, GdkEventKey* event) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - if (!self->instance || !self->wrapper || !self->wrapper->impl) { - return FALSE; - } - NSEvent* nsevent = gdk_quartz_event_get_nsevent((GdkEvent*)event); - NSView* view = (NSView*)self->instance->ui_widget; - [view keyDown:nsevent]; - return TRUE; + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + if (!self->instance || !self->wrapper || !self->wrapper->impl) { + return FALSE; + } + + NSEvent* nsevent = gdk_quartz_event_get_nsevent((GdkEvent*)event); + NSView* view = (NSView*)self->instance->ui_widget; + [view keyDown:nsevent]; + return TRUE; } static gboolean suil_cocoa_key_release(GtkWidget* widget, GdkEventKey* event) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - if (!self->instance || !self->wrapper || !self->wrapper->impl) { - return FALSE; - } - NSEvent* nsevent = gdk_quartz_event_get_nsevent((GdkEvent*)event); - NSView* view = (NSView*)self->instance->ui_widget; - [view keyUp:nsevent]; - return TRUE; + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + if (!self->instance || !self->wrapper || !self->wrapper->impl) { + return FALSE; + } + + NSEvent* nsevent = gdk_quartz_event_get_nsevent((GdkEvent*)event); + NSView* view = (NSView*)self->instance->ui_widget; + [view keyUp:nsevent]; + return TRUE; } static gboolean suil_cocoa_expose(GtkWidget* widget, GdkEventExpose* event) { - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - NSView* view = (NSView*)self->instance->ui_widget; - [view drawRect:NSMakeRect(event->area.x, - event->area.y, - event->area.width, - event->area.height)]; - return TRUE; + SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); + NSView* view = (NSView*)self->instance->ui_widget; + [view drawRect:NSMakeRect(event->area.x, + event->area.y, + event->area.width, + event->area.height)]; + return TRUE; } static void suil_cocoa_wrapper_class_init(SuilCocoaWrapperClass* klass) { - GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - GtkWidgetClass* const widget_class = (GtkWidgetClass*)(klass); - - gobject_class->finalize = suil_cocoa_wrapper_finalize; - - widget_class->realize = suil_cocoa_realize; - widget_class->expose_event = suil_cocoa_expose; - widget_class->size_request = suil_cocoa_size_request; - widget_class->size_allocate = suil_cocoa_size_allocate; - widget_class->map = suil_cocoa_map; - widget_class->unmap = suil_cocoa_unmap; - widget_class->key_press_event = suil_cocoa_key_press; - widget_class->key_release_event = suil_cocoa_key_release; + GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GtkWidgetClass* const widget_class = (GtkWidgetClass*)(klass); + + gobject_class->finalize = suil_cocoa_wrapper_finalize; + + widget_class->realize = suil_cocoa_realize; + widget_class->expose_event = suil_cocoa_expose; + widget_class->size_request = suil_cocoa_size_request; + widget_class->size_allocate = suil_cocoa_size_allocate; + widget_class->map = suil_cocoa_map; + widget_class->unmap = suil_cocoa_unmap; + widget_class->key_press_event = suil_cocoa_key_press; + widget_class->key_release_event = suil_cocoa_key_release; } static void suil_cocoa_wrapper_init(SuilCocoaWrapper* self) { - self->wrapper = NULL; - self->instance = NULL; - self->flt_win = NULL; - self->custom_size = false; - self->mapped = false; - self->req_width = self->req_height = 0; - self->alo_width = self->alo_height = 0; - self->idle_iface = NULL; - self->idle_ms = 1000 / 30; // 30 Hz default + self->wrapper = NULL; + self->instance = NULL; + self->flt_win = NULL; + self->custom_size = false; + self->mapped = false; + self->req_width = 0; + self->req_height = 0; + self->alo_width = 0; + self->alo_height = 0; + self->idle_iface = NULL; + self->idle_ms = 1000 / 30; // 30 Hz default } static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(handle); - wrap->req_width = width; - wrap->req_height = height; - wrap->custom_size = true; - gtk_widget_queue_resize(GTK_WIDGET(handle)); - return 0; + SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(handle); + + wrap->req_width = width; + wrap->req_height = height; + wrap->custom_size = true; + + gtk_widget_queue_resize(GTK_WIDGET(handle)); + + return 0; } static gboolean suil_cocoa_wrapper_idle(void* data) { - SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(data); - wrap->idle_iface->idle(wrap->instance->handle); - return TRUE; // Continue calling + SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(data); + wrap->idle_iface->idle(wrap->instance->handle); + return TRUE; // Continue calling } static GdkFilterReturn event_filter(GdkXEvent* xevent, GdkEvent* event, gpointer data) { - SuilCocoaWrapper* wrap = (SuilCocoaWrapper*)data; - if (!wrap->instance || !wrap->wrapper || !wrap->wrapper->impl) { - return GDK_FILTER_CONTINUE; - } - - NSEvent* nsevent = (NSEvent*)xevent; - NSView* view = (NSView*)wrap->instance->ui_widget; - if (view && nsevent) { - switch([nsevent type]) { - case NSEventTypeFlagsChanged: - [view flagsChanged:nsevent]; - return GDK_FILTER_REMOVE; - case NSEventTypeMouseEntered: - [view mouseEntered:nsevent]; - return GDK_FILTER_REMOVE; - case NSEventTypeMouseExited: - [view mouseExited:nsevent]; - return GDK_FILTER_REMOVE; - - /* Explicitly pass though mouse events. Needed for mouse-drags leaving - the window, and mouse-up after that. */ - case NSEventTypeMouseMoved: - [view mouseMoved:nsevent]; - break; - case NSEventTypeLeftMouseDragged: - [view mouseDragged:nsevent]; - break; - case NSEventTypeLeftMouseDown: - [view mouseDown:nsevent]; - break; - case NSEventTypeLeftMouseUp: - [view mouseUp:nsevent]; - break; - case NSEventTypeRightMouseDown: - [view rightMouseDown:nsevent]; - break; - case NSEventTypeRightMouseUp: - [view rightMouseUp:nsevent]; - break; - case NSEventTypeScrollWheel: - [view scrollWheel:nsevent]; - break; - default: - break; - } - } - return GDK_FILTER_CONTINUE; + SuilCocoaWrapper* wrap = (SuilCocoaWrapper*)data; + if (!wrap->instance || !wrap->wrapper || !wrap->wrapper->impl) { + return GDK_FILTER_CONTINUE; + } + + NSEvent* nsevent = (NSEvent*)xevent; + NSView* view = (NSView*)wrap->instance->ui_widget; + if (view && nsevent) { + switch ([nsevent type]) { + case NSEventTypeFlagsChanged: + [view flagsChanged:nsevent]; + return GDK_FILTER_REMOVE; + case NSEventTypeMouseEntered: + [view mouseEntered:nsevent]; + return GDK_FILTER_REMOVE; + case NSEventTypeMouseExited: + [view mouseExited:nsevent]; + return GDK_FILTER_REMOVE; + + /* Explicitly pass though mouse events. Needed for mouse-drags leaving + the window, and mouse-up after that. */ + case NSEventTypeMouseMoved: + [view mouseMoved:nsevent]; + break; + case NSEventTypeLeftMouseDragged: + [view mouseDragged:nsevent]; + break; + case NSEventTypeLeftMouseDown: + [view mouseDown:nsevent]; + break; + case NSEventTypeLeftMouseUp: + [view mouseUp:nsevent]; + break; + case NSEventTypeRightMouseDown: + [view rightMouseDown:nsevent]; + break; + case NSEventTypeRightMouseUp: + [view rightMouseUp:nsevent]; + break; + case NSEventTypeScrollWheel: + [view scrollWheel:nsevent]; + break; + default: + break; + } + } + return GDK_FILTER_CONTINUE; } static int wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(wrapper->impl); - - instance->host_widget = GTK_WIDGET(wrap); - wrap->wrapper = wrapper; - wrap->instance = instance; - - 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_cocoa_wrapper_idle, wrap); - } - - return 0; + SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(wrapper->impl); + + instance->host_widget = GTK_WIDGET(wrap); + wrap->wrapper = wrapper; + wrap->instance = instance; + + 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_cocoa_wrapper_idle, wrap); + } + + return 0; } static void wrapper_free(SuilWrapper* wrapper) { - if (wrapper->impl) { - SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(wrapper->impl); - if (wrap->idle_id) { - g_source_remove(wrap->idle_id); - wrap->idle_id = 0; - } - - gdk_window_remove_filter(wrap->flt_win, event_filter, wrapper->impl); - gtk_object_destroy(GTK_OBJECT(wrap)); - } + if (wrapper->impl) { + SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER(wrapper->impl); + if (wrap->idle_id) { + g_source_remove(wrap->idle_id); + wrap->idle_id = 0; + } + + 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, @@ -371,67 +379,66 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - GtkWidget* parent = NULL; - for (unsigned i = 0; i < n_features; ++i) { - if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { - parent = (GtkWidget*)(*features)[i]->data; - } - } - - if (!GTK_CONTAINER(parent)) { - SUIL_ERRORF("No GtkContainer parent given for %s UI\n", - ui_type_uri); - return NULL; - } - - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - - SuilCocoaWrapper* const wrap = SUIL_COCOA_WRAPPER( - g_object_new(SUIL_TYPE_COCOA_WRAPPER, NULL)); - - wrapper->impl = wrap; - wrapper->resize.handle = wrap; - wrapper->resize.ui_resize = wrapper_resize; - - gtk_container_add(GTK_CONTAINER(parent), GTK_WIDGET(wrap)); - gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); - gtk_widget_realize(GTK_WIDGET(wrap)); - - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap)); - wrap->flt_win = gtk_widget_get_window(parent); - gdk_window_add_filter(wrap->flt_win, event_filter, wrap); - - NSView* parent_view = gdk_quartz_window_get_nsview(window); - suil_add_feature(features, &n_features, LV2_UI__parent, parent_view); - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - 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; - } - } - } - - return wrapper; + GtkWidget* parent = NULL; + for (unsigned i = 0; i < n_features; ++i) { + if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { + parent = (GtkWidget*)(*features)[i]->data; + } + } + + if (!GTK_CONTAINER(parent)) { + SUIL_ERRORF("No GtkContainer parent given for %s UI\n", ui_type_uri); + return NULL; + } + + SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + + SuilCocoaWrapper* const wrap = + SUIL_COCOA_WRAPPER(g_object_new(SUIL_TYPE_COCOA_WRAPPER, NULL)); + + wrapper->impl = wrap; + wrapper->resize.handle = wrap; + wrapper->resize.ui_resize = wrapper_resize; + + gtk_container_add(GTK_CONTAINER(parent), GTK_WIDGET(wrap)); + gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); + gtk_widget_realize(GTK_WIDGET(wrap)); + + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap)); + wrap->flt_win = gtk_widget_get_window(parent); + gdk_window_add_filter(wrap->flt_win, event_filter, wrap); + + NSView* parent_view = gdk_quartz_window_get_nsview(window); + suil_add_feature(features, &n_features, LV2_UI__parent, parent_view); + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + 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; + } + } + } + + return wrapper; } -} // extern "C" +} // extern "C" diff --git a/src/cocoa_in_qt5.mm b/src/cocoa_in_qt5.mm index 185f4fe..8c8c219 100644 --- a/src/cocoa_in_qt5.mm +++ b/src/cocoa_in_qt5.mm @@ -29,95 +29,100 @@ extern "C" { typedef struct { - QWidget* host_widget; - QWidget* parent; + QWidget* host_widget; + QWidget* parent; } SuilCocoaInQt5Wrapper; class SuilQCocoaWidget : public QMacCocoaViewContainer { public: - SuilQCocoaWidget(NSView* view, QWidget* parent) - : QMacCocoaViewContainer(view, parent) - , _instance(NULL) - , _idle_iface(NULL) - , _ui_timer(0) - { - } - - void start_idle(SuilInstance* instance, - const LV2UI_Idle_Interface* idle_iface) { - _instance = instance; - _idle_iface = idle_iface; - NSView* view = (NSView*)instance->ui_widget; - setCocoaView((NSView*)instance->ui_widget); - setMinimumWidth([view fittingSize].width); - setMinimumHeight([view fittingSize].height); - if (_idle_iface && _ui_timer == 0) { - _ui_timer = this->startTimer(30); - } - } + SuilQCocoaWidget(NSView* view, QWidget* parent) + : QMacCocoaViewContainer(view, parent) + , _instance(NULL) + , _idle_iface(NULL) + , _ui_timer(0) + {} + + void start_idle(SuilInstance* instance, + const LV2UI_Idle_Interface* idle_iface) + { + _instance = instance; + _idle_iface = idle_iface; + + NSView* view = (NSView*)instance->ui_widget; + setCocoaView((NSView*)instance->ui_widget); + setMinimumWidth([view fittingSize].width); + setMinimumHeight([view fittingSize].height); + + if (_idle_iface && _ui_timer == 0) { + _ui_timer = this->startTimer(30); + } + } protected: - void timerEvent(QTimerEvent* event) { - if (event->timerId() == _ui_timer && _idle_iface) { - _idle_iface->idle(_instance->handle); - } - QWidget::timerEvent(event); - } - - void closeEvent(QCloseEvent* event) { - if (_ui_timer && _idle_iface) { - this->killTimer(_ui_timer); - _ui_timer = 0; - } - QWidget::closeEvent(event); - } + void timerEvent(QTimerEvent* event) + { + if (event->timerId() == _ui_timer && _idle_iface) { + _idle_iface->idle(_instance->handle); + } + + QWidget::timerEvent(event); + } + + void closeEvent(QCloseEvent* event) + { + if (_ui_timer && _idle_iface) { + this->killTimer(_ui_timer); + _ui_timer = 0; + } + + QWidget::closeEvent(event); + } private: - SuilInstance* _instance; - const LV2UI_Idle_Interface* _idle_iface; - int _ui_timer; + SuilInstance* _instance; + const LV2UI_Idle_Interface* _idle_iface; + int _ui_timer; }; static void wrapper_free(SuilWrapper* wrapper) { - SuilCocoaInQt5Wrapper* impl = (SuilCocoaInQt5Wrapper*)wrapper->impl; + SuilCocoaInQt5Wrapper* impl = (SuilCocoaInQt5Wrapper*)wrapper->impl; - if (impl->host_widget) { - delete impl->host_widget; - } + if (impl->host_widget) { + delete impl->host_widget; + } - free(impl); + free(impl); } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilCocoaInQt5Wrapper* const impl = (SuilCocoaInQt5Wrapper*)wrapper->impl; - SuilQCocoaWidget* const ew = (SuilQCocoaWidget*)impl->parent; + SuilCocoaInQt5Wrapper* const impl = (SuilCocoaInQt5Wrapper*)wrapper->impl; + SuilQCocoaWidget* const ew = (SuilQCocoaWidget*)impl->parent; - if (instance->descriptor->extension_data) { - const LV2UI_Idle_Interface* idle_iface - = (const LV2UI_Idle_Interface*) - instance->descriptor->extension_data(LV2_UI__idleInterface); - ew->start_idle(instance, idle_iface); - } + if (instance->descriptor->extension_data) { + const LV2UI_Idle_Interface* idle_iface = + (const LV2UI_Idle_Interface*)instance->descriptor->extension_data( + LV2_UI__idleInterface); + ew->start_idle(instance, idle_iface); + } - impl->host_widget = ew; + impl->host_widget = ew; - instance->host_widget = impl->host_widget; + instance->host_widget = impl->host_widget; - return 0; + return 0; } static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - SuilQCocoaWidget* const ew = (SuilQCocoaWidget*)handle; - ew->resize(width, height); - return 0; + SuilQCocoaWidget* const ew = (SuilQCocoaWidget*)handle; + ew->resize(width, height); + return 0; } SUIL_LIB_EXPORT @@ -128,39 +133,40 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - QWidget* parent = NULL; - for (unsigned i = 0; i < n_features; ++i) { - if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { - parent = (QWidget*)(*features)[i]->data; - } - } + QWidget* parent = NULL; + for (unsigned i = 0; i < n_features; ++i) { + if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { + parent = (QWidget*)(*features)[i]->data; + } + } + + if (!parent) { + SUIL_ERRORF("No QWidget parent given for %s UI\n", ui_type_uri); + return NULL; + } - if (!parent) { - SUIL_ERRORF("No QWidget parent given for %s UI\n", ui_type_uri); - return NULL; - } + SuilCocoaInQt5Wrapper* const impl = + (SuilCocoaInQt5Wrapper*)calloc(1, sizeof(SuilCocoaInQt5Wrapper)); - SuilCocoaInQt5Wrapper* const impl = (SuilCocoaInQt5Wrapper*) - calloc(1, sizeof(SuilCocoaInQt5Wrapper)); + SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); - SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - NSView* view = [NSView new]; + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; - SuilQCocoaWidget* const ew = new SuilQCocoaWidget(view, parent); + NSView* view = [NSView new]; + SuilQCocoaWidget* const ew = new SuilQCocoaWidget(view, parent); - impl->parent = ew; + impl->parent = ew; - wrapper->impl = impl; - wrapper->resize.handle = ew; - wrapper->resize.ui_resize = wrapper_resize; + wrapper->impl = impl; + wrapper->resize.handle = ew; + wrapper->resize.ui_resize = wrapper_resize; - suil_add_feature(features, &n_features, LV2_UI__parent, ew->cocoaView()); - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - suil_add_feature(features, &n_features, LV2_UI__idleInterface, NULL); + suil_add_feature(features, &n_features, LV2_UI__parent, ew->cocoaView()); + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + suil_add_feature(features, &n_features, LV2_UI__idleInterface, NULL); - return wrapper; + return wrapper; } -} // extern "C" +} // extern "C" diff --git a/src/dylib.h b/src/dylib.h index 246693c..d4bb827 100644 --- a/src/dylib.h +++ b/src/dylib.h @@ -19,58 +19,58 @@ #ifdef _WIN32 -#include <windows.h> +# include <windows.h> enum DylibFlags { - DYLIB_GLOBAL = 0, - DYLIB_LAZY = 1, - DYLIB_NOW = 2, + DYLIB_GLOBAL = 0, + DYLIB_LAZY = 1, + DYLIB_NOW = 2, }; static inline void* dylib_open(const char* const filename, const int flags) { - return LoadLibrary(filename); + return LoadLibrary(filename); } static inline int dylib_close(void* const handle) { - return !FreeLibrary((HMODULE)handle); + return !FreeLibrary((HMODULE)handle); } static inline const char* dylib_error(void) { - return "Unknown error"; + return "Unknown error"; } #else -#include <dlfcn.h> +# include <dlfcn.h> enum DylibFlags { - DYLIB_GLOBAL = RTLD_GLOBAL, - DYLIB_LAZY = RTLD_LAZY, - DYLIB_NOW = RTLD_NOW, + DYLIB_GLOBAL = RTLD_GLOBAL, + DYLIB_LAZY = RTLD_LAZY, + DYLIB_NOW = RTLD_NOW, }; static inline void* dylib_open(const char* const filename, const int flags) { - return dlopen(filename, flags); + return dlopen(filename, flags); } static inline int dylib_close(void* const handle) { - return dlclose(handle); + return dlclose(handle); } static inline const char* dylib_error(void) { - return dlerror(); + return dlerror(); } #endif diff --git a/src/gtk2_in_qt4.cpp b/src/gtk2_in_qt4.cpp index 2bb3a03..ddf174f 100644 --- a/src/gtk2_in_qt4.cpp +++ b/src/gtk2_in_qt4.cpp @@ -22,17 +22,17 @@ #undef signals -#include <gtk/gtk.h> #include <gdk/gdkx.h> +#include <gtk/gtk.h> extern "C" { using SuilGtk2InQt4Wrapper = _SuilGtk2InQt4Wrapper; struct _SuilGtk2InQt4Wrapper { - QX11EmbedContainer* host_widget; - QWidget* parent; - GtkWidget* plug; + QX11EmbedContainer* host_widget; + QWidget* parent; + GtkWidget* plug; }; static void @@ -40,8 +40,8 @@ on_size_request(GtkWidget* widget, GtkRequisition* requisition, gpointer user_data) { - QX11EmbedContainer* const wrap = (QX11EmbedContainer*)user_data; - wrap->setMinimumSize(requisition->width, requisition->height); + QX11EmbedContainer* const wrap = (QX11EmbedContainer*)user_data; + wrap->setMinimumSize(requisition->width, requisition->height); } static void @@ -49,58 +49,57 @@ on_size_allocate(GtkWidget* widget, GdkRectangle* allocation, gpointer user_data) { - QX11EmbedContainer* const wrap = (QX11EmbedContainer*)user_data; - wrap->resize(allocation->width, allocation->height); + QX11EmbedContainer* const wrap = (QX11EmbedContainer*)user_data; + wrap->resize(allocation->width, allocation->height); } static void wrapper_free(SuilWrapper* wrapper) { - SuilGtk2InQt4Wrapper* impl = (SuilGtk2InQt4Wrapper*)wrapper->impl; + SuilGtk2InQt4Wrapper* impl = (SuilGtk2InQt4Wrapper*)wrapper->impl; - if (impl->plug) { - gtk_widget_destroy(impl->plug); - } + if (impl->plug) { + gtk_widget_destroy(impl->plug); + } - if (impl->host_widget) { - delete impl->host_widget; - } + if (impl->host_widget) { + delete impl->host_widget; + } - free(impl); + free(impl); } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilGtk2InQt4Wrapper* const impl = (SuilGtk2InQt4Wrapper*)wrapper->impl; - QWidget* root = static_cast<QWidget*>(impl->parent); - QX11EmbedContainer* const wrap = new QX11EmbedContainer(root); - GtkWidget* const plug = gtk_plug_new(wrap->winId()); - GtkWidget* const widget = (GtkWidget*)instance->ui_widget; + SuilGtk2InQt4Wrapper* const impl = (SuilGtk2InQt4Wrapper*)wrapper->impl; + QWidget* root = static_cast<QWidget*>(impl->parent); + QX11EmbedContainer* const wrap = new QX11EmbedContainer(root); + GtkWidget* const plug = gtk_plug_new(wrap->winId()); + GtkWidget* const widget = (GtkWidget*)instance->ui_widget; - gtk_container_add(GTK_CONTAINER(plug), widget); - gtk_widget_show_all(plug); + gtk_container_add(GTK_CONTAINER(plug), widget); + gtk_widget_show_all(plug); #ifdef SUIL_OLD_GTK - wrap->resize(widget->allocation.width, widget->allocation.height); + wrap->resize(widget->allocation.width, widget->allocation.height); #else - GtkAllocation alloc; - gtk_widget_get_allocation(widget, &alloc); - wrap->resize(alloc.width, alloc.height); + GtkAllocation alloc; + gtk_widget_get_allocation(widget, &alloc); + wrap->resize(alloc.width, alloc.height); #endif - g_signal_connect( - G_OBJECT(plug), "size-request", G_CALLBACK(on_size_request), wrap); + g_signal_connect( + G_OBJECT(plug), "size-request", G_CALLBACK(on_size_request), wrap); - g_signal_connect( - G_OBJECT(plug), "size-allocate", G_CALLBACK(on_size_allocate), wrap); + g_signal_connect( + G_OBJECT(plug), "size-allocate", G_CALLBACK(on_size_allocate), wrap); - impl->host_widget = wrap; - impl->plug = plug; - instance->host_widget = wrap; + impl->host_widget = wrap; + impl->plug = plug; + instance->host_widget = wrap; - return 0; + return 0; } SUIL_LIB_EXPORT @@ -111,39 +110,40 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - /* We have to open libgtk here, so Gtk type symbols are present and will be - found by the introspection stuff. This is required at least to make - GtkBuilder use in UIs work, otherwise they will cause "Invalid object - type" errors. - */ - if (!host->gtk_lib) { - dylib_error(); - host->gtk_lib = dylib_open(SUIL_GTK2_LIB_NAME, DYLIB_LAZY|DYLIB_GLOBAL); - if (!host->gtk_lib) { - SUIL_ERRORF("Failed to open %s (%s)\n", - SUIL_GTK2_LIB_NAME, dylib_error()); - return nullptr; - } - gtk_init(nullptr, nullptr); - } - - /* Create wrapper implementation. */ - SuilGtk2InQt4Wrapper* const impl = (SuilGtk2InQt4Wrapper*) - calloc(1, sizeof(SuilGtk2InQt4Wrapper)); - - /* Set parent widget if given. */ - for (unsigned i = 0; i < n_features; ++i) { - if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { - impl->parent = static_cast<QWidget*>((*features)[i]->data); - } - } - - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - wrapper->impl = impl; - - return wrapper; + /* We have to open libgtk here, so Gtk type symbols are present and will be + found by the introspection stuff. This is required at least to make + GtkBuilder use in UIs work, otherwise they will cause "Invalid object + type" errors. + */ + if (!host->gtk_lib) { + dylib_error(); + host->gtk_lib = dylib_open(SUIL_GTK2_LIB_NAME, DYLIB_LAZY | DYLIB_GLOBAL); + if (!host->gtk_lib) { + SUIL_ERRORF( + "Failed to open %s (%s)\n", SUIL_GTK2_LIB_NAME, dylib_error()); + return nullptr; + } + + gtk_init(nullptr, nullptr); + } + + /* Create wrapper implementation. */ + SuilGtk2InQt4Wrapper* const impl = + (SuilGtk2InQt4Wrapper*)calloc(1, sizeof(SuilGtk2InQt4Wrapper)); + + /* Set parent widget if given. */ + for (unsigned i = 0; i < n_features; ++i) { + if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { + impl->parent = static_cast<QWidget*>((*features)[i]->data); + } + } + + SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + wrapper->impl = impl; + + return wrapper; } -} // extern "C" +} // extern "C" diff --git a/src/gtk2_in_qt5.cpp b/src/gtk2_in_qt5.cpp index 14030b2..496350e 100644 --- a/src/gtk2_in_qt5.cpp +++ b/src/gtk2_in_qt5.cpp @@ -41,87 +41,86 @@ extern "C" { struct SuilGtk2InQt5Wrapper { - QWidget* host_widget; - QWindow* window; - GtkWidget* plug; + QWidget* host_widget; + QWindow* window; + GtkWidget* plug; }; static void on_size_request(GtkWidget*, GtkRequisition* requisition, gpointer user_data) { - auto* const wrap = (QWidget*)user_data; - wrap->setMinimumSize(requisition->width, requisition->height); + auto* const wrap = (QWidget*)user_data; + wrap->setMinimumSize(requisition->width, requisition->height); } static void on_size_allocate(GtkWidget*, GdkRectangle* allocation, gpointer user_data) { - auto* const wrap = (QWidget*)user_data; - wrap->resize(allocation->width, allocation->height); + auto* const wrap = (QWidget*)user_data; + wrap->resize(allocation->width, allocation->height); } static void wrapper_free(SuilWrapper* wrapper) { - auto* impl = (SuilGtk2InQt5Wrapper*)wrapper->impl; + auto* impl = (SuilGtk2InQt5Wrapper*)wrapper->impl; - if (impl->window) { - impl->window->setParent(nullptr); - delete impl->window; - } + if (impl->window) { + impl->window->setParent(nullptr); + delete impl->window; + } - if (impl->plug) { - gtk_widget_destroy(impl->plug); - } + if (impl->plug) { + gtk_widget_destroy(impl->plug); + } - delete impl->host_widget; + delete impl->host_widget; - free(impl); + free(impl); } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - auto* const impl = (SuilGtk2InQt5Wrapper*)wrapper->impl; - auto* const wrap = new QWidget(nullptr, Qt::Window); - GtkWidget* const plug = gtk_plug_new(0); - auto* const widget = (GtkWidget*)instance->ui_widget; + auto* const impl = (SuilGtk2InQt5Wrapper*)wrapper->impl; + auto* const wrap = new QWidget(nullptr, Qt::Window); + GtkWidget* const plug = gtk_plug_new(0); + auto* const widget = (GtkWidget*)instance->ui_widget; - gtk_container_add(GTK_CONTAINER(plug), widget); - gtk_widget_show_all(plug); + gtk_container_add(GTK_CONTAINER(plug), widget); + gtk_widget_show_all(plug); - const WId wid = (WId)gtk_plug_get_id((GtkPlug*)plug); - QWindow* window = QWindow::fromWinId(wid); - QWidget* container = - QWidget::createWindowContainer(window, wrap, Qt::WindowFlags()); + const WId wid = (WId)gtk_plug_get_id((GtkPlug*)plug); + QWindow* window = QWindow::fromWinId(wid); + QWidget* container = + QWidget::createWindowContainer(window, wrap, Qt::WindowFlags()); - auto* layout = new QVBoxLayout(); - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(container, 0, Qt::Alignment()); - wrap->setLayout(layout); + auto* layout = new QVBoxLayout(); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(container, 0, Qt::Alignment()); + wrap->setLayout(layout); #ifdef SUIL_OLD_GTK - wrap->resize(widget->allocation.width, widget->allocation.height); + wrap->resize(widget->allocation.width, widget->allocation.height); #else - GtkAllocation alloc; - gtk_widget_get_allocation(widget, &alloc); - wrap->resize(alloc.width, alloc.height); + GtkAllocation alloc; + gtk_widget_get_allocation(widget, &alloc); + wrap->resize(alloc.width, alloc.height); #endif - g_signal_connect( - G_OBJECT(plug), "size-request", G_CALLBACK(on_size_request), wrap); + g_signal_connect( + G_OBJECT(plug), "size-request", G_CALLBACK(on_size_request), wrap); - g_signal_connect( - G_OBJECT(plug), "size-allocate", G_CALLBACK(on_size_allocate), wrap); + g_signal_connect( + G_OBJECT(plug), "size-allocate", G_CALLBACK(on_size_allocate), wrap); - impl->host_widget = wrap; - impl->window = window; - impl->plug = plug; - instance->host_widget = wrap; + impl->host_widget = wrap; + impl->window = window; + impl->plug = plug; + instance->host_widget = wrap; - return 0; + return 0; } SUIL_LIB_EXPORT @@ -132,32 +131,33 @@ suil_wrapper_new(SuilHost* host, LV2_Feature***, unsigned) { - /* We have to open libgtk here, so Gtk type symbols are present and will be - found by the introspection stuff. This is required at least to make - GtkBuilder use in UIs work, otherwise they will cause "Invalid object - type" errors. - */ - if (!host->gtk_lib) { - dylib_error(); - host->gtk_lib = dylib_open(SUIL_GTK2_LIB_NAME, DYLIB_LAZY|DYLIB_GLOBAL); - if (!host->gtk_lib) { - SUIL_ERRORF("Failed to open %s (%s)\n", - SUIL_GTK2_LIB_NAME, dylib_error()); - return nullptr; - } - gtk_init(nullptr, nullptr); - } - - /* Create wrapper implementation. */ - auto* const impl = - (SuilGtk2InQt5Wrapper*)calloc(1, sizeof(SuilGtk2InQt5Wrapper)); - - auto* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - wrapper->impl = impl; - - return wrapper; + /* We have to open libgtk here, so Gtk type symbols are present and will be + found by the introspection stuff. This is required at least to make + GtkBuilder use in UIs work, otherwise they will cause "Invalid object + type" errors. + */ + if (!host->gtk_lib) { + dylib_error(); + host->gtk_lib = dylib_open(SUIL_GTK2_LIB_NAME, DYLIB_LAZY | DYLIB_GLOBAL); + if (!host->gtk_lib) { + SUIL_ERRORF( + "Failed to open %s (%s)\n", SUIL_GTK2_LIB_NAME, dylib_error()); + return nullptr; + } + + gtk_init(nullptr, nullptr); + } + + /* Create wrapper implementation. */ + auto* const impl = + (SuilGtk2InQt5Wrapper*)calloc(1, sizeof(SuilGtk2InQt5Wrapper)); + + auto* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + wrapper->impl = impl; + + return wrapper; } -} // extern "C" +} // extern "C" @@ -33,53 +33,55 @@ suil_host_new(SuilPortWriteFunc write_func, SuilPortSubscribeFunc subscribe_func, SuilPortUnsubscribeFunc unsubscribe_func) { - SuilHost* host = (SuilHost*)calloc(1, sizeof(struct SuilHostImpl)); - host->write_func = write_func; - host->index_func = index_func; - host->subscribe_func = subscribe_func; - host->unsubscribe_func = unsubscribe_func; - host->argc = suil_argc; - host->argv = suil_argv; - return host; + SuilHost* host = (SuilHost*)calloc(1, sizeof(struct SuilHostImpl)); + + host->write_func = write_func; + host->index_func = index_func; + host->subscribe_func = subscribe_func; + host->unsubscribe_func = unsubscribe_func; + host->argc = suil_argc; + host->argv = suil_argv; + + return host; } SUIL_API void -suil_host_set_touch_func(SuilHost* host, - SuilTouchFunc touch_func) +suil_host_set_touch_func(SuilHost* host, SuilTouchFunc touch_func) { - host->touch_func = touch_func; + host->touch_func = touch_func; } SUIL_API void suil_host_free(SuilHost* host) { - if (host) { - if (host->gtk_lib) { - dylib_close(host->gtk_lib); - } - free(host); - } + if (host) { + if (host->gtk_lib) { + dylib_close(host->gtk_lib); + } + + free(host); + } } #ifdef SUIL_WITH_X11 static void suil_load_init_module(const char* module_name) { - void* const lib = suil_open_module(module_name); - if (!lib) { - return; - } - - SuilVoidFunc init_func = suil_dlfunc(lib, "suil_host_init"); - if (init_func) { - (*init_func)(); - } else { - SUIL_ERRORF("Corrupt init module %s\n", module_name); - } - - dylib_close(lib); + void* const lib = suil_open_module(module_name); + if (!lib) { + return; + } + + SuilVoidFunc init_func = suil_dlfunc(lib, "suil_host_init"); + if (init_func) { + (*init_func)(); + } else { + SUIL_ERRORF("Corrupt init module %s\n", module_name); + } + + dylib_close(lib); } #endif @@ -87,12 +89,12 @@ SUIL_API void suil_init(int* argc, char*** argv, SuilArg key, ...) { - (void)key; + (void)key; - suil_argc = argc ? *argc : 0; - suil_argv = argv ? *argv : NULL; + suil_argc = argc ? *argc : 0; + suil_argv = argv ? *argv : NULL; #ifdef SUIL_WITH_X11 - suil_load_init_module("suil_x11"); + suil_load_init_module("suil_x11"); #endif } diff --git a/src/instance.c b/src/instance.c index 3cf5e06..0aa96c9 100644 --- a/src/instance.c +++ b/src/instance.c @@ -28,57 +28,56 @@ #include <stdlib.h> #include <string.h> -#define GTK2_UI_URI LV2_UI__GtkUI -#define GTK3_UI_URI LV2_UI__Gtk3UI -#define QT4_UI_URI LV2_UI__Qt4UI -#define QT5_UI_URI LV2_UI__Qt5UI -#define X11_UI_URI LV2_UI__X11UI -#define WIN_UI_URI LV2_UI_PREFIX "WindowsUI" +#define GTK2_UI_URI LV2_UI__GtkUI +#define GTK3_UI_URI LV2_UI__Gtk3UI +#define QT4_UI_URI LV2_UI__Qt4UI +#define QT5_UI_URI LV2_UI__Qt5UI +#define X11_UI_URI LV2_UI__X11UI +#define WIN_UI_URI LV2_UI_PREFIX "WindowsUI" #define COCOA_UI_URI LV2_UI__CocoaUI SUIL_API unsigned -suil_ui_supported(const char* host_type_uri, - const char* ui_type_uri) +suil_ui_supported(const char* host_type_uri, const char* ui_type_uri) { - enum { - SUIL_WRAPPING_UNSUPPORTED = 0, - SUIL_WRAPPING_NATIVE = 1, - SUIL_WRAPPING_EMBEDDED = 2 - }; - - if (!strcmp(host_type_uri, ui_type_uri)) { - return SUIL_WRAPPING_NATIVE; - } - - if ((!strcmp(host_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, QT4_UI_URI)) - || (!strcmp(host_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, QT5_UI_URI)) - || (!strcmp(host_type_uri, QT4_UI_URI) - && !strcmp(ui_type_uri, GTK2_UI_URI)) - || (!strcmp(host_type_uri, QT5_UI_URI) - && !strcmp(ui_type_uri, GTK2_UI_URI)) - || (!strcmp(host_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) - || (!strcmp(host_type_uri, GTK3_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) - || (!strcmp(host_type_uri, GTK3_UI_URI) - && !strcmp(ui_type_uri, QT5_UI_URI)) - || (!strcmp(host_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, WIN_UI_URI)) - || (!strcmp(host_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, COCOA_UI_URI)) - || (!strcmp(host_type_uri, QT4_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) - || (!strcmp(host_type_uri, QT5_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) - || (!strcmp(host_type_uri, QT5_UI_URI) - && !strcmp(ui_type_uri, COCOA_UI_URI))) { - return SUIL_WRAPPING_EMBEDDED; - } - - return SUIL_WRAPPING_UNSUPPORTED; + enum { + SUIL_WRAPPING_UNSUPPORTED = 0, + SUIL_WRAPPING_NATIVE = 1, + SUIL_WRAPPING_EMBEDDED = 2 + }; + + if (!strcmp(host_type_uri, ui_type_uri)) { + return SUIL_WRAPPING_NATIVE; + } + + if ((!strcmp(host_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, QT4_UI_URI)) || + (!strcmp(host_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, QT5_UI_URI)) || + (!strcmp(host_type_uri, QT4_UI_URI) && + !strcmp(ui_type_uri, GTK2_UI_URI)) || + (!strcmp(host_type_uri, QT5_UI_URI) && + !strcmp(ui_type_uri, GTK2_UI_URI)) || + (!strcmp(host_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) || + (!strcmp(host_type_uri, GTK3_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) || + (!strcmp(host_type_uri, GTK3_UI_URI) && + !strcmp(ui_type_uri, QT5_UI_URI)) || + (!strcmp(host_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, WIN_UI_URI)) || + (!strcmp(host_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, COCOA_UI_URI)) || + (!strcmp(host_type_uri, QT4_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) || + (!strcmp(host_type_uri, QT5_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) || + (!strcmp(host_type_uri, QT5_UI_URI) && + !strcmp(ui_type_uri, COCOA_UI_URI))) { + return SUIL_WRAPPING_EMBEDDED; + } + + return SUIL_WRAPPING_UNSUPPORTED; } static SuilWrapper* @@ -88,110 +87,108 @@ open_wrapper(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - const char* module_name = NULL; + const char* module_name = NULL; #ifdef SUIL_WITH_GTK2_IN_QT4 - if (!strcmp(container_type_uri, QT4_UI_URI) - && !strcmp(ui_type_uri, GTK2_UI_URI)) { - module_name = "suil_gtk2_in_qt4"; - } + if (!strcmp(container_type_uri, QT4_UI_URI) && + !strcmp(ui_type_uri, GTK2_UI_URI)) { + module_name = "suil_gtk2_in_qt4"; + } #endif #ifdef SUIL_WITH_GTK2_IN_QT5 - if (!strcmp(container_type_uri, QT5_UI_URI) - && !strcmp(ui_type_uri, GTK2_UI_URI)) { - module_name = "suil_gtk2_in_qt5"; - } + if (!strcmp(container_type_uri, QT5_UI_URI) && + !strcmp(ui_type_uri, GTK2_UI_URI)) { + module_name = "suil_gtk2_in_qt5"; + } #endif #ifdef SUIL_WITH_QT4_IN_GTK2 - if (!strcmp(container_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, QT4_UI_URI)) { - module_name = "suil_qt4_in_gtk2"; - } + if (!strcmp(container_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, QT4_UI_URI)) { + module_name = "suil_qt4_in_gtk2"; + } #endif #ifdef SUIL_WITH_QT5_IN_GTK2 - if (!strcmp(container_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, QT5_UI_URI)) { - module_name = "suil_qt5_in_gtk2"; - } + if (!strcmp(container_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, QT5_UI_URI)) { + module_name = "suil_qt5_in_gtk2"; + } #endif #ifdef SUIL_WITH_X11_IN_GTK2 - if (!strcmp(container_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) { - module_name = "suil_x11_in_gtk2"; - } + if (!strcmp(container_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) { + module_name = "suil_x11_in_gtk2"; + } #endif #ifdef SUIL_WITH_X11_IN_GTK3 - if (!strcmp(container_type_uri, GTK3_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) { - module_name = "suil_x11_in_gtk3"; - } + if (!strcmp(container_type_uri, GTK3_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) { + module_name = "suil_x11_in_gtk3"; + } #endif #ifdef SUIL_WITH_QT5_IN_GTK3 - if (!strcmp(container_type_uri, GTK3_UI_URI) - && !strcmp(ui_type_uri, QT5_UI_URI)) { - module_name = "suil_qt5_in_gtk3"; - } + if (!strcmp(container_type_uri, GTK3_UI_URI) && + !strcmp(ui_type_uri, QT5_UI_URI)) { + module_name = "suil_qt5_in_gtk3"; + } #endif #ifdef SUIL_WITH_WIN_IN_GTK2 - if (!strcmp(container_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, WIN_UI_URI)) { - module_name = "suil_win_in_gtk2"; - } + if (!strcmp(container_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, WIN_UI_URI)) { + module_name = "suil_win_in_gtk2"; + } #endif #ifdef SUIL_WITH_COCOA_IN_GTK2 - if (!strcmp(container_type_uri, GTK2_UI_URI) - && !strcmp(ui_type_uri, COCOA_UI_URI)) { - module_name = "suil_cocoa_in_gtk2"; - } + if (!strcmp(container_type_uri, GTK2_UI_URI) && + !strcmp(ui_type_uri, COCOA_UI_URI)) { + module_name = "suil_cocoa_in_gtk2"; + } #endif #ifdef SUIL_WITH_X11_IN_QT4 - if (!strcmp(container_type_uri, QT4_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) { - module_name = "suil_x11_in_qt4"; - } + if (!strcmp(container_type_uri, QT4_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) { + module_name = "suil_x11_in_qt4"; + } #endif #ifdef SUIL_WITH_X11_IN_QT5 - if (!strcmp(container_type_uri, QT5_UI_URI) - && !strcmp(ui_type_uri, X11_UI_URI)) { - module_name = "suil_x11_in_qt5"; - } + if (!strcmp(container_type_uri, QT5_UI_URI) && + !strcmp(ui_type_uri, X11_UI_URI)) { + module_name = "suil_x11_in_qt5"; + } #endif #ifdef SUIL_WITH_COCOA_IN_QT5 - if (!strcmp(container_type_uri, QT5_UI_URI) - && !strcmp(ui_type_uri, COCOA_UI_URI)) { - module_name = "suil_cocoa_in_qt5"; - } + if (!strcmp(container_type_uri, QT5_UI_URI) && + !strcmp(ui_type_uri, COCOA_UI_URI)) { + module_name = "suil_cocoa_in_qt5"; + } #endif - if (!module_name) { - SUIL_ERRORF("Unable to wrap UI type <%s> as type <%s>\n", - ui_type_uri, container_type_uri); - return NULL; - } - - void* const lib = suil_open_module(module_name); - if (!lib) { - return NULL; - } - - SuilWrapperNewFunc wrapper_new = (SuilWrapperNewFunc)suil_dlfunc( - lib, "suil_wrapper_new"); - - SuilWrapper* wrapper = wrapper_new - ? wrapper_new(host, - container_type_uri, - ui_type_uri, - features, - n_features) - : NULL; - - if (wrapper) { - wrapper->lib = lib; - } else { - SUIL_ERRORF("Corrupt wrap module %s\n", module_name); - dylib_close(lib); - } - - return wrapper; + if (!module_name) { + SUIL_ERRORF("Unable to wrap UI type <%s> as type <%s>\n", + ui_type_uri, + container_type_uri); + return NULL; + } + + void* const lib = suil_open_module(module_name); + if (!lib) { + return NULL; + } + + SuilWrapperNewFunc wrapper_new = + (SuilWrapperNewFunc)suil_dlfunc(lib, "suil_wrapper_new"); + + SuilWrapper* wrapper = + wrapper_new + ? wrapper_new(host, container_type_uri, ui_type_uri, features, n_features) + : NULL; + + if (wrapper) { + wrapper->lib = lib; + } else { + SUIL_ERRORF("Corrupt wrap module %s\n", module_name); + dylib_close(lib); + } + + return wrapper; } SUIL_API @@ -206,178 +203,183 @@ suil_instance_new(SuilHost* host, const char* ui_binary_path, const LV2_Feature* const* features) { - // Open UI library - dylib_error(); - void* lib = dylib_open(ui_binary_path, DYLIB_NOW); - if (!lib) { - SUIL_ERRORF("Unable to open UI library %s (%s)\n", - ui_binary_path, dylib_error()); - return NULL; - } - - // Get discovery function - LV2UI_DescriptorFunction df = (LV2UI_DescriptorFunction) - suil_dlfunc(lib, "lv2ui_descriptor"); - if (!df) { - SUIL_ERRORF("Broken LV2 UI %s (no lv2ui_descriptor symbol found)\n", - ui_binary_path); - dylib_close(lib); - return NULL; - } - - // Get UI descriptor - const LV2UI_Descriptor* descriptor = NULL; - for (uint32_t i = 0; true; ++i) { - const LV2UI_Descriptor* ld = df(i); - if (!ld) { - break; - } - - if (!strcmp(ld->URI, ui_uri)) { - descriptor = ld; - break; - } - } - if (!descriptor) { - SUIL_ERRORF("Failed to find descriptor for <%s> in %s\n", - ui_uri, ui_binary_path); - dylib_close(lib); - return NULL; - } - - // Create SuilInstance - SuilInstance* instance = (SuilInstance*)calloc(1, sizeof(SuilInstance)); - if (!instance) { - SUIL_ERRORF("Failed to allocate memory for <%s> instance\n", ui_uri); - dylib_close(lib); - return NULL; - } - - instance->lib_handle = lib; - instance->descriptor = descriptor; - - // Make UI features array - instance->features = (LV2_Feature**)malloc(sizeof(LV2_Feature*)); - instance->features[0] = NULL; - - // Copy user provided features - const LV2_Feature* const* fi = features; - unsigned n_features = 0; - while (fi && *fi) { - const LV2_Feature* f = *fi++; - suil_add_feature(&instance->features, &n_features, f->URI, f->data); - } - - // Add additional features implemented by SuilHost functions - if (host->index_func) { - instance->port_map.handle = controller; - instance->port_map.port_index = host->index_func; - suil_add_feature(&instance->features, &n_features, - LV2_UI__portMap, &instance->port_map); - } - if (host->subscribe_func && host->unsubscribe_func) { - instance->port_subscribe.handle = controller; - instance->port_subscribe.subscribe = host->subscribe_func; - instance->port_subscribe.unsubscribe = host->unsubscribe_func; - suil_add_feature(&instance->features, &n_features, - LV2_UI__portSubscribe, &instance->port_subscribe); - } - if (host->touch_func) { - instance->touch.handle = controller; - instance->touch.touch = host->touch_func; - suil_add_feature(&instance->features, &n_features, - LV2_UI__touch, &instance->touch); - } - - // Open wrapper (this may add additional features) - if (container_type_uri && strcmp(container_type_uri, ui_type_uri)) { - instance->wrapper = open_wrapper(host, - container_type_uri, ui_type_uri, - &instance->features, n_features); - if (!instance->wrapper) { - suil_instance_free(instance); - return NULL; - } - } - - // Instantiate UI - instance->handle = descriptor->instantiate( - descriptor, - plugin_uri, - ui_bundle_path, - host->write_func, - controller, - &instance->ui_widget, - (const LV2_Feature* const*)instance->features); - - // Failed to instantiate UI - if (!instance->handle) { - SUIL_ERRORF("Failed to instantiate UI <%s> in %s\n", - ui_uri, ui_binary_path); - suil_instance_free(instance); - return NULL; - } - - if (instance->wrapper) { - if (instance->wrapper->wrap(instance->wrapper, instance)) { - SUIL_ERRORF("Failed to wrap UI <%s> in type <%s>\n", - ui_uri, container_type_uri); - suil_instance_free(instance); - return NULL; - } - } else { - instance->host_widget = instance->ui_widget; - } - - return instance; + // Open UI library + dylib_error(); + void* lib = dylib_open(ui_binary_path, DYLIB_NOW); + if (!lib) { + SUIL_ERRORF( + "Unable to open UI library %s (%s)\n", ui_binary_path, dylib_error()); + return NULL; + } + + // Get discovery function + LV2UI_DescriptorFunction df = + (LV2UI_DescriptorFunction)suil_dlfunc(lib, "lv2ui_descriptor"); + if (!df) { + SUIL_ERRORF("Broken LV2 UI %s (no lv2ui_descriptor symbol found)\n", + ui_binary_path); + dylib_close(lib); + return NULL; + } + + // Get UI descriptor + const LV2UI_Descriptor* descriptor = NULL; + for (uint32_t i = 0; true; ++i) { + const LV2UI_Descriptor* ld = df(i); + if (!ld) { + break; + } + + if (!strcmp(ld->URI, ui_uri)) { + descriptor = ld; + break; + } + } + + if (!descriptor) { + SUIL_ERRORF( + "Failed to find descriptor for <%s> in %s\n", ui_uri, ui_binary_path); + dylib_close(lib); + return NULL; + } + + // Create SuilInstance + SuilInstance* instance = (SuilInstance*)calloc(1, sizeof(SuilInstance)); + if (!instance) { + SUIL_ERRORF("Failed to allocate memory for <%s> instance\n", ui_uri); + dylib_close(lib); + return NULL; + } + + instance->lib_handle = lib; + instance->descriptor = descriptor; + + // Make UI features array + instance->features = (LV2_Feature**)malloc(sizeof(LV2_Feature*)); + instance->features[0] = NULL; + + // Copy user provided features + const LV2_Feature* const* fi = features; + unsigned n_features = 0; + while (fi && *fi) { + const LV2_Feature* f = *fi++; + suil_add_feature(&instance->features, &n_features, f->URI, f->data); + } + + // Add additional features implemented by SuilHost functions + if (host->index_func) { + instance->port_map.handle = controller; + instance->port_map.port_index = host->index_func; + suil_add_feature( + &instance->features, &n_features, LV2_UI__portMap, &instance->port_map); + } + + if (host->subscribe_func && host->unsubscribe_func) { + instance->port_subscribe.handle = controller; + instance->port_subscribe.subscribe = host->subscribe_func; + instance->port_subscribe.unsubscribe = host->unsubscribe_func; + suil_add_feature(&instance->features, + &n_features, + LV2_UI__portSubscribe, + &instance->port_subscribe); + } + + if (host->touch_func) { + instance->touch.handle = controller; + instance->touch.touch = host->touch_func; + suil_add_feature( + &instance->features, &n_features, LV2_UI__touch, &instance->touch); + } + + // Open wrapper (this may add additional features) + if (container_type_uri && strcmp(container_type_uri, ui_type_uri)) { + instance->wrapper = open_wrapper( + host, container_type_uri, ui_type_uri, &instance->features, n_features); + if (!instance->wrapper) { + suil_instance_free(instance); + return NULL; + } + } + + // Instantiate UI + instance->handle = + descriptor->instantiate(descriptor, + plugin_uri, + ui_bundle_path, + host->write_func, + controller, + &instance->ui_widget, + (const LV2_Feature* const*)instance->features); + + // Failed to instantiate UI + if (!instance->handle) { + SUIL_ERRORF( + "Failed to instantiate UI <%s> in %s\n", ui_uri, ui_binary_path); + suil_instance_free(instance); + return NULL; + } + + if (instance->wrapper) { + if (instance->wrapper->wrap(instance->wrapper, instance)) { + SUIL_ERRORF( + "Failed to wrap UI <%s> in type <%s>\n", ui_uri, container_type_uri); + suil_instance_free(instance); + return NULL; + } + } else { + instance->host_widget = instance->ui_widget; + } + + return instance; } SUIL_API void suil_instance_free(SuilInstance* instance) { - if (instance) { - for (unsigned i = 0; instance->features[i]; ++i) { - free(instance->features[i]); - } - free(instance->features); - - // Call wrapper free function to destroy widgets and drop references - if (instance->wrapper && instance->wrapper->free) { - instance->wrapper->free(instance->wrapper); - } - - // Call cleanup to destroy UI (if it still exists at this point) - if (instance->handle) { - instance->descriptor->cleanup(instance->handle); - } - - dylib_close(instance->lib_handle); - - // Close libraries and free everything - if (instance->wrapper) { + if (instance) { + for (unsigned i = 0; instance->features[i]; ++i) { + free(instance->features[i]); + } + free(instance->features); + + // Call wrapper free function to destroy widgets and drop references + if (instance->wrapper && instance->wrapper->free) { + instance->wrapper->free(instance->wrapper); + } + + // Call cleanup to destroy UI (if it still exists at this point) + if (instance->handle) { + instance->descriptor->cleanup(instance->handle); + } + + dylib_close(instance->lib_handle); + + // Close libraries and free everything + if (instance->wrapper) { #ifndef _WIN32 - // Never unload modules on windows, causes mysterious segfaults - dylib_close(instance->wrapper->lib); + // Never unload modules on windows, causes mysterious segfaults + dylib_close(instance->wrapper->lib); #endif - free(instance->wrapper); - } - free(instance); - } + free(instance->wrapper); + } + + free(instance); + } } SUIL_API SuilHandle suil_instance_get_handle(SuilInstance* instance) { - return instance->handle; + return instance->handle; } SUIL_API LV2UI_Widget suil_instance_get_widget(SuilInstance* instance) { - return instance->host_widget; + return instance->host_widget; } SUIL_API @@ -388,22 +390,19 @@ suil_instance_port_event(SuilInstance* instance, uint32_t format, const void* buffer) { - if (instance->descriptor->port_event) { - instance->descriptor->port_event(instance->handle, - port_index, - buffer_size, - format, - buffer); - } + if (instance->descriptor->port_event) { + instance->descriptor->port_event( + instance->handle, port_index, buffer_size, format, buffer); + } } SUIL_API const void* -suil_instance_extension_data(SuilInstance* instance, - const char* uri) +suil_instance_extension_data(SuilInstance* instance, const char* uri) { - if (instance->descriptor->extension_data) { - return instance->descriptor->extension_data(uri); - } - return NULL; + if (instance->descriptor->extension_data) { + return instance->descriptor->extension_data(uri); + } + + return NULL; } diff --git a/src/qt4_in_gtk2.cpp b/src/qt4_in_gtk2.cpp index a9631c1..ae64ad3 100644 --- a/src/qt4_in_gtk2.cpp +++ b/src/qt4_in_gtk2.cpp @@ -27,103 +27,104 @@ extern "C" { #define SUIL_TYPE_QT_WRAPPER (suil_qt_wrapper_get_type()) -#define SUIL_QT_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_QT_WRAPPER, SuilQtWrapper)) +#define SUIL_QT_WRAPPER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_QT_WRAPPER, SuilQtWrapper)) using SuilQtWrapper = _SuilQtWrapper; using SuilQtWrapperClass = _SuilQtWrapperClass; struct _SuilQtWrapper { - GtkSocket socket; - QApplication* app; - QX11EmbedWidget* qembed; - SuilWrapper* wrapper; - SuilInstance* instance; + GtkSocket socket; + QApplication* app; + QX11EmbedWidget* qembed; + SuilWrapper* wrapper; + SuilInstance* instance; }; struct _SuilQtWrapperClass { - GtkSocketClass parent_class; + GtkSocketClass parent_class; }; -GType suil_qt_wrapper_get_type(void); // Accessor for SUIL_TYPE_QT_WRAPPER +GType +suil_qt_wrapper_get_type(void); // Accessor for SUIL_TYPE_QT_WRAPPER G_DEFINE_TYPE(SuilQtWrapper, suil_qt_wrapper, GTK_TYPE_SOCKET) static void suil_qt_wrapper_finalize(GObject* gobject) { - SuilQtWrapper* const self = SUIL_QT_WRAPPER(gobject); + SuilQtWrapper* const self = SUIL_QT_WRAPPER(gobject); - if (self->instance->handle) { - self->instance->descriptor->cleanup(self->instance->handle); - self->instance->handle = nullptr; - } + if (self->instance->handle) { + self->instance->descriptor->cleanup(self->instance->handle); + self->instance->handle = nullptr; + } - delete self->qembed; + delete self->qembed; - self->qembed = nullptr; - self->app = nullptr; - self->wrapper->impl = nullptr; + self->qembed = nullptr; + self->app = nullptr; + self->wrapper->impl = nullptr; - G_OBJECT_CLASS(suil_qt_wrapper_parent_class)->finalize(gobject); + G_OBJECT_CLASS(suil_qt_wrapper_parent_class)->finalize(gobject); } static void suil_qt_wrapper_class_init(SuilQtWrapperClass* klass) { - GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - gobject_class->finalize = suil_qt_wrapper_finalize; + gobject_class->finalize = suil_qt_wrapper_finalize; } static void suil_qt_wrapper_init(SuilQtWrapper* self) { - self->app = nullptr; - self->qembed = nullptr; - self->instance = nullptr; + self->app = nullptr; + self->qembed = nullptr; + self->instance = nullptr; } static void suil_qt_wrapper_realize(GtkWidget* w, gpointer data) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(w); - GtkSocket* const s = GTK_SOCKET(w); + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(w); + GtkSocket* const s = GTK_SOCKET(w); - gtk_socket_add_id(s, wrap->qembed->winId()); - wrap->qembed->show(); + gtk_socket_add_id(s, wrap->qembed->winId()); + wrap->qembed->show(); } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); - wrap->qembed = new QX11EmbedWidget(); - wrap->wrapper = wrapper; - wrap->instance = instance; + wrap->qembed = new QX11EmbedWidget(); + wrap->wrapper = wrapper; + wrap->instance = instance; - QWidget* qwidget = (QWidget*)instance->ui_widget; - QVBoxLayout* layout = new QVBoxLayout(wrap->qembed); - layout->addWidget(qwidget); + QWidget* qwidget = (QWidget*)instance->ui_widget; + QVBoxLayout* layout = new QVBoxLayout(wrap->qembed); + layout->addWidget(qwidget); - qwidget->setParent(wrap->qembed); + qwidget->setParent(wrap->qembed); - g_signal_connect_after(G_OBJECT(wrap), "realize", - G_CALLBACK(suil_qt_wrapper_realize), nullptr); + g_signal_connect_after( + G_OBJECT(wrap), "realize", G_CALLBACK(suil_qt_wrapper_realize), nullptr); - instance->host_widget = GTK_WIDGET(wrap); + instance->host_widget = GTK_WIDGET(wrap); - return 0; + return 0; } static void wrapper_free(SuilWrapper* wrapper) { - if (wrapper->impl) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); - gtk_object_destroy(GTK_OBJECT(wrap)); - } + if (wrapper->impl) { + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); + gtk_object_destroy(GTK_OBJECT(wrap)); + } } SUIL_LIB_EXPORT @@ -134,23 +135,23 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; + SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER( - g_object_new(SUIL_TYPE_QT_WRAPPER, nullptr)); + SuilQtWrapper* const wrap = + SUIL_QT_WRAPPER(g_object_new(SUIL_TYPE_QT_WRAPPER, nullptr)); - if (qApp) { - wrap->app = qApp; - } else { - wrap->app = new QApplication(host->argc, host->argv, true); - } + if (qApp) { + wrap->app = qApp; + } else { + wrap->app = new QApplication(host->argc, host->argv, true); + } - wrap->wrapper = nullptr; - wrapper->impl = wrap; + wrap->wrapper = nullptr; + wrapper->impl = wrap; - return wrapper; + return wrapper; } -} // extern "C" +} // extern "C" diff --git a/src/qt5_in_gtk.cpp b/src/qt5_in_gtk.cpp index 5ce272c..5ae92df 100644 --- a/src/qt5_in_gtk.cpp +++ b/src/qt5_in_gtk.cpp @@ -37,7 +37,7 @@ #include <gtk/gtk.h> #if GTK_MAJOR_VERSION == 3 -#include <gtk/gtkx.h> +# include <gtk/gtkx.h> #endif #include <cstdlib> @@ -46,149 +46,150 @@ extern "C" { struct SuilQtWrapper { - GtkSocket socket; - QWidget* qembed; - SuilWrapper* wrapper; - SuilInstance* instance; - const LV2UI_Idle_Interface* idle_iface; - guint idle_id; - guint idle_ms; + GtkSocket socket; + QWidget* qembed; + SuilWrapper* wrapper; + SuilInstance* instance; + const LV2UI_Idle_Interface* idle_iface; + guint idle_id; + guint idle_ms; }; struct SuilQtWrapperClass { - GtkSocketClass parent_class; + GtkSocketClass parent_class; }; -GType suil_qt_wrapper_get_type(void); // Accessor for SUIL_TYPE_QT_WRAPPER +GType +suil_qt_wrapper_get_type(void); // Accessor for SUIL_TYPE_QT_WRAPPER #define SUIL_TYPE_QT_WRAPPER (suil_qt_wrapper_get_type()) -#define SUIL_QT_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_QT_WRAPPER, SuilQtWrapper)) +#define SUIL_QT_WRAPPER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_QT_WRAPPER, SuilQtWrapper)) G_DEFINE_TYPE(SuilQtWrapper, suil_qt_wrapper, GTK_TYPE_SOCKET) static void suil_qt_wrapper_finalize(GObject* gobject) { - SuilQtWrapper* const self = SUIL_QT_WRAPPER(gobject); + SuilQtWrapper* const self = SUIL_QT_WRAPPER(gobject); - if (self->idle_id) { - g_source_remove(self->idle_id); - self->idle_id = 0; - } + if (self->idle_id) { + g_source_remove(self->idle_id); + self->idle_id = 0; + } - if (self->instance->handle) { - self->instance->descriptor->cleanup(self->instance->handle); - self->instance->handle = nullptr; - } + if (self->instance->handle) { + self->instance->descriptor->cleanup(self->instance->handle); + self->instance->handle = nullptr; + } - if (self->qembed) { - self->qembed->deleteLater(); - } + if (self->qembed) { + self->qembed->deleteLater(); + } - self->qembed = nullptr; - self->idle_iface = nullptr; - self->wrapper->impl = nullptr; + self->qembed = nullptr; + self->idle_iface = nullptr; + self->wrapper->impl = nullptr; - G_OBJECT_CLASS(suil_qt_wrapper_parent_class)->finalize(gobject); + G_OBJECT_CLASS(suil_qt_wrapper_parent_class)->finalize(gobject); } static void suil_qt_wrapper_class_init(SuilQtWrapperClass* klass) { - GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - gobject_class->finalize = suil_qt_wrapper_finalize; + gobject_class->finalize = suil_qt_wrapper_finalize; } static void suil_qt_wrapper_init(SuilQtWrapper* self) { - self->qembed = nullptr; - self->wrapper = nullptr; - self->instance = nullptr; - self->idle_iface = nullptr; - self->idle_id = 0; - self->idle_ms = 1000 / 30; // 30 Hz default + self->qembed = nullptr; + self->wrapper = nullptr; + self->instance = nullptr; + self->idle_iface = nullptr; + self->idle_id = 0; + self->idle_ms = 1000 / 30; // 30 Hz default } static void suil_qt_wrapper_realize(GtkWidget* w, gpointer) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(w); - GtkSocket* const s = GTK_SOCKET(w); - const WId id = (WId)gtk_socket_get_id(s); + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(w); + GtkSocket* const s = GTK_SOCKET(w); + const WId id = (WId)gtk_socket_get_id(s); - wrap->qembed->winId(); - wrap->qembed->windowHandle()->setParent(QWindow::fromWinId(id)); - wrap->qembed->show(); + wrap->qembed->winId(); + wrap->qembed->windowHandle()->setParent(QWindow::fromWinId(id)); + wrap->qembed->show(); } static int suil_qt_wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - gtk_widget_set_size_request(GTK_WIDGET(handle), width, height); + gtk_widget_set_size_request(GTK_WIDGET(handle), width, height); - return 0; + return 0; } static gboolean suil_qt_wrapper_idle(void* data) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(data); + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(data); - if (wrap->idle_iface) { - wrap->idle_iface->idle(wrap->instance->handle); - return TRUE; // Continue calling - } + if (wrap->idle_iface) { + wrap->idle_iface->idle(wrap->instance->handle); + return TRUE; // Continue calling + } - return FALSE; + return FALSE; } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); - wrap->qembed = new QWidget(nullptr, Qt::WindowFlags()); - wrap->wrapper = wrapper; - wrap->instance = instance; + wrap->qembed = new QWidget(nullptr, Qt::WindowFlags()); + wrap->wrapper = wrapper; + wrap->instance = instance; - auto* qwidget = (QWidget*)instance->ui_widget; - auto* layout = new QVBoxLayout(); - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(qwidget, 0, Qt::Alignment()); + auto* qwidget = (QWidget*)instance->ui_widget; + auto* layout = new QVBoxLayout(); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(qwidget, 0, Qt::Alignment()); - wrap->qembed->setLayout(layout); + wrap->qembed->setLayout(layout); - g_signal_connect_after(G_OBJECT(wrap), "realize", - G_CALLBACK(suil_qt_wrapper_realize), nullptr); + g_signal_connect_after( + G_OBJECT(wrap), "realize", G_CALLBACK(suil_qt_wrapper_realize), nullptr); - instance->host_widget = GTK_WIDGET(wrap); + instance->host_widget = GTK_WIDGET(wrap); - const LV2UI_Idle_Interface* idle_iface = nullptr; - if (instance->descriptor->extension_data) { - idle_iface = (const LV2UI_Idle_Interface*) - instance->descriptor->extension_data(LV2_UI__idleInterface); - } + const LV2UI_Idle_Interface* idle_iface = nullptr; + 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_qt_wrapper_idle, wrap); - } + if (idle_iface) { + wrap->idle_iface = idle_iface; + wrap->idle_id = g_timeout_add(wrap->idle_ms, suil_qt_wrapper_idle, wrap); + } - return 0; + return 0; } static void wrapper_free(SuilWrapper* wrapper) { - if (wrapper->impl) { - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); - gtk_widget_destroy(GTK_WIDGET(wrap)); - } + if (wrapper->impl) { + SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); + gtk_widget_destroy(GTK_WIDGET(wrap)); + } } SUIL_LIB_EXPORT @@ -199,45 +200,45 @@ suil_wrapper_new(SuilHost*, LV2_Feature*** features, unsigned n_features) { - auto* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER( - g_object_new(SUIL_TYPE_QT_WRAPPER, nullptr)); - - wrap->wrapper = nullptr; - wrapper->impl = wrap; - - wrapper->resize.handle = wrap; - wrapper->resize.ui_resize = suil_qt_wrapper_resize; - - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); - - // Scan for URID map and options - LV2_URID_Map* map = nullptr; - LV2_Options_Option* options = nullptr; - 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 = (guint)(1000.0f / *(const float*)o->value); - break; - } - } - } - - return wrapper; + auto* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + + SuilQtWrapper* const wrap = + SUIL_QT_WRAPPER(g_object_new(SUIL_TYPE_QT_WRAPPER, nullptr)); + + wrap->wrapper = nullptr; + wrapper->impl = wrap; + + wrapper->resize.handle = wrap; + wrapper->resize.ui_resize = suil_qt_wrapper_resize; + + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); + + // Scan for URID map and options + LV2_URID_Map* map = nullptr; + LV2_Options_Option* options = nullptr; + 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 = (guint)(1000.0f / *(const float*)o->value); + break; + } + } + } + + return wrapper; } -} // extern "C" +} // extern "C" diff --git a/src/suil_internal.h b/src/suil_internal.h index 719471f..947af38 100644 --- a/src/suil_internal.h +++ b/src/suil_internal.h @@ -25,7 +25,7 @@ #include "suil/suil.h" #ifndef _WIN32 -# include <dlfcn.h> +# include <dlfcn.h> #endif #include <stdio.h> @@ -39,14 +39,14 @@ extern "C" { #define SUIL_ERRORF(fmt, ...) fprintf(stderr, "suil error: " fmt, __VA_ARGS__) struct SuilHostImpl { - SuilPortWriteFunc write_func; - SuilPortIndexFunc index_func; - SuilPortSubscribeFunc subscribe_func; - SuilPortUnsubscribeFunc unsubscribe_func; - SuilTouchFunc touch_func; - void* gtk_lib; - int argc; - char** argv; + SuilPortWriteFunc write_func; + SuilPortIndexFunc index_func; + SuilPortSubscribeFunc subscribe_func; + SuilPortUnsubscribeFunc unsubscribe_func; + SuilTouchFunc touch_func; + void* gtk_lib; + int argc; + char** argv; }; struct SuilWrapperImpl; @@ -54,27 +54,27 @@ struct SuilWrapperImpl; typedef void (*SuilWrapperFreeFunc)(struct SuilWrapperImpl*); typedef int (*SuilWrapperWrapFunc)(struct SuilWrapperImpl* wrapper, - SuilInstance* instance); + SuilInstance* instance); typedef struct SuilWrapperImpl { - SuilWrapperWrapFunc wrap; - SuilWrapperFreeFunc free; - void* lib; - void* impl; - LV2UI_Resize resize; + SuilWrapperWrapFunc wrap; + SuilWrapperFreeFunc free; + void* lib; + void* impl; + LV2UI_Resize resize; } SuilWrapper; struct SuilInstanceImpl { - void* lib_handle; - const LV2UI_Descriptor* descriptor; - LV2UI_Handle handle; - SuilWrapper* wrapper; - LV2_Feature** features; - LV2UI_Port_Map port_map; - LV2UI_Port_Subscribe port_subscribe; - LV2UI_Touch touch; - SuilWidget ui_widget; - SuilWidget host_widget; + void* lib_handle; + const LV2UI_Descriptor* descriptor; + LV2UI_Handle handle; + SuilWrapper* wrapper; + LV2_Feature** features; + LV2UI_Port_Map port_map; + LV2UI_Port_Subscribe port_subscribe; + LV2UI_Touch touch; + SuilWidget ui_widget; + SuilWidget host_widget; }; /** @@ -108,26 +108,30 @@ suil_host_init(void); static inline void* suil_open_module(const char* module_name) { - const char* const env_dir = getenv("SUIL_MODULE_DIR"); - const char* const mod_dir = env_dir ? env_dir : SUIL_MODULE_DIR; - const size_t path_len = strlen(mod_dir) - + strlen(SUIL_DIR_SEP SUIL_MODULE_PREFIX SUIL_MODULE_EXT) - + strlen(module_name) - + 2; - - char* const path = (char*)calloc(path_len, 1); - snprintf(path, path_len, "%s%s%s%s%s", - mod_dir, SUIL_DIR_SEP, - SUIL_MODULE_PREFIX, module_name, SUIL_MODULE_EXT); - - dylib_error(); - void* lib = dylib_open(path, DYLIB_NOW); - if (!lib) { - SUIL_ERRORF("Failed to open module %s (%s)\n", path, dylib_error()); - } - - free(path); - return lib; + const char* const env_dir = getenv("SUIL_MODULE_DIR"); + const char* const mod_dir = env_dir ? env_dir : SUIL_MODULE_DIR; + const size_t path_len = + strlen(mod_dir) + strlen(SUIL_DIR_SEP SUIL_MODULE_PREFIX SUIL_MODULE_EXT) + + strlen(module_name) + 2; + + char* const path = (char*)calloc(path_len, 1); + snprintf(path, + path_len, + "%s%s%s%s%s", + mod_dir, + SUIL_DIR_SEP, + SUIL_MODULE_PREFIX, + module_name, + SUIL_MODULE_EXT); + + dylib_error(); + void* lib = dylib_open(path, DYLIB_NOW); + if (!lib) { + SUIL_ERRORF("Failed to open module %s (%s)\n", path, dylib_error()); + } + + free(path); + return lib; } typedef void (*SuilVoidFunc)(void); @@ -137,11 +141,11 @@ static inline SuilVoidFunc suil_dlfunc(void* handle, const char* symbol) { #ifdef _WIN32 - return (SuilVoidFunc)GetProcAddress((HMODULE)handle, symbol); + return (SuilVoidFunc)GetProcAddress((HMODULE)handle, symbol); #else - typedef SuilVoidFunc (*VoidFuncGetter)(void*, const char*); - VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym; - return dlfunc(handle, symbol); + typedef SuilVoidFunc (*VoidFuncGetter)(void*, const char*); + VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym; + return dlfunc(handle, symbol); #endif } @@ -152,21 +156,21 @@ suil_add_feature(LV2_Feature*** features, const char* uri, void* data) { - for (unsigned i = 0; i < *n && (*features)[i]; ++i) { - if (!strcmp((*features)[i]->URI, uri)) { - (*features)[i]->data = data; - return; - } - } - - *features = (LV2_Feature**)realloc(*features, - sizeof(LV2_Feature*) * (*n + 2)); - - (*features)[*n] = (LV2_Feature*)malloc(sizeof(LV2_Feature)); - (*features)[*n]->URI = uri; - (*features)[*n]->data = data; - (*features)[*n + 1] = NULL; - *n += 1; + for (unsigned i = 0; i < *n && (*features)[i]; ++i) { + if (!strcmp((*features)[i]->URI, uri)) { + (*features)[i]->data = data; + return; + } + } + + *features = + (LV2_Feature**)realloc(*features, sizeof(LV2_Feature*) * (*n + 2)); + + (*features)[*n] = (LV2_Feature*)malloc(sizeof(LV2_Feature)); + (*features)[*n]->URI = uri; + (*features)[*n]->data = data; + (*features)[*n + 1] = NULL; + *n += 1; } extern int suil_argc; @@ -176,4 +180,4 @@ extern char** suil_argv; } /* extern "C" */ #endif -#endif // SUIL_INTERNAL_H +#endif // SUIL_INTERNAL_H diff --git a/src/win_in_gtk2.cpp b/src/win_in_gtk2.cpp index 3bf9dd3..479825a 100644 --- a/src/win_in_gtk2.cpp +++ b/src/win_in_gtk2.cpp @@ -19,14 +19,14 @@ #include "lv2/options/options.h" #include "lv2/urid/urid.h" -#include <gtk/gtk.h> #include <gdk/gdkwin32.h> +#include <gtk/gtk.h> #ifndef WM_MOUSEWHEEL -# define WM_MOUSEWHEEL 0x020A +# define WM_MOUSEWHEEL 0x020A #endif #ifndef WM_MOUSEHWHEEL -# define WM_MOUSEHWHEEL 0x020E +# define WM_MOUSEHWHEEL 0x020E #endif #include <string.h> @@ -34,151 +34,163 @@ extern "C" { #define SUIL_TYPE_WIN_WRAPPER (suil_win_wrapper_get_type()) -#define SUIL_WIN_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_WIN_WRAPPER, SuilWinWrapper)) +#define SUIL_WIN_WRAPPER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_WIN_WRAPPER, SuilWinWrapper)) using SuilWinWrapper = _SuilWinWrapper; using SuilWinWrapperClass = _SuilWinWrapperClass; struct _SuilWinWrapper { - GtkDrawingArea area; - SuilWrapper* wrapper; - SuilInstance* instance; - GdkWindow* flt_win; - const LV2UI_Idle_Interface* idle_iface; - guint idle_id; - guint idle_ms; + GtkDrawingArea area; + SuilWrapper* wrapper; + SuilInstance* instance; + GdkWindow* flt_win; + const LV2UI_Idle_Interface* idle_iface; + guint idle_id; + guint idle_ms; }; struct _SuilWinWrapperClass { - GtkDrawingAreaClass parent_class; + GtkDrawingAreaClass parent_class; }; -GType suil_win_wrapper_get_type(void); // Accessor for SUIL_TYPE_WIN_WRAPPER +GType +suil_win_wrapper_get_type(void); // Accessor for SUIL_TYPE_WIN_WRAPPER G_DEFINE_TYPE(SuilWinWrapper, suil_win_wrapper, GTK_TYPE_DRAWING_AREA) static void suil_win_wrapper_finalize(GObject* gobject) { - SuilWinWrapper* const self = SUIL_WIN_WRAPPER(gobject); + SuilWinWrapper* const self = SUIL_WIN_WRAPPER(gobject); - self->wrapper->impl = nullptr; - self->instance = nullptr; + self->wrapper->impl = nullptr; + self->instance = nullptr; - G_OBJECT_CLASS(suil_win_wrapper_parent_class)->finalize(gobject); + 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 != nullptr); - - 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); - } + SuilWinWrapper* const self = SUIL_WIN_WRAPPER(widget); + g_return_if_fail(self != nullptr); + + 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); - GtkWidgetClass* const widget_class = (GtkWidgetClass*)(klass); + GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GtkWidgetClass* const widget_class = (GtkWidgetClass*)(klass); - widget_class->size_allocate = suil_win_size_allocate; - 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 = nullptr; - self->flt_win = nullptr; - self->idle_iface = nullptr; - self->idle_ms = 1000 / 30; // 30 Hz default + self->instance = nullptr; + self->flt_win = nullptr; + self->idle_iface = nullptr; + self->idle_ms = 1000 / 30; // 30 Hz default } 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 + SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(data); + wrap->idle_iface->idle(wrap->instance->handle); + return TRUE; // Continue calling } static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - gtk_drawing_area_size(GTK_DRAWING_AREA(handle), width, height); - return 0; + gtk_drawing_area_size(GTK_DRAWING_AREA(handle), width, height); + return 0; } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(wrapper->impl); - - instance->host_widget = GTK_WIDGET(wrap); - wrap->wrapper = wrapper; - wrap->instance = instance; - - const LV2UI_Idle_Interface* idle_iface = nullptr; - 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); - } - - return 0; + SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(wrapper->impl); + + instance->host_widget = GTK_WIDGET(wrap); + wrap->wrapper = wrapper; + wrap->instance = instance; + + const LV2UI_Idle_Interface* idle_iface = nullptr; + 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); + } + + return 0; } static GdkFilterReturn event_filter(GdkXEvent* xevent, GdkEvent* event, gpointer data) { - SuilWinWrapper* wrap = (SuilWinWrapper*)data; - MSG* msg = (MSG*)xevent; - if (msg->message == WM_KEYDOWN || msg->message == WM_KEYUP) { - // Forward keyboard events to UI window - PostMessage((HWND)wrap->instance->ui_widget, - msg->message, msg->wParam, msg->lParam); - return GDK_FILTER_REMOVE; - } else if (msg->message == WM_MOUSEWHEEL || msg->message == WM_MOUSEHWHEEL) { - PostMessage((HWND)wrap->instance->ui_widget, - msg->message, msg->wParam, msg->lParam); - return GDK_FILTER_REMOVE; - } - return GDK_FILTER_CONTINUE; + SuilWinWrapper* wrap = (SuilWinWrapper*)data; + MSG* msg = (MSG*)xevent; + if (msg->message == WM_KEYDOWN || msg->message == WM_KEYUP) { + // Forward keyboard events to UI window + PostMessage( + (HWND)wrap->instance->ui_widget, msg->message, msg->wParam, msg->lParam); + return GDK_FILTER_REMOVE; + } + + if (msg->message == WM_MOUSEWHEEL || msg->message == WM_MOUSEHWHEEL) { + PostMessage( + (HWND)wrap->instance->ui_widget, msg->message, msg->wParam, msg->lParam); + return GDK_FILTER_REMOVE; + } + + return GDK_FILTER_CONTINUE; } static void wrapper_free(SuilWrapper* wrapper) { - if (wrapper->impl) { - SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(wrapper->impl); - if (wrap->idle_id) { - g_source_remove(wrap->idle_id); - wrap->idle_id = 0; - } - - gdk_window_remove_filter(wrap->flt_win, event_filter, wrapper->impl); - gtk_object_destroy(GTK_OBJECT(wrap)); - } + if (wrapper->impl) { + SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER(wrapper->impl); + if (wrap->idle_id) { + g_source_remove(wrap->idle_id); + wrap->idle_id = 0; + } + + gdk_window_remove_filter(wrap->flt_win, event_filter, wrapper->impl); + gtk_object_destroy(GTK_OBJECT(wrap)); + } } SUIL_LIB_EXPORT @@ -189,70 +201,69 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - GtkWidget* parent = nullptr; - for (unsigned i = 0; i < n_features; ++i) { - if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { - parent = (GtkWidget*)(*features)[i]->data; - } - } - - if (!GTK_CONTAINER(parent)) { - SUIL_ERRORF("No GtkContainer parent given for %s UI\n", - ui_type_uri); - return nullptr; - } - - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - - SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER( - g_object_new(SUIL_TYPE_WIN_WRAPPER, nullptr)); - - wrap->wrapper = nullptr; - - wrapper->impl = wrap; - wrapper->resize.handle = wrap; - wrapper->resize.ui_resize = wrapper_resize; - - gtk_container_add(GTK_CONTAINER(parent), GTK_WIDGET(wrap)); - gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); - gtk_widget_realize(GTK_WIDGET(wrap)); - - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap)); - - wrap->flt_win = gtk_widget_get_window(parent); - gdk_window_add_filter(wrap->flt_win, event_filter, wrap); - - HWND parent_window = (HWND)GDK_WINDOW_HWND(window); - suil_add_feature(features, &n_features, LV2_UI__parent, parent_window); - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); - - // Scan for URID map and options - LV2_URID_Map* map = nullptr; - LV2_Options_Option* options = nullptr; - 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; - } - } - } - - return wrapper; + GtkWidget* parent = nullptr; + for (unsigned i = 0; i < n_features; ++i) { + if (!strcmp((*features)[i]->URI, LV2_UI__parent)) { + parent = (GtkWidget*)(*features)[i]->data; + } + } + + if (!GTK_CONTAINER(parent)) { + SUIL_ERRORF("No GtkContainer parent given for %s UI\n", ui_type_uri); + return nullptr; + } + + SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + + SuilWinWrapper* const wrap = + SUIL_WIN_WRAPPER(g_object_new(SUIL_TYPE_WIN_WRAPPER, nullptr)); + + wrap->wrapper = nullptr; + + wrapper->impl = wrap; + wrapper->resize.handle = wrap; + wrapper->resize.ui_resize = wrapper_resize; + + gtk_container_add(GTK_CONTAINER(parent), GTK_WIDGET(wrap)); + gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); + gtk_widget_realize(GTK_WIDGET(wrap)); + + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap)); + + wrap->flt_win = gtk_widget_get_window(parent); + gdk_window_add_filter(wrap->flt_win, event_filter, wrap); + + HWND parent_window = (HWND)GDK_WINDOW_HWND(window); + suil_add_feature(features, &n_features, LV2_UI__parent, parent_window); + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); + + // Scan for URID map and options + LV2_URID_Map* map = nullptr; + LV2_Options_Option* options = nullptr; + 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; + } + } + } + + return wrapper; } -} // extern "C" +} // extern "C" @@ -25,6 +25,6 @@ SUIL_LIB_EXPORT void suil_host_init(void) { - // This must be called first for Qt5 in Gtk2 to function correctly - XInitThreads(); + // This must be called first for Qt5 in Gtk2 to function correctly + XInitThreads(); } diff --git a/src/x11_in_gtk2.c b/src/x11_in_gtk2.c index 1364a40..b00035d 100644 --- a/src/x11_in_gtk2.c +++ b/src/x11_in_gtk2.c @@ -39,34 +39,36 @@ #include <string.h> typedef struct { - bool is_set; - int width; - int height; + bool is_set; + int width; + int height; } SuilX11SizeHints; typedef struct { - GtkSocket socket; - GtkPlug* plug; - SuilWrapper* wrapper; - SuilInstance* instance; - const LV2UI_Idle_Interface* idle_iface; - guint idle_id; - guint idle_ms; - SuilX11SizeHints max_size; - SuilX11SizeHints custom_size; - SuilX11SizeHints base_size; - SuilX11SizeHints min_size; - bool query_wm; + GtkSocket socket; + GtkPlug* plug; + SuilWrapper* wrapper; + SuilInstance* instance; + const LV2UI_Idle_Interface* idle_iface; + guint idle_id; + guint idle_ms; + SuilX11SizeHints max_size; + SuilX11SizeHints custom_size; + SuilX11SizeHints base_size; + SuilX11SizeHints min_size; + bool query_wm; } SuilX11Wrapper; typedef struct { - GtkSocketClass parent_class; + GtkSocketClass parent_class; } SuilX11WrapperClass; -GType suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER +GType +suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER #define SUIL_TYPE_X11_WRAPPER (suil_x11_wrapper_get_type()) -#define SUIL_X11_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_X11_WRAPPER, SuilX11Wrapper)) +#define SUIL_X11_WRAPPER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_X11_WRAPPER, SuilX11Wrapper)) G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) @@ -80,456 +82,458 @@ G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) static bool x_window_is_valid(SuilX11Wrapper* socket) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - Window root = 0; - Window parent = 0; - Window* children = NULL; - unsigned childcount = 0; - - XQueryTree(GDK_WINDOW_XDISPLAY(window), - GDK_WINDOW_XID(window), - &root, &parent, &children, &childcount); - for (unsigned i = 0; i < childcount; ++i) { - if (children[i] == (Window)socket->instance->ui_widget) { - XFree(children); - return true; - } - } - if (children) { - XFree(children); - } - return false; + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); + Window root = 0; + Window parent = 0; + Window* children = NULL; + unsigned childcount = 0; + + XQueryTree(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + &root, + &parent, + &children, + &childcount); + + for (unsigned i = 0; i < childcount; ++i) { + if (children[i] == (Window)socket->instance->ui_widget) { + XFree(children); + return true; + } + } + + if (children) { + XFree(children); + } + + return false; } static Window get_parent_window(Display* display, Window child) { - Window root = 0; - Window parent = 0; - Window* children = NULL; - unsigned count = 0; - - if (child) { - if (XQueryTree(display, child, &root, &parent, &children, &count)) { - if (children) { - XFree(children); - } - } - } - - return (parent == root) ? 0 : parent; + Window root = 0; + Window parent = 0; + Window* children = NULL; + unsigned count = 0; + + if (child) { + if (XQueryTree(display, child, &root, &parent, &children, &count)) { + if (children) { + XFree(children); + } + } + } + + return (parent == root) ? 0 : parent; } static gboolean on_plug_removed(GtkSocket* sock, gpointer data) { - (void)data; + (void)data; - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(sock); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(sock); - if (self->idle_id) { - g_source_remove(self->idle_id); - self->idle_id = 0; - } + if (self->idle_id) { + g_source_remove(self->idle_id); + self->idle_id = 0; + } - if (self->instance->handle) { - self->instance->descriptor->cleanup(self->instance->handle); - self->instance->handle = NULL; - } + if (self->instance->handle) { + self->instance->descriptor->cleanup(self->instance->handle); + self->instance->handle = NULL; + } - self->plug = NULL; - return TRUE; + self->plug = NULL; + return TRUE; } static void suil_x11_wrapper_finalize(GObject* gobject) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(gobject); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(gobject); - self->wrapper->impl = NULL; + self->wrapper->impl = NULL; - G_OBJECT_CLASS(suil_x11_wrapper_parent_class)->finalize(gobject); + G_OBJECT_CLASS(suil_x11_wrapper_parent_class)->finalize(gobject); } static void suil_x11_wrapper_realize(GtkWidget* w) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); - GtkSocket* const socket = GTK_SOCKET(w); - - if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize) { - GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize(w); - } - - gtk_socket_add_id(socket, gtk_plug_get_id(wrap->plug)); - - gtk_widget_set_sensitive(GTK_WIDGET(wrap->plug), TRUE); - gtk_widget_set_can_focus(GTK_WIDGET(wrap->plug), TRUE); - gtk_widget_grab_focus(GTK_WIDGET(wrap->plug)); - - // Setup drag/drop proxy from parent/grandparent window - GdkWindow* gwindow = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); - Window xwindow = GDK_WINDOW_XID(gwindow); - Atom xdnd_proxy_atom = gdk_x11_get_xatom_by_name("XdndProxy"); - Window plugin = (Window)wrap->instance->ui_widget; - - while (xwindow) { - XChangeProperty(GDK_WINDOW_XDISPLAY(gwindow), - xwindow, - xdnd_proxy_atom, - XA_WINDOW, - 32, - PropModeReplace, - (unsigned char*)&plugin, - 1); - - xwindow = get_parent_window(GDK_WINDOW_XDISPLAY(gwindow), xwindow); - } + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); + GtkSocket* const socket = GTK_SOCKET(w); + + if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize) { + GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize(w); + } + + gtk_socket_add_id(socket, gtk_plug_get_id(wrap->plug)); + + gtk_widget_set_sensitive(GTK_WIDGET(wrap->plug), TRUE); + gtk_widget_set_can_focus(GTK_WIDGET(wrap->plug), TRUE); + gtk_widget_grab_focus(GTK_WIDGET(wrap->plug)); + + // Setup drag/drop proxy from parent/grandparent window + GdkWindow* gwindow = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); + Window xwindow = GDK_WINDOW_XID(gwindow); + Atom xdnd_proxy_atom = gdk_x11_get_xatom_by_name("XdndProxy"); + Window plugin = (Window)wrap->instance->ui_widget; + + while (xwindow) { + XChangeProperty(GDK_WINDOW_XDISPLAY(gwindow), + xwindow, + xdnd_proxy_atom, + XA_WINDOW, + 32, + PropModeReplace, + (unsigned char*)&plugin, + 1); + + xwindow = get_parent_window(GDK_WINDOW_XDISPLAY(gwindow), xwindow); + } } static void suil_x11_wrapper_show(GtkWidget* w) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); - if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show) { - GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show(w); - } + if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show) { + GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show(w); + } - gtk_widget_show(GTK_WIDGET(wrap->plug)); + gtk_widget_show(GTK_WIDGET(wrap->plug)); } static gboolean -forward_key_event(SuilX11Wrapper* socket, - GdkEvent* gdk_event) +forward_key_event(SuilX11Wrapper* socket, GdkEvent* gdk_event) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - GdkScreen* screen = gdk_visual_get_screen(gdk_window_get_visual(window)); - - Window target_window = 0; - if (gdk_event->any.window == window) { - // Event sent up to the plug window, forward it up to the parent - GtkWidget* widget = GTK_WIDGET(socket->instance->host_widget); - GdkWindow* parent = gtk_widget_get_parent_window(widget); - if (parent) { - target_window = GDK_WINDOW_XID(parent); - } else { - return FALSE; // Wrapper is a top-level window, do nothing - } - } else { - // Event sent anywhere else, send to the plugin - target_window = (Window)socket->instance->ui_widget; - } - - XKeyEvent xev; - memset(&xev, 0, sizeof(xev)); - xev.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; - xev.root = GDK_WINDOW_XID(gdk_screen_get_root_window(screen)); - xev.window = target_window; - xev.subwindow = None; - xev.time = gdk_event->key.time; - xev.state = gdk_event->key.state; - xev.keycode = gdk_event->key.hardware_keycode; - - XSendEvent(GDK_WINDOW_XDISPLAY(window), - target_window, - False, - NoEventMask, - (XEvent*)&xev); - - return (gdk_event->any.window != window); + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); + GdkScreen* screen = gdk_visual_get_screen(gdk_window_get_visual(window)); + + Window target_window = 0; + if (gdk_event->any.window == window) { + // Event sent up to the plug window, forward it up to the parent + GtkWidget* widget = GTK_WIDGET(socket->instance->host_widget); + GdkWindow* parent = gtk_widget_get_parent_window(widget); + if (parent) { + target_window = GDK_WINDOW_XID(parent); + } else { + return FALSE; // Wrapper is a top-level window, do nothing + } + } else { + // Event sent anywhere else, send to the plugin + target_window = (Window)socket->instance->ui_widget; + } + + XKeyEvent xev; + memset(&xev, 0, sizeof(xev)); + xev.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; + xev.root = GDK_WINDOW_XID(gdk_screen_get_root_window(screen)); + xev.window = target_window; + xev.subwindow = None; + xev.time = gdk_event->key.time; + xev.state = gdk_event->key.state; + xev.keycode = gdk_event->key.hardware_keycode; + + XSendEvent(GDK_WINDOW_XDISPLAY(window), + target_window, + False, + NoEventMask, + (XEvent*)&xev); + + return (gdk_event->any.window != window); } static gboolean idle_size_request(gpointer user_data) { - GtkWidget* w = GTK_WIDGET(user_data); - gtk_widget_queue_resize(w); - return FALSE; + GtkWidget* w = GTK_WIDGET(user_data); + gtk_widget_queue_resize(w); + return FALSE; } /// Read XSizeHints and store the values for later use static void query_wm_hints(SuilX11Wrapper* wrap) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); - XSizeHints hints = {0}; - long supplied = 0; - - XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window), - (Window)wrap->instance->ui_widget, - &hints, - &supplied); - - if (hints.flags & PMaxSize) { - wrap->max_size.width = hints.max_width; - wrap->max_size.height = hints.max_height; - wrap->max_size.is_set = true; - } - if (hints.flags & PBaseSize) { - wrap->base_size.width = hints.base_width; - wrap->base_size.height = hints.base_height; - wrap->base_size.is_set = true; - } - if (hints.flags & PMinSize) { - wrap->min_size.width = hints.min_width; - wrap->min_size.height = hints.min_height; - wrap->min_size.is_set = true; - } - - wrap->query_wm = false; + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); + XSizeHints hints = {0}; + long supplied = 0; + + XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window), + (Window)wrap->instance->ui_widget, + &hints, + &supplied); + + if (hints.flags & PMaxSize) { + wrap->max_size.width = hints.max_width; + wrap->max_size.height = hints.max_height; + wrap->max_size.is_set = true; + } + + if (hints.flags & PBaseSize) { + wrap->base_size.width = hints.base_width; + wrap->base_size.height = hints.base_height; + wrap->base_size.is_set = true; + } + + if (hints.flags & PMinSize) { + wrap->min_size.width = hints.min_width; + wrap->min_size.height = hints.min_height; + wrap->min_size.is_set = true; + } + + wrap->query_wm = false; } static void -forward_size_request(SuilX11Wrapper* socket, - GtkAllocation* allocation) +forward_size_request(SuilX11Wrapper* socket, GtkAllocation* allocation) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - if (x_window_is_valid(socket)) { - // Calculate allocation size constrained to X11 limits for widget - int width = allocation->width; - int height = allocation->height; - - if (socket->query_wm) { - query_wm_hints(socket); - } - - if (socket->max_size.is_set) { - width = MIN(width, socket->max_size.width); - height = MIN(height, socket->max_size.height); - } - if (socket->min_size.is_set) { - width = MAX(width, socket->min_size.width); - height = MAX(height, socket->min_size.height); - } - - // Resize widget window - XResizeWindow(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - (unsigned)width, (unsigned)height); - - // Get actual widget geometry - Window root = 0; - int wx = 0; - int wy = 0; - unsigned int ww = 0; - unsigned int wh = 0; - unsigned int ignored = 0; - XGetGeometry(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - &root, - &wx, &wy, &ww, &wh, - &ignored, &ignored); - - // Center widget in allocation - wx = (allocation->width - (int)ww) / 2; - wy = (allocation->height - (int)wh) / 2; - XMoveWindow(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - wx, wy); - } else { - /* Child has not been realized, so unable to resize now. - Queue an idle resize. */ - g_idle_add(idle_size_request, socket->plug); - } + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); + if (x_window_is_valid(socket)) { + // Calculate allocation size constrained to X11 limits for widget + int width = allocation->width; + int height = allocation->height; + + if (socket->query_wm) { + query_wm_hints(socket); + } + + if (socket->max_size.is_set) { + width = MIN(width, socket->max_size.width); + height = MIN(height, socket->max_size.height); + } + + if (socket->min_size.is_set) { + width = MAX(width, socket->min_size.width); + height = MAX(height, socket->min_size.height); + } + + // Resize widget window + XResizeWindow(GDK_WINDOW_XDISPLAY(window), + (Window)socket->instance->ui_widget, + (unsigned)width, + (unsigned)height); + + // Get actual widget geometry + Window root = 0; + int wx = 0; + int wy = 0; + unsigned int ww = 0; + unsigned int wh = 0; + unsigned int ignored = 0; + XGetGeometry(GDK_WINDOW_XDISPLAY(window), + (Window)socket->instance->ui_widget, + &root, + &wx, + &wy, + &ww, + &wh, + &ignored, + &ignored); + + // Center widget in allocation + wx = (allocation->width - (int)ww) / 2; + wy = (allocation->height - (int)wh) / 2; + XMoveWindow( + GDK_WINDOW_XDISPLAY(window), (Window)socket->instance->ui_widget, wx, wy); + } else { + /* Child has not been realized, so unable to resize now. + Queue an idle resize. */ + g_idle_add(idle_size_request, socket->plug); + } } static gboolean -suil_x11_wrapper_key_event(GtkWidget* widget, - GdkEventKey* event) +suil_x11_wrapper_key_event(GtkWidget* widget, GdkEventKey* event) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - if (self->plug) { - return forward_key_event(self, (GdkEvent*)event); - } + if (self->plug) { + return forward_key_event(self, (GdkEvent*)event); + } - return FALSE; + return FALSE; } static void -suil_x11_on_size_request(GtkWidget* widget, - GtkRequisition* requisition) +suil_x11_on_size_request(GtkWidget* widget, GtkRequisition* requisition) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - - if (self->custom_size.is_set) { - requisition->width = self->custom_size.width; - requisition->height = self->custom_size.height; - } else if (self->base_size.is_set) { - requisition->width = self->base_size.width; - requisition->height = self->base_size.height; - } else if (self->min_size.is_set) { - requisition->width = self->min_size.width; - requisition->height = self->min_size.height; - } + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + + if (self->custom_size.is_set) { + requisition->width = self->custom_size.width; + requisition->height = self->custom_size.height; + } else if (self->base_size.is_set) { + requisition->width = self->base_size.width; + requisition->height = self->base_size.height; + } else if (self->min_size.is_set) { + requisition->width = self->min_size.width; + requisition->height = self->min_size.height; + } } static void -suil_x11_on_size_allocate(GtkWidget* widget, - GtkAllocation* a) +suil_x11_on_size_allocate(GtkWidget* widget, GtkAllocation* a) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - - if (self->plug - && GTK_WIDGET_REALIZED(widget) - && GTK_WIDGET_MAPPED(widget) - && GTK_WIDGET_VISIBLE(widget)) { - forward_size_request(self, a); - } + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + + if (self->plug && GTK_WIDGET_REALIZED(widget) && GTK_WIDGET_MAPPED(widget) && + GTK_WIDGET_VISIBLE(widget)) { + forward_size_request(self, a); + } } static void suil_x11_on_map_event(GtkWidget* widget, GdkEvent* event) { - (void)event; - - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - - /* Reset the size request to the minimum sizes. This is called after the - initial size negotiation, where Gtk called suil_x11_on_size_request() to - get the size request, which might be bigger than the minimum size. - However, the Gtk2 size model has no proper way to handle minimum and - default sizes, so hack around this by setting the size request - properties (which really mean minimum size) back to the minimum after - the widget is mapped. This makes it possible for the initial mapping to - use the default size, but still allow the user to resize the widget - smaller, down to the minimum size. */ - - if ((self->custom_size.is_set || self->base_size.is_set) && - self->min_size.is_set) { - g_object_set(G_OBJECT(GTK_WIDGET(self)), - "width-request", self->min_size.width, - "height-request", self->min_size.height, - NULL); - } + (void)event; + + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + + /* Reset the size request to the minimum sizes. This is called after the + initial size negotiation, where Gtk called suil_x11_on_size_request() to + get the size request, which might be bigger than the minimum size. + However, the Gtk2 size model has no proper way to handle minimum and + default sizes, so hack around this by setting the size request + properties (which really mean minimum size) back to the minimum after + the widget is mapped. This makes it possible for the initial mapping to + use the default size, but still allow the user to resize the widget + smaller, down to the minimum size. */ + + if ((self->custom_size.is_set || self->base_size.is_set) && + self->min_size.is_set) { + g_object_set(G_OBJECT(GTK_WIDGET(self)), + "width-request", + self->min_size.width, + "height-request", + self->min_size.height, + NULL); + } } static void suil_x11_wrapper_class_init(SuilX11WrapperClass* klass) { - GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - GtkWidgetClass* const widget_class = GTK_WIDGET_CLASS(klass); - - gobject_class->finalize = suil_x11_wrapper_finalize; - widget_class->realize = suil_x11_wrapper_realize; - widget_class->show = suil_x11_wrapper_show; - widget_class->key_press_event = suil_x11_wrapper_key_event; - widget_class->key_release_event = suil_x11_wrapper_key_event; + GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GtkWidgetClass* const widget_class = GTK_WIDGET_CLASS(klass); + + gobject_class->finalize = suil_x11_wrapper_finalize; + widget_class->realize = suil_x11_wrapper_realize; + widget_class->show = suil_x11_wrapper_show; + widget_class->key_press_event = suil_x11_wrapper_key_event; + widget_class->key_release_event = suil_x11_wrapper_key_event; } static void suil_x11_wrapper_init(SuilX11Wrapper* self) { - self->plug = GTK_PLUG(gtk_plug_new(0)); - self->wrapper = NULL; - self->instance = NULL; - self->idle_iface = NULL; - self->idle_ms = 1000 / 30; // 30 Hz default - self->max_size = (SuilX11SizeHints){false, 0, 0}; - self->custom_size = (SuilX11SizeHints){false, 0, 0}; - self->base_size = (SuilX11SizeHints){false, 0, 0}; - self->min_size = (SuilX11SizeHints){false, 0, 0}; - self->query_wm = true; + self->plug = GTK_PLUG(gtk_plug_new(0)); + self->wrapper = NULL; + self->instance = NULL; + self->idle_iface = NULL; + self->idle_ms = 1000 / 30; // 30 Hz default + self->max_size = (SuilX11SizeHints){false, 0, 0}; + self->custom_size = (SuilX11SizeHints){false, 0, 0}; + self->base_size = (SuilX11SizeHints){false, 0, 0}; + self->min_size = (SuilX11SizeHints){false, 0, 0}; + self->query_wm = true; } static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(handle); + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(handle); - wrap->custom_size.width = width; - wrap->custom_size.height = height; - wrap->custom_size.is_set = width > 0 && height > 0; + wrap->custom_size.width = width; + wrap->custom_size.height = height; + wrap->custom_size.is_set = width > 0 && height > 0; - // Assume the plugin has also updated min/max size constraints - wrap->query_wm = true; + // Assume the plugin has also updated min/max size constraints + wrap->query_wm = true; - gtk_widget_queue_resize(GTK_WIDGET(handle)); - return 0; + gtk_widget_queue_resize(GTK_WIDGET(handle)); + return 0; } static gboolean suil_x11_wrapper_idle(void* data) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(data); + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(data); - wrap->idle_iface->idle(wrap->instance->handle); + wrap->idle_iface->idle(wrap->instance->handle); - return TRUE; // Continue calling + return TRUE; // Continue calling } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); - - instance->host_widget = GTK_WIDGET(wrap); - wrap->wrapper = wrapper; - wrap->instance = instance; - - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); - GdkDisplay* display = gdk_window_get_display(window); - Display* xdisplay = GDK_WINDOW_XDISPLAY(window); - Window xwindow = (Window)instance->ui_widget; - - gdk_display_sync(display); - if (x_window_is_valid(wrap)) { - XWindowAttributes attrs; - XGetWindowAttributes(xdisplay, xwindow, &attrs); - - query_wm_hints(wrap); - - if (!wrap->base_size.is_set) { - // Fall back to using initial size as base size - wrap->base_size.is_set = true; - wrap->base_size.width = attrs.width; - wrap->base_size.height = attrs.height; - } - } - - 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_x11_wrapper_idle, wrap); - } - - g_signal_connect(G_OBJECT(wrap), - "plug-removed", - G_CALLBACK(on_plug_removed), - NULL); - - g_signal_connect(G_OBJECT(wrap), - "size-request", - G_CALLBACK(suil_x11_on_size_request), - NULL); - - g_signal_connect(G_OBJECT(wrap), - "size-allocate", - G_CALLBACK(suil_x11_on_size_allocate), - NULL); - - g_signal_connect(G_OBJECT(wrap), - "map-event", - G_CALLBACK(suil_x11_on_map_event), - NULL); - - return 0; + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); + + instance->host_widget = GTK_WIDGET(wrap); + wrap->wrapper = wrapper; + wrap->instance = instance; + + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); + GdkDisplay* display = gdk_window_get_display(window); + Display* xdisplay = GDK_WINDOW_XDISPLAY(window); + Window xwindow = (Window)instance->ui_widget; + + gdk_display_sync(display); + if (x_window_is_valid(wrap)) { + XWindowAttributes attrs; + XGetWindowAttributes(xdisplay, xwindow, &attrs); + + query_wm_hints(wrap); + + if (!wrap->base_size.is_set) { + // Fall back to using initial size as base size + wrap->base_size.is_set = true; + wrap->base_size.width = attrs.width; + wrap->base_size.height = attrs.height; + } + } + + 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_x11_wrapper_idle, wrap); + } + + g_signal_connect( + G_OBJECT(wrap), "plug-removed", G_CALLBACK(on_plug_removed), NULL); + + g_signal_connect( + G_OBJECT(wrap), "size-request", G_CALLBACK(suil_x11_on_size_request), NULL); + + g_signal_connect(G_OBJECT(wrap), + "size-allocate", + G_CALLBACK(suil_x11_on_size_allocate), + NULL); + + g_signal_connect( + G_OBJECT(wrap), "map-event", G_CALLBACK(suil_x11_on_map_event), NULL); + + return 0; } static void wrapper_free(SuilWrapper* wrapper) { - if (wrapper->impl) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); - gtk_object_destroy(GTK_OBJECT(wrap)); - } + if (wrapper->impl) { + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); + gtk_object_destroy(GTK_OBJECT(wrap)); + } } SUIL_LIB_EXPORT @@ -540,50 +544,50 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - (void)host; - (void)host_type_uri; - (void)ui_type_uri; - - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER( - g_object_new(SUIL_TYPE_X11_WRAPPER, NULL)); - - wrapper->impl = wrap; - wrapper->resize.handle = wrap; - wrapper->resize.ui_resize = wrapper_resize; - - gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); - gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); - - const intptr_t parent_id = (intptr_t)gtk_plug_get_id(wrap->plug); - suil_add_feature(features, &n_features, LV2_UI__parent, (void*)parent_id); - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - 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 = (guint)(1000.0f / *(const float*)o->value); - break; - } - } - } - - return wrapper; + (void)host; + (void)host_type_uri; + (void)ui_type_uri; + + SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + + SuilX11Wrapper* const wrap = + SUIL_X11_WRAPPER(g_object_new(SUIL_TYPE_X11_WRAPPER, NULL)); + + wrapper->impl = wrap; + wrapper->resize.handle = wrap; + wrapper->resize.ui_resize = wrapper_resize; + + gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); + gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); + + const intptr_t parent_id = (intptr_t)gtk_plug_get_id(wrap->plug); + suil_add_feature(features, &n_features, LV2_UI__parent, (void*)parent_id); + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + 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 = (guint)(1000.0f / *(const float*)o->value); + break; + } + } + } + + return wrapper; } diff --git a/src/x11_in_gtk3.c b/src/x11_in_gtk3.c index aa59c05..b22e3e6 100644 --- a/src/x11_in_gtk3.c +++ b/src/x11_in_gtk3.c @@ -39,27 +39,29 @@ #include <string.h> typedef struct { - GtkSocket socket; - GtkPlug* plug; - SuilWrapper* wrapper; - SuilInstance* instance; - const LV2UI_Idle_Interface* idle_iface; - guint idle_id; - guint idle_ms; - int initial_width; - int initial_height; - int req_width; - int req_height; + GtkSocket socket; + GtkPlug* plug; + SuilWrapper* wrapper; + SuilInstance* instance; + const LV2UI_Idle_Interface* idle_iface; + guint idle_id; + guint idle_ms; + int initial_width; + int initial_height; + int req_width; + int req_height; } SuilX11Wrapper; typedef struct { - GtkSocketClass parent_class; + GtkSocketClass parent_class; } SuilX11WrapperClass; -GType suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER +GType +suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER #define SUIL_TYPE_X11_WRAPPER (suil_x11_wrapper_get_type()) -#define SUIL_X11_WRAPPER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_X11_WRAPPER, SuilX11Wrapper)) +#define SUIL_X11_WRAPPER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), SUIL_TYPE_X11_WRAPPER, SuilX11Wrapper)) G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) @@ -73,201 +75,205 @@ G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) static bool x_window_is_valid(SuilX11Wrapper* socket) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - Window root = 0; - Window parent = 0; - Window* children = NULL; - unsigned childcount = 0; - - XQueryTree(GDK_WINDOW_XDISPLAY(window), - GDK_WINDOW_XID(window), - &root, &parent, &children, &childcount); - for (unsigned i = 0; i < childcount; ++i) { - if (children[i] == (Window)socket->instance->ui_widget) { - XFree(children); - return true; - } - } - XFree(children); - return false; + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); + Window root = 0; + Window parent = 0; + Window* children = NULL; + unsigned childcount = 0; + + XQueryTree(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + &root, + &parent, + &children, + &childcount); + for (unsigned i = 0; i < childcount; ++i) { + if (children[i] == (Window)socket->instance->ui_widget) { + XFree(children); + return true; + } + } + + XFree(children); + return false; } static gboolean on_plug_removed(GtkSocket* sock, gpointer data) { - (void)data; + (void)data; - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(sock); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(sock); - if (self->idle_id) { - g_source_remove(self->idle_id); - self->idle_id = 0; - } + if (self->idle_id) { + g_source_remove(self->idle_id); + self->idle_id = 0; + } - if (self->instance->handle) { - self->instance->descriptor->cleanup(self->instance->handle); - self->instance->handle = NULL; - } + if (self->instance->handle) { + self->instance->descriptor->cleanup(self->instance->handle); + self->instance->handle = NULL; + } - self->plug = NULL; - return TRUE; + self->plug = NULL; + return TRUE; } static void suil_x11_wrapper_finalize(GObject* gobject) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(gobject); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(gobject); - self->wrapper->impl = NULL; + self->wrapper->impl = NULL; - G_OBJECT_CLASS(suil_x11_wrapper_parent_class)->finalize(gobject); + G_OBJECT_CLASS(suil_x11_wrapper_parent_class)->finalize(gobject); } static void suil_x11_wrapper_realize(GtkWidget* w) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); - GtkSocket* const socket = GTK_SOCKET(w); + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); + GtkSocket* const socket = GTK_SOCKET(w); - if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize) { - GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize(w); - } + if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize) { + GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->realize(w); + } - gtk_socket_add_id(socket, gtk_plug_get_id(wrap->plug)); + gtk_socket_add_id(socket, gtk_plug_get_id(wrap->plug)); - gtk_widget_realize(GTK_WIDGET(wrap->plug)); + gtk_widget_realize(GTK_WIDGET(wrap->plug)); - gtk_widget_set_sensitive(GTK_WIDGET(wrap->plug), TRUE); - gtk_widget_set_can_focus(GTK_WIDGET(wrap->plug), TRUE); - gtk_widget_grab_focus(GTK_WIDGET(wrap->plug)); + gtk_widget_set_sensitive(GTK_WIDGET(wrap->plug), TRUE); + gtk_widget_set_can_focus(GTK_WIDGET(wrap->plug), TRUE); + gtk_widget_grab_focus(GTK_WIDGET(wrap->plug)); } static void suil_x11_wrapper_show(GtkWidget* w) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(w); - if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show) { - GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show(w); - } + if (GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show) { + GTK_WIDGET_CLASS(suil_x11_wrapper_parent_class)->show(w); + } - gtk_widget_show(GTK_WIDGET(wrap->plug)); + gtk_widget_show(GTK_WIDGET(wrap->plug)); } static gboolean -forward_key_event(SuilX11Wrapper* socket, - GdkEvent* gdk_event) +forward_key_event(SuilX11Wrapper* socket, GdkEvent* gdk_event) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - GdkScreen* screen = gdk_visual_get_screen(gdk_window_get_visual(window)); - - Window target_window = 0; - if (gdk_event->any.window == window) { - // Event sent up to the plug window, forward it up to the parent - GtkWidget* widget = GTK_WIDGET(socket->instance->host_widget); - GdkWindow* parent = gtk_widget_get_parent_window(widget); - if (parent) { - target_window = GDK_WINDOW_XID(parent); - } else { - return FALSE; // Wrapper is a top-level window, do nothing - } - } else { - // Event sent anywhere else, send to the plugin - target_window = (Window)socket->instance->ui_widget; - } - - XKeyEvent xev; - memset(&xev, 0, sizeof(xev)); - xev.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; - xev.root = GDK_WINDOW_XID(gdk_screen_get_root_window(screen)); - xev.window = target_window; - xev.subwindow = None; - xev.time = gdk_event->key.time; - xev.state = gdk_event->key.state; - xev.keycode = gdk_event->key.hardware_keycode; - - XSendEvent(GDK_WINDOW_XDISPLAY(window), - target_window, - False, - NoEventMask, - (XEvent*)&xev); - - return (gdk_event->any.window != window); + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); + GdkScreen* screen = gdk_visual_get_screen(gdk_window_get_visual(window)); + + Window target_window = 0; + if (gdk_event->any.window == window) { + // Event sent up to the plug window, forward it up to the parent + GtkWidget* widget = GTK_WIDGET(socket->instance->host_widget); + GdkWindow* parent = gtk_widget_get_parent_window(widget); + if (parent) { + target_window = GDK_WINDOW_XID(parent); + } else { + return FALSE; // Wrapper is a top-level window, do nothing + } + } else { + // Event sent anywhere else, send to the plugin + target_window = (Window)socket->instance->ui_widget; + } + + XKeyEvent xev; + memset(&xev, 0, sizeof(xev)); + xev.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; + xev.root = GDK_WINDOW_XID(gdk_screen_get_root_window(screen)); + xev.window = target_window; + xev.subwindow = None; + xev.time = gdk_event->key.time; + xev.state = gdk_event->key.state; + xev.keycode = gdk_event->key.hardware_keycode; + + XSendEvent(GDK_WINDOW_XDISPLAY(window), + target_window, + False, + NoEventMask, + (XEvent*)&xev); + + return (gdk_event->any.window != window); } static gboolean idle_size_request(gpointer user_data) { - GtkWidget* w = GTK_WIDGET(user_data); - gtk_widget_queue_resize(w); - return FALSE; + GtkWidget* w = GTK_WIDGET(user_data); + gtk_widget_queue_resize(w); + return FALSE; } static void -forward_size_request(SuilX11Wrapper* socket, - GtkAllocation* allocation) +forward_size_request(SuilX11Wrapper* socket, GtkAllocation* allocation) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - if (x_window_is_valid(socket)) { - // Calculate allocation size constrained to X11 limits for widget - int width = allocation->width; - int height = allocation->height; - XSizeHints hints; - memset(&hints, 0, sizeof(hints)); - XGetNormalHints(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - &hints); - if (hints.flags & PMaxSize) { - width = MIN(width, hints.max_width); - height = MIN(height, hints.max_height); - } - if (hints.flags & PMinSize) { - width = MAX(width, hints.min_width); - height = MAX(height, hints.min_height); - } - - // Resize widget window - XResizeWindow(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - (unsigned)width, (unsigned)height); - - // Get actual widget geometry - Window root = 0; - int wx = 0; - int wy = 0; - unsigned int ww = 0; - unsigned int wh = 0; - unsigned int ignored = 0; - XGetGeometry(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - &root, - &wx, &wy, &ww, &wh, - &ignored, &ignored); - - // Center widget in allocation - wx = (allocation->width - (int)ww) / 2; - wy = (allocation->height - (int)wh) / 2; - XMoveWindow(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - wx, wy); - } else { - /* Child has not been realized, so unable to resize now. - Queue an idle resize. */ - g_idle_add(idle_size_request, socket->plug); - } + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); + if (x_window_is_valid(socket)) { + // Calculate allocation size constrained to X11 limits for widget + int width = allocation->width; + int height = allocation->height; + XSizeHints hints; + memset(&hints, 0, sizeof(hints)); + XGetNormalHints( + GDK_WINDOW_XDISPLAY(window), (Window)socket->instance->ui_widget, &hints); + if (hints.flags & PMaxSize) { + width = MIN(width, hints.max_width); + height = MIN(height, hints.max_height); + } + if (hints.flags & PMinSize) { + width = MAX(width, hints.min_width); + height = MAX(height, hints.min_height); + } + + // Resize widget window + XResizeWindow(GDK_WINDOW_XDISPLAY(window), + (Window)socket->instance->ui_widget, + (unsigned)width, + (unsigned)height); + + // Get actual widget geometry + Window root = 0; + int wx = 0; + int wy = 0; + unsigned int ww = 0; + unsigned int wh = 0; + unsigned int ignored = 0; + XGetGeometry(GDK_WINDOW_XDISPLAY(window), + (Window)socket->instance->ui_widget, + &root, + &wx, + &wy, + &ww, + &wh, + &ignored, + &ignored); + + // Center widget in allocation + wx = (allocation->width - (int)ww) / 2; + wy = (allocation->height - (int)wh) / 2; + XMoveWindow( + GDK_WINDOW_XDISPLAY(window), (Window)socket->instance->ui_widget, wx, wy); + } else { + /* Child has not been realized, so unable to resize now. + Queue an idle resize. */ + g_idle_add(idle_size_request, socket->plug); + } } static gboolean -suil_x11_wrapper_key_event(GtkWidget* widget, - GdkEventKey* event) +suil_x11_wrapper_key_event(GtkWidget* widget, GdkEventKey* event) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - if (self->plug) { - return forward_key_event(self, (GdkEvent*)event); - } + if (self->plug) { + return forward_key_event(self, (GdkEvent*)event); + } - return FALSE; + return FALSE; } static void @@ -275,24 +281,23 @@ suil_x11_wrapper_get_preferred_width(GtkWidget* widget, gint* minimum_width, gint* natural_width) { - - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - if (x_window_is_valid(self)) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(self->plug)); - XSizeHints hints; - memset(&hints, 0, sizeof(hints)); - long supplied = 0; - XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window), - (Window)self->instance->ui_widget, - &hints, - &supplied); - *natural_width = ((hints.flags & PBaseSize) ? hints.base_width - : self->initial_width); - *minimum_width = ((hints.flags & PMinSize) ? hints.min_width - : self->req_width); - } else { - *natural_width = *minimum_width = self->req_width; - } + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + if (x_window_is_valid(self)) { + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(self->plug)); + XSizeHints hints; + memset(&hints, 0, sizeof(hints)); + long supplied = 0; + XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window), + (Window)self->instance->ui_widget, + &hints, + &supplied); + *natural_width = + ((hints.flags & PBaseSize) ? hints.base_width : self->initial_width); + *minimum_width = + ((hints.flags & PMinSize) ? hints.min_width : self->req_width); + } else { + *natural_width = *minimum_width = self->req_width; + } } static void @@ -300,141 +305,136 @@ suil_x11_wrapper_get_preferred_height(GtkWidget* widget, gint* minimum_height, gint* natural_height) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - if (x_window_is_valid(self)) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(self->plug)); - XSizeHints hints; - memset(&hints, 0, sizeof(hints)); - long supplied = 0; - XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window), - (Window)self->instance->ui_widget, - &hints, - &supplied); - *natural_height = ((hints.flags & PBaseSize) ? hints.base_height - : self->initial_height); - *minimum_height = ((hints.flags & PMinSize) ? hints.min_height - : self->req_height); - } else { - *natural_height = *minimum_height = self->req_height; - } + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + if (x_window_is_valid(self)) { + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(self->plug)); + XSizeHints hints; + memset(&hints, 0, sizeof(hints)); + long supplied = 0; + XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window), + (Window)self->instance->ui_widget, + &hints, + &supplied); + *natural_height = + ((hints.flags & PBaseSize) ? hints.base_height : self->initial_height); + *minimum_height = + ((hints.flags & PMinSize) ? hints.min_height : self->req_height); + } else { + *natural_height = *minimum_height = self->req_height; + } } static void -suil_x11_on_size_allocate(GtkWidget* widget, - GtkAllocation* a) +suil_x11_on_size_allocate(GtkWidget* widget, GtkAllocation* a) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - - if (self->plug - && gtk_widget_get_realized(widget) - && gtk_widget_get_mapped(widget) - && gtk_widget_get_visible(widget)) { - forward_size_request(self, a); - } + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + + if (self->plug && gtk_widget_get_realized(widget) && + gtk_widget_get_mapped(widget) && gtk_widget_get_visible(widget)) { + forward_size_request(self, a); + } } static void suil_x11_wrapper_class_init(SuilX11WrapperClass* klass) { - GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - GtkWidgetClass* const widget_class = GTK_WIDGET_CLASS(klass); - - gobject_class->finalize = suil_x11_wrapper_finalize; - widget_class->realize = suil_x11_wrapper_realize; - widget_class->show = suil_x11_wrapper_show; - widget_class->key_press_event = suil_x11_wrapper_key_event; - widget_class->key_release_event = suil_x11_wrapper_key_event; - widget_class->get_preferred_width = suil_x11_wrapper_get_preferred_width; - widget_class->get_preferred_height = suil_x11_wrapper_get_preferred_height; + GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); + GtkWidgetClass* const widget_class = GTK_WIDGET_CLASS(klass); + + gobject_class->finalize = suil_x11_wrapper_finalize; + widget_class->realize = suil_x11_wrapper_realize; + widget_class->show = suil_x11_wrapper_show; + widget_class->key_press_event = suil_x11_wrapper_key_event; + widget_class->key_release_event = suil_x11_wrapper_key_event; + widget_class->get_preferred_width = suil_x11_wrapper_get_preferred_width; + widget_class->get_preferred_height = suil_x11_wrapper_get_preferred_height; } static void suil_x11_wrapper_init(SuilX11Wrapper* self) { - self->plug = GTK_PLUG(gtk_plug_new(0)); - self->wrapper = NULL; - self->instance = NULL; - self->idle_iface = NULL; - self->idle_ms = 1000 / 30; // 30 Hz default - self->req_width = 0; - self->req_height = 0; + self->plug = GTK_PLUG(gtk_plug_new(0)); + self->wrapper = NULL; + self->instance = NULL; + self->idle_iface = NULL; + self->idle_ms = 1000 / 30; // 30 Hz default + self->req_width = 0; + self->req_height = 0; } static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(handle); + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(handle); - wrap->req_width = width; - wrap->req_height = height; + wrap->req_width = width; + wrap->req_height = height; - gtk_widget_queue_resize(GTK_WIDGET(handle)); - return 0; + gtk_widget_queue_resize(GTK_WIDGET(handle)); + return 0; } static gboolean suil_x11_wrapper_idle(void* data) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(data); + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(data); - wrap->idle_iface->idle(wrap->instance->handle); + wrap->idle_iface->idle(wrap->instance->handle); - return TRUE; // Continue calling + return TRUE; // Continue calling } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); - - instance->host_widget = GTK_WIDGET(wrap); - wrap->wrapper = wrapper; - wrap->instance = instance; - - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); - GdkDisplay* display = gdk_window_get_display(window); - Display* xdisplay = GDK_WINDOW_XDISPLAY(window); - Window xwindow = (Window)instance->ui_widget; - - gdk_display_sync(display); - - XWindowAttributes attrs; - XGetWindowAttributes(xdisplay, xwindow, &attrs); - wrap->initial_width = attrs.width; - wrap->initial_height = attrs.height; - - 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_x11_wrapper_idle, wrap); - } - - g_signal_connect(G_OBJECT(wrap), - "plug-removed", - G_CALLBACK(on_plug_removed), - NULL); - - g_signal_connect(G_OBJECT(wrap), - "size-allocate", - G_CALLBACK(suil_x11_on_size_allocate), - NULL); - - return 0; + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); + + instance->host_widget = GTK_WIDGET(wrap); + wrap->wrapper = wrapper; + wrap->instance = instance; + + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); + GdkDisplay* display = gdk_window_get_display(window); + Display* xdisplay = GDK_WINDOW_XDISPLAY(window); + Window xwindow = (Window)instance->ui_widget; + + gdk_display_sync(display); + + XWindowAttributes attrs; + XGetWindowAttributes(xdisplay, xwindow, &attrs); + wrap->initial_width = attrs.width; + wrap->initial_height = attrs.height; + + 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_x11_wrapper_idle, wrap); + } + + g_signal_connect( + G_OBJECT(wrap), "plug-removed", G_CALLBACK(on_plug_removed), NULL); + + g_signal_connect(G_OBJECT(wrap), + "size-allocate", + G_CALLBACK(suil_x11_on_size_allocate), + NULL); + + return 0; } static void wrapper_free(SuilWrapper* wrapper) { - if (wrapper->impl) { - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); - gtk_widget_destroy(GTK_WIDGET(wrap)); - } + if (wrapper->impl) { + SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(wrapper->impl); + gtk_widget_destroy(GTK_WIDGET(wrap)); + } } SUIL_LIB_EXPORT @@ -445,50 +445,50 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - (void)host; - (void)host_type_uri; - (void)ui_type_uri; - - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER( - g_object_new(SUIL_TYPE_X11_WRAPPER, NULL)); - - wrapper->impl = wrap; - wrapper->resize.handle = wrap; - wrapper->resize.ui_resize = wrapper_resize; - - gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); - gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); - - const intptr_t parent_id = (intptr_t)gtk_plug_get_id(wrap->plug); - suil_add_feature(features, &n_features, LV2_UI__parent, (void*)parent_id); - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - 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 = (guint)(1000.0f / *(const float*)o->value); - break; - } - } - } - - return wrapper; + (void)host; + (void)host_type_uri; + (void)ui_type_uri; + + SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; + + SuilX11Wrapper* const wrap = + SUIL_X11_WRAPPER(g_object_new(SUIL_TYPE_X11_WRAPPER, NULL)); + + wrapper->impl = wrap; + wrapper->resize.handle = wrap; + wrapper->resize.ui_resize = wrapper_resize; + + gtk_widget_set_sensitive(GTK_WIDGET(wrap), TRUE); + gtk_widget_set_can_focus(GTK_WIDGET(wrap), TRUE); + + const intptr_t parent_id = (intptr_t)gtk_plug_get_id(wrap->plug); + suil_add_feature(features, &n_features, LV2_UI__parent, (void*)parent_id); + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + 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 = (guint)(1000.0f / *(const float*)o->value); + break; + } + } + } + + return wrapper; } diff --git a/src/x11_in_qt4.cpp b/src/x11_in_qt4.cpp index 9acb842..914609f 100644 --- a/src/x11_in_qt4.cpp +++ b/src/x11_in_qt4.cpp @@ -25,97 +25,100 @@ extern "C" { struct SuilX11InQt4Wrapper { - QX11EmbedContainer* host_widget; - QX11EmbedWidget* parent; + QX11EmbedContainer* host_widget; + QX11EmbedWidget* parent; }; class SuilQX11Container : public QX11EmbedContainer { public: - SuilQX11Container(SuilInstance* instance, - const LV2UI_Idle_Interface* idle_iface, - QX11EmbedWidget* widget) - : QX11EmbedContainer() - , _instance(instance) - , _idle_iface(idle_iface) - , _widget(widget) - , _ui_timer(0) - {} + SuilQX11Container(SuilInstance* instance, + const LV2UI_Idle_Interface* idle_iface, + QX11EmbedWidget* widget) + : QX11EmbedContainer() + , _instance(instance) + , _idle_iface(idle_iface) + , _widget(widget) + , _ui_timer(0) + {} protected: - void showEvent(QShowEvent* event) { - if (_idle_iface && _ui_timer == 0) { - _ui_timer = this->startTimer(30); - _widget->embedInto(winId()); - resize(_widget->size()); - } - QX11EmbedContainer::showEvent(event); - } - - void timerEvent(QTimerEvent* event) { - if (event->timerId() == _ui_timer && _idle_iface) { - _idle_iface->idle(_instance->handle); - } - QX11EmbedContainer::timerEvent(event); - } - - void closeEvent(QCloseEvent* event) { - if (_ui_timer && _idle_iface) { - this->killTimer(_ui_timer); - _ui_timer = 0; - } - QX11EmbedContainer::closeEvent(event); - } + void showEvent(QShowEvent* event) + { + if (_idle_iface && _ui_timer == 0) { + _ui_timer = this->startTimer(30); + _widget->embedInto(winId()); + resize(_widget->size()); + } + QX11EmbedContainer::showEvent(event); + } + + void timerEvent(QTimerEvent* event) + { + if (event->timerId() == _ui_timer && _idle_iface) { + _idle_iface->idle(_instance->handle); + } + QX11EmbedContainer::timerEvent(event); + } + + void closeEvent(QCloseEvent* event) + { + if (_ui_timer && _idle_iface) { + this->killTimer(_ui_timer); + _ui_timer = 0; + } + QX11EmbedContainer::closeEvent(event); + } private: - SuilInstance* const _instance; - const LV2UI_Idle_Interface* const _idle_iface; - QX11EmbedWidget* const _widget; - int _ui_timer; + SuilInstance* const _instance; + const LV2UI_Idle_Interface* const _idle_iface; + QX11EmbedWidget* const _widget; + int _ui_timer; }; static void wrapper_free(SuilWrapper* wrapper) { - SuilX11InQt4Wrapper* impl = (SuilX11InQt4Wrapper*)wrapper->impl; + SuilX11InQt4Wrapper* impl = (SuilX11InQt4Wrapper*)wrapper->impl; - if (impl->parent) { - delete impl->parent; - } + if (impl->parent) { + delete impl->parent; + } - if (impl->host_widget) { - delete impl->host_widget; - } + if (impl->host_widget) { + delete impl->host_widget; + } - free(impl); + free(impl); } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - const LV2UI_Idle_Interface* idle_iface = nullptr; - if (instance->descriptor->extension_data) { - idle_iface = (const LV2UI_Idle_Interface*) - instance->descriptor->extension_data(LV2_UI__idleInterface); - } + const LV2UI_Idle_Interface* idle_iface = nullptr; + if (instance->descriptor->extension_data) { + idle_iface = + (const LV2UI_Idle_Interface*)instance->descriptor->extension_data( + LV2_UI__idleInterface); + } - SuilX11InQt4Wrapper* const impl = (SuilX11InQt4Wrapper*)wrapper->impl; - QX11EmbedWidget* const ew = impl->parent; + SuilX11InQt4Wrapper* const impl = (SuilX11InQt4Wrapper*)wrapper->impl; + QX11EmbedWidget* const ew = impl->parent; - impl->host_widget = new SuilQX11Container(instance, idle_iface, ew); + impl->host_widget = new SuilQX11Container(instance, idle_iface, ew); - instance->host_widget = impl->host_widget; + instance->host_widget = impl->host_widget; - return 0; + return 0; } static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - QX11EmbedWidget* const ew = (QX11EmbedWidget*)handle; - ew->resize(width, height); - return 0; + QX11EmbedWidget* const ew = (QX11EmbedWidget*)handle; + ew->resize(width, height); + return 0; } SUIL_LIB_EXPORT @@ -126,27 +129,27 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features) { - SuilX11InQt4Wrapper* const impl = (SuilX11InQt4Wrapper*) - calloc(1, sizeof(SuilX11InQt4Wrapper)); + SuilX11InQt4Wrapper* const impl = + (SuilX11InQt4Wrapper*)calloc(1, sizeof(SuilX11InQt4Wrapper)); - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; + SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; - QX11EmbedWidget* const ew = new QX11EmbedWidget(); + QX11EmbedWidget* const ew = new QX11EmbedWidget(); - impl->parent = ew; + impl->parent = ew; - wrapper->impl = impl; - wrapper->resize.handle = ew; - wrapper->resize.ui_resize = wrapper_resize; + wrapper->impl = impl; + wrapper->resize.handle = ew; + wrapper->resize.ui_resize = wrapper_resize; - const intptr_t parent_id = (intptr_t)ew->winId(); - suil_add_feature(features, &n_features, LV2_UI__parent, (void*)parent_id); - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); + const intptr_t parent_id = (intptr_t)ew->winId(); + suil_add_feature(features, &n_features, LV2_UI__parent, (void*)parent_id); + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); - return wrapper; + return wrapper; } -} // extern "C" +} // extern "C" diff --git a/src/x11_in_qt5.cpp b/src/x11_in_qt5.cpp index 41defa2..b4f24bc 100644 --- a/src/x11_in_qt5.cpp +++ b/src/x11_in_qt5.cpp @@ -41,167 +41,164 @@ extern "C" { class SuilQX11Widget : public QWidget { public: - SuilQX11Widget(QWidget* parent, Qt::WindowFlags wflags) - : QWidget(parent, wflags) - , _instance(nullptr) - , _idle_iface(nullptr) - , _window(0) - , _ui_timer(0) - {} - - SuilQX11Widget(const SuilQX11Widget&) = delete; - SuilQX11Widget& operator=(const SuilQX11Widget&) = delete; - - SuilQX11Widget(SuilQX11Widget&&) = delete; - SuilQX11Widget& operator=(SuilQX11Widget&&) = delete; - - ~SuilQX11Widget() override; - - void start_idle(SuilInstance* instance, - const LV2UI_Idle_Interface* idle_iface) - { - _instance = instance; - _idle_iface = idle_iface; - if (_idle_iface && _ui_timer == 0) { - _ui_timer = this->startTimer(30, Qt::CoarseTimer); - } - } - - void set_window(Window window) - { - _window = window; - } - - QSize sizeHint() const override - { - if (_window) { - XWindowAttributes attrs{}; - XGetWindowAttributes(QX11Info::display(), _window, &attrs); - return {attrs.width, attrs.height}; - } - - return {0, 0}; - } - - QSize minimumSizeHint() const override - { - if (_window) { - XSizeHints hints{}; - long supplied{}; - XGetWMNormalHints(QX11Info::display(), _window, &hints, &supplied); - if ((hints.flags & PMinSize)) { - return {hints.min_width, hints.min_height}; - } - } - - return {0, 0}; - } + SuilQX11Widget(QWidget* parent, Qt::WindowFlags wflags) + : QWidget(parent, wflags) + , _instance(nullptr) + , _idle_iface(nullptr) + , _window(0) + , _ui_timer(0) + {} + + SuilQX11Widget(const SuilQX11Widget&) = delete; + SuilQX11Widget& operator=(const SuilQX11Widget&) = delete; + + SuilQX11Widget(SuilQX11Widget&&) = delete; + SuilQX11Widget& operator=(SuilQX11Widget&&) = delete; + + ~SuilQX11Widget() override; + + void start_idle(SuilInstance* instance, + const LV2UI_Idle_Interface* idle_iface) + { + _instance = instance; + _idle_iface = idle_iface; + if (_idle_iface && _ui_timer == 0) { + _ui_timer = this->startTimer(30, Qt::CoarseTimer); + } + } + + void set_window(Window window) { _window = window; } + + QSize sizeHint() const override + { + if (_window) { + XWindowAttributes attrs{}; + XGetWindowAttributes(QX11Info::display(), _window, &attrs); + return {attrs.width, attrs.height}; + } + + return {0, 0}; + } + + QSize minimumSizeHint() const override + { + if (_window) { + XSizeHints hints{}; + long supplied{}; + XGetWMNormalHints(QX11Info::display(), _window, &hints, &supplied); + if ((hints.flags & PMinSize)) { + return {hints.min_width, hints.min_height}; + } + } + + return {0, 0}; + } protected: - void resizeEvent(QResizeEvent* event) override - { - QWidget::resizeEvent(event); - - if (_window) { - XResizeWindow(QX11Info::display(), - _window, - (unsigned)event->size().width(), - (unsigned)event->size().height()); - } - } - - void timerEvent(QTimerEvent* event) override - { - if (event->timerId() == _ui_timer && _idle_iface) { - _idle_iface->idle(_instance->handle); - } - QWidget::timerEvent(event); - } - - void closeEvent(QCloseEvent* event) override - { - if (_ui_timer && _idle_iface) { - this->killTimer(_ui_timer); - _ui_timer = 0; - } - QWidget::closeEvent(event); - } + void resizeEvent(QResizeEvent* event) override + { + QWidget::resizeEvent(event); + + if (_window) { + XResizeWindow(QX11Info::display(), + _window, + (unsigned)event->size().width(), + (unsigned)event->size().height()); + } + } + + void timerEvent(QTimerEvent* event) override + { + if (event->timerId() == _ui_timer && _idle_iface) { + _idle_iface->idle(_instance->handle); + } + + QWidget::timerEvent(event); + } + + void closeEvent(QCloseEvent* event) override + { + if (_ui_timer && _idle_iface) { + this->killTimer(_ui_timer); + _ui_timer = 0; + } + + QWidget::closeEvent(event); + } private: - SuilInstance* _instance; - const LV2UI_Idle_Interface* _idle_iface; - Window _window; - int _ui_timer; + SuilInstance* _instance; + const LV2UI_Idle_Interface* _idle_iface; + Window _window; + int _ui_timer; }; SuilQX11Widget::~SuilQX11Widget() = default; struct SuilX11InQt5Wrapper { - QWidget* host_widget; - SuilQX11Widget* parent; + QWidget* host_widget; + SuilQX11Widget* parent; }; static void wrapper_free(SuilWrapper* wrapper) { - auto* impl = (SuilX11InQt5Wrapper*)wrapper->impl; + auto* impl = (SuilX11InQt5Wrapper*)wrapper->impl; - delete impl->host_widget; + delete impl->host_widget; - free(impl); + free(impl); } static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) +wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) { - auto* const impl = (SuilX11InQt5Wrapper*)wrapper->impl; - SuilQX11Widget* const ew = impl->parent; - Display* const display = QX11Info::display(); - const auto window = (Window)instance->ui_widget; + auto* const impl = (SuilX11InQt5Wrapper*)wrapper->impl; + SuilQX11Widget* const ew = impl->parent; + Display* const display = QX11Info::display(); + const auto window = (Window)instance->ui_widget; - XWindowAttributes attrs{}; - XSizeHints hints{}; - long supplied{}; - XSync(display, False); - XGetWindowAttributes(display, window, &attrs); - XGetWMNormalHints(display, window, &hints, &supplied); + XWindowAttributes attrs{}; + XSizeHints hints{}; + long supplied{}; + XSync(display, False); + XGetWindowAttributes(display, window, &attrs); + XGetWMNormalHints(display, window, &hints, &supplied); - impl->parent->set_window(window); + impl->parent->set_window(window); - if ((hints.flags & PBaseSize)) { - impl->parent->setBaseSize(hints.base_width, hints.base_height); - } + if ((hints.flags & PBaseSize)) { + impl->parent->setBaseSize(hints.base_width, hints.base_height); + } - if ((hints.flags & PMinSize)) { - impl->parent->setMinimumSize(hints.min_width, hints.min_height); - } + if ((hints.flags & PMinSize)) { + impl->parent->setMinimumSize(hints.min_width, hints.min_height); + } - if ((hints.flags & PMaxSize)) { - impl->parent->setMaximumSize(hints.max_width, hints.max_height); - } + if ((hints.flags & PMaxSize)) { + impl->parent->setMaximumSize(hints.max_width, hints.max_height); + } - if (instance->descriptor->extension_data) { - const auto* idle_iface = - (const LV2UI_Idle_Interface*)instance->descriptor->extension_data( - LV2_UI__idleInterface); + if (instance->descriptor->extension_data) { + const auto* idle_iface = + (const LV2UI_Idle_Interface*)instance->descriptor->extension_data( + LV2_UI__idleInterface); - ew->start_idle(instance, idle_iface); - } + ew->start_idle(instance, idle_iface); + } - impl->host_widget = ew; + impl->host_widget = ew; + instance->host_widget = impl->host_widget; - instance->host_widget = impl->host_widget; - - return 0; + return 0; } static int wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) { - auto* const ew = (QWidget*)handle; - ew->resize(width, height); - return 0; + auto* const ew = (QWidget*)handle; + ew->resize(width, height); + return 0; } SUIL_LIB_EXPORT @@ -212,27 +209,27 @@ suil_wrapper_new(SuilHost*, LV2_Feature*** features, unsigned n_features) { - auto* const impl = - (SuilX11InQt5Wrapper*)calloc(1, sizeof(SuilX11InQt5Wrapper)); + auto* const impl = + (SuilX11InQt5Wrapper*)calloc(1, sizeof(SuilX11InQt5Wrapper)); - auto* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; + auto* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); + wrapper->wrap = wrapper_wrap; + wrapper->free = wrapper_free; - auto* const ew = new SuilQX11Widget(nullptr, Qt::Window); + auto* const ew = new SuilQX11Widget(nullptr, Qt::Window); - impl->parent = ew; + impl->parent = ew; - wrapper->impl = impl; - wrapper->resize.handle = ew; - wrapper->resize.ui_resize = wrapper_resize; + wrapper->impl = impl; + wrapper->resize.handle = ew; + wrapper->resize.ui_resize = wrapper_resize; - void* parent_id = (void*)(intptr_t)ew->winId(); - suil_add_feature(features, &n_features, LV2_UI__parent, parent_id); - suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); - suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); + void* parent_id = (void*)(intptr_t)ew->winId(); + suil_add_feature(features, &n_features, LV2_UI__parent, parent_id); + suil_add_feature(features, &n_features, LV2_UI__resize, &wrapper->resize); + suil_add_feature(features, &n_features, LV2_UI__idleInterface, nullptr); - return wrapper; + return wrapper; } -} // extern "C" +} // extern "C" |