mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
Screen sharing : Display a preview when a Window has been selected.
This commit is contained in:
parent
ae686db48c
commit
d7a5f3898b
15 changed files with 176 additions and 18 deletions
|
|
@ -833,9 +833,12 @@ endif()
|
|||
target_link_libraries(${TARGET_NAME} ${APP_PLUGIN})
|
||||
|
||||
|
||||
if(WIN32 AND ENABLE_LDAP)
|
||||
find_package(OpenLDAP REQUIRED)
|
||||
target_link_libraries(${TARGET_NAME} wsock32 ws2_32 ${OPENLDAP_LIBRARIES})
|
||||
if(WIN32)
|
||||
if(ENABLE_LDAP)
|
||||
find_package(OpenLDAP REQUIRED)
|
||||
target_link_libraries(${TARGET_NAME} wsock32 ws2_32 ${OPENLDAP_LIBRARIES})
|
||||
endif()
|
||||
target_link_libraries(${TARGET_NAME} Dwmapi)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
|
|
|
|||
|
|
@ -495,6 +495,7 @@ void App::initContentApp () {
|
|||
mEngine->addImageProvider(QRCodeProvider::ProviderId, new QRCodeProvider());
|
||||
mEngine->addImageProvider(ThumbnailProvider::ProviderId, new ThumbnailProvider());
|
||||
mEngine->addImageProvider(ScreenProvider::ProviderId, new ScreenProvider());
|
||||
mEngine->addImageProvider(WindowProvider::ProviderId, new WindowProvider());
|
||||
|
||||
mEngine->rootContext()->setContextProperty("applicationName", APPLICATION_NAME);
|
||||
mEngine->rootContext()->setContextProperty("executableName", EXECUTABLE_NAME);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
#include "ScreenProvider.hpp"
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
#include <QThread>
|
||||
#include <QWindow>
|
||||
#include "components/other/desktop-tools/DesktopTools.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -31,13 +34,73 @@ ScreenProvider::ScreenProvider () : QQuickImageProvider(
|
|||
QQmlImageProviderBase::ForceAsynchronousImageLoading
|
||||
) {}
|
||||
|
||||
QImage ScreenProvider::requestImage (const QString &id, QSize *size, const QSize &) {
|
||||
int index = id.toInt();
|
||||
auto screens = QGuiApplication::screens();
|
||||
if(index >= 0 && index < screens.size()){
|
||||
auto image = screens[index]->grabWindow(0);
|
||||
*size = image.size();
|
||||
return image.toImage();
|
||||
}else
|
||||
return QImage();
|
||||
QImage ScreenProvider::requestImage (const QString &id, QSize *size, const QSize &requestedSize) {
|
||||
if(!requestedSize.isNull()) {
|
||||
int index = id.toInt();
|
||||
auto screens = QGuiApplication::screens();
|
||||
if(index >= 0 && index < screens.size()){
|
||||
auto screen = screens[index];
|
||||
auto geometry = screen->geometry();
|
||||
#if __APPLE__
|
||||
auto image = screen->grabWindow(0, geometry.x(), geometry.y() ,geometry.width(), geometry.height()).scaled(requestedSize, Qt::KeepAspectRatio,Qt::SmoothTransformation);
|
||||
#else
|
||||
auto image = screen->grabWindow(0, 0, 0,geometry.width(), geometry.height()).scaled(requestedSize, Qt::KeepAspectRatio,Qt::SmoothTransformation);
|
||||
#endif
|
||||
*size = image.size();
|
||||
qDebug() << "Screen(" << index << ") = " << screen->geometry() << " VG:" << screen->virtualGeometry() << " / " << screen->size() << " VS:" << screen->virtualSize() << " DeviceRatio: " << screen->devicePixelRatio();
|
||||
return image.toImage();
|
||||
}
|
||||
}
|
||||
QImage image(10,10, QImage::Format_Indexed8);
|
||||
image.fill(Qt::gray);
|
||||
*size = image.size();
|
||||
return image;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
const QString WindowProvider::ProviderId = "window";
|
||||
|
||||
WindowProvider::WindowProvider () : QQuickImageProvider(
|
||||
QQmlImageProviderBase::Image,
|
||||
QQmlImageProviderBase::ForceAsynchronousImageLoading
|
||||
) {}
|
||||
|
||||
// Note: Using WId don't work with Window/Mac (For Mac, NSView cannot be used while we are working with CGWindowID)
|
||||
// Linux seems to be ok but we want to use the same code.
|
||||
QImage WindowProvider::requestImage (const QString &id, QSize *size, const QSize &requestedSize) {
|
||||
if(!requestedSize.isNull()) {
|
||||
auto winId = id.toLongLong();
|
||||
if(winId > 0){
|
||||
QRect area = DesktopTools::getWindowGeometry(reinterpret_cast<void*>(winId));
|
||||
if(!area.isNull()) {
|
||||
qDebug() << "Window (" << winId << ") = " << area;
|
||||
auto screens = QGuiApplication::screens();
|
||||
for(auto screen : screens){
|
||||
auto geometry = screen->geometry();
|
||||
auto devicePixelRatio = screen->devicePixelRatio();
|
||||
// Warning: there are inconsistencies in geomtries from OS.
|
||||
#if defined(__APPLE__)
|
||||
devicePixelRatio = 1.0;// Doesn't apply device ratio.
|
||||
// Change area to be absolute
|
||||
area.setRect(area.x() + geometry.x(), area.y() + geometry.y(), area.width(), area.height());
|
||||
#endif
|
||||
geometry.setWidth(geometry.width() * devicePixelRatio);
|
||||
geometry.setHeight(geometry.height() * devicePixelRatio);
|
||||
if( geometry.contains(area.center())){
|
||||
QThread::msleep(40);// Let OS some time to display properly the Window after a click.
|
||||
qDebug() << "Grab (" << (area.x() - geometry.x())/devicePixelRatio<< ", " << (area.y() - geometry.y())/devicePixelRatio << ", " << area.width()/devicePixelRatio << ", " << area.height()/devicePixelRatio << ")";
|
||||
auto image = screen->grabWindow(0, (area.x() - geometry.x())/devicePixelRatio, (area.y() - geometry.y())/devicePixelRatio, area.width()/devicePixelRatio, area.height()/devicePixelRatio).scaled(requestedSize, Qt::KeepAspectRatio,Qt::SmoothTransformation);
|
||||
*size = image.size();
|
||||
return image.toImage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
QImage image(10,10, QImage::Format_Indexed8);
|
||||
image.fill(Qt::gray);
|
||||
*size = image.size();
|
||||
return image;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,4 +34,13 @@ public:
|
|||
static const QString ProviderId;
|
||||
};
|
||||
|
||||
class WindowProvider : public QQuickImageProvider {
|
||||
public:
|
||||
WindowProvider ();
|
||||
|
||||
QImage requestImage (const QString &id, QSize *size, const QSize &requestedSize) override;
|
||||
|
||||
static const QString ProviderId;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -120,3 +120,17 @@ void DesktopTools::getWindowIdFromMouse(VideoSourceDescriptorModel *model) {
|
|||
uintptr_t DesktopTools::getDisplayIndex(void* screenSharing){
|
||||
return *(uintptr_t*)(&screenSharing);
|
||||
}
|
||||
|
||||
QRect DesktopTools::getWindowGeometry(void* screenSharing) {
|
||||
const char *displayStr = getenv("DISPLAY");
|
||||
if (displayStr == NULL) displayStr = ":0";
|
||||
Display *display = XOpenDisplay(displayStr);
|
||||
if (display == NULL) {
|
||||
qCritical() << "Can't open X display!";
|
||||
return QRect();
|
||||
}
|
||||
Window windowId = (Window)screenSharing;
|
||||
XWindowAttributes attributes;
|
||||
XGetWindowAttributes(display, windowId, &attributes);
|
||||
return QRect(attributes.x, attributes.y, attributes.width, attributes.height);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ public:
|
|||
Q_INVOKABLE void getWindowIdFromMouse(VideoSourceDescriptorModel *model);
|
||||
static void *getDisplay(uintptr_t screenIndex){return reinterpret_cast<void*>(screenIndex);}
|
||||
static uintptr_t getDisplayIndex(void* screenSharing);
|
||||
static QRect getWindowGeometry(void* screenSharing);
|
||||
|
||||
signals:
|
||||
void screenSaverStatusChanged(bool status);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public:
|
|||
static void *getDisplay(int screenIndex);
|
||||
static int getDisplayIndex(void *screenSharing);
|
||||
Q_INVOKABLE void getWindowIdFromMouse(VideoSourceDescriptorModel *model);
|
||||
static QRect getWindowGeometry(void* screenSharing);
|
||||
|
||||
signals:
|
||||
void screenSaverStatusChanged(bool status);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <ScreenCaptureKit/ScreenCaptureKit.h>
|
||||
#include <QDebug>
|
||||
#include <QRect>
|
||||
#include <QThread>
|
||||
#include "components/videoSource/VideoSourceDescriptorModel.hpp"
|
||||
|
||||
|
|
@ -69,3 +70,25 @@ void DesktopTools::getWindowIdFromMouse(VideoSourceDescriptorModel *model) {
|
|||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
QRect DesktopTools::getWindowGeometry(void* screenSharing) {
|
||||
QRect result;
|
||||
CGWindowID windowId = *(CGWindowID*)&screenSharing;
|
||||
CFArrayRef descriptions = CGWindowListCopyWindowInfo(kCGWindowListOptionIncludingWindow, windowId);
|
||||
if(CFArrayGetCount(descriptions) > 0) {
|
||||
CFDictionaryRef description = (CFDictionaryRef)CFArrayGetValueAtIndex ((CFArrayRef)descriptions, 0);
|
||||
if(CFDictionaryContainsKey(description, kCGWindowBounds)) {
|
||||
CFDictionaryRef bounds = (CFDictionaryRef)CFDictionaryGetValue (description, kCGWindowBounds);
|
||||
if(bounds) {
|
||||
CGRect windowRect;
|
||||
CGRectMakeWithDictionaryRepresentation(bounds, &windowRect);
|
||||
result = QRect(windowRect.origin.x, windowRect.origin.y, windowRect.size.width, windowRect.size.height);
|
||||
}else
|
||||
qWarning() << "Bounds found be cannot be parsed for Window ID : " << windowId;
|
||||
}else
|
||||
qWarning() << "No bounds specified in Apple description for Window ID : " << windowId;
|
||||
}else
|
||||
qWarning() << "No description found for Window ID : " << windowId;
|
||||
CFRelease(descriptions);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <QDebug>
|
||||
#include <Windows.h>
|
||||
#include <dwmapi.h>
|
||||
// =============================================================================
|
||||
|
||||
DesktopTools::DesktopTools(QObject *parent) : QObject(parent) {
|
||||
|
|
@ -79,3 +80,14 @@ void DesktopTools::getWindowIdFromMouse(VideoSourceDescriptorModel *model) {
|
|||
uintptr_t DesktopTools::getDisplayIndex(void* screenSharing) {
|
||||
return *(uintptr_t*)(&screenSharing);
|
||||
}
|
||||
|
||||
QRect DesktopTools::getWindowGeometry(void* screenSharing) {
|
||||
QRect result;
|
||||
HWND windowId = *(HWND*)&screenSharing;
|
||||
RECT area;
|
||||
if (S_OK == DwmGetWindowAttribute(windowId, DWMWA_EXTENDED_FRAME_BOUNDS, &area, sizeof(RECT))) {
|
||||
result = QRect(area.left + 1, area.top, area.right - area.left, area.bottom - area.top);// +1 for border
|
||||
}else
|
||||
qWarning() << "Cannot get attributes from HWND: " << windowId;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public:
|
|||
return reinterpret_cast<void *>(screenIndex);
|
||||
}
|
||||
static uintptr_t getDisplayIndex(void *screenSharing);
|
||||
static QRect getWindowGeometry(void* screenSharing);
|
||||
HWND mWindowId = 0; // Window
|
||||
VideoSourceDescriptorModel *mVideoSourceDescriptorModel = nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,14 @@ void * VideoSourceDescriptorModel::getScreenSharing() const{
|
|||
return mDesc->getScreenSharing();
|
||||
}
|
||||
|
||||
quint64 VideoSourceDescriptorModel::getWindowId() const{
|
||||
if(!mDesc) return 0;
|
||||
else{
|
||||
void * temp = mDesc->getScreenSharing();
|
||||
return *(quint64*)&temp;
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoSourceDescriptorModel::isScreenSharing() const{
|
||||
return mDesc && mDesc->getType() == linphone::VideoSourceType::ScreenSharing;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,12 +36,14 @@ class VideoSourceDescriptorModel : public QObject{
|
|||
Q_PROPERTY(bool isScreenSharing READ isScreenSharing NOTIFY videoDescriptorChanged)
|
||||
Q_PROPERTY(LinphoneEnums::VideoSourceScreenSharingType screenSharingType READ getVideoSourceType NOTIFY videoDescriptorChanged)
|
||||
Q_PROPERTY(int screenSharingIndex READ getScreenSharingIndex WRITE setScreenSharingDisplay NOTIFY videoDescriptorChanged)
|
||||
Q_PROPERTY(quint64 windowId READ getWindowId NOTIFY videoDescriptorChanged)
|
||||
public:
|
||||
VideoSourceDescriptorModel();
|
||||
VideoSourceDescriptorModel(std::shared_ptr<linphone::VideoSourceDescriptor> desc);
|
||||
void setScreenSharingDisplay(int index);
|
||||
void setScreenSharingWindow(void *window); // Get data from DesktopTools.
|
||||
void *getScreenSharing() const;
|
||||
quint64 getWindowId() const;
|
||||
|
||||
bool isScreenSharing() const;
|
||||
LinphoneEnums::VideoSourceScreenSharingType getVideoSourceType() const;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ Item {
|
|||
property color foregroundColor: '#00000000'
|
||||
readonly property alias status: image.status
|
||||
property int radius: width/2
|
||||
property alias cache: image.cache
|
||||
|
||||
Rectangle {
|
||||
id: backgroundArea
|
||||
|
|
|
|||
|
|
@ -377,6 +377,7 @@ Rectangle{
|
|||
backgroundColor: 'white'
|
||||
source: 'image://screen/'+index
|
||||
radius: 10
|
||||
cache: false
|
||||
}
|
||||
Text{
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -421,6 +422,18 @@ Rectangle{
|
|||
mainItem.callModel.setVideoSourceDescriptorModel(screenSharingItem.desc)
|
||||
}
|
||||
}
|
||||
|
||||
RoundedImage{
|
||||
visible: windowSharingRadioButton.checked
|
||||
Layout.leftMargin: 15
|
||||
Layout.preferredWidth: 114
|
||||
Layout.preferredHeight: 64
|
||||
backgroundColor: 'white'
|
||||
source: windowSharingRadioButton.checked ? 'image://window/'+screenSharingItem.desc.windowId : ''
|
||||
radius: 10
|
||||
cache: false
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: IncallMenuStyle.list.border.width
|
||||
|
|
|
|||
|
|
@ -675,12 +675,18 @@ Rectangle {
|
|||
}
|
||||
Connections{
|
||||
target: DesktopTools
|
||||
onWindowIdSelectionStarted: window.attachVirtualWindow(Utils.buildCommonDialogUri('ConfirmDialog'), {
|
||||
descriptionText: "Click on the window that you want to share."
|
||||
, showButtonOnly: 42
|
||||
, buttonTexts : ['']
|
||||
})
|
||||
onWindowIdSelectionEnded: window.detachVirtualWindow()
|
||||
onWindowIdSelectionStarted: {
|
||||
mainItem.enabled = false
|
||||
window.attachVirtualWindow(Utils.buildCommonDialogUri('ConfirmDialog'), {
|
||||
descriptionText: "Click on the window that you want to share."
|
||||
, showButtonOnly: 42
|
||||
, buttonTexts : ['']
|
||||
})
|
||||
}
|
||||
onWindowIdSelectionEnded: {
|
||||
window.detachVirtualWindow()
|
||||
mainItem.enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue