diff options
author | David Robillard <d@drobilla.net> | 2019-03-17 17:31:05 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-03-17 17:31:05 +0100 |
commit | 406f89271452fdb573c7e28113b1ed08ff2b4eda (patch) | |
tree | d2dcbaf61f3749f73dc7a5e10d3fc6cd5e6e129a /src | |
parent | 7983a5aae615290d04fd43cbc2752f8cf4a46d10 (diff) | |
download | suil-406f89271452fdb573c7e28113b1ed08ff2b4eda.tar.gz suil-406f89271452fdb573c7e28113b1ed08ff2b4eda.tar.bz2 suil-406f89271452fdb573c7e28113b1ed08ff2b4eda.zip |
Squashed 'waflib/' changes from 915dcb1..e7a29b6
e7a29b6 Upgrade to waf 2.0.15
8280f9d Add command for running executables from the build directory
8073c1a Make make_simple_dox() safe in case of exception
70d03b8 Avoid use of global counter hacks for configuration display
b7d689a Rewrite test framework
94deadf Automatically add options and move add_flags() to options context
f4259ee Reduce system include path noise
927b608 Automatically display configuration header
c44b8f3 Set line justification from a constant in the wscript
a48e26f Automatically detect if wscript has a test hook
ef66724 Save runtime variables in the environment
63bcbcd Clean up TestContext
b1d9505 Add ExecutionContext for setting runtime environment
387c1df Add show_diff() and test_file_equals() utilities
29d4d29 Fix in-tree library paths
9fde01f Add custom configuration context
6d3612f Add lib_path_name constant
git-subtree-dir: waflib
git-subtree-split: e7a29b6b9b2f842314244c23c14d8f8f560904e1
Diffstat (limited to 'src')
-rw-r--r-- | src/cocoa_in_gtk2.mm | 433 | ||||
-rw-r--r-- | src/cocoa_in_qt5.mm | 166 | ||||
-rw-r--r-- | src/gtk2_in_qt4.cpp | 147 | ||||
-rw-r--r-- | src/gtk2_in_qt5.cpp | 157 | ||||
-rw-r--r-- | src/host.c | 90 | ||||
-rw-r--r-- | src/instance.c | 390 | ||||
-rw-r--r-- | src/qt4_in_gtk2.cpp | 154 | ||||
-rw-r--r-- | src/qt5_in_gtk2.cpp | 229 | ||||
-rw-r--r-- | src/suil_internal.h | 185 | ||||
-rw-r--r-- | src/win_in_gtk2.cpp | 258 | ||||
-rw-r--r-- | src/x11.c | 28 | ||||
-rw-r--r-- | src/x11_in_gtk2.c | 398 | ||||
-rw-r--r-- | src/x11_in_gtk3.c | 402 | ||||
-rw-r--r-- | src/x11_in_qt4.cpp | 151 | ||||
-rw-r--r-- | src/x11_in_qt5.cpp | 148 |
15 files changed, 0 insertions, 3336 deletions
diff --git a/src/cocoa_in_gtk2.mm b/src/cocoa_in_gtk2.mm deleted file mode 100644 index 3ff87d0..0000000 --- a/src/cocoa_in_gtk2.mm +++ /dev/null @@ -1,433 +0,0 @@ -/* - Copyright 2011-2017 David Robillard <http://drobilla.net> - Copyright 2014 Robin Gareus <robin@gareus.org> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <string.h> - -#include <gtk/gtk.h> -#include <gdk/gdkquartz.h> - -#include "./suil_internal.h" - -#include "lv2/lv2plug.in/ns/ext/options/options.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" - -#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 -#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)) - -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; -}; - -struct _SuilCocoaWrapperClass { - GtkWidgetClass parent_class; -}; - -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); - - self->wrapper->impl = NULL; - - 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); -} - -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)); - } -} - -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; - - if (!self->mapped) { - return; - } - - 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)]; -} - -static void -suil_cocoa_map(GtkWidget* widget) -{ - SuilCocoaWrapper* const self = SUIL_COCOA_WRAPPER(widget); - self->mapped = true; - - 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); - - 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; - - 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; -} - -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; -} - -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; -} - -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; -} - -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 -} - -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; -} - -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 -} - -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; -} - -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; -} - -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)); - } -} - - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - 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; -} - -} // extern "C" diff --git a/src/cocoa_in_qt5.mm b/src/cocoa_in_qt5.mm deleted file mode 100644 index 4259075..0000000 --- a/src/cocoa_in_qt5.mm +++ /dev/null @@ -1,166 +0,0 @@ -/* - Copyright 2017 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#import <Cocoa/Cocoa.h> - -#include <QCloseEvent> -#include <QMacCocoaViewContainer> -#include <QTimerEvent> -#include <QWidget> - -#undef signals - -#include "./suil_config.h" -#include "./suil_internal.h" - -extern "C" { - -typedef struct { - 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); - } - } - -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); - } - -private: - SuilInstance* _instance; - const LV2UI_Idle_Interface* _idle_iface; - int _ui_timer; -}; - -static void -wrapper_free(SuilWrapper* wrapper) -{ - SuilCocoaInQt5Wrapper* impl = (SuilCocoaInQt5Wrapper*)wrapper->impl; - - if (impl->host_widget) { - delete impl->host_widget; - } - - free(impl); -} - -static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) -{ - 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); - } - - impl->host_widget = ew; - - instance->host_widget = impl->host_widget; - - 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; -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - 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; - } - } - - 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)); - - SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - NSView* view = [NSView new]; - - SuilQCocoaWidget* const ew = new SuilQCocoaWidget(view, parent); - - impl->parent = ew; - - 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); - - return wrapper; -} - -} // extern "C" diff --git a/src/gtk2_in_qt4.cpp b/src/gtk2_in_qt4.cpp deleted file mode 100644 index 546f7a9..0000000 --- a/src/gtk2_in_qt4.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - Copyright 2011-2015 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <QX11EmbedContainer> -#undef signals - -#include <gtk/gtk.h> -#include <gdk/gdkx.h> - -#include "./suil_config.h" -#include "./suil_internal.h" - -extern "C" { - -typedef struct _SuilGtk2InQt4Wrapper SuilGtk2InQt4Wrapper; - -struct _SuilGtk2InQt4Wrapper { - QX11EmbedContainer* host_widget; - QWidget* parent; - GtkWidget* plug; -}; - -static void -on_size_request(GtkWidget* widget, - GtkRequisition* requisition, - gpointer user_data) -{ - QX11EmbedContainer* const wrap = (QX11EmbedContainer*)user_data; - wrap->setMinimumSize(requisition->width, requisition->height); -} - -static void -on_size_allocate(GtkWidget* widget, - GdkRectangle* allocation, - gpointer user_data) -{ - QX11EmbedContainer* const wrap = (QX11EmbedContainer*)user_data; - wrap->resize(allocation->width, allocation->height); -} - -static void -wrapper_free(SuilWrapper* wrapper) -{ - SuilGtk2InQt4Wrapper* impl = (SuilGtk2InQt4Wrapper*)wrapper->impl; - - if (impl->plug) { - gtk_widget_destroy(impl->plug); - } - - if (impl->host_widget) { - delete impl->host_widget; - } - - free(impl); -} - -static int -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; - - gtk_container_add(GTK_CONTAINER(plug), widget); - gtk_widget_show_all(plug); - -#ifdef SUIL_OLD_GTK - wrap->resize(widget->allocation.width, widget->allocation.height); -#else - 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-allocate", G_CALLBACK(on_size_allocate), wrap); - - impl->host_widget = wrap; - impl->plug = plug; - instance->host_widget = wrap; - - return 0; -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - 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) { - dlerror(); - host->gtk_lib = dlopen(SUIL_GTK2_LIB_NAME, RTLD_LAZY|RTLD_GLOBAL); - if (!host->gtk_lib) { - SUIL_ERRORF("Failed to open %s (%s)\n", - SUIL_GTK2_LIB_NAME, dlerror()); - return NULL; - } - gtk_init(NULL, NULL); - } - - /* 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" diff --git a/src/gtk2_in_qt5.cpp b/src/gtk2_in_qt5.cpp deleted file mode 100644 index 50b9012..0000000 --- a/src/gtk2_in_qt5.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - Copyright 2011-2015 David Robillard <http://drobilla.net> - Copyright 2015 Rui Nuno Capela <rncbc@rncbc.org> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <QVBoxLayout> -#include <QWidget> -#include <QWindow> - -#undef signals - -#include <gtk/gtk.h> - -#include "./suil_config.h" -#include "./suil_internal.h" - -extern "C" { - -typedef struct _SuilGtk2InQt5Wrapper SuilGtk2InQt5Wrapper; - -struct _SuilGtk2InQt5Wrapper { - QWidget* host_widget; - QWindow* window; - GtkWidget* plug; -}; - -static void -on_size_request(GtkWidget* widget, - GtkRequisition* requisition, - gpointer user_data) -{ - QWidget* const wrap = (QWidget*)user_data; - wrap->setMinimumSize(requisition->width, requisition->height); -} - -static void -on_size_allocate(GtkWidget* widget, - GdkRectangle* allocation, - gpointer user_data) -{ - QWidget* const wrap = (QWidget*)user_data; - wrap->resize(allocation->width, allocation->height); -} - -static void -wrapper_free(SuilWrapper* wrapper) -{ - SuilGtk2InQt5Wrapper* impl = (SuilGtk2InQt5Wrapper*)wrapper->impl; - - if (impl->window) { - impl->window->setParent(NULL); - delete impl->window; - } - - if (impl->plug) { - gtk_widget_destroy(impl->plug); - } - - if (impl->host_widget) { - delete impl->host_widget; - } - - free(impl); -} - -static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) -{ - SuilGtk2InQt5Wrapper* const impl = (SuilGtk2InQt5Wrapper*)wrapper->impl; - QWidget* const wrap = new QWidget(NULL, Qt::Window); - GtkWidget* const plug = gtk_plug_new(0); - GtkWidget* const widget = (GtkWidget*)instance->ui_widget; - - 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); - QVBoxLayout* layout = new QVBoxLayout(); - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(container); - wrap->setLayout(layout); - -#ifdef SUIL_OLD_GTK - wrap->resize(widget->allocation.width, widget->allocation.height); -#else - 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-allocate", G_CALLBACK(on_size_allocate), wrap); - - impl->host_widget = wrap; - impl->window = window; - impl->plug = plug; - instance->host_widget = wrap; - - return 0; -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - 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) { - dlerror(); - host->gtk_lib = dlopen(SUIL_GTK2_LIB_NAME, RTLD_LAZY|RTLD_GLOBAL); - if (!host->gtk_lib) { - SUIL_ERRORF("Failed to open %s (%s)\n", - SUIL_GTK2_LIB_NAME, dlerror()); - return NULL; - } - gtk_init(NULL, NULL); - } - - /* Create wrapper implementation. */ - SuilGtk2InQt5Wrapper* const impl = (SuilGtk2InQt5Wrapper*) - calloc(1, sizeof(SuilGtk2InQt5Wrapper)); - - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - wrapper->impl = impl; - - return wrapper; -} - -} // extern "C" diff --git a/src/host.c b/src/host.c deleted file mode 100644 index f64f9c5..0000000 --- a/src/host.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright 2011-2017 David Robillard <http://drobilla.net> - Copyright 2017 Stefan Westerfeld <stefan@space.twc.de> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "./suil_internal.h" - -int suil_argc = 0; -char** suil_argv = NULL; - -SUIL_API -SuilHost* -suil_host_new(SuilPortWriteFunc write_func, - SuilPortIndexFunc index_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; -} - -SUIL_API -void -suil_host_set_touch_func(SuilHost* host, - SuilTouchFunc touch_func) -{ - host->touch_func = touch_func; -} - -SUIL_API -void -suil_host_free(SuilHost* host) -{ - if (host) { - if (host->gtk_lib) { - dlclose(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); - } - - dlclose(lib); -} -#endif - -SUIL_API -void -suil_init(int* argc, char*** argv, SuilArg key, ...) -{ - suil_argc = argc ? *argc : 0; - suil_argv = argv ? *argv : NULL; - -#ifdef SUIL_WITH_X11 - suil_load_init_module("suil_x11"); -#endif -} diff --git a/src/instance.c b/src/instance.c deleted file mode 100644 index d365ca2..0000000 --- a/src/instance.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - Copyright 2007-2017 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "./suil_config.h" -#include "./suil_internal.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 COCOA_UI_URI LV2_UI__CocoaUI - -SUIL_API -unsigned -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; - } else 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, 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; - } else { - return SUIL_WRAPPING_UNSUPPORTED; - } -} - -static SuilWrapper* -open_wrapper(SuilHost* host, - const char* container_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features) -{ - 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"; - } -#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"; - } -#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"; - } -#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"; - } -#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"; - } -#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"; - } -#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"; - } -#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"; - } -#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"; - } -#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"; - } -#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"; - } -#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); - dlclose(lib); - } - - return wrapper; -} - -SUIL_API -SuilInstance* -suil_instance_new(SuilHost* host, - SuilController controller, - const char* container_type_uri, - const char* plugin_uri, - const char* ui_uri, - const char* ui_type_uri, - const char* ui_bundle_path, - const char* ui_binary_path, - const LV2_Feature* const* features) -{ - // Open UI library - dlerror(); - void* lib = dlopen(ui_binary_path, RTLD_NOW); - if (!lib) { - SUIL_ERRORF("Unable to open UI library %s (%s)\n", - ui_binary_path, dlerror()); - 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); - dlclose(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; - } else 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); - dlclose(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); - dlclose(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); - } - - dlclose(instance->lib_handle); - - // Close libraries and free everything - if (instance->wrapper) { -#ifndef _WIN32 - // Never unload modules on windows, causes mysterious segfaults - dlclose(instance->wrapper->lib); -#endif - free(instance->wrapper); - } - free(instance); - } -} - -SUIL_API -SuilHandle -suil_instance_get_handle(SuilInstance* instance) -{ - return instance->handle; -} - -SUIL_API -LV2UI_Widget -suil_instance_get_widget(SuilInstance* instance) -{ - return instance->host_widget; -} - -SUIL_API -void -suil_instance_port_event(SuilInstance* instance, - uint32_t port_index, - uint32_t buffer_size, - uint32_t format, - const void* 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) -{ - 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 deleted file mode 100644 index fbec381..0000000 --- a/src/qt4_in_gtk2.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright 2011-2017 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <gtk/gtk.h> - -#include <QApplication> -#include <QVBoxLayout> -#include <QX11EmbedWidget> - -#include "./suil_internal.h" - -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)) - -typedef struct _SuilQtWrapper SuilQtWrapper; -typedef struct _SuilQtWrapperClass SuilQtWrapperClass; - -struct _SuilQtWrapper { - GtkSocket socket; - QApplication* app; - QX11EmbedWidget* qembed; - SuilWrapper* wrapper; - SuilInstance* instance; -}; - -struct _SuilQtWrapperClass { - GtkSocketClass parent_class; -}; - -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); - - if (self->instance->handle) { - self->instance->descriptor->cleanup(self->instance->handle); - self->instance->handle = NULL; - } - - delete self->qembed; - - self->qembed = NULL; - self->app = NULL; - self->wrapper->impl = NULL; - - 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); - - gobject_class->finalize = suil_qt_wrapper_finalize; -} - -static void -suil_qt_wrapper_init(SuilQtWrapper* self) -{ - self->app = NULL; - self->qembed = NULL; - self->instance = NULL; -} - -static void -suil_qt_wrapper_realize(GtkWidget* w, gpointer data) -{ - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(w); - GtkSocket* const s = GTK_SOCKET(w); - - gtk_socket_add_id(s, wrap->qembed->winId()); - wrap->qembed->show(); -} - -static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) -{ - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); - - 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->setParent(wrap->qembed); - - g_signal_connect_after(G_OBJECT(wrap), "realize", - G_CALLBACK(suil_qt_wrapper_realize), NULL); - - instance->host_widget = GTK_WIDGET(wrap); - - 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)); - } -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features) -{ - 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, NULL)); - - if (qApp) { - wrap->app = qApp; - } else { - wrap->app = new QApplication(host->argc, host->argv, true); - } - - wrap->wrapper = NULL; - wrapper->impl = wrap; - - return wrapper; -} - -} // extern "C" diff --git a/src/qt5_in_gtk2.cpp b/src/qt5_in_gtk2.cpp deleted file mode 100644 index 4c77c4d..0000000 --- a/src/qt5_in_gtk2.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - Copyright 2011-2017 David Robillard <http://drobilla.net> - Copyright 2018 Rui Nuno Capela <rncbc@rncbc.org> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <gtk/gtk.h> - -#include <QVBoxLayout> -#include <QWidget> -#include <QWindow> - -#include "lv2/lv2plug.in/ns/ext/options/options.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" - -#include "./suil_internal.h" - -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)) - -typedef struct _SuilQtWrapper SuilQtWrapper; -typedef struct _SuilQtWrapperClass SuilQtWrapperClass; - -struct _SuilQtWrapper { - 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; -}; - -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); - - 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->qembed) { - self->qembed->deleteLater(); - } - - self->qembed = NULL; - self->idle_iface = NULL; - self->wrapper->impl = NULL; - - 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); - - gobject_class->finalize = suil_qt_wrapper_finalize; -} - -static void -suil_qt_wrapper_init(SuilQtWrapper* self) -{ - self->qembed = NULL; - self->wrapper = NULL; - self->instance = NULL; - self->idle_iface = NULL; - self->idle_id = 0; - self->idle_ms = 1000 / 30; // 30 Hz default -} - -static void -suil_qt_wrapper_realize(GtkWidget* w, gpointer data) -{ - 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(); -} - -static int -suil_qt_wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) -{ - gtk_widget_set_size_request(GTK_WIDGET(handle), width, height); - - return 0; -} - -static gboolean -suil_qt_wrapper_idle(void* data) -{ - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(data); - - if (wrap->idle_iface) { - wrap->idle_iface->idle(wrap->instance->handle); - return TRUE; // Continue calling - } - - return FALSE; -} - -static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) -{ - SuilQtWrapper* const wrap = SUIL_QT_WRAPPER(wrapper->impl); - - wrap->qembed = new QWidget(); - wrap->wrapper = wrapper; - wrap->instance = instance; - - QWidget* qwidget = (QWidget*)instance->ui_widget; - QVBoxLayout* layout = new QVBoxLayout(); - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(qwidget); - - wrap->qembed->setLayout(layout); - - g_signal_connect_after(G_OBJECT(wrap), "realize", - G_CALLBACK(suil_qt_wrapper_realize), NULL); - - instance->host_widget = GTK_WIDGET(wrap); - - 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_qt_wrapper_idle, wrap); - } - - 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)); - } -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features) -{ - 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, NULL)); - - wrap->wrapper = NULL; - 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, 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" diff --git a/src/suil_internal.h b/src/suil_internal.h deleted file mode 100644 index ecafbcf..0000000 --- a/src/suil_internal.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - Copyright 2007-2017 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#ifndef SUIL_INTERNAL_H -#define SUIL_INTERNAL_H - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef _WIN32 -#include <windows.h> -#define dlopen(path, flags) LoadLibrary(path) -#define dlclose(lib) FreeLibrary((HMODULE)lib) -#define inline __inline -#define snprintf _snprintf -static inline char* dlerror(void) { return "Unknown error"; } -#else -#include <dlfcn.h> -#endif - -#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" - -#include "suil/suil.h" -#include "./suil_config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#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; -}; - -struct _SuilWrapper; - -typedef void (*SuilWrapperFreeFunc)(struct _SuilWrapper*); - -typedef int (*SuilWrapperWrapFunc)(struct _SuilWrapper* wrapper, - SuilInstance* instance); - -typedef struct _SuilWrapper { - 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; -}; - -/** - The type of the suil_wrapper_new entry point in a wrapper module. - - This constructs a SuilWrapper which contains everything necessary - to wrap a widget, including a possibly extended features array to - be used for instantiating the UI. -*/ -typedef SuilWrapper* (*SuilWrapperNewFunc)(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features); - -/** Prototype for suil_wrapper_new in each wrapper module. */ -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features); - -/** Prototype for suil_host_init in each init module. */ -SUIL_LIB_EXPORT -void -suil_host_init(void); - -/** Dynamically load the suil module with the given name. */ -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); - - dlerror(); - void* lib = dlopen(path, RTLD_NOW); - if (!lib) { - SUIL_ERRORF("Failed to open module %s (%s)\n", path, dlerror()); - } - - free(path); - return lib; -} - -typedef void (*SuilVoidFunc)(void); - -/** dlsym wrapper to return a function pointer (without annoying warning) */ -static inline SuilVoidFunc -suil_dlfunc(void* handle, const char* symbol) -{ -#ifdef _WIN32 - return (SuilVoidFunc)GetProcAddress((HMODULE)handle, symbol); -#else - typedef SuilVoidFunc (*VoidFuncGetter)(void*, const char*); - VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym; - return dlfunc(handle, symbol); -#endif -} - -/** Add a feature to a (mutable) LV2 feature array. */ -static inline void -suil_add_feature(LV2_Feature*** features, - unsigned* n, - 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; -} - -extern int suil_argc; -extern char** suil_argv; - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif // SUIL_INTERNAL_H diff --git a/src/win_in_gtk2.cpp b/src/win_in_gtk2.cpp deleted file mode 100644 index 70c7c1a..0000000 --- a/src/win_in_gtk2.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - Copyright 2011-2015 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <string.h> - -#include <gtk/gtk.h> -#include <gdk/gdkwin32.h> - -#ifndef WM_MOUSEWHEEL -# define WM_MOUSEWHEEL 0x020A -#endif -#ifndef WM_MOUSEHWHEEL -# define WM_MOUSEHWHEEL 0x020E -#endif - -#include "./suil_internal.h" - -#include "lv2/lv2plug.in/ns/ext/options/options.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" - -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)) - -typedef struct _SuilWinWrapper SuilWinWrapper; -typedef struct _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; -}; - -struct _SuilWinWrapperClass { - GtkDrawingAreaClass parent_class; -}; - -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); - - self->wrapper->impl = NULL; - self->instance = NULL; - - G_OBJECT_CLASS(suil_win_wrapper_parent_class)->finalize(gobject); -} - -static void -suil_win_size_allocate(GtkWidget* widget, GtkAllocation* allocation) -{ - SuilWinWrapper* const self = SUIL_WIN_WRAPPER(widget); - g_return_if_fail(self != NULL); - - widget->allocation = *allocation; - if (gtk_widget_get_realized(widget)) { - gdk_window_move_resize(widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); - - RECT wr = { 0, 0, (long)allocation->width, (long)allocation->height }; - AdjustWindowRectEx(&wr, WS_CHILD, FALSE, WS_EX_TOPMOST); - - SetWindowPos((HWND)self->instance->ui_widget, HWND_NOTOPMOST, - 0, 0, wr.right - wr.left, wr.bottom - wr.top, - SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); - UpdateWindow((HWND)self->instance->ui_widget); - PostMessage((HWND)self->instance->ui_widget, WM_PAINT, 0, 0); - } -} - -static void -suil_win_wrapper_class_init(SuilWinWrapperClass* klass) -{ - GObjectClass* const gobject_class = G_OBJECT_CLASS(klass); - GtkWidgetClass* const widget_class = (GtkWidgetClass*)(klass); - - widget_class->size_allocate = suil_win_size_allocate; - gobject_class->finalize = suil_win_wrapper_finalize; -} - -static void -suil_win_wrapper_init(SuilWinWrapper* self) -{ - self->instance = NULL; - self->flt_win = NULL; - self->idle_iface = NULL; - 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 -} - -static int -wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) -{ - gtk_drawing_area_size(GTK_DRAWING_AREA(handle), width, height); - return 0; -} - -static int -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 = NULL; - if (instance->descriptor->extension_data) { - idle_iface = (const LV2UI_Idle_Interface*) - instance->descriptor->extension_data(LV2_UI__idleInterface); - } - if (idle_iface) { - wrap->idle_iface = idle_iface; - wrap->idle_id = g_timeout_add (wrap->idle_ms, suil_win_wrapper_idle, wrap); - } - - 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; -} - -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)); - } -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - 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; - - SuilWinWrapper* const wrap = SUIL_WIN_WRAPPER( - g_object_new(SUIL_TYPE_WIN_WRAPPER, NULL)); - - wrap->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); - - 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, 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" diff --git a/src/x11.c b/src/x11.c deleted file mode 100644 index 4c8a15a..0000000 --- a/src/x11.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright 2017 David Robillard <http://drobilla.net> - Copyright 2017 Stefan Westerfeld <stefan@space.twc.de> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <X11/Xlib.h> - -#include "./suil_internal.h" - -SUIL_LIB_EXPORT -void -suil_host_init(void) -{ - // 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 deleted file mode 100644 index 7ec9592..0000000 --- a/src/x11_in_gtk2.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - Copyright 2011-2016 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <gdk/gdkx.h> -#include <gtk/gtk.h> -#include <string.h> - -#include "lv2/lv2plug.in/ns/ext/options/options.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" - -#include "./suil_internal.h" - -#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)) - -typedef struct _SuilX11Wrapper SuilX11Wrapper; -typedef struct _SuilX11WrapperClass SuilX11WrapperClass; - -struct _SuilX11Wrapper { - GtkSocket socket; - GtkPlug* plug; - SuilWrapper* wrapper; - SuilInstance* instance; - const LV2UI_Idle_Interface* idle_iface; - guint idle_id; - guint idle_ms; -}; - -struct _SuilX11WrapperClass { - GtkSocketClass parent_class; -}; - -GType suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER - -G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) - -/** - Check if 'swallowed' subwindow is known to the X server. - - Gdk/GTK can mark the window as realized, mapped and visible even though - there is no window-ID on the X server for it yet. Then, - suil_x11_on_size_allocate() will cause a "BadWinow" X error. -*/ -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; -} - -static gboolean -on_plug_removed(GtkSocket* sock, gpointer data) -{ - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(sock); - - 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; - } - - self->plug = NULL; - return TRUE; -} - -static void -suil_x11_wrapper_finalize(GObject* gobject) -{ - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(gobject); - - self->wrapper->impl = NULL; - - 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)); -} - -static void -suil_x11_wrapper_show(GtkWidget* 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); - } - - gtk_widget_show(GTK_WIDGET(wrap->plug)); -} - -static gboolean -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; - 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; -} - -static void -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, - width, height); - - // Get actual widget geometry - Window root; - int wx, wy; - unsigned int ww, wh; - unsigned int ignored; - XGetGeometry(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - &root, - &wx, &wy, &ww, &wh, - &ignored, &ignored); - - // Center widget in allocation - wx = (allocation->width - ww) / 2; - wy = (allocation->height - 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) -{ - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - - if (self->plug) { - return forward_key_event(self, (GdkEvent*)event); - } - - return FALSE; -} - -static void -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); - } -} - -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; -} - -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 -} - -static int -wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) -{ - gtk_widget_set_size_request(GTK_WIDGET(handle), width, height); - return 0; -} - -static gboolean -suil_x11_wrapper_idle(void* data) -{ - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(data); - - wrap->idle_iface->idle(wrap->instance->handle); - - return TRUE; // Continue calling -} - -static int -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; - - 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_object_destroy(GTK_OBJECT(wrap)); - } -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features) -{ - 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 = 1000.0f / *(const float*)o->value; - break; - } - } - } - - return wrapper; -} diff --git a/src/x11_in_gtk3.c b/src/x11_in_gtk3.c deleted file mode 100644 index 0c016c9..0000000 --- a/src/x11_in_gtk3.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - Copyright 2011-2016 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <string.h> - -#include <gdk/gdkx.h> -#include <gtk/gtk.h> -#include <gtk/gtkx.h> - -#include "./suil_internal.h" - -#include "lv2/lv2plug.in/ns/ext/options/options.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" - -#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)) - -typedef struct _SuilX11Wrapper SuilX11Wrapper; -typedef struct _SuilX11WrapperClass SuilX11WrapperClass; - -struct _SuilX11Wrapper { - GtkSocket socket; - GtkPlug* plug; - SuilWrapper* wrapper; - SuilInstance* instance; - const LV2UI_Idle_Interface* idle_iface; - guint idle_id; - guint idle_ms; -}; - -struct _SuilX11WrapperClass { - GtkSocketClass parent_class; -}; - -GType suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER - -G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) - -/** - Check if 'swallowed' subwindow is known to the X server. - - Gdk/GTK can mark the window as realized, mapped and visible even though - there is no window-ID on the X server for it yet. Then, - suil_x11_on_size_allocate() will cause a "BadWinow" X error. -*/ -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; -} - -static gboolean -on_plug_removed(GtkSocket* sock, gpointer data) -{ - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(sock); - - 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; - } - - self->plug = NULL; - return TRUE; -} - -static void -suil_x11_wrapper_finalize(GObject* gobject) -{ - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(gobject); - - self->wrapper->impl = NULL; - - 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_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)); -} - -static void -suil_x11_wrapper_show(GtkWidget* 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); - } - - gtk_widget_show(GTK_WIDGET(wrap->plug)); -} - -static gboolean -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; - 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; -} - -static void -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, - width, height); - - // Get actual widget geometry - Window root; - int wx, wy; - unsigned int ww, wh; - unsigned int ignored; - XGetGeometry(GDK_WINDOW_XDISPLAY(window), - (Window)socket->instance->ui_widget, - &root, - &wx, &wy, &ww, &wh, - &ignored, &ignored); - - // Center widget in allocation - wx = (allocation->width - ww) / 2; - wy = (allocation->height - 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) -{ - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - - if (self->plug) { - return forward_key_event(self, (GdkEvent*)event); - } - - return FALSE; -} - -static void -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); - } -} - -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; -} - -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 -} - -static int -wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) -{ - gtk_widget_set_size_request(GTK_WIDGET(handle), width, height); - return 0; -} - -static gboolean -suil_x11_wrapper_idle(void* data) -{ - SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(data); - - wrap->idle_iface->idle(wrap->instance->handle); - - return TRUE; // Continue calling -} - -static int -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; - - 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)); - } -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features) -{ - 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 = 1000.0f / *(const float*)o->value; - break; - } - } - } - - return wrapper; -} diff --git a/src/x11_in_qt4.cpp b/src/x11_in_qt4.cpp deleted file mode 100644 index c21357d..0000000 --- a/src/x11_in_qt4.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright 2011-2015 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <QX11EmbedContainer> -#include <QtEvents> -#undef signals - -#include "./suil_config.h" -#include "./suil_internal.h" - -extern "C" { - -typedef struct { - QX11EmbedContainer* host_widget; - QX11EmbedWidget* parent; -} SuilX11InQt4Wrapper; - -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) - {} - -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); - } - -private: - 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; - - if (impl->parent) { - delete impl->parent; - } - - if (impl->host_widget) { - delete impl->host_widget; - } - - free(impl); -} - -static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* 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); - } - - SuilX11InQt4Wrapper* const impl = (SuilX11InQt4Wrapper*)wrapper->impl; - QX11EmbedWidget* const ew = impl->parent; - - impl->host_widget = new SuilQX11Container(instance, idle_iface, ew); - - instance->host_widget = impl->host_widget; - - 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; -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features) -{ - SuilX11InQt4Wrapper* const impl = (SuilX11InQt4Wrapper*) - calloc(1, sizeof(SuilX11InQt4Wrapper)); - - SuilWrapper* wrapper = (SuilWrapper*)calloc(1, sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - - QX11EmbedWidget* const ew = new QX11EmbedWidget(); - - impl->parent = ew; - - 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, NULL); - - return wrapper; -} - -} // extern "C" diff --git a/src/x11_in_qt5.cpp b/src/x11_in_qt5.cpp deleted file mode 100644 index be90323..0000000 --- a/src/x11_in_qt5.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright 2011-2015 David Robillard <http://drobilla.net> - Copyright 2015 Rui Nuno Capela <rncbc@rncbc.org> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <QWidget> - -#include <QTimerEvent> -#include <QCloseEvent> - -#undef signals - -#include "./suil_config.h" -#include "./suil_internal.h" - -extern "C" { - -typedef struct { - QWidget* host_widget; - QWidget* parent; -} SuilX11InQt5Wrapper; - -class SuilQX11Widget : public QWidget -{ -public: - SuilQX11Widget(QWidget* parent, Qt::WindowFlags wflags) - : QWidget(parent, wflags) - , _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; - 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); - } - -private: - SuilInstance* _instance; - const LV2UI_Idle_Interface* _idle_iface; - int _ui_timer; -}; - -static void -wrapper_free(SuilWrapper* wrapper) -{ - SuilX11InQt5Wrapper* impl = (SuilX11InQt5Wrapper*)wrapper->impl; - - if (impl->host_widget) { - delete impl->host_widget; - } - - free(impl); -} - -static int -wrapper_wrap(SuilWrapper* wrapper, - SuilInstance* instance) -{ - SuilX11InQt5Wrapper* const impl = (SuilX11InQt5Wrapper*)wrapper->impl; - SuilQX11Widget* const ew = (SuilQX11Widget*)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); - } - - impl->host_widget = ew; - - instance->host_widget = impl->host_widget; - - return 0; -} - -static int -wrapper_resize(LV2UI_Feature_Handle handle, int width, int height) -{ - QWidget* const ew = (QWidget*)handle; - ew->resize(width, height); - return 0; -} - -SUIL_LIB_EXPORT -SuilWrapper* -suil_wrapper_new(SuilHost* host, - const char* host_type_uri, - const char* ui_type_uri, - LV2_Feature*** features, - unsigned n_features) -{ - SuilX11InQt5Wrapper* const impl = (SuilX11InQt5Wrapper*) - calloc(1, sizeof(SuilX11InQt5Wrapper)); - - SuilWrapper* wrapper = (SuilWrapper*)malloc(sizeof(SuilWrapper)); - wrapper->wrap = wrapper_wrap; - wrapper->free = wrapper_free; - - QWidget* const ew = new SuilQX11Widget(NULL, Qt::Window); - - impl->parent = ew; - - 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, NULL); - - return wrapper; -} - -} // extern "C" |