• Main Page
  • Classes
  • Files
  • File List

CMSWindowsServerTaskBarReceiver.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2003 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CMSWindowsServerTaskBarReceiver.h"
00020 #include "CServer.h"
00021 #include "CMSWindowsClipboard.h"
00022 #include "IEventQueue.h"
00023 #include "LogOutputters.h"
00024 #include "BasicTypes.h"
00025 #include "CArch.h"
00026 #include "CArchTaskBarWindows.h"
00027 #include "resource.h"
00028 #include "CArchMiscWindows.h"
00029 #include "CMSWindowsScreen.h"
00030 
00031 //
00032 // CMSWindowsServerTaskBarReceiver
00033 //
00034 
00035 const UINT CMSWindowsServerTaskBarReceiver::s_stateToIconID[kMaxState] =
00036 {
00037     IDI_TASKBAR_NOT_RUNNING,
00038     IDI_TASKBAR_NOT_WORKING,
00039     IDI_TASKBAR_NOT_CONNECTED,
00040     IDI_TASKBAR_CONNECTED
00041 };
00042 
00043 CMSWindowsServerTaskBarReceiver::CMSWindowsServerTaskBarReceiver(
00044                 HINSTANCE appInstance, const CBufferedLogOutputter* logBuffer) :
00045     CServerTaskBarReceiver(),
00046     m_appInstance(appInstance),
00047     m_window(NULL),
00048     m_logBuffer(logBuffer)
00049 {
00050     for (UInt32 i = 0; i < kMaxState; ++i) {
00051         m_icon[i] = loadIcon(s_stateToIconID[i]);
00052     }
00053     m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR));
00054 
00055     // don't create the window yet.  we'll create it on demand.  this
00056     // has the side benefit of being created in the thread used for
00057     // the task bar.  that's good because it means the existence of
00058     // the window won't prevent changing the main thread's desktop.
00059 
00060     // add ourself to the task bar
00061     ARCH->addReceiver(this);
00062 }
00063 
00064 void
00065 CMSWindowsServerTaskBarReceiver::cleanup()
00066 {
00067     ARCH->removeReceiver(this);
00068     for (UInt32 i = 0; i < kMaxState; ++i) {
00069         deleteIcon(m_icon[i]);
00070     }
00071     DestroyMenu(m_menu);
00072     destroyWindow();
00073 }
00074 
00075 CMSWindowsServerTaskBarReceiver::~CMSWindowsServerTaskBarReceiver()
00076 {
00077     cleanup();
00078 }
00079 
00080 void
00081 CMSWindowsServerTaskBarReceiver::showStatus()
00082 {
00083     // create the window
00084     createWindow();
00085 
00086     // lock self while getting status
00087     lock();
00088 
00089     // get the current status
00090     std::string status = getToolTip();
00091 
00092     // get the connect clients, if any
00093     const CClients& clients = getClients();
00094 
00095     // done getting status
00096     unlock();
00097 
00098     // update dialog
00099     HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS);
00100     SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str());
00101     child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_CLIENTS);
00102     SendMessage(child, LB_RESETCONTENT, 0, 0);
00103     for (CClients::const_iterator index = clients.begin();
00104                             index != clients.end(); ) {
00105         const char* client = index->c_str();
00106         if (++index == clients.end()) {
00107             SendMessage(child, LB_ADDSTRING, 0, (LPARAM)client);
00108         }
00109         else {
00110             SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)client);
00111         }
00112     }
00113 
00114     if (!IsWindowVisible(m_window)) {
00115         // position it by the mouse
00116         POINT cursorPos;
00117         GetCursorPos(&cursorPos);
00118         RECT windowRect;
00119         GetWindowRect(m_window, &windowRect);
00120         int  x = cursorPos.x;
00121         int  y = cursorPos.y;
00122         int fw = GetSystemMetrics(SM_CXDLGFRAME);
00123         int fh = GetSystemMetrics(SM_CYDLGFRAME);
00124         int ww = windowRect.right  - windowRect.left;
00125         int wh = windowRect.bottom - windowRect.top;
00126         int sw = GetSystemMetrics(SM_CXFULLSCREEN);
00127         int sh = GetSystemMetrics(SM_CYFULLSCREEN);
00128         if (fw < 1) {
00129             fw = 1;
00130         }
00131         if (fh < 1) {
00132             fh = 1;
00133         }
00134         if (x + ww - fw > sw) {
00135             x -= ww - fw;
00136         }
00137         else {
00138             x -= fw;
00139         }
00140         if (x < 0) {
00141             x = 0;
00142         }
00143         if (y + wh - fh > sh) {
00144             y -= wh - fh;
00145         }
00146         else {
00147             y -= fh;
00148         }
00149         if (y < 0) {
00150             y = 0;
00151         }
00152         SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh,
00153                             SWP_SHOWWINDOW);
00154     }
00155 }
00156 
00157 void
00158 CMSWindowsServerTaskBarReceiver::runMenu(int x, int y)
00159 {
00160     // do popup menu.  we need a window to pass to TrackPopupMenu().
00161     // the SetForegroundWindow() and SendMessage() calls around
00162     // TrackPopupMenu() are to get the menu to be dismissed when
00163     // another window gets activated and are just one of those
00164     // win32 weirdnesses.
00165     createWindow();
00166     SetForegroundWindow(m_window);
00167     HMENU menu = GetSubMenu(m_menu, 0);
00168     SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE);
00169     HMENU logLevelMenu = GetSubMenu(menu, 3);
00170     CheckMenuRadioItem(logLevelMenu, 0, 6,
00171                             CLOG->getFilter() - kERROR, MF_BYPOSITION);
00172     int n = TrackPopupMenu(menu,
00173                             TPM_NONOTIFY |
00174                             TPM_RETURNCMD |
00175                             TPM_LEFTBUTTON |
00176                             TPM_RIGHTBUTTON,
00177                             x, y, 0, m_window, NULL);
00178     SendMessage(m_window, WM_NULL, 0, 0);
00179 
00180     // perform the requested operation
00181     switch (n) {
00182     case IDC_TASKBAR_STATUS:
00183         showStatus();
00184         break;
00185 
00186     case IDC_TASKBAR_LOG:
00187         copyLog();
00188         break;
00189 
00190     case IDC_TASKBAR_SHOW_LOG:
00191         ARCH->showConsole(true);
00192         break;
00193 
00194     case IDC_RELOAD_CONFIG:
00195         EVENTQUEUE->addEvent(CEvent(getReloadConfigEvent(),
00196                             IEventQueue::getSystemTarget()));
00197         break;
00198 
00199     case IDC_FORCE_RECONNECT:
00200         EVENTQUEUE->addEvent(CEvent(getForceReconnectEvent(),
00201                             IEventQueue::getSystemTarget()));
00202         break;
00203 
00204     case ID_SYNERGY_RESETSERVER:
00205         EVENTQUEUE->addEvent(CEvent(getResetServerEvent(),
00206                             IEventQueue::getSystemTarget()));
00207         break;
00208 
00209     case IDC_TASKBAR_LOG_LEVEL_ERROR:
00210         CLOG->setFilter(kERROR);
00211         break;
00212 
00213     case IDC_TASKBAR_LOG_LEVEL_WARNING:
00214         CLOG->setFilter(kWARNING);
00215         break;
00216 
00217     case IDC_TASKBAR_LOG_LEVEL_NOTE:
00218         CLOG->setFilter(kNOTE);
00219         break;
00220 
00221     case IDC_TASKBAR_LOG_LEVEL_INFO:
00222         CLOG->setFilter(kINFO);
00223         break;
00224 
00225     case IDC_TASKBAR_LOG_LEVEL_DEBUG:
00226         CLOG->setFilter(kDEBUG);
00227         break;
00228 
00229     case IDC_TASKBAR_LOG_LEVEL_DEBUG1:
00230         CLOG->setFilter(kDEBUG1);
00231         break;
00232 
00233     case IDC_TASKBAR_LOG_LEVEL_DEBUG2:
00234         CLOG->setFilter(kDEBUG2);
00235         break;
00236 
00237     case IDC_TASKBAR_QUIT:
00238         quit();
00239         break;
00240     }
00241 }
00242 
00243 void
00244 CMSWindowsServerTaskBarReceiver::primaryAction()
00245 {
00246     showStatus();
00247 }
00248 
00249 const IArchTaskBarReceiver::Icon
00250 CMSWindowsServerTaskBarReceiver::getIcon() const
00251 {
00252     return reinterpret_cast<Icon>(m_icon[getStatus()]);
00253 }
00254 
00255 void
00256 CMSWindowsServerTaskBarReceiver::copyLog() const
00257 {
00258     if (m_logBuffer != NULL) {
00259         // collect log buffer
00260         CString data;
00261         for (CBufferedLogOutputter::const_iterator index = m_logBuffer->begin();
00262                                 index != m_logBuffer->end(); ++index) {
00263             data += *index;
00264             data += "\n";
00265         }
00266 
00267         // copy log to clipboard
00268         if (!data.empty()) {
00269             CMSWindowsClipboard clipboard(m_window);
00270             clipboard.open(0);
00271             clipboard.emptyUnowned();
00272             clipboard.add(IClipboard::kText, data);
00273             clipboard.close();
00274         }
00275     }
00276 }
00277 
00278 void
00279 CMSWindowsServerTaskBarReceiver::onStatusChanged()
00280 {
00281     if (IsWindowVisible(m_window)) {
00282         showStatus();
00283     }
00284 }
00285 
00286 HICON
00287 CMSWindowsServerTaskBarReceiver::loadIcon(UINT id)
00288 {
00289     HANDLE icon = LoadImage(m_appInstance,
00290                             MAKEINTRESOURCE(id),
00291                             IMAGE_ICON,
00292                             0, 0,
00293                             LR_DEFAULTCOLOR);
00294     return reinterpret_cast<HICON>(icon);
00295 }
00296 
00297 void
00298 CMSWindowsServerTaskBarReceiver::deleteIcon(HICON icon)
00299 {
00300     if (icon != NULL) {
00301         DestroyIcon(icon);
00302     }
00303 }
00304 
00305 void
00306 CMSWindowsServerTaskBarReceiver::createWindow()
00307 {
00308     // ignore if already created
00309     if (m_window != NULL) {
00310         return;
00311     }
00312 
00313     // get the status dialog
00314     m_window = CreateDialogParam(m_appInstance,
00315                             MAKEINTRESOURCE(IDD_TASKBAR_STATUS),
00316                             NULL,
00317                             (DLGPROC)&CMSWindowsServerTaskBarReceiver::staticDlgProc,
00318                             reinterpret_cast<LPARAM>(
00319                                 reinterpret_cast<void*>(this)));
00320 
00321     // window should appear on top of everything, including (especially)
00322     // the task bar.
00323     LONG_PTR style = GetWindowLongPtr(m_window, GWL_EXSTYLE);
00324     style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
00325     SetWindowLongPtr(m_window, GWL_EXSTYLE, style);
00326 
00327     // tell the task bar about this dialog
00328     CArchTaskBarWindows::addDialog(m_window);
00329 }
00330 
00331 void
00332 CMSWindowsServerTaskBarReceiver::destroyWindow()
00333 {
00334     if (m_window != NULL) {
00335         CArchTaskBarWindows::removeDialog(m_window);
00336         DestroyWindow(m_window);
00337         m_window = NULL;
00338     }
00339 }
00340 
00341 BOOL
00342 CMSWindowsServerTaskBarReceiver::dlgProc(HWND hwnd,
00343                             UINT msg, WPARAM wParam, LPARAM)
00344 {
00345     switch (msg) {
00346     case WM_INITDIALOG:
00347         // use default focus
00348         return TRUE;
00349 
00350     case WM_ACTIVATE:
00351         // hide when another window is activated
00352         if (LOWORD(wParam) == WA_INACTIVE) {
00353             ShowWindow(hwnd, SW_HIDE);
00354         }
00355         break;
00356     }
00357     return FALSE;
00358 }
00359 
00360 BOOL CALLBACK
00361 CMSWindowsServerTaskBarReceiver::staticDlgProc(HWND hwnd,
00362                             UINT msg, WPARAM wParam, LPARAM lParam)
00363 {
00364     // if msg is WM_INITDIALOG, extract the CMSWindowsServerTaskBarReceiver*
00365     // and put it in the extra window data then forward the call.
00366     CMSWindowsServerTaskBarReceiver* self = NULL;
00367     if (msg == WM_INITDIALOG) {
00368         self = reinterpret_cast<CMSWindowsServerTaskBarReceiver*>(
00369                             reinterpret_cast<void*>(lParam));
00370         SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
00371     }
00372     else {
00373         // get the extra window data and forward the call
00374         LONG data = (LONG)GetWindowLongPtr(hwnd, GWLP_USERDATA);
00375         if (data != 0) {
00376             self = reinterpret_cast<CMSWindowsServerTaskBarReceiver*>(
00377                             reinterpret_cast<void*>(data));
00378         }
00379     }
00380 
00381     // forward the message
00382     if (self != NULL) {
00383         return self->dlgProc(hwnd, msg, wParam, lParam);
00384     }
00385     else {
00386         return (msg == WM_INITDIALOG) ? TRUE : FALSE;
00387     }
00388 }
00389 
00390 IArchTaskBarReceiver*
00391 createTaskBarReceiver(const CBufferedLogOutputter* logBuffer)
00392 {
00393     CArchMiscWindows::setIcons(
00394         (HICON)LoadImage(CArchMiscWindows::instanceWin32(),
00395         MAKEINTRESOURCE(IDI_SYNERGY),
00396         IMAGE_ICON,
00397         32, 32, LR_SHARED),
00398         (HICON)LoadImage(CArchMiscWindows::instanceWin32(),
00399         MAKEINTRESOURCE(IDI_SYNERGY),
00400         IMAGE_ICON,
00401         16, 16, LR_SHARED));
00402 
00403     return new CMSWindowsServerTaskBarReceiver(
00404         CMSWindowsScreen::getWindowInstance(), logBuffer);
00405 }

Generated on Sat May 18 2013 00:00:04 for Synergy by  doxygen 1.7.1