From 271bbcbe951f1d51ac542e064732e35e7207bbbf Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 14 May 2021 23:34:39 +0200 Subject: [PATCH 1/9] Add macro condition "virtual desktop" (draft) --- CMakeLists.txt | 2 + data/locale/en-US.ini | 2 + src/headers/advanced-scene-switcher.hpp | 2 + src/headers/macro-condition-virt-desktop.hpp | 48 +++++++++++ src/linux/advanced-scene-switcher-nix.cpp | 64 ++++++++++++++ src/macro-condition-virt-desktop.cpp | 87 ++++++++++++++++++++ src/osx/advanced-scene-switcher-osx.mm | 10 +++ src/win/advanced-scene-switcher-win.cpp | 10 +++ 8 files changed, 225 insertions(+) create mode 100644 src/headers/macro-condition-virt-desktop.hpp create mode 100644 src/macro-condition-virt-desktop.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f80e9438f..95643471c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,7 @@ set(advanced-scene-switcher_HEADERS src/headers/macro-condition-scene.hpp src/headers/macro-condition-streaming.hpp src/headers/macro-condition-video.hpp + src/headers/macro-condition-virt-desktop.hpp src/headers/macro-condition-window.hpp src/headers/macro.hpp src/headers/curl-helper.hpp @@ -156,6 +157,7 @@ set(advanced-scene-switcher_SOURCES src/macro-condition-scene.cpp src/macro-condition-streaming.cpp src/macro-condition-video.cpp + src/macro-condition-virt-desktop.cpp src/macro-condition-window.cpp src/macro.cpp src/macro-tab.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 9524bfaae..c37179441 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -122,6 +122,8 @@ AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for {{duratio AdvSceneSwitcher.condition.pluginState="Plugin state" AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval" AdvSceneSwitcher.condition.pluginState.entry="{{condition}}" +AdvSceneSwitcher.condition.virtDesktop="Virtual desktop" +AdvSceneSwitcher.condition.virtDesktop.entry="Currently active virtual desktop is {{virtDesktops}}" ; Macro Actions AdvSceneSwitcher.action.switchScene="Switch scene" diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 737cd3b5e..217acfab1 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -284,6 +284,8 @@ void GetWindowList(QStringList &windows); void GetCurrentWindowTitle(std::string &title); bool isFullscreen(std::string &title); bool isMaximized(std::string &title); +bool GetCurrentVirtualDesktop(long &desktop); +bool GetVirtualDesktopCount(long &ndesktops); /****************************************************************************** * Screenregion helper diff --git a/src/headers/macro-condition-virt-desktop.hpp b/src/headers/macro-condition-virt-desktop.hpp new file mode 100644 index 000000000..52fdf7e2b --- /dev/null +++ b/src/headers/macro-condition-virt-desktop.hpp @@ -0,0 +1,48 @@ +#pragma once +#include "macro.hpp" +#include +#include + +class MacroConditionVirtDesktop : public MacroCondition { +public: + bool CheckCondition(); + bool Save(obs_data_t *obj); + bool Load(obs_data_t *obj); + int GetId() { return id; }; + static std::shared_ptr Create() + { + return std::make_shared(); + } + long _desktop = 0; + +private: + static bool _registered; + static const int id; +}; + +class MacroConditionVirtDesktopEdit : public QWidget { + Q_OBJECT + +public: + MacroConditionVirtDesktopEdit( + QWidget *parent, + std::shared_ptr cond = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr cond) + { + return new MacroConditionVirtDesktopEdit( + parent, + std::dynamic_pointer_cast(cond)); + } + +private slots: + void DesktopChanged(int value); + +protected: + QComboBox *_virtDesktops; + std::shared_ptr _entryData; + +private: + bool _loading = true; +}; diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 9f1c1db33..90766c187 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -393,3 +393,67 @@ int secondsSinceLastInput() return idle_time; } + +static bool GetCurrentVirtualDesktop(long &desktop) +{ + Atom type; + long unsigned nitems; + long unsigned int bytes = 0; + int format = 0; + unsigned char *data; + Window root; + Atom request; + Display *display = disp(); + + //TODO check for _NET_CURRENT_DESKTOP + if (!ewmhIsSupported()) { + return false; + } + + request = XInternAtom(display, "_NET_CURRENT_DESKTOP", False); + root = XDefaultRootWindow(display); + + int status = XGetWindowProperty(display, root, request, 0L, 1L, false, + XA_CARDINAL, &type, &format, &nitems, + &bytes, &data); + + if (status == Success && nitems > 0) { + desktop = *((long *)data); + } else { + desktop = -1; + } + free(data); + return desktop != -1; +} + +static bool GetVirtualDesktopCount(long &ndesktops) +{ + Atom type; + long unsigned nitems; + long unsigned int bytes = 0; + int format = 0; + unsigned char *data; + Window root; + Atom request; + Display *display = disp(); + + //TODO check for _NET_NUMBER_OF_DESKTOPS + if (!ewmhIsSupported()) { + return false; + } + + request = XInternAtom(display, "_NET_CURRENT_DESKTOP", False); + root = XDefaultRootWindow(display); + + int status = XGetWindowProperty(display, root, request, 0L, 1L, false, + XA_CARDINAL, &type, &format, &nitems, + &bytes, &data); + + if (status == Success && nitems > 0) { + ndesktops = *((long *)data); + } else { + ndesktops = 0; + } + free(data); + return ndesktops != 0; +} diff --git a/src/macro-condition-virt-desktop.cpp b/src/macro-condition-virt-desktop.cpp new file mode 100644 index 000000000..a7492c3a2 --- /dev/null +++ b/src/macro-condition-virt-desktop.cpp @@ -0,0 +1,87 @@ +#include "headers/macro-condition-edit.hpp" +#include "headers/macro-condition-virt-desktop.hpp" +#include "headers/utility.hpp" +#include "headers/advanced-scene-switcher.hpp" + +const int MacroConditionVirtDesktop::id = 12; + +bool MacroConditionVirtDesktop::_registered = MacroConditionFactory::Register( + MacroConditionVirtDesktop::id, + {MacroConditionVirtDesktop::Create, + MacroConditionVirtDesktopEdit::Create, + "AdvSceneSwitcher.condition.virtDesktop"}); + +bool MacroConditionVirtDesktop::CheckCondition() +{ + long curDesktop; + GetCurrentVirtualDesktop(curDesktop); + return _desktop == curDesktop; +} + +bool MacroConditionVirtDesktop::Save(obs_data_t *obj) +{ + MacroCondition::Save(obj); + obs_data_set_int(obj, "desktop", static_cast(_desktop)); + return true; +} + +bool MacroConditionVirtDesktop::Load(obs_data_t *obj) +{ + MacroCondition::Load(obj); + _desktop = obs_data_get_int(obj, "desktop"); + return true; +} + +static void populateVirtualDesktopSelection(QComboBox *list) +{ + long count; + GetVirtualDesktopCount(count); + + for (long i = 0; i < count; i++) { + list->addItem(std::to_string(i).c_str()); + } +} + +MacroConditionVirtDesktopEdit::MacroConditionVirtDesktopEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent) +{ + _virtDesktops = new QComboBox(); + + QWidget::connect(_virtDesktops, SIGNAL(currentIndexChanged(int)), this, + SLOT(DesktopChanged(int))); + + QHBoxLayout *mainLayout = new QHBoxLayout; + + std::unordered_map widgetPlaceholders = { + {"{{virtDesktops}}", _virtDesktops}, + }; + + placeWidgets( + obs_module_text("AdvSceneSwitcher.condition.virtDesktop.entry"), + mainLayout, widgetPlaceholders); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroConditionVirtDesktopEdit::DesktopChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_desktop = value; +} + +void MacroConditionVirtDesktopEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _virtDesktops->setCurrentIndex(_entryData->_desktop); +} diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index 1bb0c5788..4f9bccb05 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -247,3 +247,13 @@ bool isInFocus(const QString &executable) return (equals || matches); } + +bool GetCurrentVirtualDesktop(long &desktop) +{ + return false; +} + +bool GetVirtualDesktopCount(long &ndesktops) +{ + return false; +} diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index 02e64712b..c6f0dd345 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -285,3 +285,13 @@ int secondsSinceLastInput() { return (getTime() - getLastInputTime()) / 1000; } + +bool GetCurrentVirtualDesktop(long &desktop) +{ + return false; +} + +bool GetVirtualDesktopCount(long &ndesktops) +{ + return false; +} From 3c283a08182cece75c82381a9cb5d84afe57ec76 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 14 May 2021 23:35:57 +0200 Subject: [PATCH 2/9] Format --- src/headers/macro-condition-virt-desktop.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/headers/macro-condition-virt-desktop.hpp b/src/headers/macro-condition-virt-desktop.hpp index 52fdf7e2b..f82381f75 100644 --- a/src/headers/macro-condition-virt-desktop.hpp +++ b/src/headers/macro-condition-virt-desktop.hpp @@ -33,7 +33,8 @@ class MacroConditionVirtDesktopEdit : public QWidget { { return new MacroConditionVirtDesktopEdit( parent, - std::dynamic_pointer_cast(cond)); + std::dynamic_pointer_cast( + cond)); } private slots: From fb38f6060914f500fc556715e72dcc3a05bd4bbd Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 14 May 2021 23:55:23 +0200 Subject: [PATCH 3/9] Drop static used for testing ... --- src/linux/advanced-scene-switcher-nix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 90766c187..e93cde839 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -394,7 +394,7 @@ int secondsSinceLastInput() return idle_time; } -static bool GetCurrentVirtualDesktop(long &desktop) +bool GetCurrentVirtualDesktop(long &desktop) { Atom type; long unsigned nitems; @@ -426,7 +426,7 @@ static bool GetCurrentVirtualDesktop(long &desktop) return desktop != -1; } -static bool GetVirtualDesktopCount(long &ndesktops) +bool GetVirtualDesktopCount(long &ndesktops) { Atom type; long unsigned nitems; From 950dfe868831b53a41be96444afed222893c9585 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 15 May 2021 00:04:35 +0200 Subject: [PATCH 4/9] Request correct information to get virt desktop count --- src/linux/advanced-scene-switcher-nix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index e93cde839..ef78c9c91 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -442,7 +442,7 @@ bool GetVirtualDesktopCount(long &ndesktops) return false; } - request = XInternAtom(display, "_NET_CURRENT_DESKTOP", False); + request = XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", False); root = XDefaultRootWindow(display); int status = XGetWindowProperty(display, root, request, 0L, 1L, false, From d691492a3177b97261f62c498606e8891e2f820d Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 15 May 2021 00:04:49 +0200 Subject: [PATCH 5/9] Populate virt desktop selection --- src/macro-condition-virt-desktop.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/macro-condition-virt-desktop.cpp b/src/macro-condition-virt-desktop.cpp index a7492c3a2..6e9c01d6f 100644 --- a/src/macro-condition-virt-desktop.cpp +++ b/src/macro-condition-virt-desktop.cpp @@ -47,16 +47,14 @@ MacroConditionVirtDesktopEdit::MacroConditionVirtDesktopEdit( : QWidget(parent) { _virtDesktops = new QComboBox(); - QWidget::connect(_virtDesktops, SIGNAL(currentIndexChanged(int)), this, SLOT(DesktopChanged(int))); + populateVirtualDesktopSelection(_virtDesktops); QHBoxLayout *mainLayout = new QHBoxLayout; - std::unordered_map widgetPlaceholders = { {"{{virtDesktops}}", _virtDesktops}, }; - placeWidgets( obs_module_text("AdvSceneSwitcher.condition.virtDesktop.entry"), mainLayout, widgetPlaceholders); From e9d6067db29705363a64ba32c728f90e767540a2 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 15 May 2021 00:19:00 +0200 Subject: [PATCH 6/9] Show currently active virtual desktop --- data/locale/en-US.ini | 4 ++- src/headers/macro-condition-virt-desktop.hpp | 2 ++ src/macro-condition-virt-desktop.cpp | 34 ++++++++++++++++++-- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index c37179441..e6feb579b 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -123,7 +123,9 @@ AdvSceneSwitcher.condition.pluginState="Plugin state" AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval" AdvSceneSwitcher.condition.pluginState.entry="{{condition}}" AdvSceneSwitcher.condition.virtDesktop="Virtual desktop" -AdvSceneSwitcher.condition.virtDesktop.entry="Currently active virtual desktop is {{virtDesktops}}" +AdvSceneSwitcher.condition.virtDesktop.notAvailable="Not availbale" +AdvSceneSwitcher.condition.virtDesktop.entry.line1="Active virtual desktop is {{virtDesktops}}" +AdvSceneSwitcher.condition.virtDesktop.entry.line2="Current: {{currentDesktop}}" ; Macro Actions AdvSceneSwitcher.action.switchScene="Switch scene" diff --git a/src/headers/macro-condition-virt-desktop.hpp b/src/headers/macro-condition-virt-desktop.hpp index f82381f75..1e0192998 100644 --- a/src/headers/macro-condition-virt-desktop.hpp +++ b/src/headers/macro-condition-virt-desktop.hpp @@ -39,9 +39,11 @@ class MacroConditionVirtDesktopEdit : public QWidget { private slots: void DesktopChanged(int value); + void UpdateCurrentDesktop(); protected: QComboBox *_virtDesktops; + QLabel *_currentDesktop; std::shared_ptr _entryData; private: diff --git a/src/macro-condition-virt-desktop.cpp b/src/macro-condition-virt-desktop.cpp index 6e9c01d6f..9f02f1b5b 100644 --- a/src/macro-condition-virt-desktop.cpp +++ b/src/macro-condition-virt-desktop.cpp @@ -46,20 +46,37 @@ MacroConditionVirtDesktopEdit::MacroConditionVirtDesktopEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent) { + _currentDesktop = new QLabel(); + _currentDesktop->setTextInteractionFlags(Qt::TextSelectableByMouse); _virtDesktops = new QComboBox(); QWidget::connect(_virtDesktops, SIGNAL(currentIndexChanged(int)), this, SLOT(DesktopChanged(int))); populateVirtualDesktopSelection(_virtDesktops); - QHBoxLayout *mainLayout = new QHBoxLayout; + QVBoxLayout *mainLayout = new QVBoxLayout; + QHBoxLayout *line1Layout = new QHBoxLayout; + QHBoxLayout *line2Layout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { {"{{virtDesktops}}", _virtDesktops}, + {"{{currentDesktop}}", _currentDesktop}, }; placeWidgets( - obs_module_text("AdvSceneSwitcher.condition.virtDesktop.entry"), - mainLayout, widgetPlaceholders); + obs_module_text( + "AdvSceneSwitcher.condition.virtDesktop.entry.line1"), + line1Layout, widgetPlaceholders); + placeWidgets( + obs_module_text( + "AdvSceneSwitcher.condition.virtDesktop.entry.line2"), + line2Layout, widgetPlaceholders); + mainLayout->addLayout(line1Layout); + mainLayout->addLayout(line2Layout); setLayout(mainLayout); + // Current virtual desktop position + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(UpdateCurrentDesktop())); + timer->start(1000); + _entryData = entryData; UpdateEntryData(); _loading = false; @@ -83,3 +100,14 @@ void MacroConditionVirtDesktopEdit::UpdateEntryData() _virtDesktops->setCurrentIndex(_entryData->_desktop); } + +void MacroConditionVirtDesktopEdit::UpdateCurrentDesktop() +{ + long curDesktop; + if (GetCurrentVirtualDesktop(curDesktop)) { + _currentDesktop->setText(QString::number(curDesktop)); + } else { + _currentDesktop->setText(obs_module_text( + "AdvSceneSwitcher.condition.virtDesktop.notAvailable")); + } +} From 6c1eb3ffab01b0175b765e0fe8f51ded535ac232 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 15 May 2021 00:40:43 +0200 Subject: [PATCH 7/9] Fix random order of various macro entries --- src/headers/macro.hpp | 4 ++-- src/macro-action-audio.cpp | 2 +- src/macro-action-recording.cpp | 2 +- src/macro-action-replay-buffer.cpp | 2 +- src/macro-action-streaming.cpp | 2 +- src/macro-action-wait.cpp | 2 +- src/macro-condition-audio.cpp | 2 +- src/macro-condition-media.cpp | 25 ++++++++++++------------- src/macro-condition-plugin-state.cpp | 7 +++---- src/macro-condition-recording.cpp | 2 +- src/macro-condition-scene.cpp | 2 +- src/macro-condition-streaming.cpp | 2 +- src/macro-condition-video.cpp | 2 +- src/macro.cpp | 2 +- 14 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/headers/macro.hpp b/src/headers/macro.hpp index ebd23b3a5..bdc586e2f 100644 --- a/src/headers/macro.hpp +++ b/src/headers/macro.hpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include @@ -42,7 +42,7 @@ class MacroCondition { LogicType GetLogicType() { return _logic; } void SetLogicType(LogicType logic) { _logic = logic; } - static const std::unordered_map logicTypes; + static const std::map logicTypes; private: LogicType _logic; diff --git a/src/macro-action-audio.cpp b/src/macro-action-audio.cpp index 9d7d2b534..8614e8428 100644 --- a/src/macro-action-audio.cpp +++ b/src/macro-action-audio.cpp @@ -9,7 +9,7 @@ bool MacroActionAudio::_registered = MacroActionFactory::Register( {MacroActionAudio::Create, MacroActionAudioEdit::Create, "AdvSceneSwitcher.action.audio"}); -const static std::unordered_map actionTypes = { +const static std::map actionTypes = { {AudioAction::MUTE, "AdvSceneSwitcher.action.audio.type.mute"}, {AudioAction::UNMUTE, "AdvSceneSwitcher.action.audio.type.unmute"}, }; diff --git a/src/macro-action-recording.cpp b/src/macro-action-recording.cpp index 9aaccf6af..9c79ee8b7 100644 --- a/src/macro-action-recording.cpp +++ b/src/macro-action-recording.cpp @@ -9,7 +9,7 @@ bool MacroActionRecord::_registered = MacroActionFactory::Register( {MacroActionRecord::Create, MacroActionRecordEdit::Create, "AdvSceneSwitcher.action.recording"}); -const static std::unordered_map actionTypes = { +const static std::map actionTypes = { {RecordAction::STOP, "AdvSceneSwitcher.action.recording.type.stop"}, {RecordAction::START, "AdvSceneSwitcher.action.recording.type.start"}, {RecordAction::PAUSE, "AdvSceneSwitcher.action.recording.type.pause"}, diff --git a/src/macro-action-replay-buffer.cpp b/src/macro-action-replay-buffer.cpp index d028c90ae..942f41564 100644 --- a/src/macro-action-replay-buffer.cpp +++ b/src/macro-action-replay-buffer.cpp @@ -9,7 +9,7 @@ bool MacroActionReplayBuffer::_registered = MacroActionFactory::Register( {MacroActionReplayBuffer::Create, MacroActionReplayBufferEdit::Create, "AdvSceneSwitcher.action.replay"}); -const static std::unordered_map actionTypes = { +const static std::map actionTypes = { {ReplayBufferAction::STOP, "AdvSceneSwitcher.action.replay.type.stop"}, {ReplayBufferAction::START, "AdvSceneSwitcher.action.replay.type.start"}, diff --git a/src/macro-action-streaming.cpp b/src/macro-action-streaming.cpp index e1617ad5e..09b689def 100644 --- a/src/macro-action-streaming.cpp +++ b/src/macro-action-streaming.cpp @@ -9,7 +9,7 @@ bool MacroActionStream::_registered = MacroActionFactory::Register( {MacroActionStream::Create, MacroActionStreamEdit::Create, "AdvSceneSwitcher.action.streaming"}); -const static std::unordered_map actionTypes = { +const static std::map actionTypes = { {StreamAction::STOP, "AdvSceneSwitcher.action.streaming.type.stop"}, {StreamAction::START, "AdvSceneSwitcher.action.streaming.type.start"}, }; diff --git a/src/macro-action-wait.cpp b/src/macro-action-wait.cpp index 536cd2382..f30914d2b 100644 --- a/src/macro-action-wait.cpp +++ b/src/macro-action-wait.cpp @@ -11,7 +11,7 @@ bool MacroActionWait::_registered = MacroActionFactory::Register( {MacroActionWait::Create, MacroActionWaitEdit::Create, "AdvSceneSwitcher.action.wait"}); -static std::unordered_map waitTypes = { +static std::map waitTypes = { {WaitType::FIXED, "AdvSceneSwitcher.action.wait.type.fixed"}, {WaitType::RANDOM, "AdvSceneSwitcher.action.wait.type.random"}, }; diff --git a/src/macro-condition-audio.cpp b/src/macro-condition-audio.cpp index d1251ceba..c25f7b963 100644 --- a/src/macro-condition-audio.cpp +++ b/src/macro-condition-audio.cpp @@ -10,7 +10,7 @@ bool MacroConditionAudio::_registered = MacroConditionFactory::Register( {MacroConditionAudio::Create, MacroConditionAudioEdit::Create, "AdvSceneSwitcher.condition.audio"}); -static std::unordered_map audioConditionTypes = { +static std::map audioConditionTypes = { {AudioCondition::ABOVE, "AdvSceneSwitcher.ondition.audio.state.above"}, {AudioCondition::BELOW, "AdvSceneSwitcher.ondition.audio.state.below"}, }; diff --git a/src/macro-condition-media.cpp b/src/macro-condition-media.cpp index fbcf44e47..828718d58 100644 --- a/src/macro-condition-media.cpp +++ b/src/macro-condition-media.cpp @@ -10,21 +10,20 @@ bool MacroConditionMedia::_registered = MacroConditionFactory::Register( {MacroConditionMedia::Create, MacroConditionMediaEdit::Create, "AdvSceneSwitcher.condition.media"}); -static std::unordered_map - mediaTimeRestrictions = { - {MediaTimeRestriction::TIME_RESTRICTION_NONE, - "AdvSceneSwitcher.mediaTab.timeRestriction.none"}, - {MediaTimeRestriction::TIME_RESTRICTION_SHORTER, - "AdvSceneSwitcher.mediaTab.timeRestriction.shorter"}, - {MediaTimeRestriction::TIME_RESTRICTION_LONGER, - "AdvSceneSwitcher.mediaTab.timeRestriction.longer"}, - {MediaTimeRestriction::TIME_RESTRICTION_REMAINING_SHORTER, - "AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter"}, - {MediaTimeRestriction::TIME_RESTRICTION_REMAINING_LONGER, - "AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger"}, +static std::map mediaTimeRestrictions = { + {MediaTimeRestriction::TIME_RESTRICTION_NONE, + "AdvSceneSwitcher.mediaTab.timeRestriction.none"}, + {MediaTimeRestriction::TIME_RESTRICTION_SHORTER, + "AdvSceneSwitcher.mediaTab.timeRestriction.shorter"}, + {MediaTimeRestriction::TIME_RESTRICTION_LONGER, + "AdvSceneSwitcher.mediaTab.timeRestriction.longer"}, + {MediaTimeRestriction::TIME_RESTRICTION_REMAINING_SHORTER, + "AdvSceneSwitcher.mediaTab.timeRestriction.remainShorter"}, + {MediaTimeRestriction::TIME_RESTRICTION_REMAINING_LONGER, + "AdvSceneSwitcher.mediaTab.timeRestriction.remainLonger"}, }; -static std::unordered_map mediaStates = { +static std::map mediaStates = { {MediaState::OBS_MEDIA_STATE_NONE, "AdvSceneSwitcher.mediaTab.states.none"}, {MediaState::OBS_MEDIA_STATE_PLAYING, diff --git a/src/macro-condition-plugin-state.cpp b/src/macro-condition-plugin-state.cpp index fc660116d..ac69b8da5 100644 --- a/src/macro-condition-plugin-state.cpp +++ b/src/macro-condition-plugin-state.cpp @@ -11,10 +11,9 @@ bool MacroConditionPluginState::_registered = MacroConditionFactory::Register( MacroConditionPluginStateEdit::Create, "AdvSceneSwitcher.condition.pluginState"}); -static std::unordered_map - pluginStateConditionTypes = { - {PluginStateCondition::SCENESWITCHED, - "AdvSceneSwitcher.condition.pluginState.state.sceneSwitched"}, +static std::map pluginStateConditionTypes = { + {PluginStateCondition::SCENESWITCHED, + "AdvSceneSwitcher.condition.pluginState.state.sceneSwitched"}, }; bool MacroConditionPluginState::CheckCondition() diff --git a/src/macro-condition-recording.cpp b/src/macro-condition-recording.cpp index f18ef38ba..cd23f5ce2 100644 --- a/src/macro-condition-recording.cpp +++ b/src/macro-condition-recording.cpp @@ -10,7 +10,7 @@ bool MacroConditionRecord::_registered = MacroConditionFactory::Register( {MacroConditionRecord::Create, MacroConditionRecordEdit::Create, "AdvSceneSwitcher.condition.record"}); -static std::unordered_map recordStates = { +static std::map recordStates = { {RecordState::STOP, "AdvSceneSwitcher.condition.record.state.stop"}, {RecordState::PAUSE, "AdvSceneSwitcher.condition.record.state.pause"}, {RecordState::START, "AdvSceneSwitcher.condition.record.state.start"}, diff --git a/src/macro-condition-scene.cpp b/src/macro-condition-scene.cpp index 4e19f8faa..095bb26d9 100644 --- a/src/macro-condition-scene.cpp +++ b/src/macro-condition-scene.cpp @@ -10,7 +10,7 @@ bool MacroConditionScene::_registered = MacroConditionFactory::Register( {MacroConditionScene::Create, MacroConditionSceneEdit::Create, "AdvSceneSwitcher.condition.scene"}); -static std::unordered_map sceneTypes = { +static std::map sceneTypes = { {SceneType::CURRENT, "AdvSceneSwitcher.condition.scene.type.current"}, {SceneType::PREVIOUS, "AdvSceneSwitcher.condition.scene.type.previous"}, }; diff --git a/src/macro-condition-streaming.cpp b/src/macro-condition-streaming.cpp index e31116c26..3ccfed816 100644 --- a/src/macro-condition-streaming.cpp +++ b/src/macro-condition-streaming.cpp @@ -10,7 +10,7 @@ bool MacroConditionStream::_registered = MacroConditionFactory::Register( {MacroConditionStream::Create, MacroConditionStreamEdit::Create, "AdvSceneSwitcher.condition.stream"}); -static std::unordered_map streamStates = { +static std::map streamStates = { {StreamState::STOP, "AdvSceneSwitcher.condition.stream.state.stop"}, {StreamState::START, "AdvSceneSwitcher.condition.stream.state.start"}, }; diff --git a/src/macro-condition-video.cpp b/src/macro-condition-video.cpp index 9fa76aae9..fa4b40a65 100644 --- a/src/macro-condition-video.cpp +++ b/src/macro-condition-video.cpp @@ -15,7 +15,7 @@ bool MacroConditionVideo::_registered = MacroConditionFactory::Register( {MacroConditionVideo::Create, MacroConditionVideoEdit::Create, "AdvSceneSwitcher.condition.video"}); -static std::unordered_map conditionTypes = { +static std::map conditionTypes = { {VideoCondition::MATCH, "AdvSceneSwitcher.condition.video.condition.match"}, {VideoCondition::DIFFER, diff --git a/src/macro.cpp b/src/macro.cpp index a333f14fe..e0dda4403 100644 --- a/src/macro.cpp +++ b/src/macro.cpp @@ -4,7 +4,7 @@ #include "headers/macro-condition-edit.hpp" #include "headers/macro-action-switch-scene.hpp" -const std::unordered_map MacroCondition::logicTypes = { +const std::map MacroCondition::logicTypes = { {LogicType::NONE, {"AdvSceneSwitcher.logic.none"}}, {LogicType::AND, {"AdvSceneSwitcher.logic.and"}}, {LogicType::OR, {"AdvSceneSwitcher.logic.or"}}, From 2ac1a226e23d0cc1ee9c0e5737dfae13dc1e81ee Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 16 May 2021 14:58:43 +0200 Subject: [PATCH 8/9] Implement virtual desktop funcs for windows --- src/win/advanced-scene-switcher-win.cpp | 259 +++++++++++++++++++++++- 1 file changed, 257 insertions(+), 2 deletions(-) diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index c6f0dd345..36e7e6bfe 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -1,5 +1,7 @@ #define WIN32_LEAN_AND_MEAN #include +#include +#include #include #include #include @@ -11,6 +13,7 @@ #include #define MAX_SEARCH 1000 +#define MAXDESKTOPS 255 static bool GetWindowTitle(HWND window, std::string &title) { @@ -286,12 +289,264 @@ int secondsSinceLastInput() return (getTime() - getLastInputTime()) / 1000; } +// Virtual Desktop code +// based on https://github.com/Eun/MoveToDesktop/ +// +// TODO: +// - clean up +// - call FreeCom() on exit + +struct IApplicationView : public IUnknown { +public: +}; + +MIDL_INTERFACE("FF72FFDD-BE7E-43FC-9C03-AD81681E88E4") +IVirtualDesktop : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE IsViewVisible( + IApplicationView * pView, int *pfVisible) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetID(GUID * pGuid) = 0; +}; + +class IVirtualDesktopManagerInternal : public IUnknown { +public: + virtual HRESULT STDMETHODCALLTYPE GetCount(UINT *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE MoveViewToDesktop( + IApplicationView *pView, IVirtualDesktop *pDesktop) = 0; + + // 10240 + virtual HRESULT STDMETHODCALLTYPE CanViewMoveDesktops( + IApplicationView *pView, int *pfCanViewMoveDesktops) = 0; + + virtual HRESULT STDMETHODCALLTYPE + GetCurrentDesktop(IVirtualDesktop **desktop) = 0; + + virtual HRESULT STDMETHODCALLTYPE + GetDesktops(IObjectArray **ppDesktops) = 0; + + virtual HRESULT STDMETHODCALLTYPE + SwitchDesktop(IVirtualDesktop *pDesktop) = 0; + + virtual HRESULT STDMETHODCALLTYPE + CreateDesktopW(IVirtualDesktop **ppNewDesktop) = 0; + + // pFallbackDesktop - ??????? ???? ?? ??????? ????? ???????? ??????? ????? ???????? ?????????? + virtual HRESULT STDMETHODCALLTYPE + RemoveDesktop(IVirtualDesktop *pRemove, + IVirtualDesktop *pFallbackDesktop) = 0; + + // 10240 + virtual HRESULT STDMETHODCALLTYPE + FindDesktop(GUID *desktopId, IVirtualDesktop **ppDesktop) = 0; +}; + +IServiceProvider *pServiceProvider = nullptr; +IVirtualDesktopManager *pDesktopManager = nullptr; +IVirtualDesktopManagerInternal *pDesktopManagerInternal = nullptr; + +const CLSID CLSID_ImmersiveShell = {0xC2F03A33, 0x21F5, 0x47FA, 0xB4, + 0xBB, 0x15, 0x63, 0x62, + 0xA2, 0xF2, 0x39}; + +const CLSID CLSID_VirtualDesktopAPI_Unknown = {0xC5E0CDCA, 0x7B6E, 0x41B2, 0x9F, + 0xC4, 0xD9, 0x39, 0x75, + 0xCC, 0x46, 0x7B}; + +const IID IID_IVirtualDesktopManagerInternal = {0xEF9F1A6C, 0xD3CC, 0x4358, + 0xB7, 0x12, 0xF8, + 0x4B, 0x63, 0x5B, + 0xEB, 0xE7}; + +const IID UUID_IVirtualDesktopManagerInternal_10130{0xEF9F1A6C, 0xD3CC, 0x4358, + 0xB7, 0x12, 0xF8, + 0x4B, 0x63, 0x5B, + 0xEB, 0xE7}; +const IID UUID_IVirtualDesktopManagerInternal_10240{0xAF8DA486, 0x95BB, 0x4460, + 0xB3, 0xB7, 0x6E, + 0x7A, 0x6B, 0x29, + 0x62, 0xB5}; +const IID UUID_IVirtualDesktopManagerInternal_14393{0xf31574d6, 0xb682, 0x4cdc, + 0xbd, 0x56, 0x18, + 0x27, 0x86, 0x0a, + 0xbe, 0xc6}; + +enum EComStatus { + COMSTATUS_UNINITIALIZED, + COMSTATUS_INITIALIZED, + COMSTATUS_ERROR, +}; + +int ComStatus = COMSTATUS_UNINITIALIZED; +#define COMMAND_TIMEOUT 500 // Blocks Command below this timeout +bool bAddedMenu = false; +bool bReadIni = false; +bool bSwitchDesktopAfterMove = false; +bool bCreateNewDesktopOnMove = false; +bool bDeleteEmptyDesktops = true; +ULONGLONG nLastCommand = 0; + +UINT16 GetWinBuildNumber() +{ + UINT16 buildNumbers[] = {10130, 10240, 14393}; + OSVERSIONINFOEXW osvi = {sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0}; + ULONGLONG mask = ::VerSetConditionMask(0, VER_BUILDNUMBER, VER_EQUAL); + + for (size_t i = 0; i < sizeof(buildNumbers) / sizeof(buildNumbers[0]); + i++) { + osvi.dwBuildNumber = buildNumbers[i]; + if (VerifyVersionInfoW(&osvi, VER_BUILDNUMBER, mask) != FALSE) { + return buildNumbers[i]; + } + } + + return 0; +} + +BOOL InitCom() +{ + if (ComStatus == COMSTATUS_INITIALIZED) { + return true; + } else if (ComStatus == COMSTATUS_ERROR) { + return false; + } + + ComStatus = COMSTATUS_ERROR; + HRESULT hr = ::CoInitialize(NULL); + if (FAILED(hr)) { + return FALSE; + } + + hr = ::CoCreateInstance(CLSID_ImmersiveShell, NULL, CLSCTX_LOCAL_SERVER, + __uuidof(IServiceProvider), + (PVOID *)&pServiceProvider); + if (FAILED(hr)) { + return FALSE; + } + + hr = pServiceProvider->QueryService(__uuidof(IVirtualDesktopManager), + &pDesktopManager); + if (FAILED(hr)) { + pServiceProvider->Release(); + pServiceProvider = nullptr; + return FALSE; + } + + UINT16 buildNumber = GetWinBuildNumber(); + + switch (buildNumber) { + case 10130: + hr = pServiceProvider->QueryService( + CLSID_VirtualDesktopAPI_Unknown, + UUID_IVirtualDesktopManagerInternal_10130, + (void **)&pDesktopManagerInternal); + break; + case 10240: + hr = pServiceProvider->QueryService( + CLSID_VirtualDesktopAPI_Unknown, + UUID_IVirtualDesktopManagerInternal_10240, + (void **)&pDesktopManagerInternal); + break; + case 14393: + default: + hr = pServiceProvider->QueryService( + CLSID_VirtualDesktopAPI_Unknown, + UUID_IVirtualDesktopManagerInternal_14393, + (void **)&pDesktopManagerInternal); + break; + } + if (FAILED(hr)) { + pDesktopManager->Release(); + pDesktopManager = nullptr; + pServiceProvider->Release(); + pServiceProvider = nullptr; + return FALSE; + } + + ComStatus = COMSTATUS_INITIALIZED; + return TRUE; +} + +VOID FreeCom() +{ + if (ComStatus == COMSTATUS_INITIALIZED) { + pDesktopManager->Release(); + pDesktopManagerInternal->Release(); + pServiceProvider->Release(); + ComStatus = COMSTATUS_UNINITIALIZED; + } +} + bool GetCurrentVirtualDesktop(long &desktop) { - return false; + UINT count = 0; + IObjectArray *pObjectArray = nullptr; + IVirtualDesktop *pCurrentDesktop = nullptr; + + if (!InitCom()) { + return false; + } + + HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray); + if (FAILED(hr)) { + return false; + } + + hr = pObjectArray->GetCount(&count); + if (FAILED(hr)) { + pObjectArray->Release(); + return false; + } + + hr = pDesktopManagerInternal->GetCurrentDesktop(&pCurrentDesktop); + if (FAILED(hr)) { + pObjectArray->Release(); + return false; + } + int index = -1; + for (UINT i = 0; i < count && i < MAXDESKTOPS && index == -1; ++i) { + IVirtualDesktop *pDesktop = nullptr; + + if (FAILED(pObjectArray->GetAt(i, __uuidof(IVirtualDesktop), + (void **)&pDesktop))) + continue; + if (pDesktop == pCurrentDesktop) { + index = i; + } + pDesktop->Release(); + } + + pObjectArray->Release(); + + if (pCurrentDesktop != nullptr) { + pCurrentDesktop->Release(); + } + desktop = index; + return true; } bool GetVirtualDesktopCount(long &ndesktops) { - return false; + if (!InitCom()) { + return false; + } + IObjectArray *pObjectArray = nullptr; + HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray); + if (FAILED(hr)) { + return false; + } + + UINT count; + hr = pObjectArray->GetCount(&count); + if (FAILED(hr)) { + pObjectArray->Release(); + return false; + } + + pObjectArray->Release(); + ndesktops = count; + + return true; } From 7d381b9ba1e27bcf6bbdfd90dfb26bde0a7483ec Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 6 Jun 2021 19:23:09 +0200 Subject: [PATCH 9/9] Adjust to merge --- src/headers/macro-condition-virt-desktop.hpp | 4 ++-- src/headers/platform-funcs.hpp | 2 ++ src/macro-condition-virt-desktop.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/headers/macro-condition-virt-desktop.hpp b/src/headers/macro-condition-virt-desktop.hpp index 1e0192998..c9ceca47a 100644 --- a/src/headers/macro-condition-virt-desktop.hpp +++ b/src/headers/macro-condition-virt-desktop.hpp @@ -8,7 +8,7 @@ class MacroConditionVirtDesktop : public MacroCondition { bool CheckCondition(); bool Save(obs_data_t *obj); bool Load(obs_data_t *obj); - int GetId() { return id; }; + std::string GetId() { return id; }; static std::shared_ptr Create() { return std::make_shared(); @@ -17,7 +17,7 @@ class MacroConditionVirtDesktop : public MacroCondition { private: static bool _registered; - static const int id; + static const std::string id; }; class MacroConditionVirtDesktopEdit : public QWidget { diff --git a/src/headers/platform-funcs.hpp b/src/headers/platform-funcs.hpp index d61649013..ed621f7a7 100644 --- a/src/headers/platform-funcs.hpp +++ b/src/headers/platform-funcs.hpp @@ -9,3 +9,5 @@ std::pair getCursorPos(); int secondsSinceLastInput(); void GetProcessList(QStringList &processes); bool isInFocus(const QString &executable); +bool GetCurrentVirtualDesktop(long &desktop); +bool GetVirtualDesktopCount(long &ndesktops); diff --git a/src/macro-condition-virt-desktop.cpp b/src/macro-condition-virt-desktop.cpp index 9f02f1b5b..1c0a0d60b 100644 --- a/src/macro-condition-virt-desktop.cpp +++ b/src/macro-condition-virt-desktop.cpp @@ -3,7 +3,7 @@ #include "headers/utility.hpp" #include "headers/advanced-scene-switcher.hpp" -const int MacroConditionVirtDesktop::id = 12; +const std::string MacroConditionVirtDesktop::id = "virtual_desktop"; bool MacroConditionVirtDesktop::_registered = MacroConditionFactory::Register( MacroConditionVirtDesktop::id,