From 2040df435f751b9aa4a548198134e69d7e271bf5 Mon Sep 17 00:00:00 2001 From: sithlord48 Date: Sun, 19 Jan 2025 14:37:34 -0500 Subject: [PATCH] fix: #8107: Remove legacy tray code --- src/apps/deskflow-client/CMakeLists.txt | 63 --- .../MSWindowsClientTaskBarReceiver.cpp | 333 ------------ .../MSWindowsClientTaskBarReceiver.h | 66 --- .../OSXClientTaskBarReceiver.cpp | 61 --- .../OSXClientTaskBarReceiver.h | 38 -- .../XWindowsClientTaskBarReceiver.cpp | 61 --- .../XWindowsClientTaskBarReceiver.h | 43 -- src/apps/deskflow-client/deskflow-client.cpp | 12 +- src/apps/deskflow-client/resource.h | 37 -- src/apps/deskflow-core/deskflow-core.cpp | 4 +- src/apps/deskflow-server/CMakeLists.txt | 67 --- .../MSWindowsServerTaskBarReceiver.cpp | 360 ------------- .../MSWindowsServerTaskBarReceiver.h | 67 --- .../OSXServerTaskBarReceiver.cpp | 61 --- .../OSXServerTaskBarReceiver.h | 37 -- .../XWindowsServerTaskBarReceiver.cpp | 61 --- .../XWindowsServerTaskBarReceiver.h | 43 -- src/apps/deskflow-server/deskflow-server.cpp | 12 +- src/apps/deskflow-server/resource.h | 42 -- src/apps/res/tb_error.ico | Bin 46390 -> 0 bytes src/apps/res/tb_idle.ico | Bin 53861 -> 0 bytes src/apps/res/tb_run.ico | Bin 59820 -> 0 bytes src/lib/arch/Arch.cpp | 1 - src/lib/arch/Arch.h | 3 - src/lib/arch/CMakeLists.txt | 6 - src/lib/arch/IArchTaskBar.h | 64 --- src/lib/arch/IArchTaskBarReceiver.h | 102 ---- src/lib/arch/unix/ArchTaskBarXWindows.cpp | 48 -- src/lib/arch/unix/ArchTaskBarXWindows.h | 36 -- src/lib/arch/win32/ArchTaskBarWindows.cpp | 488 ------------------ src/lib/arch/win32/ArchTaskBarWindows.h | 114 ---- src/lib/deskflow/App.cpp | 10 +- src/lib/deskflow/App.h | 9 +- src/lib/deskflow/ArgParser.cpp | 2 - src/lib/deskflow/CMakeLists.txt | 4 - src/lib/deskflow/ClientApp.cpp | 13 +- src/lib/deskflow/ClientApp.h | 2 +- src/lib/deskflow/ClientTaskBarReceiver.cpp | 123 ----- src/lib/deskflow/ClientTaskBarReceiver.h | 98 ---- src/lib/deskflow/IApp.h | 2 - src/lib/deskflow/ServerApp.cpp | 13 +- src/lib/deskflow/ServerApp.h | 2 +- src/lib/deskflow/ServerTaskBarReceiver.cpp | 123 ----- src/lib/deskflow/ServerTaskBarReceiver.h | 102 ---- src/lib/deskflow/win32/AppUtilWindows.cpp | 1 - src/lib/gui/core/CoreProcess.cpp | 1 - src/test/mock/deskflow/MockApp.h | 2 +- .../deskflow/GenericArgsParsingTests.cpp | 12 - .../unittests/deskflow/ServerAppTests.cpp | 2 +- 49 files changed, 15 insertions(+), 2836 deletions(-) delete mode 100644 src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.cpp delete mode 100644 src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.h delete mode 100644 src/apps/deskflow-client/OSXClientTaskBarReceiver.cpp delete mode 100644 src/apps/deskflow-client/OSXClientTaskBarReceiver.h delete mode 100644 src/apps/deskflow-client/XWindowsClientTaskBarReceiver.cpp delete mode 100644 src/apps/deskflow-client/XWindowsClientTaskBarReceiver.h delete mode 100644 src/apps/deskflow-client/resource.h delete mode 100644 src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.cpp delete mode 100644 src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.h delete mode 100644 src/apps/deskflow-server/OSXServerTaskBarReceiver.cpp delete mode 100644 src/apps/deskflow-server/OSXServerTaskBarReceiver.h delete mode 100644 src/apps/deskflow-server/XWindowsServerTaskBarReceiver.cpp delete mode 100644 src/apps/deskflow-server/XWindowsServerTaskBarReceiver.h delete mode 100644 src/apps/deskflow-server/resource.h delete mode 100644 src/apps/res/tb_error.ico delete mode 100644 src/apps/res/tb_idle.ico delete mode 100644 src/apps/res/tb_run.ico delete mode 100644 src/lib/arch/IArchTaskBar.h delete mode 100644 src/lib/arch/IArchTaskBarReceiver.h delete mode 100644 src/lib/arch/unix/ArchTaskBarXWindows.cpp delete mode 100644 src/lib/arch/unix/ArchTaskBarXWindows.h delete mode 100644 src/lib/arch/win32/ArchTaskBarWindows.cpp delete mode 100644 src/lib/arch/win32/ArchTaskBarWindows.h delete mode 100644 src/lib/deskflow/ClientTaskBarReceiver.cpp delete mode 100644 src/lib/deskflow/ClientTaskBarReceiver.h delete mode 100644 src/lib/deskflow/ServerTaskBarReceiver.cpp delete mode 100644 src/lib/deskflow/ServerTaskBarReceiver.h diff --git a/src/apps/deskflow-client/CMakeLists.txt b/src/apps/deskflow-client/CMakeLists.txt index 46c2d8c7a..cb2e8ad51 100644 --- a/src/apps/deskflow-client/CMakeLists.txt +++ b/src/apps/deskflow-client/CMakeLists.txt @@ -22,79 +22,16 @@ if(WIN32) set(EXE_DESCRIPTION "${CMAKE_PROJECT_DESCRIPTION}\\n CLI client application") set(EXE_ICON " -#include \"${CMAKE_CURRENT_SOURCE_DIR}/resource.h\" IDI_DESKFLOW ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\" - IDI_TASKBAR_NOT_RUNNING ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/tb_idle.ico\" - IDI_TASKBAR_NOT_WORKING ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/tb_error.ico\" - IDI_TASKBAR_NOT_CONNECTED ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\" - IDI_TASKBAR_CONNECTED ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/tb_run.ico\" - ") - - set(EXE_RC_DIALOG " - IDD_TASKBAR_STATUS DIALOG DISCARDABLE 0, 0, 145, 18 - STYLE DS_MODALFRAME | WS_POPUP - FONT 8, \"MS Sans Serif\" - BEGIN - EDITTEXT IDC_TASKBAR_STATUS_STATUS,3,3,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER - END - ") - - set(EXE_RC_MENU " - IDR_TASKBAR MENU DISCARDABLE - BEGIN - POPUP \"${CMAKE_PROJECT_PROPER_NAME}\" - BEGIN - MENUITEM \"Show Status\", IDC_TASKBAR_STATUS - MENUITEM \"Show Log\", IDC_TASKBAR_SHOW_LOG - MENUITEM \"Copy Log To Clipboard\", IDC_TASKBAR_LOG - POPUP \"Set Log Level\" - BEGIN - MENUITEM \"Error\", IDC_TASKBAR_LOG_LEVEL_ERROR - MENUITEM \"Warning\", IDC_TASKBAR_LOG_LEVEL_WARNING - MENUITEM \"Note\", IDC_TASKBAR_LOG_LEVEL_NOTE - MENUITEM \"Info\", IDC_TASKBAR_LOG_LEVEL_INFO - MENUITEM \"Debug\", IDC_TASKBAR_LOG_LEVEL_DEBUG - MENUITEM \"Debug1\", IDC_TASKBAR_LOG_LEVEL_DEBUG1 - MENUITEM \"Debug2\", IDC_TASKBAR_LOG_LEVEL_DEBUG2 - END - MENUITEM SEPARATOR - MENUITEM \"Quit\", IDC_TASKBAR_QUIT - END - END - ") - - set(EXE_RC_STRINGTABLE " - STRINGTABLE DISCARDABLE - BEGIN - IDS_FAILED \"${CMAKE_PROJECT_PROPER_NAME} is about to quit with errors or warnings. Please check the log then click OK.\" - IDS_INIT_FAILED \"${CMAKE_PROJECT_PROPER_NAME} failed to initialize: %{1}\" - IDS_UNCAUGHT_EXCEPTION \"Uncaught exception: %{1}\" - END ") configure_file(${CMAKE_SOURCE_DIR}/src/apps/res/rc_template.rc.in ${target}.rc) set(PLATFORM_SOURCES ${target}.exe.manifest - MSWindowsClientTaskBarReceiver.cpp - MSWindowsClientTaskBarReceiver.h - resource.h ${PROJECT_SOURCE_DIR}/src/apps/res/deskflow.ico - ${PROJECT_SOURCE_DIR}/src/apps/res/tb_error.ico - ${PROJECT_SOURCE_DIR}/src/apps/res/tb_idle.ico - ${PROJECT_SOURCE_DIR}/src/apps/res/tb_run.ico ${CMAKE_CURRENT_BINARY_DIR}/${target}.rc ) -elseif(APPLE) - set(PLATFORM_SOURCES - OSXClientTaskBarReceiver.cpp - OSXClientTaskBarReceiver.h - ) -elseif(UNIX) - set(PLATFORM_SOURCES - XWindowsClientTaskBarReceiver.cpp - XWindowsClientTaskBarReceiver.h - ) endif() add_executable(${target} ${PLATFORM_SOURCES} ${target}.cpp) diff --git a/src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.cpp b/src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.cpp deleted file mode 100644 index 4fd871485..000000000 --- a/src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "MSWindowsClientTaskBarReceiver.h" - -#include "arch/Arch.h" -#include "arch/win32/ArchMiscWindows.h" -#include "arch/win32/ArchTaskBarWindows.h" -#include "base/EventQueue.h" -#include "base/EventTypes.h" -#include "base/log_outputters.h" -#include "client/Client.h" -#include "platform/MSWindowsClipboard.h" -#include "platform/MSWindowsScreen.h" -#include "resource.h" - -// -// MSWindowsClientTaskBarReceiver -// - -const UINT MSWindowsClientTaskBarReceiver::s_stateToIconID[kMaxState] = { - IDI_TASKBAR_NOT_RUNNING, IDI_TASKBAR_NOT_WORKING, IDI_TASKBAR_NOT_CONNECTED, IDI_TASKBAR_CONNECTED -}; - -MSWindowsClientTaskBarReceiver::MSWindowsClientTaskBarReceiver( - HINSTANCE appInstance, const BufferedLogOutputter *logBuffer, IEventQueue *events -) - : ClientTaskBarReceiver(events), - m_appInstance(appInstance), - m_window(NULL), - m_logBuffer(logBuffer) -{ - for (uint32_t i = 0; i < kMaxState; ++i) { - m_icon[i] = loadIcon(s_stateToIconID[i]); - } - m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR)); - - // don't create the window yet. we'll create it on demand. this - // has the side benefit of being created in the thread used for - // the task bar. that's good because it means the existence of - // the window won't prevent changing the main thread's desktop. - - // add ourself to the task bar - ARCH->addReceiver(this); -} - -MSWindowsClientTaskBarReceiver::~MSWindowsClientTaskBarReceiver() -{ - cleanup(); -} - -void MSWindowsClientTaskBarReceiver::cleanup() -{ - ARCH->removeReceiver(this); - for (uint32_t i = 0; i < kMaxState; ++i) { - deleteIcon(m_icon[i]); - } - DestroyMenu(m_menu); - destroyWindow(); -} - -void MSWindowsClientTaskBarReceiver::showStatus() -{ - // create the window - createWindow(); - - // lock self while getting status - lock(); - - // get the current status - std::string status = getToolTip(); - - // done getting status - unlock(); - - // update dialog - HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str()); - - if (!IsWindowVisible(m_window)) { - // position it by the mouse - POINT cursorPos; - GetCursorPos(&cursorPos); - RECT windowRect; - GetWindowRect(m_window, &windowRect); - int x = cursorPos.x; - int y = cursorPos.y; - int fw = GetSystemMetrics(SM_CXDLGFRAME); - int fh = GetSystemMetrics(SM_CYDLGFRAME); - int ww = windowRect.right - windowRect.left; - int wh = windowRect.bottom - windowRect.top; - int sw = GetSystemMetrics(SM_CXFULLSCREEN); - int sh = GetSystemMetrics(SM_CYFULLSCREEN); - if (fw < 1) { - fw = 1; - } - if (fh < 1) { - fh = 1; - } - if (x + ww - fw > sw) { - x -= ww - fw; - } else { - x -= fw; - } - if (x < 0) { - x = 0; - } - if (y + wh - fh > sh) { - y -= wh - fh; - } else { - y -= fh; - } - if (y < 0) { - y = 0; - } - SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh, SWP_SHOWWINDOW); - } -} - -void MSWindowsClientTaskBarReceiver::runMenu(int x, int y) -{ - // do popup menu. we need a window to pass to TrackPopupMenu(). - // the SetForegroundWindow() and SendMessage() calls around - // TrackPopupMenu() are to get the menu to be dismissed when - // another window gets activated and are just one of those - // win32 weirdnesses. - createWindow(); - SetForegroundWindow(m_window); - HMENU menu = GetSubMenu(m_menu, 0); - SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE); - HMENU logLevelMenu = GetSubMenu(menu, 3); - CheckMenuRadioItem(logLevelMenu, 0, 6, CLOG->getFilter() - kERROR, MF_BYPOSITION); - int n = - TrackPopupMenu(menu, TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, 0, m_window, NULL); - SendMessage(m_window, WM_NULL, 0, 0); - - // perform the requested operation - switch (n) { - case IDC_TASKBAR_STATUS: - showStatus(); - break; - - case IDC_TASKBAR_LOG: - copyLog(); - break; - - case IDC_TASKBAR_SHOW_LOG: - ARCH->showConsole(true); - break; - - case IDC_TASKBAR_LOG_LEVEL_ERROR: - CLOG->setFilter(kERROR); - break; - - case IDC_TASKBAR_LOG_LEVEL_WARNING: - CLOG->setFilter(kWARNING); - break; - - case IDC_TASKBAR_LOG_LEVEL_NOTE: - CLOG->setFilter(kNOTE); - break; - - case IDC_TASKBAR_LOG_LEVEL_INFO: - CLOG->setFilter(kINFO); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG: - CLOG->setFilter(kDEBUG); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG1: - CLOG->setFilter(kDEBUG1); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG2: - CLOG->setFilter(kDEBUG2); - break; - - case IDC_TASKBAR_QUIT: - quit(); - break; - } -} - -void MSWindowsClientTaskBarReceiver::primaryAction() -{ - showStatus(); -} - -IArchTaskBarReceiver::Icon MSWindowsClientTaskBarReceiver::getIcon() const -{ - return static_cast(m_icon[getStatus()]); -} - -void MSWindowsClientTaskBarReceiver::copyLog() const -{ - if (m_logBuffer != NULL) { - // collect log buffer - std::string data; - for (BufferedLogOutputter::const_iterator index = m_logBuffer->begin(); index != m_logBuffer->end(); ++index) { - data += *index; - data += "\n"; - } - - // copy log to clipboard - if (!data.empty()) { - MSWindowsClipboard clipboard(m_window); - clipboard.open(0); - clipboard.emptyUnowned(); - clipboard.add(IClipboard::kText, data); - clipboard.close(); - } - } -} - -void MSWindowsClientTaskBarReceiver::onStatusChanged() -{ - if (IsWindowVisible(m_window)) { - showStatus(); - } -} - -HICON -MSWindowsClientTaskBarReceiver::loadIcon(UINT id) -{ - HANDLE icon = LoadImage(m_appInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); - return static_cast(icon); -} - -void MSWindowsClientTaskBarReceiver::deleteIcon(HICON icon) -{ - if (icon != NULL) { - DestroyIcon(icon); - } -} - -void MSWindowsClientTaskBarReceiver::createWindow() -{ - // ignore if already created - if (m_window != NULL) { - return; - } - - // get the status dialog - m_window = CreateDialogParam( - m_appInstance, MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsClientTaskBarReceiver::staticDlgProc, - reinterpret_cast(static_cast(this)) - ); - - // window should appear on top of everything, including (especially) - // the task bar. - LONG_PTR style = GetWindowLongPtr(m_window, GWL_EXSTYLE); - style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST; - SetWindowLongPtr(m_window, GWL_EXSTYLE, style); - - // tell the task bar about this dialog - ArchTaskBarWindows::addDialog(m_window); -} - -void MSWindowsClientTaskBarReceiver::destroyWindow() -{ - if (m_window != NULL) { - ArchTaskBarWindows::removeDialog(m_window); - DestroyWindow(m_window); - m_window = NULL; - } -} - -BOOL MSWindowsClientTaskBarReceiver::dlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM) -{ - switch (msg) { - case WM_INITDIALOG: - // use default focus - return TRUE; - - case WM_ACTIVATE: - // hide when another window is activated - if (LOWORD(wParam) == WA_INACTIVE) { - ShowWindow(hwnd, SW_HIDE); - } - break; - } - return FALSE; -} - -BOOL CALLBACK MSWindowsClientTaskBarReceiver::staticDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - // if msg is WM_INITDIALOG, extract the MSWindowsClientTaskBarReceiver* - // and put it in the extra window data then forward the call. - MSWindowsClientTaskBarReceiver *self = NULL; - if (msg == WM_INITDIALOG) { - self = static_cast(reinterpret_cast(lParam)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam); - } else { - // get the extra window data and forward the call - LONG_PTR data = GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (data != 0) { - self = (MSWindowsClientTaskBarReceiver *)data; - } - } - - // forward the message - if (self != NULL) { - return self->dlgProc(hwnd, msg, wParam, lParam); - } else { - return (msg == WM_INITDIALOG) ? TRUE : FALSE; - } -} - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events) -{ - ArchMiscWindows::setIcons( - (HICON)LoadImage(ArchMiscWindows::instanceWin32(), MAKEINTRESOURCE(IDI_DESKFLOW), IMAGE_ICON, 32, 32, LR_SHARED), - (HICON)LoadImage(ArchMiscWindows::instanceWin32(), MAKEINTRESOURCE(IDI_DESKFLOW), IMAGE_ICON, 16, 16, LR_SHARED) - ); - - return new MSWindowsClientTaskBarReceiver(MSWindowsScreen::getWindowInstance(), logBuffer, events); -} diff --git a/src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.h b/src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.h deleted file mode 100644 index 5c0b29d2a..000000000 --- a/src/apps/deskflow-client/MSWindowsClientTaskBarReceiver.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "deskflow/ClientTaskBarReceiver.h" - -#define WIN32_LEAN_AND_MEAN -#include - -class BufferedLogOutputter; -class IEventQueue; - -//! Implementation of ClientTaskBarReceiver for Microsoft Windows -class MSWindowsClientTaskBarReceiver : public ClientTaskBarReceiver -{ -public: - MSWindowsClientTaskBarReceiver(HINSTANCE, const BufferedLogOutputter *, IEventQueue *events); - virtual ~MSWindowsClientTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - void showStatus() override; - void runMenu(int x, int y) override; - void primaryAction() override; - Icon getIcon() const override; - void cleanup(); - -protected: - void copyLog() const; - - // ClientTaskBarReceiver overrides - virtual void onStatusChanged(); - -private: - HICON loadIcon(UINT); - void deleteIcon(HICON); - void createWindow(); - void destroyWindow(); - - BOOL dlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - static BOOL CALLBACK staticDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - -private: - HINSTANCE m_appInstance; - HWND m_window; - HMENU m_menu; - HICON m_icon[kMaxState]; - const BufferedLogOutputter *m_logBuffer; - - static const UINT s_stateToIconID[]; -}; diff --git a/src/apps/deskflow-client/OSXClientTaskBarReceiver.cpp b/src/apps/deskflow-client/OSXClientTaskBarReceiver.cpp deleted file mode 100644 index bfe0fbf16..000000000 --- a/src/apps/deskflow-client/OSXClientTaskBarReceiver.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "OSXClientTaskBarReceiver.h" -#include "arch/Arch.h" - -// -// OSXClientTaskBarReceiver -// - -OSXClientTaskBarReceiver::OSXClientTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events) - : ClientTaskBarReceiver(events) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -OSXClientTaskBarReceiver::~OSXClientTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void OSXClientTaskBarReceiver::showStatus() -{ - // do nothing -} - -void OSXClientTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void OSXClientTaskBarReceiver::primaryAction() -{ - // do nothing -} - -IArchTaskBarReceiver::Icon OSXClientTaskBarReceiver::getIcon() const -{ - return nullptr; -} - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events) -{ - return new OSXClientTaskBarReceiver(logBuffer, events); -} diff --git a/src/apps/deskflow-client/OSXClientTaskBarReceiver.h b/src/apps/deskflow-client/OSXClientTaskBarReceiver.h deleted file mode 100644 index 6989b765b..000000000 --- a/src/apps/deskflow-client/OSXClientTaskBarReceiver.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "deskflow/ClientTaskBarReceiver.h" - -class BufferedLogOutputter; -class IEventQueue; - -//! Implementation of ClientTaskBarReceiver for OS X -class OSXClientTaskBarReceiver : public ClientTaskBarReceiver -{ -public: - OSXClientTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events); - virtual ~OSXClientTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - void showStatus() override; - void runMenu(int x, int y) override; - void primaryAction() override; - Icon getIcon() const override; -}; diff --git a/src/apps/deskflow-client/XWindowsClientTaskBarReceiver.cpp b/src/apps/deskflow-client/XWindowsClientTaskBarReceiver.cpp deleted file mode 100644 index d077ed97e..000000000 --- a/src/apps/deskflow-client/XWindowsClientTaskBarReceiver.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "XWindowsClientTaskBarReceiver.h" -#include "arch/Arch.h" - -// -// CXWindowsClientTaskBarReceiver -// - -CXWindowsClientTaskBarReceiver::CXWindowsClientTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events) - : ClientTaskBarReceiver(events) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -CXWindowsClientTaskBarReceiver::~CXWindowsClientTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void CXWindowsClientTaskBarReceiver::showStatus() -{ - // do nothing -} - -void CXWindowsClientTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void CXWindowsClientTaskBarReceiver::primaryAction() -{ - // do nothing -} - -IArchTaskBarReceiver::Icon CXWindowsClientTaskBarReceiver::getIcon() const -{ - return nullptr; -} - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events) -{ - return new CXWindowsClientTaskBarReceiver(logBuffer, events); -} diff --git a/src/apps/deskflow-client/XWindowsClientTaskBarReceiver.h b/src/apps/deskflow-client/XWindowsClientTaskBarReceiver.h deleted file mode 100644 index 82759e669..000000000 --- a/src/apps/deskflow-client/XWindowsClientTaskBarReceiver.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "deskflow/ClientTaskBarReceiver.h" - -class BufferedLogOutputter; -class IEventQueue; - -//! Implementation of ClientTaskBarReceiver for X Windows -class CXWindowsClientTaskBarReceiver : public ClientTaskBarReceiver -{ -public: - CXWindowsClientTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events); - CXWindowsClientTaskBarReceiver(const CXWindowsClientTaskBarReceiver &) = delete; - CXWindowsClientTaskBarReceiver(CXWindowsClientTaskBarReceiver &&) = delete; - virtual ~CXWindowsClientTaskBarReceiver(); - - CXWindowsClientTaskBarReceiver &operator=(const CXWindowsClientTaskBarReceiver &) = delete; - CXWindowsClientTaskBarReceiver &operator=(CXWindowsClientTaskBarReceiver &&) = delete; - - // IArchTaskBarReceiver overrides - void showStatus() override; - void runMenu(int x, int y) override; - void primaryAction() override; - Icon getIcon() const override; -}; diff --git a/src/apps/deskflow-client/deskflow-client.cpp b/src/apps/deskflow-client/deskflow-client.cpp index 48181e145..1621af298 100644 --- a/src/apps/deskflow-client/deskflow-client.cpp +++ b/src/apps/deskflow-client/deskflow-client.cpp @@ -25,16 +25,6 @@ #include "arch/win32/ArchMiscWindows.h" #endif -#if WINAPI_MSWINDOWS -#include "MSWindowsClientTaskBarReceiver.h" -#elif WINAPI_XWINDOWS -#include "XWindowsClientTaskBarReceiver.h" -#elif WINAPI_CARBON -#include "OSXClientTaskBarReceiver.h" -#else -#error Platform not supported. -#endif - int main(int argc, char **argv) { #if SYSAPI_WIN32 @@ -48,6 +38,6 @@ int main(int argc, char **argv) Log log; EventQueue events; - ClientApp app(&events, createTaskBarReceiver); + ClientApp app(&events); return app.run(argc, argv); } diff --git a/src/apps/deskflow-client/resource.h b/src/apps/deskflow-client/resource.h deleted file mode 100644 index 645de76a7..000000000 --- a/src/apps/deskflow-client/resource.h +++ /dev/null @@ -1,37 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by deskflowc.rc -// -#define IDS_FAILED 1 -#define IDS_INIT_FAILED 2 -#define IDS_UNCAUGHT_EXCEPTION 3 -#define IDI_DESKFLOW 101 -#define IDI_TASKBAR_NOT_RUNNING 102 -#define IDI_TASKBAR_NOT_WORKING 103 -#define IDI_TASKBAR_NOT_CONNECTED 104 -#define IDI_TASKBAR_CONNECTED 105 -#define IDR_TASKBAR 107 -#define IDD_TASKBAR_STATUS 108 -#define IDC_TASKBAR_STATUS_STATUS 1000 -#define IDC_TASKBAR_QUIT 40001 -#define IDC_TASKBAR_STATUS 40002 -#define IDC_TASKBAR_LOG 40003 -#define IDC_TASKBAR_SHOW_LOG 40004 -#define IDC_TASKBAR_LOG_LEVEL_ERROR 40009 -#define IDC_TASKBAR_LOG_LEVEL_WARNING 40010 -#define IDC_TASKBAR_LOG_LEVEL_NOTE 40011 -#define IDC_TASKBAR_LOG_LEVEL_INFO 40012 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG 40013 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG1 40014 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG2 40015 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 109 -#define _APS_NEXT_COMMAND_VALUE 40016 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/src/apps/deskflow-core/deskflow-core.cpp b/src/apps/deskflow-core/deskflow-core.cpp index cb2e4785e..a8231365b 100644 --- a/src/apps/deskflow-core/deskflow-core.cpp +++ b/src/apps/deskflow-core/deskflow-core.cpp @@ -57,10 +57,10 @@ int main(int argc, char **argv) EventQueue events; if (isServer(argc, argv)) { - ServerApp app(&events, nullptr); + ServerApp app(&events); return app.run(argc, argv); } else if (isClient(argc, argv)) { - ClientApp app(&events, nullptr); + ClientApp app(&events); return app.run(argc, argv); } else { showHelp(); diff --git a/src/apps/deskflow-server/CMakeLists.txt b/src/apps/deskflow-server/CMakeLists.txt index 203f76096..109c38679 100644 --- a/src/apps/deskflow-server/CMakeLists.txt +++ b/src/apps/deskflow-server/CMakeLists.txt @@ -22,83 +22,16 @@ if(WIN32) set(EXE_DESCRIPTION "${CMAKE_PROJECT_DESCRIPTION}\\n CLI server application") set(EXE_ICON " -#include \"${CMAKE_CURRENT_SOURCE_DIR}/resource.h\" IDI_DESKFLOW ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\" - IDI_TASKBAR_NOT_RUNNING ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/tb_idle.ico\" - IDI_TASKBAR_NOT_WORKING ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/tb_error.ico\" - IDI_TASKBAR_NOT_CONNECTED ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/deskflow.ico\" - IDI_TASKBAR_CONNECTED ICON DISCARDABLE \"${CMAKE_SOURCE_DIR}/src/apps/res/tb_run.ico\" - ") - - set(EXE_RC_DIALOG " - IDD_TASKBAR_STATUS DIALOG DISCARDABLE 0, 0, 145, 18 - STYLE DS_MODALFRAME | WS_POPUP - FONT 8, \"MS Sans Serif\" - BEGIN - EDITTEXT IDC_TASKBAR_STATUS_STATUS,3,3,139,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER - LISTBOX IDC_TASKBAR_STATUS_CLIENTS,3,17,139,40,NOT LBS_NOTIFY | LBS_SORT | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | WS_TABSTOP - END - ") - - set(EXE_RC_MENU " - IDR_TASKBAR MENU DISCARDABLE - BEGIN - POPUP \"${CMAKE_PROJECT_PROPER_NAME}\" - BEGIN - MENUITEM \"Show Status\", IDC_TASKBAR_STATUS - MENUITEM \"Show Log\", IDC_TASKBAR_SHOW_LOG - MENUITEM \"Copy Log To Clipboard\", IDC_TASKBAR_LOG - POPUP \"Set Log Level\" - BEGIN - MENUITEM \"Error\", IDC_TASKBAR_LOG_LEVEL_ERROR - MENUITEM \"Warning\", IDC_TASKBAR_LOG_LEVEL_WARNING - MENUITEM \"Note\", IDC_TASKBAR_LOG_LEVEL_NOTE - MENUITEM \"Info\", IDC_TASKBAR_LOG_LEVEL_INFO - MENUITEM \"Debug\", IDC_TASKBAR_LOG_LEVEL_DEBUG - MENUITEM \"Debug1\", IDC_TASKBAR_LOG_LEVEL_DEBUG1 - MENUITEM \"Debug2\", IDC_TASKBAR_LOG_LEVEL_DEBUG2 - END - MENUITEM \"Reload Configuration\", IDC_RELOAD_CONFIG - MENUITEM \"Force Reconnect\", IDC_FORCE_RECONNECT - MENUITEM \"Reset Server\", ID_DESKFLOW_RESETSERVER - MENUITEM SEPARATOR - MENUITEM \"Quit\", IDC_TASKBAR_QUIT - END - END - ") - - set(EXE_RC_STRINGTABLE " - STRINGTABLE DISCARDABLE - BEGIN - IDS_FAILED \"${CMAKE_PROJECT_PROPER_NAME} is about to quit with errors or warnings. Please check the log then click OK.\" - IDS_INIT_FAILED \"${CMAKE_PROJECT_PROPER_NAME} failed to initialize: %{1}\" - IDS_UNCAUGHT_EXCEPTION \"Uncaught exception: %{1}\" - END ") configure_file(${CMAKE_SOURCE_DIR}/src/apps/res/rc_template.rc.in ${target}.rc) set(PLATFORM_SOURCES ${target}.exe.manifest - MSWindowsServerTaskBarReceiver.cpp - MSWindowsServerTaskBarReceiver.h - resource.h ${PROJECT_SOURCE_DIR}/src/apps/res/deskflow.ico - ${PROJECT_SOURCE_DIR}/src/apps/res/tb_error.ico - ${PROJECT_SOURCE_DIR}/src/apps/res/tb_idle.ico - ${PROJECT_SOURCE_DIR}/src/apps/res/tb_run.ico ${CMAKE_CURRENT_BINARY_DIR}/${target}.rc ) -elseif(APPLE) - set(PLATFORM_SOURCES - OSXServerTaskBarReceiver.cpp - OSXServerTaskBarReceiver.h - ) -elseif(UNIX) - set(PLATFORM_SOURCES - XWindowsServerTaskBarReceiver.cpp - XWindowsServerTaskBarReceiver.h - ) endif() add_executable(${target} ${PLATFORM_SOURCES} ${target}.cpp) diff --git a/src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.cpp b/src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.cpp deleted file mode 100644 index 604562359..000000000 --- a/src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "MSWindowsServerTaskBarReceiver.h" - -#include "arch/Arch.h" -#include "arch/win32/ArchMiscWindows.h" -#include "arch/win32/ArchTaskBarWindows.h" -#include "base/EventQueue.h" -#include "base/EventTypes.h" -#include "base/IEventQueue.h" -#include "base/log_outputters.h" -#include "platform/MSWindowsClipboard.h" -#include "platform/MSWindowsScreen.h" -#include "resource.h" -#include "server/Server.h" - -// -// MSWindowsServerTaskBarReceiver -// - -const UINT MSWindowsServerTaskBarReceiver::s_stateToIconID[kMaxState] = { - IDI_TASKBAR_NOT_RUNNING, IDI_TASKBAR_NOT_WORKING, IDI_TASKBAR_NOT_CONNECTED, IDI_TASKBAR_CONNECTED -}; - -MSWindowsServerTaskBarReceiver::MSWindowsServerTaskBarReceiver( - HINSTANCE appInstance, const BufferedLogOutputter *logBuffer, IEventQueue *events -) - : ServerTaskBarReceiver(events), - m_events(events), - m_appInstance(appInstance), - m_window(NULL), - m_logBuffer(logBuffer) -{ - for (uint32_t i = 0; i < kMaxState; ++i) { - m_icon[i] = loadIcon(s_stateToIconID[i]); - } - m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR)); - - // don't create the window yet. we'll create it on demand. this - // has the side benefit of being created in the thread used for - // the task bar. that's good because it means the existence of - // the window won't prevent changing the main thread's desktop. - - // add ourself to the task bar - ARCH->addReceiver(this); -} - -void MSWindowsServerTaskBarReceiver::cleanup() -{ - ARCH->removeReceiver(this); - for (uint32_t i = 0; i < kMaxState; ++i) { - deleteIcon(m_icon[i]); - } - DestroyMenu(m_menu); - destroyWindow(); -} - -MSWindowsServerTaskBarReceiver::~MSWindowsServerTaskBarReceiver() -{ - cleanup(); -} - -void MSWindowsServerTaskBarReceiver::showStatus() -{ - // create the window - createWindow(); - - // lock self while getting status - lock(); - - // get the current status - std::string status = getToolTip(); - - // get the connect clients, if any - const Clients &clients = getClients(); - - // done getting status - unlock(); - - // update dialog - HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str()); - child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_CLIENTS); - SendMessage(child, LB_RESETCONTENT, 0, 0); - for (Clients::const_iterator index = clients.begin(); index != clients.end();) { - const char *client = index->c_str(); - if (++index == clients.end()) { - SendMessage(child, LB_ADDSTRING, 0, (LPARAM)client); - } else { - SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)client); - } - } - - if (!IsWindowVisible(m_window)) { - // position it by the mouse - POINT cursorPos; - GetCursorPos(&cursorPos); - RECT windowRect; - GetWindowRect(m_window, &windowRect); - int x = cursorPos.x; - int y = cursorPos.y; - int fw = GetSystemMetrics(SM_CXDLGFRAME); - int fh = GetSystemMetrics(SM_CYDLGFRAME); - int ww = windowRect.right - windowRect.left; - int wh = windowRect.bottom - windowRect.top; - int sw = GetSystemMetrics(SM_CXFULLSCREEN); - int sh = GetSystemMetrics(SM_CYFULLSCREEN); - if (fw < 1) { - fw = 1; - } - if (fh < 1) { - fh = 1; - } - if (x + ww - fw > sw) { - x -= ww - fw; - } else { - x -= fw; - } - if (x < 0) { - x = 0; - } - if (y + wh - fh > sh) { - y -= wh - fh; - } else { - y -= fh; - } - if (y < 0) { - y = 0; - } - SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh, SWP_SHOWWINDOW); - } -} - -void MSWindowsServerTaskBarReceiver::runMenu(int x, int y) -{ - // do popup menu. we need a window to pass to TrackPopupMenu(). - // the SetForegroundWindow() and SendMessage() calls around - // TrackPopupMenu() are to get the menu to be dismissed when - // another window gets activated and are just one of those - // win32 weirdnesses. - createWindow(); - SetForegroundWindow(m_window); - HMENU menu = GetSubMenu(m_menu, 0); - SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE); - HMENU logLevelMenu = GetSubMenu(menu, 3); - CheckMenuRadioItem(logLevelMenu, 0, 6, CLOG->getFilter() - kERROR, MF_BYPOSITION); - int n = - TrackPopupMenu(menu, TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, 0, m_window, NULL); - SendMessage(m_window, WM_NULL, 0, 0); - - // perform the requested operation - switch (n) { - case IDC_TASKBAR_STATUS: - showStatus(); - break; - - case IDC_TASKBAR_LOG: - copyLog(); - break; - - case IDC_TASKBAR_SHOW_LOG: - ARCH->showConsole(true); - break; - - case IDC_RELOAD_CONFIG: - m_events->addEvent(Event(m_events->forServerApp().reloadConfig(), m_events->getSystemTarget())); - break; - - case IDC_FORCE_RECONNECT: - m_events->addEvent(Event(m_events->forServerApp().forceReconnect(), m_events->getSystemTarget())); - break; - - case ID_DESKFLOW_RESETSERVER: - m_events->addEvent(Event(m_events->forServerApp().resetServer(), m_events->getSystemTarget())); - break; - - case IDC_TASKBAR_LOG_LEVEL_ERROR: - CLOG->setFilter(kERROR); - break; - - case IDC_TASKBAR_LOG_LEVEL_WARNING: - CLOG->setFilter(kWARNING); - break; - - case IDC_TASKBAR_LOG_LEVEL_NOTE: - CLOG->setFilter(kNOTE); - break; - - case IDC_TASKBAR_LOG_LEVEL_INFO: - CLOG->setFilter(kINFO); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG: - CLOG->setFilter(kDEBUG); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG1: - CLOG->setFilter(kDEBUG1); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG2: - CLOG->setFilter(kDEBUG2); - break; - - case IDC_TASKBAR_QUIT: - quit(); - break; - } -} - -void MSWindowsServerTaskBarReceiver::primaryAction() -{ - showStatus(); -} - -IArchTaskBarReceiver::Icon MSWindowsServerTaskBarReceiver::getIcon() const -{ - return static_cast(m_icon[getStatus()]); -} - -void MSWindowsServerTaskBarReceiver::copyLog() const -{ - if (m_logBuffer != NULL) { - // collect log buffer - std::string data; - for (BufferedLogOutputter::const_iterator index = m_logBuffer->begin(); index != m_logBuffer->end(); ++index) { - data += *index; - data += "\n"; - } - - // copy log to clipboard - if (!data.empty()) { - MSWindowsClipboard clipboard(m_window); - clipboard.open(0); - clipboard.emptyUnowned(); - clipboard.add(IClipboard::kText, data); - clipboard.close(); - } - } -} - -void MSWindowsServerTaskBarReceiver::onStatusChanged() -{ - if (IsWindowVisible(m_window)) { - showStatus(); - } -} - -HICON -MSWindowsServerTaskBarReceiver::loadIcon(UINT id) -{ - HANDLE icon = LoadImage(m_appInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); - return static_cast(icon); -} - -void MSWindowsServerTaskBarReceiver::deleteIcon(HICON icon) -{ - if (icon != NULL) { - DestroyIcon(icon); - } -} - -void MSWindowsServerTaskBarReceiver::createWindow() -{ - // ignore if already created - if (m_window != NULL) { - return; - } - - // get the status dialog - m_window = CreateDialogParam( - m_appInstance, MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsServerTaskBarReceiver::staticDlgProc, - reinterpret_cast(static_cast(this)) - ); - - // window should appear on top of everything, including (especially) - // the task bar. - LONG_PTR style = GetWindowLongPtr(m_window, GWL_EXSTYLE); - style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST; - SetWindowLongPtr(m_window, GWL_EXSTYLE, style); - - // tell the task bar about this dialog - ArchTaskBarWindows::addDialog(m_window); -} - -void MSWindowsServerTaskBarReceiver::destroyWindow() -{ - if (m_window != NULL) { - ArchTaskBarWindows::removeDialog(m_window); - DestroyWindow(m_window); - m_window = NULL; - } -} - -BOOL MSWindowsServerTaskBarReceiver::dlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM) -{ - switch (msg) { - case WM_INITDIALOG: - // use default focus - return TRUE; - - case WM_ACTIVATE: - // hide when another window is activated - if (LOWORD(wParam) == WA_INACTIVE) { - ShowWindow(hwnd, SW_HIDE); - } - break; - } - return FALSE; -} - -BOOL CALLBACK MSWindowsServerTaskBarReceiver::staticDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - // if msg is WM_INITDIALOG, extract the MSWindowsServerTaskBarReceiver* - // and put it in the extra window data then forward the call. - MSWindowsServerTaskBarReceiver *self = NULL; - if (msg == WM_INITDIALOG) { - self = static_cast(reinterpret_cast(lParam)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); - } else { - // get the extra window data and forward the call - LONG_PTR data = GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (data != 0) { - self = static_cast(reinterpret_cast(data)); - } - } - - // forward the message - if (self != NULL) { - return self->dlgProc(hwnd, msg, wParam, lParam); - } else { - return (msg == WM_INITDIALOG) ? TRUE : FALSE; - } -} - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events) -{ - ArchMiscWindows::setIcons( - (HICON)LoadImage(ArchMiscWindows::instanceWin32(), MAKEINTRESOURCE(IDI_DESKFLOW), IMAGE_ICON, 32, 32, LR_SHARED), - (HICON)LoadImage(ArchMiscWindows::instanceWin32(), MAKEINTRESOURCE(IDI_DESKFLOW), IMAGE_ICON, 16, 16, LR_SHARED) - ); - - return new MSWindowsServerTaskBarReceiver(MSWindowsScreen::getWindowInstance(), logBuffer, events); -} diff --git a/src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.h b/src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.h deleted file mode 100644 index 694868564..000000000 --- a/src/apps/deskflow-server/MSWindowsServerTaskBarReceiver.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "deskflow/ServerTaskBarReceiver.h" - -#define WIN32_LEAN_AND_MEAN -#include - -class BufferedLogOutputter; -class IEventQueue; - -//! Implementation of ServerTaskBarReceiver for Microsoft Windows -class MSWindowsServerTaskBarReceiver : public ServerTaskBarReceiver -{ -public: - MSWindowsServerTaskBarReceiver(HINSTANCE, const BufferedLogOutputter *, IEventQueue *events); - virtual ~MSWindowsServerTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - void showStatus() override; - void runMenu(int x, int y) override; - void primaryAction() override; - Icon getIcon() const override; - void cleanup(); - -protected: - void copyLog() const; - - // ServerTaskBarReceiver overrides - virtual void onStatusChanged(); - -private: - HICON loadIcon(UINT); - void deleteIcon(HICON); - void createWindow(); - void destroyWindow(); - - BOOL dlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - static BOOL CALLBACK staticDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - -private: - HINSTANCE m_appInstance; - HWND m_window; - HMENU m_menu; - HICON m_icon[kMaxState]; - const BufferedLogOutputter *m_logBuffer; - IEventQueue *m_events; - - static const UINT s_stateToIconID[]; -}; diff --git a/src/apps/deskflow-server/OSXServerTaskBarReceiver.cpp b/src/apps/deskflow-server/OSXServerTaskBarReceiver.cpp deleted file mode 100644 index 26b9f12e3..000000000 --- a/src/apps/deskflow-server/OSXServerTaskBarReceiver.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "OSXServerTaskBarReceiver.h" -#include "arch/Arch.h" - -// -// OSXServerTaskBarReceiver -// - -OSXServerTaskBarReceiver::OSXServerTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events) - : ServerTaskBarReceiver(events) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -OSXServerTaskBarReceiver::~OSXServerTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void OSXServerTaskBarReceiver::showStatus() -{ - // do nothing -} - -void OSXServerTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void OSXServerTaskBarReceiver::primaryAction() -{ - // do nothing -} - -IArchTaskBarReceiver::Icon OSXServerTaskBarReceiver::getIcon() const -{ - return nullptr; -} - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events) -{ - return new OSXServerTaskBarReceiver(logBuffer, events); -} diff --git a/src/apps/deskflow-server/OSXServerTaskBarReceiver.h b/src/apps/deskflow-server/OSXServerTaskBarReceiver.h deleted file mode 100644 index e86fe8c1d..000000000 --- a/src/apps/deskflow-server/OSXServerTaskBarReceiver.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "deskflow/ServerTaskBarReceiver.h" - -class BufferedLogOutputter; - -//! Implementation of ServerTaskBarReceiver for OS X -class OSXServerTaskBarReceiver : public ServerTaskBarReceiver -{ -public: - OSXServerTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events); - virtual ~OSXServerTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - void showStatus() override; - void runMenu(int x, int y) override; - void primaryAction() override; - Icon getIcon() const override; -}; diff --git a/src/apps/deskflow-server/XWindowsServerTaskBarReceiver.cpp b/src/apps/deskflow-server/XWindowsServerTaskBarReceiver.cpp deleted file mode 100644 index bb71d0600..000000000 --- a/src/apps/deskflow-server/XWindowsServerTaskBarReceiver.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "XWindowsServerTaskBarReceiver.h" -#include "arch/Arch.h" - -// -// CXWindowsServerTaskBarReceiver -// - -CXWindowsServerTaskBarReceiver::CXWindowsServerTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events) - : ServerTaskBarReceiver(events) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -CXWindowsServerTaskBarReceiver::~CXWindowsServerTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void CXWindowsServerTaskBarReceiver::showStatus() -{ - // do nothing -} - -void CXWindowsServerTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void CXWindowsServerTaskBarReceiver::primaryAction() -{ - // do nothing -} - -IArchTaskBarReceiver::Icon CXWindowsServerTaskBarReceiver::getIcon() const -{ - return nullptr; -} - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events) -{ - return new CXWindowsServerTaskBarReceiver(logBuffer, events); -} diff --git a/src/apps/deskflow-server/XWindowsServerTaskBarReceiver.h b/src/apps/deskflow-server/XWindowsServerTaskBarReceiver.h deleted file mode 100644 index 9841b305c..000000000 --- a/src/apps/deskflow-server/XWindowsServerTaskBarReceiver.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "deskflow/ServerTaskBarReceiver.h" - -class BufferedLogOutputter; -class IEventQueue; - -//! Implementation of ServerTaskBarReceiver for X Windows -class CXWindowsServerTaskBarReceiver : public ServerTaskBarReceiver -{ -public: - CXWindowsServerTaskBarReceiver(const BufferedLogOutputter *, IEventQueue *events); - CXWindowsServerTaskBarReceiver(const CXWindowsServerTaskBarReceiver &) = delete; - CXWindowsServerTaskBarReceiver(CXWindowsServerTaskBarReceiver &&) = delete; - virtual ~CXWindowsServerTaskBarReceiver(); - - CXWindowsServerTaskBarReceiver &operator=(const CXWindowsServerTaskBarReceiver &) = delete; - CXWindowsServerTaskBarReceiver &operator=(const CXWindowsServerTaskBarReceiver &&) = delete; - - // IArchTaskBarReceiver overrides - void showStatus() override; - void runMenu(int x, int y) override; - void primaryAction() override; - Icon getIcon() const override; -}; diff --git a/src/apps/deskflow-server/deskflow-server.cpp b/src/apps/deskflow-server/deskflow-server.cpp index 85f6af248..6012d656e 100644 --- a/src/apps/deskflow-server/deskflow-server.cpp +++ b/src/apps/deskflow-server/deskflow-server.cpp @@ -25,16 +25,6 @@ #include "arch/win32/ArchMiscWindows.h" #endif -#if WINAPI_MSWINDOWS -#include "MSWindowsServerTaskBarReceiver.h" -#elif WINAPI_XWINDOWS -#include "XWindowsServerTaskBarReceiver.h" -#elif WINAPI_CARBON -#include "OSXServerTaskBarReceiver.h" -#else -#error Platform not supported. -#endif - int main(int argc, char **argv) { #if SYSAPI_WIN32 @@ -48,6 +38,6 @@ int main(int argc, char **argv) Log log; EventQueue events; - ServerApp app(&events, createTaskBarReceiver); + ServerApp app(&events); return app.run(argc, argv); } diff --git a/src/apps/deskflow-server/resource.h b/src/apps/deskflow-server/resource.h deleted file mode 100644 index f30b20d0c..000000000 --- a/src/apps/deskflow-server/resource.h +++ /dev/null @@ -1,42 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by server .rc file -// -#define IDS_FAILED 1 -#define IDS_INIT_FAILED 2 -#define IDS_UNCAUGHT_EXCEPTION 3 -#define IDI_DESKFLOW 101 -#define IDI_TASKBAR_NOT_RUNNING 102 -#define IDI_TASKBAR_NOT_WORKING 103 -#define IDI_TASKBAR_NOT_CONNECTED 104 -#define IDI_TASKBAR_CONNECTED 105 -#define IDR_TASKBAR 107 -#define IDD_TASKBAR_STATUS 108 -#define IDC_TASKBAR_STATUS_STATUS 1000 -#define IDC_TASKBAR_STATUS_CLIENTS 1001 -#define IDC_TASKBAR_QUIT 40003 -#define IDC_TASKBAR_STATUS 40004 -#define IDC_TASKBAR_LOG 40005 -#define IDC_RELOAD_CONFIG 40006 -#define IDC_FORCE_RECONNECT 40007 -#define IDC_TASKBAR_SHOW_LOG 40008 -#define IDC_TASKBAR_LOG_LEVEL_ERROR 40009 -#define IDC_TASKBAR_LOG_LEVEL_WARNING 40010 -#define IDC_TASKBAR_LOG_LEVEL_NOTE 40011 -#define IDC_TASKBAR_LOG_LEVEL_INFO 40012 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG 40013 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG1 40014 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG2 40015 -#define ID_DESKFLOW_RELOADSYSTEM 40016 -#define ID_DESKFLOW_RESETSERVER 40017 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 109 -#define _APS_NEXT_COMMAND_VALUE 40018 -#define _APS_NEXT_CONTROL_VALUE 1003 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/src/apps/res/tb_error.ico b/src/apps/res/tb_error.ico deleted file mode 100644 index bf98cb4725e2625b91f1534b73de6a6d4ac64fb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46390 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

IfdPqJKcdgD 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. - */ - -#pragma once - -#include "common/IInterface.h" - -class IArchTaskBarReceiver; - -//! Interface for architecture dependent task bar control -/*! -This interface defines the task bar icon operations required -by deskflow. Each architecture must implement this interface -though each operation can be a no-op. -*/ -class IArchTaskBar : public IInterface -{ -public: - //! @name manipulators - //@{ - - //! Add a receiver - /*! - Add a receiver object to be notified of user and application - events. This should be called before other methods. When - the receiver is added to the task bar, its icon appears on - the task bar. - */ - virtual void addReceiver(IArchTaskBarReceiver *) = 0; - - //! Remove a receiver - /*! - Remove a receiver object from the task bar. This removes the - icon from the task bar. - */ - virtual void removeReceiver(IArchTaskBarReceiver *) = 0; - - //! Update a receiver - /*! - Updates the display of the receiver on the task bar. This - should be called when the receiver appearance may have changed - (e.g. it's icon or tool tip has changed). - */ - virtual void updateReceiver(IArchTaskBarReceiver *) = 0; - - //@} - - virtual void init() = 0; -}; diff --git a/src/lib/arch/IArchTaskBarReceiver.h b/src/lib/arch/IArchTaskBarReceiver.h deleted file mode 100644 index 59a1c5e81..000000000 --- a/src/lib/arch/IArchTaskBarReceiver.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "common/IInterface.h" - -#include - -class IScreen; -class INode; - -//! Interface for architecture dependent task bar event handling -/*! -This interface defines the task bar icon event handlers required -by deskflow. Each architecture must implement this interface -though each operation can be a no-op. -*/ -class IArchTaskBarReceiver : public IInterface -{ -public: - // Icon data is architecture dependent - using Icon = void *; - - //! @name manipulators - //@{ - - //! Show status window - /*! - Open a window displaying current status. This should return - immediately without waiting for the window to be closed. - */ - virtual void showStatus() = 0; - - //! Popup menu - /*! - Popup a menu of operations at or around \c x,y and perform the - chosen operation. - */ - virtual void runMenu(int x, int y) = 0; - - //! Perform primary action - /*! - Perform the primary (default) action. - */ - virtual void primaryAction() = 0; - - //@} - //! @name accessors - //@{ - - //! Lock receiver - /*! - Locks the receiver from changing state. The receiver should be - locked when querying it's state to ensure consistent results. - Each call to \c lock() must have a matching \c unlock() and - locks cannot be nested. - */ - virtual void lock() const = 0; - - //! Unlock receiver - virtual void unlock() const = 0; - - //! Get icon - /*! - Returns the icon to display in the task bar. The interface - to set the icon is left to subclasses. Getting and setting - the icon must be thread safe. - */ - virtual Icon getIcon() const = 0; - - //! Get tooltip - /*! - Returns the tool tip to display in the task bar. The interface - to set the tooltip is left to sublclasses. Getting and setting - the icon must be thread safe. - */ - virtual std::string getToolTip() const = 0; - - virtual void updateStatus(INode *, const std::string &errorMsg) = 0; - - virtual void cleanup() - { - } - - //@} -}; diff --git a/src/lib/arch/unix/ArchTaskBarXWindows.cpp b/src/lib/arch/unix/ArchTaskBarXWindows.cpp deleted file mode 100644 index 6773bba28..000000000 --- a/src/lib/arch/unix/ArchTaskBarXWindows.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "arch/unix/ArchTaskBarXWindows.h" - -// -// ArchTaskBarXWindows -// - -ArchTaskBarXWindows::ArchTaskBarXWindows() -{ - // do nothing -} - -ArchTaskBarXWindows::~ArchTaskBarXWindows() -{ - // do nothing -} - -void ArchTaskBarXWindows::addReceiver(IArchTaskBarReceiver * /*receiver*/) -{ - // do nothing -} - -void ArchTaskBarXWindows::removeReceiver(IArchTaskBarReceiver * /*receiver*/) -{ - // do nothing -} - -void ArchTaskBarXWindows::updateReceiver(IArchTaskBarReceiver * /*receiver*/) -{ - // do nothing -} diff --git a/src/lib/arch/unix/ArchTaskBarXWindows.h b/src/lib/arch/unix/ArchTaskBarXWindows.h deleted file mode 100644 index 98fd40ef1..000000000 --- a/src/lib/arch/unix/ArchTaskBarXWindows.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "arch/IArchTaskBar.h" - -#define ARCH_TASKBAR ArchTaskBarXWindows - -//! X11 implementation of IArchTaskBar -class ArchTaskBarXWindows : public IArchTaskBar -{ -public: - ArchTaskBarXWindows(); - virtual ~ArchTaskBarXWindows(); - - // IArchTaskBar overrides - virtual void addReceiver(IArchTaskBarReceiver *); - virtual void removeReceiver(IArchTaskBarReceiver *); - virtual void updateReceiver(IArchTaskBarReceiver *); -}; diff --git a/src/lib/arch/win32/ArchTaskBarWindows.cpp b/src/lib/arch/win32/ArchTaskBarWindows.cpp deleted file mode 100644 index 23de5fd39..000000000 --- a/src/lib/arch/win32/ArchTaskBarWindows.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "arch/win32/ArchTaskBarWindows.h" -#include "arch/Arch.h" -#include "arch/IArchTaskBarReceiver.h" -#include "arch/XArch.h" -#include "arch/win32/ArchMiscWindows.h" -#include "deskflow/win32/AppUtilWindows.h" - -#include -#include - -static const UINT kAddReceiver = WM_USER + 10; -static const UINT kRemoveReceiver = WM_USER + 11; -static const UINT kUpdateReceiver = WM_USER + 12; -static const UINT kNotifyReceiver = WM_USER + 13; -static const UINT kFirstReceiverID = WM_USER + 14; - -// -// ArchTaskBarWindows -// - -ArchTaskBarWindows *ArchTaskBarWindows::s_instance = NULL; - -ArchTaskBarWindows::ArchTaskBarWindows() - : m_mutex(NULL), - m_condVar(NULL), - m_ready(false), - m_result(0), - m_thread(NULL), - m_hwnd(NULL), - m_taskBarRestart(0), - m_nextID(kFirstReceiverID) -{ - // save the singleton instance - s_instance = this; -} - -ArchTaskBarWindows::~ArchTaskBarWindows() -{ - if (m_thread != NULL) { - PostMessage(m_hwnd, WM_QUIT, 0, 0); - ARCH->wait(m_thread, -1.0); - ARCH->closeThread(m_thread); - } - if (m_condVar != NULL) { - ARCH->closeCondVar(m_condVar); - } - if (m_mutex != NULL) { - ARCH->closeMutex(m_mutex); - } - s_instance = NULL; -} - -void ArchTaskBarWindows::init() -{ - // we need a mutex - m_mutex = ARCH->newMutex(); - - // and a condition variable which uses the above mutex - m_ready = false; - m_condVar = ARCH->newCondVar(); - - // we're going to want to get a result from the thread we're - // about to create to know if it initialized successfully. - // so we lock the condition variable. - ARCH->lockMutex(m_mutex); - - // open a window and run an event loop in a separate thread. - // this has to happen in a separate thread because if we - // create a window on the current desktop with the current - // thread then the current thread won't be able to switch - // desktops if it needs to. - m_thread = ARCH->newThread(&ArchTaskBarWindows::threadEntry, this); - - // wait for child thread - while (!m_ready) { - ARCH->waitCondVar(m_condVar, m_mutex, -1.0); - } - - // ready - ARCH->unlockMutex(m_mutex); -} - -void ArchTaskBarWindows::addDialog(HWND hwnd) -{ - ArchMiscWindows::addDialog(hwnd); -} - -void ArchTaskBarWindows::removeDialog(HWND hwnd) -{ - ArchMiscWindows::removeDialog(hwnd); -} - -void ArchTaskBarWindows::addReceiver(IArchTaskBarReceiver *receiver) -{ - // ignore bogus receiver - if (receiver == NULL) { - return; - } - - // add receiver if necessary - ReceiverToInfoMap::iterator index = m_receivers.find(receiver); - if (index == m_receivers.end()) { - // add it, creating a new message ID for it - ReceiverInfo info; - info.m_id = getNextID(); - index = m_receivers.insert(std::make_pair(receiver, info)).first; - - // add ID to receiver mapping - m_idTable.insert(std::make_pair(info.m_id, index)); - } - - // add receiver - PostMessage(m_hwnd, kAddReceiver, index->second.m_id, 0); -} - -void ArchTaskBarWindows::removeReceiver(IArchTaskBarReceiver *receiver) -{ - // find receiver - ReceiverToInfoMap::iterator index = m_receivers.find(receiver); - if (index == m_receivers.end()) { - return; - } - - // remove icon. wait for this to finish before returning. - SendMessage(m_hwnd, kRemoveReceiver, index->second.m_id, 0); - - // recycle the ID - recycleID(index->second.m_id); - - // discard - m_idTable.erase(index->second.m_id); - m_receivers.erase(index); -} - -void ArchTaskBarWindows::updateReceiver(IArchTaskBarReceiver *receiver) -{ - // find receiver - ReceiverToInfoMap::const_iterator index = m_receivers.find(receiver); - if (index == m_receivers.end()) { - return; - } - - // update icon and tool tip - PostMessage(m_hwnd, kUpdateReceiver, index->second.m_id, 0); -} - -UINT ArchTaskBarWindows::getNextID() -{ - if (m_oldIDs.empty()) { - return m_nextID++; - } - UINT id = m_oldIDs.back(); - m_oldIDs.pop_back(); - return id; -} - -void ArchTaskBarWindows::recycleID(UINT id) -{ - m_oldIDs.push_back(id); -} - -void ArchTaskBarWindows::addIcon(UINT id) -{ - ARCH->lockMutex(m_mutex); - CIDToReceiverMap::const_iterator index = m_idTable.find(id); - if (index != m_idTable.end()) { - modifyIconNoLock(index->second, NIM_ADD); - } - ARCH->unlockMutex(m_mutex); -} - -void ArchTaskBarWindows::removeIcon(UINT id) -{ - ARCH->lockMutex(m_mutex); - removeIconNoLock(id); - ARCH->unlockMutex(m_mutex); -} - -void ArchTaskBarWindows::updateIcon(UINT id) -{ - ARCH->lockMutex(m_mutex); - CIDToReceiverMap::const_iterator index = m_idTable.find(id); - if (index != m_idTable.end()) { - modifyIconNoLock(index->second, NIM_MODIFY); - } - ARCH->unlockMutex(m_mutex); -} - -void ArchTaskBarWindows::addAllIcons() -{ - ARCH->lockMutex(m_mutex); - for (ReceiverToInfoMap::const_iterator index = m_receivers.begin(); index != m_receivers.end(); ++index) { - modifyIconNoLock(index, NIM_ADD); - } - ARCH->unlockMutex(m_mutex); -} - -void ArchTaskBarWindows::removeAllIcons() -{ - ARCH->lockMutex(m_mutex); - for (ReceiverToInfoMap::const_iterator index = m_receivers.begin(); index != m_receivers.end(); ++index) { - removeIconNoLock(index->second.m_id); - } - ARCH->unlockMutex(m_mutex); -} - -void ArchTaskBarWindows::modifyIconNoLock(ReceiverToInfoMap::const_iterator index, DWORD taskBarMessage) -{ - // get receiver - UINT id = index->second.m_id; - IArchTaskBarReceiver *receiver = index->first; - - // lock receiver so icon and tool tip are guaranteed to be consistent - receiver->lock(); - - // get icon data - HICON icon = static_cast(const_cast(receiver->getIcon())); - - // get tool tip - std::string toolTip = receiver->getToolTip(); - - // done querying - receiver->unlock(); - - // prepare to add icon - NOTIFYICONDATA data; - data.cbSize = sizeof(NOTIFYICONDATA); - data.hWnd = m_hwnd; - data.uID = id; - data.uFlags = NIF_MESSAGE; - data.uCallbackMessage = kNotifyReceiver; - data.hIcon = icon; - if (icon != NULL) { - data.uFlags |= NIF_ICON; - } - if (!toolTip.empty()) { - strncpy(data.szTip, toolTip.c_str(), sizeof(data.szTip)); - data.szTip[sizeof(data.szTip) - 1] = '\0'; - data.uFlags |= NIF_TIP; - } else { - data.szTip[0] = '\0'; - } - - // add icon - if (Shell_NotifyIcon(taskBarMessage, &data) == 0) { - // failed - } -} - -void ArchTaskBarWindows::removeIconNoLock(UINT id) -{ - NOTIFYICONDATA data; - data.cbSize = sizeof(NOTIFYICONDATA); - data.hWnd = m_hwnd; - data.uID = id; - if (Shell_NotifyIcon(NIM_DELETE, &data) == 0) { - // failed - } -} - -void ArchTaskBarWindows::handleIconMessage(IArchTaskBarReceiver *receiver, LPARAM lParam) -{ - // process message - switch (lParam) { - case WM_LBUTTONDOWN: - receiver->showStatus(); - break; - - case WM_LBUTTONDBLCLK: - receiver->primaryAction(); - break; - - case WM_RBUTTONUP: { - POINT p; - GetCursorPos(&p); - receiver->runMenu(p.x, p.y); - break; - } - - case WM_MOUSEMOVE: - // currently unused - break; - - default: - // unused - break; - } -} - -bool ArchTaskBarWindows::processDialogs(MSG *msg) -{ - // only one thread can be in this method on any particular object - // at any given time. that's not a problem since only our event - // loop calls this method and there's just one of those. - - ARCH->lockMutex(m_mutex); - - // there was previously some code here, with the comment "remove removed - // dialogs": - // m_dialogs.erase(false); - // - // it's not entirely clear what this code was doing, but it was probably - // trying to erase dialogs that had been removed (i.e. the map value was - // `false`). - for (auto it = m_dialogs.begin(); it != m_dialogs.end();) { - if (it->second == false) { - it = m_dialogs.erase(it); - } else { - ++it; - } - } - - // merge added dialogs into the dialog list - for (Dialogs::const_iterator index = m_addedDialogs.begin(); index != m_addedDialogs.end(); ++index) { - m_dialogs.insert(std::make_pair(index->first, index->second)); - } - m_addedDialogs.clear(); - - ARCH->unlockMutex(m_mutex); - - // check message against all dialogs until one handles it. - // note that we don't hold a lock while checking because - // the message is processed and may make calls to this - // object. that's okay because addDialog() and - // removeDialog() don't change the map itself (just the - // values of some elements). - ARCH->lockMutex(m_mutex); - for (Dialogs::const_iterator index = m_dialogs.begin(); index != m_dialogs.end(); ++index) { - if (index->second) { - ARCH->unlockMutex(m_mutex); - if (IsDialogMessage(index->first, msg)) { - return true; - } - ARCH->lockMutex(m_mutex); - } - } - ARCH->unlockMutex(m_mutex); - - return false; -} - -LRESULT -ArchTaskBarWindows::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case kNotifyReceiver: { - // lookup receiver - CIDToReceiverMap::const_iterator index = m_idTable.find((UINT)wParam); - if (index != m_idTable.end()) { - IArchTaskBarReceiver *receiver = index->second->first; - handleIconMessage(receiver, lParam); - return 0; - } - break; - } - - case kAddReceiver: - addIcon((UINT)wParam); - break; - - case kRemoveReceiver: - removeIcon((UINT)wParam); - break; - - case kUpdateReceiver: - updateIcon((UINT)wParam); - break; - - default: - if (msg == m_taskBarRestart) { - // task bar was recreated so re-add our icons - addAllIcons(); - } - break; - } - - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -LRESULT CALLBACK ArchTaskBarWindows::staticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - // if msg is WM_NCCREATE, extract the ArchTaskBarWindows* and put - // it in the extra window data then forward the call. - ArchTaskBarWindows *self = NULL; - if (msg == WM_NCCREATE) { - CREATESTRUCT *createInfo; - createInfo = reinterpret_cast(lParam); - self = static_cast(createInfo->lpCreateParams); - SetWindowLongPtr(hwnd, 0, reinterpret_cast(createInfo->lpCreateParams)); - } else { - // get the extra window data and forward the call - LONG_PTR data = GetWindowLongPtr(hwnd, 0); - if (data != 0) { - self = static_cast(reinterpret_cast(data)); - } - } - - // forward the message - if (self != NULL) { - return self->wndProc(hwnd, msg, wParam, lParam); - } else { - return DefWindowProc(hwnd, msg, wParam, lParam); - } -} - -void ArchTaskBarWindows::threadMainLoop() -{ - // register the task bar restart message - m_taskBarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); - - // register a window class - LPCTSTR className = TEXT("DeskflowTaskBar"); - WNDCLASSEX classInfo; - classInfo.cbSize = sizeof(classInfo); - classInfo.style = CS_NOCLOSE; - classInfo.lpfnWndProc = &ArchTaskBarWindows::staticWndProc; - classInfo.cbClsExtra = 0; - classInfo.cbWndExtra = sizeof(ArchTaskBarWindows *); - classInfo.hInstance = instanceWin32(); - classInfo.hIcon = NULL; - classInfo.hCursor = NULL; - classInfo.hbrBackground = NULL; - classInfo.lpszMenuName = NULL; - classInfo.lpszClassName = className; - classInfo.hIconSm = NULL; - ATOM windowClass = RegisterClassEx(&classInfo); - - // create window - m_hwnd = CreateWindowEx( - WS_EX_TOOLWINDOW, className, TEXT("Deskflow Task Bar"), WS_POPUP, 0, 0, 1, 1, NULL, NULL, instanceWin32(), - static_cast(this) - ); - - // signal ready - ARCH->lockMutex(m_mutex); - m_ready = true; - ARCH->broadcastCondVar(m_condVar); - ARCH->unlockMutex(m_mutex); - - // handle failure - if (m_hwnd == NULL) { - UnregisterClass(className, instanceWin32()); - return; - } - - // main loop - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - if (!processDialogs(&msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - // clean up - removeAllIcons(); - DestroyWindow(m_hwnd); - UnregisterClass(className, instanceWin32()); -} - -void *ArchTaskBarWindows::threadEntry(void *self) -{ - static_cast(self)->threadMainLoop(); - return NULL; -} - -HINSTANCE ArchTaskBarWindows::instanceWin32() -{ - return ArchMiscWindows::instanceWin32(); -} diff --git a/src/lib/arch/win32/ArchTaskBarWindows.h b/src/lib/arch/win32/ArchTaskBarWindows.h deleted file mode 100644 index e14fa2304..000000000 --- a/src/lib/arch/win32/ArchTaskBarWindows.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "arch/IArchMultithread.h" -#include "arch/IArchTaskBar.h" -#include "common/stdmap.h" -#include "common/stdvector.h" - -#define WIN32_LEAN_AND_MEAN -#include - -#define ARCH_TASKBAR ArchTaskBarWindows - -//! Win32 implementation of IArchTaskBar -class ArchTaskBarWindows : public IArchTaskBar -{ -public: - ArchTaskBarWindows(); - virtual ~ArchTaskBarWindows(); - - virtual void init(); - - //! Add a dialog window - /*! - Tell the task bar event loop about a dialog. Win32 annoyingly - requires messages destined for modeless dialog boxes to be - dispatched differently than other messages. - */ - static void addDialog(HWND); - - //! Remove a dialog window - /*! - Remove a dialog window added via \c addDialog(). - */ - static void removeDialog(HWND); - - // IArchTaskBar overrides - virtual void addReceiver(IArchTaskBarReceiver *); - virtual void removeReceiver(IArchTaskBarReceiver *); - virtual void updateReceiver(IArchTaskBarReceiver *); - -private: - class ReceiverInfo - { - public: - UINT m_id; - }; - - using ReceiverToInfoMap = std::map; - using CIDToReceiverMap = std::map; - using CIDStack = std::vector; - using Dialogs = std::map; - - UINT getNextID(); - void recycleID(UINT); - - void addIcon(UINT); - void removeIcon(UINT); - void updateIcon(UINT); - void addAllIcons(); - void removeAllIcons(); - void modifyIconNoLock(ReceiverToInfoMap::const_iterator, DWORD taskBarMessage); - void removeIconNoLock(UINT id); - void handleIconMessage(IArchTaskBarReceiver *, LPARAM); - - bool processDialogs(MSG *); - LRESULT wndProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK staticWndProc(HWND, UINT, WPARAM, LPARAM); - void threadMainLoop(); - static void *threadEntry(void *); - - HINSTANCE instanceWin32(); - -private: - static ArchTaskBarWindows *s_instance; - - // multithread data - ArchMutex m_mutex; - ArchCond m_condVar; - bool m_ready; - int m_result; - ArchThread m_thread; - - // child thread data - HWND m_hwnd; - UINT m_taskBarRestart; - - // shared data - ReceiverToInfoMap m_receivers; - CIDToReceiverMap m_idTable; - CIDStack m_oldIDs; - UINT m_nextID; - - // dialogs - Dialogs m_dialogs; - Dialogs m_addedDialogs; -}; diff --git a/src/lib/deskflow/App.cpp b/src/lib/deskflow/App.cpp index 47622b21c..1ca80b2bb 100644 --- a/src/lib/deskflow/App.cpp +++ b/src/lib/deskflow/App.cpp @@ -67,14 +67,12 @@ App *App::s_instance = nullptr; // App // -App::App(IEventQueue *events, CreateTaskBarReceiverFunc createTaskBarReceiver, deskflow::ArgsBase *args) +App::App(IEventQueue *events, deskflow::ArgsBase *args) : m_bye(&exit), - m_taskBarReceiver(NULL), m_suspended(false), m_events(events), m_args(args), m_fileLog(nullptr), - m_createTaskBarReceiver(createTaskBarReceiver), m_appUtil(events), m_ipcClient(nullptr), m_socketMultiplexer(nullptr) @@ -228,10 +226,6 @@ void App::initApp(int argc, const char **argv) // as a tray icon tooltip BufferedLogOutputter *logBuffer = new BufferedLogOutputter(1000); CLOG->insert(logBuffer, true); - - // make the task bar receiver. the user can control this app - // through the task bar. - m_taskBarReceiver = m_createTaskBarReceiver(logBuffer, m_events); } } @@ -276,7 +270,7 @@ void App::runEventsLoop(void *) // MinimalApp // -MinimalApp::MinimalApp() : App(NULL, NULL, new deskflow::ArgsBase()) +MinimalApp::MinimalApp() : App(NULL, new deskflow::ArgsBase()) { m_arch.init(); setEvents(m_events); diff --git a/src/lib/deskflow/App.h b/src/lib/deskflow/App.h index c77298def..3b96346ae 100644 --- a/src/lib/deskflow/App.h +++ b/src/lib/deskflow/App.h @@ -55,7 +55,7 @@ public: } }; - App(IEventQueue *events, CreateTaskBarReceiverFunc createTaskBarReceiver, deskflow::ArgsBase *args); + App(IEventQueue *events, deskflow::ArgsBase *args); App(App const &) = delete; App(App &&) = delete; virtual ~App(); @@ -110,11 +110,6 @@ public: m_socketMultiplexer = sm; } - virtual IArchTaskBarReceiver *taskBarReceiver() const - { - return m_taskBarReceiver; - } - SocketMultiplexer *getSocketMultiplexer() const { return m_socketMultiplexer; @@ -136,7 +131,6 @@ protected: void cleanupIpcClient(); void runEventsLoop(void *); - IArchTaskBarReceiver *m_taskBarReceiver; bool m_suspended; IEventQueue *m_events; @@ -201,7 +195,6 @@ private: " -1, --no-restart do not try to restart on failure.\n" \ "* --restart restart the server automatically if it fails.\n" \ " -l --log write log messages to file.\n" \ - " --no-tray disable the system tray icon.\n" \ " --enable-drag-drop enable file drag & drop.\n" \ " --enable-crypto enable TLS encryption.\n" \ " --tls-cert specify the path to the TLS certificate file.\n" diff --git a/src/lib/deskflow/ArgParser.cpp b/src/lib/deskflow/ArgParser.cpp index 5f67d9d24..c938ccae7 100644 --- a/src/lib/deskflow/ArgParser.cpp +++ b/src/lib/deskflow/ArgParser.cpp @@ -199,8 +199,6 @@ bool ArgParser::parseGenericArgs(int argc, const char *const *argv, int &i) m_app->version(); } argsBase().m_shouldExitOk = true; - } else if (isArg(i, argc, argv, nullptr, "--no-tray")) { - argsBase().m_disableTray = true; } else if (isArg(i, argc, argv, nullptr, "--ipc")) { argsBase().m_enableIpc = true; } else if (isArg(i, argc, argv, nullptr, "--server")) { diff --git a/src/lib/deskflow/CMakeLists.txt b/src/lib/deskflow/CMakeLists.txt index a1e4021df..ffc0c0941 100644 --- a/src/lib/deskflow/CMakeLists.txt +++ b/src/lib/deskflow/CMakeLists.txt @@ -94,8 +94,6 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE} ClientApp.h ClientArgs.cpp ClientArgs.h - ClientTaskBarReceiver.cpp - ClientTaskBarReceiver.h clipboard_types.h Clipboard.cpp Clipboard.h @@ -149,8 +147,6 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE} ServerApp.h ServerArgs.cpp ServerArgs.h - ServerTaskBarReceiver.cpp - ServerTaskBarReceiver.h StreamChunker.cpp StreamChunker.h XDeskflow.cpp diff --git a/src/lib/deskflow/ClientApp.cpp b/src/lib/deskflow/ClientApp.cpp index 00d6e4a9d..916fb1adc 100644 --- a/src/lib/deskflow/ClientApp.cpp +++ b/src/lib/deskflow/ClientApp.cpp @@ -19,7 +19,6 @@ #include "deskflow/ClientApp.h" #include "arch/Arch.h" -#include "arch/IArchTaskBarReceiver.h" #include "base/Event.h" #include "base/IEventQueue.h" #include "base/Log.h" @@ -74,8 +73,8 @@ #define RETRY_TIME 1.0 -ClientApp::ClientApp(IEventQueue *events, CreateTaskBarReceiverFunc createTaskBarReceiver) - : App(events, createTaskBarReceiver, new deskflow::ClientArgs()), +ClientApp::ClientApp(IEventQueue *events) + : App(events, new deskflow::ClientArgs()), m_client(NULL), m_clientScreen(NULL), m_serverAddress(NULL) @@ -230,9 +229,6 @@ void ClientApp::updateStatus() void ClientApp::updateStatus(const std::string &msg) { - if (m_taskBarReceiver) { - m_taskBarReceiver->updateStatus(m_client, msg); - } } void ClientApp::resetRestartTimeout() @@ -542,11 +538,6 @@ int ClientApp::runInner(int argc, char **argv, ILogOutputter *outputter, Startup // run result = startup(argc, argv); } catch (...) { - if (m_taskBarReceiver) { - // done with task bar receiver - delete m_taskBarReceiver; - } - delete m_serverAddress; throw; diff --git a/src/lib/deskflow/ClientApp.h b/src/lib/deskflow/ClientApp.h index 1f5a36a30..09c9e96e9 100644 --- a/src/lib/deskflow/ClientApp.h +++ b/src/lib/deskflow/ClientApp.h @@ -36,7 +36,7 @@ class ClientArgs; class ClientApp : public App { public: - ClientApp(IEventQueue *events, CreateTaskBarReceiverFunc createTaskBarReceiver); + ClientApp(IEventQueue *events); virtual ~ClientApp(); // diff --git a/src/lib/deskflow/ClientTaskBarReceiver.cpp b/src/lib/deskflow/ClientTaskBarReceiver.cpp deleted file mode 100644 index 9ea599821..000000000 --- a/src/lib/deskflow/ClientTaskBarReceiver.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "deskflow/ClientTaskBarReceiver.h" -#include "arch/Arch.h" -#include "base/IEventQueue.h" -#include "base/String.h" -#include "client/Client.h" -#include "common/constants.h" -#include "mt/Lock.h" - -// -// ClientTaskBarReceiver -// - -ClientTaskBarReceiver::ClientTaskBarReceiver(IEventQueue *events) : m_state(kNotRunning), m_events(events) -{ - // do nothing -} - -ClientTaskBarReceiver::~ClientTaskBarReceiver() -{ - // do nothing -} - -void ClientTaskBarReceiver::updateStatus(Client *client, const std::string &errorMsg) -{ - { - // update our status - m_errorMessage = errorMsg; - if (client == NULL) { - if (m_errorMessage.empty()) { - m_state = kNotRunning; - } else { - m_state = kNotWorking; - } - } else { - m_server = client->getServerAddress().getHostname(); - - if (client->isConnected()) { - m_state = kConnected; - } else if (client->isConnecting()) { - m_state = kConnecting; - } else { - m_state = kNotConnected; - } - } - - // let subclasses have a go - onStatusChanged(client); - } - - // tell task bar - ARCH->updateReceiver(this); -} - -ClientTaskBarReceiver::EState ClientTaskBarReceiver::getStatus() const -{ - return m_state; -} - -const std::string &ClientTaskBarReceiver::getErrorMessage() const -{ - return m_errorMessage; -} - -void ClientTaskBarReceiver::quit() -{ - m_events->addEvent(Event(Event::kQuit)); -} - -void ClientTaskBarReceiver::onStatusChanged(Client *) -{ - // do nothing -} - -void ClientTaskBarReceiver::lock() const -{ - // do nothing -} - -void ClientTaskBarReceiver::unlock() const -{ - // do nothing -} - -std::string ClientTaskBarReceiver::getToolTip() const -{ - switch (m_state) { - case kNotRunning: - return deskflow::string::sprintf("%s: Not running", kAppName); - - case kNotWorking: - return deskflow::string::sprintf("%s: %s", kAppName, m_errorMessage.c_str()); - - case kNotConnected: - return deskflow::string::sprintf("%s: Not connected: %s", kAppName, m_errorMessage.c_str()); - - case kConnecting: - return deskflow::string::sprintf("%s: Connecting to %s...", kAppName, m_server.c_str()); - - case kConnected: - return deskflow::string::sprintf("%s: Connected to %s", kAppName, m_server.c_str()); - - default: - return ""; - } -} diff --git a/src/lib/deskflow/ClientTaskBarReceiver.h b/src/lib/deskflow/ClientTaskBarReceiver.h deleted file mode 100644 index baa84fe7c..000000000 --- a/src/lib/deskflow/ClientTaskBarReceiver.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "arch/IArchTaskBarReceiver.h" -#include "base/log_outputters.h" -#include "client/Client.h" - -class IEventQueue; - -//! Implementation of IArchTaskBarReceiver for the deskflow server -class ClientTaskBarReceiver : public IArchTaskBarReceiver -{ -public: - ClientTaskBarReceiver(IEventQueue *events); - virtual ~ClientTaskBarReceiver(); - - //! @name manipulators - //@{ - - //! Update status - /*! - Determine the status and query required information from the client. - */ - void updateStatus(Client *, const std::string &errorMsg); - - void updateStatus(INode *n, const std::string &errorMsg) - { - updateStatus((Client *)n, errorMsg); - } - - //@} - - // IArchTaskBarReceiver overrides - virtual void showStatus() = 0; - virtual void runMenu(int x, int y) = 0; - virtual void primaryAction() = 0; - virtual void lock() const; - virtual void unlock() const; - virtual Icon getIcon() const = 0; - virtual std::string getToolTip() const; - virtual void cleanup() - { - } - -protected: - enum EState - { - kNotRunning, - kNotWorking, - kNotConnected, - kConnecting, - kConnected, - kMaxState - }; - - //! Get status - EState getStatus() const; - - //! Get error message - const std::string &getErrorMessage() const; - - //! Quit app - /*! - Causes the application to quit gracefully - */ - void quit(); - - //! Status change notification - /*! - Called when status changes. The default implementation does nothing. - */ - virtual void onStatusChanged(Client *client); - -private: - EState m_state; - std::string m_errorMessage; - std::string m_server; - IEventQueue *m_events; -}; - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events); diff --git a/src/lib/deskflow/IApp.h b/src/lib/deskflow/IApp.h index 802d56178..19174dccd 100644 --- a/src/lib/deskflow/IApp.h +++ b/src/lib/deskflow/IApp.h @@ -27,7 +27,6 @@ class ArgsBase; } class ILogOutputter; -class IArchTaskBarReceiver; namespace deskflow { class Screen; } @@ -41,7 +40,6 @@ public: virtual int standardStartup(int argc, char **argv) = 0; virtual int runInner(int argc, char **argv, ILogOutputter *outputter, StartupFunc startup) = 0; virtual void startNode() = 0; - virtual IArchTaskBarReceiver *taskBarReceiver() const = 0; virtual void bye(int error) = 0; virtual int mainLoop() = 0; virtual void initApp(int argc, const char **argv) = 0; diff --git a/src/lib/deskflow/ServerApp.cpp b/src/lib/deskflow/ServerApp.cpp index 73b764fd1..a296e3008 100644 --- a/src/lib/deskflow/ServerApp.cpp +++ b/src/lib/deskflow/ServerApp.cpp @@ -28,7 +28,6 @@ #include "deskflow/ArgParser.h" #include "deskflow/Screen.h" #include "deskflow/ServerArgs.h" -#include "deskflow/ServerTaskBarReceiver.h" #include "deskflow/XScreen.h" #include "net/InverseSockets/InverseSocketFactory.h" #include "net/SocketMultiplexer.h" @@ -81,8 +80,8 @@ using namespace deskflow::server; // ServerApp // -ServerApp::ServerApp(IEventQueue *events, CreateTaskBarReceiverFunc createTaskBarReceiver) - : App(events, createTaskBarReceiver, new deskflow::ServerArgs()), +ServerApp::ServerApp(IEventQueue *events) + : App(events, new deskflow::ServerArgs()), m_server(NULL), m_serverState(kUninitialized), m_serverScreen(NULL), @@ -327,9 +326,6 @@ void ServerApp::updateStatus() void ServerApp::updateStatus(const std::string &msg) { - if (m_taskBarReceiver) { - m_taskBarReceiver->updateStatus(m_server, msg); - } } void ServerApp::closeClientListener(ClientListener *listen) @@ -808,11 +804,6 @@ int ServerApp::runInner(int argc, char **argv, ILogOutputter *outputter, Startup // run int result = startup(argc, argv); - if (m_taskBarReceiver) { - // done with task bar receiver - delete m_taskBarReceiver; - } - delete m_deskflowAddress; return result; } diff --git a/src/lib/deskflow/ServerApp.h b/src/lib/deskflow/ServerApp.h index a7b58ec54..7010b45a8 100644 --- a/src/lib/deskflow/ServerApp.h +++ b/src/lib/deskflow/ServerApp.h @@ -56,7 +56,7 @@ class ServerApp : public App using ServerConfig = deskflow::server::Config; public: - ServerApp(IEventQueue *events, CreateTaskBarReceiverFunc createTaskBarReceiver); + ServerApp(IEventQueue *events); virtual ~ServerApp(); // diff --git a/src/lib/deskflow/ServerTaskBarReceiver.cpp b/src/lib/deskflow/ServerTaskBarReceiver.cpp deleted file mode 100644 index 08c5908b7..000000000 --- a/src/lib/deskflow/ServerTaskBarReceiver.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "deskflow/ServerTaskBarReceiver.h" -#include "arch/Arch.h" -#include "base/IEventQueue.h" -#include "base/String.h" -#include "common/constants.h" -#include "mt/Lock.h" -#include "server/Server.h" - -// -// ServerTaskBarReceiver -// - -ServerTaskBarReceiver::ServerTaskBarReceiver(IEventQueue *events) : m_state(kNotRunning), m_events(events) -{ - // do nothing -} - -ServerTaskBarReceiver::~ServerTaskBarReceiver() -{ - // do nothing -} - -void ServerTaskBarReceiver::updateStatus(Server *server, const std::string &errorMsg) -{ - { - // update our status - m_errorMessage = errorMsg; - if (server == NULL) { - if (m_errorMessage.empty()) { - m_state = kNotRunning; - } else { - m_state = kNotWorking; - } - } else { - m_clients.clear(); - server->getClients(m_clients); - if (m_clients.size() <= 1) { - m_state = kNotConnected; - } else { - m_state = kConnected; - } - } - - // let subclasses have a go - onStatusChanged(server); - } - - // tell task bar - ARCH->updateReceiver(this); -} - -ServerTaskBarReceiver::EState ServerTaskBarReceiver::getStatus() const -{ - return m_state; -} - -const std::string &ServerTaskBarReceiver::getErrorMessage() const -{ - return m_errorMessage; -} - -const ServerTaskBarReceiver::Clients &ServerTaskBarReceiver::getClients() const -{ - return m_clients; -} - -void ServerTaskBarReceiver::quit() -{ - m_events->addEvent(Event(Event::kQuit)); -} - -void ServerTaskBarReceiver::onStatusChanged(Server *) -{ - // do nothing -} - -void ServerTaskBarReceiver::lock() const -{ - // do nothing -} - -void ServerTaskBarReceiver::unlock() const -{ - // do nothing -} - -std::string ServerTaskBarReceiver::getToolTip() const -{ - switch (m_state) { - case kNotRunning: - return deskflow::string::sprintf("%s: Not running", kAppName); - - case kNotWorking: - return deskflow::string::sprintf("%s: %s", kAppName, m_errorMessage.c_str()); - - case kNotConnected: - return deskflow::string::sprintf("%s: Waiting for clients", kAppName); - - case kConnected: - return deskflow::string::sprintf("%s: Connected", kAppName); - - default: - return ""; - } -} diff --git a/src/lib/deskflow/ServerTaskBarReceiver.h b/src/lib/deskflow/ServerTaskBarReceiver.h deleted file mode 100644 index c83b58d5b..000000000 --- a/src/lib/deskflow/ServerTaskBarReceiver.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "arch/IArchTaskBarReceiver.h" -#include "base/Event.h" -#include "base/EventTypes.h" -#include "common/stdvector.h" -#include "deskflow/ServerApp.h" -#include "server/Server.h" - -class IEventQueue; - -//! Implementation of IArchTaskBarReceiver for the deskflow server -class ServerTaskBarReceiver : public IArchTaskBarReceiver -{ -public: - ServerTaskBarReceiver(IEventQueue *events); - virtual ~ServerTaskBarReceiver(); - - //! @name manipulators - //@{ - - //! Update status - /*! - Determine the status and query required information from the server. - */ - void updateStatus(Server *, const std::string &errorMsg); - - void updateStatus(INode *n, const std::string &errorMsg) - { - updateStatus((Server *)n, errorMsg); - } - - //@} - - // IArchTaskBarReceiver overrides - virtual void showStatus() = 0; - virtual void runMenu(int x, int y) = 0; - virtual void primaryAction() = 0; - virtual void lock() const; - virtual void unlock() const; - virtual Icon getIcon() const = 0; - virtual std::string getToolTip() const; - -protected: - using Clients = std::vector; - enum EState - { - kNotRunning, - kNotWorking, - kNotConnected, - kConnected, - kMaxState - }; - - //! Get status - EState getStatus() const; - - //! Get error message - const std::string &getErrorMessage() const; - - //! Get connected clients - const Clients &getClients() const; - - //! Quit app - /*! - Causes the application to quit gracefully - */ - void quit(); - - //! Status change notification - /*! - Called when status changes. The default implementation does - nothing. - */ - virtual void onStatusChanged(Server *server); - -private: - EState m_state; - std::string m_errorMessage; - Clients m_clients; - IEventQueue *m_events; -}; - -IArchTaskBarReceiver *createTaskBarReceiver(const BufferedLogOutputter *logBuffer, IEventQueue *events); diff --git a/src/lib/deskflow/win32/AppUtilWindows.cpp b/src/lib/deskflow/win32/AppUtilWindows.cpp index 1d7ffe0b5..29be6cbad 100644 --- a/src/lib/deskflow/win32/AppUtilWindows.cpp +++ b/src/lib/deskflow/win32/AppUtilWindows.cpp @@ -18,7 +18,6 @@ #include "deskflow/win32/AppUtilWindows.h" -#include "arch/IArchTaskBarReceiver.h" #include "arch/win32/ArchMiscWindows.h" #include "arch/win32/XArchWindows.h" #include "base/Event.h" diff --git a/src/lib/gui/core/CoreProcess.cpp b/src/lib/gui/core/CoreProcess.cpp index 552f60e26..5860ba726 100644 --- a/src/lib/gui/core/CoreProcess.cpp +++ b/src/lib/gui/core/CoreProcess.cpp @@ -499,7 +499,6 @@ void CoreProcess::cleanup() bool CoreProcess::addGenericArgs(QStringList &args, const ProcessMode processMode) const { args << "-f" - << "--no-tray" << "--debug" << m_appConfig.logLevelText(); args << "--name" << m_appConfig.screenName(); diff --git a/src/test/mock/deskflow/MockApp.h b/src/test/mock/deskflow/MockApp.h index 6d5b9530f..60b882a8b 100644 --- a/src/test/mock/deskflow/MockApp.h +++ b/src/test/mock/deskflow/MockApp.h @@ -26,7 +26,7 @@ class MockApp : public App { public: - MockApp() : App(NULL, NULL, NULL) + MockApp() : App(NULL, NULL) { } diff --git a/src/test/unittests/deskflow/GenericArgsParsingTests.cpp b/src/test/unittests/deskflow/GenericArgsParsingTests.cpp index 648d20fdc..4c1777842 100644 --- a/src/test/unittests/deskflow/GenericArgsParsingTests.cpp +++ b/src/test/unittests/deskflow/GenericArgsParsingTests.cpp @@ -216,18 +216,6 @@ TEST_F(GenericArgsParsingTests, parseGenericArgs_versionCmd_showVersion) EXPECT_EQ(1, i); } -TEST_F(GenericArgsParsingTests, parseGenericArgs_noTrayCmd_disableTrayTrue) -{ - int i = 1; - const int argc = 2; - const char *kNoTrayCmd[argc] = {"stub", "--no-tray"}; - - m_argParser->parseGenericArgs(argc, kNoTrayCmd, i); - - EXPECT_EQ(true, argsBase.m_disableTray); - EXPECT_EQ(1, i); -} - TEST_F(GenericArgsParsingTests, parseGenericArgs_ipcCmd_enableIpcTrue) { int i = 1; diff --git a/src/test/unittests/deskflow/ServerAppTests.cpp b/src/test/unittests/deskflow/ServerAppTests.cpp index 7aa862784..1ea0f30d1 100644 --- a/src/test/unittests/deskflow/ServerAppTests.cpp +++ b/src/test/unittests/deskflow/ServerAppTests.cpp @@ -29,7 +29,7 @@ using ::testing::NiceMock; class MockServerApp : public ServerApp { public: - MockServerApp() : ServerApp(nullptr, nullptr) + MockServerApp() : ServerApp(nullptr) { } };