From 9fa515a9d49d98d4ed75ab8fdafe55c2e1ea0f64 Mon Sep 17 00:00:00 2001 From: Admin Date: Sun, 3 Jan 2021 23:55:04 +0300 Subject: [PATCH] ui fixes for macos --- client/client.pro | 11 +- client/ui/framelesswindow.mm | 231 ----------------------------------- client/ui/macos_util.h | 8 ++ client/ui/macos_util.mm | 48 ++++++++ client/ui/mainwindow.cpp | 14 +++ client/ui/mainwindow.h | 5 + 6 files changed, 81 insertions(+), 236 deletions(-) delete mode 100644 client/ui/framelesswindow.mm create mode 100644 client/ui/macos_util.h create mode 100644 client/ui/macos_util.mm diff --git a/client/client.pro b/client/client.pro index f05ee2d7..ff423075 100644 --- a/client/client.pro +++ b/client/client.pro @@ -23,7 +23,6 @@ HEADERS += \ runguard.h \ settings.h \ ui/Controls/SlidingStackedWidget.h \ - ui/framelesswindow.h \ ui/mainwindow.h \ utils.h \ vpnconnection.h \ @@ -67,7 +66,9 @@ win32 { OTHER_FILES += platform_win/vpnclient.rc RC_FILE = platform_win/vpnclient.rc - HEADERS += + HEADERS += \ + ui/framelesswindow.h \ + SOURCES += \ ui/framelesswindow.cpp @@ -92,8 +93,8 @@ win32 { macx { ICON = $$PWD/images/app.icns - HEADERS += - SOURCES += \ - ui/framelesswindow.mm + HEADERS += ui/macos_util.h + SOURCES += ui/macos_util.mm + LIBS += -framework Cocoa } diff --git a/client/ui/framelesswindow.mm b/client/ui/framelesswindow.mm deleted file mode 100644 index 94686643..00000000 --- a/client/ui/framelesswindow.mm +++ /dev/null @@ -1,231 +0,0 @@ -// This code is a part of Qt-Nice-Frameless-Window -// https://github.com/Bringer-of-Light/Qt-Nice-Frameless-Window -// Licensed by MIT License - https://github.com/Bringer-of-Light/Qt-Nice-Frameless-Window/blob/master/LICENSE - - -#include "framelesswindow.h" -#ifdef Q_OS_MAC -#include -#include - -CFramelessWindow::CFramelessWindow(QWidget *parent) - : QMainWindow(parent), - m_draggableHeight(0), - m_bWinMoving(false), - m_bMousePressed(false), - m_bCloseBtnQuit(true), - m_bNativeSystemBtn(false), - m_bIsCloseBtnEnabled(true), - m_bIsMinBtnEnabled(true), - m_bIsZoomBtnEnabled(true), - m_bTitleBarVisible(false) -{ - initUI(); -} - -//此类用于支持重载系统按钮的行为 -//this Objective-c class is used to override the action of sysytem close button and zoom button -//https://stackoverflow.com/questions/27643659/setting-c-function-as-selector-for-nsbutton-produces-no-results -@interface ButtonPasser : NSObject{ -} -@property(readwrite) CFramelessWindow* window; -+ (void)closeButtonAction:(id)sender; -- (void)zoomButtonAction:(id)sender; -@end - -@implementation ButtonPasser{ -} -+ (void)closeButtonAction:(id)sender -{ - Q_UNUSED(sender); - ProcessSerialNumber pn; - GetFrontProcess (&pn); - ShowHideProcess(&pn,false); -} -- (void)zoomButtonAction:(id)sender -{ - Q_UNUSED(sender); - if (0 == self.window) return; - if (self.window->isMaximized()) self.window->showNormal(); - else self.window->showMaximized(); -} -@end - -void CFramelessWindow::initUI() -{ - m_bNativeSystemBtn = false; - - //如果当前osx版本老于10.9,则后续代码不可用。转为使用定制的系统按钮,不支持自由缩放窗口及窗口阴影 - if (QSysInfo::MV_None == QSysInfo::macVersion()) - { - if (QSysInfo::MV_None == QSysInfo::MacintoshVersion) {setWindowFlags(Qt::FramelessWindowHint); return;} - } - if (QSysInfo::MV_10_9 >= QSysInfo::MacintoshVersion) {setWindowFlags(Qt::FramelessWindowHint); return;} - - NSView* view = (NSView*)winId(); - if (0 == view) {setWindowFlags(Qt::FramelessWindowHint); return;} - NSWindow *window = view.window; - if (0 == window) {setWindowFlags(Qt::FramelessWindowHint); return;} - - //设置标题文字和图标为不可见 - window.titleVisibility = NSWindowTitleHidden; //MAC_10_10及以上版本支持 - //设置标题栏为透明 - window.titlebarAppearsTransparent = YES; //MAC_10_10及以上版本支持 - //设置不可由标题栏拖动,避免与自定义拖动冲突 - [window setMovable:NO]; //MAC_10_6及以上版本支持 - //window.movableByWindowBackground = YES; - //设置view扩展到标题栏 - window.styleMask |= NSWindowStyleMaskFullSizeContentView; //MAC_10_10及以上版本支持 - - m_bNativeSystemBtn = true; - - ButtonPasser * passer = [[ButtonPasser alloc] init]; - passer.window = this; - //重载全屏按钮的行为 - //override the action of fullscreen button - NSButton *zoomButton = [window standardWindowButton:NSWindowZoomButton]; - [zoomButton setTarget:passer]; - [zoomButton setAction:@selector(zoomButtonAction:)]; -} - -void CFramelessWindow::setCloseBtnQuit(bool bQuit) -{ - if (bQuit || !m_bNativeSystemBtn) return; - NSView* view = (NSView*)winId(); - if (0 == view) return; - NSWindow *window = view.window; - if (0 == window) return; - - //重载关闭按钮的行为 - //override the action of close button - //https://stackoverflow.com/questions/27643659/setting-c-function-as-selector-for-nsbutton-produces-no-results - //https://developer.apple.com/library/content/documentation/General/Conceptual/CocoaEncyclopedia/Target-Action/Target-Action.html - NSButton *closeButton = [window standardWindowButton:NSWindowCloseButton]; - [closeButton setTarget:[ButtonPasser class]]; - [closeButton setAction:@selector(closeButtonAction:)]; -} - -void CFramelessWindow::setCloseBtnEnabled(bool bEnable) -{ - if (!m_bNativeSystemBtn) return; - NSView* view = (NSView*)winId(); - if (0 == view) return; - NSWindow *window = view.window; - if (0 == window) return; - - m_bIsCloseBtnEnabled = bEnable; - if (bEnable){ - [[window standardWindowButton:NSWindowCloseButton] setEnabled:YES]; - }else{ - [[window standardWindowButton:NSWindowCloseButton] setEnabled:NO]; - } -} - -void CFramelessWindow::setMinBtnEnabled(bool bEnable) -{ - if (!m_bNativeSystemBtn) return; - NSView* view = (NSView*)winId(); - if (0 == view) return; - NSWindow *window = view.window; - if (0 == window) return; - - m_bIsMinBtnEnabled = bEnable; - if (bEnable){ - [[window standardWindowButton:NSWindowMiniaturizeButton] setEnabled:YES]; - }else{ - [[window standardWindowButton:NSWindowMiniaturizeButton] setEnabled:NO]; - } -} - -void CFramelessWindow::setZoomBtnEnabled(bool bEnable) -{ - if (!m_bNativeSystemBtn) return; - NSView* view = (NSView*)winId(); - if (0 == view) return; - NSWindow *window = view.window; - if (0 == window) return; - - m_bIsZoomBtnEnabled = bEnable; - if (bEnable){ - [[window standardWindowButton:NSWindowZoomButton] setEnabled:YES]; - }else{ - [[window standardWindowButton:NSWindowZoomButton] setEnabled:NO]; - } -} - -void CFramelessWindow::setDraggableAreaHeight(int height) -{ - if (height < 0) height = 0; - m_draggableHeight = height; -} - -void CFramelessWindow::mousePressEvent(QMouseEvent *event) -{ - if ((event->button() != Qt::LeftButton) || isMaximized() ) - { - return QMainWindow::mousePressEvent(event); - } - - int height = size().height(); - if (m_draggableHeight > 0) height = m_draggableHeight; - QRect rc; - rc.setRect(0,0,size().width(), height); - if(rc.contains(this->mapFromGlobal(QCursor::pos()))==true)//如果按下的位置 - { - m_WindowPos = this->pos(); - m_MousePos = event->globalPos(); - m_bMousePressed = true; - } - return QMainWindow::mousePressEvent(event); -} - -void CFramelessWindow::mouseReleaseEvent(QMouseEvent *event) -{ - m_bWinMoving = false; - if ((event->button() == Qt::LeftButton)) - { - m_bMousePressed = false; - } - return QMainWindow::mouseReleaseEvent(event); -} - -void CFramelessWindow::mouseMoveEvent(QMouseEvent *event) -{ - if (!m_bMousePressed) return QMainWindow::mouseMoveEvent(event); - m_bWinMoving = true; - this->move(m_WindowPos + (event->globalPos() - m_MousePos)); - return QMainWindow::mouseMoveEvent(event); -} - -void CFramelessWindow::resizeEvent(QResizeEvent *event) -{ - QMainWindow::resizeEvent(event); - //TODO -// if (!isFullScreen()) -// { -// emit restoreFromFullScreen(); -// } -} - -void CFramelessWindow::onRestoreFromFullScreen() -{ - setTitlebarVisible(false); -} - -void CFramelessWindow::setTitlebarVisible(bool bTitlebarVisible) -{ - if (!m_bNativeSystemBtn) return; - NSView* view = (NSView*)winId(); - if (0 == view) return; - NSWindow *window = view.window; - if (0 == window) return; - - m_bTitleBarVisible = bTitlebarVisible; - if (bTitlebarVisible) - { - window.styleMask ^= NSWindowStyleMaskFullSizeContentView; //MAC_10_10及以上版本支持 - }else{ - window.styleMask |= NSWindowStyleMaskFullSizeContentView; //MAC_10_10及以上版本支持 - } -} -#endif //Q_OS_MAC diff --git a/client/ui/macos_util.h b/client/ui/macos_util.h new file mode 100644 index 00000000..831f1f88 --- /dev/null +++ b/client/ui/macos_util.h @@ -0,0 +1,8 @@ +#ifndef OSXUTIL_H +#define OSXUTIL_H +#include +#include + +void fixWidget(QWidget *widget); + +#endif diff --git a/client/ui/macos_util.mm b/client/ui/macos_util.mm new file mode 100644 index 00000000..9f433747 --- /dev/null +++ b/client/ui/macos_util.mm @@ -0,0 +1,48 @@ +#include +#include +#include "macos_util.h" + +//this Objective-c class is used to override the action of system close button and zoom button +//https://stackoverflow.com/questions/27643659/setting-c-function-as-selector-for-nsbutton-produces-no-results +@interface ButtonPasser : NSObject{ +} +@property(readwrite) QMainWindow* window; ++ (void)closeButtonAction:(id)sender; +- (void)zoomButtonAction:(id)sender; +@end + +@implementation ButtonPasser{ +} ++ (void)closeButtonAction:(id)sender +{ + Q_UNUSED(sender); + ProcessSerialNumber pn; + GetFrontProcess (&pn); + ShowHideProcess(&pn,false); +} +- (void)zoomButtonAction:(id)sender +{ + Q_UNUSED(sender); + if (0 == self.window) return; + if (self.window->isMaximized()) self.window->showNormal(); + else self.window->showMaximized(); +} +@end + +void fixWidget(QWidget *widget) +{ + NSView *view = (NSView *)widget->winId(); + if (0 == view) return; + NSWindow *window = view.window; + if (0 == window) return; + + //override the action of close button + //https://stackoverflow.com/questions/27643659/setting-c-function-as-selector-for-nsbutton-produces-no-results + //https://developer.apple.com/library/content/documentation/General/Conceptual/CocoaEncyclopedia/Target-Action/Target-Action.html +// NSButton *closeButton = [window standardWindowButton:NSWindowCloseButton]; +// [closeButton setTarget:[ButtonPasser class]]; +// [closeButton setAction:@selector(closeButtonAction:)]; + + [[window standardWindowButton:NSWindowZoomButton] setHidden:YES]; + [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; +} diff --git a/client/ui/mainwindow.cpp b/client/ui/mainwindow.cpp index f0ce2c91..cc13775f 100644 --- a/client/ui/mainwindow.cpp +++ b/client/ui/mainwindow.cpp @@ -14,8 +14,16 @@ #include "utils.h" #include "vpnconnection.h" +#ifdef Q_OS_MAC +#include "ui/macos_util.h" +#endif + MainWindow::MainWindow(QWidget *parent) : +#ifdef Q_OS_WIN CFramelessWindow(parent), +#else + QMainWindow(parent), +#endif ui(new Ui::MainWindow), m_settings(new Settings), m_vpnConnection(nullptr) @@ -26,6 +34,12 @@ MainWindow::MainWindow(QWidget *parent) : ui->stackedWidget_main->setSpeed(200); ui->stackedWidget_main->setAnimation(QEasingCurve::Linear); +#ifdef Q_OS_MAC + ui->widget_tittlebar->hide(); + ui->stackedWidget_main->move(0,0); + fixWidget(this); +#endif + // Post initialization if (m_settings->haveAuthData()) { diff --git a/client/ui/mainwindow.h b/client/ui/mainwindow.h index 3795973f..f5042181 100644 --- a/client/ui/mainwindow.h +++ b/client/ui/mainwindow.h @@ -16,7 +16,12 @@ class MainWindow; /** * @brief The MainWindow class - Main application window */ +#ifdef Q_OS_WIN class MainWindow : public CFramelessWindow +#else +class MainWindow : public QMainWindow +#endif + { Q_OBJECT