Added touchbar to media view overlay.

Fixed #7795.
This commit is contained in:
23rd 2020-07-13 17:48:54 +03:00 committed by John Preston
parent 780b5555d7
commit d9c566ac44
5 changed files with 256 additions and 0 deletions

View file

@ -907,6 +907,8 @@ PRIVATE
platform/mac/touchbar/mac_touchbar_main.mm
platform/mac/touchbar/mac_touchbar_manager.h
platform/mac/touchbar/mac_touchbar_manager.mm
platform/mac/touchbar/mac_touchbar_media_view.h
platform/mac/touchbar/mac_touchbar_media_view.mm
platform/win/audio_win.cpp
platform/win/audio_win.h
platform/win/file_utilities_win.cpp

View file

@ -62,6 +62,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_media_view.h"
#include "styles/style_history.h"
#ifdef Q_OS_MAC
#include "platform/mac/touchbar/mac_touchbar_media_view.h"
#endif // Q_OS_MAC
#include <QtWidgets/QApplication>
#include <QtWidgets/QDesktopWidget>
#include <QtCore/QBuffer>
@ -341,6 +345,15 @@ OverlayWidget::OverlayWidget()
setWindowState(Qt::WindowFullScreen);
}
#if defined Q_OS_MAC && !defined OS_OSX
TouchBar::SetupMediaViewTouchBar(
winId(),
static_cast<PlaybackControls::Delegate*>(this),
_touchbarTrackState.events(),
_touchbarDisplay.events(),
_touchbarFullscreenToggled.events());
#endif // Q_OS_MAC && !OS_OSX
Core::App().calls().currentCallValue(
) | rpl::start_with_next([=](Calls::Call *call) {
if (!_streamed) {
@ -2014,6 +2027,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
if (isHidden()) {
moveToScreen();
}
_touchbarDisplay.fire(TouchBarItemType::Photo);
clearStreaming();
destroyThemePreview();
@ -2081,6 +2095,8 @@ void OverlayWidget::displayDocument(
_themeCloudData = cloud;
_radial.stop();
_touchbarDisplay.fire(TouchBarItemType::None);
refreshMediaViewer();
if (_document) {
if (_document->sticker()) {
@ -2284,6 +2300,8 @@ void OverlayWidget::startStreamingPlayer() {
void OverlayWidget::initStreamingThumbnail() {
Expects(_document != nullptr);
_touchbarDisplay.fire(TouchBarItemType::Video);
const auto good = _documentMedia->goodThumbnail();
const auto useGood = (good != nullptr);
const auto thumbnail = _documentMedia->thumbnail();
@ -2730,6 +2748,7 @@ void OverlayWidget::playbackToggleFullScreen() {
}
_streamed->controls.setInFullScreen(_fullScreenVideo);
_touchbarFullscreenToggled.fire_copy(_fullScreenVideo);
updateControls();
update();
}
@ -2776,6 +2795,7 @@ void OverlayWidget::updatePlaybackState() {
const auto state = _streamed->instance.player().prepareLegacyState();
if (state.position != kTimeUnknown && state.length != kTimeUnknown) {
_streamed->controls.updatePlayback(state);
_touchbarTrackState.fire_copy(state);
}
}

View file

@ -71,6 +71,12 @@ class OverlayWidget final
public:
OverlayWidget();
enum class TouchBarItemType {
Photo,
Video,
None,
};
void showPhoto(not_null<PhotoData*> photo, HistoryItem *context);
void showPhoto(not_null<PhotoData*> photo, not_null<PeerData*> context);
void showDocument(
@ -496,6 +502,10 @@ private:
base::flat_map<OverState, crl::time> _animations;
base::flat_map<OverState, anim::value> _animationOpacities;
rpl::event_stream<Media::Player::TrackState> _touchbarTrackState;
rpl::event_stream<TouchBarItemType> _touchbarDisplay;
rpl::event_stream<bool> _touchbarFullscreenToggled;
int _verticalWheelDelta = 0;
bool _themePreviewShown = false;

View file

@ -0,0 +1,26 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#ifndef OS_OSX
#include "media/view/media_view_playback_controls.h"
#include "media/view/media_view_overlay_widget.h"
namespace TouchBar {
void SetupMediaViewTouchBar(
WId winId,
not_null<Media::View::PlaybackControls::Delegate*> controlsDelegate,
rpl::producer<Media::Player::TrackState> trackState,
rpl::producer<Media::View::OverlayWidget::TouchBarItemType> display,
rpl::producer<bool> fullscreenToggled);
} // namespace TouchBar
#endif // OS_OSX

View file

@ -0,0 +1,198 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/mac/touchbar/mac_touchbar_media_view.h"
#ifndef OS_OSX
#include "media/audio/media_audio.h"
#include "platform/mac/touchbar/mac_touchbar_common.h"
#include "platform/mac/touchbar/mac_touchbar_controls.h"
#include "styles/style_media_player.h"
#include "styles/style_media_view.h"
#import <AppKit/NSButton.h>
#import <AppKit/NSCustomTouchBarItem.h>
#import <AppKit/NSTouchBar.h>
using namespace TouchBar;
using Delegate = Media::View::PlaybackControls::Delegate;
using ItemType = Media::View::OverlayWidget::TouchBarItemType;
namespace {
inline NSTouchBarItemIdentifier Format(NSString *s) {
return [NSString stringWithFormat:@"button.%@", s];
}
const auto kPlayItemIdentifier = Format(@"playPause");
const auto kRotateItemIdentifier = Format(@"rotate");
const auto kFullscreenItemIdentifier = Format(@"fullscreen");
const auto kPipItemIdentifier = Format(@"pip");
const auto kTrackItemIdentifier = @"trackPosition";
const auto kSeekItemIdentifier = @"seekBar";
}
#pragma mark - MediaViewTouchBar
@interface MediaViewTouchBar : NSTouchBar
- (id)init:(not_null<Delegate*>)controlsDelegate
trackState:(rpl::producer<Media::Player::TrackState>)trackState
display:(rpl::producer<ItemType>)display
fullscreenToggled:(rpl::producer<bool>)fullscreenToggled;
@end
@implementation MediaViewTouchBar {
rpl::lifetime _lifetime;
}
- (id)init:(not_null<Delegate*>)controlsDelegate
trackState:(rpl::producer<Media::Player::TrackState>)trackState
display:(rpl::producer<ItemType>)display
fullscreenToggled:(rpl::producer<bool>)fullscreenToggled {
self = [super init];
if (!self) {
return self;
}
const auto allocate = [](NSTouchBarItemIdentifier i) {
return [[NSCustomTouchBarItem alloc] initWithIdentifier:i];
};
auto *playPause = allocate(kPlayItemIdentifier);
{
auto *button = CreateTouchBarButtonWithTwoStates(
st::touchBarIconPlayerPause,
st::touchBarIconPlayerPlay,
_lifetime,
[=](bool value) {
value
? controlsDelegate->playbackControlsPlay()
: controlsDelegate->playbackControlsPause();
},
false,
rpl::duplicate(
trackState
) | rpl::map([](const auto &state) {
return (state.state == Media::Player::State::Playing);
}) | rpl::distinct_until_changed());
playPause.view = button;
playPause.customizationLabel = @"Play/Pause";
}
auto *rotate = allocate(kRotateItemIdentifier);
{
auto *button = CreateTouchBarButton(
[NSImage imageNamed:NSImageNameTouchBarRotateLeftTemplate],
_lifetime,
[=] { controlsDelegate->playbackControlsRotate(); });
rotate.view = button;
rotate.customizationLabel = @"Rotate";
}
auto *fullscreen = allocate(kFullscreenItemIdentifier);
{
auto *button = CreateTouchBarButtonWithTwoStates(
[NSImage imageNamed:NSImageNameTouchBarExitFullScreenTemplate],
[NSImage imageNamed:NSImageNameTouchBarEnterFullScreenTemplate],
_lifetime,
[=](bool value) {
value
? controlsDelegate->playbackControlsFromFullScreen()
: controlsDelegate->playbackControlsToFullScreen();
},
true,
std::move(fullscreenToggled));
fullscreen.view = button;
fullscreen.customizationLabel = @"Fullscreen";
}
auto *pip = allocate(kPipItemIdentifier);
{
auto *button = TouchBar::CreateTouchBarButton(
CreateNSImageFromStyleIcon(
st::mediaviewPipButton.icon,
kCircleDiameter / 4 * 3),
_lifetime,
[=] { controlsDelegate->playbackControlsToPictureInPicture(); });
pip.view = button;
pip.customizationLabel = @"Picture-in-Picture";
}
auto *trackPosition = CreateTouchBarTrackPosition(
kTrackItemIdentifier,
rpl::duplicate(trackState));
auto *seekBar = TouchBar::CreateTouchBarSlider(
kSeekItemIdentifier,
_lifetime,
[=](bool touchUp, double value, double duration) {
const auto progress = value * duration;
touchUp
? controlsDelegate->playbackControlsSeekFinished(progress)
: controlsDelegate->playbackControlsSeekProgress(progress);
},
std::move(trackState));
self.templateItems = [NSSet setWithArray:@[
playPause,
rotate,
fullscreen,
pip,
seekBar,
trackPosition]];
const auto items = [](ItemType type) {
switch (type) {
case ItemType::Photo: return @[kRotateItemIdentifier];
case ItemType::Video: return @[
kRotateItemIdentifier,
kFullscreenItemIdentifier,
kPipItemIdentifier,
kPlayItemIdentifier,
kSeekItemIdentifier,
kTrackItemIdentifier];
default: return @[];
};
};
std::move(
display
) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](ItemType type) {
TouchBar::CustomEnterToCocoaEventLoop([=] {
self.defaultItemIdentifiers = items(type);
});
}, _lifetime);
return self;
}
@end // @implementation MediaViewTouchBar
namespace TouchBar {
void SetupMediaViewTouchBar(
WId winId,
not_null<Delegate*> controlsDelegate,
rpl::producer<Media::Player::TrackState> trackState,
rpl::producer<ItemType> display,
rpl::producer<bool> fullscreenToggled) {
auto *window = [reinterpret_cast<NSView*>(winId) window];
CustomEnterToCocoaEventLoop([=] {
[window setTouchBar:[[[MediaViewTouchBar alloc]
init:std::move(controlsDelegate)
trackState:std::move(trackState)
display:std::move(display)
fullscreenToggled:std::move(fullscreenToggled)
] autorelease]];
});
}
} // namespace TouchBar
#endif // OS_OSX