From b45b38cf6af082a48de7225eb9c54cba24144097 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 14 May 2020 18:49:35 -0400 Subject: [PATCH 01/47] Add ability to use regex for executable switching Previously, only exact matches to a window title would switch scenes --- src/executable-switch.cpp | 2 +- src/linux/advanced-scene-switcher-nix.cpp | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 009a41d4..cf9a4218 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -129,7 +129,7 @@ void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSour GetProcessList(runningProcesses); for (ExecutableSceneSwitch& s : executableSwitches) { - if (runningProcesses.contains(s.mExe)) + if (runningProcesses.indexOf(QRegularExpression(s.mExe)) != -1) { scene = s.mScene; transition = s.mTransition; diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 66961225..420b7fbd 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -295,10 +295,7 @@ bool isInFocus(const QString &exeToCheck) string curWindow; GetCurrentWindowTitle(curWindow); - return (QString::compare( - QString::fromStdString(curWindow), - exeToCheck, - Qt::CaseInsensitive) == 0) ? true : false; + return QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); } From 3654f392475674addf4d1e61faa663dc5225998f Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 14 May 2020 18:51:44 -0400 Subject: [PATCH 02/47] Fix scene not switching with multiple executables --- src/executable-switch.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index cf9a4218..21f21846 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -134,7 +134,9 @@ void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSour scene = s.mScene; transition = s.mTransition; match = !s.mInFocus || (s.mInFocus && isInFocus(s.mExe)); - break; + + if (match) + break; } } } From 26c24d4d530d160fb45ad86edc99ef9c3e2b32cc Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 14 May 2020 18:52:45 -0400 Subject: [PATCH 03/47] Change executable entry box to be editable --- forms/advanced-scene-switcher.ui | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 1564578c..14eae67a 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -1127,7 +1127,14 @@ - + + + true + + + 20 + + From e9b1ef58bacc2a6cb80ea43b2271db9f1be5e2b3 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 14 May 2020 18:54:17 -0400 Subject: [PATCH 04/47] Change executable list to disable sorting This allows the UI to show the order in which the executables will be checked --- forms/advanced-scene-switcher.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 14eae67a..9ea4c17b 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -1180,7 +1180,7 @@ true - true + false From 318502d8d03227dead4b114cbab7ef740f0d15b2 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 14 May 2020 19:10:23 -0400 Subject: [PATCH 05/47] Move forms/advanced-scene-switcher.ui to src/headers/ Out-of-tree building (at least) fails without this file in this location, and builds successfully without it under forms --- {forms => src/headers}/advanced-scene-switcher.ui | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {forms => src/headers}/advanced-scene-switcher.ui (100%) diff --git a/forms/advanced-scene-switcher.ui b/src/headers/advanced-scene-switcher.ui similarity index 100% rename from forms/advanced-scene-switcher.ui rename to src/headers/advanced-scene-switcher.ui From 451bb6518c1f24c823f4d2d3ed5fe0608c1c60a4 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 14 May 2020 19:10:23 -0400 Subject: [PATCH 06/47] Revert "Move forms/advanced-scene-switcher.ui to src/headers/" This reverts commit 318502d8d03227dead4b114cbab7ef740f0d15b2. --- {src/headers => forms}/advanced-scene-switcher.ui | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {src/headers => forms}/advanced-scene-switcher.ui (100%) diff --git a/src/headers/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui similarity index 100% rename from src/headers/advanced-scene-switcher.ui rename to forms/advanced-scene-switcher.ui From 5f87a61177169adb8c840b02c8eeb83528ef3d2b Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 17 May 2020 00:18:28 -0400 Subject: [PATCH 07/47] Remove direct match from window switcher and reorganize Direct matching before regex has the potential to interfere with some usecases. For example, if a user wants to enter regex syntax such as `shell[1]`, a direct match would return a window matching `shell[1]` exactly instead of `shell1`. Granted, the odds of the two conflicting each other are slim, but the core logic shouldn't prevent a user from utilizing regex to its full potential. One can always escape reserved characters if they want to match it directly. I have also added a warning and link to https://regexr.com in the UI should this be accepted. The rest of what has changed is simply to align with the executable switcher's matching, namely the use of `QRegularExpression` to drop the need for a try/catch block and moving the check for fullscreen to the if statement in order to remove the possibility of a race condition. --- forms/advanced-scene-switcher.ui | 33 ++++++++++++++++++++++ src/window-title-switch.cpp | 48 ++++++++++---------------------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 9ea4c17b..b8982ec8 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -364,6 +364,39 @@ Window Title + + + + + + https://regexr.com + + + <html><head/><body><p>WARNING! Entries require valid RegEx to function, otherwise they will silently fail. You can check syntax and matches using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> + + + Qt::AutoText + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index ce24f448..899baca5 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -228,53 +228,35 @@ void SceneSwitcher::on_ignoreWindows_currentRowChanged(int idx) void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) { - //check if title should be ignored string title; + + // Check if current window is ignored GetCurrentWindowTitle(title); for (auto& window : ignoreWindowsSwitches) { - try - { - bool matches = regex_match(title, regex(window)); - if (matches) - { - title = lastTitle; - break; - } - } - catch (const regex_error&) + // True if ignored switch matches title + bool matches = QString::fromStdString(title).contains(QRegularExpression(window.c_str())); + if (matches) { + title = lastTitle; + break; } } lastTitle = title; - //direct match + // Check for regex match for (WindowSceneSwitch& s : windowSwitches) { - if (s.window == title) + // True if window switch matches title + bool matches = QString::fromStdString(title).contains(QRegularExpression(s.window.c_str())); + // True if fullscreen is disabled OR window is fullscreen + bool fullscreen = (!s.fullscreen || isFullscreen()); + if (matches && fullscreen) { - match = !s.fullscreen || (s.fullscreen && isFullscreen()); + match = true; scene = s.scene; transition = s.transition; - return; + break; } } - //regex match - for (WindowSceneSwitch& s : windowSwitches) - { - try - { - bool matches = regex_match(title, regex(s.window)); - if (matches) - { - match = !s.fullscreen || (s.fullscreen && isFullscreen()); - scene = s.scene; - transition = s.transition; - } - } - catch (const regex_error&) - { - } - } - } From a2543f1b85a9a2d0c0a0df04f87be69b22851c36 Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 17 May 2020 00:24:24 -0400 Subject: [PATCH 08/47] Add ability to use existing window ignore for executable switching Also cleaned up some logic --- src/executable-switch.cpp | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 21f21846..47ad2b49 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -125,18 +125,41 @@ void SceneSwitcher::on_executableRemove_clicked() void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) { + string title; QStringList runningProcesses; + bool ignored = false; + + // Check if current window is ignored + GetCurrentWindowTitle(title); + for (auto& window : ignoreWindowsSwitches) + { + // True if ignored switch matches title + bool matches = QString::fromStdString(title).contains(QRegularExpression(window.c_str())); + if (matches) + { + ignored = true; + title = lastTitle; + break; + } + } + lastTitle = title; + + // Check for regex match GetProcessList(runningProcesses); for (ExecutableSceneSwitch& s : executableSwitches) { - if (runningProcesses.indexOf(QRegularExpression(s.mExe)) != -1) + // True if executable switch is running + bool running = (runningProcesses.indexOf(QRegularExpression(s.mExe)) != -1); + // True if focus is disabled OR window in focus + bool focus = (!s.mInFocus || isInFocus(s.mExe)); + // True if current window is ignored AND executable switch matches last window + bool ignore = (ignored && QString::fromStdString(title).contains(QRegularExpression(s.mExe))); + if (running && (focus || ignore)) { + match = true; scene = s.mScene; transition = s.mTransition; - match = !s.mInFocus || (s.mInFocus && isInFocus(s.mExe)); - - if (match) - break; + break; } } } From f0aa76517ae03c9cb463090c268eb23353ccfe7b Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 17 May 2020 00:27:01 -0400 Subject: [PATCH 09/47] Change executable switcher warning to regex requirement Also change wording to align with Window Title, and fix an inconsequential error --- forms/advanced-scene-switcher.ui | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index b8982ec8..3cfd4824 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -1137,8 +1137,17 @@ + + https://regexr.com + - WARNING! Only add game exes to this list and never run more than one game that is listed here at the same time, otherwise you riskbad behaviour. You have been warned. + <html><head/><body><p>WARNING! Entries require valid RegEx to function, otherwise they will silently fail. You can check syntax and matches using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> + + + Qt::AutoText + + + true @@ -1185,7 +1194,7 @@ - needs to be in focus + only if window is in focus 100 @@ -2456,7 +2465,7 @@ ms - 00 + 0 1000000 From d5052c94ca53ea766b77b09d2d710cdce0ec3658 Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 17 May 2020 13:42:50 -0400 Subject: [PATCH 10/47] Add direct matching to window, executable, and ignored switches Reverts part of commit 5f87a61177169adb8c840b02c8eeb83528ef3d2b Direct matching occurs in the same loop as regex in order to allow the list order to function as indicated in the UI --- src/executable-switch.cpp | 18 +++++++++++++----- src/linux/advanced-scene-switcher-nix.cpp | 7 ++++++- src/window-title-switch.cpp | 14 +++++++++++--- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 47ad2b49..0f770357 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -133,32 +133,40 @@ void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSour GetCurrentWindowTitle(title); for (auto& window : ignoreWindowsSwitches) { + // True if ignored switch equals title + bool equals = (title == window); // True if ignored switch matches title bool matches = QString::fromStdString(title).contains(QRegularExpression(window.c_str())); - if (matches) + + if (equals || matches) { ignored = true; title = lastTitle; + break; } } lastTitle = title; - // Check for regex match + // Check for match GetProcessList(runningProcesses); for (ExecutableSceneSwitch& s : executableSwitches) { - // True if executable switch is running - bool running = (runningProcesses.indexOf(QRegularExpression(s.mExe)) != -1); + // True if executable switch is running (direct) + bool equals = runningProcesses.contains(s.mExe); + // True if executable switch is running (regex) + bool matches = (runningProcesses.indexOf(QRegularExpression(s.mExe)) != -1); // True if focus is disabled OR window in focus bool focus = (!s.mInFocus || isInFocus(s.mExe)); // True if current window is ignored AND executable switch matches last window bool ignore = (ignored && QString::fromStdString(title).contains(QRegularExpression(s.mExe))); - if (running && (focus || ignore)) + + if ((equals || matches) && (focus || ignore)) { match = true; scene = s.mScene; transition = s.mTransition; + break; } } diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 420b7fbd..88028756 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -295,7 +295,12 @@ bool isInFocus(const QString &exeToCheck) string curWindow; GetCurrentWindowTitle(curWindow); - return QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); + // True if executable switch equals current window + bool equals = (exeToCheck.toStdString() == curWindow); + // True if executable switch matches current window + bool matches = QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); + + return (equals || matches); } diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index 899baca5..d92aac3e 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -234,28 +234,36 @@ void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBS GetCurrentWindowTitle(title); for (auto& window : ignoreWindowsSwitches) { + // True if ignored switch equals title + bool equals = (title == window); // True if ignored switch matches title bool matches = QString::fromStdString(title).contains(QRegularExpression(window.c_str())); - if (matches) + + if (equals || matches) { title = lastTitle; + break; } } lastTitle = title; - // Check for regex match + // Check for match for (WindowSceneSwitch& s : windowSwitches) { + // True if window switch equals title + bool equals = (title == s.window); // True if window switch matches title bool matches = QString::fromStdString(title).contains(QRegularExpression(s.window.c_str())); // True if fullscreen is disabled OR window is fullscreen bool fullscreen = (!s.fullscreen || isFullscreen()); - if (matches && fullscreen) + + if ((equals || matches) && fullscreen) { match = true; scene = s.scene; transition = s.transition; + break; } } From e33e93fd183b8de49c82fb0387ee3e6434b55e35 Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 17 May 2020 13:47:48 -0400 Subject: [PATCH 11/47] Change UI warning to allow direct matches and disable list sorting --- forms/advanced-scene-switcher.ui | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 3cfd4824..bfab89d3 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -372,7 +372,7 @@ https://regexr.com - <html><head/><body><p>WARNING! Entries require valid RegEx to function, otherwise they will silently fail. You can check syntax and matches using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> + <html><head/><body><p>Entries can contain either direct window titles or valid regex. You can check syntax and matches for regular expressions using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> Qt::AutoText @@ -459,7 +459,7 @@ - true + false @@ -581,7 +581,7 @@ - true + false @@ -1141,7 +1141,7 @@ https://regexr.com - <html><head/><body><p>WARNING! Entries require valid RegEx to function, otherwise they will silently fail. You can check syntax and matches using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> + <html><head/><body><p>Entries can contain either direct window titles or valid regex. You can check syntax and matches for regular expressions using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> Qt::AutoText From ac051a42a80534a5151d5e631a7ff3649defe0e1 Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 17 May 2020 23:44:24 -0400 Subject: [PATCH 12/47] Remove unnecessary spaces --- src/linux/advanced-scene-switcher-nix.cpp | 1 - src/osx/advanced-scene-switcher-osx.mm | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 88028756..3815fdb0 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -303,7 +303,6 @@ bool isInFocus(const QString &exeToCheck) return (equals || matches); } - int secondsSinceLastInput() { time_t idle_time; diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index 31a13010..729c359a 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -45,14 +45,14 @@ void GetCurrentWindowTitle(string &title) } } -pair getCursorPos() { - pair pos(0, 0); - CGEventRef event = CGEventCreate(NULL); - CGPoint cursorPos = CGEventGetLocation(event); - CFRelease(event); - pos.first = cursorPos.x; - pos.second = cursorPos.y; - return pos; +pair getCursorPos() { + pair pos(0, 0); + CGEventRef event = CGEventCreate(NULL); + CGPoint cursorPos = CGEventGetLocation(event); + CFRelease(event); + pos.first = cursorPos.x; + pos.second = cursorPos.y; + return pos; } bool isFullscreen() { @@ -76,12 +76,12 @@ bool isFullscreen() { // Get the window size and position AXUIElementCopyAttributeValue( frontMostWindow, kAXSizeAttribute, (CFTypeRef *)&temp); - AXValueGetValue(temp, kAXValueTypeCGSize, &windowSize); + AXValueGetValue(temp, kAXValueTypeCGSize, &windowSize); CFRelease(temp); AXUIElementCopyAttributeValue( frontMostWindow, kAXPositionAttribute, (CFTypeRef *)&temp); - AXValueGetValue(temp, kAXValueTypeCGPoint, &windowPosition); + AXValueGetValue(temp, kAXValueTypeCGPoint, &windowPosition); CFRelease(temp); CGRect screenBound = CGDisplayBounds(CGMainDisplayID()); @@ -118,7 +118,7 @@ void GetProcessList(QStringList& list) NSString *name = app.localizedName; if (!name) continue; - + const char *str = name.UTF8String; if (str && *str) list << (str); From a4de8c0c590e5182035ca52a40c9329629c2adf1 Mon Sep 17 00:00:00 2001 From: Myned Date: Mon, 18 May 2020 00:10:23 -0400 Subject: [PATCH 13/47] Change isInFocus() check to be OS-agnostic isInFocus() can utilize the platform-dependent GetCurrentWindowTitle() instead of re-implementing the same functionality. Tested on Linux and macOS without issues --- src/osx/advanced-scene-switcher-osx.mm | 26 ++++++++++--------------- src/win/advanced-scene-switcher-win.cpp | 22 +++++++++------------ 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index 729c359a..372e5c63 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -126,21 +126,15 @@ void GetProcessList(QStringList& list) } } -bool isInFocus(QString const& appQName) +bool isInFocus(const QString &exeToCheck) { - QByteArray ba = appQName.toLocal8Bit(); - const char * appName = ba.data(); - @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSRunningApplication *app = [ws frontmostApplication]; - if (app) { - NSString *name = app.localizedName; - if (!name) - return false; - - const char *str = name.UTF8String; - return (str && *str && strcmp(appName,str) == 0 )? true : false; - } - } - return false; + string curWindow; + GetCurrentWindowTitle(curWindow); + + // True if executable switch equals current window + bool equals = (exeToCheck.toStdString() == curWindow); + // True if executable switch matches current window + bool matches = QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); + + return (equals || matches); } diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index d20bb9e5..dc42d67f 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -131,21 +131,17 @@ void GetProcessList(QStringList &processes) { CloseHandle(procSnapshot); } -bool isInFocus(const QString &exeToCheck) { - // only checks if the current foreground window is from the same executable, - // may return true for incorrent not meant windows from a program - HWND foregroundWindow = GetForegroundWindow(); - DWORD processId = 0; - GetWindowThreadProcessId(foregroundWindow, &processId); +bool isInFocus(const QString &exeToCheck) +{ + string curWindow; + GetCurrentWindowTitle(curWindow); - HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); - if (process == NULL) return false; + // True if executable switch equals current window + bool equals = (exeToCheck.toStdString() == curWindow); + // True if executable switch matches current window + bool matches = QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); - WCHAR executablePath[600]; - GetModuleFileNameEx(process, 0, executablePath, 600); - CloseHandle(process); - - return exeToCheck == QString::fromWCharArray(executablePath).split(QRegExp("(/|\\\\)")).back(); + return (equals || matches); } int getLastInputTime() From e4b640903dfec7c1d6ba472b47c385e2779555a8 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:34:22 -0400 Subject: [PATCH 14/47] Add ability to choose focus state to window title switcher --- src/advanced-scene-switcher.cpp | 11 +++-- src/headers/advanced-scene-switcher.hpp | 1 + src/headers/switcher-data-structs.hpp | 6 ++- src/headers/utility.hpp | 26 ++++++++--- src/linux/advanced-scene-switcher-nix.cpp | 11 +++++ src/window-title-switch.cpp | 53 ++++++++++++++++++----- 6 files changed, 85 insertions(+), 23 deletions(-) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index a4356ab0..3ab0570a 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -159,7 +159,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent) string transitionName = GetWeakSourceName(s.transition); QString text = MakeSwitchName(sceneName.c_str(), s.window.c_str(), - transitionName.c_str(), s.fullscreen); + transitionName.c_str(), s.fullscreen, s.focus); QListWidgetItem *item = new QListWidgetItem(text, ui->switches); item->setData(Qt::UserRole, s.window.c_str()); @@ -429,7 +429,9 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) obs_data_set_string(array_obj, "window_title", s.window.c_str()); obs_data_set_bool(array_obj, "fullscreen", - s.fullscreen); + s.fullscreen); + obs_data_set_bool(array_obj, "focus", + s.focus); obs_data_array_push_back(array, array_obj); obs_source_release(source); obs_source_release(transition); @@ -906,11 +908,14 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) obs_data_get_string(array_obj, "window_title"); bool fullscreen = obs_data_get_bool(array_obj, "fullscreen"); + bool focus = + obs_data_get_bool(array_obj, "focus"); switcher->windowSwitches.emplace_back( GetWeakSourceByName(scene), window, GetWeakTransitionByName(transition), - fullscreen); + fullscreen, + focus); obs_data_release(array_obj); } diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 88317c64..bced11c6 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -134,6 +134,7 @@ public slots: * Windowtitle helper ********************************************************************************/ void GetWindowList(std::vector &windows); +void GetWindowList(QStringList &windows); // Overloaded void GetCurrentWindowTitle(std::string &title); bool isFullscreen(); diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index 6b88e49c..11f50e0a 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -42,13 +42,15 @@ struct WindowSceneSwitch { string window; OBSWeakSource transition; bool fullscreen; + bool focus; inline WindowSceneSwitch(OBSWeakSource scene_, const char *window_, - OBSWeakSource transition_, bool fullscreen_) + OBSWeakSource transition_, bool fullscreen_, bool focus_) : scene(scene_), window(window_), transition(transition_), - fullscreen(fullscreen_) + fullscreen(fullscreen_), + focus(focus_) { } }; diff --git a/src/headers/utility.hpp b/src/headers/utility.hpp index f1cca4f9..2aea243e 100644 --- a/src/headers/utility.hpp +++ b/src/headers/utility.hpp @@ -14,14 +14,26 @@ static inline bool WeakSourceValid(obs_weak_source_t* ws) } static inline QString MakeSwitchName(const QString &scene, const QString &value, - const QString &transition, bool fullscreen) + const QString &transition, bool fullscreen, bool focus) { - if (!fullscreen) - return QStringLiteral("[") + scene + QStringLiteral(", ") + - transition + QStringLiteral("]: ") + value; - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + - QStringLiteral("]: ") + value + - QStringLiteral(" (only if window is fullscreen)"); + QString name = QStringLiteral("[") + scene + QStringLiteral(", ") + + transition + QStringLiteral("]: ") + value; + + if (fullscreen || focus) + { + name += QStringLiteral(" (only if"); + + if (fullscreen) + name += QStringLiteral(" fullscreen"); + if (fullscreen && focus) + name += QStringLiteral(" and"); + if (focus) + name += QStringLiteral(" focused"); + + name += QStringLiteral(")"); + } + + return name; } static inline QString MakeSwitchNameExecutable(const QString &scene, diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 3815fdb0..313daf1d 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -174,6 +174,17 @@ void GetWindowList(vector &windows) } } +// Overloaded +void GetWindowList(QStringList &windows) +{ + windows.clear(); + + for (size_t i = 0; i < getTopLevelWindows().size(); ++i){ + if (GetWindowTitle(i) != "") + windows << QString::fromStdString(GetWindowTitle(i)); + } +} + void GetCurrentWindowTitle(string &title) { if (!ewmhIsSupported()) { diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index d92aac3e..5e6bd943 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -1,12 +1,39 @@ #include #include "headers/advanced-scene-switcher.hpp" +bool isRunning(std::string &title) +{ + QStringList windows; + + GetWindowList(windows); + // True if switch is running (direct) + bool equals = windows.contains(title.c_str()); + // True if switch is running (regex) + bool matches = (windows.indexOf(QRegularExpression(title.c_str())) != -1); + + return (equals || matches); +} + +bool isFocused(std::string &title) +{ + string current; + + GetCurrentWindowTitle(current); + // True if switch equals current window + bool equals = (title == current); + // True if switch matches current window + bool matches = QString::fromStdString(current).contains(QRegularExpression(title.c_str())); + + return (equals || matches); +} + void SceneSwitcher::on_add_clicked() { QString sceneName = ui->scenes->currentText(); QString windowName = ui->windows->currentText(); QString transitionName = ui->transitions->currentText(); bool fullscreen = ui->fullscreenCheckBox->isChecked(); + bool focus = ui->focusCheckBox->isChecked(); if (windowName.isEmpty() || sceneName.isEmpty()) return; @@ -15,7 +42,7 @@ void SceneSwitcher::on_add_clicked() OBSWeakSource transition = GetWeakTransitionByQString(transitionName); QVariant v = QVariant::fromValue(windowName); - QString text = MakeSwitchName(sceneName, windowName, transitionName, fullscreen); + QString text = MakeSwitchName(sceneName, windowName, transitionName, fullscreen, focus); int idx = FindByData(windowName); @@ -23,7 +50,7 @@ void SceneSwitcher::on_add_clicked() { lock_guard lock(switcher->m); switcher->windowSwitches.emplace_back( - source, windowName.toUtf8().constData(), transition, fullscreen); + source, windowName.toUtf8().constData(), transition, fullscreen, focus); QListWidgetItem* item = new QListWidgetItem(text, ui->switches); item->setData(Qt::UserRole, v); @@ -44,6 +71,7 @@ void SceneSwitcher::on_add_clicked() s.scene = source; s.transition = transition; s.fullscreen = fullscreen; + s.focus = focus; break; } } @@ -198,6 +226,7 @@ void SceneSwitcher::on_switches_currentRowChanged(int idx) ui->windows->setCurrentText(window); ui->transitions->setCurrentText(transitionName.c_str()); ui->fullscreenCheckBox->setChecked(s.fullscreen); + ui->focusCheckBox->setChecked(s.focus); break; } } @@ -229,18 +258,20 @@ void SceneSwitcher::on_ignoreWindows_currentRowChanged(int idx) void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) { string title; + bool ignored = false; // Check if current window is ignored GetCurrentWindowTitle(title); for (auto& window : ignoreWindowsSwitches) { - // True if ignored switch equals title + // True if ignored switch equals current window bool equals = (title == window); - // True if ignored switch matches title + // True if ignored switch matches current window bool matches = QString::fromStdString(title).contains(QRegularExpression(window.c_str())); if (equals || matches) { + ignored = true; title = lastTitle; break; @@ -251,14 +282,14 @@ void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBS // Check for match for (WindowSceneSwitch& s : windowSwitches) { - // True if window switch equals title - bool equals = (title == s.window); - // True if window switch matches title - bool matches = QString::fromStdString(title).contains(QRegularExpression(s.window.c_str())); - // True if fullscreen is disabled OR window is fullscreen - bool fullscreen = (!s.fullscreen || isFullscreen()); + // True if fullscreen is disabled OR current window is fullscreen + bool fullscreen = (!s.fullscreen || isFullscreen(s.window)); + // True if focus is disabled OR switch is focused + bool focus = (!s.focus || isFocused(s.window)); + // True if current window is ignored AND switch matches last window + bool ignore = (ignored && QString::fromStdString(title).contains(QRegularExpression(s.window.c_str()))); - if ((equals || matches) && fullscreen) + if (isRunning(s.window) && (fullscreen && (focus || ignore))) { match = true; scene = s.scene; From be83232caa5bef0b2bd8028534fb6cf90e1e2f66 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:37:03 -0400 Subject: [PATCH 15/47] Update UI for focus addition, add/change warnings, and move exe tab --- forms/advanced-scene-switcher.ui | 352 +++++++++++++++++-------------- 1 file changed, 188 insertions(+), 164 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index bfab89d3..f599352f 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -6,14 +6,20 @@ 0 0 - 981 - 457 + 1010 + 560 Advanced Scene Switcher + + true + + + QLayout::SetNoConstraint + @@ -24,6 +30,17 @@ General + + + + + + WARNING! Condition checking interval must be at least as long as the duration of transitions to avoid scene locking + + + + + @@ -369,10 +386,10 @@ - https://regexr.com + https://regexr.com/ - <html><head/><body><p>Entries can contain either direct window titles or valid regex. You can check syntax and matches for regular expressions using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> + <html><head/><body><p>Enter either direct window titles or valid regex. You can check syntax and matches for regular expressions using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> Qt::AutoText @@ -431,7 +448,14 @@ - only if window is fullscreen + only if fullscreen + + + + + + + only if focused @@ -653,6 +677,165 @@ + + + ArrowCursor + + + Executable + + + + + + + + + + + <html><head/><body><p>WARNING! Simultaneously running multiple applications from the same executable may result in undesired behavior</p></body></html> + + + Qt::AutoText + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + true + + + 20 + + + + + + + + 100 + 0 + + + + + + + + + + + only if focused + + + 100 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + true + + + false + + + + + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Implemented by dasOven + + + + + + + Screen Region @@ -1125,165 +1308,6 @@ - - - ArrowCursor - - - Executable - - - - - - - - https://regexr.com - - - <html><head/><body><p>Entries can contain either direct window titles or valid regex. You can check syntax and matches for regular expressions using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> - - - Qt::AutoText - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - true - - - 20 - - - - - - - - 100 - 0 - - - - - - - - - - - only if window is in focus - - - 100 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - true - - - false - - - - - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Implemented by dasOven - - - - - - - Idle Detection From de5b6f8eb4f0a53aacebca7aff62a60d7a58670f Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:40:37 -0400 Subject: [PATCH 16/47] Fix fullscreen check only returning true if window is focused on Linux --- src/headers/advanced-scene-switcher.hpp | 2 +- src/linux/advanced-scene-switcher-nix.cpp | 106 +++++++++++++++------- 2 files changed, 74 insertions(+), 34 deletions(-) diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index bced11c6..8a990d02 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -136,7 +136,7 @@ public slots: void GetWindowList(std::vector &windows); void GetWindowList(QStringList &windows); // Overloaded void GetCurrentWindowTitle(std::string &title); -bool isFullscreen(); +bool isFullscreen(std::string &title); /******************************************************************************** * Screenregion helper diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 313daf1d..8d69b2db 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -98,6 +98,39 @@ static bool ewmhIsSupported() return ewmh_window != 0; } +static QStringList getStates(Window window) { + QStringList states; + + if (!ewmhIsSupported()) + return states; + + Atom wmState = XInternAtom(disp(), "_NET_WM_STATE", true), type; + int format; + unsigned long num, bytes; + unsigned char *data; + + int status = XGetWindowProperty( + disp(), + window, + wmState, + 0, + ~0L, + false, + AnyPropertyType, + &type, + &format, + &num, + &bytes, + &data + ); + + if (status == Success) + for (unsigned long i = 0; i < num; i++) + states.append(QString(XGetAtomName(disp(), ((Atom*)data)[i]))); + + return states; +} + static std::vector getTopLevelWindows() { std::vector res; @@ -251,43 +284,50 @@ pair getCursorPos() return pos; } -bool isFullscreen() +bool isFullscreen(std::string &title) { - if (!ewmhIsSupported()) { + if (!ewmhIsSupported()) return false; + + // Find switch in top level windows + Atom titleProperty = XInternAtom(disp(), "_NET_WM_NAME", true); + vector windows = getTopLevelWindows(); + for (auto &window : windows) + { + XTextProperty text; + int status = XGetTextProperty(disp(), window, &text, titleProperty); + string name(reinterpret_cast(text.value)); + + if (status == 0 || name == "") + continue; + + // True if switch equals window + bool equals = (title == name); + // True if switch matches window + bool matches = QString::fromStdString(name).contains(QRegularExpression(title.c_str())); + + // If found, check if switch is fullscreen + if (equals || matches) + { + QStringList states = getStates(window); + + if (!states.isEmpty()) + { + // True if window is fullscreen + bool fullscreen = states.contains("_NET_WM_STATE_FULLSCREEN"); + // True if window is maximized vertically + bool vertical = states.contains("_NET_WM_STATE_MAXIMIZED_VERT"); + // True if window is maximized horizontally + bool horizontal = states.contains("_NET_WM_STATE_MAXIMIZED_HORZ"); + + return (fullscreen || (vertical && horizontal)); + } + + break; + } } - Atom active = XInternAtom(disp(), "_NET_ACTIVE_WINDOW", true); - Atom actualType; - int format; - unsigned long num, bytes; - Window* data = 0; - - Window rootWin = RootWindow(disp(), 0); - XGetWindowProperty( - disp(), - rootWin, - active, - 0L, - ~0L, - false, - AnyPropertyType, - &actualType, - &format, - &num, - &bytes, - (uint8_t**)&data); - - - XWindowAttributes window_attributes_return; - XWindowAttributes screen_attributes_return; - - XGetWindowAttributes(disp(), rootWin, &screen_attributes_return); - XGetWindowAttributes(disp(), data[0], &window_attributes_return); - - //menu bar is always 24 pixels in height - return (window_attributes_return.width >= screen_attributes_return.width && - window_attributes_return.height + 24 >= screen_attributes_return.height) ? true : false; + return false; } //exe switch is not quite what is expected but it works for now From 70894f93029104a5fe75ffc4710f25351f0a7e8a Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:42:58 -0400 Subject: [PATCH 17/47] Add regex matching to reverted isInFocus() for Windows Reverts part of a4de8c0c590e5182035ca52a40c9329629c2adf1 --- src/win/advanced-scene-switcher-win.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index dc42d67f..677885a6 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -131,15 +131,27 @@ void GetProcessList(QStringList &processes) { CloseHandle(procSnapshot); } -bool isInFocus(const QString &exeToCheck) +bool isInFocus(const QString &executable) { - string curWindow; - GetCurrentWindowTitle(curWindow); + // only checks if the current foreground window is from the same executable, + // may return true for any window from a program + HWND foregroundWindow = GetForegroundWindow(); + DWORD processId = 0; + GetWindowThreadProcessId(foregroundWindow, &processId); + + HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); + if (process == NULL) return false; + + WCHAR executablePath[600]; + GetModuleFileNameEx(process, 0, executablePath, 600); + CloseHandle(process); + + QString file = QString::fromWCharArray(executablePath).split(QRegularExpression("(/|\\\\)")).back(); // True if executable switch equals current window - bool equals = (exeToCheck.toStdString() == curWindow); + bool equals = (executable == file); // True if executable switch matches current window - bool matches = QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); + bool matches = file.contains(QRegularExpression(executable)); return (equals || matches); } From 463b54f1fbf198f31be5d67ce00a9085627280ea Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:52:11 -0400 Subject: [PATCH 18/47] Remove sorting when adding switches --- src/executable-switch.cpp | 2 -- src/window-title-switch.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 0f770357..f1226076 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -90,8 +90,6 @@ void SceneSwitcher::on_executableAdd_clicked() } } } - - ui->executables->sortItems(); } } diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index 5e6bd943..48efdbf9 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -76,8 +76,6 @@ void SceneSwitcher::on_add_clicked() } } } - - ui->switches->sortItems(); } } @@ -129,7 +127,6 @@ void SceneSwitcher::on_ignoreWindowsAdd_clicked() lock_guard lock(switcher->m); switcher->ignoreWindowsSwitches.emplace_back(windowName.toUtf8().constData()); - ui->ignoreWindows->sortItems(); } } From f00c244bfa6765c7315a33dc25c2b77d1ce1c4f4 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:52:41 -0400 Subject: [PATCH 19/47] Change wording slightly --- src/executable-switch.cpp | 4 ++-- src/headers/advanced-scene-switcher.hpp | 2 +- src/headers/utility.hpp | 2 +- src/linux/advanced-scene-switcher-nix.cpp | 10 +++++----- src/osx/advanced-scene-switcher-osx.mm | 10 +++++----- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index f1226076..9a31ae4f 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -154,9 +154,9 @@ void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSour bool equals = runningProcesses.contains(s.mExe); // True if executable switch is running (regex) bool matches = (runningProcesses.indexOf(QRegularExpression(s.mExe)) != -1); - // True if focus is disabled OR window in focus + // True if focus is disabled OR switch is focused bool focus = (!s.mInFocus || isInFocus(s.mExe)); - // True if current window is ignored AND executable switch matches last window + // True if current window is ignored AND switch matches last window bool ignore = (ignored && QString::fromStdString(title).contains(QRegularExpression(s.mExe))); if ((equals || matches) && (focus || ignore)) diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 8a990d02..5bc5cae0 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -152,7 +152,7 @@ int secondsSinceLastInput(); * Executable helper ********************************************************************************/ void GetProcessList(QStringList &processes); -bool isInFocus(const QString &exeToCheck); +bool isInFocus(const QString &executable); /******************************************************************************** * Sceneswitch helper diff --git a/src/headers/utility.hpp b/src/headers/utility.hpp index 2aea243e..c28c92b6 100644 --- a/src/headers/utility.hpp +++ b/src/headers/utility.hpp @@ -46,7 +46,7 @@ static inline QString MakeSwitchNameExecutable(const QString &scene, transition + QStringLiteral("]: ") + value; return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + QStringLiteral("]: ") + value + - QStringLiteral(" (only if window is focused)"); + QStringLiteral(" (only if focused)"); } static inline QString MakeScreenRegionSwitchName(const QString &scene, diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 8d69b2db..af72858e 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -341,15 +341,15 @@ void GetProcessList(QStringList &processes) } } -bool isInFocus(const QString &exeToCheck) +bool isInFocus(const QString &executable) { - string curWindow; - GetCurrentWindowTitle(curWindow); + string current; + GetCurrentWindowTitle(current); // True if executable switch equals current window - bool equals = (exeToCheck.toStdString() == curWindow); + bool equals = (executable.toStdString() == current); // True if executable switch matches current window - bool matches = QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); + bool matches = QString::fromStdString(current).contains(QRegularExpression(executable)); return (equals || matches); } diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index 372e5c63..f3ed34b1 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -126,15 +126,15 @@ void GetProcessList(QStringList& list) } } -bool isInFocus(const QString &exeToCheck) +bool isInFocus(const QString &executable) { - string curWindow; - GetCurrentWindowTitle(curWindow); + string current; + GetCurrentWindowTitle(current); // True if executable switch equals current window - bool equals = (exeToCheck.toStdString() == curWindow); + bool equals = (executable.toStdString() == current); // True if executable switch matches current window - bool matches = QString::fromStdString(curWindow).contains(QRegularExpression(exeToCheck)); + bool matches = QString::fromStdString(current).contains(QRegularExpression(executable)); return (equals || matches); } From e61905d02f5aa4143b507e8a53b98d45a93ba944 Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:53:47 -0400 Subject: [PATCH 20/47] Change window title property on Linux to align with freedesktop spec Freedesktop recommends using _NET_WM_NAME instead of WM_NAME, and on KDE, for example, the difference between them is including the application name for some windows (e.g. "freedesktop - Google Search - Vivaldi" compared to "freedesktop - Google Search") --- src/linux/advanced-scene-switcher-nix.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index af72858e..188494b5 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -184,9 +184,11 @@ static std::string GetWindowTitle(size_t i) char* name; XTextProperty text; - int status = XGetWMName(disp(), w, &text); + Atom titleProperty = XInternAtom(disp(), "_NET_WM_NAME", true); + int status = XGetTextProperty(disp(), w, &text, titleProperty); name = reinterpret_cast(text.value); - if (status >= Success && name != nullptr) + + if (status != 0 && name != nullptr) { std::string str(name); windowTitle = str; @@ -248,10 +250,11 @@ void GetCurrentWindowTitle(string &title) (uint8_t**)&data); XTextProperty text; - int status = XGetWMName(disp(), data[0], &text); + Atom titleProperty = XInternAtom(disp(), "_NET_WM_NAME", true); + int status = XGetTextProperty(disp(), data[0], &text, titleProperty); name = reinterpret_cast(text.value); - if (status >= Success && name != nullptr) { + if (status != 0 && name != nullptr) { std::string str(name); title = str; } From a7a8adb91b2e47f4f5e00329c3f68b965906874b Mon Sep 17 00:00:00 2001 From: Myned Date: Thu, 21 May 2020 00:54:49 -0400 Subject: [PATCH 21/47] Remove whitespace --- src/executable-switch.cpp | 3 --- src/headers/switcher-data-structs.hpp | 2 +- src/osx/advanced-scene-switcher-osx.mm | 8 +++++--- src/window-title-switch.cpp | 8 -------- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 9a31ae4f..181a94ee 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -16,7 +16,6 @@ int SceneSwitcher::executableFindByData(const QString& exe) return -1; } - void SceneSwitcher::on_executables_currentRowChanged(int idx) { if (loading) @@ -44,7 +43,6 @@ void SceneSwitcher::on_executables_currentRowChanged(int idx) } } - void SceneSwitcher::on_executableAdd_clicked() { QString sceneName = ui->executableScenes->currentText(); @@ -93,7 +91,6 @@ void SceneSwitcher::on_executableAdd_clicked() } } - void SceneSwitcher::on_executableRemove_clicked() { QListWidgetItem* item = ui->executables->currentItem(); diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index 11f50e0a..371c9d05 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -230,7 +230,7 @@ struct MediaSwitch { typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch; /******************************************************************************** - * SwitcherData + * SwitcherData ********************************************************************************/ struct SwitcherData { thread th; diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index f3ed34b1..5972287f 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -45,7 +45,8 @@ void GetCurrentWindowTitle(string &title) } } -pair getCursorPos() { +pair getCursorPos() +{ pair pos(0, 0); CGEventRef event = CGEventCreate(NULL); CGPoint cursorPos = CGEventGetLocation(event); @@ -53,9 +54,10 @@ pair getCursorPos() { pos.first = cursorPos.x; pos.second = cursorPos.y; return pos; - } +} -bool isFullscreen() { +bool isFullscreen() +{ @autoreleasepool { AXValueRef temp; CGSize windowSize; diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index 48efdbf9..0b65a66b 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -106,9 +106,6 @@ void SceneSwitcher::on_remove_clicked() delete item; } - - - void SceneSwitcher::on_ignoreWindowsAdd_clicked() { QString windowName = ui->ignoreWindowsWindows->currentText(); @@ -177,9 +174,6 @@ int SceneSwitcher::FindByData(const QString& window) return idx; } - - - int SceneSwitcher::IgnoreWindowsFindByData(const QString& window) { int count = ui->ignoreWindows->count(); @@ -200,7 +194,6 @@ int SceneSwitcher::IgnoreWindowsFindByData(const QString& window) return idx; } - void SceneSwitcher::on_switches_currentRowChanged(int idx) { if (loading) @@ -229,7 +222,6 @@ void SceneSwitcher::on_switches_currentRowChanged(int idx) } } - void SceneSwitcher::on_ignoreWindows_currentRowChanged(int idx) { if (loading) From 2a0e9e9d9ac8f231ee2ed7c80a1268bc1aa3825c Mon Sep 17 00:00:00 2001 From: Myned Date: Fri, 22 May 2020 23:58:18 -0400 Subject: [PATCH 22/47] Change wording --- forms/advanced-scene-switcher.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index f599352f..3897fb68 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -577,7 +577,7 @@ - is in focus + is focused From 87da123c192c17695a5768b65d2f5a589358215f Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 23 May 2020 00:00:04 -0400 Subject: [PATCH 23/47] Change default focus value to true --- src/advanced-scene-switcher.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index 3ab0570a..88275192 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -909,7 +909,8 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) bool fullscreen = obs_data_get_bool(array_obj, "fullscreen"); bool focus = - obs_data_get_bool(array_obj, "focus"); + obs_data_get_bool(array_obj, "focus") + || !obs_data_has_user_value(array_obj, "focus"); switcher->windowSwitches.emplace_back( GetWeakSourceByName(scene), window, From f0cf5a5c193597563c7a0d16cd1e25b29fd8f750 Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 23 May 2020 00:25:30 -0400 Subject: [PATCH 24/47] Fix Windows and macOS build errors Adds to e4b640903dfec7c1d6ba472b47c385e2779555a8 and de5b6f8eb4f0a53aacebca7aff62a60d7a58670f --- src/osx/advanced-scene-switcher-osx.mm | 24 +++++++++++++++++++++++- src/win/advanced-scene-switcher-win.cpp | 19 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index 5972287f..05935906 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -26,6 +26,27 @@ void GetWindowList(vector &windows) } } +// Overloaded +void GetWindowList(QStringList &windows) +{ + windows.clear(); + + @autoreleasepool { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSArray *array = [ws runningApplications]; + for (NSRunningApplication *app in array) { + NSString *name = app.localizedName; + if (!name) + continue; + + const char *str = name.UTF8String; + if (str && *str) + windows.emplace_back(str); + windows << QString(str); + } + } +} + void GetCurrentWindowTitle(string &title) { title.resize(0); @@ -56,7 +77,8 @@ pair getCursorPos() return pos; } -bool isFullscreen() +// Argument added in lieu of fullscreen bug fix +bool isFullscreen(std::string &title) { @autoreleasepool { AXValueRef temp; diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index 677885a6..720b4a3b 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -58,6 +58,22 @@ void GetWindowList(vector& windows) } } +// Overloaded +void GetWindowList(QStringList &windows) +{ + windows.clear(); + + HWND window = GetWindow(GetDesktopWindow(), GW_CHILD); + + while (window) + { + string title; + if (WindowValid(window) && GetWindowTitle(window, title)) + windows << QString::fromStdString(title); + window = GetNextWindow(window, GW_HWNDNEXT); + } +} + void GetCurrentWindowTitle(string& title) { HWND window = GetForegroundWindow(); @@ -87,7 +103,8 @@ pair getCursorPos() return pos; } -bool isFullscreen() +// Argument added in lieu of fullscreen bug fix +bool isFullscreen(std::string &title) { RECT appBounds; RECT rc; From 3959e41e88b74ca82889fec9a83ee0bdd26ddf8b Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 23 May 2020 00:27:19 -0400 Subject: [PATCH 25/47] Add clearing of passed window list like with other platforms --- src/win/advanced-scene-switcher-win.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index 720b4a3b..7cdfb8a1 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -47,6 +47,8 @@ static bool WindowValid(HWND window) void GetWindowList(vector& windows) { + windows.resize(0); + HWND window = GetWindow(GetDesktopWindow(), GW_CHILD); while (window) From 23201100fa0a3eadd59ecab5a1bd62a104caf7df Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 23 May 2020 00:34:40 -0400 Subject: [PATCH 26/47] Fix macOS build error (again) Adds to f0cf5a5c193597563c7a0d16cd1e25b29fd8f750 Forgot to remove vestigial code --- src/osx/advanced-scene-switcher-osx.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index 05935906..a3488604 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -41,7 +41,6 @@ void GetWindowList(QStringList &windows) const char *str = name.UTF8String; if (str && *str) - windows.emplace_back(str); windows << QString(str); } } From 55d8303ecf4d3c9cefb262424f0838497d97908b Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 26 May 2020 02:43:36 -0400 Subject: [PATCH 27/47] Fix isFullscreen() logic error for Linux Not sure why this arose in the first place --- 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 188494b5..6207475a 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -299,9 +299,9 @@ bool isFullscreen(std::string &title) { XTextProperty text; int status = XGetTextProperty(disp(), window, &text, titleProperty); - string name(reinterpret_cast(text.value)); + char *name = reinterpret_cast(text.value); - if (status == 0 || name == "") + if (status == 0 || strcmp(name, "") == 0) continue; // True if switch equals window From d6380b865e21675cbde37aee34c275eda6acfb91 Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 2 Jun 2020 00:38:35 -0400 Subject: [PATCH 28/47] Fix some windows (Steam) not being found on Linux Reverts part of commit e61905d02f5aa4143b507e8a53b98d45a93ba944 Fallback to WM_NAME if _NET_WM_NAME does not exist Also fixes some BadWindow errors that were due to some apps like Steam only populating WM_NAME, and only for certain windows (tooltips count as windows due to the odd way the GUI works on Linux, so they don't have either property) --- src/linux/advanced-scene-switcher-nix.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 6207475a..750fe32c 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -184,8 +184,9 @@ static std::string GetWindowTitle(size_t i) char* name; XTextProperty text; - Atom titleProperty = XInternAtom(disp(), "_NET_WM_NAME", true); - int status = XGetTextProperty(disp(), w, &text, titleProperty); + int status = XGetTextProperty(disp(), w, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); + if (status == 0) + status = XGetTextProperty(disp(), w, &text, XInternAtom(disp(), "WM_NAME", true)); name = reinterpret_cast(text.value); if (status != 0 && name != nullptr) @@ -235,7 +236,7 @@ void GetCurrentWindowTitle(string &title) Window rootWin = RootWindow(disp(), 0); - XGetWindowProperty( + int xstatus = XGetWindowProperty( disp(), rootWin, active, @@ -249,9 +250,13 @@ void GetCurrentWindowTitle(string &title) &bytes, (uint8_t**)&data); + int status = 0; XTextProperty text; - Atom titleProperty = XInternAtom(disp(), "_NET_WM_NAME", true); - int status = XGetTextProperty(disp(), data[0], &text, titleProperty); + if (xstatus == Success) { + status = XGetTextProperty(disp(), data[0], &text, XInternAtom(disp(), "_NET_WM_NAME", true)); + if (status == 0) + status = XGetTextProperty(disp(), data[0], &text, XInternAtom(disp(), "WM_NAME", true)); + } name = reinterpret_cast(text.value); if (status != 0 && name != nullptr) { @@ -293,15 +298,16 @@ bool isFullscreen(std::string &title) return false; // Find switch in top level windows - Atom titleProperty = XInternAtom(disp(), "_NET_WM_NAME", true); vector windows = getTopLevelWindows(); for (auto &window : windows) { XTextProperty text; - int status = XGetTextProperty(disp(), window, &text, titleProperty); + int status = XGetTextProperty(disp(), window, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); + if (status == 0) + status = XGetTextProperty(disp(), window, &text, XInternAtom(disp(), "WM_NAME", true)); char *name = reinterpret_cast(text.value); - if (status == 0 || strcmp(name, "") == 0) + if (status == 0 || name == nullptr) continue; // True if switch equals window From 78ed7415f58dba457fb86eec549cbf921441806b Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 2 Jun 2020 00:39:14 -0400 Subject: [PATCH 29/47] Fix allocation error --- src/linux/advanced-scene-switcher-nix.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 750fe32c..e124e5b4 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -193,10 +193,9 @@ static std::string GetWindowTitle(size_t i) { std::string str(name); windowTitle = str; + XFree(name); } - XFree(name); - return windowTitle; } @@ -262,9 +261,8 @@ void GetCurrentWindowTitle(string &title) if (status != 0 && name != nullptr) { std::string str(name); title = str; + XFree(name); } - - XFree(name); } pair getCursorPos() From cfb0a44b1fe157a906ddf92562163f6a9d996431 Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 2 Jun 2020 00:40:22 -0400 Subject: [PATCH 30/47] Change UI to specify greater than Scene locking can occur when interval is equal to transition time due to inconsistencies in timers --- forms/advanced-scene-switcher.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 3897fb68..9a4f5f64 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -35,7 +35,7 @@ - WARNING! Condition checking interval must be at least as long as the duration of transitions to avoid scene locking + WARNING! Condition checking interval must be greater than the duration of transitions to avoid scene locking From 5590e97f4fe5b8956ca45799f48d470ba4f9f52f Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 6 Jun 2020 18:39:57 -0400 Subject: [PATCH 31/47] Fix fullscreen check only returning true if window is focused on Windows by @WarmUpTill --- src/win/advanced-scene-switcher-win.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index 7cdfb8a1..35f7ec82 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -105,22 +105,36 @@ pair getCursorPos() return pos; } -// Argument added in lieu of fullscreen bug fix bool isFullscreen(std::string &title) { RECT appBounds; RECT rc; + + HWND hwnd = GetWindow(GetDesktopWindow(), GW_CHILD); + while (hwnd) + { + string wtitle; + if (WindowValid(hwnd) && GetWindowTitle(hwnd, wtitle) && wtitle == title) + break; + + hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); + } + GetWindowRect(GetDesktopWindow(), &rc); - HWND hwnd = GetForegroundWindow(); if (hwnd != GetDesktopWindow() && hwnd != GetShellWindow()) { GetWindowRect(hwnd, &appBounds); - if (rc.bottom == appBounds.bottom && rc.top == appBounds.top && rc.left == appBounds.left - && rc.right == appBounds.right) - { + if + ( + rc.bottom == appBounds.bottom + && rc.top == appBounds.top + && rc.left == appBounds.left + && rc.right == appBounds.right + ) { return true; } } + return false; } From 4b86849356aeec6e45b5a5c9503e1f3a22e93721 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 6 Jun 2020 18:51:26 +0200 Subject: [PATCH 32/47] Revert "do not use QThread::create" This reverts commit 98c3131017db23b04d3185599eee0229f72ac9b2. --- src/advanced-scene-switcher.cpp | 4 +--- src/headers/switcher-data-structs.hpp | 12 +----------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index df59e982..57f8c432 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -1569,7 +1569,7 @@ void SwitcherData::Start() { if (!(th && th->isRunning())) { stop = false; - switcher->th = new SwitcherThread(); + switcher->th = QThread::create([]() { switcher->Thread(); }); switcher->th->start((QThread::Priority)switcher->threadPriority); } } @@ -1582,8 +1582,6 @@ void SwitcherData::Stop() transitionCv.notify_one(); cv.notify_one(); th->wait(); - delete th; - th = nullptr; } } diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index bcdca7b2..b10e43af 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -253,14 +253,11 @@ struct TimeSwitch { typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch; -class SwitcherThread; - /******************************************************************************** * SwitcherData ********************************************************************************/ struct SwitcherData { - SwitcherThread *th; - + QThread* th = nullptr; condition_variable cv; mutex m; bool transitionActive = false; @@ -485,10 +482,3 @@ struct SwitcherData { } inline ~SwitcherData() { Stop(); } }; - -extern SwitcherData *switcher; -class SwitcherThread : public QThread { -public: - explicit SwitcherThread(){}; - void run() { switcher->Thread(); }; -}; From 9386109168748391356048926690c6593df74349 Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 6 Jun 2020 23:19:58 -0400 Subject: [PATCH 33/47] Remove tooltip from UI Wasn't able to isolate it to the link, so it gets in the way --- forms/advanced-scene-switcher.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index f1fc9e12..5a49b795 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -440,7 +440,7 @@ - https://regexr.com/ + <html><head/><body><p>Enter either direct window titles or valid regex. You can check syntax and matches for regular expressions using <a href="https://regexr.com"><span style=" text-decoration: underline; color:#268bd2;">RegExr</span></a></p></body></html> From c6a26d862fff7ae64b7c30a79d95949f6e246d0a Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 6 Jun 2020 23:21:06 -0400 Subject: [PATCH 34/47] Enable sorting for Ignored windows There is no use in reordering them --- forms/advanced-scene-switcher.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 5a49b795..15b8ba5c 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -659,7 +659,7 @@ - false + true From cba39633aa42d83f1057ffe3cdcfeaa2eb4e9047 Mon Sep 17 00:00:00 2001 From: Myned Date: Sat, 6 Jun 2020 23:23:02 -0400 Subject: [PATCH 35/47] Add ability to reorder Window and Executable switches with arrows --- forms/advanced-scene-switcher.ui | 170 ++++++++++++++++++++++++ src/executable-switch.cpp | 30 +++++ src/headers/advanced-scene-switcher.hpp | 4 + src/window-title-switch.cpp | 30 +++++ 4 files changed, 234 insertions(+) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 15b8ba5c..28fb264c 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -546,6 +546,91 @@ 4 + + + + + 22 + 22 + + + + + + + + ../../../forms/images/up.svg../../../forms/images/up.svg + + + true + + + upArrowIconSmall + + + + + + + + 22 + 22 + + + + + + + + ../../../forms/images/down.svg../../../forms/images/down.svg + + + true + + + downArrowIconSmall + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + @@ -834,6 +919,91 @@ + + + + + 22 + 22 + + + + + + + + ../../../forms/images/up.svg../../../forms/images/up.svg + + + true + + + upArrowIconSmall + + + + + + + + 22 + 22 + + + + + + + + ../../../forms/images/down.svg../../../forms/images/down.svg + + + true + + + downArrowIconSmall + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 181a94ee..d05ba3e7 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -43,6 +43,36 @@ void SceneSwitcher::on_executables_currentRowChanged(int idx) } } +void SceneSwitcher::on_executableUp_clicked() +{ + int index = ui->executables->currentRow(); + if (index != -1 && index != 0) + { + ui->executables->insertItem(index - 1, ui->executables->takeItem(index)); + ui->executables->setCurrentRow(index - 1); + + lock_guard lock(switcher->m); + + iter_swap(switcher->executableSwitches.begin() + index, + switcher->executableSwitches.begin() + index - 1); + } +} + +void SceneSwitcher::on_executableDown_clicked() +{ + int index = ui->executables->currentRow(); + if (index != -1 && index != ui->executables->count() - 1) + { + ui->executables->insertItem(index + 1, ui->executables->takeItem(index)); + ui->executables->setCurrentRow(index + 1); + + lock_guard lock(switcher->m); + + iter_swap(switcher->executableSwitches.begin() + index, + switcher->executableSwitches.begin() + index + 1); + } +} + void SceneSwitcher::on_executableAdd_clicked() { QString sceneName = ui->executableScenes->currentText(); diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 591e2348..99b7601b 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -51,6 +51,8 @@ public: public slots: void on_switches_currentRowChanged(int idx); + void on_up_clicked(); + void on_down_clicked(); void on_add_clicked(); void on_remove_clicked(); void on_noMatchDontSwitch_clicked(); @@ -99,6 +101,8 @@ public slots: void on_writePathLineEdit_textChanged(const QString &text); void on_browseButton_2_clicked(); + void on_executableUp_clicked(); + void on_executableDown_clicked(); void on_executableAdd_clicked(); void on_executableRemove_clicked(); void on_executables_currentRowChanged(int idx); diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index 0b65a66b..791b6a5d 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -27,6 +27,36 @@ bool isFocused(std::string &title) return (equals || matches); } +void SceneSwitcher::on_up_clicked() +{ + int index = ui->switches->currentRow(); + if (index != -1 && index != 0) + { + ui->switches->insertItem(index - 1, ui->switches->takeItem(index)); + ui->switches->setCurrentRow(index - 1); + + lock_guard lock(switcher->m); + + iter_swap(switcher->windowSwitches.begin() + index, + switcher->windowSwitches.begin() + index - 1); + } +} + +void SceneSwitcher::on_down_clicked() +{ + int index = ui->switches->currentRow(); + if (index != -1 && index != ui->switches->count() - 1) + { + ui->switches->insertItem(index + 1, ui->switches->takeItem(index)); + ui->switches->setCurrentRow(index + 1); + + lock_guard lock(switcher->m); + + iter_swap(switcher->windowSwitches.begin() + index, + switcher->windowSwitches.begin() + index + 1); + } +} + void SceneSwitcher::on_add_clicked() { QString sceneName = ui->scenes->currentText(); From acd2e2863a27a1603f8f2db791791647144a6267 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 7 Jun 2020 13:25:51 +0200 Subject: [PATCH 36/47] adjust win isFullscreen() to use GetMonitorInfo() only tested on a single monitor setup but should work on secondary monitors also as MONITOR_DEFAULTTONEAREST is set --- src/win/advanced-scene-switcher-win.cpp | 67 +++++++++++++------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index 35f7ec82..d9667920 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -6,7 +6,7 @@ using namespace std; -static bool GetWindowTitle(HWND window, string& title) +static bool GetWindowTitle(HWND window, string &title) { size_t len = (size_t)GetWindowTextLengthW(window); wstring wtitle; @@ -45,14 +45,13 @@ static bool WindowValid(HWND window) return true; } -void GetWindowList(vector& windows) +void GetWindowList(vector &windows) { windows.resize(0); HWND window = GetWindow(GetDesktopWindow(), GW_CHILD); - while (window) - { + while (window) { string title; if (WindowValid(window) && GetWindowTitle(window, title)) windows.emplace_back(title); @@ -67,8 +66,7 @@ void GetWindowList(QStringList &windows) HWND window = GetWindow(GetDesktopWindow(), GW_CHILD); - while (window) - { + while (window) { string title; if (WindowValid(window) && GetWindowTitle(window, title)) windows << QString::fromStdString(title); @@ -76,7 +74,7 @@ void GetWindowList(QStringList &windows) } } -void GetCurrentWindowTitle(string& title) +void GetCurrentWindowTitle(string &title) { HWND window = GetForegroundWindow(); DWORD pid; @@ -97,8 +95,7 @@ pair getCursorPos() { pair pos(0, 0); POINT cursorPos; - if (GetPhysicalCursorPos(&cursorPos)) - { + if (GetPhysicalCursorPos(&cursorPos)) { pos.first = cursorPos.x; pos.second = cursorPos.y; } @@ -108,29 +105,28 @@ pair getCursorPos() bool isFullscreen(std::string &title) { RECT appBounds; - RECT rc; + MONITORINFO monitorInfo = {0}; HWND hwnd = GetWindow(GetDesktopWindow(), GW_CHILD); - while (hwnd) - { + while (hwnd) { string wtitle; - if (WindowValid(hwnd) && GetWindowTitle(hwnd, wtitle) && wtitle == title) + if (WindowValid(hwnd) && GetWindowTitle(hwnd, wtitle) && + wtitle == title) break; hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); } - GetWindowRect(GetDesktopWindow(), &rc); - if (hwnd != GetDesktopWindow() && hwnd != GetShellWindow()) - { + monitorInfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), + &monitorInfo); + + if (hwnd && hwnd != GetDesktopWindow() && hwnd != GetShellWindow()) { GetWindowRect(hwnd, &appBounds); - if - ( - rc.bottom == appBounds.bottom - && rc.top == appBounds.top - && rc.left == appBounds.left - && rc.right == appBounds.right - ) { + if (monitorInfo.rcMonitor.bottom == appBounds.bottom && + monitorInfo.rcMonitor.top == appBounds.top && + monitorInfo.rcMonitor.left == appBounds.left && + monitorInfo.rcMonitor.right == appBounds.right) { return true; } } @@ -138,13 +134,15 @@ bool isFullscreen(std::string &title) return false; } -void GetProcessList(QStringList &processes) { +void GetProcessList(QStringList &processes) +{ HANDLE procSnapshot; PROCESSENTRY32 procEntry; procSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (procSnapshot == INVALID_HANDLE_VALUE) return; + if (procSnapshot == INVALID_HANDLE_VALUE) + return; procEntry.dwSize = sizeof(PROCESSENTRY32); @@ -155,9 +153,12 @@ void GetProcessList(QStringList &processes) { do { QString tempexe = QString::fromWCharArray(procEntry.szExeFile); - if (tempexe == "System") continue; - if (tempexe == "[System Process]") continue; - if (processes.contains(tempexe)) continue; + if (tempexe == "System") + continue; + if (tempexe == "[System Process]") + continue; + if (processes.contains(tempexe)) + continue; processes.append(tempexe); } while (Process32Next(procSnapshot, &procEntry)); @@ -172,14 +173,18 @@ bool isInFocus(const QString &executable) DWORD processId = 0; GetWindowThreadProcessId(foregroundWindow, &processId); - HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); - if (process == NULL) return false; + HANDLE process = OpenProcess( + PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); + if (process == NULL) + return false; WCHAR executablePath[600]; GetModuleFileNameEx(process, 0, executablePath, 600); CloseHandle(process); - QString file = QString::fromWCharArray(executablePath).split(QRegularExpression("(/|\\\\)")).back(); + QString file = QString::fromWCharArray(executablePath) + .split(QRegularExpression("(/|\\\\)")) + .back(); // True if executable switch equals current window bool equals = (executable == file); From 2f77d9916173cb199197ee9a6158d0fec86dad76 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 6 Jun 2020 18:51:26 +0200 Subject: [PATCH 37/47] Undo "Revert "do not use QThread::create"" This reverts commit 4b86849356aeec6e45b5a5c9503e1f3a22e93721. --- src/advanced-scene-switcher.cpp | 4 +++- src/headers/switcher-data-structs.hpp | 12 +++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index 57f8c432..df59e982 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -1569,7 +1569,7 @@ void SwitcherData::Start() { if (!(th && th->isRunning())) { stop = false; - switcher->th = QThread::create([]() { switcher->Thread(); }); + switcher->th = new SwitcherThread(); switcher->th->start((QThread::Priority)switcher->threadPriority); } } @@ -1582,6 +1582,8 @@ void SwitcherData::Stop() transitionCv.notify_one(); cv.notify_one(); th->wait(); + delete th; + th = nullptr; } } diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index b10e43af..bcdca7b2 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -253,11 +253,14 @@ struct TimeSwitch { typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch; +class SwitcherThread; + /******************************************************************************** * SwitcherData ********************************************************************************/ struct SwitcherData { - QThread* th = nullptr; + SwitcherThread *th; + condition_variable cv; mutex m; bool transitionActive = false; @@ -482,3 +485,10 @@ struct SwitcherData { } inline ~SwitcherData() { Stop(); } }; + +extern SwitcherData *switcher; +class SwitcherThread : public QThread { +public: + explicit SwitcherThread(){}; + void run() { switcher->Thread(); }; +}; From da2e11e35ebb6fd32bec2a6126e41c53fdf8c691 Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 7 Jun 2020 14:19:23 -0400 Subject: [PATCH 38/47] Resize UI to fit added elements This size is what Qt Designer defaults to when saving --- forms/advanced-scene-switcher.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 28fb264c..f54c3184 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -6,8 +6,8 @@ 0 0 - 492 - 981 + 1010 + 608 From 7458e9f2d53d5d8664761b95319bd96f11540631 Mon Sep 17 00:00:00 2001 From: Myned Date: Sun, 7 Jun 2020 21:08:40 -0400 Subject: [PATCH 39/47] Change and fix a multitude of UI elements Fix spelling Add minimum size Simplify tab names and reorder by type and use Change layout of start, interval, and no-condition selection --- forms/advanced-scene-switcher.ui | 2479 +++++++++++++++--------------- 1 file changed, 1251 insertions(+), 1228 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index f54c3184..4dccbf01 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -6,10 +6,22 @@ 0 0 - 1010 - 608 + 1100 + 600 + + + 0 + 0 + + + + + 1100 + 600 + + Advanced Scene Switcher @@ -27,7 +39,7 @@ - General + General @@ -49,54 +61,105 @@ - - - QFormLayout::ExpandingFieldsGrow - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - + - - - - 0 - 0 - - - - If no switch condition is met - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - + + + - Don't switch - - - true + Start - + + + + Check switch conditions every + + + + + + + Not Active + + + + + + + Advanced Scene Switcher is: + + + + + + + + 100 + 0 + + + + ms + + + 50 + + + 20000 + + + 300 + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 0 + + + + + + + + + + + + Don't switch + + + true + + + + + + + + + + + Switch to any scene in Random tab + + + + + + 0 @@ -132,94 +195,64 @@ - - - - Switch to any Scene on Random Tab - - + + + + + + + 0 + 0 + + + + If no switch condition is met + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + - - - - Check switch conditions every + + + + Qt::Vertical - - - + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + - 100 + 10 0 - - ms - - - 50 - - - 20000 - - - 300 - - + - - - - Advanced Scene Switcher is: - - - - - - - Not Active - - - - - + + Qt::Horizontal - 200 + 40 20 - - - - Start - - - - - - - Qt::Vertical - - - QSizePolicy::Preferred - - - - 20 - 40 - - - - @@ -430,9 +463,522 @@ + + + Transition + + + + + + + + <html><head/><body><p>The settings below only affect scene transitions caused by the scene switcher and not the ones you are causing manually. Additionally they will take priority over transition settings configured elsewhere in the scene switcher.</p></body></html> + + + true + + + + + + + + + Switch from scene + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + to scene + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + using transition + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + true + + + + + + + 4 + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 5 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + When scene + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + is active change default scene transition to + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + true + + + + + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Pause + + + + + + + + Pause the Scene Switcher on scene + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + true + + + + + + + 4 + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Pause the Scene Switcher when + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + true + + + + + + + is in focus + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + true + + + + + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + - Window Title + Title @@ -547,48 +1093,34 @@ 4 - + 22 22 - - - - - - ../../../forms/images/up.svg../../../forms/images/up.svg - true - upArrowIconSmall + addIconSmall - + 22 22 - - - - - - ../../../forms/images/down.svg../../../forms/images/down.svg - true - downArrowIconSmall + removeIconSmall @@ -632,34 +1164,48 @@ - + 22 22 + + + + + + ../../../forms/images/up.svg../../../forms/images/up.svg + true - addIconSmall + upArrowIconSmall - + 22 22 + + + + + + ../../../forms/images/down.svg../../../forms/images/down.svg + true - removeIconSmall + downArrowIconSmall @@ -821,7 +1367,7 @@ ArrowCursor - Executable + Executable @@ -919,6 +1465,77 @@ + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 5 + 20 + + + + @@ -965,77 +1582,6 @@ - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - Qt::Vertical - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - @@ -1062,7 +1608,7 @@ - Screen Region + Region @@ -1319,250 +1865,50 @@ - + - Scene Sequence + Media - + - + - + When - - - - 0 - 0 - - - - - 100 - 0 - - - + - + - is active switch to + state is - - - - 0 - 0 - - - - - 100 - 0 - - - + - + - after + and - + + + + - s - - - 1000000.000000000000000 - - - - - - - using - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - A sequence of automatic scene switches can be cancelled by either pausing/stoping the scene switcher or manually switching to a differnent scene - - - - - - - - 0 - 0 - - - - true - - - - - - - 4 - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 75 - true - - - - SWITCHER CONDITION CHECK INTERVAL LONGER THAN SHORTEST SCENE ROUND TRIP WAIT (This might lead to undesired switching behaviour) - - - - - - - - - - - Save Round Trips to file - - - - - - - Load Round Trips from file - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Idle Detection - - - - - - Enable Idle Detection - - - - - - - - - After - - - - - - - s - - - + ms - 1 + 0 1000000 @@ -1570,27 +1916,14 @@ - + - of no inputs + switch to - - - switch to scene - - - - - - - - 0 - 0 - - + 100 @@ -1600,24 +1933,24 @@ - + using the - + - + transition - + Qt::Horizontal @@ -1632,53 +1965,9 @@ - - - - - Do not switch if - - - - - - - true - - - 20 - - - - - - - is in focus - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - + + + true true @@ -1686,121 +1975,12 @@ - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Pause - - - - - - - - Pause the Scene Switcher on scene - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - true - - - - - + 4 - + 22 @@ -1816,7 +1996,7 @@ - + 22 @@ -1832,7 +2012,7 @@ - + Qt::Horizontal @@ -1844,567 +2024,20 @@ - - - - - - Qt::Horizontal - - - - - - + - Pause the Scene Switcher when + Implemented by Exeldro - - - - - 0 - 0 - - - - - 100 - 0 - - - - true - - - - - - - is in focus - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - true - - - - - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Transitions - - - - - - - - <html><head/><body><p>The settings below only affect scene transitions caused by the scene switcher and not the ones you are causing manually. Additionally they will take priority over transition settings configured elsewhere in the scene switcher.</p></body></html> - - - true - - - - - - - - - Switch from scene - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - to scene - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - using transition - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - true - - - - - - - 4 - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - - - - - Qt::Horizontal - - - - 5 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - - - - Warning: If the Scene Swicher interval is shorter than the duration of your transitions, the options below might lead to scene changes not being completed! (In this case avoid using the options below or increase the scene switcher interval on the general tab) - - - true - - - - - - - - - - - When scene - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - is active change default scene transition to - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - true - - - - - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - Random - - - - - - - - If no switch condition is met switch to - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - using the - - - - - - - - - - transition for a duration of - - - - - - - s - - - 999999999.990000009536743 - - - - - - - or any of the options below: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - true - - - - - - - - - - 22 - 22 - - - - true - - - addIconSmall - - - - - - - - 22 - 22 - - - - true - - - removeIconSmall - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - Write To File / Read From File + File @@ -2670,65 +2303,28 @@ - + - Media + Random - + - + - + - When + If no switch condition is met switch to - - - - - - state is + + + + 0 + 0 + - - - - - - - - - and - - - - - - - - - - ms - - - 0 - - - 1000000 - - - - - - - switch to - - - - - 100 @@ -2738,24 +2334,41 @@ - + using the - + - + - transition + transition for a duration of - + + + s + + + 999999999.990000009536743 + + + + + + + or any of the options below: + + + + + Qt::Horizontal @@ -2770,9 +2383,12 @@ - - - true + + + + 0 + 0 + true @@ -2780,12 +2396,9 @@ - - - 4 - + - + 22 @@ -2801,7 +2414,7 @@ - + 22 @@ -2817,7 +2430,7 @@ - + Qt::Horizontal @@ -2829,20 +2442,13 @@ - - - - Implemented by Exeldro - - - - Time + Time @@ -2974,6 +2580,423 @@ + + + Idle + + + + + + Enable Idle Detection + + + + + + + + + After + + + + + + + s + + + + + + 1 + + + 1000000 + + + + + + + of no inputs + + + + + + + switch to scene + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + using the + + + + + + + + + + transition + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Do not switch if + + + + + + + true + + + 20 + + + + + + + is in focus + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + true + + + + + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Sequence + + + + + + + + When + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + is active switch to + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + + after + + + + + + + s + + + 1000000.000000000000000 + + + + + + + using + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + A sequence of automatic scene switches can be cancelled by either pausing/stopping the scene switcher or manually switching to a different scene + + + + + + + + 0 + 0 + + + + true + + + + + + + 4 + + + + + + 22 + 22 + + + + true + + + addIconSmall + + + + + + + + 22 + 22 + + + + true + + + removeIconSmall + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 75 + true + + + + SWITCHER CONDITION CHECK INTERVAL LONGER THAN SHORTEST SCENE ROUND TRIP WAIT (This might lead to undesired switching behaviour) + + + + + + + + + + + Save Round Trips to file + + + + + + + Load Round Trips from file + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + From 7a924438bce6fca01ade25da04efcb40dbe53183 Mon Sep 17 00:00:00 2001 From: Myned Date: Mon, 8 Jun 2020 14:58:44 -0400 Subject: [PATCH 40/47] Add .clang-format and apply to src/ files --- .clang-format | 107 +++++++++++ src/advanced-scene-switcher.cpp | 23 ++- src/executable-switch.cpp | 98 +++++----- src/file-switch.cpp | 101 +++++------ src/general.cpp | 17 +- src/headers/switcher-data-structs.hpp | 3 +- src/headers/utility.hpp | 8 +- src/hotkey.cpp | 90 +++++----- src/idle-switch.cpp | 101 +++++------ src/linux/advanced-scene-switcher-nix.cpp | 210 +++++++++------------- src/osx/advanced-scene-switcher-osx.mm | 209 ++++++++++----------- src/pause-switch.cpp | 119 ++++++------ src/priority.cpp | 6 +- src/random.cpp | 62 +++---- src/scene-round-trip.cpp | 206 +++++++++++---------- src/scene-transitions.cpp | 151 ++++++++-------- src/screen-region-switch.cpp | 75 ++++---- src/window-title-switch.cpp | 142 +++++++-------- 18 files changed, 863 insertions(+), 865 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..c9dfc48e --- /dev/null +++ b/.clang-format @@ -0,0 +1,107 @@ +# please use clang-format version 8 or later + +Standard: Cpp11 +AccessModifierOffset: -8 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +#AllowAllArgumentsOnNextLine: false # requires clang-format 9 +#AllowAllConstructorInitializersOnNextLine: false # requires clang-format 9 +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +#AllowShortLambdasOnASingleLine: Inline # requires clang-format 9 +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakStringLiterals: false # apparently unpredictable +ColumnLimit: 80 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +FixNamespaceComments: false +ForEachMacros: + - 'json_object_foreach' + - 'json_object_foreach_safe' + - 'json_array_foreach' +IncludeBlocks: Preserve +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 8 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +#ObjCBinPackProtocolList: Auto # requires clang-format 7 +ObjCBlockIndentWidth: 8 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +#SpaceAfterLogicalNot: false # requires clang-format 9 +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +#SpaceBeforeCtorInitializerColon: true # requires clang-format 7 +#SpaceBeforeInheritanceColon: true # requires clang-format 7 +SpaceBeforeParens: ControlStatements +#SpaceBeforeRangeBasedForLoopColon: true # requires clang-format 7 +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +#StatementMacros: # requires clang-format 8 +# - 'Q_OBJECT' +TabWidth: 8 +#TypenameMacros: # requires clang-format 9 +# - 'DARRAY' +UseTab: ForContinuationAndIndentation +--- +Language: ObjC diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index df59e982..37b7dbc0 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -159,9 +159,10 @@ SceneSwitcher::SceneSwitcher(QWidget *parent) for (auto &s : switcher->windowSwitches) { string sceneName = GetWeakSourceName(s.scene); string transitionName = GetWeakSourceName(s.transition); - QString text = - MakeSwitchName(sceneName.c_str(), s.window.c_str(), - transitionName.c_str(), s.fullscreen, s.focus); + QString text = MakeSwitchName(sceneName.c_str(), + s.window.c_str(), + transitionName.c_str(), + s.fullscreen, s.focus); QListWidgetItem *item = new QListWidgetItem(text, ui->switches); item->setData(Qt::UserRole, s.window.c_str()); @@ -461,9 +462,8 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) obs_data_set_string(array_obj, "window_title", s.window.c_str()); obs_data_set_bool(array_obj, "fullscreen", - s.fullscreen); - obs_data_set_bool(array_obj, "focus", - s.focus); + s.fullscreen); + obs_data_set_bool(array_obj, "focus", s.focus); obs_data_array_push_back(array, array_obj); obs_source_release(source); obs_source_release(transition); @@ -979,13 +979,12 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) bool fullscreen = obs_data_get_bool(array_obj, "fullscreen"); bool focus = - obs_data_get_bool(array_obj, "focus") - || !obs_data_has_user_value(array_obj, "focus"); + obs_data_get_bool(array_obj, "focus") || + !obs_data_has_user_value(array_obj, "focus"); switcher->windowSwitches.emplace_back( GetWeakSourceByName(scene), window, - GetWeakTransitionByName(transition), - fullscreen, + GetWeakTransitionByName(transition), fullscreen, focus); obs_data_release(array_obj); @@ -1570,11 +1569,11 @@ void SwitcherData::Start() if (!(th && th->isRunning())) { stop = false; switcher->th = new SwitcherThread(); - switcher->th->start((QThread::Priority)switcher->threadPriority); + switcher->th->start( + (QThread::Priority)switcher->threadPriority); } } - void SwitcherData::Stop() { if (th && th->isRunning()) { diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index d05ba3e7..7b345a35 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -1,12 +1,11 @@ #include "headers/advanced-scene-switcher.hpp" -int SceneSwitcher::executableFindByData(const QString& exe) +int SceneSwitcher::executableFindByData(const QString &exe) { int count = ui->executables->count(); - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->executables->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->executables->item(i); QString itemExe = item->data(Qt::UserRole).toString(); if (itemExe == exe) @@ -23,20 +22,20 @@ void SceneSwitcher::on_executables_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->executables->item(idx); + QListWidgetItem *item = ui->executables->item(idx); QString exec = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->executableSwitches) - { - if (exec.compare(s.mExe) == 0) - { + for (auto &s : switcher->executableSwitches) { + if (exec.compare(s.mExe) == 0) { QString sceneName = GetWeakSourceName(s.mScene).c_str(); - QString transitionName = GetWeakSourceName(s.mTransition).c_str(); + QString transitionName = + GetWeakSourceName(s.mTransition).c_str(); ui->executableScenes->setCurrentText(sceneName); ui->executable->setCurrentText(exec); - ui->executableTransitions->setCurrentText(transitionName); + ui->executableTransitions->setCurrentText( + transitionName); ui->requiresFocusCheckBox->setChecked(s.mInFocus); break; } @@ -46,30 +45,30 @@ void SceneSwitcher::on_executables_currentRowChanged(int idx) void SceneSwitcher::on_executableUp_clicked() { int index = ui->executables->currentRow(); - if (index != -1 && index != 0) - { - ui->executables->insertItem(index - 1, ui->executables->takeItem(index)); + if (index != -1 && index != 0) { + ui->executables->insertItem(index - 1, + ui->executables->takeItem(index)); ui->executables->setCurrentRow(index - 1); lock_guard lock(switcher->m); iter_swap(switcher->executableSwitches.begin() + index, - switcher->executableSwitches.begin() + index - 1); + switcher->executableSwitches.begin() + index - 1); } } void SceneSwitcher::on_executableDown_clicked() { int index = ui->executables->currentRow(); - if (index != -1 && index != ui->executables->count() - 1) - { - ui->executables->insertItem(index + 1, ui->executables->takeItem(index)); + if (index != -1 && index != ui->executables->count() - 1) { + ui->executables->insertItem(index + 1, + ui->executables->takeItem(index)); ui->executables->setCurrentRow(index + 1); lock_guard lock(switcher->m); iter_swap(switcher->executableSwitches.begin() + index, - switcher->executableSwitches.begin() + index + 1); + switcher->executableSwitches.begin() + index + 1); } } @@ -87,30 +86,28 @@ void SceneSwitcher::on_executableAdd_clicked() OBSWeakSource transition = GetWeakTransitionByQString(transitionName); QVariant v = QVariant::fromValue(exeName); - QString text = MakeSwitchNameExecutable(sceneName, exeName, transitionName, inFocus); + QString text = MakeSwitchNameExecutable(sceneName, exeName, + transitionName, inFocus); int idx = executableFindByData(exeName); - if (idx == -1) - { + if (idx == -1) { lock_guard lock(switcher->m); switcher->executableSwitches.emplace_back( - source, transition, exeName.toUtf8().constData(), inFocus); + source, transition, exeName.toUtf8().constData(), + inFocus); - QListWidgetItem* item = new QListWidgetItem(text, ui->executables); + QListWidgetItem *item = + new QListWidgetItem(text, ui->executables); item->setData(Qt::UserRole, v); - } - else - { - QListWidgetItem* item = ui->executables->item(idx); + } else { + QListWidgetItem *item = ui->executables->item(idx); item->setText(text); { lock_guard lock(switcher->m); - for (auto& s : switcher->executableSwitches) - { - if (s.mExe == exeName) - { + for (auto &s : switcher->executableSwitches) { + if (s.mExe == exeName) { s.mScene = source; s.mTransition = transition; s.mInFocus = inFocus; @@ -123,7 +120,7 @@ void SceneSwitcher::on_executableAdd_clicked() void SceneSwitcher::on_executableRemove_clicked() { - QListWidgetItem* item = ui->executables->currentItem(); + QListWidgetItem *item = ui->executables->currentItem(); if (!item) return; @@ -131,14 +128,12 @@ void SceneSwitcher::on_executableRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->executableSwitches; + auto &switches = switcher->executableSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s.mExe == exe) - { + if (s.mExe == exe) { switches.erase(it); break; } @@ -148,7 +143,8 @@ void SceneSwitcher::on_executableRemove_clicked() delete item; } -void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) +void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition) { string title; QStringList runningProcesses; @@ -156,15 +152,14 @@ void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSour // Check if current window is ignored GetCurrentWindowTitle(title); - for (auto& window : ignoreWindowsSwitches) - { + for (auto &window : ignoreWindowsSwitches) { // True if ignored switch equals title bool equals = (title == window); // True if ignored switch matches title - bool matches = QString::fromStdString(title).contains(QRegularExpression(window.c_str())); + bool matches = QString::fromStdString(title).contains( + QRegularExpression(window.c_str())); - if (equals || matches) - { + if (equals || matches) { ignored = true; title = lastTitle; @@ -175,19 +170,20 @@ void SwitcherData::checkExeSwitch(bool& match, OBSWeakSource& scene, OBSWeakSour // Check for match GetProcessList(runningProcesses); - for (ExecutableSceneSwitch& s : executableSwitches) - { + for (ExecutableSceneSwitch &s : executableSwitches) { // True if executable switch is running (direct) bool equals = runningProcesses.contains(s.mExe); // True if executable switch is running (regex) - bool matches = (runningProcesses.indexOf(QRegularExpression(s.mExe)) != -1); + bool matches = (runningProcesses.indexOf( + QRegularExpression(s.mExe)) != -1); // True if focus is disabled OR switch is focused bool focus = (!s.mInFocus || isInFocus(s.mExe)); // True if current window is ignored AND switch matches last window - bool ignore = (ignored && QString::fromStdString(title).contains(QRegularExpression(s.mExe))); + bool ignore = + (ignored && QString::fromStdString(title).contains( + QRegularExpression(s.mExe))); - if ((equals || matches) && (focus || ignore)) - { + if ((equals || matches) && (focus || ignore)) { match = true; scene = s.mScene; transition = s.mTransition; diff --git a/src/file-switch.cpp b/src/file-switch.cpp index 909452ca..3d4c4545 100644 --- a/src/file-switch.cpp +++ b/src/file-switch.cpp @@ -4,12 +4,11 @@ #include #include "headers/advanced-scene-switcher.hpp" - - void SceneSwitcher::on_browseButton_clicked() { QString path = QFileDialog::getOpenFileName( - this, tr("Select a file to write to ..."), QDir::currentPath(), tr("Text files (*.txt)")); + this, tr("Select a file to write to ..."), QDir::currentPath(), + tr("Text files (*.txt)")); if (!path.isEmpty()) ui->writePathLineEdit->setText(path); } @@ -20,28 +19,24 @@ void SceneSwitcher::on_readFileCheckBox_stateChanged(int state) return; lock_guard lock(switcher->m); - if (!state) - { + if (!state) { ui->browseButton_2->setDisabled(true); ui->readPathLineEdit->setDisabled(true); switcher->fileIO.readEnabled = false; - } - else - { + } else { ui->browseButton_2->setDisabled(false); ui->readPathLineEdit->setDisabled(false); switcher->fileIO.readEnabled = true; } } -void SceneSwitcher::on_readPathLineEdit_textChanged(const QString& text) +void SceneSwitcher::on_readPathLineEdit_textChanged(const QString &text) { if (loading) return; lock_guard lock(switcher->m); - if (text.isEmpty()) - { + if (text.isEmpty()) { switcher->fileIO.readEnabled = false; return; } @@ -49,14 +44,13 @@ void SceneSwitcher::on_readPathLineEdit_textChanged(const QString& text) switcher->fileIO.readPath = text.toUtf8().constData(); } -void SceneSwitcher::on_writePathLineEdit_textChanged(const QString& text) +void SceneSwitcher::on_writePathLineEdit_textChanged(const QString &text) { if (loading) return; lock_guard lock(switcher->m); - if (text.isEmpty()) - { + if (text.isEmpty()) { switcher->fileIO.writeEnabled = false; return; } @@ -67,7 +61,8 @@ void SceneSwitcher::on_writePathLineEdit_textChanged(const QString& text) void SceneSwitcher::on_browseButton_2_clicked() { QString path = QFileDialog::getOpenFileName( - this, tr("Select a file to read from ..."), QDir::currentPath(), tr("Any files (*.*)")); + this, tr("Select a file to read from ..."), QDir::currentPath(), + tr("Any files (*.*)")); if (!path.isEmpty()) ui->readPathLineEdit->setText(path); } @@ -77,31 +72,32 @@ void SwitcherData::writeSceneInfoToFile() if (!fileIO.writeEnabled || fileIO.writePath.empty()) return; - obs_source_t* currentSource = obs_frontend_get_current_scene(); + obs_source_t *currentSource = obs_frontend_get_current_scene(); QFile file(QString::fromStdString(fileIO.writePath)); - if (file.open(QIODevice::WriteOnly)) - { - const char* msg = obs_source_get_name(currentSource); + if (file.open(QIODevice::WriteOnly)) { + const char *msg = obs_source_get_name(currentSource); file.write(msg, qstrlen(msg)); file.close(); } obs_source_release(currentSource); } -void SwitcherData::checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) +void SwitcherData::checkSwitchInfoFromFile(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition) { if (!fileIO.readEnabled || fileIO.readPath.empty()) return; QFile file(QString::fromStdString(fileIO.readPath)); - if (file.open(QIODevice::ReadOnly)) - { + if (file.open(QIODevice::ReadOnly)) { QTextStream in(&file); QString sceneStr = in.readLine(); - obs_source_t* sceneRead = obs_get_source_by_name(sceneStr.toUtf8().constData()); - if (sceneRead){ - obs_weak_source_t* sceneReadWs = obs_source_get_weak_source(sceneRead); + obs_source_t *sceneRead = + obs_get_source_by_name(sceneStr.toUtf8().constData()); + if (sceneRead) { + obs_weak_source_t *sceneReadWs = + obs_source_get_weak_source(sceneRead); match = true; scene = sceneReadWs; @@ -114,32 +110,28 @@ void SwitcherData::checkSwitchInfoFromFile(bool& match, OBSWeakSource& scene, OB } } -void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) +void SwitcherData::checkFileContent(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition) { - for (FileSwitch& s : fileSwitches) - { + for (FileSwitch &s : fileSwitches) { bool equal = false; QString t = QString::fromStdString(s.text); QFile file(QString::fromStdString(s.file)); if (!file.open(QIODevice::ReadOnly)) continue; - if (s.useTime) - { + if (s.useTime) { QDateTime newLastMod = QFileInfo(file).lastModified(); if (s.lastMod == newLastMod) continue; s.lastMod = newLastMod; } - - if (s.useRegex) - { + + if (s.useRegex) { QTextStream in(&file); QRegExp rx(t); equal = rx.exactMatch(in.readAll()); - } - else - { + } else { /*Im using QTextStream here so the conversion between different lineendings is done by QT. *QT itself uses only the linefeed internally so the input by the user is always using that, *but the files selected by the user might use different line endings. @@ -147,24 +139,21 @@ void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSo */ QTextStream in(&file); QTextStream text(&t); - while (!in.atEnd() && !text.atEnd()) - { + while (!in.atEnd() && !text.atEnd()) { QString fileLine = in.readLine(); QString textLine = text.readLine(); - if (QString::compare(fileLine, textLine, Qt::CaseSensitive) != 0) - { + if (QString::compare(fileLine, textLine, + Qt::CaseSensitive) != 0) { equal = false; break; - } - else { + } else { equal = true; } } } file.close(); - if (equal) - { + if (equal) { scene = s.scene; transition = s.transition; match = true; @@ -177,7 +166,8 @@ void SwitcherData::checkFileContent(bool& match, OBSWeakSource& scene, OBSWeakSo void SceneSwitcher::on_browseButton_3_clicked() { QString path = QFileDialog::getOpenFileName( - this, tr("Select a file to read from ..."), QDir::currentPath(), tr("Any files (*.*)")); + this, tr("Select a file to read from ..."), QDir::currentPath(), + tr("Any files (*.*)")); if (!path.isEmpty()) ui->filePathLineEdit->setText(path); } @@ -191,28 +181,31 @@ void SceneSwitcher::on_fileAdd_clicked() bool useRegex = ui->fileContentRegExCheckBox->isChecked(); bool useTime = ui->fileContentTimeCheckBox->isChecked(); - if (sceneName.isEmpty() || transitionName.isEmpty() || fileName.isEmpty() || text.isEmpty()) + if (sceneName.isEmpty() || transitionName.isEmpty() || + fileName.isEmpty() || text.isEmpty()) return; OBSWeakSource source = GetWeakSourceByQString(sceneName); OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - QString switchText = MakeFileSwitchName(sceneName, transitionName, fileName, text, useRegex, useTime); + QString switchText = MakeFileSwitchName( + sceneName, transitionName, fileName, text, useRegex, useTime); QVariant v = QVariant::fromValue(switchText); - - QListWidgetItem* item = new QListWidgetItem(switchText, ui->fileScenesList); + QListWidgetItem *item = + new QListWidgetItem(switchText, ui->fileScenesList); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); - switcher->fileSwitches.emplace_back( - source, transition, fileName.toUtf8().constData(), text.toUtf8().constData(), useRegex, useTime); - + switcher->fileSwitches.emplace_back(source, transition, + fileName.toUtf8().constData(), + text.toUtf8().constData(), useRegex, + useTime); } void SceneSwitcher::on_fileRemove_clicked() { - QListWidgetItem* item = ui->fileScenesList->currentItem(); + QListWidgetItem *item = ui->fileScenesList->currentItem(); if (!item) return; @@ -223,7 +216,7 @@ void SceneSwitcher::on_fileRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->fileSwitches; + auto &switches = switcher->fileSwitches; switches.erase(switches.begin() + idx); } qDeleteAll(ui->fileScenesList->selectedItems()); diff --git a/src/general.cpp b/src/general.cpp index 9bc85203..25e22cff 100644 --- a/src/general.cpp +++ b/src/general.cpp @@ -15,10 +15,10 @@ void SceneSwitcher::on_startAtLaunch_toggled(bool value) switcher->startAtLaunch = value; } -void SceneSwitcher::UpdateNonMatchingScene(const QString& name) +void SceneSwitcher::UpdateNonMatchingScene(const QString &name) { - obs_source_t* scene = obs_get_source_by_name(name.toUtf8().constData()); - obs_weak_source_t* ws = obs_source_get_weak_source(scene); + obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData()); + obs_weak_source_t *ws = obs_source_get_weak_source(scene); switcher->nonMatchingScene = ws; @@ -57,7 +57,7 @@ void SceneSwitcher::on_noMatchRandomSwitch_clicked() ui->noMatchSwitchScene->setEnabled(false); } -void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(const QString& text) +void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(const QString &text) { if (loading) return; @@ -89,19 +89,16 @@ void SceneSwitcher::SetStopped() void SceneSwitcher::on_toggleStartButton_clicked() { - if (switcher->th && switcher->th->isRunning()) - { + if (switcher->th && switcher->th->isRunning()) { switcher->Stop(); SetStopped(); - } - else - { + } else { switcher->Start(); SetStarted(); } } -void SceneSwitcher::closeEvent(QCloseEvent*) +void SceneSwitcher::closeEvent(QCloseEvent *) { obs_frontend_save(); } diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index 652d55fb..0782a25c 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -47,7 +47,8 @@ struct WindowSceneSwitch { bool focus; inline WindowSceneSwitch(OBSWeakSource scene_, const char *window_, - OBSWeakSource transition_, bool fullscreen_, bool focus_) + OBSWeakSource transition_, bool fullscreen_, + bool focus_) : scene(scene_), window(window_), transition(transition_), diff --git a/src/headers/utility.hpp b/src/headers/utility.hpp index bd8987a0..95fb644f 100644 --- a/src/headers/utility.hpp +++ b/src/headers/utility.hpp @@ -14,13 +14,13 @@ static inline bool WeakSourceValid(obs_weak_source_t *ws) } static inline QString MakeSwitchName(const QString &scene, const QString &value, - const QString &transition, bool fullscreen, bool focus) + const QString &transition, bool fullscreen, + bool focus) { QString name = QStringLiteral("[") + scene + QStringLiteral(", ") + - transition + QStringLiteral("]: ") + value; + transition + QStringLiteral("]: ") + value; - if (fullscreen || focus) - { + if (fullscreen || focus) { name += QStringLiteral(" (only if"); if (fullscreen) diff --git a/src/hotkey.cpp b/src/hotkey.cpp index f95b5773..6ca4f7d8 100644 --- a/src/hotkey.cpp +++ b/src/hotkey.cpp @@ -1,30 +1,29 @@ #include #include "headers/advanced-scene-switcher.hpp" -void startHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed) +void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, + bool pressed) { UNUSED_PARAMETER(data); UNUSED_PARAMETER(hotkey); - if (pressed) - { + if (pressed) { if (!(switcher->th && switcher->th->isRunning())) switcher->Start(); } - obs_data_array* hotkeyData = obs_hotkey_save(id); + obs_data_array *hotkeyData = obs_hotkey_save(id); - if (hotkeyData != NULL) - { - char* path = obs_module_config_path(""); + if (hotkeyData != NULL) { + char *path = obs_module_config_path(""); ofstream file; - file.open(string(path).append(START_HOTKEY_PATH), ofstream::trunc); - if (file.is_open()) - { + file.open(string(path).append(START_HOTKEY_PATH), + ofstream::trunc); + if (file.is_open()) { size_t num = obs_data_array_count(hotkeyData); - for (size_t i = 0; i < num; i++) - { - obs_data_t* data = obs_data_array_item(hotkeyData, i); + for (size_t i = 0; i < num; i++) { + obs_data_t *data = + obs_data_array_item(hotkeyData, i); string temp = obs_data_get_json(data); obs_data_release(data); file << temp; @@ -36,30 +35,29 @@ void startHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pr obs_data_array_release(hotkeyData); } -void stopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed) +void stopHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, + bool pressed) { UNUSED_PARAMETER(data); UNUSED_PARAMETER(hotkey); - if (pressed) - { + if (pressed) { if (switcher->th && switcher->th->isRunning()) switcher->Stop(); } - obs_data_array* hotkeyData = obs_hotkey_save(id); + obs_data_array *hotkeyData = obs_hotkey_save(id); - if (hotkeyData != NULL) - { - char* path = obs_module_config_path(""); + if (hotkeyData != NULL) { + char *path = obs_module_config_path(""); ofstream file; - file.open(string(path).append(STOP_HOTKEY_PATH), ofstream::trunc); - if (file.is_open()) - { + file.open(string(path).append(STOP_HOTKEY_PATH), + ofstream::trunc); + if (file.is_open()) { size_t num = obs_data_array_count(hotkeyData); - for (size_t i = 0; i < num; i++) - { - obs_data_t* data = obs_data_array_item(hotkeyData, i); + for (size_t i = 0; i < num; i++) { + obs_data_t *data = + obs_data_array_item(hotkeyData, i); string temp = obs_data_get_json(data); obs_data_release(data); file << temp; @@ -71,32 +69,31 @@ void stopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pre obs_data_array_release(hotkeyData); } -void startStopToggleHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pressed) +void startStopToggleHotkeyFunc(void *data, obs_hotkey_id id, + obs_hotkey_t *hotkey, bool pressed) { UNUSED_PARAMETER(data); UNUSED_PARAMETER(hotkey); - if (pressed) - { + if (pressed) { if (switcher->th && switcher->th->isRunning()) switcher->Stop(); else switcher->Start(); } - obs_data_array* hotkeyData = obs_hotkey_save(id); + obs_data_array *hotkeyData = obs_hotkey_save(id); - if (hotkeyData != NULL) - { - char* path = obs_module_config_path(""); + if (hotkeyData != NULL) { + char *path = obs_module_config_path(""); ofstream file; - file.open(string(path).append(TOGGLE_HOTKEY_PATH), ofstream::trunc); - if (file.is_open()) - { + file.open(string(path).append(TOGGLE_HOTKEY_PATH), + ofstream::trunc); + if (file.is_open()) { size_t num = obs_data_array_count(hotkeyData); - for (size_t i = 0; i < num; i++) - { - obs_data_t* data = obs_data_array_item(hotkeyData, i); + for (size_t i = 0; i < num; i++) { + obs_data_t *data = + obs_data_array_item(hotkeyData, i); string temp = obs_data_get_json(data); obs_data_release(data); file << temp; @@ -111,16 +108,16 @@ void startStopToggleHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotke string loadConfigFile(string filename) { ifstream settingsFile; - char* path = obs_module_config_path(""); + char *path = obs_module_config_path(""); string value; settingsFile.open(string(path).append(filename)); - if (settingsFile.is_open()) - { + if (settingsFile.is_open()) { settingsFile.seekg(0, ios::end); value.reserve(settingsFile.tellg()); settingsFile.seekg(0, ios::beg); - value.assign((istreambuf_iterator(settingsFile)), istreambuf_iterator()); + value.assign((istreambuf_iterator(settingsFile)), + istreambuf_iterator()); settingsFile.close(); } bfree(path); @@ -130,10 +127,9 @@ string loadConfigFile(string filename) void loadKeybinding(obs_hotkey_id hotkeyId, string path) { string bindings = loadConfigFile(path); - if (!bindings.empty()) - { - obs_data_array_t* hotkeyData = obs_data_array_create(); - obs_data_t* data = obs_data_create_from_json(bindings.c_str()); + if (!bindings.empty()) { + obs_data_array_t *hotkeyData = obs_data_array_create(); + obs_data_t *data = obs_data_create_from_json(bindings.c_str()); obs_data_array_insert(hotkeyData, 0, data); obs_data_release(data); obs_hotkey_load(hotkeyId, hotkeyData); diff --git a/src/idle-switch.cpp b/src/idle-switch.cpp index 371d2a23..1f20fc64 100644 --- a/src/idle-switch.cpp +++ b/src/idle-switch.cpp @@ -1,6 +1,7 @@ #include "headers/advanced-scene-switcher.hpp" -void SwitcherData::checkIdleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) +void SwitcherData::checkIdleSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition) { if (!idleData.idleEnable) return; @@ -11,44 +12,36 @@ void SwitcherData::checkIdleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSou GetCurrentWindowTitle(title); //lock.lock(); - for (string& window : ignoreIdleWindows) - { - if (window == title) - { + for (string &window : ignoreIdleWindows) { + if (window == title) { ignoreIdle = true; break; } } - if (!ignoreIdle) - { - for (string& window : ignoreIdleWindows) - { - try - { - bool matches = regex_match(title, regex(window)); - if (matches) - { + if (!ignoreIdle) { + for (string &window : ignoreIdleWindows) { + try { + bool matches = + regex_match(title, regex(window)); + if (matches) { ignoreIdle = true; break; } - } - catch (const regex_error&) - { + } catch (const regex_error &) { } } } - if (!ignoreIdle && secondsSinceLastInput() > idleData.time) - { + if (!ignoreIdle && secondsSinceLastInput() > idleData.time) { if (idleData.alreadySwitched) return; - scene = (idleData.usePreviousScene) ? previousScene : idleData.scene; + scene = (idleData.usePreviousScene) ? previousScene + : idleData.scene; transition = idleData.transition; match = true; idleData.alreadySwitched = true; - } - else + } else idleData.alreadySwitched = false; } @@ -58,16 +51,13 @@ void SceneSwitcher::on_idleCheckBox_stateChanged(int state) return; lock_guard lock(switcher->m); - if (!state) - { + if (!state) { ui->idleScenes->setDisabled(true); ui->idleSpinBox->setDisabled(true); ui->idleTransitions->setDisabled(true); switcher->idleData.idleEnable = false; - } - else - { + } else { ui->idleScenes->setDisabled(false); ui->idleSpinBox->setDisabled(false); ui->idleTransitions->setDisabled(false); @@ -79,18 +69,17 @@ void SceneSwitcher::on_idleCheckBox_stateChanged(int state) } } - -void SceneSwitcher::UpdateIdleDataTransition(const QString& name) +void SceneSwitcher::UpdateIdleDataTransition(const QString &name) { - obs_weak_source_t* transition = GetWeakTransitionByQString(name); + obs_weak_source_t *transition = GetWeakTransitionByQString(name); switcher->idleData.transition = transition; } -void SceneSwitcher::UpdateIdleDataScene(const QString& name) +void SceneSwitcher::UpdateIdleDataScene(const QString &name) { switcher->idleData.usePreviousScene = (name == PREVIOUS_SCENE_NAME); - obs_source_t* scene = obs_get_source_by_name(name.toUtf8().constData()); - obs_weak_source_t* ws = obs_source_get_weak_source(scene); + obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData()); + obs_weak_source_t *ws = obs_source_get_weak_source(scene); switcher->idleData.scene = ws; @@ -98,7 +87,7 @@ void SceneSwitcher::UpdateIdleDataScene(const QString& name) obs_source_release(scene); } -void SceneSwitcher::on_idleTransitions_currentTextChanged(const QString& text) +void SceneSwitcher::on_idleTransitions_currentTextChanged(const QString &text) { if (loading) return; @@ -107,7 +96,7 @@ void SceneSwitcher::on_idleTransitions_currentTextChanged(const QString& text) UpdateIdleDataTransition(text); } -void SceneSwitcher::on_idleScenes_currentTextChanged(const QString& text) +void SceneSwitcher::on_idleScenes_currentTextChanged(const QString &text) { if (loading) return; @@ -131,15 +120,13 @@ void SceneSwitcher::on_ignoreIdleWindows_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->ignoreIdleWindows->item(idx); + QListWidgetItem *item = ui->ignoreIdleWindows->item(idx); QString window = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& w : switcher->ignoreIdleWindows) - { - if (window.compare(w.c_str()) == 0) - { + for (auto &w : switcher->ignoreIdleWindows) { + if (window.compare(w.c_str()) == 0) { ui->ignoreIdleWindowsWindows->setCurrentText(w.c_str()); break; } @@ -155,22 +142,24 @@ void SceneSwitcher::on_ignoreIdleAdd_clicked() QVariant v = QVariant::fromValue(windowName); - QList items = ui->ignoreIdleWindows->findItems(windowName, Qt::MatchExactly); + QList items = + ui->ignoreIdleWindows->findItems(windowName, Qt::MatchExactly); - if (items.size() == 0) - { - QListWidgetItem* item = new QListWidgetItem(windowName, ui->ignoreIdleWindows); + if (items.size() == 0) { + QListWidgetItem *item = + new QListWidgetItem(windowName, ui->ignoreIdleWindows); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); - switcher->ignoreIdleWindows.emplace_back(windowName.toUtf8().constData()); + switcher->ignoreIdleWindows.emplace_back( + windowName.toUtf8().constData()); ui->ignoreIdleWindows->sortItems(); } } void SceneSwitcher::on_ignoreIdleRemove_clicked() { - QListWidgetItem* item = ui->ignoreIdleWindows->currentItem(); + QListWidgetItem *item = ui->ignoreIdleWindows->currentItem(); if (!item) return; @@ -178,14 +167,12 @@ void SceneSwitcher::on_ignoreIdleRemove_clicked() { lock_guard lock(switcher->m); - auto& windows = switcher->ignoreIdleWindows; + auto &windows = switcher->ignoreIdleWindows; - for (auto it = windows.begin(); it != windows.end(); ++it) - { - auto& s = *it; + for (auto it = windows.begin(); it != windows.end(); ++it) { + auto &s = *it; - if (s == windowName.toUtf8().constData()) - { + if (s == windowName.toUtf8().constData()) { windows.erase(it); break; } @@ -195,18 +182,16 @@ void SceneSwitcher::on_ignoreIdleRemove_clicked() delete item; } -int SceneSwitcher::IgnoreIdleWindowsFindByData(const QString& window) +int SceneSwitcher::IgnoreIdleWindowsFindByData(const QString &window) { int count = ui->ignoreIdleWindows->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->ignoreIdleWindows->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->ignoreIdleWindows->item(i); QString itemRegion = item->data(Qt::UserRole).toString(); - if (itemRegion == window) - { + if (itemRegion == window) { idx = i; break; } diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index e124e5b4..2fc9b261 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -18,7 +18,7 @@ using namespace std; -static Display* xdisplay = 0; +static Display *xdisplay = 0; Display *disp() { @@ -40,31 +40,22 @@ void cleanupDisplay() static bool ewmhIsSupported() { Display *display = disp(); - Atom netSupportingWmCheck = XInternAtom(display, - "_NET_SUPPORTING_WM_CHECK", true); + Atom netSupportingWmCheck = + XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", true); Atom actualType; int format = 0; unsigned long num = 0, bytes = 0; unsigned char *data = NULL; Window ewmh_window = 0; - int status = XGetWindowProperty( - display, - DefaultRootWindow(display), - netSupportingWmCheck, - 0L, - 1L, - false, - XA_WINDOW, - &actualType, - &format, - &num, - &bytes, - &data); + int status = XGetWindowProperty(display, DefaultRootWindow(display), + netSupportingWmCheck, 0L, 1L, false, + XA_WINDOW, &actualType, &format, &num, + &bytes, &data); if (status == Success) { if (num > 0) { - ewmh_window = ((Window*)data)[0]; + ewmh_window = ((Window *)data)[0]; } if (data) { XFree(data); @@ -73,21 +64,12 @@ static bool ewmhIsSupported() } if (ewmh_window) { - status = XGetWindowProperty( - display, - ewmh_window, - netSupportingWmCheck, - 0L, - 1L, - false, - XA_WINDOW, - &actualType, - &format, - &num, - &bytes, - &data); + status = XGetWindowProperty(display, ewmh_window, + netSupportingWmCheck, 0L, 1L, false, + XA_WINDOW, &actualType, &format, + &num, &bytes, &data); if (status != Success || num == 0 || - ewmh_window != ((Window*)data)[0]) { + ewmh_window != ((Window *)data)[0]) { ewmh_window = 0; } if (status == Success && data) { @@ -98,35 +80,26 @@ static bool ewmhIsSupported() return ewmh_window != 0; } -static QStringList getStates(Window window) { +static QStringList getStates(Window window) +{ QStringList states; if (!ewmhIsSupported()) return states; Atom wmState = XInternAtom(disp(), "_NET_WM_STATE", true), type; - int format; - unsigned long num, bytes; - unsigned char *data; + int format; + unsigned long num, bytes; + unsigned char *data; - int status = XGetWindowProperty( - disp(), - window, - wmState, - 0, - ~0L, - false, - AnyPropertyType, - &type, - &format, - &num, - &bytes, - &data - ); + int status = XGetWindowProperty(disp(), window, wmState, 0, ~0L, false, + AnyPropertyType, &type, &format, &num, + &bytes, &data); if (status == Success) for (unsigned long i = 0; i < num; i++) - states.append(QString(XGetAtomName(disp(), ((Atom*)data)[i]))); + states.append(QString( + XGetAtomName(disp(), ((Atom *)data)[i]))); return states; } @@ -145,24 +118,15 @@ static std::vector getTopLevelWindows() Atom actualType; int format; unsigned long num, bytes; - Window* data = 0; + Window *data = 0; for (int i = 0; i < ScreenCount(disp()); ++i) { Window rootWin = RootWindow(disp(), i); - int status = XGetWindowProperty( - disp(), - rootWin, - netClList, - 0L, - ~0L, - false, - AnyPropertyType, - &actualType, - &format, - &num, - &bytes, - (uint8_t**)&data); + int status = XGetWindowProperty(disp(), rootWin, netClList, 0L, + ~0L, false, AnyPropertyType, + &actualType, &format, &num, + &bytes, (uint8_t **)&data); if (status != Success) { continue; @@ -181,16 +145,17 @@ static std::string GetWindowTitle(size_t i) { Window w = getTopLevelWindows().at(i); std::string windowTitle; - char* name; + char *name; XTextProperty text; - int status = XGetTextProperty(disp(), w, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); + int status = XGetTextProperty( + disp(), w, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); if (status == 0) - status = XGetTextProperty(disp(), w, &text, XInternAtom(disp(), "WM_NAME", true)); - name = reinterpret_cast(text.value); + status = XGetTextProperty(disp(), w, &text, + XInternAtom(disp(), "WM_NAME", true)); + name = reinterpret_cast(text.value); - if (status != 0 && name != nullptr) - { + if (status != 0 && name != nullptr) { std::string str(name); windowTitle = str; XFree(name); @@ -203,7 +168,7 @@ void GetWindowList(vector &windows) { windows.resize(0); - for (size_t i = 0; i < getTopLevelWindows().size(); ++i){ + for (size_t i = 0; i < getTopLevelWindows().size(); ++i) { if (GetWindowTitle(i) != "") windows.emplace_back(GetWindowTitle(i)); } @@ -214,7 +179,7 @@ void GetWindowList(QStringList &windows) { windows.clear(); - for (size_t i = 0; i < getTopLevelWindows().size(); ++i){ + for (size_t i = 0; i < getTopLevelWindows().size(); ++i) { if (GetWindowTitle(i) != "") windows << QString::fromStdString(GetWindowTitle(i)); } @@ -230,33 +195,28 @@ void GetCurrentWindowTitle(string &title) Atom actualType; int format; unsigned long num, bytes; - Window* data = 0; - char* name; + Window *data = 0; + char *name; Window rootWin = RootWindow(disp(), 0); - int xstatus = XGetWindowProperty( - disp(), - rootWin, - active, - 0L, - ~0L, - false, - AnyPropertyType, - &actualType, - &format, - &num, - &bytes, - (uint8_t**)&data); + int xstatus = XGetWindowProperty(disp(), rootWin, active, 0L, ~0L, + false, AnyPropertyType, &actualType, + &format, &num, &bytes, + (uint8_t **)&data); int status = 0; XTextProperty text; if (xstatus == Success) { - status = XGetTextProperty(disp(), data[0], &text, XInternAtom(disp(), "_NET_WM_NAME", true)); + status = XGetTextProperty(disp(), data[0], &text, + XInternAtom(disp(), "_NET_WM_NAME", + true)); if (status == 0) - status = XGetTextProperty(disp(), data[0], &text, XInternAtom(disp(), "WM_NAME", true)); + status = XGetTextProperty(disp(), data[0], &text, + XInternAtom(disp(), "WM_NAME", + true)); } - name = reinterpret_cast(text.value); + name = reinterpret_cast(text.value); if (status != 0 && name != nullptr) { std::string str(name); @@ -281,10 +241,9 @@ pair getCursorPos() dpy = XOpenDisplay(NULL); root = XDefaultRootWindow(dpy); - if(XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y, - &win_x, &win_y, &mask)) - { - pos = pair (root_x,root_y); + if (XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y, + &win_x, &win_y, &mask)) { + pos = pair(root_x, root_y); } XCloseDisplay(dpy); return pos; @@ -297,13 +256,16 @@ bool isFullscreen(std::string &title) // Find switch in top level windows vector windows = getTopLevelWindows(); - for (auto &window : windows) - { + for (auto &window : windows) { XTextProperty text; - int status = XGetTextProperty(disp(), window, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); + int status = XGetTextProperty( + disp(), window, &text, + XInternAtom(disp(), "_NET_WM_NAME", true)); if (status == 0) - status = XGetTextProperty(disp(), window, &text, XInternAtom(disp(), "WM_NAME", true)); - char *name = reinterpret_cast(text.value); + status = XGetTextProperty(disp(), window, &text, + XInternAtom(disp(), "WM_NAME", + true)); + char *name = reinterpret_cast(text.value); if (status == 0 || name == nullptr) continue; @@ -311,21 +273,23 @@ bool isFullscreen(std::string &title) // True if switch equals window bool equals = (title == name); // True if switch matches window - bool matches = QString::fromStdString(name).contains(QRegularExpression(title.c_str())); + bool matches = QString::fromStdString(name).contains( + QRegularExpression(title.c_str())); // If found, check if switch is fullscreen - if (equals || matches) - { + if (equals || matches) { QStringList states = getStates(window); - if (!states.isEmpty()) - { + if (!states.isEmpty()) { // True if window is fullscreen - bool fullscreen = states.contains("_NET_WM_STATE_FULLSCREEN"); + bool fullscreen = states.contains( + "_NET_WM_STATE_FULLSCREEN"); // True if window is maximized vertically - bool vertical = states.contains("_NET_WM_STATE_MAXIMIZED_VERT"); + bool vertical = states.contains( + "_NET_WM_STATE_MAXIMIZED_VERT"); // True if window is maximized horizontally - bool horizontal = states.contains("_NET_WM_STATE_MAXIMIZED_HORZ"); + bool horizontal = states.contains( + "_NET_WM_STATE_MAXIMIZED_HORZ"); return (fullscreen || (vertical && horizontal)); } @@ -341,7 +305,7 @@ bool isFullscreen(std::string &title) void GetProcessList(QStringList &processes) { processes.clear(); - for (size_t i = 0; i < getTopLevelWindows().size(); ++i){ + for (size_t i = 0; i < getTopLevelWindows().size(); ++i) { string s = GetWindowTitle(i); if (s != "") processes << QString::fromStdString(s); @@ -356,29 +320,29 @@ bool isInFocus(const QString &executable) // True if executable switch equals current window bool equals = (executable.toStdString() == current); // True if executable switch matches current window - bool matches = QString::fromStdString(current).contains(QRegularExpression(executable)); + bool matches = QString::fromStdString(current).contains( + QRegularExpression(executable)); return (equals || matches); } int secondsSinceLastInput() { - time_t idle_time; - static XScreenSaverInfo *mit_info; - Display *display; - int screen; + time_t idle_time; + static XScreenSaverInfo *mit_info; + Display *display; + int screen; - mit_info = XScreenSaverAllocInfo(); + mit_info = XScreenSaverAllocInfo(); - if((display=XOpenDisplay(NULL)) == NULL) - { - return(-1); + if ((display = XOpenDisplay(NULL)) == NULL) { + return (-1); } - screen = DefaultScreen(display); - XScreenSaverQueryInfo(display, RootWindow(display,screen), mit_info); - idle_time = (mit_info->idle) / 1000; - XFree(mit_info); - XCloseDisplay(display); + screen = DefaultScreen(display); + XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info); + idle_time = (mit_info->idle) / 1000; + XFree(mit_info); + XCloseDisplay(display); - return idle_time; + return idle_time; } diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index a3488604..5830c963 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -6,147 +6,151 @@ #include #include "../headers/advanced-scene-switcher.hpp" - void GetWindowList(vector &windows) { - windows.resize(0); + windows.resize(0); - @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSArray *array = [ws runningApplications]; - for (NSRunningApplication *app in array) { - NSString *name = app.localizedName; - if (!name) - continue; + @autoreleasepool { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSArray *array = [ws runningApplications]; + for (NSRunningApplication *app in array) { + NSString *name = app.localizedName; + if (!name) + continue; - const char *str = name.UTF8String; - if (str && *str) - windows.emplace_back(str); - } - } + const char *str = name.UTF8String; + if (str && *str) + windows.emplace_back(str); + } + } } // Overloaded void GetWindowList(QStringList &windows) { - windows.clear(); + windows.clear(); - @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSArray *array = [ws runningApplications]; - for (NSRunningApplication *app in array) { - NSString *name = app.localizedName; - if (!name) - continue; + @autoreleasepool { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSArray *array = [ws runningApplications]; + for (NSRunningApplication *app in array) { + NSString *name = app.localizedName; + if (!name) + continue; - const char *str = name.UTF8String; - if (str && *str) - windows << QString(str); - } - } + const char *str = name.UTF8String; + if (str && *str) + windows << QString(str); + } + } } void GetCurrentWindowTitle(string &title) { - title.resize(0); + title.resize(0); - @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSRunningApplication *app = [ws frontmostApplication]; - if (app) { - NSString *name = app.localizedName; - if (!name) - return; + @autoreleasepool { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSRunningApplication *app = [ws frontmostApplication]; + if (app) { + NSString *name = app.localizedName; + if (!name) + return; - const char *str = name.UTF8String; - if (str && *str) - title = str; - } - } + const char *str = name.UTF8String; + if (str && *str) + title = str; + } + } } pair getCursorPos() { - pair pos(0, 0); - CGEventRef event = CGEventCreate(NULL); - CGPoint cursorPos = CGEventGetLocation(event); - CFRelease(event); - pos.first = cursorPos.x; - pos.second = cursorPos.y; - return pos; + pair pos(0, 0); + CGEventRef event = CGEventCreate(NULL); + CGPoint cursorPos = CGEventGetLocation(event); + CFRelease(event); + pos.first = cursorPos.x; + pos.second = cursorPos.y; + return pos; } // Argument added in lieu of fullscreen bug fix bool isFullscreen(std::string &title) { - @autoreleasepool { - AXValueRef temp; - CGSize windowSize; - CGPoint windowPosition; - AXUIElementRef frontMostApp; - AXUIElementRef frontMostWindow; + @autoreleasepool { + AXValueRef temp; + CGSize windowSize; + CGPoint windowPosition; + AXUIElementRef frontMostApp; + AXUIElementRef frontMostWindow; - pid_t pid; - ProcessSerialNumber psn; - @try { - GetFrontProcess(&psn); - GetProcessPID(&psn, &pid); - frontMostApp = AXUIElementCreateApplication(pid); + pid_t pid; + ProcessSerialNumber psn; + @try { + GetFrontProcess(&psn); + GetProcessPID(&psn, &pid); + frontMostApp = AXUIElementCreateApplication(pid); - AXUIElementCopyAttributeValue( - frontMostApp, kAXFocusedWindowAttribute, (CFTypeRef *)&frontMostWindow); + AXUIElementCopyAttributeValue( + frontMostApp, kAXFocusedWindowAttribute, + (CFTypeRef *)&frontMostWindow); - // Get the window size and position - AXUIElementCopyAttributeValue( - frontMostWindow, kAXSizeAttribute, (CFTypeRef *)&temp); - AXValueGetValue(temp, kAXValueTypeCGSize, &windowSize); - CFRelease(temp); + // Get the window size and position + AXUIElementCopyAttributeValue(frontMostWindow, + kAXSizeAttribute, + (CFTypeRef *)&temp); + AXValueGetValue(temp, kAXValueTypeCGSize, &windowSize); + CFRelease(temp); - AXUIElementCopyAttributeValue( - frontMostWindow, kAXPositionAttribute, (CFTypeRef *)&temp); - AXValueGetValue(temp, kAXValueTypeCGPoint, &windowPosition); - CFRelease(temp); + AXUIElementCopyAttributeValue(frontMostWindow, + kAXPositionAttribute, + (CFTypeRef *)&temp); + AXValueGetValue(temp, kAXValueTypeCGPoint, + &windowPosition); + CFRelease(temp); - CGRect screenBound = CGDisplayBounds(CGMainDisplayID()); - CGSize screenSize = screenBound.size; + CGRect screenBound = CGDisplayBounds(CGMainDisplayID()); + CGSize screenSize = screenBound.size; - if((windowSize.width == screenSize.width) && (windowSize.height == screenSize.height) && - (windowPosition.x == 0) && (windowPosition.y == 0)) - return true; - } - @catch (...) { - // deal with the exception - } - @catch (NSException *exception) { - // deal with the exception - } - - } - return false; + if ((windowSize.width == screenSize.width) && + (windowSize.height == screenSize.height) && + (windowPosition.x == 0) && (windowPosition.y == 0)) + return true; + } @catch (...) { + // deal with the exception + } @catch (NSException *exception) { + // deal with the exception + } + } + return false; } int secondsSinceLastInput() { - double time = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType) + 0.5; - return (int) time; + double time = CGEventSourceSecondsSinceLastEventType( + kCGEventSourceStateCombinedSessionState, + kCGAnyInputEventType) + + 0.5; + return (int)time; } -void GetProcessList(QStringList& list) +void GetProcessList(QStringList &list) { - list.clear(); - @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSArray *array = [ws runningApplications]; - for (NSRunningApplication *app in array) { - NSString *name = app.localizedName; - if (!name) - continue; + list.clear(); + @autoreleasepool { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSArray *array = [ws runningApplications]; + for (NSRunningApplication *app in array) { + NSString *name = app.localizedName; + if (!name) + continue; - const char *str = name.UTF8String; - if (str && *str) - list << (str); - } - } + const char *str = name.UTF8String; + if (str && *str) + list << (str); + } + } } bool isInFocus(const QString &executable) @@ -157,7 +161,8 @@ bool isInFocus(const QString &executable) // True if executable switch equals current window bool equals = (executable.toStdString() == current); // True if executable switch matches current window - bool matches = QString::fromStdString(current).contains(QRegularExpression(executable)); + bool matches = QString::fromStdString(current).contains( + QRegularExpression(executable)); return (equals || matches); } diff --git a/src/pause-switch.cpp b/src/pause-switch.cpp index f6b30c53..37ecc9c3 100644 --- a/src/pause-switch.cpp +++ b/src/pause-switch.cpp @@ -10,11 +10,12 @@ void SceneSwitcher::on_pauseScenesAdd_clicked() OBSWeakSource source = GetWeakSourceByQString(sceneName); QVariant v = QVariant::fromValue(sceneName); - QList items = ui->pauseScenes->findItems(sceneName, Qt::MatchExactly); + QList items = + ui->pauseScenes->findItems(sceneName, Qt::MatchExactly); - if (items.size() == 0) - { - QListWidgetItem* item = new QListWidgetItem(sceneName, ui->pauseScenes); + if (items.size() == 0) { + QListWidgetItem *item = + new QListWidgetItem(sceneName, ui->pauseScenes); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); @@ -25,7 +26,7 @@ void SceneSwitcher::on_pauseScenesAdd_clicked() void SceneSwitcher::on_pauseScenesRemove_clicked() { - QListWidgetItem* item = ui->pauseScenes->currentItem(); + QListWidgetItem *item = ui->pauseScenes->currentItem(); if (!item) return; @@ -33,14 +34,12 @@ void SceneSwitcher::on_pauseScenesRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->pauseScenesSwitches; + auto &switches = switcher->pauseScenesSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s == GetWeakSourceByQString(pauseScene)) - { + if (s == GetWeakSourceByQString(pauseScene)) { switches.erase(it); break; } @@ -59,22 +58,24 @@ void SceneSwitcher::on_pauseWindowsAdd_clicked() QVariant v = QVariant::fromValue(windowName); - QList items = ui->pauseWindows->findItems(windowName, Qt::MatchExactly); + QList items = + ui->pauseWindows->findItems(windowName, Qt::MatchExactly); - if (items.size() == 0) - { - QListWidgetItem* item = new QListWidgetItem(windowName, ui->pauseWindows); + if (items.size() == 0) { + QListWidgetItem *item = + new QListWidgetItem(windowName, ui->pauseWindows); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); - switcher->pauseWindowsSwitches.emplace_back(windowName.toUtf8().constData()); + switcher->pauseWindowsSwitches.emplace_back( + windowName.toUtf8().constData()); ui->pauseWindows->sortItems(); } } void SceneSwitcher::on_pauseWindowsRemove_clicked() { - QListWidgetItem* item = ui->pauseWindows->currentItem(); + QListWidgetItem *item = ui->pauseWindows->currentItem(); if (!item) return; @@ -82,14 +83,12 @@ void SceneSwitcher::on_pauseWindowsRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->pauseWindowsSwitches; + auto &switches = switcher->pauseWindowsSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s == windowName.toUtf8().constData()) - { + if (s == windowName.toUtf8().constData()) { switches.erase(it); break; } @@ -106,16 +105,14 @@ void SceneSwitcher::on_pauseScenes_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->pauseScenes->item(idx); + QListWidgetItem *item = ui->pauseScenes->item(idx); QString scene = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->pauseScenesSwitches) - { + for (auto &s : switcher->pauseScenesSwitches) { string name = GetWeakSourceName(s); - if (scene.compare(name.c_str()) == 0) - { + if (scene.compare(name.c_str()) == 0) { ui->pauseScenesScenes->setCurrentText(name.c_str()); break; } @@ -129,33 +126,29 @@ void SceneSwitcher::on_pauseWindows_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->pauseWindows->item(idx); + QListWidgetItem *item = ui->pauseWindows->item(idx); QString window = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->pauseWindowsSwitches) - { - if (window.compare(s.c_str()) == 0) - { + for (auto &s : switcher->pauseWindowsSwitches) { + if (window.compare(s.c_str()) == 0) { ui->pauseWindowsWindows->setCurrentText(s.c_str()); break; } } } -int SceneSwitcher::PauseScenesFindByData(const QString& scene) +int SceneSwitcher::PauseScenesFindByData(const QString &scene) { int count = ui->pauseScenes->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->pauseScenes->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->pauseScenes->item(i); QString itemRegion = item->data(Qt::UserRole).toString(); - if (itemRegion == scene) - { + if (itemRegion == scene) { idx = i; break; } @@ -164,18 +157,16 @@ int SceneSwitcher::PauseScenesFindByData(const QString& scene) return idx; } -int SceneSwitcher::PauseWindowsFindByData(const QString& window) +int SceneSwitcher::PauseWindowsFindByData(const QString &window) { int count = ui->pauseWindows->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->pauseWindows->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->pauseWindows->item(i); QString itemRegion = item->data(Qt::UserRole).toString(); - if (itemRegion == window) - { + if (itemRegion == window) { idx = i; break; } @@ -187,13 +178,11 @@ int SceneSwitcher::PauseWindowsFindByData(const QString& window) bool SwitcherData::checkPause() { bool pause = false; - obs_source_t* currentSource = obs_frontend_get_current_scene(); - obs_weak_source_t* ws = obs_source_get_weak_source(currentSource); + obs_source_t *currentSource = obs_frontend_get_current_scene(); + obs_weak_source_t *ws = obs_source_get_weak_source(currentSource); - for (OBSWeakSource& s : pauseScenesSwitches) - { - if (s == ws) - { + for (OBSWeakSource &s : pauseScenesSwitches) { + if (s == ws) { pause = true; break; } @@ -202,39 +191,31 @@ bool SwitcherData::checkPause() obs_weak_source_release(ws); string title; - if (!pause) - { + if (!pause) { //lock.unlock(); GetCurrentWindowTitle(title); //lock.lock(); - for (string& window : pauseWindowsSwitches) - { - if (window == title) - { + for (string &window : pauseWindowsSwitches) { + if (window == title) { pause = true; break; } } } - if (!pause) - { + if (!pause) { //lock.unlock(); GetCurrentWindowTitle(title); //lock.lock(); - for (string& window : pauseWindowsSwitches) - { - try - { - bool matches = regex_match(title, regex(window)); - if (matches) - { + for (string &window : pauseWindowsSwitches) { + try { + bool matches = + regex_match(title, regex(window)); + if (matches) { pause = true; break; } - } - catch (const regex_error&) - { + } catch (const regex_error &) { } } } diff --git a/src/priority.cpp b/src/priority.cpp index 60f5e30e..6ce1a55d 100644 --- a/src/priority.cpp +++ b/src/priority.cpp @@ -3,14 +3,14 @@ void SceneSwitcher::on_threadPriority_currentTextChanged(const QString &text) { - if (loading || ui->threadPriority->count() != switcher->threadPriorities.size()) + if (loading || + ui->threadPriority->count() != switcher->threadPriorities.size()) return; lock_guard lock(switcher->m); for (auto p : switcher->threadPriorities) { - if (p.name == text.toUtf8() - .constData()) { + if (p.name == text.toUtf8().constData()) { switcher->threadPriority = p.value; break; } diff --git a/src/random.cpp b/src/random.cpp index 84b64dd2..265cb7dd 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -8,17 +8,16 @@ void SceneSwitcher::on_randomScenesList_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->randomScenesList->item(idx); + QListWidgetItem *item = ui->randomScenesList->item(idx); QString randomSceneStr = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->randomSwitches) - { - if (randomSceneStr.compare(s.randomSwitchStr.c_str()) == 0) - { + for (auto &s : switcher->randomSwitches) { + if (randomSceneStr.compare(s.randomSwitchStr.c_str()) == 0) { QString sceneName = GetWeakSourceName(s.scene).c_str(); - QString transitionName = GetWeakSourceName(s.transition).c_str(); + QString transitionName = + GetWeakSourceName(s.transition).c_str(); ui->randomScenes->setCurrentText(sceneName); ui->randomSpinBox->setValue(s.delay); ui->randomTransitions->setCurrentText(transitionName); @@ -27,13 +26,12 @@ void SceneSwitcher::on_randomScenesList_currentRowChanged(int idx) } } -int SceneSwitcher::randomFindByData(const QString& randomStr) +int SceneSwitcher::randomFindByData(const QString &randomStr) { int count = ui->randomScenesList->count(); - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->randomScenesList->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->randomScenesList->item(i); QString str = item->data(Qt::UserRole).toString(); if (str == randomStr) @@ -49,42 +47,38 @@ void SceneSwitcher::on_randomAdd_clicked() QString transitionName = ui->randomTransitions->currentText(); double delay = ui->randomSpinBox->value(); - if (sceneName.isEmpty()) return; OBSWeakSource source = GetWeakSourceByQString(sceneName); OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - QString text = MakeRandomSwitchName(sceneName, transitionName, delay); QVariant v = QVariant::fromValue(text); int idx = randomFindByData(text); - if (idx == -1) - { + if (idx == -1) { lock_guard lock(switcher->m); switcher->randomSwitches.emplace_back( source, transition, delay, text.toUtf8().constData()); - QListWidgetItem* item = new QListWidgetItem(text, ui->randomScenesList); + QListWidgetItem *item = + new QListWidgetItem(text, ui->randomScenesList); item->setData(Qt::UserRole, v); - } - else - { - QListWidgetItem* item = ui->randomScenesList->item(idx); + } else { + QListWidgetItem *item = ui->randomScenesList->item(idx); item->setText(text); { lock_guard lock(switcher->m); - for (auto& s : switcher->randomSwitches) - { - if (s.scene == source) - { + for (auto &s : switcher->randomSwitches) { + if (s.scene == source) { s.delay = delay; s.transition = transition; - s.randomSwitchStr = text.toUtf8().constData();; + s.randomSwitchStr = + text.toUtf8().constData(); + ; break; } } @@ -96,7 +90,7 @@ void SceneSwitcher::on_randomAdd_clicked() void SceneSwitcher::on_randomRemove_clicked() { - QListWidgetItem* item = ui->randomScenesList->currentItem(); + QListWidgetItem *item = ui->randomScenesList->currentItem(); if (!item) return; @@ -104,14 +98,12 @@ void SceneSwitcher::on_randomRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->randomSwitches; + auto &switches = switcher->randomSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s.randomSwitchStr == text) - { + if (s.randomSwitchStr == text) { switches.erase(it); break; } @@ -121,17 +113,17 @@ void SceneSwitcher::on_randomRemove_clicked() delete item; } -void SwitcherData::checkRandom(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, int& delay) +void SwitcherData::checkRandom(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition, int &delay) { if (randomSwitches.size() == 0) return; - vector rs (randomSwitches); + vector rs(randomSwitches); std::random_device rng; std::mt19937 urng(rng()); std::shuffle(rs.begin(), rs.end(), urng); - for (RandomSwitch& r : rs) - { + for (RandomSwitch &r : rs) { if (r.scene == lastRandomScene) continue; scene = r.scene; diff --git a/src/scene-round-trip.cpp b/src/scene-round-trip.cpp index aaae6f26..b9b5c538 100644 --- a/src/scene-round-trip.cpp +++ b/src/scene-round-trip.cpp @@ -22,14 +22,15 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked() OBSWeakSource source2 = GetWeakSourceByQString(scene2Name); OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - QString text = MakeSceneRoundTripSwitchName(scene1Name, scene2Name, transitionName, delay); + QString text = MakeSceneRoundTripSwitchName(scene1Name, scene2Name, + transitionName, delay); QVariant v = QVariant::fromValue(text); int idx = SceneRoundTripFindByData(scene1Name); - if (idx == -1) - { - QListWidgetItem* item = new QListWidgetItem(text, ui->sceneRoundTrips); + if (idx == -1) { + QListWidgetItem *item = + new QListWidgetItem(text, ui->sceneRoundTrips); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); @@ -37,23 +38,22 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked() source1, source2, transition, int(delay * 1000), (scene2Name == QString(PREVIOUS_SCENE_NAME)), text.toUtf8().constData()); - } - else - { - QListWidgetItem* item = ui->sceneRoundTrips->item(idx); + } else { + QListWidgetItem *item = ui->sceneRoundTrips->item(idx); item->setText(text); { lock_guard lock(switcher->m); - for (auto& s : switcher->sceneRoundTripSwitches) - { - if (s.scene1 == source1) - { + for (auto &s : switcher->sceneRoundTripSwitches) { + if (s.scene1 == source1) { s.scene2 = source2; s.delay = int(delay * 1000); s.transition = transition; - s.usePreviousScene = (scene2Name == QString(PREVIOUS_SCENE_NAME)); - s.sceneRoundTripStr = text.toUtf8().constData(); + s.usePreviousScene = + (scene2Name == + QString(PREVIOUS_SCENE_NAME)); + s.sceneRoundTripStr = + text.toUtf8().constData(); break; } } @@ -65,7 +65,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked() void SceneSwitcher::on_sceneRoundTripRemove_clicked() { - QListWidgetItem* item = ui->sceneRoundTrips->currentItem(); + QListWidgetItem *item = ui->sceneRoundTrips->currentItem(); if (!item) return; @@ -73,14 +73,12 @@ void SceneSwitcher::on_sceneRoundTripRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->sceneRoundTripSwitches; + auto &switches = switcher->sceneRoundTripSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s.sceneRoundTripStr == text) - { + if (s.sceneRoundTripStr == text) { switches.erase(it); break; } @@ -96,22 +94,19 @@ void SceneSwitcher::on_autoStopSceneCheckBox_stateChanged(int state) return; lock_guard lock(switcher->m); - if (!state) - { + if (!state) { ui->autoStopScenes->setDisabled(true); switcher->autoStopEnable = false; - } - else - { + } else { ui->autoStopScenes->setDisabled(false); switcher->autoStopEnable = true; } } -void SceneSwitcher::UpdateAutoStopScene(const QString& name) +void SceneSwitcher::UpdateAutoStopScene(const QString &name) { - obs_source_t* scene = obs_get_source_by_name(name.toUtf8().constData()); - obs_weak_source_t* ws = obs_source_get_weak_source(scene); + obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData()); + obs_weak_source_t *ws = obs_source_get_weak_source(scene); switcher->autoStopScene = ws; @@ -119,7 +114,7 @@ void SceneSwitcher::UpdateAutoStopScene(const QString& name) obs_source_release(scene); } -void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString& text) +void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString &text) { if (loading) return; @@ -131,23 +126,30 @@ void SceneSwitcher::on_autoStopScenes_currentTextChanged(const QString& text) void SceneSwitcher::on_sceneRoundTripSave_clicked() { QString directory = QFileDialog::getSaveFileName( - this, tr("Save Scene Round Trip to file ..."), QDir::currentPath(), tr("Text files (*.txt)")); - if (!directory.isEmpty()) - { + this, tr("Save Scene Round Trip to file ..."), + QDir::currentPath(), tr("Text files (*.txt)")); + if (!directory.isEmpty()) { QFile file(directory); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream out(&file); - for (SceneRoundTripSwitch s : switcher->sceneRoundTripSwitches) - { - out << QString::fromStdString(GetWeakSourceName(s.scene1)) << "\n"; + for (SceneRoundTripSwitch s : + switcher->sceneRoundTripSwitches) { + out << QString::fromStdString( + GetWeakSourceName(s.scene1)) + << "\n"; if (s.usePreviousScene) out << (PREVIOUS_SCENE_NAME) << "\n"; else - out << QString::fromStdString(GetWeakSourceName(s.scene2)) << "\n"; + out << QString::fromStdString( + GetWeakSourceName(s.scene2)) + << "\n"; out << s.delay << "\n"; - out << QString::fromStdString(s.sceneRoundTripStr) << "\n"; - out << QString::fromStdString(GetWeakSourceName(s.transition)) << "\n"; + out << QString::fromStdString(s.sceneRoundTripStr) + << "\n"; + out << QString::fromStdString( + GetWeakSourceName(s.transition)) + << "\n"; } } } @@ -157,9 +159,9 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked() lock_guard lock(switcher->m); QString directory = QFileDialog::getOpenFileName( - this, tr("Select a file to read Scene Round Trip from ..."), QDir::currentPath(), tr("Text files (*.txt)")); - if (!directory.isEmpty()) - { + this, tr("Select a file to read Scene Round Trip from ..."), + QDir::currentPath(), tr("Text files (*.txt)")); + if (!directory.isEmpty()) { QFile file(directory); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; @@ -169,26 +171,34 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked() vector newSceneRoundTripSwitch; - while (!in.atEnd()) - { + while (!in.atEnd()) { QString line = in.readLine(); lines.push_back(line); - if (lines.size() == 5) - { - OBSWeakSource scene1 = GetWeakSourceByQString(lines[0]); - OBSWeakSource scene2 = GetWeakSourceByQString(lines[1]); - OBSWeakSource transition = GetWeakTransitionByQString(lines[4]); + if (lines.size() == 5) { + OBSWeakSource scene1 = + GetWeakSourceByQString(lines[0]); + OBSWeakSource scene2 = + GetWeakSourceByQString(lines[1]); + OBSWeakSource transition = + GetWeakTransitionByQString(lines[4]); - if (WeakSourceValid(scene1) && ((lines[1] == QString(PREVIOUS_SCENE_NAME)) || (WeakSourceValid(scene2))) - && WeakSourceValid(transition)) - { - newSceneRoundTripSwitch.emplace_back(SceneRoundTripSwitch( - GetWeakSourceByQString(lines[0]), - GetWeakSourceByQString(lines[1]), - GetWeakTransitionByQString(lines[4]), - lines[2].toInt(), - (lines[1] == QString(PREVIOUS_SCENE_NAME)), - lines[3].toStdString())); + if (WeakSourceValid(scene1) && + ((lines[1] == + QString(PREVIOUS_SCENE_NAME)) || + (WeakSourceValid(scene2))) && + WeakSourceValid(transition)) { + newSceneRoundTripSwitch.emplace_back( + SceneRoundTripSwitch( + GetWeakSourceByQString( + lines[0]), + GetWeakSourceByQString( + lines[1]), + GetWeakTransitionByQString( + lines[4]), + lines[2].toInt(), + (lines[1] == + QString(PREVIOUS_SCENE_NAME)), + lines[3].toStdString())); } lines.clear(); } @@ -200,39 +210,42 @@ void SceneSwitcher::on_sceneRoundTripLoad_clicked() switcher->sceneRoundTripSwitches.clear(); ui->sceneRoundTrips->clear(); switcher->sceneRoundTripSwitches = newSceneRoundTripSwitch; - for (SceneRoundTripSwitch s : switcher->sceneRoundTripSwitches) - { - QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(s.sceneRoundTripStr), ui->sceneRoundTrips); - item->setData(Qt::UserRole, QString::fromStdString(s.sceneRoundTripStr)); + for (SceneRoundTripSwitch s : + switcher->sceneRoundTripSwitches) { + QListWidgetItem *item = new QListWidgetItem( + QString::fromStdString(s.sceneRoundTripStr), + ui->sceneRoundTrips); + item->setData( + Qt::UserRole, + QString::fromStdString(s.sceneRoundTripStr)); } } } - -void SwitcherData::checkSceneRoundTrip(bool& match, OBSWeakSource& scene, OBSWeakSource& transition, unique_lock& lock) +void SwitcherData::checkSceneRoundTrip(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition, + unique_lock &lock) { bool sceneRoundTripActive = false; - obs_source_t* currentSource = obs_frontend_get_current_scene(); - obs_weak_source_t* ws = obs_source_get_weak_source(currentSource); + obs_source_t *currentSource = obs_frontend_get_current_scene(); + obs_weak_source_t *ws = obs_source_get_weak_source(currentSource); - for (SceneRoundTripSwitch& s : sceneRoundTripSwitches) - { - if (s.scene1 == ws) - { + for (SceneRoundTripSwitch &s : sceneRoundTripSwitches) { + if (s.scene1 == ws) { sceneRoundTripActive = true; int dur = s.delay - interval; - if (dur > 0) - { + if (dur > 0) { waitScene = currentSource; cv.wait_for(lock, chrono::milliseconds(dur)); } - obs_source_t* currentSource2 = obs_frontend_get_current_scene(); + obs_source_t *currentSource2 = + obs_frontend_get_current_scene(); // only switch if user hasn't changed scene manually - if (currentSource == currentSource2) - { + if (currentSource == currentSource2) { match = true; - scene = (s.usePreviousScene) ? previousScene : s.scene2; + scene = (s.usePreviousScene) ? previousScene + : s.scene2; transition = s.transition; } obs_source_release(currentSource2); @@ -250,42 +263,41 @@ void SceneSwitcher::on_sceneRoundTrips_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->sceneRoundTrips->item(idx); + QListWidgetItem *item = ui->sceneRoundTrips->item(idx); QString sceneRoundTrip = item->text(); lock_guard lock(switcher->m); - for (auto& s : switcher->sceneRoundTripSwitches) - { - if (sceneRoundTrip.compare(s.sceneRoundTripStr.c_str()) == 0) - { + for (auto &s : switcher->sceneRoundTripSwitches) { + if (sceneRoundTrip.compare(s.sceneRoundTripStr.c_str()) == 0) { string scene1 = GetWeakSourceName(s.scene1); string scene2 = GetWeakSourceName(s.scene2); string transitionName = GetWeakSourceName(s.transition); int delay = s.delay; - ui->sceneRoundTripScenes1->setCurrentText(scene1.c_str()); - ui->sceneRoundTripScenes2->setCurrentText(scene2.c_str()); - ui->sceneRoundTripTransitions->setCurrentText(transitionName.c_str()); - ui->sceneRoundTripSpinBox->setValue((double)delay/1000); + ui->sceneRoundTripScenes1->setCurrentText( + scene1.c_str()); + ui->sceneRoundTripScenes2->setCurrentText( + scene2.c_str()); + ui->sceneRoundTripTransitions->setCurrentText( + transitionName.c_str()); + ui->sceneRoundTripSpinBox->setValue((double)delay / + 1000); break; } } } - -int SceneSwitcher::SceneRoundTripFindByData(const QString& scene1) +int SceneSwitcher::SceneRoundTripFindByData(const QString &scene1) { QRegExp rx(scene1 + " ->.*"); int count = ui->sceneRoundTrips->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->sceneRoundTrips->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->sceneRoundTrips->item(i); QString itemString = item->data(Qt::UserRole).toString(); - if (rx.exactMatch(itemString)) - { + if (rx.exactMatch(itemString)) { idx = i; break; } @@ -294,14 +306,12 @@ int SceneSwitcher::SceneRoundTripFindByData(const QString& scene1) return idx; } - void SwitcherData::autoStopStreamAndRecording() { - obs_source_t* currentSource = obs_frontend_get_current_scene(); - obs_weak_source_t* ws = obs_source_get_weak_source(currentSource); + obs_source_t *currentSource = obs_frontend_get_current_scene(); + obs_weak_source_t *ws = obs_source_get_weak_source(currentSource); - if (ws && autoStopScene == ws) - { + if (ws && autoStopScene == ws) { if (obs_frontend_streaming_active()) obs_frontend_streaming_stop(); if (obs_frontend_recording_active()) diff --git a/src/scene-transitions.cpp b/src/scene-transitions.cpp index e84010e9..c643990d 100644 --- a/src/scene-transitions.cpp +++ b/src/scene-transitions.cpp @@ -16,33 +16,33 @@ void SceneSwitcher::on_transitionsAdd_clicked() OBSWeakSource source2 = GetWeakSourceByQString(scene2Name); OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - QString text = MakeSceneTransitionName(scene1Name, scene2Name, transitionName); + QString text = + MakeSceneTransitionName(scene1Name, scene2Name, transitionName); QVariant v = QVariant::fromValue(text); int idx = SceneTransitionsFindByData(scene1Name, scene2Name); - if (idx == -1) - { - QListWidgetItem* item = new QListWidgetItem(text, ui->sceneTransitions); + if (idx == -1) { + QListWidgetItem *item = + new QListWidgetItem(text, ui->sceneTransitions); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); switcher->sceneTransitions.emplace_back( - source1, source2, transition, text.toUtf8().constData()); - } - else - { - QListWidgetItem* item = ui->sceneTransitions->item(idx); + source1, source2, transition, + text.toUtf8().constData()); + } else { + QListWidgetItem *item = ui->sceneTransitions->item(idx); item->setText(text); { lock_guard lock(switcher->m); - for (auto& s : switcher->sceneTransitions) - { - if (s.scene1 == source1 && s.scene2 == source2) - { + for (auto &s : switcher->sceneTransitions) { + if (s.scene1 == source1 && + s.scene2 == source2) { s.transition = transition; - s.sceneTransitionStr = text.toUtf8().constData(); + s.sceneTransitionStr = + text.toUtf8().constData(); break; } } @@ -54,7 +54,7 @@ void SceneSwitcher::on_transitionsAdd_clicked() void SceneSwitcher::on_transitionsRemove_clicked() { - QListWidgetItem* item = ui->sceneTransitions->currentItem(); + QListWidgetItem *item = ui->sceneTransitions->currentItem(); if (!item) return; @@ -62,14 +62,12 @@ void SceneSwitcher::on_transitionsRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->sceneTransitions; + auto &switches = switcher->sceneTransitions; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s.sceneTransitionStr == text) - { + if (s.sceneTransitionStr == text) { switches.erase(it); break; } @@ -82,7 +80,8 @@ void SceneSwitcher::on_transitionsRemove_clicked() void SceneSwitcher::on_defaultTransitionsAdd_clicked() { QString sceneName = ui->defaultTransitionsScene->currentText(); - QString transitionName = ui->defaultTransitionsTransitions->currentText(); + QString transitionName = + ui->defaultTransitionsTransitions->currentText(); if (sceneName.isEmpty() || transitionName.isEmpty()) return; @@ -90,33 +89,31 @@ void SceneSwitcher::on_defaultTransitionsAdd_clicked() OBSWeakSource source = GetWeakSourceByQString(sceneName); OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - QString text = MakeDefaultSceneTransitionName(sceneName, transitionName); + QString text = + MakeDefaultSceneTransitionName(sceneName, transitionName); QVariant v = QVariant::fromValue(text); int idx = DefaultTransitionsFindByData(sceneName); - if (idx == -1) - { - QListWidgetItem* item = new QListWidgetItem(text, ui->defaultTransitions); + if (idx == -1) { + QListWidgetItem *item = + new QListWidgetItem(text, ui->defaultTransitions); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); switcher->defaultSceneTransitions.emplace_back( source, transition, text.toUtf8().constData()); - } - else - { - QListWidgetItem* item = ui->defaultTransitions->item(idx); + } else { + QListWidgetItem *item = ui->defaultTransitions->item(idx); item->setText(text); { lock_guard lock(switcher->m); - for (auto& s : switcher->defaultSceneTransitions) - { - if (s.scene == source) - { + for (auto &s : switcher->defaultSceneTransitions) { + if (s.scene == source) { s.transition = transition; - s.sceneTransitionStr = text.toUtf8().constData(); + s.sceneTransitionStr = + text.toUtf8().constData(); break; } } @@ -128,7 +125,7 @@ void SceneSwitcher::on_defaultTransitionsAdd_clicked() void SceneSwitcher::on_defaultTransitionsRemove_clicked() { - QListWidgetItem* item = ui->defaultTransitions->currentItem(); + QListWidgetItem *item = ui->defaultTransitions->currentItem(); if (!item) return; @@ -136,14 +133,12 @@ void SceneSwitcher::on_defaultTransitionsRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->defaultSceneTransitions; + auto &switches = switcher->defaultSceneTransitions; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s.sceneTransitionStr == text) - { + if (s.sceneTransitionStr == text) { switches.erase(it); break; } @@ -155,14 +150,13 @@ void SceneSwitcher::on_defaultTransitionsRemove_clicked() void SwitcherData::setDefaultSceneTransitions() { - obs_source_t* currentSource = obs_frontend_get_current_scene(); - obs_weak_source_t* ws = obs_source_get_weak_source(currentSource); + obs_source_t *currentSource = obs_frontend_get_current_scene(); + obs_weak_source_t *ws = obs_source_get_weak_source(currentSource); - for (DefaultSceneTransition& s : defaultSceneTransitions) - { - if (s.scene == ws) - { - obs_source_t* transition = obs_weak_source_get_source(s.transition); + for (DefaultSceneTransition &s : defaultSceneTransitions) { + if (s.scene == ws) { + obs_source_t *transition = + obs_weak_source_get_source(s.transition); //This might cancel the current transition //There is no way to be sure when the previous transition finished obs_frontend_set_current_transition(transition); @@ -174,19 +168,18 @@ void SwitcherData::setDefaultSceneTransitions() obs_weak_source_release(ws); } -int SceneSwitcher::SceneTransitionsFindByData(const QString& scene1, const QString& scene2) +int SceneSwitcher::SceneTransitionsFindByData(const QString &scene1, + const QString &scene2) { QRegExp rx(scene1 + " --- .* --> " + scene2); int count = ui->sceneTransitions->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->sceneTransitions->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->sceneTransitions->item(i); QString itemString = item->data(Qt::UserRole).toString(); - if (rx.exactMatch(itemString)) - { + if (rx.exactMatch(itemString)) { idx = i; break; } @@ -195,19 +188,17 @@ int SceneSwitcher::SceneTransitionsFindByData(const QString& scene1, const QStri return idx; } -int SceneSwitcher::DefaultTransitionsFindByData(const QString& scene) +int SceneSwitcher::DefaultTransitionsFindByData(const QString &scene) { QRegExp rx(scene + " --> .*"); int count = ui->defaultTransitions->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->defaultTransitions->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->defaultTransitions->item(i); QString itemString = item->data(Qt::UserRole).toString(); - if (rx.exactMatch(itemString)) - { + if (rx.exactMatch(itemString)) { idx = i; break; } @@ -223,21 +214,21 @@ void SceneSwitcher::on_sceneTransitions_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->sceneTransitions->item(idx); + QListWidgetItem *item = ui->sceneTransitions->item(idx); QString sceneTransition = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->sceneTransitions) - { - if (sceneTransition.compare(s.sceneTransitionStr.c_str()) == 0) - { + for (auto &s : switcher->sceneTransitions) { + if (sceneTransition.compare(s.sceneTransitionStr.c_str()) == + 0) { string scene1 = GetWeakSourceName(s.scene1); string scene2 = GetWeakSourceName(s.scene2); string transitionName = GetWeakSourceName(s.transition); ui->transitionsScene1->setCurrentText(scene1.c_str()); ui->transitionsScene2->setCurrentText(scene2.c_str()); - ui->transitionsTransitions->setCurrentText(transitionName.c_str()); + ui->transitionsTransitions->setCurrentText( + transitionName.c_str()); break; } } @@ -250,31 +241,31 @@ void SceneSwitcher::on_defaultTransitions_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->defaultTransitions->item(idx); + QListWidgetItem *item = ui->defaultTransitions->item(idx); QString sceneTransition = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->defaultSceneTransitions) - { - if (sceneTransition.compare(s.sceneTransitionStr.c_str()) == 0) - { + for (auto &s : switcher->defaultSceneTransitions) { + if (sceneTransition.compare(s.sceneTransitionStr.c_str()) == + 0) { string scene = GetWeakSourceName(s.scene); string transitionName = GetWeakSourceName(s.transition); - ui->defaultTransitionsScene->setCurrentText(scene.c_str()); - ui->defaultTransitionsTransitions->setCurrentText(transitionName.c_str()); + ui->defaultTransitionsScene->setCurrentText( + scene.c_str()); + ui->defaultTransitionsTransitions->setCurrentText( + transitionName.c_str()); break; } } } -obs_weak_source_t* getNextTransition(obs_weak_source_t* scene1, obs_weak_source_t* scene2) +obs_weak_source_t *getNextTransition(obs_weak_source_t *scene1, + obs_weak_source_t *scene2) { - obs_weak_source_t* ws = nullptr; - if (scene1 && scene2) - { - for (SceneTransition& t : switcher->sceneTransitions) - { + obs_weak_source_t *ws = nullptr; + if (scene1 && scene2) { + for (SceneTransition &t : switcher->sceneTransitions) { if (t.scene1 == scene1 && t.scene2 == scene2) ws = t.transition; } diff --git a/src/screen-region-switch.cpp b/src/screen-region-switch.cpp index bd42ab85..a5acea21 100644 --- a/src/screen-region-switch.cpp +++ b/src/screen-region-switch.cpp @@ -1,18 +1,16 @@ #include "headers/advanced-scene-switcher.hpp" -void SwitcherData::checkScreenRegionSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) +void SwitcherData::checkScreenRegionSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition) { pair cursorPos = getCursorPos(); int minRegionSize = 99999; - for (auto& s : screenRegionSwitches) - { - if (cursorPos.first >= s.minX && cursorPos.second >= s.minY - && cursorPos.first <= s.maxX && cursorPos.second <= s.maxY) - { + for (auto &s : screenRegionSwitches) { + if (cursorPos.first >= s.minX && cursorPos.second >= s.minY && + cursorPos.first <= s.maxX && cursorPos.second <= s.maxY) { int regionSize = (s.maxX - s.minX) + (s.maxY - s.minY); - if (regionSize < minRegionSize) - { + if (regionSize < minRegionSize) { match = true; scene = s.scene; transition = s.transition; @@ -43,40 +41,37 @@ void SceneSwitcher::on_screenRegionAdd_clicked() int maxX = ui->screenRegionMaxX->value(); int maxY = ui->screenRegionMaxY->value(); - string regionStr = to_string(minX) + ", " + to_string(minY) + " x " + to_string(maxX) + ", " - + to_string(maxY); + string regionStr = to_string(minX) + ", " + to_string(minY) + " x " + + to_string(maxX) + ", " + to_string(maxY); QString region = QString::fromStdString(regionStr); OBSWeakSource source = GetWeakSourceByQString(sceneName); OBSWeakSource transition = GetWeakTransitionByQString(transitionName); QVariant v = QVariant::fromValue(region); - QString text = MakeScreenRegionSwitchName(sceneName, transitionName, minX, minY, maxX, maxY); + QString text = MakeScreenRegionSwitchName(sceneName, transitionName, + minX, minY, maxX, maxY); int idx = ScreenRegionFindByData(region); - if (idx == -1) - { - QListWidgetItem* item = new QListWidgetItem(text, ui->screenRegions); + if (idx == -1) { + QListWidgetItem *item = + new QListWidgetItem(text, ui->screenRegions); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); switcher->screenRegionSwitches.emplace_back( source, transition, minX, minY, maxX, maxY, regionStr); - } - else - { - QListWidgetItem* item = ui->screenRegions->item(idx); + } else { + QListWidgetItem *item = ui->screenRegions->item(idx); item->setText(text); string curRegion = region.toUtf8().constData(); { lock_guard lock(switcher->m); - for (auto& s : switcher->screenRegionSwitches) - { - if (s.regionStr == curRegion) - { + for (auto &s : switcher->screenRegionSwitches) { + if (s.regionStr == curRegion) { s.scene = source; s.transition = transition; break; @@ -90,22 +85,21 @@ void SceneSwitcher::on_screenRegionAdd_clicked() void SceneSwitcher::on_screenRegionRemove_clicked() { - QListWidgetItem* item = ui->screenRegions->currentItem(); + QListWidgetItem *item = ui->screenRegions->currentItem(); if (!item) return; - string region = item->data(Qt::UserRole).toString().toUtf8().constData(); + string region = + item->data(Qt::UserRole).toString().toUtf8().constData(); { lock_guard lock(switcher->m); - auto& switches = switcher->screenRegionSwitches; + auto &switches = switcher->screenRegionSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s.regionStr == region) - { + if (s.regionStr == region) { switches.erase(it); break; } @@ -122,19 +116,18 @@ void SceneSwitcher::on_screenRegions_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->screenRegions->item(idx); + QListWidgetItem *item = ui->screenRegions->item(idx); QString region = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->screenRegionSwitches) - { - if (region.compare(s.regionStr.c_str()) == 0) - { + for (auto &s : switcher->screenRegionSwitches) { + if (region.compare(s.regionStr.c_str()) == 0) { string name = GetWeakSourceName(s.scene); string transitionName = GetWeakSourceName(s.transition); ui->screenRegionScenes->setCurrentText(name.c_str()); - ui->screenRegionsTransitions->setCurrentText(transitionName.c_str()); + ui->screenRegionsTransitions->setCurrentText( + transitionName.c_str()); ui->screenRegionMinX->setValue(s.minX); ui->screenRegionMinY->setValue(s.minY); ui->screenRegionMaxX->setValue(s.maxX); @@ -144,18 +137,16 @@ void SceneSwitcher::on_screenRegions_currentRowChanged(int idx) } } -int SceneSwitcher::ScreenRegionFindByData(const QString& region) +int SceneSwitcher::ScreenRegionFindByData(const QString ®ion) { int count = ui->screenRegions->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->screenRegions->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->screenRegions->item(i); QString itemRegion = item->data(Qt::UserRole).toString(); - if (itemRegion == region) - { + if (itemRegion == region) { idx = i; break; } diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index 791b6a5d..0e02a0f4 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -9,7 +9,8 @@ bool isRunning(std::string &title) // True if switch is running (direct) bool equals = windows.contains(title.c_str()); // True if switch is running (regex) - bool matches = (windows.indexOf(QRegularExpression(title.c_str())) != -1); + bool matches = + (windows.indexOf(QRegularExpression(title.c_str())) != -1); return (equals || matches); } @@ -22,7 +23,8 @@ bool isFocused(std::string &title) // True if switch equals current window bool equals = (title == current); // True if switch matches current window - bool matches = QString::fromStdString(current).contains(QRegularExpression(title.c_str())); + bool matches = QString::fromStdString(current).contains( + QRegularExpression(title.c_str())); return (equals || matches); } @@ -30,30 +32,30 @@ bool isFocused(std::string &title) void SceneSwitcher::on_up_clicked() { int index = ui->switches->currentRow(); - if (index != -1 && index != 0) - { - ui->switches->insertItem(index - 1, ui->switches->takeItem(index)); + if (index != -1 && index != 0) { + ui->switches->insertItem(index - 1, + ui->switches->takeItem(index)); ui->switches->setCurrentRow(index - 1); lock_guard lock(switcher->m); iter_swap(switcher->windowSwitches.begin() + index, - switcher->windowSwitches.begin() + index - 1); + switcher->windowSwitches.begin() + index - 1); } } void SceneSwitcher::on_down_clicked() { int index = ui->switches->currentRow(); - if (index != -1 && index != ui->switches->count() - 1) - { - ui->switches->insertItem(index + 1, ui->switches->takeItem(index)); + if (index != -1 && index != ui->switches->count() - 1) { + ui->switches->insertItem(index + 1, + ui->switches->takeItem(index)); ui->switches->setCurrentRow(index + 1); lock_guard lock(switcher->m); iter_swap(switcher->windowSwitches.begin() + index, - switcher->windowSwitches.begin() + index + 1); + switcher->windowSwitches.begin() + index + 1); } } @@ -72,32 +74,29 @@ void SceneSwitcher::on_add_clicked() OBSWeakSource transition = GetWeakTransitionByQString(transitionName); QVariant v = QVariant::fromValue(windowName); - QString text = MakeSwitchName(sceneName, windowName, transitionName, fullscreen, focus); + QString text = MakeSwitchName(sceneName, windowName, transitionName, + fullscreen, focus); int idx = FindByData(windowName); - if (idx == -1) - { + if (idx == -1) { lock_guard lock(switcher->m); switcher->windowSwitches.emplace_back( - source, windowName.toUtf8().constData(), transition, fullscreen, focus); + source, windowName.toUtf8().constData(), transition, + fullscreen, focus); - QListWidgetItem* item = new QListWidgetItem(text, ui->switches); + QListWidgetItem *item = new QListWidgetItem(text, ui->switches); item->setData(Qt::UserRole, v); - } - else - { - QListWidgetItem* item = ui->switches->item(idx); + } else { + QListWidgetItem *item = ui->switches->item(idx); item->setText(text); string window = windowName.toUtf8().constData(); { lock_guard lock(switcher->m); - for (auto& s : switcher->windowSwitches) - { - if (s.window == window) - { + for (auto &s : switcher->windowSwitches) { + if (s.window == window) { s.scene = source; s.transition = transition; s.fullscreen = fullscreen; @@ -111,22 +110,21 @@ void SceneSwitcher::on_add_clicked() void SceneSwitcher::on_remove_clicked() { - QListWidgetItem* item = ui->switches->currentItem(); + QListWidgetItem *item = ui->switches->currentItem(); if (!item) return; - string window = item->data(Qt::UserRole).toString().toUtf8().constData(); + string window = + item->data(Qt::UserRole).toString().toUtf8().constData(); { lock_guard lock(switcher->m); - auto& switches = switcher->windowSwitches; + auto &switches = switcher->windowSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s.window == window) - { + if (s.window == window) { switches.erase(it); break; } @@ -145,21 +143,23 @@ void SceneSwitcher::on_ignoreWindowsAdd_clicked() QVariant v = QVariant::fromValue(windowName); - QList items = ui->ignoreWindows->findItems(windowName, Qt::MatchExactly); + QList items = + ui->ignoreWindows->findItems(windowName, Qt::MatchExactly); - if (items.size() == 0) - { - QListWidgetItem* item = new QListWidgetItem(windowName, ui->ignoreWindows); + if (items.size() == 0) { + QListWidgetItem *item = + new QListWidgetItem(windowName, ui->ignoreWindows); item->setData(Qt::UserRole, v); lock_guard lock(switcher->m); - switcher->ignoreWindowsSwitches.emplace_back(windowName.toUtf8().constData()); + switcher->ignoreWindowsSwitches.emplace_back( + windowName.toUtf8().constData()); } } void SceneSwitcher::on_ignoreWindowsRemove_clicked() { - QListWidgetItem* item = ui->ignoreWindows->currentItem(); + QListWidgetItem *item = ui->ignoreWindows->currentItem(); if (!item) return; @@ -167,14 +167,12 @@ void SceneSwitcher::on_ignoreWindowsRemove_clicked() { lock_guard lock(switcher->m); - auto& switches = switcher->ignoreWindowsSwitches; + auto &switches = switcher->ignoreWindowsSwitches; - for (auto it = switches.begin(); it != switches.end(); ++it) - { - auto& s = *it; + for (auto it = switches.begin(); it != switches.end(); ++it) { + auto &s = *it; - if (s == windowName.toUtf8().constData()) - { + if (s == windowName.toUtf8().constData()) { switches.erase(it); break; } @@ -184,18 +182,16 @@ void SceneSwitcher::on_ignoreWindowsRemove_clicked() delete item; } -int SceneSwitcher::FindByData(const QString& window) +int SceneSwitcher::FindByData(const QString &window) { int count = ui->switches->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->switches->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->switches->item(i); QString itemWindow = item->data(Qt::UserRole).toString(); - if (itemWindow == window) - { + if (itemWindow == window) { idx = i; break; } @@ -204,18 +200,16 @@ int SceneSwitcher::FindByData(const QString& window) return idx; } -int SceneSwitcher::IgnoreWindowsFindByData(const QString& window) +int SceneSwitcher::IgnoreWindowsFindByData(const QString &window) { int count = ui->ignoreWindows->count(); int idx = -1; - for (int i = 0; i < count; i++) - { - QListWidgetItem* item = ui->ignoreWindows->item(i); + for (int i = 0; i < count; i++) { + QListWidgetItem *item = ui->ignoreWindows->item(i); QString itemRegion = item->data(Qt::UserRole).toString(); - if (itemRegion == window) - { + if (itemRegion == window) { idx = i; break; } @@ -231,15 +225,13 @@ void SceneSwitcher::on_switches_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->switches->item(idx); + QListWidgetItem *item = ui->switches->item(idx); QString window = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->windowSwitches) - { - if (window.compare(s.window.c_str()) == 0) - { + for (auto &s : switcher->windowSwitches) { + if (window.compare(s.window.c_str()) == 0) { string name = GetWeakSourceName(s.scene); string transitionName = GetWeakSourceName(s.transition); ui->scenes->setCurrentText(name.c_str()); @@ -259,37 +251,35 @@ void SceneSwitcher::on_ignoreWindows_currentRowChanged(int idx) if (idx == -1) return; - QListWidgetItem* item = ui->ignoreWindows->item(idx); + QListWidgetItem *item = ui->ignoreWindows->item(idx); QString window = item->data(Qt::UserRole).toString(); lock_guard lock(switcher->m); - for (auto& s : switcher->ignoreWindowsSwitches) - { - if (window.compare(s.c_str()) == 0) - { + for (auto &s : switcher->ignoreWindowsSwitches) { + if (window.compare(s.c_str()) == 0) { ui->ignoreWindowsWindows->setCurrentText(s.c_str()); break; } } } -void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBSWeakSource& transition) +void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene, + OBSWeakSource &transition) { string title; bool ignored = false; // Check if current window is ignored GetCurrentWindowTitle(title); - for (auto& window : ignoreWindowsSwitches) - { + for (auto &window : ignoreWindowsSwitches) { // True if ignored switch equals current window bool equals = (title == window); // True if ignored switch matches current window - bool matches = QString::fromStdString(title).contains(QRegularExpression(window.c_str())); + bool matches = QString::fromStdString(title).contains( + QRegularExpression(window.c_str())); - if (equals || matches) - { + if (equals || matches) { ignored = true; title = lastTitle; @@ -299,17 +289,17 @@ void SwitcherData::checkWindowTitleSwitch(bool& match, OBSWeakSource& scene, OBS lastTitle = title; // Check for match - for (WindowSceneSwitch& s : windowSwitches) - { + for (WindowSceneSwitch &s : windowSwitches) { // True if fullscreen is disabled OR current window is fullscreen bool fullscreen = (!s.fullscreen || isFullscreen(s.window)); // True if focus is disabled OR switch is focused bool focus = (!s.focus || isFocused(s.window)); // True if current window is ignored AND switch matches last window - bool ignore = (ignored && QString::fromStdString(title).contains(QRegularExpression(s.window.c_str()))); + bool ignore = (ignored && + QString::fromStdString(title).contains( + QRegularExpression(s.window.c_str()))); - if (isRunning(s.window) && (fullscreen && (focus || ignore))) - { + if (isRunning(s.window) && (fullscreen && (focus || ignore))) { match = true; scene = s.scene; transition = s.transition; From e693794549d3c0e36b5c5714b963352b9f65720e Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 9 Jun 2020 07:09:08 -0400 Subject: [PATCH 41/47] Add sorting of window lists for UI --- src/advanced-scene-switcher.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index 37b7dbc0..9fa4ccb3 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -130,6 +130,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent) vector windows; GetWindowList(windows); + sort(windows.begin(), windows.end()); for (string &window : windows) { ui->windows->addItem(window.c_str()); From 8e4a8b7e9d032df5953fa05324094769729e4110 Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 9 Jun 2020 07:10:30 -0400 Subject: [PATCH 42/47] Use QString::fromStdString() instead of c_str() --- src/executable-switch.cpp | 2 +- src/linux/advanced-scene-switcher-nix.cpp | 2 +- src/window-title-switch.cpp | 18 ++++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 7b345a35..05fef095 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -157,7 +157,7 @@ void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene, bool equals = (title == window); // True if ignored switch matches title bool matches = QString::fromStdString(title).contains( - QRegularExpression(window.c_str())); + QRegularExpression(QString::fromStdString(window))); if (equals || matches) { ignored = true; diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 2fc9b261..8a134674 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -274,7 +274,7 @@ bool isFullscreen(std::string &title) bool equals = (title == name); // True if switch matches window bool matches = QString::fromStdString(name).contains( - QRegularExpression(title.c_str())); + QRegularExpression(QString::fromStdString(title))); // If found, check if switch is fullscreen if (equals || matches) { diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index 0e02a0f4..d31e6f80 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -7,10 +7,10 @@ bool isRunning(std::string &title) GetWindowList(windows); // True if switch is running (direct) - bool equals = windows.contains(title.c_str()); + bool equals = windows.contains(QString::fromStdString(title)); // True if switch is running (regex) - bool matches = - (windows.indexOf(QRegularExpression(title.c_str())) != -1); + bool matches = (windows.indexOf(QRegularExpression( + QString::fromStdString(title))) != -1); return (equals || matches); } @@ -24,7 +24,7 @@ bool isFocused(std::string &title) bool equals = (title == current); // True if switch matches current window bool matches = QString::fromStdString(current).contains( - QRegularExpression(title.c_str())); + QRegularExpression(QString::fromStdString(title))); return (equals || matches); } @@ -277,7 +277,7 @@ void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene, bool equals = (title == window); // True if ignored switch matches current window bool matches = QString::fromStdString(title).contains( - QRegularExpression(window.c_str())); + QRegularExpression(QString::fromStdString(window))); if (equals || matches) { ignored = true; @@ -295,9 +295,11 @@ void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene, // True if focus is disabled OR switch is focused bool focus = (!s.focus || isFocused(s.window)); // True if current window is ignored AND switch matches last window - bool ignore = (ignored && - QString::fromStdString(title).contains( - QRegularExpression(s.window.c_str()))); + bool ignore = + (ignored && + QString::fromStdString(title).contains( + QRegularExpression( + QString::fromStdString(s.window)))); if (isRunning(s.window) && (fullscreen && (focus || ignore))) { match = true; From c9f1f9624b9473c420c191846fc0b85bc718b227 Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 9 Jun 2020 07:46:08 -0400 Subject: [PATCH 43/47] Use actual window titles and fix fullscreen check on macOS Fallback to window owner if title does not exist Remove duplicate entries from list --- src/osx/advanced-scene-switcher-osx.mm | 201 +++++++++++++++++-------- 1 file changed, 135 insertions(+), 66 deletions(-) diff --git a/src/osx/advanced-scene-switcher-osx.mm b/src/osx/advanced-scene-switcher-osx.mm index 5830c963..98737ac3 100644 --- a/src/osx/advanced-scene-switcher-osx.mm +++ b/src/osx/advanced-scene-switcher-osx.mm @@ -11,16 +11,32 @@ void GetWindowList(vector &windows) windows.resize(0); @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSArray *array = [ws runningApplications]; - for (NSRunningApplication *app in array) { - NSString *name = app.localizedName; - if (!name) - continue; + NSMutableArray *apps = + (__bridge NSMutableArray *)CGWindowListCopyWindowInfo( + kCGWindowListOptionAll, kCGNullWindowID); + for (NSDictionary *app in apps) { + // Construct string from NSString accounting for nil + string name([[app objectForKey:@"kCGWindowName"] + UTF8String], + [[app objectForKey:@"kCGWindowName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); + string owner([[app objectForKey:@"kCGWindowOwnerName"] + UTF8String], + [[app objectForKey:@"kCGWindowOwnerName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); - const char *str = name.UTF8String; - if (str && *str) - windows.emplace_back(str); + // Check if name exists + if (!name.empty() && + find(windows.begin(), windows.end(), name) == + windows.end()) + windows.emplace_back(name); + // Check if owner exists + else if (!owner.empty() && + find(windows.begin(), windows.end(), owner) == + windows.end()) + windows.emplace_back(owner); } } } @@ -31,16 +47,31 @@ void GetWindowList(QStringList &windows) windows.clear(); @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSArray *array = [ws runningApplications]; - for (NSRunningApplication *app in array) { - NSString *name = app.localizedName; - if (!name) - continue; + NSMutableArray *apps = + (__bridge NSMutableArray *)CGWindowListCopyWindowInfo( + kCGWindowListOptionAll, kCGNullWindowID); + for (NSDictionary *app in apps) { + // Construct string from NSString accounting for nil + string name([[app objectForKey:@"kCGWindowName"] + UTF8String], + [[app objectForKey:@"kCGWindowName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); + string owner([[app objectForKey:@"kCGWindowOwnerName"] + UTF8String], + [[app objectForKey:@"kCGWindowOwnerName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); - const char *str = name.UTF8String; - if (str && *str) - windows << QString(str); + // Check if name exists + if (!name.empty() && + !windows.contains(QString::fromStdString(name))) + windows << QString::fromStdString(name); + // Check if owner exists + else if (!owner.empty() && + !windows.contains( + QString::fromStdString(name))) + windows << QString::fromStdString(owner); } } } @@ -50,16 +81,36 @@ void GetCurrentWindowTitle(string &title) title.resize(0); @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSRunningApplication *app = [ws frontmostApplication]; - if (app) { - NSString *name = app.localizedName; - if (!name) - return; + NSMutableArray *apps = + (__bridge NSMutableArray *)CGWindowListCopyWindowInfo( + kCGWindowListOptionOnScreenOnly, + kCGNullWindowID); + for (NSDictionary *app in apps) { + int layer = + [[app objectForKey:@"kCGWindowLayer"] intValue]; + // True if window is frontmost + if (layer == 0) { + // Construct string from NSString accounting for nil + string name( + [[app objectForKey:@"kCGWindowName"] + UTF8String], + [[app objectForKey:@"kCGWindowName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); + string owner( + [[app objectForKey:@"kCGWindowOwnerName"] + UTF8String], + [[app objectForKey:@"kCGWindowOwnerName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); - const char *str = name.UTF8String; - if (str && *str) - title = str; + if (!name.empty()) + title = name; + else if (!owner.empty()) + title = owner; + + break; + } } } } @@ -75,54 +126,72 @@ pair getCursorPos() return pos; } -// Argument added in lieu of fullscreen bug fix -bool isFullscreen(std::string &title) +bool isFullscreen(string &title) { + // Check for match @autoreleasepool { - AXValueRef temp; - CGSize windowSize; - CGPoint windowPosition; - AXUIElementRef frontMostApp; - AXUIElementRef frontMostWindow; + NSArray *screens = [NSScreen screens]; + NSMutableArray *apps = + (__bridge NSMutableArray *)CGWindowListCopyWindowInfo( + kCGWindowListOptionAll, kCGNullWindowID); + for (NSDictionary *app in apps) { + // Construct string from NSString accounting for nil + string name([[app objectForKey:@"kCGWindowName"] + UTF8String], + [[app objectForKey:@"kCGWindowName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); + string owner([[app objectForKey:@"kCGWindowOwnerName"] + UTF8String], + [[app objectForKey:@"kCGWindowOwnerName"] + lengthOfBytesUsingEncoding: + NSUTF8StringEncoding]); - pid_t pid; - ProcessSerialNumber psn; - @try { - GetFrontProcess(&psn); - GetProcessPID(&psn, &pid); - frontMostApp = AXUIElementCreateApplication(pid); + // True if switch equals app + bool equals = (title == name || title == owner); + // True if switch matches app + bool matches = (QString::fromStdString(name).contains( + QRegularExpression( + QString::fromStdString( + title))) || + QString::fromStdString(owner).contains( + QRegularExpression( + QString::fromStdString( + title)))); - AXUIElementCopyAttributeValue( - frontMostApp, kAXFocusedWindowAttribute, - (CFTypeRef *)&frontMostWindow); + // If found, check if fullscreen + if (equals || matches) { + // Get window bounds + NSRect bounds; + CGRectMakeWithDictionaryRepresentation( + (CFDictionaryRef)[app + objectForKey:@"kCGWindowBounds"], + &bounds); - // Get the window size and position - AXUIElementCopyAttributeValue(frontMostWindow, - kAXSizeAttribute, - (CFTypeRef *)&temp); - AXValueGetValue(temp, kAXValueTypeCGSize, &windowSize); - CFRelease(temp); + // Compare to screen bounds + for (NSScreen *screen in screens) { + NSRect frame = [screen visibleFrame]; - AXUIElementCopyAttributeValue(frontMostWindow, - kAXPositionAttribute, - (CFTypeRef *)&temp); - AXValueGetValue(temp, kAXValueTypeCGPoint, - &windowPosition); - CFRelease(temp); + // True if flipped window origin equals screen origin + bool origin = + (bounds.origin.x == + frame.origin.x && + ([screens[0] visibleFrame] + .size.height - + frame.size.height - + bounds.origin.y == + frame.origin.y)); + // True if window size equals screen size + bool size = NSEqualSizes(bounds.size, + frame.size); - CGRect screenBound = CGDisplayBounds(CGMainDisplayID()); - CGSize screenSize = screenBound.size; - - if ((windowSize.width == screenSize.width) && - (windowSize.height == screenSize.height) && - (windowPosition.x == 0) && (windowPosition.y == 0)) - return true; - } @catch (...) { - // deal with the exception - } @catch (NSException *exception) { - // deal with the exception + if (origin && size) + return true; + } + } } } + return false; } From 66d847c04792e707a063c76a70ccfc6445a33e5e Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 9 Jun 2020 17:10:14 -0400 Subject: [PATCH 44/47] Fix ignored switches not directly matching last window --- src/executable-switch.cpp | 7 ++++--- src/window-title-switch.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 05fef095..512be7f3 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -178,10 +178,11 @@ void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene, QRegularExpression(s.mExe)) != -1); // True if focus is disabled OR switch is focused bool focus = (!s.mInFocus || isInFocus(s.mExe)); - // True if current window is ignored AND switch matches last window + // True if current window is ignored AND switch equals OR matches last window bool ignore = - (ignored && QString::fromStdString(title).contains( - QRegularExpression(s.mExe))); + (ignored && (title == s.mExe || + QString::fromStdString(title).contains( + QRegularExpression(s.mExe)))); if ((equals || matches) && (focus || ignore)) { match = true; diff --git a/src/window-title-switch.cpp b/src/window-title-switch.cpp index d31e6f80..f3baf143 100644 --- a/src/window-title-switch.cpp +++ b/src/window-title-switch.cpp @@ -294,12 +294,13 @@ void SwitcherData::checkWindowTitleSwitch(bool &match, OBSWeakSource &scene, bool fullscreen = (!s.fullscreen || isFullscreen(s.window)); // True if focus is disabled OR switch is focused bool focus = (!s.focus || isFocused(s.window)); - // True if current window is ignored AND switch matches last window + // True if current window is ignored AND switch equals OR matches last window bool ignore = (ignored && - QString::fromStdString(title).contains( - QRegularExpression( - QString::fromStdString(s.window)))); + (title == s.window || + QString::fromStdString(title).contains( + QRegularExpression( + QString::fromStdString(s.window))))); if (isRunning(s.window) && (fullscreen && (focus || ignore))) { match = true; From 7347be370e855017389b295e266c97a850937b8d Mon Sep 17 00:00:00 2001 From: Myned Date: Tue, 9 Jun 2020 17:14:22 -0400 Subject: [PATCH 45/47] Fix type error Pushed a little too soon --- src/executable-switch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/executable-switch.cpp b/src/executable-switch.cpp index 512be7f3..0aac4418 100644 --- a/src/executable-switch.cpp +++ b/src/executable-switch.cpp @@ -180,7 +180,7 @@ void SwitcherData::checkExeSwitch(bool &match, OBSWeakSource &scene, bool focus = (!s.mInFocus || isInFocus(s.mExe)); // True if current window is ignored AND switch equals OR matches last window bool ignore = - (ignored && (title == s.mExe || + (ignored && (title == s.mExe.toStdString() || QString::fromStdString(title).contains( QRegularExpression(s.mExe)))); From 7bfde0a39bb9ec3bb3e8bb543608155d8ac6578f Mon Sep 17 00:00:00 2001 From: Myned Date: Wed, 10 Jun 2020 04:06:04 -0400 Subject: [PATCH 46/47] Add regex matching to fullscreen check --- src/win/advanced-scene-switcher-win.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index d9667920..bf1e047e 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -111,7 +111,9 @@ bool isFullscreen(std::string &title) while (hwnd) { string wtitle; if (WindowValid(hwnd) && GetWindowTitle(hwnd, wtitle) && - wtitle == title) + (wtitle == title || + QString::fromStdString(wtitle).contains(QRegularExpression( + QString::fromStdString(title))))) break; hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); From 3151a7542f28e1ab5e93492a3eee6bf21efaa092 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Thu, 11 Jun 2020 16:25:17 +0200 Subject: [PATCH 47/47] return true in isFullscreen() if window maximized --- src/win/advanced-scene-switcher-win.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/win/advanced-scene-switcher-win.cpp b/src/win/advanced-scene-switcher-win.cpp index bf1e047e..1ea43573 100644 --- a/src/win/advanced-scene-switcher-win.cpp +++ b/src/win/advanced-scene-switcher-win.cpp @@ -124,6 +124,9 @@ bool isFullscreen(std::string &title) &monitorInfo); if (hwnd && hwnd != GetDesktopWindow() && hwnd != GetShellWindow()) { + if (IsZoomed(hwnd)) { + return true; + } GetWindowRect(hwnd, &appBounds); if (monitorInfo.rcMonitor.bottom == appBounds.bottom && monitorInfo.rcMonitor.top == appBounds.top &&