Fix calls build in Xcode. Fix calls panel in Retina.

Also implement panels that appear in all spaces on macOS.
Using them for calls panels and custom notifications, so it
will be possible to use custom notifications in macOS as well.
This commit is contained in:
John Preston
2017-05-02 10:25:20 +03:00
parent e050e270fc
commit 0cdac83f8a
17 changed files with 104 additions and 50 deletions
@@ -46,10 +46,10 @@ public:
, _cache(cache) {
resize(cache.width() / cache.devicePixelRatio(), cache.height() / cache.devicePixelRatio());
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool);
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_OpaquePaintEvent);
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint);
setWindowOpacity(0.);
show();
@@ -113,16 +113,16 @@ BoxController::Row::Row(HistoryItem *item) : PeerListBox::Row(item->history()->p
}
void BoxController::Row::paintStatusText(Painter &p, int x, int y, int outerWidth, bool selected) {
auto &icon = ([this] {
auto icon = ([this] {
switch (_type) {
case Type::In: return st::callArrowIn;
case Type::Out: return st::callArrowOut;
case Type::Missed: return st::callArrowMissed;
case Type::In: return &st::callArrowIn;
case Type::Out: return &st::callArrowOut;
case Type::Missed: return &st::callArrowMissed;
}
Unexpected("_type in Calls::BoxController::Row::paintStatusText().");
})();
icon.paint(p, x + st::callArrowPosition.x(), y + st::callArrowPosition.y(), outerWidth);
x += + st::callArrowPosition.x() + icon.width() + st::callArrowSkip;
icon->paint(p, x + st::callArrowPosition.x(), y + st::callArrowPosition.y(), outerWidth);
x += + st::callArrowPosition.x() + icon->width() + st::callArrowSkip;
PeerListBox::Row::paintStatusText(p, x, y, outerWidth, selected);
}
@@ -285,7 +285,7 @@ bool BoxController::insertRow(HistoryItem *item, InsertWay way) {
}
}
(way == InsertWay::Append) ? view()->appendRow(createRow(item)) : view()->prependRow(createRow(item));
view()->reorderRows([](auto &begin, auto &end) {
view()->reorderRows([](auto &&begin, auto &&end) {
std::sort(begin, end, [](auto &a, auto &b) {
return static_cast<Row&>(*a).maxItemId() > static_cast<Row&>(*a).maxItemId();
});
+8 -6
View File
@@ -184,8 +184,6 @@ void Panel::refreshCallbacks() {
}
void Panel::initLayout() {
hide();
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool);
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
setAttribute(Qt::WA_NoSystemBackground, true);
@@ -203,6 +201,8 @@ void Panel::initLayout() {
refreshUserPhoto();
});
createDefaultCacheImage();
Platform::InitOnTopPanel(this);
}
void Panel::processUserPhoto() {
@@ -235,7 +235,7 @@ void Panel::refreshUserPhoto() {
void Panel::createUserpicCache(ImagePtr image) {
auto size = st::callWidth * cIntRetinaFactor();
auto options = _useTransparency ? (Images::Option::RoundedLarge | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::Smooth) : 0;
auto options = _useTransparency ? (Images::Option::RoundedLarge | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::Smooth) : Images::Option::None;
auto width = image->width();
auto height = image->height();
if (width > height) {
@@ -245,7 +245,7 @@ void Panel::createUserpicCache(ImagePtr image) {
height = qMax((height * size) / width, 1);
width = size;
}
_userPhoto = image->pixNoCache(width, height, options, size, size);
_userPhoto = image->pixNoCache(width, height, options, st::callWidth, st::callWidth);
if (cRetina()) _userPhoto.setDevicePixelRatio(cRetinaFactor());
refreshCacheImageUserPhoto();
@@ -301,7 +301,8 @@ void Panel::createDefaultCacheImage() {
if (!_useTransparency || !_cache.isNull()) {
return;
}
auto cache = QImage(size(), QImage::Format_ARGB32_Premultiplied);
auto cache = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
cache.setDevicePixelRatio(cRetinaFactor());
cache.fill(Qt::transparent);
{
Painter p(&cache);
@@ -317,7 +318,8 @@ void Panel::createDefaultCacheImage() {
}
void Panel::refreshCacheImageUserPhoto() {
auto cache = QImage(size(), QImage::Format_ARGB32_Premultiplied);
auto cache = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
cache.setDevicePixelRatio(cRetinaFactor());
cache.fill(Qt::transparent);
{
Painter p(&cache);
+9 -4
View File
@@ -45,11 +45,9 @@ void TopBar::initControls() {
_mute->setClickedCallback([this] {
_call->setMute(!_call->isMute());
});
setMuted(_call->isMute());
subscribe(_call->muteChanged(), [this](bool mute) {
_mute->setIconOverride(mute ? &st::callBarUnmuteIcon : nullptr);
_mute->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr);
_hangup->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr);
_muted = mute;
setMuted(mute);
update();
});
_info->setClickedCallback([this] {
@@ -66,6 +64,13 @@ void TopBar::initControls() {
updateDurationText();
}
void TopBar::setMuted(bool mute) {
_mute->setIconOverride(mute ? &st::callBarUnmuteIcon : nullptr);
_mute->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr);
_hangup->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr);
_muted = mute;
}
void TopBar::updateDurationText() {
if (!_call) {
return;
@@ -48,6 +48,7 @@ private:
void updateDurationText();
void updateControlsGeometry();
void startDurationUpdateTimer(TimeMs currentDuration);
void setMuted(bool mute);
base::weak_unique_ptr<Call> _call;
@@ -25,9 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Platform {
namespace Notifications {
inline void CustomNotificationShownHook(QWidget *widget) {
}
inline bool SkipAudio() {
return false;
}
@@ -405,6 +405,9 @@ bool TransparentWindowsSupported(QPoint globalPosition) {
return false;
}
void InitOnTopPanel(QWidget *panel) {
}
namespace ThirdParty {
void start() {
@@ -168,16 +168,6 @@ void FlashBounce() {
[NSApp requestUserAttention:NSInformationalRequest];
}
void CustomNotificationShownHook(QWidget *widget) {
widget->hide();
objc_holdOnTop(widget->winId());
widget->show();
psShowOverAll(widget, false);
if (auto window = App::wnd()) {
window->customNotificationCreated(widget);
}
}
class Manager::Private : public QObject, private base::Subscriber {
public:
Private(Manager *manager);
@@ -20,7 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
// e is NSEvent*
bool objc_handleMediaKeyEvent(void *e);
void objc_holdOnTop(WId winId);
bool objc_darkMode();
void objc_showOverAll(WId winId, bool canFocus = true);
void objc_bringToBack(WId winId);
@@ -36,7 +36,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace {
constexpr auto kIgnoreActivationTimeoutMs = 1500;
constexpr auto kIgnoreActivationTimeoutMs = 500;
} // namespace
@@ -196,13 +196,34 @@ void SetWatchingMediaKeys(bool watching) {
}
}
} // namespace Platform
void InitOnTopPanel(QWidget *panel) {
Expects(!panel->windowHandle());
void objc_holdOnTop(WId winId) {
NSWindow *wnd = [reinterpret_cast<NSView *>(winId) window];
[wnd setHidesOnDeactivate:NO];
// Force creating windowHandle() without creating the platform window yet.
panel->setAttribute(Qt::WA_NativeWindow, true);
panel->windowHandle()->setProperty("_td_macNonactivatingPanelMask", QVariant(true));
panel->setAttribute(Qt::WA_NativeWindow, false);
panel->createWinId();
auto platformWindow = [reinterpret_cast<NSView*>(panel->winId()) window];
t_assert([platformWindow isKindOfClass:[NSPanel class]]);
auto platformPanel = static_cast<NSPanel*>(platformWindow);
[platformPanel setLevel:NSPopUpMenuWindowLevel];
[platformPanel setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces|NSWindowCollectionBehaviorStationary|NSWindowCollectionBehaviorFullScreenAuxiliary|NSWindowCollectionBehaviorIgnoresCycle];
[platformPanel setFloatingPanel:YES];
[platformPanel setHidesOnDeactivate:NO];
if (auto window = App::wnd()) {
window->customNotificationCreated(panel);
}
objc_ignoreApplicationActivationRightNow();
}
} // namespace Platform
bool objc_darkMode() {
bool result = false;
@autoreleasepool {
@@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Platform {
namespace Notifications {
void CustomNotificationShownHook(QWidget *widget);
bool SkipAudio();
bool SkipToast();
@@ -36,6 +36,8 @@ void finish();
void SetWatchingMediaKeys(bool watching);
bool TransparentWindowsSupported(QPoint globalPosition);
void InitOnTopPanel(QWidget *panel);
namespace ThirdParty {
void start();
@@ -25,9 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Platform {
namespace Notifications {
inline void CustomNotificationShownHook(QWidget *widget) {
}
class Manager : public Window::Notifications::NativeManager {
public:
Manager(Window::Notifications::System *system);
@@ -534,6 +534,9 @@ bool TransparentWindowsSupported(QPoint globalPosition) {
return true;
}
void InitOnTopPanel(QWidget *panel) {
}
namespace ThirdParty {
void start() {
@@ -199,7 +199,6 @@ void Manager::showNextFromQueue() {
queued.item,
queued.forwardedCount,
startPosition, startShift, shiftDirection);
Platform::Notifications::CustomNotificationShownHook(notification.get());
_notifications.push_back(std::move(notification));
--count;
} while (count > 0 && !_queuedNotifications.empty());
@@ -353,9 +352,11 @@ Widget::Widget(Manager *manager, QPoint startPosition, int shift, Direction shif
, _a_shift(animation(this, &Widget::step_shift)) {
setWindowOpacity(0.);
setWindowFlags(qFlags(Qt::Tool) | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint);
setAttribute(Qt::WA_OpaquePaintEvent);
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool);
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
setAttribute(Qt::WA_OpaquePaintEvent);
Platform::InitOnTopPanel(this);
_a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::notifyFastAnim);
}