From 6f1dd312b9adb6af006a3a91fb013339aeeb3a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rgen=20Persson?= Date: Sun, 1 Jan 2023 10:25:28 +0100 Subject: [PATCH] More features for user idle mode --- LGTV Companion Service/Service.h | 2 +- LGTV Companion Setup/Product.wxs | 2 +- LGTV Companion UI/LGTV Companion UI.cpp | 538 +++++++++++++++------ LGTV Companion UI/LGTV Companion UI.h | 18 +- LGTV Companion UI/LGTV Companion UI.rc | Bin 36470 -> 39346 bytes LGTV Companion UI/resource.h | 26 +- LGTV Companion User/Daemon.cpp | 190 +++++--- LGTV Companion User/Daemon.h | 32 +- LGTV Companion User/LGTV Companion User.rc | 19 +- LGTV Companion User/resource.h | 3 +- 10 files changed, 593 insertions(+), 237 deletions(-) diff --git a/LGTV Companion Service/Service.h b/LGTV Companion Service/Service.h index f3ad09a..cbd5d00 100644 --- a/LGTV Companion Service/Service.h +++ b/LGTV Companion Service/Service.h @@ -37,7 +37,7 @@ #pragma comment(lib, "Iphlpapi.lib") #define APPNAME L"LGTV Companion" -#define APPVERSION L"1.8.7" +#define APPVERSION L"1.9.0" #define SVCNAME L"LGTVsvc" #define SVCDISPLAYNAME L"LGTV Companion Service" #define SERVICE_PORT "3000" diff --git a/LGTV Companion Setup/Product.wxs b/LGTV Companion Setup/Product.wxs index 9db5d52..e1b679d 100644 --- a/LGTV Companion Setup/Product.wxs +++ b/LGTV Companion Setup/Product.wxs @@ -3,7 +3,7 @@ - + diff --git a/LGTV Companion UI/LGTV Companion UI.cpp b/LGTV Companion UI/LGTV Companion UI.cpp index 1b2952a..bf98820 100644 --- a/LGTV Companion UI/LGTV Companion UI.cpp +++ b/LGTV Companion UI/LGTV Companion UI.cpp @@ -180,6 +180,7 @@ HWND hDeviceWindow = NULL; HWND hOptionsWindow = NULL; HWND hTopologyWindow = NULL; HWND hUserIdleConfWindow = NULL; +HWND hWhitelistConfWindow = NULL; wstring CommandLineParameters; wstring DataPath; @@ -199,6 +200,7 @@ HANDLE hPipe = INVALID_HANDLE_VALUE; WSADATA WSAData; int iTopConfPhase; int iTopConfDisplay; +vector WhitelistTemp; //Application entry point int APIENTRY wWinMain(_In_ HINSTANCE Instance, @@ -300,6 +302,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE Instance, !IsDialogMessage(hDeviceWindow,&msg) && !IsDialogMessage(hOptionsWindow,&msg) && !IsDialogMessage(hTopologyWindow, &msg) && + !IsDialogMessage(hUserIdleConfWindow, &msg) && + !IsDialogMessage(hWhitelistConfWindow, &msg) && !IsDialogMessage(hUserIdleConfWindow, &msg)) // if (!IsDialogMessage(hMainWnd, &msg)) @@ -1288,10 +1292,7 @@ LRESULT CALLBACK OptionsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l SendDlgItemMessage(hWnd, IDC_LIST, WM_SETFONT, (WPARAM)hEditMediumfont, MAKELPARAM(TRUE, 0)); SendDlgItemMessage(hWnd, IDC_SPIN, UDM_SETRANGE, (WPARAM)NULL, MAKELPARAM(100, 1)); SendDlgItemMessage(hWnd, IDC_SPIN, UDM_SETPOS, (WPARAM)NULL, (LPARAM)Prefs.PowerOnTimeout); - SendDlgItemMessage(hWnd, IDC_EDIT_BLANK, WM_SETFONT, (WPARAM)hEditMediumfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_SPIN2, UDM_SETRANGE, (WPARAM)NULL, MAKELPARAM(240, 1)); - SendDlgItemMessage(hWnd, IDC_SPIN2, UDM_SETPOS, (WPARAM)NULL, (LPARAM)Prefs.BlankScreenWhenIdleDelay); - + for (auto& item : Prefs.EventLogRestartString) { if (std::find(str.begin(), str.end(), widen(item)) == str.end()) @@ -1387,10 +1388,9 @@ LRESULT CALLBACK OptionsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l CheckDlgButton(hWnd, IDC_LOGGING, Prefs.Logging ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hWnd, IDC_AUTOUPDATE, Prefs.AutoUpdate ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hWnd, IDC_CHECK_BLANK, Prefs.BlankScreenWhenIdle ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(GetDlgItem(hWnd, IDC_EDIT_BLANK), Prefs.BlankScreenWhenIdle); CheckDlgButton(hWnd, IDC_CHECK_RDPBLANK, Prefs.PowerOffDuringRDP ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hWnd, IDC_CHECK_TOPOLOGY, Prefs.AdhereTopology ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(GetDlgItem(hWnd, IDOK), true); + EnableWindow(GetDlgItem(hWnd, IDOK), false); }break; case WM_COMMAND: { @@ -1408,24 +1408,16 @@ LRESULT CALLBACK OptionsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l if (mess == IDNO) { CheckDlgButton(hWnd, IDC_CHECK_BLANK, BST_UNCHECKED); - EnableWindow(GetDlgItem(hWnd, IDC_EDIT_BLANK), false); } if (mess == IDYES) { CheckDlgButton(hWnd, IDC_CHECK_BLANK, BST_CHECKED); - EnableWindow(GetDlgItem(hWnd, IDC_EDIT_BLANK), true); - Prefs.ResetAPIkeys = true; EnableWindow(GetDlgItem(hWnd, IDOK), true); } } else { - if (IsDlgButtonChecked(hWnd, IDC_CHECK_BLANK)) - EnableWindow(GetDlgItem(hWnd, IDC_EDIT_BLANK), true); - else - EnableWindow(GetDlgItem(hWnd, IDC_EDIT_BLANK), false); - EnableWindow(GetDlgItem(hWnd, IDOK), true); } }break; @@ -1484,7 +1476,6 @@ LRESULT CALLBACK OptionsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l } Prefs.AutoUpdate = IsDlgButtonChecked(hWnd, IDC_AUTOUPDATE); Prefs.BlankScreenWhenIdle = IsDlgButtonChecked(hWnd, IDC_CHECK_BLANK) == BST_CHECKED; - Prefs.BlankScreenWhenIdleDelay = atoi(narrow(GetWndText(GetDlgItem(hWnd, IDC_EDIT_BLANK))).c_str()); Prefs.PowerOffDuringRDP = IsDlgButtonChecked(hWnd, IDC_CHECK_RDPBLANK) == BST_CHECKED; Prefs.AdhereTopology = IsDlgButtonChecked(hWnd, IDC_CHECK_TOPOLOGY) == BST_CHECKED; @@ -1581,7 +1572,7 @@ LRESULT CALLBACK OptionsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l // explain the power saving options else if (wParam == IDC_SYSLINK5) { - MessageBox(hWnd, L"The option to automatically blank the screen triggers in the absence of user input from keyboard, mouse and/or controllers." + MessageBox(hWnd, L"The option to automatically blank the screen, i e turn the transmitters off, is triggered in the absence of user input from keyboard, mouse and/or controllers. " "The difference, when compared to both the screensaver and windows power plan settings, is that those OS implemented power saving functions " "utilize more obscured variables for determining user idle / busy states, and which can also be programmatically overridden f.e. by games, " "media players, production software or your web browser, In short, and simplified, this option is a more aggressively configured screen and " @@ -1969,6 +1960,7 @@ LRESULT CALLBACK ConfigureTopologyWndProc(HWND hWnd, UINT message, WPARAM wParam case WM_CLOSE: { EndDialog(hWnd, 0); + EnableWindow(GetParent(hWnd), true); }break; case WM_DESTROY: { @@ -1981,57 +1973,262 @@ LRESULT CALLBACK ConfigureTopologyWndProc(HWND hWnd, UINT message, WPARAM wParam } -// Process messages for the options window +// Process messages for the user idle conf window LRESULT CALLBACK UserIdleConfWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: { - /* - SendDlgItemMessage(hWnd, IDC_COMBO, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_NO_1, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_NO_2, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_NO_3, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_NO_4, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_NO_5, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_NO_6, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); + SendDlgItemMessage(hWnd, IDC_LIST, WM_SETFONT, (WPARAM)hEditMediumfont, MAKELPARAM(TRUE, 0)); + SendDlgItemMessage(hWnd, IDC_EDIT_TIME, WM_SETFONT, (WPARAM)hEditMediumfont, MAKELPARAM(TRUE, 0)); + SendDlgItemMessage(hWnd, IDC_SPIN, UDM_SETRANGE, (WPARAM)NULL, MAKELPARAM(240, 1)); + SendDlgItemMessage(hWnd, IDC_SPIN, UDM_SETPOS, (WPARAM)NULL, (LPARAM)Prefs.BlankScreenWhenIdleDelay); + + WhitelistTemp = Prefs.WhiteList; + SendMessage(hWnd, APP_LISTBOX_REDRAW, 0, 0); + + CheckDlgButton(hWnd, IDC_CHECK_WHITELIST, Prefs.bIdleWhitelistEnabled ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hWnd, IDC_CHECK_FULLSCREEN, Prefs.bFullscreenCheckEnabled ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_LIST), Prefs.bIdleWhitelistEnabled); + EnableWindow(GetDlgItem(hWnd, IDC_SYSLINK_ADD), Prefs.bIdleWhitelistEnabled); + EnableWindow(GetDlgItem(hWnd, IDC_SYSLINK_EDIR), Prefs.bIdleWhitelistEnabled); + EnableWindow(GetDlgItem(hWnd, IDC_SYSLINK_DELETE), Prefs.bIdleWhitelistEnabled); + EnableWindow(GetDlgItem(hWnd, IDOK), false); - SendDlgItemMessage(hWnd, IDC_STATIC_T_11, WM_SETFONT, (WPARAM)hEditSmallfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_T_12, WM_SETFONT, (WPARAM)hEditSmallfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_T_13, WM_SETFONT, (WPARAM)hEditSmallfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_T_14, WM_SETFONT, (WPARAM)hEditSmallfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_T_15, WM_SETFONT, (WPARAM)hEditSmallfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_T_16, WM_SETFONT, (WPARAM)hEditSmallfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_STATUS_1, WM_SETFONT, (WPARAM)hEditMediumfont, MAKELPARAM(TRUE, 0)); - SendDlgItemMessage(hWnd, IDC_STATIC_STATUS_2, WM_SETFONT, (WPARAM)hEditMediumBoldfont, MAKELPARAM(TRUE, 0)); - SetWindowText(GetDlgItem(hWnd, IDC_STATIC_STATUS_2), L"Not configured!"); - for (auto& k : Devices) + }break; + case APP_LISTBOX_EDIT: + { + int index = (int)SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_GETCURSEL, 0, 0); + if (index != LB_ERR) { - if (k.UniqueDeviceKey != "") - { - SetWindowText(GetDlgItem(hWnd, IDC_STATIC_STATUS_2), L"Configuration OK!"); + int data = (int)SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_GETITEMDATA, index, 0); + if (data != LB_ERR && data < WhitelistTemp.size()) + { + hWhitelistConfWindow = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_WHITELIST_EDIT), hWnd, (DLGPROC)WhitelistConfWndProc); + SetWindowText(hWhitelistConfWindow, L"Edit whitelisted process"); + SetWindowText(GetDlgItem(hWhitelistConfWindow, IDOK), L"Change"); + SetWindowText(GetDlgItem(hWhitelistConfWindow, IDC_EDIT_NAME), WhitelistTemp[data].Name.c_str()); + SetWindowText(GetDlgItem(hWhitelistConfWindow, IDC_EDIT_PROCESS), WhitelistTemp[data].Application.c_str()); + EnableWindow(hWnd, false); + ShowWindow(hWhitelistConfWindow, SW_SHOW); } } + }break; + case APP_LISTBOX_ADD: + { + hWhitelistConfWindow = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_WHITELIST_EDIT), hWnd, (DLGPROC)WhitelistConfWndProc); + SetWindowText(hWhitelistConfWindow, L"Add whitelisted process"); + SetWindowText(GetDlgItem(hWhitelistConfWindow, IDOK), L"Add"); + EnableWindow(hWnd, false); + ShowWindow(hWhitelistConfWindow, SW_SHOW); + }break; + case APP_LISTBOX_DELETE: + { - SendMessage(GetDlgItem(hWnd, IDC_COMBO), (UINT)CB_RESETCONTENT, (WPARAM)0, (LPARAM)0); - SendMessage(GetDlgItem(hWnd, IDC_COMBO), (UINT)CB_SETCURSEL, (WPARAM)-1, (LPARAM)0); + int index = (int)SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_GETCURSEL, 0, 0); + if (index != LB_ERR) + { + TCHAR * text; + int len = (int)SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_GETTEXTLEN, index, 0); + text = new TCHAR[len + 1]; + if (SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_GETTEXT, (WPARAM)index, (LPARAM)text) != LB_ERR) + { + wstring s = L"Do you want to delete '"; + s += text; + s += L"' from the whitelist?"; + if (MessageBox(hWnd, s.c_str(), L"Delete item", MB_YESNO | MB_ICONQUESTION) == IDYES) + { + int data = (int)SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_GETITEMDATA, index, 0); + if (data != LB_ERR && data < WhitelistTemp.size()) + { + WhitelistTemp.erase(WhitelistTemp.begin() + data); + SendMessage(hWnd, APP_LISTBOX_REDRAW, 0, 0); + } + else + { + MessageBox(hWnd, L"Could not delete item!", L"Error", MB_OK | MB_ICONINFORMATION); + } + } + } + else + { + MessageBox(hWnd, L"There was an error when managing the listbox", L"Error", MB_OK | MB_ICONINFORMATION); + } + } + }break; + case APP_LISTBOX_REDRAW: + { + int i = 0; + SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_RESETCONTENT, 0, 0); + for (auto& w : WhitelistTemp) + { + if (w.Application != L"" && w.Name != L"") + { + int index = (int)SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_ADDSTRING, 0, (LPARAM)(w.Name.c_str())); + SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_SETITEMDATA, index, (LPARAM)i); + i++; + } + } + if (SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_GETCOUNT, 0, 0) > 0) + { + SendMessage(GetDlgItem(hWnd, IDC_LIST), LB_SETCURSEL, 0, 0); + ShowWindow(GetDlgItem(hWnd, IDC_SYSLINK_EDIR), SW_SHOW); + ShowWindow(GetDlgItem(hWnd, IDC_SYSLINK_DELETE), SW_SHOW); - if (Devices.size() > 0) + } + else { - for (const auto& item : Devices) + ShowWindow(GetDlgItem(hWnd, IDC_SYSLINK_EDIR), SW_HIDE); + ShowWindow(GetDlgItem(hWnd, IDC_SYSLINK_DELETE), SW_HIDE); + } + }break; + case WM_COMMAND: + { + switch (HIWORD(wParam)) + { + case LBN_DBLCLK: + { + PostMessage(hWnd, APP_LISTBOX_EDIT, 0, 0); + }break; + + case BN_CLICKED: + { + switch (LOWORD(wParam)) { - stringstream s; - s << item.DeviceId << ": " << item.Name << "(" << item.IP << ")"; - SendMessage(GetDlgItem(hWnd, IDC_COMBO), (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)widen(s.str()).c_str()); + case IDC_CHECK_WHITELIST: + { + EnableWindow(GetDlgItem(hWnd, IDC_LIST), IsDlgButtonChecked(hWnd, IDC_CHECK_WHITELIST)); + EnableWindow(GetDlgItem(hWnd, IDC_SYSLINK_ADD), IsDlgButtonChecked(hWnd, IDC_CHECK_WHITELIST)); + EnableWindow(GetDlgItem(hWnd, IDC_SYSLINK_EDIR), IsDlgButtonChecked(hWnd, IDC_CHECK_WHITELIST)); + EnableWindow(GetDlgItem(hWnd, IDC_SYSLINK_DELETE), IsDlgButtonChecked(hWnd, IDC_CHECK_WHITELIST)); + EnableWindow(GetDlgItem(hWnd, IDOK), true); + }break; + case IDC_CHECK_FULLSCREEN: + { + EnableWindow(GetDlgItem(hWnd, IDOK), true); + }break; + case IDOK: + { + Prefs.BlankScreenWhenIdleDelay = atoi(narrow(GetWndText(GetDlgItem(hWnd, IDC_EDIT_TIME))).c_str()); + Prefs.bFullscreenCheckEnabled = IsDlgButtonChecked(hWnd, IDC_CHECK_FULLSCREEN); + Prefs.bIdleWhitelistEnabled = IsDlgButtonChecked(hWnd, IDC_CHECK_WHITELIST); + Prefs.WhiteList = WhitelistTemp; + EndDialog(hWnd, 0); + EnableWindow(GetParent(hWnd), true); + EnableWindow(GetDlgItem(GetParent(hWnd), IDOK), true); + }break; + case IDCANCEL: + { + EndDialog(hWnd, 0); + EnableWindow(GetParent(hWnd), true); + }break; + default:break; } - SendMessage(GetDlgItem(hWnd, IDC_COMBO), (UINT)CB_SETCURSEL, (WPARAM)0, (LPARAM)0); + }break; + case EN_CHANGE: + { + switch (LOWORD(wParam)) + { + case IDC_EDIT_TIME: + { + EnableWindow(GetDlgItem(hWnd, IDOK), true); + }break; + default:break; + } + }break; + default:break; } - SendMessage(hWnd, APP_TOP_PHASE_1, NULL, NULL); - iTopConfDisplay = 0; - */ }break; + case WM_NOTIFY: + { + switch (((NMHDR*)lParam)->code) + { + case NM_CLICK: + { + if (wParam == IDC_SYSLINK_INFO_1) + { + MessageBox(hWnd, L"Please configure the time, in minutes, without user input from keyboard, mouse or game controllers before " + "triggering the user idle mode.",L"User idle time configuration", MB_OK | MB_ICONINFORMATION); + } + else if (wParam == IDC_SYSLINK_INFO_2) + { + MessageBox(hWnd, L"The option prevents user idle mode when a whitelisted process is running on the system. Enable the option to prevent user idle mode " + "while running a movie player, for example.", L"User idle mode whitelist configuration", MB_OK | MB_ICONINFORMATION); + } + else if (wParam == IDC_SYSLINK_INFO_3) + { + MessageBox(hWnd, L"The option prevents user idle mode when an application or game is running in fullscreen " + "mode.", L"User idle mode fullscreen configuration", MB_OK | MB_ICONINFORMATION); + } + else if (wParam == IDC_SYSLINK_ADD) + { + PostMessage(hWnd, APP_LISTBOX_ADD, 0, 0); + } + else if (wParam == IDC_SYSLINK_EDIR) + { + PostMessage(hWnd, APP_LISTBOX_EDIT, 0, 0); + } + else if (wParam == IDC_SYSLINK_DELETE) + { + PostMessage(hWnd, APP_LISTBOX_DELETE, 0, 0); + } + }break; + default:break; + } + }break; + case WM_CTLCOLORSTATIC: + { + HDC hdcStatic = (HDC)wParam; + SetTextColor(hdcStatic, COLORREF(COLOR_STATIC)); + if ((HWND)lParam == GetDlgItem(hWnd, IDC_CHECK_WHITELIST) + || (HWND)lParam == GetDlgItem(hWnd, IDC_CHECK_FULLSCREEN)) + { + SetBkMode(hdcStatic, TRANSPARENT); + } + return(INT_PTR)hBackbrush; + }break; + + case WM_PAINT: + { + RECT rc = { 0 }; + + GetClientRect(hWnd, &rc); + + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hWnd, &ps); + FillRect(hdc, &rc, (HBRUSH)hBackbrush); + + EndPaint(hWnd, &ps); + }break; + + case WM_CLOSE: + { + EndDialog(hWnd, 0); + EnableWindow(GetParent(hWnd), true); + }break; + case WM_DESTROY: + { + hUserIdleConfWindow = NULL; + }break; + default: + return false; + } + return true; +} + +// Process messages for the user idle conf window +LRESULT CALLBACK WhitelistConfWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + { + SendDlgItemMessage(hWnd, IDC_EDIT_NAME, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); + SendDlgItemMessage(hWnd, IDC_EDIT_PROCESS, WM_SETFONT, (WPARAM)hEditfont, MAKELPARAM(TRUE, 0)); + }break; + case WM_COMMAND: { @@ -2044,127 +2241,154 @@ LRESULT CALLBACK UserIdleConfWndProc(HWND hWnd, UINT message, WPARAM wParam, LPA case IDOK: { - /* - switch (iTopConfPhase) // three phases - intro, match displays, finalise + wstring name = GetWndText(GetDlgItem(hWnd, IDC_EDIT_NAME)); + wstring proc = GetWndText(GetDlgItem(hWnd, IDC_EDIT_PROCESS)); + + if (name.find_last_of(L"\\/") != string::npos) { - case 1: + name = name.substr(name.find_last_of(L"\\/")); + name.erase(0, 1); + } + if (proc.find_last_of(L"\\/") != string::npos) { - vector displays = QueryDisplays(); - // No WebOs devices attached - if (displays.size() == 0) + proc = proc.substr(proc.find_last_of(L"\\/")); + proc.erase(0, 1); + } + + if (name != L"" && proc != L"") + { + if (GetWndText(GetDlgItem(hWnd, IDOK)) == L"Add") // add item { - MessageBox(hWnd, L"To configure your devices, ensure that all your WebOS-devices are powered ON, connected to to your PC and enabled (with an extended desktop in case of multiple displays).", L"No WebOS devices detected", MB_OK | MB_ICONWARNING); - break; + WHITELIST w; + w.Name = name; + w.Application = proc; + WhitelistTemp.push_back(w); } - // If exactly one physical device connected/enabled and exactly one device cofigured it is considered an automatic match - else if (Devices.size() == 1 && displays.size() == 1) + else //change item { - if (MessageBox(hWnd, L"Your device can be automatically configured.\n\nDo you want to accept the automatic configuration?", L"Automatic match", MB_YESNO) == IDYES) + if (hUserIdleConfWindow) { - Devices[0].UniqueDeviceKey_Temp = narrow(displays[0].target.monitorDevicePath); - SendMessage(hWnd, APP_TOP_PHASE_3, NULL, NULL); - SetWindowText(GetDlgItem(hWnd, IDC_STATIC_STATUS_2), L"All OK!"); - break; + int index = (int)SendMessage(GetDlgItem(hUserIdleConfWindow, IDC_LIST), LB_GETCURSEL, 0, 0); + if (index != LB_ERR) + { + int data = (int)SendMessage(GetDlgItem(hUserIdleConfWindow, IDC_LIST), LB_GETITEMDATA, index, 0); + if (data != LB_ERR && data < WhitelistTemp.size()) + { + WhitelistTemp[data].Application = proc; + WhitelistTemp[data].Name = name; + } + } } } - SendMessage(hWnd, APP_TOP_PHASE_2, NULL, NULL); - SendMessage(hWnd, APP_TOP_NEXT_DISPLAY, NULL, NULL); - }break; - case 2: - { - vector displays = QueryDisplays(); - int sel = (int)(SendMessage(GetDlgItem(hWnd, IDC_COMBO), (UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0)); - if (sel == CB_ERR || Devices.size() <= sel) - break; - Devices[sel].UniqueDeviceKey_Temp = narrow(displays[iTopConfDisplay].target.monitorDevicePath); - - iTopConfDisplay++; - if (iTopConfDisplay >= displays.size()) // all displays iterated - { - SendMessage(hWnd, APP_TOP_PHASE_3, NULL, NULL); - } - else // more displays are connected - { - SendMessage(hWnd, APP_TOP_NEXT_DISPLAY, NULL, NULL); - } - }break; - case 3: - { - for (auto& k : Devices) - { - k.UniqueDeviceKey = k.UniqueDeviceKey_Temp; - } EndDialog(hWnd, 0); + SendMessage(GetParent(hWnd), APP_LISTBOX_REDRAW, 0, 0); EnableWindow(GetParent(hWnd), true); EnableWindow(GetDlgItem(GetParent(hWnd), IDOK), true); - }break; - default:break; } - */ + else + { + MessageBox(hWnd, L"Please ensure that both display name and process executable name are properly " + "configured before continuing. Please note that process executable name should not include the path.", + L"Invalid configuration", MB_OK | MB_ICONERROR); + } + }break; case IDCANCEL: { - /* - bool conf = false; - for (auto& k : Devices) - { - if (k.UniqueDeviceKey != "") - { - conf = true; - break; - } - } - if (!conf) - { - CheckDlgButton(GetParent(hWnd), IDC_CHECK_TOPOLOGY, BST_UNCHECKED); - } - */ EndDialog(hWnd, 0); EnableWindow(GetParent(hWnd), true); }break; default:break; } }break; + case EN_CHANGE: + { + switch (LOWORD(wParam)) + { + case IDC_EDIT_NAME: + case IDC_EDIT_PROCESS: + { + EnableWindow(GetDlgItem(hWnd, IDOK), true); + }break; + default:break; + } + }break; default:break; } }break; - case WM_CTLCOLORSTATIC: + case WM_NOTIFY: { - /* - HDC hdcStatic = (HDC)wParam; - if ((HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_1) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_2) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_3) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_4) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_T_1) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_T_2) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_T_3) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_T_4) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_STATUS_1) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_STATUS_2)) + switch (((NMHDR*)lParam)->code) { - SetBkMode(hdcStatic, TRANSPARENT); - } - if ((HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_STATUS_2)) + case NM_CLICK: { - wstring s = GetWndText(GetDlgItem(hWnd, IDC_STATIC_STATUS_2)); - if(s.find(L"OK!") != wstring::npos) - SetTextColor(hdcStatic, COLORREF(COLOR_GREEN)); - else if (s.find(L"Updating") != wstring::npos) - SetTextColor(hdcStatic, COLORREF(COLOR_BLUE)); - else - SetTextColor(hdcStatic, COLORREF(COLOR_RED)); - } + if (wParam == IDC_SYSLINK_BROWSE) + { + IFileOpenDialog* pfd; + DWORD dwOptions; + LPWSTR Path; + IShellItem* psi; + COMDLG_FILTERSPEC aFileTypes[] = { + { L"Executable files", L"*.exe" }, + { L"All files", L"*.*" }, + }; + + if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { + if (SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, reinterpret_cast(&pfd)))) { + if (SUCCEEDED(pfd->GetOptions(&dwOptions))) + { + pfd->SetOptions(dwOptions | FOS_FILEMUSTEXIST); + pfd->SetFileTypes(_countof(aFileTypes), aFileTypes); + if (SUCCEEDED(pfd->Show(hWnd))) + if (SUCCEEDED(pfd->GetResult(&psi))) { + if (SUCCEEDED(psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &Path))) + { - else if ((HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_1) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_2) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_3) - || (HWND)lParam == GetDlgItem(hWnd, IDC_STATIC_NO_4)) - SetTextColor(hdcStatic, COLORREF(COLOR_BLUE)); - else - SetTextColor(hdcStatic, COLORREF(COLOR_STATIC)); -*/ + TCHAR buffer[MAX_PATH] = { 0 }; + GetModuleFileName(NULL, buffer, MAX_PATH); + + wstring path = Path; + wstring exe, name; + std::wstring::size_type pos = path.find_last_of(L"\\/"); + if (pos != wstring::npos) + { + exe = path.substr(pos); + exe.erase(0, 1); + pos = exe.find_last_of(L"."); + if (pos != wstring::npos) + { + name = exe.substr(0, pos); + } + if (GetWndText(GetDlgItem(hWnd, IDC_EDIT_NAME)) == L"") + SetWindowText(GetDlgItem(hWnd, IDC_EDIT_NAME), name.c_str()); + SetWindowText(GetDlgItem(hWnd, IDC_EDIT_PROCESS), exe.c_str()); + } + + CoTaskMemFree(Path); + + } + psi->Release(); + } + } + pfd->Release(); + } + CoUninitialize(); + } + } + }break; + default:break; + } + }break; + case WM_CTLCOLORSTATIC: + { + HDC hdcStatic = (HDC)wParam; + SetTextColor(hdcStatic, COLORREF(COLOR_STATIC)); +// if ((HWND)lParam == GetDlgItem(hWnd, IDC_CHECK_WHITELIST) +// || (HWND)lParam == GetDlgItem(hWnd, IDC_CHECK_FULLSCREEN)) +// { +// SetBkMode(hdcStatic, TRANSPARENT); +// } return(INT_PTR)hBackbrush; }break; @@ -2184,10 +2408,11 @@ LRESULT CALLBACK UserIdleConfWndProc(HWND hWnd, UINT message, WPARAM wParam, LPA case WM_CLOSE: { EndDialog(hWnd, 0); + EnableWindow(GetParent(hWnd), true); }break; - case WM_DESTROY: + case WM_DESTROY: { - hUserIdleConfWindow = NULL; + hWhitelistConfWindow = NULL; }break; default: return false; @@ -2297,6 +2522,25 @@ bool ReadConfigFile() if (!j.empty() && j.is_boolean()) Prefs.AdhereTopology = j.get(); + j = jsonPrefs[JSON_PREFS_NODE][JSON_IDLEWHITELIST]; + if (!j.empty() && j.is_boolean()) + Prefs.bIdleWhitelistEnabled = j.get(); + + j = jsonPrefs[JSON_PREFS_NODE][JSON_IDLEFULLSCREEN]; + if (!j.empty() && j.is_boolean()) + Prefs.bFullscreenCheckEnabled = j.get(); + + j = jsonPrefs[JSON_PREFS_NODE][JSON_WHITELIST]; + if (!j.empty() && j.size() > 0) + { + for (auto& elem : j.items()) + { + WHITELIST w; + w.Application = widen(elem.value().get()); + w.Name = widen(elem.key()); + Prefs.WhiteList.push_back(w); + } + } return true; } } @@ -2556,6 +2800,8 @@ void WriteConfigFile(void) prefs[JSON_PREFS_NODE][JSON_IDLEBLANKDELAY] = (int)Prefs.BlankScreenWhenIdleDelay; prefs[JSON_PREFS_NODE][JSON_RDP_POWEROFF] = (bool)Prefs.PowerOffDuringRDP; prefs[JSON_PREFS_NODE][JSON_ADHERETOPOLOGY] = (bool)Prefs.AdhereTopology; + prefs[JSON_PREFS_NODE][JSON_IDLEWHITELIST] = (bool)Prefs.bIdleWhitelistEnabled; + prefs[JSON_PREFS_NODE][JSON_IDLEFULLSCREEN] = (bool)Prefs.bFullscreenCheckEnabled; for (auto& item : Prefs.EventLogRestartString) prefs[JSON_PREFS_NODE][JSON_EVENT_RESTART_STRINGS].push_back(item); @@ -2563,6 +2809,12 @@ void WriteConfigFile(void) for (auto& item : Prefs.EventLogShutdownString) prefs[JSON_PREFS_NODE][JSON_EVENT_SHUTDOWN_STRINGS].push_back(item); + if (Prefs.WhiteList.size() > 0) + { + for (auto& w : Prefs.WhiteList) + prefs[JSON_PREFS_NODE][JSON_WHITELIST][narrow(w.Name)] = narrow(w.Application); + } + //Iterate nodes int deviceid = 1; for (auto& item : Devices) diff --git a/LGTV Companion UI/LGTV Companion UI.h b/LGTV Companion UI/LGTV Companion UI.h index 2784030..b42e9d7 100644 --- a/LGTV Companion UI/LGTV Companion UI.h +++ b/LGTV Companion UI/LGTV Companion UI.h @@ -53,7 +53,7 @@ #define APPNAME_SHORT L"LGTVcomp" #define APPNAME_FULL L"LGTV Companion" -#define APP_VERSION L"1.8.7" +#define APP_VERSION L"1.9.0" #define WINDOW_CLASS_UNIQUE L"YOLOx0x0x0181818" #define NOTIFY_NEW_COMMANDLINE 1 @@ -67,6 +67,10 @@ #define JSON_IDLEBLANK "BlankWhenIdle" #define JSON_IDLEBLANKDELAY "BlankWhenIdleDelay" #define JSON_ADHERETOPOLOGY "AdhereDisplayTopology" +#define JSON_IDLEWHITELIST "IdleWhiteListEnabled" +#define JSON_IDLEFULLSCREEN "IdleFullscreen" +#define JSON_WHITELIST "IdleWhiteList" + #define DEFAULT_RESTART {"restart"} #define DEFAULT_SHUTDOWN {"shutdown","power off"} #define JSON_RDP_POWEROFF "PowerOffDuringRDP" @@ -89,6 +93,10 @@ #define APP_TOP_PHASE_2 WM_USER+11 #define APP_TOP_PHASE_3 WM_USER+12 #define APP_TOP_NEXT_DISPLAY WM_USER+13 +#define APP_LISTBOX_EDIT WM_USER+14 +#define APP_LISTBOX_ADD WM_USER+15 +#define APP_LISTBOX_DELETE WM_USER+16 +#define APP_LISTBOX_REDRAW WM_USER+17 #define APP_CMDLINE_ON 1 #define APP_CMDLINE_OFF 2 @@ -109,6 +117,10 @@ #define VERSIONCHECKLINK L"https://api.github.com/repos/JPersson77/LGTVCompanion/releases" #define DONATELINK L"https://www.paypal.com/donate/?hosted_button_id=TGZRPAHV4QC62" +struct WHITELIST { + std::wstring Name; + std::wstring Application; +}; struct PREFS { std::vector EventLogRestartString = DEFAULT_RESTART; std::vector EventLogShutdownString = DEFAULT_SHUTDOWN; @@ -121,6 +133,9 @@ struct PREFS { int BlankScreenWhenIdleDelay = 10; bool PowerOffDuringRDP = false; bool AdhereTopology = false; + bool bIdleWhitelistEnabled = false; + bool bFullscreenCheckEnabled = false; + std::vector WhiteList; }; struct SESSIONPARAMETERS { std::string DeviceId; @@ -156,6 +171,7 @@ LRESULT CALLBACK DeviceWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK OptionsWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK ConfigureTopologyWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK UserIdleConfWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK WhitelistConfWndProc(HWND, UINT, WPARAM, LPARAM); bool MessageExistingProcess(std::wstring); bool ReadConfigFile(); diff --git a/LGTV Companion UI/LGTV Companion UI.rc b/LGTV Companion UI/LGTV Companion UI.rc index 8d8cb7fd298da4e45d7fc2009dfbbe13960285f3..c7718a03999c3a9fceff224bf190872109b9440e 100644 GIT binary patch delta 1629 zcmZux-%p!m6h7ZNsD;+G^cSrnwJ_c&w0P^o7I>v&6~dGJnwnVdCob1 z+&%K`-jUt!rx3kQt2kHqaNWO?xW@hKKE9WD$dmRkS0Wv46SNHD zIhUL7r)Sw|_qpQ~ryLDY3||&!n$mj{nOpf|V#wekqzpN(4+r>Rdy{`3IOV#aM}e(D zbJV1HUR>zmof}u#=?q&9D>!)h$7VPGHqw4fUW((T1kMCy_`z00o8hlFd-&I;T|8V# zO1Ai9DJ?#>DdhF8%IHBep#0>GXp3ipzvzhZ^+wnc17ESkkVKZJUJLN0ji|py({z?5 zsH7~q2Xf=jHx_yA#Lu=UcnK!XucuFQC^zD$!GDs@&=l1u#`RpDPo3_z>c|Xh$Nf@H zTZxuX^~==czicnKW@r?sX+){utkN_e`1*Li*T;`f1_y^IrHYKqRjepEr~}p0KLbGp zM0}fF4mZz+p1Ww?>iG--nNrx4s#8+EQ~{<6mQ^6nBYKE7@H1~GaVwb!t1|3)SVpPD zn%&EG&+~k;F@Q{7ZOcQ$IesV7XRX1fNJZrA=SxwaUs^(<>ai0BgCyteDQgL+2CWIs zRzrj$Vx3pWf+PD3nKKmExhrI65qhF$q+FN`&Njkge$mAIHQg#l_YDcF}@ab zy65Rbhe%>Do@-N#S9vSP_ zGIFys9@J8N_;Jl5LVQ*pglkStEy?FfettaevtThO3r0-NHesiHwHVjR5eu42`R;B9 zwFDnd`1w)A7x-WCWdU)$Pz5H%n#0SxXJ6#mayQ=_3u;;3DnYlObhw=%$l#cG1B>2kqvfjh_2>bu)K3H|OU&-}%njYj^#8+0}X@61S*8 z%T%H}G)W%H(-~T2TcP_@X0QB}jrb-NIa=Yj%AQS*+@&>sllUfz_}v&)JowY=Mk)Le zHpc`!kFD+`Whg-xX^yc4sT5-y;-}(Zat2>K*HAirOcBU>-}VcRszy9WQN*|6xT#wQ z5|pC{M*kJ=o5Pm6fnG&M)YcFZ31g`t6Jt2xx1fOi{`0Cq3rV;7Y z&9)lm{il$rrcMabn2w|(ebX4P+k4h{oHDlSF4%X6@y>2TpVg{_uv1%bawC(tW>`T2 z2el#WH^e}m2^I{=ij0uM_eRSJC=QKfIX)ONQ1pM%AP%cV?v?ch@M^^2 z?1&XLd+O3+V|@sZ#JG2b7mzn3k&E!qL%MCOWtCavc`X%Qf{P{Hsa+n5867%oqCBmf zIEeGrKv>F}qcQf(Qi^6MOG&y)OZ*miT{2U!j&fa^iJ>B~Ru<9pAG#t2vdrq7LzpddMct9MEV8yu|1Z{1YAsCGAv((0o(Q;S`7rPC zfmV3_9J7&17`mW&cEl|)U&Wx$+5T|uiqih^B-V}R>63W>?1CjiI+mZh Sus?UH-MaBwX}{PV?fwhO9 Devices; -LASTINPUTINFO SavedLII; //Application entry point int APIENTRY wWinMain(_In_ HINSTANCE Instance, @@ -38,8 +37,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE Instance, WindowTitle = APPNAME_FULL; WindowTitle += L" v"; WindowTitle += APP_VERSION; - SavedLII.cbSize = sizeof(LASTINPUTINFO); - SavedLII.dwTime = 0; //commandline processing if (lpCmdLine) @@ -111,13 +108,20 @@ int APIENTRY wWinMain(_In_ HINSTANCE Instance, if (Prefs.AdhereTopology) SetTimer(hMainWnd, TIMER_TOPOLOGY, 8000, (TIMERPROC)NULL); - wstring startupmess = WindowTitle; startupmess += L" is running."; Log(startupmess); HPOWERNOTIFY rsrn = RegisterSuspendResumeNotification(hMainWnd, DEVICE_NOTIFY_WINDOW_HANDLE); HPOWERNOTIFY rpsn = RegisterPowerSettingNotification(hMainWnd, &(GUID_CONSOLE_DISPLAY_STATE), DEVICE_NOTIFY_WINDOW_HANDLE); + /* + DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; + ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); + NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + memcpy(&(NotificationFilter.dbcc_classguid), &(GUID_DEVINTERFACE_USB_DEVICE), sizeof(struct _GUID)); + HDEVNOTIFY dev_notify = RegisterDeviceNotification(hMainWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); + */ WTSRegisterSessionNotification(hMainWnd, NOTIFY_FOR_ALL_SESSIONS); @@ -147,6 +151,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE Instance, UnregisterSuspendResumeNotification(rsrn); UnregisterPowerSettingNotification(rpsn); +// UnregisterDeviceNotification(dev_notify); WTSUnRegisterSessionNotification(hMainWnd); return (int)msg.wParam; } @@ -245,7 +250,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { LASTINPUTINFO lii; lii.cbSize = sizeof(LASTINPUTINFO); - if (GetLastUserInputTime(&lii)) + if (GetLastInputInfo(&lii)) { if (bDaemonVisible) { @@ -253,7 +258,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) DWORD time = (GetTickCount() - lii.dwTime) / 1000; wstring ago = widen(to_string(time)); - SendMessage(GetDlgItem(hMainWnd, IDC_EDIT2), WM_SETTEXT, 0, (WPARAM)tick.c_str()); +// SendMessage(GetDlgItem(hMainWnd, IDC_EDIT2), WM_SETTEXT, 0, (WPARAM)tick.c_str()); SendMessage(GetDlgItem(hMainWnd, IDC_EDIT3), WM_SETTEXT, 0, (WPARAM)ago.c_str()); } if (bIdle) @@ -268,12 +273,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } else { - SetTimer(hWnd, TIMER_MAIN, TIMER_MAIN_DELAY_WHEN_BUSY, (TIMERPROC)NULL); + SetTimer(hWnd, TIMER_MAIN, bDaemonVisible?(TIMER_MAIN_DELAY_WHEN_BUSY)/10: TIMER_MAIN_DELAY_WHEN_BUSY, (TIMERPROC)NULL); SetTimer(hWnd, TIMER_IDLE, Prefs.BlankScreenWhenIdleDelay * 60 * 1000, (TIMERPROC)NULL); dwLastInputTick = lii.dwTime; bIdlePreventEarlyWakeup = false; bIdle = false; - // Log(L"Busy"); CommunicateWithService("-daemon userbusy"); } } @@ -294,14 +298,35 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) }break; case TIMER_IDLE: { + if (Prefs.bFullscreenCheckEnabled) + if (FullscreenApplicationRunning()) + { + Log(L"Fullscreen application prohibiting idle"); + return 0; + } + if (Prefs.bIdleWhitelistEnabled) + { + string proc = WhitelistProcessRunning(); + if (proc != "") + { + wstring mess = L"Whitelisted application prohibiting idle ("; + mess += widen(proc); + mess += L")"; + Log(mess); + return 0; + } + } + bIdle = true; bIdlePreventEarlyWakeup = false; - // KillTimer(hWnd, TIMER_IDLE); + SetTimer(hWnd, TIMER_MAIN, TIMER_MAIN_DELAY_WHEN_IDLE, (TIMERPROC)NULL); - // Log(L"Idle"); + CommunicateWithService("-daemon useridle"); + return 0; }break; + case TIMER_RDP: { KillTimer(hWnd, TIMER_RDP); @@ -386,7 +411,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) bIdlePreventEarlyWakeup = false; if (Prefs.BlankScreenWhenIdle) { - SetTimer(hWnd, TIMER_MAIN, TIMER_MAIN_DELAY_WHEN_BUSY, (TIMERPROC)NULL); + SetTimer(hWnd, TIMER_MAIN, bDaemonVisible?(TIMER_MAIN_DELAY_WHEN_BUSY)/10: TIMER_MAIN_DELAY_WHEN_BUSY, (TIMERPROC)NULL); SetTimer(hWnd, TIMER_IDLE, Prefs.BlankScreenWhenIdleDelay * 60 * 1000, (TIMERPROC)NULL); } Log(L"Resuming system."); @@ -415,7 +440,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) bIdlePreventEarlyWakeup = false; if (Prefs.BlankScreenWhenIdle) { - SetTimer(hWnd, TIMER_MAIN, TIMER_MAIN_DELAY_WHEN_BUSY, (TIMERPROC)NULL); + SetTimer(hWnd, TIMER_MAIN, bDaemonVisible?(TIMER_MAIN_DELAY_WHEN_BUSY)/10: TIMER_MAIN_DELAY_WHEN_BUSY, (TIMERPROC)NULL); SetTimer(hWnd, TIMER_IDLE, Prefs.BlankScreenWhenIdleDelay * 60 * 1000, (TIMERPROC)NULL); } Log(L"System requests displays ON."); @@ -428,6 +453,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) default:break; } }break; + case USER_DISPLAYCHANGE: { CheckDisplayTopology(); @@ -442,7 +468,50 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } }break; + /* + case WM_DEVICECHANGE: + { + if (lParam) + { + PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; + PDEV_BROADCAST_DEVICEINTERFACE lpdbv = (PDEV_BROADCAST_DEVICEINTERFACE)lpdb; + wstring path; + if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + { + path = wstring(lpdbv->dbcc_name); + switch (wParam) + { + case DBT_DEVICEARRIVAL: + { + for (auto& dev : usb_list) + { + if (path.find(dev, 0) != wstring::npos) + { + wstring s = L"New device connected: "; + s += path; + Log(s); + } + } + }break; + case DBT_DEVICEREMOVECOMPLETE: + { + for (auto& dev : usb_list) + { + if (path.find(dev, 0) != wstring::npos) + { + wstring s = L"Device disconnected: "; + s += path; + Log(s); + } + } + }break; + default:break; + } + } + } + }break; + */ case WM_WTSSESSION_CHANGE: { if (wParam == WTS_REMOTE_CONNECT) @@ -565,11 +634,6 @@ bool ReadConfigFile() if (!j.empty() && j.is_boolean()) Prefs.AdhereTopology = j.get(); -/* - j = jsonPrefs[JSON_PREFS_NODE][JSON_ADVANCEDIDLE]; - if (!j.empty() && j.is_boolean()) - Prefs.bAdvancedUserIdle = j.get(); - j = jsonPrefs[JSON_PREFS_NODE][JSON_IDLEWHITELIST]; if (!j.empty() && j.is_boolean()) Prefs.bIdleWhitelistEnabled = j.get(); @@ -581,14 +645,19 @@ bool ReadConfigFile() j = jsonPrefs[JSON_PREFS_NODE][JSON_WHITELIST]; if (!j.empty() && j.size() > 0) { - for (auto& elem : j.items()) + for (auto& item : j.items()) { - string temp = elem.value().get(); - if (std::find(Prefs.EventLogRestartString.begin(), Prefs.EventLogRestartString.end(), temp) == Prefs.EventLogRestartString.end()) - Prefs.EventLogRestartString.push_back(temp); + if (item.value().is_string()) + { + WHITELIST w; + w.Name = widen(item.key()); + w.Application = widen(item.value().get()); + Prefs.WhiteList.push_back(w); + } + } } -*/ + return true; } } @@ -919,53 +988,54 @@ bool VerifyTopology(void) } return true; } -bool GetLastUserInputTime(PLASTINPUTINFO pLII) -{ - if (SavedLII.dwTime == 0) - SavedLII.dwTime = GetTickCount(); - //white list management - if (Prefs.bIdleWhitelistEnabled) +string WhitelistProcessRunning(void) +{ + if (Prefs.WhiteList.size() > 0) { - if (WhitelistProcessRunning()) - { - pLII->dwTime = GetTickCount(); - Log(L"Whitelist process prohibiting idle."); - return true; + PROCESSENTRY32 entry; + entry.dwSize = sizeof(PROCESSENTRY32); + + const auto snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + + if (!Process32First(snapshot, &entry)) { + CloseHandle(snapshot); + Log(L"Failed to iterate running processes"); + return ""; } + + do { + for (auto &w : Prefs.WhiteList) + { + if (w.Application != L"") + { + if (!_tcsicmp(entry.szExeFile, w.Application.c_str())) + { + CloseHandle(snapshot); + return narrow(w.Name); + } + } + } + } while (Process32Next(snapshot, &entry)); + + CloseHandle(snapshot); } - //fullscreen management - if (Prefs.bFullscreenCheckEnabled) + return ""; +} +bool FullscreenApplicationRunning(void) +{ + QUERY_USER_NOTIFICATION_STATE pquns; + if (SHQueryUserNotificationState(&pquns) == S_OK) { - if (FullscreenApplicationRunning()) + if (pquns == QUNS_RUNNING_D3D_FULL_SCREEN || + pquns == QUNS_PRESENTATION_MODE || + pquns == QUNS_BUSY || + pquns == QUNS_APP) { - pLII->dwTime = GetTickCount(); - Log(L"Fullscreen process prohibiting idle."); return true; } } - if (Prefs.bAdvancedUserIdle) - { - MyGetLastinputInfo(pLII); - } - else - GetLastInputInfo(pLII); - - SavedLII.dwTime = pLII->dwTime; - - return true; -} - -bool WhitelistProcessRunning(void) -{ - return false; -} -bool FullscreenApplicationRunning(void) -{ return false; } -bool MyGetLastinputInfo(PLASTINPUTINFO plii) -{ - return false; -} \ No newline at end of file + diff --git a/LGTV Companion User/Daemon.h b/LGTV Companion User/Daemon.h index f67cd4e..13f2e43 100644 --- a/LGTV Companion User/Daemon.h +++ b/LGTV Companion User/Daemon.h @@ -1,6 +1,7 @@ #pragma once #pragma comment(lib, "urlmon.lib") #pragma comment(lib, "Wtsapi32.lib") +#pragma comment(lib, "User32.lib") #if defined _M_IX86 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") @@ -29,7 +30,12 @@ #include #include #include - +#include +#include +#include +#include +#include +#include #include "resource.h" #include "nlohmann/json.hpp" #include "WinToast-1.2.0/wintoastlib.h" @@ -37,7 +43,7 @@ #define APPNAME_SHORT L"LGTVdaemon" #define APP_PATH L"LGTV Companion" #define APPNAME_FULL L"LGTV Companion Daemon" -#define APP_VERSION L"1.8.7" +#define APP_VERSION L"1.9.0" #define WINDOW_CLASS_UNIQUE L"YOLOx0x0x0181818" #define NOTIFY_NEW_PROCESS 1 @@ -46,7 +52,7 @@ #define TIMER_RDP 20 #define TIMER_TOPOLOGY 21 -#define TIMER_MAIN_DELAY_WHEN_BUSY 2000 +#define TIMER_MAIN_DELAY_WHEN_BUSY 10000 #define TIMER_MAIN_DELAY_WHEN_IDLE 100 #define TIMER_RDP_DELAY 10000 @@ -60,7 +66,6 @@ #define JSON_IDLEBLANK "BlankWhenIdle" #define JSON_IDLEBLANKDELAY "BlankWhenIdleDelay" #define JSON_ADHERETOPOLOGY "AdhereDisplayTopology" -#define JSON_ADVANCEDIDLE "AdvancedUserInputIdle" #define JSON_IDLEWHITELIST "IdleWhiteListEnabled" #define JSON_IDLEFULLSCREEN "IdleFullscreen" #define JSON_WHITELIST "IdleWhiteList" @@ -70,10 +75,17 @@ #define VERSIONCHECKLINK L"https://api.github.com/repos/JPersson77/LGTVCompanion/releases" #define DONATELINK L"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=jorgen.persson@gmail.com&lc=US&item_name=Friendly+gift+for+the+development+of+LGTV+Companion&no_note=0&cn=¤cy_code=EUR&bn=PP-DonationsBF:btn_donateCC_LG.gif:NonHosted" +const std::vector usb_list { + L"USB#HID_0955", //nvidia + L"HID#VID_0955", //nvidia + L"USB#VID_413D" //dummy +}; + struct WHITELIST { - std::string Name; - std::string Application; + std::wstring Name; + std::wstring Application; }; + struct PREFS { bool AutoUpdate = false; bool BlankScreenWhenIdle = false; @@ -85,7 +97,7 @@ struct PREFS { bool AdhereTopology = false; bool bIdleWhitelistEnabled = false; bool bFullscreenCheckEnabled = false; - bool bAdvancedUserIdle = false; + std::vector WhiteList; }; class WinToastHandler : public WinToastLib::IWinToastHandler @@ -132,7 +144,5 @@ std::vector QueryDisplays(); static BOOL CALLBACK meproc(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData); bool CheckDisplayTopology(void); bool VerifyTopology(); -bool GetLastUserInputTime(PLASTINPUTINFO); -bool WhitelistProcessRunning(void); -bool FullscreenApplicationRunning(void); -bool MyGetLastinputInfo (PLASTINPUTINFO); \ No newline at end of file +std::string WhitelistProcessRunning(void); +bool FullscreenApplicationRunning(void); \ No newline at end of file diff --git a/LGTV Companion User/LGTV Companion User.rc b/LGTV Companion User/LGTV Companion User.rc index b9425d5..3350749 100644 --- a/LGTV Companion User/LGTV Companion User.rc +++ b/LGTV Companion User/LGTV Companion User.rc @@ -60,16 +60,14 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK // Dialog // -IDD_MAIN DIALOGEX 0, 0, 309, 176 +IDD_MAIN DIALOGEX 0, 0, 309, 191 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Dialog" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - EDITTEXT IDC_EDIT,7,7,295,134,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL - EDITTEXT IDC_EDIT2,7,155,88,14,ES_AUTOHSCROLL - LTEXT "LastInputTick",IDC_STATIC,7,146,48,8 - EDITTEXT IDC_EDIT3,118,155,88,14,ES_AUTOHSCROLL - LTEXT "Seconds ago",IDC_STATIC,118,147,48,8 + EDITTEXT IDC_EDIT,7,7,295,134,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL + EDITTEXT IDC_EDIT3,7,166,94,14,ES_AUTOHSCROLL + LTEXT "Seconds since last input (mouse, kb, controller)",IDC_STATIC,9,147,79,19 END @@ -85,9 +83,14 @@ BEGIN BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 302 - VERTGUIDE, 118 + VERTGUIDE, 101 + VERTGUIDE, 112 + VERTGUIDE, 200 + VERTGUIDE, 212 TOPMARGIN, 7 - BOTTOMMARGIN, 169 + BOTTOMMARGIN, 184 + HORZGUIDE, 147 + HORZGUIDE, 166 END END #endif // APSTUDIO_INVOKED diff --git a/LGTV Companion User/resource.h b/LGTV Companion User/resource.h index cce6195..e8e63e4 100644 --- a/LGTV Companion User/resource.h +++ b/LGTV Companion User/resource.h @@ -6,9 +6,8 @@ #define IDI_ICON1 103 #define IDC_EDIT 1001 #define IDC_EDIT2 1002 -#define IDC_BUTTON1 1003 -#define IDC_TEST 1003 #define IDC_EDIT3 1004 +#define IDC_EDIT5 1005 // Next default values for new objects //