Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
6.5KB

  1. /*
  2. * Carla Bridge Toolkit, Gtk version
  3. * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaBridgeClient.hpp"
  18. #include "CarlaBridgeToolkit.hpp"
  19. #include <gtk/gtk.h>
  20. #ifdef CARLA_OS_LINUX
  21. # include <gdk/gdkx.h>
  22. #endif
  23. CARLA_BRIDGE_START_NAMESPACE
  24. // -------------------------------------------------------------------------
  25. static int gargc = 0;
  26. static char** gargv = nullptr;
  27. // -------------------------------------------------------------------------
  28. class CarlaBridgeToolkitGtk : public CarlaBridgeToolkit
  29. {
  30. public:
  31. CarlaBridgeToolkitGtk(CarlaBridgeClient* const client, const char* const windowTitle)
  32. : CarlaBridgeToolkit(client, windowTitle),
  33. fNeedsShow(false),
  34. fWindow(nullptr),
  35. fLastX(0),
  36. fLastY(0),
  37. fLastWidth(0),
  38. fLastHeight(0),
  39. leakDetector_CarlaBridgeToolkitGtk()
  40. {
  41. carla_debug("CarlaBridgeToolkitGtk::CarlaBridgeToolkitGtk(%p, \"%s\")", client, windowTitle);
  42. }
  43. ~CarlaBridgeToolkitGtk() override
  44. {
  45. CARLA_SAFE_ASSERT(fWindow == nullptr);
  46. carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()");
  47. }
  48. void init() override
  49. {
  50. CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr,);
  51. carla_debug("CarlaBridgeToolkitGtk::init()");
  52. gtk_init(&gargc, &gargv);
  53. fWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  54. gtk_window_resize(GTK_WINDOW(fWindow), 30, 30);
  55. gtk_widget_hide(fWindow);
  56. }
  57. void exec(const bool showUI) override
  58. {
  59. CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,);
  60. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  61. carla_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI));
  62. GtkWidget* const widget((GtkWidget*)kClient->getWidget());
  63. gtk_container_add(GTK_CONTAINER(fWindow), widget);
  64. gtk_window_set_resizable(GTK_WINDOW(fWindow), kClient->isResizable());
  65. gtk_window_set_title(GTK_WINDOW(fWindow), kWindowTitle);
  66. if (const char* const winIdStr = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID"))
  67. {
  68. if (const long long winId = std::strtoll(winIdStr, nullptr, 16))
  69. {
  70. #ifdef CARLA_OS_LINUX
  71. if (GdkWindow* const gdkWindow = GDK_WINDOW(fWindow))
  72. {
  73. if (GdkDisplay* const gdkDisplay = gdk_window_get_display(gdkWindow))
  74. {
  75. ::Display* const display(gdk_x11_display_get_xdisplay(gdkDisplay));
  76. # ifdef BRIDGE_GTK3
  77. ::XID const xid(gdk_x11_window_get_xid(gdkWindow));
  78. # else
  79. ::XID xid = 0;
  80. if (GdkDrawable* const gdkDrawable = GDK_DRAWABLE(fWindow))
  81. xid = gdk_x11_drawable_get_xid(gdkDrawable);
  82. # endif
  83. if (display != nullptr && xid != 0)
  84. XSetTransientForHint(display, xid, static_cast<::Window>(winId));
  85. }
  86. }
  87. #else
  88. (void)winId;
  89. #endif
  90. }
  91. }
  92. if (showUI || fNeedsShow)
  93. {
  94. show();
  95. fNeedsShow = false;
  96. }
  97. g_timeout_add(30, gtk_ui_timeout, this);
  98. g_signal_connect(fWindow, "destroy", G_CALLBACK(gtk_ui_destroy), this);
  99. // First idle
  100. handleTimeout();
  101. // Main loop
  102. gtk_main();
  103. }
  104. void quit() override
  105. {
  106. carla_debug("CarlaBridgeToolkitGtk::quit()");
  107. if (fWindow != nullptr)
  108. {
  109. gtk_widget_destroy(fWindow);
  110. fWindow = nullptr;
  111. gtk_main_quit_if_needed();
  112. }
  113. }
  114. void show() override
  115. {
  116. carla_debug("CarlaBridgeToolkitGtk::show()");
  117. fNeedsShow = true;
  118. if (fWindow != nullptr)
  119. gtk_widget_show_all(fWindow);
  120. }
  121. void hide() override
  122. {
  123. carla_debug("CarlaBridgeToolkitGtk::hide()");
  124. fNeedsShow = false;
  125. if (fWindow != nullptr)
  126. gtk_widget_hide(fWindow);
  127. }
  128. void resize(int width, int height) override
  129. {
  130. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  131. carla_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height);
  132. gtk_window_resize(GTK_WINDOW(fWindow), width, height);
  133. }
  134. // ---------------------------------------------------------------------
  135. protected:
  136. bool fNeedsShow;
  137. GtkWidget* fWindow;
  138. gint fLastX;
  139. gint fLastY;
  140. gint fLastWidth;
  141. gint fLastHeight;
  142. void handleDestroy()
  143. {
  144. carla_debug("CarlaBridgeToolkitGtk::handleDestroy()");
  145. fWindow = nullptr;
  146. }
  147. gboolean handleTimeout()
  148. {
  149. if (fWindow != nullptr)
  150. {
  151. gtk_window_get_position(GTK_WINDOW(fWindow), &fLastX, &fLastY);
  152. gtk_window_get_size(GTK_WINDOW(fWindow), &fLastWidth, &fLastHeight);
  153. }
  154. kClient->uiIdle();
  155. if (! kClient->oscIdle())
  156. {
  157. gtk_main_quit_if_needed();
  158. return false;
  159. }
  160. return true;
  161. }
  162. // ---------------------------------------------------------------------
  163. private:
  164. static void gtk_main_quit_if_needed()
  165. {
  166. if (gtk_main_level() != 0)
  167. gtk_main_quit();
  168. }
  169. static void gtk_ui_destroy(GtkWidget*, gpointer data)
  170. {
  171. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  172. ((CarlaBridgeToolkitGtk*)data)->handleDestroy();
  173. gtk_main_quit_if_needed();
  174. }
  175. static gboolean gtk_ui_timeout(gpointer data)
  176. {
  177. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  178. return ((CarlaBridgeToolkitGtk*)data)->handleTimeout();
  179. }
  180. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitGtk)
  181. };
  182. // -------------------------------------------------------------------------
  183. CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const windowTitle)
  184. {
  185. return new CarlaBridgeToolkitGtk(client, windowTitle);
  186. }
  187. // -------------------------------------------------------------------------
  188. CARLA_BRIDGE_END_NAMESPACE