|
- /*
- * Carla Bridge UI
- * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a full copy of the GNU General Public License see the doc/GPL.txt file.
- */
-
- #include "CarlaBridgeFormat.hpp"
- #include "CarlaBridgeToolkit.hpp"
-
- #include <gtk/gtk.h>
-
- #ifdef HAVE_X11
- # include <gdk/gdkx.h>
- #endif
-
- CARLA_BRIDGE_UI_START_NAMESPACE
-
- // -------------------------------------------------------------------------
-
- static int gargc = 0;
- static char** gargv = nullptr;
-
- static const bool gHideShowTesting = std::getenv("CARLA_UI_TESTING") != nullptr;
-
- // -------------------------------------------------------------------------
-
- class CarlaBridgeToolkitGtk : public CarlaBridgeToolkit
- {
- public:
- CarlaBridgeToolkitGtk(CarlaBridgeFormat* const format)
- : CarlaBridgeToolkit(format),
- fNeedsShow(false),
- fWindow(nullptr),
- fLastX(0),
- fLastY(0),
- fLastWidth(0),
- fLastHeight(0)
- {
- carla_debug("CarlaBridgeToolkitGtk::CarlaBridgeToolkitGtk(%p)", format);
- }
-
- ~CarlaBridgeToolkitGtk() override
- {
- CARLA_SAFE_ASSERT(fWindow == nullptr);
- carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()");
- }
-
- bool init(const int /*argc*/, const char** /*argv[]*/) override
- {
- CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr, false);
- carla_debug("CarlaBridgeToolkitGtk::init()");
-
- gtk_init(&gargc, &gargv);
-
- fWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr, false);
-
- gtk_window_resize(GTK_WINDOW(fWindow), 30, 30);
- gtk_widget_hide(fWindow);
-
- return true;
- }
-
- void exec(const bool showUI) override
- {
- CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
- carla_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI));
-
- const CarlaBridgeFormat::Options& options(fPlugin->getOptions());
-
- GtkWindow* const gtkWindow(GTK_WINDOW(fWindow));
- CARLA_SAFE_ASSERT_RETURN(gtkWindow != nullptr,);
-
- GtkWidget* const widget((GtkWidget*)fPlugin->getWidget());
- gtk_container_add(GTK_CONTAINER(fWindow), widget);
-
- gtk_window_set_resizable(gtkWindow, options.isResizable);
- gtk_window_set_title(gtkWindow, options.windowTitle.buffer());
-
- if (showUI || fNeedsShow)
- {
- show();
- fNeedsShow = false;
- }
-
- g_timeout_add(30, gtk_ui_timeout, this);
- g_signal_connect(fWindow, "destroy", G_CALLBACK(gtk_ui_destroy), this);
- g_signal_connect(fWindow, "realize", G_CALLBACK(gtk_ui_realize), this);
-
- // First idle
- handleTimeout();
-
- // Main loop
- gtk_main();
- }
-
- void quit() override
- {
- carla_debug("CarlaBridgeToolkitGtk::quit()");
-
- if (fWindow != nullptr)
- {
- gtk_widget_destroy(fWindow);
- fWindow = nullptr;
-
- gtk_main_quit_if_needed();
- }
- }
-
- void show() override
- {
- carla_debug("CarlaBridgeToolkitGtk::show()");
-
- fNeedsShow = true;
-
- if (fWindow != nullptr)
- gtk_widget_show_all(fWindow);
- }
-
- void focus() override
- {
- carla_debug("CarlaBridgeToolkitGtk::focus()");
- }
-
- void hide() override
- {
- carla_debug("CarlaBridgeToolkitGtk::hide()");
-
- fNeedsShow = false;
-
- if (fWindow != nullptr)
- gtk_widget_hide(fWindow);
- }
-
- void setSize(const uint width, const uint height) override
- {
- CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
- carla_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height);
-
- gtk_window_resize(GTK_WINDOW(fWindow), static_cast<gint>(width), static_cast<gint>(height));
- }
-
- void setTitle(const char* const title) override
- {
- CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
- carla_debug("CarlaBridgeToolkitGtk::setTitle(\"%s\")", title);
-
- gtk_window_set_title(GTK_WINDOW(fWindow), title);
- }
-
- // ---------------------------------------------------------------------
-
- protected:
- bool fNeedsShow;
- GtkWidget* fWindow;
-
- gint fLastX;
- gint fLastY;
- gint fLastWidth;
- gint fLastHeight;
-
- void handleDestroy()
- {
- carla_debug("CarlaBridgeToolkitGtk::handleDestroy()");
-
- fWindow = nullptr;
- }
-
- void handleRealize()
- {
- carla_debug("CarlaBridgeToolkitGtk::handleRealize()");
-
- const CarlaBridgeFormat::Options& options(fPlugin->getOptions());
-
- if (options.transientWindowId != 0)
- setTransient(options.transientWindowId);
- }
-
- gboolean handleTimeout()
- {
- if (fWindow != nullptr)
- {
- gtk_window_get_position(GTK_WINDOW(fWindow), &fLastX, &fLastY);
- gtk_window_get_size(GTK_WINDOW(fWindow), &fLastWidth, &fLastHeight);
- }
-
- if (fPlugin->isPipeRunning())
- fPlugin->idlePipe();
-
- fPlugin->idleUI();
-
- if (gHideShowTesting)
- {
- static int counter = 0;
- ++counter;
-
- if (counter == 100)
- {
- hide();
- }
- else if (counter == 200)
- {
- show();
- counter = 0;
- }
- }
-
- return true;
- }
-
- void setTransient(const uintptr_t winId)
- {
- CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
- carla_debug("CarlaBridgeToolkitGtk::setTransient(0x" P_UINTPTR ")", winId);
-
- #ifdef HAVE_X11
- GdkWindow* const gdkWindow(gtk_widget_get_window(fWindow));
- CARLA_SAFE_ASSERT_RETURN(gdkWindow != nullptr,);
-
- # ifdef BRIDGE_GTK3
- GdkDisplay* const gdkDisplay(gdk_window_get_display(gdkWindow));
- CARLA_SAFE_ASSERT_RETURN(gdkDisplay != nullptr,);
-
- ::Display* const display(gdk_x11_display_get_xdisplay(gdkDisplay));
- CARLA_SAFE_ASSERT_RETURN(display != nullptr,);
-
- const ::XID xid(gdk_x11_window_get_xid(gdkWindow));
- CARLA_SAFE_ASSERT_RETURN(xid != 0,);
- # else
- ::Display* const display(gdk_x11_drawable_get_xdisplay(gdkWindow));
- CARLA_SAFE_ASSERT_RETURN(display != nullptr,);
-
- const ::XID xid(gdk_x11_drawable_get_xid(gdkWindow));
- CARLA_SAFE_ASSERT_RETURN(xid != 0,);
- # endif
-
- XSetTransientForHint(display, xid, static_cast< ::Window>(winId));
- #endif
- }
-
- // ---------------------------------------------------------------------
-
- private:
- static void gtk_main_quit_if_needed()
- {
- if (gtk_main_level() != 0)
- gtk_main_quit();
- }
-
- static void gtk_ui_destroy(GtkWidget*, gpointer data)
- {
- CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
-
- ((CarlaBridgeToolkitGtk*)data)->handleDestroy();
- gtk_main_quit_if_needed();
- }
-
- static void gtk_ui_realize(GtkWidget*, gpointer data)
- {
- CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
-
- ((CarlaBridgeToolkitGtk*)data)->handleRealize();
- }
-
- static gboolean gtk_ui_timeout(gpointer data)
- {
- CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
-
- return ((CarlaBridgeToolkitGtk*)data)->handleTimeout();
- }
-
- CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitGtk)
- };
-
- // -------------------------------------------------------------------------
-
- CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeFormat* const format)
- {
- return new CarlaBridgeToolkitGtk(format);
- }
-
- // -------------------------------------------------------------------------
-
- CARLA_BRIDGE_UI_END_NAMESPACE
|