Browse Source

Initial implementation of child windows for macOS; Cleanup

tags/1.9.8
falkTX 8 years ago
parent
commit
0e301dc562
13 changed files with 135 additions and 48 deletions
  1. +27
    -5
      source/backend/CarlaUtils.cpp
  2. +2
    -0
      source/backend/CarlaUtils.h
  3. +5
    -0
      source/backend/Makefile
  4. +1
    -1
      source/backend/plugin/CarlaPluginLV2.cpp
  5. +2
    -2
      source/backend/plugin/CarlaPluginVST2.cpp
  6. +5
    -0
      source/bridges-plugin/CarlaBridgePlugin.cpp
  7. +15
    -5
      source/bridges-ui/CarlaBridgeToolkitPlugin.cpp
  8. +5
    -1
      source/carla_host.py
  9. +1
    -1
      source/carla_settings.py
  10. +6
    -0
      source/carla_utils.py
  11. +11
    -10
      source/modules/dgl/src/Window.cpp
  12. +48
    -16
      source/utils/CarlaPluginUI.cpp
  13. +7
    -7
      source/utils/CarlaPluginUI.hpp

+ 27
- 5
source/backend/CarlaUtils.cpp View File

@@ -27,6 +27,10 @@

#include "water/files/File.h"

#ifdef CARLA_OS_MAC
# import <Cocoa/Cocoa.h>
#endif

#ifndef CARLA_UTILS_CACHED_PLUGINS_ONLY
# include "rtaudio/RtAudio.h"
# include "rtmidi/RtMidi.h"
@@ -711,7 +715,8 @@ const char* carla_get_library_folder()

void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2)
{
carla_debug("carla_x11_reparent_window()");
CARLA_SAFE_ASSERT_RETURN(winId1 != 0,);
CARLA_SAFE_ASSERT_RETURN(winId2 != 0,);

#ifdef HAVE_X11
if (::Display* const disp = XOpenDisplay(nullptr))
@@ -725,6 +730,8 @@ void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2)

void carla_x11_move_window(uintptr_t winId, int x, int y)
{
CARLA_SAFE_ASSERT_RETURN(winId != 0,);

#ifdef HAVE_X11
if (::Display* const disp = XOpenDisplay(nullptr))
{
@@ -736,12 +743,15 @@ void carla_x11_move_window(uintptr_t winId, int x, int y)

int* carla_x11_get_window_pos(uintptr_t winId)
{
carla_debug("carla_x11_get_window_pos()");

static int pos[2];

if (winId == 0)
{
pos[0] = 0;
pos[1] = 0;
}
#ifdef HAVE_X11
if (::Display* const disp = XOpenDisplay(nullptr))
else if (::Display* const disp = XOpenDisplay(nullptr))
{
int x, y;
Window child;
@@ -752,8 +762,8 @@ int* carla_x11_get_window_pos(uintptr_t winId)
pos[0] = x - xwa.x;
pos[1] = y - xwa.y;
}
else
#endif
else
{
pos[0] = 0;
pos[1] = 0;
@@ -762,6 +772,18 @@ int* carla_x11_get_window_pos(uintptr_t winId)
return pos;
}

int carla_cocoa_get_window(void* nsViewPtr)
{
CARLA_SAFE_ASSERT_RETURN(nsViewPtr != nullptr, 0);

#ifdef CARLA_OS_MAC
NSView* nsView = (NSView*)nsViewPtr;
return [[nsView window] windowNumber];
#else
return 0;
#endif
}

// -------------------------------------------------------------------------------------------------------------------

#include "CarlaPipeUtils.cpp"


+ 2
- 0
source/backend/CarlaUtils.h View File

@@ -248,6 +248,8 @@ CARLA_EXPORT void carla_x11_move_window(uintptr_t winId, int x, int y);

CARLA_EXPORT int* carla_x11_get_window_pos(uintptr_t winId);

CARLA_EXPORT int carla_cocoa_get_window(void* nsViewPtr);

// -------------------------------------------------------------------------------------------------------------------

/** @} */


+ 5
- 0
source/backend/Makefile View File

@@ -110,6 +110,11 @@ $(OBJDIR)/CarlaStandalone.cpp.o: CarlaStandalone.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@

$(OBJDIR)/CarlaUtils.cpp.o: CarlaUtils.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@
endif

$(OBJDIR)/%.cpp.o: %.cpp


+ 1
- 1
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -496,7 +496,7 @@ private:
// -------------------------------------------------------------------------------------------------------------------

class CarlaPluginLV2 : public CarlaPlugin,
private CarlaPluginUI::CloseCallback
private CarlaPluginUI::Callback
{
public:
CarlaPluginLV2(CarlaEngine* const engine, const uint id)


+ 2
- 2
source/backend/plugin/CarlaPluginVST2.cpp View File

@@ -49,7 +49,7 @@ static const int32_t kVstMidiEventSize = static_cast<int32_t>(sizeof(VstMidiEven
// -----------------------------------------------------

class CarlaPluginVST2 : public CarlaPlugin,
private CarlaPluginUI::CloseCallback
private CarlaPluginUI::Callback
{
public:
CarlaPluginVST2(CarlaEngine* const engine, const uint id)
@@ -435,7 +435,7 @@ public:
const char* msg = nullptr;
const uintptr_t frontendWinId(pData->engine->getOptions().frontendWinId);

#if defined(CARLA_OS_MAC) && defined(__LP64__)
#if defined(CARLA_OS_MAC) && defined(CARLA_OS_64BIT)
fUI.window = CarlaPluginUI::newCocoa(this, frontendWinId, false);
#elif defined(CARLA_OS_WIN)
fUI.window = CarlaPluginUI::newWindows(this, frontendWinId, false);


+ 5
- 0
source/bridges-plugin/CarlaBridgePlugin.cpp View File

@@ -178,7 +178,12 @@ public:
for (; runMainLoopOnce() && ! gCloseNow;)
{
gIdle();
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
// MacOS and Win32 have event-loops to run, so minimize sleep time
carla_msleep(1);
#else
carla_msleep(5);
#endif
}

carla_set_engine_about_to_close();


+ 15
- 5
source/bridges-ui/CarlaBridgeToolkitPlugin.cpp View File

@@ -17,15 +17,17 @@

#include "CarlaBridgeUI.hpp"
#include "CarlaBridgeToolkit.hpp"
#include "CarlaMainLoop.hpp"
#include "CarlaPluginUI.hpp"

CARLA_BRIDGE_START_NAMESPACE

using CarlaBackend::runMainLoopOnce;

// -------------------------------------------------------------------------

class CarlaBridgeToolkitPlugin : public CarlaBridgeToolkit,
private CarlaPluginUI::CloseCallback
private CarlaPluginUI::Callback
{
public:
CarlaBridgeToolkitPlugin(CarlaBridgeUI* const u)
@@ -50,9 +52,9 @@ public:
const CarlaBridgeUI::Options& options(ui->getOptions());

#if defined(CARLA_OS_MAC) && defined(BRIDGE_COCOA)
fUI = nullptr;
fUI = CarlaPluginUI::newCocoa(this, 0, options.isResizable);
#elif defined(CARLA_OS_WIN) && defined(BRIDGE_HWND)
fUI = nullptr;
fUI = CarlaPluginUI::newWindows(this, 0, options.isResizable);
#elif defined(HAVE_X11) && defined(BRIDGE_X11)
fUI = CarlaPluginUI::newX11(this, 0, options.isResizable);
#endif
@@ -60,8 +62,11 @@ public:

fUI->setTitle(options.windowTitle.buffer());

#ifdef HAVE_X11
// Out-of-process reparenting only possible on X11
if (options.transientWindowId != 0)
fUI->setTransientWinId(options.transientWindowId);
#endif

return true;
}
@@ -83,14 +88,19 @@ public:

fIdling = true;

for (; fIdling;)
for (; runMainLoopOnce() && fIdling;)
{
if (ui->isPipeRunning())
ui->idlePipe();

ui->idleUI();
fUI->idle();
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
// MacOS and Win32 have event-loops to run, so minimize sleep time
carla_msleep(1);
#else
carla_msleep(20);
#endif
}
}



+ 5
- 1
source/carla_host.py View File

@@ -2129,7 +2129,11 @@ class HostWindow(QMainWindow):

# set our gui as parent for all plugins UIs
if self.host.manageUIs and not (self.host.isControl or self.host.isPlugin):
winIdStr = "%x" % int(self.winId())
if MACOS:
nsViewPtr = int(self.winId())
winIdStr = "%x" % gCarla.utils.cocoa_get_window(nsViewPtr)
else:
winIdStr = "%x" % int(self.winId())
self.host.set_engine_option(ENGINE_OPTION_FRONTEND_WIN_ID, 0, winIdStr)

def hideEvent(self, event):


+ 1
- 1
source/carla_settings.py View File

@@ -243,7 +243,7 @@ class CarlaSettingsW(QDialog):
self.ui.ch_main_show_logs.setEnabled(False)
self.ui.ch_main_show_logs.setVisible(False)

if MACOS or WINDOWS:
if WINDOWS:
self.ui.ch_engine_manage_uis.setEnabled(False)
self.ui.ch_engine_manage_uis.setVisible(False)



+ 6
- 0
source/carla_utils.py View File

@@ -224,6 +224,9 @@ class CarlaUtils(object):
self.lib.carla_x11_get_window_pos.argtypes = [c_uintptr]
self.lib.carla_x11_get_window_pos.restype = POINTER(c_int)

self.lib.carla_cocoa_get_window.argtypes = [c_uintptr]
self.lib.carla_cocoa_get_window.restype = c_int

# use _putenv on windows
if not WINDOWS:
self.msvcrt = None
@@ -338,4 +341,7 @@ class CarlaUtils(object):
data = self.lib.carla_x11_get_window_pos(winId)
return (int(data[0]), int(data[1]))

def cocoa_get_window(self, winId):
return self.lib.carla_cocoa_get_window(winId)

# ------------------------------------------------------------------------------------------------------------

+ 11
- 10
source/modules/dgl/src/Window.cpp View File

@@ -403,11 +403,7 @@ struct Window::PrivateData {
SetFocus(hwnd);
#elif defined(DISTRHO_OS_MAC)
if (mWindow != nullptr)
{
// TODO
//[NSApp activateIgnoringOtherApps:YES];
//[mWindow makeKeyAndOrderFront:mWindow];
}
[mWindow makeKeyWindow];
#elif defined(DISTRHO_OS_LINUX)
XRaiseWindow(xDisplay, xWindow);
XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime);
@@ -626,12 +622,17 @@ struct Window::PrivateData {

void setTransientWinId(const uintptr_t winId)
{
#if defined(DISTRHO_OS_LINUX)
DISTRHO_SAFE_ASSERT_RETURN(winId != 0,);

#if defined(DISTRHO_OS_MAC)
NSWindow* window = [NSApp windowWithWindowNumber:winId];
DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,);

[window addChildWindow:mWindow
ordered:NSWindowAbove];
[mWindow makeKeyWindow];
#elif defined(DISTRHO_OS_LINUX)
XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId));
#else
return;
// unused
(void)winId;
#endif
}



+ 48
- 16
source/utils/CarlaPluginUI.cpp View File

@@ -53,7 +53,7 @@ static int temporaryErrorHandler(Display*, XErrorEvent*)
class X11PluginUI : public CarlaPluginUI
{
public:
X11PluginUI(CloseCallback* const cb, const uintptr_t parentId, const bool isResizable) noexcept
X11PluginUI(Callback* const cb, const uintptr_t parentId, const bool isResizable) noexcept
: CarlaPluginUI(cb, isResizable),
fDisplay(nullptr),
fWindow(0),
@@ -330,16 +330,18 @@ private:
@interface CarlaPluginWindow : NSWindow
{
@public
CarlaPluginUI::CloseCallback* callback;
CarlaPluginUI::Callback* callback;
NSView* view;
}

- (id) initWithContentRect:(NSRect)contentRect
styleMask:(unsigned int)aStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag;
- (void) setCloseCallback:(CarlaPluginUI::CloseCallback*)cb;
- (void) setup:(CarlaPluginUI::Callback*)cb view:(NSView*)v;
- (BOOL) canBecomeKeyWindow;
- (BOOL) windowShouldClose:(id)sender;
- (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize;
@end

@implementation CarlaPluginWindow
@@ -350,6 +352,7 @@ private:
defer:(BOOL)flag
{
callback = nil;
view = nil;

NSWindow* result = [super initWithContentRect:contentRect
styleMask:(NSClosableWindowMask |
@@ -367,9 +370,10 @@ private:
(void)aStyle; (void)bufferingType; (void)flag;
}

- (void)setCloseCallback:(CarlaPluginUI::CloseCallback*)cb
- (void)setup:(CarlaPluginUI::Callback*)cb view:(NSView*)v
{
callback = cb;
view = v;
}

- (BOOL)canBecomeKeyWindow
@@ -379,23 +383,36 @@ private:

- (BOOL)windowShouldClose:(id)sender
{
if (callback)
if (callback != nil)
callback->handlePluginUIClosed();

return NO;

// unused
(void)sender;
}

- (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize
{
if (callback != nil)
callback->handlePluginUIResized(frameSize.width, frameSize.height);

return frameSize;

// unused
(void)sender;
}

@end

class CocoaPluginUI : public CarlaPluginUI
{
public:
CocoaPluginUI(CloseCallback* const cb, const uintptr_t parentId, const bool isResizable) noexcept
CocoaPluginUI(Callback* const cb, const uintptr_t parentId, const bool isResizable) noexcept
: CarlaPluginUI(cb, isResizable),
fView(nullptr),
fWindow(0)
fWindow(0),
fParentId(parentId)
{
[NSAutoreleasePool new];
[NSApplication sharedApplication];
@@ -418,13 +435,16 @@ public:
if (! isResizable)
[[fWindow standardWindowButton:NSWindowZoomButton] setHidden:YES];

[fWindow setCloseCallback:cb];
[fWindow setup:cb view:fView];
[fWindow setContentView:fView];
[fWindow makeFirstResponder:fView];
[fWindow makeKeyAndOrderFront:fWindow];

[NSApp activateIgnoringOtherApps:YES];
[fWindow center];

if (parentId != 0)
setTransientWinId(parentId);
}

~CocoaPluginUI() override
@@ -443,6 +463,9 @@ public:

[fView setHidden:NO];
[fWindow setIsVisible:YES];

if (fParentId != 0)
setTransientWinId(fParentId);
}

void hide() override
@@ -459,14 +482,14 @@ public:

void focus() override
{
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fWindow != 0,);

// TODO
[fWindow makeKeyWindow];
}

void setSize(const uint width, const uint height, const bool forceUpdate) override
{
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fWindow != 0,);
CARLA_SAFE_ASSERT_RETURN(fView != nullptr,);

[fView setFrame:NSMakeRect(0, 0, width, height)];
@@ -504,7 +527,12 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(fWindow != 0,);

// TODO
NSWindow* window = [NSApp windowWithWindowNumber:winId];
CARLA_SAFE_ASSERT_RETURN(window != nullptr,);

[window addChildWindow:fWindow
ordered:NSWindowAbove];
[fWindow makeKeyWindow];
}

void* getPtr() const noexcept override
@@ -520,6 +548,7 @@ public:
private:
NSView* fView;
id fWindow;
uintptr_t fParentId;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CocoaPluginUI)
};
@@ -538,7 +567,7 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
class WindowsPluginUI : public CarlaPluginUI
{
public:
WindowsPluginUI(CloseCallback* const cb, const uintptr_t parentId, const bool isResizable) noexcept
WindowsPluginUI(Callback* const cb, const uintptr_t parentId, const bool isResizable) noexcept
: CarlaPluginUI(cb, isResizable),
fWindow(0),
fIsVisible(false),
@@ -582,6 +611,9 @@ public:
}

SetWindowLongPtr(fWindow, GWLP_USERDATA, (LONG_PTR)this);

if (parentId != 0)
setTransientWinId(parentId);
}

~WindowsPluginUI() override
@@ -963,21 +995,21 @@ bool CarlaPluginUI::tryTransientWinIdMatch(const uintptr_t pid, const char* cons
// -----------------------------------------------------

#ifdef HAVE_X11
CarlaPluginUI* CarlaPluginUI::newX11(CloseCallback* cb, uintptr_t parentId, bool isResizable)
CarlaPluginUI* CarlaPluginUI::newX11(Callback* cb, uintptr_t parentId, bool isResizable)
{
return new X11PluginUI(cb, parentId, isResizable);
}
#endif

#ifdef CARLA_OS_MAC
CarlaPluginUI* CarlaPluginUI::newCocoa(CloseCallback* cb, uintptr_t parentId, bool isResizable)
CarlaPluginUI* CarlaPluginUI::newCocoa(Callback* cb, uintptr_t parentId, bool isResizable)
{
return new CocoaPluginUI(cb, parentId, isResizable);
}
#endif

#ifdef CARLA_OS_WIN
CarlaPluginUI* CarlaPluginUI::newWindows(CloseCallback* cb, uintptr_t parentId, bool isResizable)
CarlaPluginUI* CarlaPluginUI::newWindows(Callback* cb, uintptr_t parentId, bool isResizable)
{
return new WindowsPluginUI(cb, parentId, isResizable);
}


+ 7
- 7
source/utils/CarlaPluginUI.hpp View File

@@ -25,9 +25,9 @@
class CarlaPluginUI
{
public:
class CloseCallback {
class Callback {
public:
virtual ~CloseCallback() {}
virtual ~Callback() {}
virtual void handlePluginUIClosed() = 0;
virtual void handlePluginUIResized(const uint width, const uint height) = 0;
};
@@ -48,21 +48,21 @@ public:
static bool tryTransientWinIdMatch(const uintptr_t pid, const char* const uiTitle, const uintptr_t winId, const bool centerUI);

#ifdef CARLA_OS_MAC
static CarlaPluginUI* newCocoa(CloseCallback*, uintptr_t, bool);
static CarlaPluginUI* newCocoa(Callback*, uintptr_t, bool);
#endif
#ifdef CARLA_OS_WIN
static CarlaPluginUI* newWindows(CloseCallback*, uintptr_t, bool);
static CarlaPluginUI* newWindows(Callback*, uintptr_t, bool);
#endif
#ifdef HAVE_X11
static CarlaPluginUI* newX11(CloseCallback*, uintptr_t, bool);
static CarlaPluginUI* newX11(Callback*, uintptr_t, bool);
#endif

protected:
bool fIsIdling;
bool fIsResizable;
CloseCallback* fCallback;
Callback* fCallback;

CarlaPluginUI(CloseCallback* const cb, const bool isResizable) noexcept
CarlaPluginUI(Callback* const cb, const bool isResizable) noexcept
: fIsIdling(false),
fIsResizable(isResizable),
fCallback(cb) {}


Loading…
Cancel
Save