copy WindowButtonsProxy from electron
This commit is contained in:
parent
c8cfefb3ca
commit
92681dc9d9
|
@ -107,7 +107,6 @@ void MainWindow::showEvent(QShowEvent *event)
|
|||
titleBarWidget->maximizeButton->hide();
|
||||
titleBarWidget->closeButton->hide();
|
||||
Utilities::showMacWindowButton(windowHandle());
|
||||
Utilities::setStandardWindowButtonsOffset(win, QPoint(0, -5));
|
||||
#endif // Q_OS_MAC
|
||||
inited = true;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ void FLWindow::initFramelessWindow()
|
|||
m_maximizeButton->hide();
|
||||
m_closeButton->hide();
|
||||
Utilities::showMacWindowButton(windowHandle());
|
||||
Utilities::setStandardWindowButtonsOffset(windowHandle(), QPoint(10, 10));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -65,18 +64,6 @@ bool FLWindow::nativeEvent(const QByteArray &eventType, void *message, long *res
|
|||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
void FLWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
auto win = windowHandle();
|
||||
if (win) {
|
||||
Utilities::setStandardWindowButtonsOffset(win, QPoint(10, 10));
|
||||
}
|
||||
|
||||
QWidget::resizeEvent(event);
|
||||
}
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
void FLWindow::setupUi()
|
||||
{
|
||||
resize(800, 600);
|
||||
|
|
|
@ -18,10 +18,6 @@ protected:
|
|||
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
private:
|
||||
void initFramelessWindow();
|
||||
void setupUi();
|
||||
|
|
|
@ -24,7 +24,11 @@ if(WIN32)
|
|||
)
|
||||
else()
|
||||
if(APPLE)
|
||||
list(APPEND SOURCES core/utilities_macos.mm)
|
||||
list(APPEND SOURCES
|
||||
core/utilities_macos.mm
|
||||
core/window_buttons_proxy.h
|
||||
core/window_buttons_proxy.mm
|
||||
)
|
||||
else()
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS X11Extras REQUIRED)
|
||||
list(APPEND SOURCES core/utilities_linux.cpp)
|
||||
|
|
|
@ -81,6 +81,7 @@ FRAMELESSHELPER_API bool isMacMainWindow(QWindow *w);
|
|||
FRAMELESSHELPER_API bool makeMacKeyWindow(QWindow *w);
|
||||
FRAMELESSHELPER_API bool makeMacMainWindow(QWindow *w);
|
||||
FRAMELESSHELPER_API bool setStandardWindowButtonsOffset(QWindow *w, const QPoint &offset);
|
||||
FRAMELESSHELPER_API bool setTrafficLightPosition(QWindow *w, const QPoint &pos);
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <QtCore/qlist.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
|
||||
#include "window_buttons_proxy.h"
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
namespace Utilities {
|
||||
|
@ -241,8 +243,8 @@ static void overrideNSWindowMethods(NSWindow* window)
|
|||
cls, @selector(canBecomeMainWindow), (IMP) __canBecomeMainWindow);
|
||||
gOrigSendEvent = (sendEventType) replaceMethod(
|
||||
cls, @selector(sendEvent:), (IMP) __sendEvent);
|
||||
gOrigIsFlipped = (isFlippedType) replaceMethod(
|
||||
cls, @selector (isFlipped), (IMP) __isFlipped);
|
||||
//gOrigIsFlipped = (isFlippedType) replaceMethod(
|
||||
// cls, @selector (isFlipped), (IMP) __isFlipped);
|
||||
|
||||
gNSWindowOverrode = true;
|
||||
}
|
||||
|
@ -271,15 +273,51 @@ static void restoreNSWindowMethods(NSWindow* window)
|
|||
restoreMethod(cls, @selector(sendEvent:), (IMP) gOrigSendEvent);
|
||||
gOrigSendEvent = nullptr;
|
||||
|
||||
restoreMethod(cls, @selector(isFlipped), (IMP) gOrigIsFlipped);
|
||||
gOrigIsFlipped = nullptr;
|
||||
//restoreMethod(cls, @selector(isFlipped), (IMP) gOrigIsFlipped);
|
||||
//gOrigIsFlipped = nullptr;
|
||||
|
||||
gNSWindowOverrode = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static QHash<QWindow*, NSWindow*> gQWindowToNSWindow;
|
||||
class NSWindowData
|
||||
{
|
||||
private:
|
||||
NSWindow* m_window;
|
||||
WindowButtonsProxy *m_buttonProxy;
|
||||
bool m_windowButtonVisibility;
|
||||
QPoint m_trafficLightPosition;
|
||||
|
||||
public:
|
||||
NSWindowData(NSWindow *window)
|
||||
: m_windowButtonVisibility(false)
|
||||
, m_buttonProxy(nullptr)
|
||||
, m_window(window)
|
||||
{
|
||||
overrideNSWindowMethods(window);
|
||||
m_buttonProxy = [[WindowButtonsProxy alloc] initWithWindow:window];
|
||||
}
|
||||
|
||||
~NSWindowData()
|
||||
{
|
||||
restoreNSWindowMethods(m_window);
|
||||
[m_buttonProxy release];
|
||||
}
|
||||
|
||||
NSWindow* window() { return m_window; }
|
||||
|
||||
QPoint trafficLightPosition() { return m_trafficLightPosition; }
|
||||
bool setTrafficLightPosition(const QPoint &pos) {
|
||||
m_trafficLightPosition = pos;
|
||||
if (m_buttonProxy) {
|
||||
[m_buttonProxy setMargin:m_trafficLightPosition];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static QHash<QWindow*, NSWindowData*> gQWindowToNSWindow;
|
||||
|
||||
static NSWindow* getNSWindow(QWindow* w)
|
||||
{
|
||||
|
@ -303,8 +341,8 @@ bool setMacWindowHook(QWindow* w)
|
|||
if (nswindow == nullptr)
|
||||
return false;
|
||||
|
||||
gQWindowToNSWindow.insert(w, nswindow);
|
||||
overrideNSWindowMethods(nswindow);
|
||||
NSWindowData *obj = new NSWindowData(nswindow);
|
||||
gQWindowToNSWindow.insert(w, obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -313,9 +351,10 @@ bool unsetMacWindowHook(QWindow* w)
|
|||
{
|
||||
if (!gQWindowToNSWindow.contains(w))
|
||||
return false;
|
||||
NSWindow* obj = gQWindowToNSWindow[w];
|
||||
|
||||
NSWindowData* obj = gQWindowToNSWindow[w];
|
||||
gQWindowToNSWindow.remove(w);
|
||||
restoreNSWindowMethods(obj);
|
||||
delete obj;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -487,6 +526,12 @@ bool setStandardWindowButtonsOffset(QWindow *w, const QPoint &offset)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool setTrafficLightPosition(QWindow *w, const QPoint &pos)
|
||||
{
|
||||
NSWindowData* obj = gQWindowToNSWindow[w];
|
||||
return obj->setTrafficLightPosition(pos);
|
||||
}
|
||||
|
||||
} // namespace Utilities
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2021 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_PROXY_H_
|
||||
#define SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_PROXY_H_
|
||||
|
||||
#include <memory>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <QtCore/qpoint.h>
|
||||
|
||||
@class WindowButtonsProxy;
|
||||
|
||||
// A helper view that floats above the window buttons.
|
||||
@interface ButtonsAreaHoverView : NSView {
|
||||
@private
|
||||
WindowButtonsProxy* proxy_;
|
||||
}
|
||||
- (id)initWithProxy:(WindowButtonsProxy*)proxy;
|
||||
@end
|
||||
|
||||
// Manipulating the window buttons.
|
||||
@interface WindowButtonsProxy : NSObject {
|
||||
@private
|
||||
NSWindow* window_;
|
||||
|
||||
// Current left-top margin of buttons.
|
||||
QPoint margin_;
|
||||
// The default left-top margin.
|
||||
QPoint default_margin_;
|
||||
|
||||
// Track mouse moves above window buttons.
|
||||
BOOL show_on_hover_;
|
||||
BOOL mouse_inside_;
|
||||
NSTrackingArea* tracking_area_;
|
||||
ButtonsAreaHoverView* hover_view_;
|
||||
}
|
||||
|
||||
- (id)initWithWindow:(NSWindow*)window;
|
||||
|
||||
- (void)setVisible:(BOOL)visible;
|
||||
- (BOOL)isVisible;
|
||||
|
||||
// Only show window buttons when mouse moves above them.
|
||||
- (void)setShowOnHover:(BOOL)yes;
|
||||
|
||||
// Set left-top margin of the window buttons..
|
||||
- (void)setMargin:(const QPoint&)margin;
|
||||
|
||||
// Return the bounds of all 3 buttons, with margin on all sides.
|
||||
- (NSRect)getButtonsContainerBounds;
|
||||
|
||||
- (void)redraw;
|
||||
- (void)updateTrackingAreas;
|
||||
@end
|
||||
|
||||
#endif // SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_PROXY_H_
|
|
@ -0,0 +1,225 @@
|
|||
// Copyright (c) 2021 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "window_buttons_proxy.h"
|
||||
|
||||
@implementation ButtonsAreaHoverView : NSView
|
||||
|
||||
- (id)initWithProxy:(WindowButtonsProxy*)proxy {
|
||||
if ((self = [super init])) {
|
||||
proxy_ = proxy;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// Ignore all mouse events.
|
||||
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
[proxy_ updateTrackingAreas];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation WindowButtonsProxy
|
||||
|
||||
- (id)initWithWindow:(NSWindow*)window {
|
||||
window_ = window;
|
||||
show_on_hover_ = NO;
|
||||
mouse_inside_ = NO;
|
||||
|
||||
// Remember the default margin.
|
||||
margin_ = default_margin_ = [self getCurrentMargin];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (hover_view_)
|
||||
[hover_view_ removeFromSuperview];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setVisible:(BOOL)visible {
|
||||
NSView* titleBarContainer = [self titleBarContainer];
|
||||
if (!titleBarContainer)
|
||||
return;
|
||||
[titleBarContainer setHidden:!visible];
|
||||
}
|
||||
|
||||
- (BOOL)isVisible {
|
||||
NSView* titleBarContainer = [self titleBarContainer];
|
||||
if (!titleBarContainer)
|
||||
return YES;
|
||||
return ![titleBarContainer isHidden];
|
||||
}
|
||||
|
||||
- (void)setShowOnHover:(BOOL)yes {
|
||||
NSView* titleBarContainer = [self titleBarContainer];
|
||||
if (!titleBarContainer)
|
||||
return;
|
||||
show_on_hover_ = yes;
|
||||
// Put a transparent view above the window buttons so we can track mouse
|
||||
// events when mouse enter/leave the window buttons.
|
||||
if (show_on_hover_) {
|
||||
auto old_ptr = hover_view_;
|
||||
hover_view_ = [[ButtonsAreaHoverView alloc] initWithProxy:self];
|
||||
[old_ptr release];
|
||||
[hover_view_ setFrame:[self getButtonsBounds]];
|
||||
[titleBarContainer addSubview:hover_view_];
|
||||
} else {
|
||||
[hover_view_ removeFromSuperview];
|
||||
[hover_view_ release];
|
||||
hover_view_ = nullptr;
|
||||
}
|
||||
[self updateButtonsVisibility];
|
||||
}
|
||||
|
||||
- (void)setMargin:(const QPoint&)margin {
|
||||
if (!margin.isNull())
|
||||
margin_ = margin;
|
||||
else
|
||||
margin_ = default_margin_;
|
||||
[self redraw];
|
||||
}
|
||||
|
||||
- (NSRect)getButtonsContainerBounds {
|
||||
return NSInsetRect([self getButtonsBounds], -margin_.x(), -margin_.y());
|
||||
}
|
||||
|
||||
- (void)redraw {
|
||||
NSView* titleBarContainer = [self titleBarContainer];
|
||||
if (!titleBarContainer)
|
||||
return;
|
||||
|
||||
NSView* left = [self leftButton];
|
||||
NSView* middle = [self middleButton];
|
||||
NSView* right = [self rightButton];
|
||||
|
||||
float button_width = NSWidth(left.frame);
|
||||
float button_height = NSHeight(left.frame);
|
||||
float padding = NSMinX(middle.frame) - NSMaxX(left.frame);
|
||||
float start;
|
||||
if (false /*base::i18n::IsRTL()*/)
|
||||
start =
|
||||
NSWidth(window_.frame) - 3 * button_width - 2 * padding - margin_.x();
|
||||
else
|
||||
start = margin_.x();
|
||||
|
||||
NSRect cbounds = titleBarContainer.frame;
|
||||
cbounds.size.height = button_height + 2 * margin_.y();
|
||||
cbounds.origin.y = NSHeight(window_.frame) - NSHeight(cbounds);
|
||||
[titleBarContainer setFrame:cbounds];
|
||||
|
||||
[left setFrameOrigin:NSMakePoint(start, margin_.y())];
|
||||
start += button_width + padding;
|
||||
[middle setFrameOrigin:NSMakePoint(start, margin_.y())];
|
||||
start += button_width + padding;
|
||||
[right setFrameOrigin:NSMakePoint(start, margin_.y())];
|
||||
|
||||
if (hover_view_)
|
||||
[hover_view_ setFrame:[self getButtonsBounds]];
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
if (tracking_area_)
|
||||
[hover_view_ removeTrackingArea:tracking_area_];
|
||||
auto old_ptr = tracking_area_;
|
||||
tracking_area_ = [[NSTrackingArea alloc]
|
||||
initWithRect:NSZeroRect
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways |
|
||||
NSTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
[old_ptr release];
|
||||
[hover_view_ addTrackingArea:tracking_area_];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent*)event {
|
||||
mouse_inside_ = YES;
|
||||
[self updateButtonsVisibility];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent*)event {
|
||||
mouse_inside_ = NO;
|
||||
[self updateButtonsVisibility];
|
||||
}
|
||||
|
||||
- (void)updateButtonsVisibility {
|
||||
NSArray* buttons = @[
|
||||
[window_ standardWindowButton:NSWindowCloseButton],
|
||||
[window_ standardWindowButton:NSWindowMiniaturizeButton],
|
||||
[window_ standardWindowButton:NSWindowZoomButton],
|
||||
];
|
||||
// Show buttons when mouse hovers above them.
|
||||
BOOL hidden = show_on_hover_ && !mouse_inside_;
|
||||
// Always show buttons under fullscreen.
|
||||
if ([window_ styleMask] & NSWindowStyleMaskFullScreen)
|
||||
hidden = NO;
|
||||
for (NSView* button in buttons) {
|
||||
[button setHidden:hidden];
|
||||
[button setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
// Return the bounds of all 3 buttons.
|
||||
- (NSRect)getButtonsBounds {
|
||||
NSView* left = [self leftButton];
|
||||
NSView* right = [self rightButton];
|
||||
return NSMakeRect(NSMinX(left.frame), NSMinY(left.frame),
|
||||
NSMaxX(right.frame) - NSMinX(left.frame),
|
||||
NSHeight(left.frame));
|
||||
}
|
||||
|
||||
// Compute margin from position of current buttons.
|
||||
- (QPoint)getCurrentMargin {
|
||||
QPoint result;
|
||||
NSView* titleBarContainer = [self titleBarContainer];
|
||||
if (!titleBarContainer)
|
||||
return result;
|
||||
|
||||
NSView* left = [self leftButton];
|
||||
NSView* right = [self rightButton];
|
||||
|
||||
result.setX((NSHeight(titleBarContainer.frame) - NSHeight(left.frame)) / 2);
|
||||
|
||||
if (false /*base::i18n::IsRTL()*/)
|
||||
result.setX(NSWidth(window_.frame) - NSMaxX(right.frame));
|
||||
else
|
||||
result.setX(NSMinX(left.frame));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Receive the titlebar container, which might be nil if the window does not
|
||||
// have the NSWindowStyleMaskTitled style.
|
||||
- (NSView*)titleBarContainer {
|
||||
NSView* left = [self leftButton];
|
||||
if (!left.superview)
|
||||
return nil;
|
||||
return left.superview.superview;
|
||||
}
|
||||
|
||||
// Receive the window buttons, note that the buttons might be removed and
|
||||
// re-added on the fly so we should not cache them.
|
||||
- (NSButton*)leftButton {
|
||||
if (false /*base::i18n::IsRTL()*/)
|
||||
return [window_ standardWindowButton:NSWindowZoomButton];
|
||||
else
|
||||
return [window_ standardWindowButton:NSWindowCloseButton];
|
||||
}
|
||||
|
||||
- (NSButton*)middleButton {
|
||||
return [window_ standardWindowButton:NSWindowMiniaturizeButton];
|
||||
}
|
||||
|
||||
- (NSButton*)rightButton {
|
||||
if (false /*base::i18n::IsRTL()*/)
|
||||
return [window_ standardWindowButton:NSWindowCloseButton];
|
||||
else
|
||||
return [window_ standardWindowButton:NSWindowZoomButton];
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue