Custom title on macOS 10.10+ added.

This commit is contained in:
John Preston 2016-11-08 17:07:25 +03:00
parent 19f4e50e33
commit 475b35bf55
16 changed files with 336 additions and 170 deletions

View File

@ -77,7 +77,7 @@ void IntroWidget::onCheckUpdateStatus() {
if (Sandbox::updatingState() == Application::UpdatingReady) { if (Sandbox::updatingState() == Application::UpdatingReady) {
if (_update) return; if (_update) return;
_update.create(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton); _update.create(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton);
_update->show(); if (!_a_show.animating()) _update->show();
_update->setClickedCallback([] { _update->setClickedCallback([] {
checkReadyUpdate(); checkReadyUpdate();
App::restart(); App::restart();
@ -194,6 +194,8 @@ void IntroWidget::animShow(const QPixmap &bgAnimCache, bool back) {
_a_show.stop(); _a_show.stop();
step()->show(); step()->show();
_settings->show();
if (_update) _update->show();
if (step()->hasBack()) { if (step()->hasBack()) {
_back->showFast(); _back->showFast();
} else { } else {
@ -203,6 +205,8 @@ void IntroWidget::animShow(const QPixmap &bgAnimCache, bool back) {
step()->hide(); step()->hide();
_back->hideFast(); _back->hideFast();
_settings->hide();
if (_update) _update->hide();
a_coordUnder = back ? anim::ivalue(-st::slideShift, 0) : anim::ivalue(0, -st::slideShift); a_coordUnder = back ? anim::ivalue(-st::slideShift, 0) : anim::ivalue(0, -st::slideShift);
a_coordOver = back ? anim::ivalue(0, width()) : anim::ivalue(width(), 0); a_coordOver = back ? anim::ivalue(0, width()) : anim::ivalue(width(), 0);
@ -228,6 +232,8 @@ void IntroWidget::step_show(float64 ms, bool timer) {
if (step()->hasBack()) { if (step()->hasBack()) {
_back->showFast(); _back->showFast();
} }
_settings->show();
if (_update) _update->show();
if (App::app()) App::app()->mtpUnpause(); if (App::app()) App::app()->mtpUnpause();
} else { } else {
a_coordUnder.update(dt, Window::SlideAnimation::transition()); a_coordUnder.update(dt, Window::SlideAnimation::transition());

View File

@ -162,8 +162,6 @@ void MainWindow::onStateChanged(Qt::WindowState state) {
void MainWindow::initHook() { void MainWindow::initHook() {
Platform::MainWindow::initHook(); Platform::MainWindow::initHook();
setWindowIcon(wndIcon);
Application::instance()->installEventFilter(this); Application::instance()->installEventFilter(this);
connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState))); connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState)));
connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()), Qt::QueuedConnection); connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()), Qt::QueuedConnection);

View File

@ -191,6 +191,10 @@ MainWindow::MainWindow()
_psUpdateIndicatorTimer.setSingleShot(true); _psUpdateIndicatorTimer.setSingleShot(true);
} }
void MainWindow::initHook() {
setWindowIcon(wndIcon);
}
bool MainWindow::psHasTrayIcon() const { bool MainWindow::psHasTrayIcon() const {
return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (cWorkMode() != dbiwmWindowOnly)); return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (cWorkMode() != dbiwmWindowOnly));
} }

View File

@ -60,6 +60,7 @@ public slots:
void psUpdateIndicator(); void psUpdateIndicator();
protected: protected:
void initHook() override;
bool psHasTrayIcon() const; bool psHasTrayIcon() const;

View File

@ -25,13 +25,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Platform { namespace Platform {
class MacPrivate : public PsMacWindowPrivate {
public:
void activeSpaceChanged();
void darkModeChanged();
};
class MainWindow : public Window::MainWindow { class MainWindow : public Window::MainWindow {
Q_OBJECT Q_OBJECT
@ -64,8 +57,14 @@ public:
void closeWithoutDestroy() override; void closeWithoutDestroy() override;
int getCustomTitleHeight() const {
return _customTitleHeight;
}
~MainWindow(); ~MainWindow();
class Private;
public slots: public slots:
void psShowTrayMenu(); void psShowTrayMenu();
@ -82,6 +81,7 @@ private slots:
protected: protected:
void stateChangedHook(Qt::WindowState state) override; void stateChangedHook(Qt::WindowState state) override;
void initHook() override;
QImage psTrayIcon(bool selected = false) const; QImage psTrayIcon(bool selected = false) const;
bool psHasTrayIcon() const { bool psHasTrayIcon() const {
@ -106,7 +106,8 @@ protected:
private: private:
void createGlobalMenu(); void createGlobalMenu();
MacPrivate _private; friend class Private;
std_::unique_ptr<Private> _private;
mutable bool psIdle; mutable bool psIdle;
mutable QTimer psIdleTimer; mutable QTimer psIdleTimer;
@ -128,6 +129,8 @@ private:
QAction *psNewChannel = nullptr; QAction *psNewChannel = nullptr;
QAction *psShowTelegram = nullptr; QAction *psShowTelegram = nullptr;
int _customTitleHeight = 0;
}; };
} // namespace Platform } // namespace Platform

View File

@ -28,18 +28,72 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "platform/platform_notifications_manager.h" #include "platform/platform_notifications_manager.h"
#include "boxes/contactsbox.h" #include "boxes/contactsbox.h"
#include "boxes/aboutbox.h" #include "boxes/aboutbox.h"
#include "lang.h" #include "lang.h"
#include "platform/mac/mac_utilities.h"
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CFURL.h> #include <CoreFoundation/CFURL.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hidsystem/ev_keymap.h> #include <IOKit/hidsystem/ev_keymap.h>
#include <SPMediaKeyTap.h>
@interface MainWindowObserver : NSObject {
}
- (id) init:(MainWindow::Private*)window;
- (void) activeSpaceDidChange:(NSNotification *)aNotification;
- (void) darkModeChanged:(NSNotification *)aNotification;
- (void) screenIsLocked:(NSNotification *)aNotification;
- (void) screenIsUnlocked:(NSNotification *)aNotification;
- (void) windowWillEnterFullScreen:(NSNotification *)aNotification;
- (void) windowWillExitFullScreen:(NSNotification *)aNotification;
@end
namespace Platform { namespace Platform {
void MacPrivate::activeSpaceChanged() { class MainWindow::Private {
public:
Private(MainWindow *window);
void setWindowBadge(const QString &str);
void startBounce();
void enableShadow(WId winId);
bool filterNativeEvent(void *event);
void willEnterFullScreen();
void willExitFullScreen();
void initCustomTitle(NSWindow *window, NSView *view);
~Private();
private:
MainWindow *_public;
friend class MainWindow;
MainWindowObserver *_observer;
};
} // namespace Platform
@implementation MainWindowObserver {
MainWindow::Private *_private;
}
- (id) init:(MainWindow::Private*)window {
if (self = [super init]) {
_private = window;
}
return self;
}
- (void) activeSpaceDidChange:(NSNotification *)aNotification {
if (auto manager = Window::Notifications::Default::manager()) { if (auto manager = Window::Notifications::Default::manager()) {
manager->enumerateNotifications([](QWidget *widget) { manager->enumerateNotifications([](QWidget *widget) {
objc_activateWnd(widget->winId()); objc_activateWnd(widget->winId());
@ -47,14 +101,110 @@ void MacPrivate::activeSpaceChanged() {
} }
} }
void MacPrivate::darkModeChanged() { - (void) darkModeChanged:(NSNotification *)aNotification {
Notify::unreadCounterUpdated(); Notify::unreadCounterUpdated();
} }
- (void) screenIsLocked:(NSNotification *)aNotification {
Global::SetScreenIsLocked(true);
}
- (void) screenIsUnlocked:(NSNotification *)aNotification {
Global::SetScreenIsLocked(false);
}
- (void) windowWillEnterFullScreen:(NSNotification *)aNotification {
_private->willEnterFullScreen();
}
- (void) windowWillExitFullScreen:(NSNotification *)aNotification {
_private->willExitFullScreen();
}
@end
namespace Platform {
MainWindow::Private::Private(MainWindow *window)
: _public(window)
, _observer([[MainWindowObserver alloc] init:this]) {
@autoreleasepool {
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:_observer selector:@selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(darkModeChanged:) name:Q2NSString(strNotificationAboutThemeChange()) object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsLocked:) name:Q2NSString(strNotificationAboutScreenLocked()) object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsUnlocked:) name:Q2NSString(strNotificationAboutScreenUnlocked()) object:nil];
#ifndef OS_MAC_STORE
// Register defaults for the whitelist of apps that want to use media keys
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers], kMediaKeyUsingBundleIdentifiersDefaultsKey, nil]];
#endif // !OS_MAC_STORE
}
}
void MainWindow::Private::setWindowBadge(const QString &str) {
@autoreleasepool {
[[NSApp dockTile] setBadgeLabel:Q2NSString(str)];
}
}
void MainWindow::Private::startBounce() {
[NSApp requestUserAttention:NSInformationalRequest];
}
void MainWindow::Private::initCustomTitle(NSWindow *window, NSView *view) {
[window setStyleMask:[window styleMask] | NSFullSizeContentViewWindowMask];
[window setTitlebarAppearsTransparent:YES];
auto inner = [window contentLayoutRect];
auto full = [view frame];
_public->_customTitleHeight = qMax(qRound(full.size.height - inner.size.height), 0);
#ifndef OS_MAC_OLD
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
#endif // !OS_MAC_OLD
}
void MainWindow::Private::willEnterFullScreen() {
_public->setTitleVisibility(false);
}
void MainWindow::Private::willExitFullScreen() {
_public->setTitleVisibility(true);
}
void MainWindow::Private::enableShadow(WId winId) {
// [[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask];
// [[(NSView*)winId window] setHasShadow:YES];
}
bool MainWindow::Private::filterNativeEvent(void *event) {
NSEvent *e = static_cast<NSEvent*>(event);
if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) {
#ifndef OS_MAC_STORE
// If event tap is not installed, handle events that reach the app instead
if (![SPMediaKeyTap usesGlobalMediaKeyTap]) {
return objc_handleMediaKeyEvent(e);
}
#else // !OS_MAC_STORE
return objc_handleMediaKeyEvent(e);
#endif // else for !OS_MAC_STORE
}
return false;
}
MainWindow::Private::~Private() {
[_observer release];
}
MainWindow::MainWindow() MainWindow::MainWindow()
: icon256(qsl(":/gui/art/icon256.png")) : icon256(qsl(":/gui/art/icon256.png"))
, iconbig256(qsl(":/gui/art/iconbig256.png")) , iconbig256(qsl(":/gui/art/iconbig256.png"))
, wndIcon(QPixmap::fromImage(iconbig256, Qt::ColorOnly)) { , wndIcon(QPixmap::fromImage(iconbig256, Qt::ColorOnly))
, _private(std_::make_unique<Private>(this)) {
QImage tray(qsl(":/gui/art/osxtray.png")); QImage tray(qsl(":/gui/art/osxtray.png"));
trayImg = tray.copy(0, cRetina() ? 0 : tray.width() / 2, tray.width() / (cRetina() ? 2 : 4), tray.width() / (cRetina() ? 2 : 4)); trayImg = tray.copy(0, cRetina() ? 0 : tray.width() / 2, tray.width() / (cRetina() ? 2 : 4), tray.width() / (cRetina() ? 2 : 4));
trayImgSel = tray.copy(tray.width() / (cRetina() ? 2 : 4), cRetina() ? 0 : tray.width() / 2, tray.width() / (cRetina() ? 2 : 4), tray.width() / (cRetina() ? 2 : 4)); trayImgSel = tray.copy(tray.width() / (cRetina() ? 2 : 4), cRetina() ? 0 : tray.width() / 2, tray.width() / (cRetina() ? 2 : 4), tray.width() / (cRetina() ? 2 : 4));
@ -81,6 +231,18 @@ void MainWindow::stateChangedHook(Qt::WindowState state) {
} }
} }
void MainWindow::initHook() {
_customTitleHeight = 0;
if (auto view = reinterpret_cast<NSView*>(winId())) {
if (auto window = [view window]) {
if ([window respondsToSelector:@selector(contentLayoutRect)]
&& [window respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
_private->initCustomTitle(window, view);
}
}
}
}
void MainWindow::onHideAfterFullScreen() { void MainWindow::onHideAfterFullScreen() {
hide(); hide();
} }
@ -124,7 +286,6 @@ void MainWindow::psUpdateWorkmode() {
if (auto manager = Platform::Notifications::manager()) { if (auto manager = Platform::Notifications::manager()) {
manager->updateDelegate(); manager->updateDelegate();
} }
setWindowIcon(wndIcon);
} }
void _placeCounter(QImage &img, int size, int count, const style::color &bg, const style::color &color) { void _placeCounter(QImage &img, int size, int count, const style::color &bg, const style::color &color) {
@ -166,10 +327,9 @@ void MainWindow::psUpdateCounter() {
int32 counter = App::histories().unreadBadge(); int32 counter = App::histories().unreadBadge();
setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"));
setWindowIcon(wndIcon);
QString cnt = (counter < 1000) ? QString("%1").arg(counter) : QString("..%1").arg(counter % 100, 2, 10, QChar('0')); QString cnt = (counter < 1000) ? QString("%1").arg(counter) : QString("..%1").arg(counter % 100, 2, 10, QChar('0'));
_private.setWindowBadge(counter ? cnt : QString()); _private->setWindowBadge(counter ? cnt : QString());
if (trayIcon) { if (trayIcon) {
bool muted = App::histories().unreadOnlyMuted(); bool muted = App::histories().unreadOnlyMuted();
@ -195,7 +355,7 @@ void MainWindow::psFirstShow() {
bool showShadows = true; bool showShadows = true;
show(); show();
_private.enableShadow(winId()); _private->enableShadow(winId());
if (cWindowPos().maximized) { if (cWindowPos().maximized) {
setWindowState(Qt::WindowMaximized); setWindowState(Qt::WindowMaximized);
} }
@ -353,11 +513,11 @@ void MainWindow::psMacUpdateMenu() {
} }
void MainWindow::psFlash() { void MainWindow::psFlash() {
_private.startBounce(); return _private->startBounce();
} }
bool MainWindow::psFilterNativeEvent(void *event) { bool MainWindow::psFilterNativeEvent(void *event) {
return _private.filterNativeEvent(event); return _private->filterNativeEvent(event);
} }
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) { bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {

View File

@ -0,0 +1,46 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "window/window_title.h"
namespace Ui {
class PlainShadow;
} // namespace Ui
namespace Platform {
class TitleWidget : public Window::TitleWidget {
public:
TitleWidget(QWidget *parent, int height);
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private:
ChildWidget<Ui::PlainShadow> _shadow;
};
Window::TitleWidget *CreateTitleWidget(QWidget *parent);
} // namespace Platform

View File

@ -0,0 +1,53 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "platform/mac/window_title_mac.h"
#include "ui/widgets/shadow.h"
#include "styles/style_window.h"
#include "platform/platform_main_window.h"
namespace Platform {
TitleWidget::TitleWidget(QWidget *parent, int height) : Window::TitleWidget(parent)
, _shadow(this, st::titleShadow) {
setAttribute(Qt::WA_OpaquePaintEvent);
resize(width(), height);
}
void TitleWidget::paintEvent(QPaintEvent *e) {
Painter(this).fillRect(rect(), st::titleBg);
}
void TitleWidget::resizeEvent(QResizeEvent *e) {
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
}
Window::TitleWidget *CreateTitleWidget(QWidget *parent) {
if (auto window = qobject_cast<Platform::MainWindow*>(parent)) {
if (auto height = window->getCustomTitleHeight()) {
return new TitleWidget(parent, height);
}
}
return nullptr;
}
} // namespace Platform

View File

@ -22,9 +22,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "window/window_title.h" #include "window/window_title.h"
#if defined Q_OS_WIN #ifdef Q_OS_MAC
#include "platform/mac/window_title_mac.h"
#elif defined Q_OS_WIN // Q_OS_MAC
#include "platform/win/window_title_win.h" #include "platform/win/window_title_win.h"
#else // Q_OS_WIN #elif defined Q_OS_WINRT || defined Q_OS_LINUX
namespace Platform { namespace Platform {
inline Window::TitleWidget *CreateTitleWidget(QWidget *parent) { inline Window::TitleWidget *CreateTitleWidget(QWidget *parent) {
@ -32,4 +34,4 @@ inline Window::TitleWidget *CreateTitleWidget(QWidget *parent) {
} }
} // namespace Platform } // namespace Platform
#endif // else for Q_OS_WIN #endif // Q_OS_MAC || Q_OS_WIN || Q_OS_WINRT || Q_OS_LINUX

View File

@ -777,6 +777,8 @@ void MainWindow::initHook() {
} }
psInitSysMenu(); psInitSysMenu();
setWindowIcon(wndIcon);
} }
bool MainWindow::psHasNativeNotifications() { bool MainWindow::psHasNativeNotifications() {

View File

@ -47,6 +47,7 @@ TitleWidget::TitleWidget(QWidget *parent) : Window::TitleWidget(parent)
}); });
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
resize(width(), st::titleHeight);
} }
void TitleWidget::init() { void TitleWidget::init() {

View File

@ -17,29 +17,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
class PsMacWindowData; // e is NSEvent*
bool objc_handleMediaKeyEvent(void *e);
class PsMacWindowPrivate {
public:
PsMacWindowPrivate();
void setWindowBadge(const QString &str);
void startBounce();
void enableShadow(WId winId);
bool filterNativeEvent(void *event);
virtual void activeSpaceChanged() {
}
virtual void darkModeChanged() {
}
~PsMacWindowPrivate();
PsMacWindowData *data;
};
void objc_holdOnTop(WId winId); void objc_holdOnTop(WId winId);
bool objc_darkMode(); bool objc_darkMode();

View File

@ -28,19 +28,15 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "lang.h" #include "lang.h"
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CFURL.h> #include <CoreFoundation/CFURL.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hidsystem/ev_keymap.h> #include <IOKit/hidsystem/ev_keymap.h>
#include <SPMediaKeyTap.h> #include <SPMediaKeyTap.h>
using Platform::Q2NSString; using Platform::Q2NSString;
using Platform::NSlang; using Platform::NSlang;
using Platform::NS2QString; using Platform::NS2QString;
bool handleMediaKeyEvent(NSEvent *e);
@interface qVisualize : NSObject { @interface qVisualize : NSObject {
} }
@ -152,68 +148,12 @@ ApplicationDelegate *_sharedDelegate = nil;
- (void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)e { - (void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)e {
if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) { if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) {
handleMediaKeyEvent(e); objc_handleMediaKeyEvent(e);
} }
} }
@end @end
@interface ObserverHelper : NSObject {
}
- (id) init:(PsMacWindowPrivate *)aWnd;
- (void) activeSpaceDidChange:(NSNotification *)aNotification;
- (void) darkModeChanged:(NSNotification *)aNotification;
- (void) screenIsLocked:(NSNotification *)aNotification;
- (void) screenIsUnlocked:(NSNotification *)aNotification;
@end
class PsMacWindowData {
public:
PsMacWindowData(PsMacWindowPrivate *wnd) :
wnd(wnd),
observerHelper([[ObserverHelper alloc] init:wnd]) {
}
~PsMacWindowData() {
[observerHelper release];
}
PsMacWindowPrivate *wnd;
ObserverHelper *observerHelper;
};
@implementation ObserverHelper {
PsMacWindowPrivate *wnd;
}
- (id) init:(PsMacWindowPrivate *)aWnd {
if (self = [super init]) {
wnd = aWnd;
}
return self;
}
- (void) activeSpaceDidChange:(NSNotification *)aNotification {
wnd->activeSpaceChanged();
}
- (void) darkModeChanged:(NSNotification *)aNotification {
wnd->darkModeChanged();
}
- (void) screenIsLocked:(NSNotification *)aNotification {
Global::SetScreenIsLocked(true);
}
- (void) screenIsUnlocked:(NSNotification *)aNotification {
Global::SetScreenIsLocked(false);
}
@end
namespace Platform { namespace Platform {
void SetWatchingMediaKeys(bool watching) { void SetWatchingMediaKeys(bool watching) {
@ -224,34 +164,6 @@ void SetWatchingMediaKeys(bool watching) {
} // namespace Platform } // namespace Platform
PsMacWindowPrivate::PsMacWindowPrivate() : data(new PsMacWindowData(this)) {
@autoreleasepool {
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:data->observerHelper selector:@selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(darkModeChanged:) name:Q2NSString(strNotificationAboutThemeChange()) object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(screenIsLocked:) name:Q2NSString(strNotificationAboutScreenLocked()) object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(screenIsUnlocked:) name:Q2NSString(strNotificationAboutScreenUnlocked()) object:nil];
#ifndef OS_MAC_STORE
// Register defaults for the whitelist of apps that want to use media keys
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers], kMediaKeyUsingBundleIdentifiersDefaultsKey, nil]];
#endif // OS_MAC_STORE
}
}
void PsMacWindowPrivate::setWindowBadge(const QString &str) {
@autoreleasepool {
[[NSApp dockTile] setBadgeLabel:Q2NSString(str)];
}
}
void PsMacWindowPrivate::startBounce() {
[NSApp requestUserAttention:NSInformationalRequest];
}
void objc_holdOnTop(WId winId) { void objc_holdOnTop(WId winId) {
NSWindow *wnd = [reinterpret_cast<NSView *>(winId) window]; NSWindow *wnd = [reinterpret_cast<NSView *>(winId) window];
[wnd setHidesOnDeactivate:NO]; [wnd setHidesOnDeactivate:NO];
@ -289,7 +201,9 @@ void objc_activateWnd(WId winId) {
[wnd orderFront:wnd]; [wnd orderFront:wnd];
} }
bool handleMediaKeyEvent(NSEvent *e) { bool objc_handleMediaKeyEvent(void *ev) {
auto e = reinterpret_cast<NSEvent*>(ev);
int keyCode = (([e data1] & 0xFFFF0000) >> 16); int keyCode = (([e data1] & 0xFFFF0000) >> 16);
int keyFlags = ([e data1] & 0x0000FFFF); int keyFlags = ([e data1] & 0x0000FFFF);
int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA; int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
@ -330,26 +244,6 @@ bool handleMediaKeyEvent(NSEvent *e) {
return false; return false;
} }
void PsMacWindowPrivate::enableShadow(WId winId) {
// [[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask];
// [[(NSView*)winId window] setHasShadow:YES];
}
bool PsMacWindowPrivate::filterNativeEvent(void *event) {
NSEvent *e = static_cast<NSEvent*>(event);
if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) {
#ifndef OS_MAC_STORE
// If event tap is not installed, handle events that reach the app instead
if (![SPMediaKeyTap usesGlobalMediaKeyTap]) {
return handleMediaKeyEvent(e);
}
#else // !OS_MAC_STORE
return handleMediaKeyEvent(e);
#endif // else for !OS_MAC_STORE
}
return false;
}
void objc_debugShowAlert(const QString &str) { void objc_debugShowAlert(const QString &str) {
@autoreleasepool { @autoreleasepool {
@ -366,10 +260,6 @@ void objc_outputDebugString(const QString &str) {
} }
} }
PsMacWindowPrivate::~PsMacWindowPrivate() {
delete data;
}
bool objc_idleSupported() { bool objc_idleSupported() {
int64 idleTime = 0; int64 idleTime = 0;
return objc_idleTime(idleTime); return objc_idleTime(idleTime);

View File

@ -39,11 +39,11 @@ MainWindow::MainWindow() : QWidget()
} }
} }
}); });
_title = Platform::CreateTitleWidget(this);
} }
void MainWindow::init() { void MainWindow::init() {
initHook();
_positionUpdatedTimer->setSingleShot(true); _positionUpdatedTimer->setSingleShot(true);
connect(_positionUpdatedTimer, SIGNAL(timeout()), this, SLOT(savePositionByTimer())); connect(_positionUpdatedTimer, SIGNAL(timeout()), this, SLOT(savePositionByTimer()));
@ -51,10 +51,11 @@ void MainWindow::init() {
p.setColor(QPalette::Window, st::windowBg->c); p.setColor(QPalette::Window, st::windowBg->c);
setPalette(p); setPalette(p);
if (_title) _title->init(); if ((_title = Platform::CreateTitleWidget(this))) {
_title->init();
}
initSize(); initSize();
initHook();
} }
HitTestResult MainWindow::hitTest(const QPoint &p) const { HitTestResult MainWindow::hitTest(const QPoint &p) const {
@ -104,6 +105,13 @@ void MainWindow::positionUpdated() {
_positionUpdatedTimer->start(SaveWindowPositionTimeout); _positionUpdatedTimer->start(SaveWindowPositionTimeout);
} }
void MainWindow::setTitleVisibility(bool visible) {
if (_title && (_title->isHidden() == visible)) {
_title->setVisible(visible);
updateControlsGeometry();
}
}
int32 MainWindow::screenNameChecksum(const QString &name) const { int32 MainWindow::screenNameChecksum(const QString &name) const {
auto bytes = name.toUtf8(); auto bytes = name.toUtf8();
return hashCrc32(bytes.constData(), bytes.size()); return hashCrc32(bytes.constData(), bytes.size());
@ -114,9 +122,13 @@ void MainWindow::setPositionInited() {
} }
void MainWindow::resizeEvent(QResizeEvent *e) { void MainWindow::resizeEvent(QResizeEvent *e) {
updateControlsGeometry();
}
void MainWindow::updateControlsGeometry() {
auto bodyTop = 0; auto bodyTop = 0;
if (_title) { if (_title && !_title->isHidden()) {
_title->setGeometry(0, bodyTop, width(), st::titleHeight); _title->setGeometry(0, bodyTop, width(), _title->height());
bodyTop += _title->height(); bodyTop += _title->height();
} }
_body->setGeometry(0, bodyTop, width(), height() - bodyTop); _body->setGeometry(0, bodyTop, width(), height() - bodyTop);

View File

@ -40,6 +40,8 @@ public:
} }
void positionUpdated(); void positionUpdated();
void setTitleVisibility(bool visible);
virtual void closeWithoutDestroy(); virtual void closeWithoutDestroy();
virtual ~MainWindow(); virtual ~MainWindow();
@ -70,6 +72,7 @@ private slots:
} }
private: private:
void updateControlsGeometry();
void initSize(); void initSize();
ChildObject<QTimer> _positionUpdatedTimer; ChildObject<QTimer> _positionUpdatedTimer;

View File

@ -369,6 +369,8 @@
'<(src_loc)/platform/mac/main_window_mac.h', '<(src_loc)/platform/mac/main_window_mac.h',
'<(src_loc)/platform/mac/notifications_manager_mac.mm', '<(src_loc)/platform/mac/notifications_manager_mac.mm',
'<(src_loc)/platform/mac/notifications_manager_mac.h', '<(src_loc)/platform/mac/notifications_manager_mac.h',
'<(src_loc)/platform/mac/window_title_mac.mm',
'<(src_loc)/platform/mac/window_title_mac.h',
'<(src_loc)/platform/win/main_window_win.cpp', '<(src_loc)/platform/win/main_window_win.cpp',
'<(src_loc)/platform/win/main_window_win.h', '<(src_loc)/platform/win/main_window_win.h',
'<(src_loc)/platform/win/notifications_manager_win.cpp', '<(src_loc)/platform/win/notifications_manager_win.cpp',
@ -605,6 +607,8 @@
'<(src_loc)/platform/mac/main_window_mac.h', '<(src_loc)/platform/mac/main_window_mac.h',
'<(src_loc)/platform/mac/notifications_manager_mac.mm', '<(src_loc)/platform/mac/notifications_manager_mac.mm',
'<(src_loc)/platform/mac/notifications_manager_mac.h', '<(src_loc)/platform/mac/notifications_manager_mac.h',
'<(src_loc)/platform/mac/window_title_mac.mm',
'<(src_loc)/platform/mac/window_title_mac.h',
'<(sp_media_key_tap_loc)/SPMediaKeyTap.m', '<(sp_media_key_tap_loc)/SPMediaKeyTap.m',
'<(sp_media_key_tap_loc)/SPMediaKeyTap.h', '<(sp_media_key_tap_loc)/SPMediaKeyTap.h',
'<(sp_media_key_tap_loc)/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m', '<(sp_media_key_tap_loc)/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m',
@ -628,6 +632,8 @@
'<(src_loc)/platform/win/main_window_win.h', '<(src_loc)/platform/win/main_window_win.h',
'<(src_loc)/platform/win/notifications_manager_win.cpp', '<(src_loc)/platform/win/notifications_manager_win.cpp',
'<(src_loc)/platform/win/notifications_manager_win.h', '<(src_loc)/platform/win/notifications_manager_win.h',
'<(src_loc)/platform/win/window_title_win.cpp',
'<(src_loc)/platform/win/window_title_win.h',
'<(src_loc)/platform/win/windows_app_user_model_id.cpp', '<(src_loc)/platform/win/windows_app_user_model_id.cpp',
'<(src_loc)/platform/win/windows_app_user_model_id.h', '<(src_loc)/platform/win/windows_app_user_model_id.h',
'<(src_loc)/platform/win/windows_dlls.cpp', '<(src_loc)/platform/win/windows_dlls.cpp',