Browse Source

HACK: Massive hack to forward events to popups.

Has lots of problems, just testing.
experiment/fixing-key-events-macos-embedding
Steven Kirk 2 years ago
parent
commit
37d06c0644
  1. 57
      native/Avalonia.Native/src/OSX/AvnWindow.mm
  2. 4
      native/Avalonia.Native/src/OSX/PopupImpl.mm
  3. 3
      native/Avalonia.Native/src/OSX/WindowBaseImpl.h
  4. 2
      native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
  5. 1
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  6. 2
      native/Avalonia.Native/src/OSX/WindowInterfaces.h
  7. 6
      src/Avalonia.Native/PopupImpl.cs

57
native/Avalonia.Native/src/OSX/AvnWindow.mm

@ -38,6 +38,7 @@
AvnMenu* _menu;
IAvnAutomationPeer* _automationPeer;
AvnAutomationNode* _automationNode;
NSView* _Nullable _forwardKeyEventsTo;
}
-(AvnView* _Nullable) view
@ -445,30 +446,71 @@
return pt;
}
- (BOOL)makeFirstResponder:(NSResponder *)responder
- (BOOL)makeFirstResponder:(nullable NSResponder *)responder
{
auto r = [super makeFirstResponder:responder];
NSLog(@"'%@'.makeFirstResponser:%@ -> %d", [self title], responder, r);
if (_parent->Parent != nullptr)
{
if ([responder isKindOfClass:[NSView class]] && ![responder isKindOfClass:[AvnView class]])
{
NSLog(@"Native view in popup made first responder");
[_parent->Parent->Window forwardKeyEventsTo:responder];
}
else
{
[_parent->Parent->Window forwardKeyEventsTo:nil];
}
}
else
{
[self forwardKeyEventsTo:nil];
}
return r;
}
- (void)forwardKeyEventsTo:(nullable NSView*)responder
{
NSLog(@"Forward key events to @%@", responder);
_forwardKeyEventsTo = responder;
}
- (void)sendEvent:(NSEvent *_Nonnull)event
{
if (event.type == NSEventTypeLeftMouseDown)
{
[self forwardKeyEventsTo:nil];
}
if (event.type == NSEventTypeKeyDown)
{
auto children = _parent->GetChildren();
for (auto const& i : children)
if (_forwardKeyEventsTo != nil)
{
[i->Window sendEvent: event];
[_forwardKeyEventsTo keyDown: event];
return;
}
else
{
auto children = _parent->GetChildren();
for (auto const& i : children)
{
[i->Window sendEvent: event];
}
}
}
if (event.type == NSEventTypeKeyUp)
{
if (_forwardKeyEventsTo != nil)
{
[_forwardKeyEventsTo keyUp: event];
return;
}
}
[super sendEvent:event];
/// This is to detect non-client clicks. This can only be done on Windows... not popups, hence the dynamic_cast.
@ -555,6 +597,5 @@
id focused = [self accessibilityFocusedUIElement];
NSAccessibilityPostNotification(focused, NSAccessibilityFocusedUIElementChangedNotification);
}
@end

4
native/Avalonia.Native/src/OSX/PopupImpl.mm

@ -26,7 +26,7 @@ private:
PopupImpl(IAvnWindowEvents* events, TopLevelImpl* parent) : TopLevelImpl(events), WindowBaseImpl(events)
{
WindowEvents = events;
Parent = parent;
Parent = dynamic_cast<WindowBaseImpl*>(parent);
[Window setLevel:NSPopUpMenuWindowLevel];
}
protected:
@ -51,7 +51,7 @@ extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnTopLevel* parent)
{
@autoreleasepool
{
IAvnPopup* ptr = dynamic_cast<IAvnPopup*>(new PopupImpl(events, parent));
IAvnPopup* ptr = dynamic_cast<IAvnPopup*>(new PopupImpl(events, dynamic_cast<TopLevelImpl*>(parent)));
return ptr;
}
}

3
native/Avalonia.Native/src/OSX/WindowBaseImpl.h

@ -13,6 +13,7 @@
#include <list>
@class AvnMenu;
@class AvnWindow;
@protocol AvnWindowProtocol;
class WindowBaseImpl : public virtual TopLevelImpl,
@ -110,7 +111,7 @@ protected:
public:
WindowBaseImpl* Parent;
NSWindow * Window;
AvnWindow * Window;
ComPtr<IAvnWindowBaseEvents> BaseEvents;
const std::list<WindowBaseImpl*> GetChildren()
{

2
native/Avalonia.Native/src/OSX/WindowBaseImpl.mm

@ -457,7 +457,7 @@ void WindowBaseImpl::CleanNSWindow() {
void WindowBaseImpl::CreateNSWindow(bool usePanel) {
if (usePanel) {
Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];
/*Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];*/
[Window setHidesOnDeactivate:false];
} else {
Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];

1
native/Avalonia.Native/src/OSX/WindowImpl.mm

@ -7,6 +7,7 @@
#include "AutoFitContentView.h"
#include "AvnView.h"
#include "automation.h"
#include "WindowInterfaces.h"
#include "WindowProtocol.h"
#include "WindowImpl.h"

2
native/Avalonia.Native/src/OSX/WindowInterfaces.h

@ -2,7 +2,6 @@
// Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include "WindowProtocol.h"
@ -12,6 +11,7 @@
@interface AvnWindow : NSWindow <AvnWindowProtocol, NSWindowDelegate, AvnAccessibility>
-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask;
-(AvnView* _Nullable) view;
-(void)forwardKeyEventsTo:(nullable NSResponder*)responder;
@end
@interface AvnPanel : NSPanel <AvnWindowProtocol, NSWindowDelegate, AvnAccessibility>

6
src/Avalonia.Native/PopupImpl.cs

@ -1,4 +1,5 @@
using Avalonia.Controls;
using System;
using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Native.Interop;
using Avalonia.Platform;
@ -18,7 +19,8 @@ namespace Avalonia.Native
using (var e = new PopupEvents(this))
{
Init(new MacOSTopLevelHandle(_native = factory.CreatePopup(e)), factory.CreateScreens());
var parentNative = ((TopLevelImpl)_parent).Native;
Init(new MacOSTopLevelHandle(_native = factory.CreatePopup(e, parentNative)), factory.CreateScreens());
}
PopupPositioner = new ManagedPopupPositioner(new ManagedPopupPositionerPopupImplHelper(parent, MoveResize));

Loading…
Cancel
Save