diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt index 9e9cedd5..43a879b3 100644 --- a/src/cmd/CMakeLists.txt +++ b/src/cmd/CMakeLists.txt @@ -18,3 +18,7 @@ add_subdirectory(synergyc) add_subdirectory(synergys) add_subdirectory(synergyd) add_subdirectory(usynergy) + +if (WIN32) + add_subdirectory(synergyp) +endif() diff --git a/src/cmd/synergyc/synergyc.cpp b/src/cmd/synergyc/synergyc.cpp index 4cb7b20c..eccf8b9a 100644 --- a/src/cmd/synergyc/synergyc.cpp +++ b/src/cmd/synergyc/synergyc.cpp @@ -17,6 +17,9 @@ */ #include "CClientApp.h" +#include "CLog.h" +#include "CArch.h" +#include "CEventQueue.h" #if WINAPI_MSWINDOWS #include "CMSWindowsClientTaskBarReceiver.h" @@ -31,6 +34,17 @@ int main(int argc, char** argv) { +#if SYSAPI_WIN32 + // record window instance for tray icon, etc + CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); +#endif + + CArch arch; + arch.init(); + + CLog log; + CEventQueue events; + CClientApp app(createTaskBarReceiver); return app.run(argc, argv); } diff --git a/src/cmd/synergyp/CMSWindowsPortableTaskBarReceiver.cpp b/src/cmd/synergyp/CMSWindowsPortableTaskBarReceiver.cpp new file mode 100644 index 00000000..80ffbf06 --- /dev/null +++ b/src/cmd/synergyp/CMSWindowsPortableTaskBarReceiver.cpp @@ -0,0 +1,391 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 "CMSWindowsPortableTaskBarReceiver.h" +#include "CMSWindowsClipboard.h" +#include "IEventQueue.h" +#include "LogOutputters.h" +#include "BasicTypes.h" +#include "CArch.h" +#include "CArchTaskBarWindows.h" +#include "resource.h" +#include "CArchMiscWindows.h" +#include "CMSWindowsScreen.h" + +// +// CMSWindowsPortableTaskBarReceiver +// + +const UINT CMSWindowsPortableTaskBarReceiver::s_stateToIconID[kMaxState] = +{ + IDI_TASKBAR_NOT_RUNNING, + IDI_TASKBAR_NOT_WORKING, + IDI_TASKBAR_NOT_CONNECTED, + IDI_TASKBAR_CONNECTED +}; + +CMSWindowsPortableTaskBarReceiver::CMSWindowsPortableTaskBarReceiver( + HINSTANCE appInstance, const CBufferedLogOutputter* logBuffer) : + CPortableTaskBarReceiver(), + m_appInstance(appInstance), + m_window(NULL), + m_logBuffer(logBuffer) +{ + for (UInt32 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 +CMSWindowsPortableTaskBarReceiver::cleanup() +{ + ARCH->removeReceiver(this); + for (UInt32 i = 0; i < kMaxState; ++i) { + deleteIcon(m_icon[i]); + } + DestroyMenu(m_menu); + destroyWindow(); +} + +CMSWindowsPortableTaskBarReceiver::~CMSWindowsPortableTaskBarReceiver() +{ + cleanup(); +} + +void +CMSWindowsPortableTaskBarReceiver::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()); + child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_CLIENTS); + SendMessage(child, LB_RESETCONTENT, 0, 0); + + 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 +CMSWindowsPortableTaskBarReceiver::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: + EVENTQUEUE->addEvent(CEvent(getReloadConfigEvent(), + IEventQueue::getSystemTarget())); + break; + + case IDC_FORCE_RECONNECT: + EVENTQUEUE->addEvent(CEvent(getForceReconnectEvent(), + IEventQueue::getSystemTarget())); + break; + + case ID_SYNERGY_RESETSERVER: + EVENTQUEUE->addEvent(CEvent(getResetServerEvent(), + IEventQueue::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 +CMSWindowsPortableTaskBarReceiver::primaryAction() +{ + showStatus(); +} + +const IArchTaskBarReceiver::Icon +CMSWindowsPortableTaskBarReceiver::getIcon() const +{ + return reinterpret_cast(m_icon[getStatus()]); +} + +void +CMSWindowsPortableTaskBarReceiver::copyLog() const +{ + if (m_logBuffer != NULL) { + // collect log buffer + CString data; + for (CBufferedLogOutputter::const_iterator index = m_logBuffer->begin(); + index != m_logBuffer->end(); ++index) { + data += *index; + data += "\n"; + } + + // copy log to clipboard + if (!data.empty()) { + CMSWindowsClipboard clipboard(m_window); + clipboard.open(0); + clipboard.emptyUnowned(); + clipboard.add(IClipboard::kText, data); + clipboard.close(); + } + } +} + +void +CMSWindowsPortableTaskBarReceiver::onStatusChanged() +{ + if (IsWindowVisible(m_window)) { + showStatus(); + } +} + +HICON +CMSWindowsPortableTaskBarReceiver::loadIcon(UINT id) +{ + HANDLE icon = LoadImage(m_appInstance, + MAKEINTRESOURCE(id), + IMAGE_ICON, + 0, 0, + LR_DEFAULTCOLOR); + return reinterpret_cast(icon); +} + +void +CMSWindowsPortableTaskBarReceiver::deleteIcon(HICON icon) +{ + if (icon != NULL) { + DestroyIcon(icon); + } +} + +void +CMSWindowsPortableTaskBarReceiver::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)&CMSWindowsPortableTaskBarReceiver::staticDlgProc, + reinterpret_cast( + reinterpret_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 + CArchTaskBarWindows::addDialog(m_window); +} + +void +CMSWindowsPortableTaskBarReceiver::destroyWindow() +{ + if (m_window != NULL) { + CArchTaskBarWindows::removeDialog(m_window); + DestroyWindow(m_window); + m_window = NULL; + } +} + +BOOL +CMSWindowsPortableTaskBarReceiver::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 +CMSWindowsPortableTaskBarReceiver::staticDlgProc(HWND hwnd, + UINT msg, WPARAM wParam, LPARAM lParam) +{ + // if msg is WM_INITDIALOG, extract the CMSWindowsPortableTaskBarReceiver* + // and put it in the extra window data then forward the call. + CMSWindowsPortableTaskBarReceiver* self = NULL; + if (msg == WM_INITDIALOG) { + self = reinterpret_cast( + reinterpret_cast(lParam)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); + } + else { + // get the extra window data and forward the call + LONG data = (LONG)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (data != 0) { + self = reinterpret_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 CBufferedLogOutputter* logBuffer) +{ + CArchMiscWindows::setIcons( + (HICON)LoadImage(CArchMiscWindows::instanceWin32(), + MAKEINTRESOURCE(IDI_SYNERGY), + IMAGE_ICON, + 32, 32, LR_SHARED), + (HICON)LoadImage(CArchMiscWindows::instanceWin32(), + MAKEINTRESOURCE(IDI_SYNERGY), + IMAGE_ICON, + 16, 16, LR_SHARED)); + + return new CMSWindowsPortableTaskBarReceiver( + CMSWindowsScreen::getWindowInstance(), logBuffer); +} diff --git a/src/cmd/synergyp/CMSWindowsPortableTaskBarReceiver.h b/src/cmd/synergyp/CMSWindowsPortableTaskBarReceiver.h new file mode 100644 index 00000000..88832ae3 --- /dev/null +++ b/src/cmd/synergyp/CMSWindowsPortableTaskBarReceiver.h @@ -0,0 +1,66 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 + +#define WIN32_LEAN_AND_MEAN + +#include "CPortableTaskBarReceiver.h" +#include + +class CBufferedLogOutputter; + +//! Implementation of CPortableTaskBarReceiver for Microsoft Windows +class CMSWindowsPortableTaskBarReceiver : public CPortableTaskBarReceiver { +public: + CMSWindowsPortableTaskBarReceiver(HINSTANCE, const CBufferedLogOutputter*); + virtual ~CMSWindowsPortableTaskBarReceiver(); + + // IArchTaskBarReceiver overrides + virtual void showStatus(); + virtual void runMenu(int x, int y); + virtual void primaryAction(); + virtual const Icon getIcon() const; + void cleanup(); + +protected: + void copyLog() const; + + // CPortableTaskBarReceiver 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 CBufferedLogOutputter* m_logBuffer; + static const UINT s_stateToIconID[]; +}; diff --git a/src/cmd/synergyp/CMakeLists.txt b/src/cmd/synergyp/CMakeLists.txt new file mode 100644 index 00000000..292197dc --- /dev/null +++ b/src/cmd/synergyp/CMakeLists.txt @@ -0,0 +1,74 @@ +# synergy -- mouse and keyboard sharing utility +# Copyright (C) 2012 Bolton Software Ltd. +# Copyright (C) 2009 Nick Bolton +# +# 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 COPYING 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 . + +set(src + synergyp.cpp +) + +if (WIN32) + list(APPEND src + CMSWindowsPortableTaskBarReceiver.cpp + CMSWindowsPortableTaskBarReceiver.h + resource.h + synergyp.ico + synergyp.rc + tb_error.ico + tb_idle.ico + tb_run.ico + tb_wait.ico + ) +elseif (APPLE) + list(APPEND src COSXPortableTaskBarReceiver.cpp) +elseif (UNIX) + list(APPEND src CXWindowsPortableTaskBarReceiver.cpp) +endif() + +set(inc + ../../lib/arch + ../../lib/base + ../../lib/common + ../../lib/io + ../../lib/ipc + ../../lib/mt + ../../lib/net + ../../lib/platform + ../../lib/synergy + ../../lib/server +) + +if (UNIX) + list(APPEND inc + ../../.. + ) +endif() + +include_directories(${inc}) + +if (WIN32) + add_executable(synergyp WIN32 ${src}) +else() + add_executable(synergyp ${src}) +endif() + +target_link_libraries(synergyp + arch base client common io mt net ipc platform server synergy client ${libs}) + +if (CONF_CPACK) + install(TARGETS + synergyp + COMPONENT core + DESTINATION bin) +endif() diff --git a/src/cmd/synergyp/COSXPortableTaskBarReceiver.cpp b/src/cmd/synergyp/COSXPortableTaskBarReceiver.cpp new file mode 100644 index 00000000..aae65393 --- /dev/null +++ b/src/cmd/synergyp/COSXPortableTaskBarReceiver.cpp @@ -0,0 +1,66 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 "COSXServerTaskBarReceiver.h" +#include "CArch.h" + +// +// COSXServerTaskBarReceiver +// + +COSXServerTaskBarReceiver::COSXServerTaskBarReceiver( + const CBufferedLogOutputter*) +{ + // add ourself to the task bar + ARCH->addReceiver(this); +} + +COSXServerTaskBarReceiver::~COSXServerTaskBarReceiver() +{ + ARCH->removeReceiver(this); +} + +void +COSXServerTaskBarReceiver::showStatus() +{ + // do nothing +} + +void +COSXServerTaskBarReceiver::runMenu(int, int) +{ + // do nothing +} + +void +COSXServerTaskBarReceiver::primaryAction() +{ + // do nothing +} + +const IArchTaskBarReceiver::Icon +COSXServerTaskBarReceiver::getIcon() const +{ + return NULL; +} + +IArchTaskBarReceiver* +createTaskBarReceiver(const CBufferedLogOutputter* logBuffer) +{ + return new COSXServerTaskBarReceiver(logBuffer); +} diff --git a/src/cmd/synergyp/COSXPortableTaskBarReceiver.h b/src/cmd/synergyp/COSXPortableTaskBarReceiver.h new file mode 100644 index 00000000..78d76630 --- /dev/null +++ b/src/cmd/synergyp/COSXPortableTaskBarReceiver.h @@ -0,0 +1,38 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 "CPortableTaskBarReceiver.h" + +class CBufferedLogOutputter; + +//! Implementation of CPortableTaskBarReceiver for OS X +class COSXServerTaskBarReceiver : public CPortableTaskBarReceiver { +public: + COSXServerTaskBarReceiver(const CBufferedLogOutputter*); + virtual ~COSXServerTaskBarReceiver(); + + // IArchTaskBarReceiver overrides + virtual void showStatus(); + virtual void runMenu(int x, int y); + virtual void primaryAction(); + virtual const Icon getIcon() const; +}; + +#endif diff --git a/src/cmd/synergyp/CXWindowsPortableTaskBarReceiver.cpp b/src/cmd/synergyp/CXWindowsPortableTaskBarReceiver.cpp new file mode 100644 index 00000000..598555b9 --- /dev/null +++ b/src/cmd/synergyp/CXWindowsPortableTaskBarReceiver.cpp @@ -0,0 +1,66 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 "CXWindowsServerTaskBarReceiver.h" +#include "CArch.h" + +// +// CXWindowsServerTaskBarReceiver +// + +CXWindowsServerTaskBarReceiver::CXWindowsServerTaskBarReceiver( + const CBufferedLogOutputter*) +{ + // 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 +} + +const IArchTaskBarReceiver::Icon +CXWindowsServerTaskBarReceiver::getIcon() const +{ + return NULL; +} + +IArchTaskBarReceiver* +createTaskBarReceiver(const CBufferedLogOutputter* logBuffer) +{ + return new CXWindowsServerTaskBarReceiver(logBuffer); +} diff --git a/src/cmd/synergyp/CXWindowsPortableTaskBarReceiver.h b/src/cmd/synergyp/CXWindowsPortableTaskBarReceiver.h new file mode 100644 index 00000000..1780f3d0 --- /dev/null +++ b/src/cmd/synergyp/CXWindowsPortableTaskBarReceiver.h @@ -0,0 +1,38 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 "CPortableTaskBarReceiver.h" + +class CBufferedLogOutputter; + +//! Implementation of CPortableTaskBarReceiver for X Windows +class CXWindowsServerTaskBarReceiver : public CPortableTaskBarReceiver { +public: + CXWindowsServerTaskBarReceiver(const CBufferedLogOutputter*); + virtual ~CXWindowsServerTaskBarReceiver(); + + // IArchTaskBarReceiver overrides + virtual void showStatus(); + virtual void runMenu(int x, int y); + virtual void primaryAction(); + virtual const Icon getIcon() const; +}; + +#endif diff --git a/src/cmd/synergyp/resource.h b/src/cmd/synergyp/resource.h new file mode 100644 index 00000000..1cc1e8b9 --- /dev/null +++ b/src/cmd/synergyp/resource.h @@ -0,0 +1,42 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by synergys.rc +// +#define IDS_FAILED 1 +#define IDS_INIT_FAILED 2 +#define IDS_UNCAUGHT_EXCEPTION 3 +#define IDI_SYNERGY 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_SYNERGY_RELOADSYSTEM 40016 +#define ID_SYNERGY_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/cmd/synergyp/synergyp.cpp b/src/cmd/synergyp/synergyp.cpp new file mode 100644 index 00000000..eacd530c --- /dev/null +++ b/src/cmd/synergyp/synergyp.cpp @@ -0,0 +1,91 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2013 Bolton Software Ltd. + * + * 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 COPYING 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 . + */ + +#define WIN32_LEAN_AND_MEAN + +#include "Windows.h" +#include "CServerApp.h" +#include "CClientApp.h" +#include "CLog.h" +#include "CArch.h" +#include "CEventQueue.h" + +#if WINAPI_MSWINDOWS +#include "CMSWindowsPortableTaskBarReceiver.h" +#elif WINAPI_XWINDOWS +#include "CXWindowsPortableTaskBarReceiver.h" +#elif WINAPI_CARBON +#include "COSXPortableTaskBarReceiver.h" +#else +#error Platform not supported. +#endif + +INT WINAPI +WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) +{ +#if SYSAPI_WIN32 + // record window instance for tray icon, etc + CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); +#endif + + CArch arch; + arch.init(); + + CLog log; + CEventQueue events; + + CLOG->insert(new CMesssageBoxLogOutputter()); + + int argc = __argc; + char** argv = __argv; + + bool server = false, client = false; + for (int i = 0; i < argc; i++) { + if (std::string(argv[i]) == "--server") { + server = true; + } + else if (std::string(argv[i]) == "--client") { + client = true; + } + } + + if (!server && !client) { + MessageBox(NULL, + "Either the --server argument or the --client argument must be provided.", + "Server or client?", MB_OK); + return 1; + } + + if (argc <= 2) { + MessageBox(NULL, + "No additional arguments were provided. Append the --help argument for help.\n\n" + "Hint: Create a shortcut and append the \"Target\" field with the arguments.", + "No additional arguments", MB_OK); + return 1; + } + + if (server) { + CServerApp app(createTaskBarReceiver); + return app.run(argc, argv); + } + else if (client) { + CClientApp app(createTaskBarReceiver); + return app.run(argc, argv); + } + + return 0; +} diff --git a/src/cmd/synergyp/synergyp.ico b/src/cmd/synergyp/synergyp.ico new file mode 100644 index 00000000..fc2e4146 Binary files /dev/null and b/src/cmd/synergyp/synergyp.ico differ diff --git a/src/cmd/synergyp/synergyp.rc b/src/cmd/synergyp/synergyp.rc new file mode 100644 index 00000000..ecc941b3 --- /dev/null +++ b/src/cmd/synergyp/synergyp.rc @@ -0,0 +1,134 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include \r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SYNERGY ICON "synergyp.ico" +IDI_TASKBAR_NOT_RUNNING ICON "tb_idle.ico" +IDI_TASKBAR_NOT_WORKING ICON "tb_error.ico" +IDI_TASKBAR_NOT_CONNECTED ICON "tb_wait.ico" +IDI_TASKBAR_CONNECTED ICON "tb_run.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_TASKBAR MENU +BEGIN + POPUP "Synergy" + 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", ID_SYNERGY_RESETSERVER + MENUITEM SEPARATOR + MENUITEM "Quit", IDC_TASKBAR_QUIT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_TASKBAR_STATUS DIALOG 0, 0, 145, 60 +STYLE DS_SETFONT | 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 + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_FAILED "Synergy is about to quit with errors or warnings. Please check the log then click OK." + IDS_INIT_FAILED "Synergy failed to initialize: %{1}" + IDS_UNCAUGHT_EXCEPTION "Uncaught exception: %{1}" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/cmd/synergyp/tb_error.ico b/src/cmd/synergyp/tb_error.ico new file mode 100644 index 00000000..746a87c9 Binary files /dev/null and b/src/cmd/synergyp/tb_error.ico differ diff --git a/src/cmd/synergyp/tb_idle.ico b/src/cmd/synergyp/tb_idle.ico new file mode 100644 index 00000000..4e13a264 Binary files /dev/null and b/src/cmd/synergyp/tb_idle.ico differ diff --git a/src/cmd/synergyp/tb_run.ico b/src/cmd/synergyp/tb_run.ico new file mode 100644 index 00000000..88e160cb Binary files /dev/null and b/src/cmd/synergyp/tb_run.ico differ diff --git a/src/cmd/synergyp/tb_wait.ico b/src/cmd/synergyp/tb_wait.ico new file mode 100644 index 00000000..257be0a1 Binary files /dev/null and b/src/cmd/synergyp/tb_wait.ico differ diff --git a/src/cmd/synergys/synergys.cpp b/src/cmd/synergys/synergys.cpp index 1756e814..1fba56ba 100644 --- a/src/cmd/synergys/synergys.cpp +++ b/src/cmd/synergys/synergys.cpp @@ -17,6 +17,9 @@ */ #include "CServerApp.h" +#include "CLog.h" +#include "CArch.h" +#include "CEventQueue.h" #if WINAPI_MSWINDOWS #include "CMSWindowsServerTaskBarReceiver.h" @@ -31,6 +34,17 @@ int main(int argc, char** argv) { +#if SYSAPI_WIN32 + // record window instance for tray icon, etc + CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); +#endif + + CArch arch; + arch.init(); + + CLog log; + CEventQueue events; + CServerApp app(createTaskBarReceiver); return app.run(argc, argv); } diff --git a/src/lib/base/CLog.cpp b/src/lib/base/CLog.cpp index 3b097c3c..d58587c3 100644 --- a/src/lib/base/CLog.cpp +++ b/src/lib/base/CLog.cpp @@ -115,6 +115,9 @@ CLog::getFilterName() const const char* CLog::getFilterName(int level) const { + if (level < 0) { + return "Message"; + } return g_priority[level]; } diff --git a/src/lib/base/LogOutputters.cpp b/src/lib/base/LogOutputters.cpp index 2bb03622..e88b12ef 100644 --- a/src/lib/base/LogOutputters.cpp +++ b/src/lib/base/LogOutputters.cpp @@ -263,3 +263,47 @@ CFileLogOutputter::close() {} void CFileLogOutputter::show(bool showIfEmpty) {} + +// +// CMesssageBoxLogOutputter +// + +CMesssageBoxLogOutputter::CMesssageBoxLogOutputter() +{ + // do nothing +} + +CMesssageBoxLogOutputter::~CMesssageBoxLogOutputter() +{ + // do nothing +} + +void +CMesssageBoxLogOutputter::open(const char* title) +{ + // do nothing +} + +void +CMesssageBoxLogOutputter::close() +{ + // do nothing +} + +void +CMesssageBoxLogOutputter::show(bool showIfEmpty) +{ + // do nothing +} + +bool +CMesssageBoxLogOutputter::write(ELevel level, const char* msg) +{ + // don't spam user with messages. + if (level > kERROR) { + return true; + } + + MessageBox(NULL, msg, CLOG->getFilterName(level), MB_OK); + return true; +} diff --git a/src/lib/base/LogOutputters.h b/src/lib/base/LogOutputters.h index f60fa5ae..d7a08189 100644 --- a/src/lib/base/LogOutputters.h +++ b/src/lib/base/LogOutputters.h @@ -153,4 +153,20 @@ private: CBuffer m_buffer; }; +//! Write log to message box +/*! +The level for each message is ignored. +*/ +class CMesssageBoxLogOutputter : public ILogOutputter { +public: + CMesssageBoxLogOutputter(); + virtual ~CMesssageBoxLogOutputter(); + + // ILogOutputter overrides + virtual void open(const char* title); + virtual void close(); + virtual void show(bool showIfEmpty); + virtual bool write(ELevel level, const char* message); +}; + #endif diff --git a/src/lib/synergy/CApp.cpp b/src/lib/synergy/CApp.cpp index a02e47f0..0c3747b3 100644 --- a/src/lib/synergy/CApp.cpp +++ b/src/lib/synergy/CApp.cpp @@ -153,6 +153,14 @@ CApp::parseArg(const int& argc, const char* const* argv, int& i) argsBase().m_enableIpc = true; } + else if (isArg(i, argc, argv, NULL, "--server")) { + // HACK: stop error happening when using portable (synergyp) + } + + else if (isArg(i, argc, argv, NULL, "--client")) { + // HACK: stop error happening when using portable (synergyp) + } + #if VNC_SUPPORT else if (isArg(i, argc, argv, NULL, "--vnc")) { argsBase().m_enableVnc = true; @@ -244,18 +252,7 @@ CApp::version() int CApp::run(int argc, char** argv) -{ -#if SYSAPI_WIN32 - // record window instance for tray icon, etc - CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); -#endif - - CArch arch; - arch.init(); - - CLog log; - CEventQueue events; - +{ #if MAC_OS_X_VERSION_10_7 // dock hide only supported on lion :( ProcessSerialNumber psn = { 0, kCurrentProcess }; diff --git a/src/lib/synergy/CClientApp.cpp b/src/lib/synergy/CClientApp.cpp index 1ce392ee..f42c0760 100644 --- a/src/lib/synergy/CClientApp.cpp +++ b/src/lib/synergy/CClientApp.cpp @@ -205,9 +205,9 @@ CClientApp::help() "must be the address or hostname of the server. The port overrides the\n" "default port, %d.\n", args().m_pname, kDefaultPort - ); + ); - std::cout << buffer << std::endl; + LOG((CLOG_PRINT "%s", buffer)); } const char* diff --git a/src/lib/synergy/CMakeLists.txt b/src/lib/synergy/CMakeLists.txt index 637541ab..a120ca49 100644 --- a/src/lib/synergy/CMakeLists.txt +++ b/src/lib/synergy/CMakeLists.txt @@ -17,6 +17,7 @@ set(inc CClientTaskBarReceiver.h CServerTaskBarReceiver.h + CPortableTaskBarReceiver.h CApp.h CClientApp.h CServerApp.h @@ -54,6 +55,7 @@ set(inc set(src CClientTaskBarReceiver.cpp CServerTaskBarReceiver.cpp + CPortableTaskBarReceiver.cpp CApp.cpp CClientApp.cpp CServerApp.cpp diff --git a/src/lib/synergy/CPortableTaskBarReceiver.cpp b/src/lib/synergy/CPortableTaskBarReceiver.cpp new file mode 100644 index 00000000..1a7e2026 --- /dev/null +++ b/src/lib/synergy/CPortableTaskBarReceiver.cpp @@ -0,0 +1,141 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 "CPortableTaskBarReceiver.h" +#include "CLock.h" +#include "CStringUtil.h" +#include "IEventQueue.h" +#include "CArch.h" +#include "Version.h" + +// +// CPortableTaskBarReceiver +// + +CPortableTaskBarReceiver::CPortableTaskBarReceiver() : + m_state(kNotRunning) +{ + // do nothing +} + +CPortableTaskBarReceiver::~CPortableTaskBarReceiver() +{ + // do nothing +} + +void +CPortableTaskBarReceiver::updateStatus(INode* node, const CString& errorMsg) +{ + { + // update our status + m_errorMessage = errorMsg; + if (node == NULL) { + if (m_errorMessage.empty()) { + m_state = kNotRunning; + } + else { + m_state = kNotWorking; + } + } + else { + m_state = kNotConnected; + } + + // let subclasses have a go + onStatusChanged(node); + } + + // tell task bar + ARCH->updateReceiver(this); +} + +CPortableTaskBarReceiver::EState +CPortableTaskBarReceiver::getStatus() const +{ + return m_state; +} + +const CString& +CPortableTaskBarReceiver::getErrorMessage() const +{ + return m_errorMessage; +} + +void +CPortableTaskBarReceiver::quit() +{ + EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); +} + +void +CPortableTaskBarReceiver::onStatusChanged(INode*) +{ + // do nothing +} + +void +CPortableTaskBarReceiver::lock() const +{ + // do nothing +} + +void +CPortableTaskBarReceiver::unlock() const +{ + // do nothing +} + +std::string +CPortableTaskBarReceiver::getToolTip() const +{ + switch (m_state) { + case kNotRunning: + return CStringUtil::print("%s: Not running", kAppVersion); + + case kNotWorking: + return CStringUtil::print("%s: %s", + kAppVersion, m_errorMessage.c_str()); + + case kNotConnected: + return CStringUtil::print("%s: Unknown", kAppVersion); + + default: + return ""; + } +} + +CEvent::Type +CPortableTaskBarReceiver::getReloadConfigEvent() +{ + // do nothing + return NULL; +} + +CEvent::Type +CPortableTaskBarReceiver::getForceReconnectEvent() +{ + // do nothing + return NULL; +} + +CEvent::Type +CPortableTaskBarReceiver::getResetServerEvent() +{ + // do nothing + return NULL; +} diff --git a/src/lib/synergy/CPortableTaskBarReceiver.h b/src/lib/synergy/CPortableTaskBarReceiver.h new file mode 100644 index 00000000..7c0d79a4 --- /dev/null +++ b/src/lib/synergy/CPortableTaskBarReceiver.h @@ -0,0 +1,96 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012 Bolton Software 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 COPYING 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 "CString.h" +#include "IArchTaskBarReceiver.h" +#include "stdvector.h" +#include "CEvent.h" +#include "INode.h" +#include "LogOutputters.h" + +//! Implementation of IArchTaskBarReceiver for the synergy server +class CPortableTaskBarReceiver : public IArchTaskBarReceiver { +public: + CPortableTaskBarReceiver(); + virtual ~CPortableTaskBarReceiver(); + + //! @name manipulators + //@{ + + //! Update status + /*! + Determine the status and query required information from the server. + */ + void updateStatus(INode*, const CString& 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 const Icon getIcon() const = 0; + virtual std::string getToolTip() const; + +protected: + typedef std::vector CClients; + enum EState { + kNotRunning, + kNotWorking, + kNotConnected, + kConnected, + kMaxState + }; + + //! Get status + EState getStatus() const; + + //! Get error message + const CString& 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(INode* node); + +protected: + CEvent::Type getReloadConfigEvent(); + CEvent::Type getForceReconnectEvent(); + CEvent::Type getResetServerEvent(); + +private: + EState m_state; + CString m_errorMessage; + + CString m_server; + CClients m_clients; +}; + +IArchTaskBarReceiver* createTaskBarReceiver(const CBufferedLogOutputter* logBuffer); diff --git a/src/lib/synergy/CServerApp.cpp b/src/lib/synergy/CServerApp.cpp index d4b3568d..29128927 100644 --- a/src/lib/synergy/CServerApp.cpp +++ b/src/lib/synergy/CServerApp.cpp @@ -198,7 +198,7 @@ CServerApp::help() ARCH->concatPath(ARCH->getSystemDirectory(), SYS_CONFIG_NAME).c_str() ); - std::cout << buffer << std::endl; + LOG((CLOG_PRINT "%s", buffer)); } void