Changeset 2755 for trunk


Ignore:
Timestamp:
Jul 31, 2006, 5:21:38 AM (19 years ago)
Author:
bird
Message:

bedtime

Location:
trunk/synergy
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/synergy/Makefile.kmk

    r2753 r2755  
    163163        lib/platform/CPMEventQueueBuffer.cpp \
    164164        lib/platform/CPMScreenSaver.cpp \
     165        lib/platform/CPMScreen.cpp \
     166        lib/platform/CPMKeyState.cpp \
    165167        lib/platform/CPMUtil.cpp
    166168# todo:
    167 #       lib/platform/CPMKeyState.cpp \
    168 #       lib/platform/CPMScreen.cpp
    169169platform_SOURCES.nt = \
    170170        lib/platform/CMSWindowsClipboard.cpp \
     
    235235
    236236
     237#
     238# The hook DLLs.
     239#
     240DLLS = synrgyhk
     241
     242synrgyhk_DEFS = SYNRGYHK_EXPORTS
     243synrgyhk_ASTOOL.os2 = NASM
     244synrgyhk_ASFLAGS.os2 = -f obj
     245synrgyhk_SOURCES.nt = \
     246        lib/platform/CSynergyHook.cpp
     247synrgyhk_SOURCES.os2 = \
     248        lib/platform/CPMSynergyHook.cpp \
     249        lib/platform/CPMSynergyHookData.asm \
     250        lib/platform/CPMSynergyHook.def
     251
    237252include $(PATH_KBUILD)/footer.kmk
  • trunk/synergy/lib/platform/CPMEventQueueBuffer.cpp

    r2752 r2755  
    33 * Copyright (C) 2004 Chris Schoeneman
    44 * Copyright (C) 2006 Knut St. Osmundsen
    5  * 
     5 *
    66 * This package is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU General Public License
    88 * found in the file COPYING that should have accompanied this file.
    9  * 
     9 *
    1010 * This package is distributed in the hope that it will be useful,
    1111 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    5959CPMEventQueueBuffer::waitForEvent(double timeout)
    6060{
    61         // check if messages are available first. 
     61        // check if messages are available first.
    6262    ULONG fStatus = WinQueryQueueStatus(HWND_DESKTOP);
    6363    if (!fStatus) {
    6464        // convert timeout and wait.
    65         ULONG ulPMTimeout = timeout < 0.0 
     65        ULONG ulPMTimeout = timeout < 0.0
    6666                          ? SEM_INDEFINITE_WAIT
    6767                          : (ULONG)(1000.0 * timeout);
     
    8585                return kSystem;
    8686        }
    87        
     87
    8888    if (m_event.msg == m_userEvent) {
    8989                dataID = (UInt32)(uintptr_t)m_event.mp1;
    9090                return kUser;
    9191        }
    92    
     92
    9393    event = CEvent(CEvent::kSystem, IEventQueue::getSystemTarget(), &m_event);
    9494    return kSystem;
     
    105105{
    106106    ULONG fStatus = WinQueryQueueStatus(HWND_DESKTOP);
    107         return fStatus != 0; 
     107        return fStatus != 0;
    108108}
    109109
     
    120120}
    121121
     122/*
     123 * Local Variables:
     124 *  mode: c
     125 *  c-file-style: "k&r"
     126 *  c-basic-offset: 4
     127 *  tab-width: 4
     128 *  indent-tabs-mode: t
     129 * End:
     130 */
     131
  • trunk/synergy/lib/platform/CPMKeyState.cpp

    r2752 r2755  
    33 * Copyright (C) 2003 Chris Schoeneman
    44 * Copyright (C) 2006 Knut St. Osmundsen
    5  * 
     5 *
    66 * This package is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU General Public License
    88 * found in the file COPYING that should have accompanied this file.
    9  * 
     9 *
    1010 * This package is distributed in the hope that it will be useful,
    1111 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    3030{
    3131        /* 0x000 */ kKeyNone,           // reserved
    32         /* 0x001 */ kKeyNone,           // VK_BUTTON1              VK_BUTTON1          0x0001         
    33         /* 0x002 */ kKeyNone,           // VK_BUTTON2              VK_BUTTON2          0x0002         
    34         /* 0x003 */ kKeyNone,           // VK_BUTTON3              VK_BUTTON3          0x0003         
    35         /* 0x004 */ kKeyBreak,          // VK_BREAK                VK_BREAK            0x0004         
     32        /* 0x001 */ kKeyNone,           // VK_BUTTON1
     33        /* 0x002 */ kKeyNone,           // VK_BUTTON2
     34        /* 0x003 */ kKeyNone,           // VK_BUTTON3
     35        /* 0x004 */ kKeyBreak,          // VK_BREAK
    3636        /* 0x005 */ kKeyBackSpace,      // VK_BACKSPACE
    3737        /* 0x006 */ kKeyTab,            // VK_TAB
     
    3939        /* 0x008 */ kKeyReturn,         // VK_NEWLINE
    4040        /* 0x009 */ kKeyShift_L,        // VK_SHIFT
    41         /* 0x00a */ kKeyControl_L,      // VK_CTRL             0x000a         
    42         /* 0x00b */ kKeyAlt_L,          // VK_ALT              0x000b         
    43         /* 0x00c */ kKeyAltGr,          // VK_ALTGRAF          0x000c         
    44         /* 0x00d */ kKeyPause,          // VK_PAUSE            0x000d         
    45         /* 0x00e */ kKeyCapsLock,       // VK_CAPSLOCK         0x000e         
    46         /* 0x00f */ kKeyEscape,         // VK_ESC              0x000f         
    47         /* 0x010 */ kKeyNone,           // VK_SPACE            0x0010         
    48         /* 0x011 */ kKeyPageUp,         // VK_PAGEUP           0x0011         
    49         /* 0x012 */ kKeyPageDown,       // VK_PAGEDOWN         0x0012         
    50         /* 0x013 */ kKeyEnd,            // VK_END              0x0013         
    51         /* 0x014 */ kKeyHome,           // VK_HOME             0x0014         
    52         /* 0x015 */ kKeyLeft,           // VK_LEFT             0x0015         
    53         /* 0x016 */ kKeyUp,                     // VK_UP               0x0016         
    54         /* 0x017 */ kKeyRight,          // VK_RIGHT            0x0017         
    55         /* 0x018 */ kKeyDown,           // VK_DOWN             0x0018         
    56         /* 0x019 */ kKeyNone,           // VK_PRINTSCRN            0x0019     
    57         /* 0x01a */ kKeyInsert,         // VK_INSERT           0x001a         
    58         /* 0x01b */ kKeyDelete,         // VK_DELETE           0x001b         
    59         /* 0x01c */ kKeyScrollLock,     // VK_SCRLLOCK         0x001c         
    60         /* 0x01d */ kKeyNumLock,        // VK_NUMLOCK          0x001d         
    61         /* 0x01e */ kKeyKP_Enter,       // VK_ENTER            0x001e         
    62         /* 0x01f */ kKeySysReq,         // VK_SYSRQ            0x001f         
    63         /* 0x020 */ kKeyF1,                     // VK_F1               0x0020         
    64         /* 0x021 */ kKeyF2,                     // VK_F2               0x0021         
    65         /* 0x022 */ kKeyF3,                     // VK_F3               0x0022         
    66         /* 0x023 */ kKeyF4,                     // VK_F4               0x0023         
    67         /* 0x024 */ kKeyF5,                     // VK_F5               0x0024         
    68         /* 0x025 */ kKeyF6,                     // VK_F6               0x0025         
    69         /* 0x026 */ kKeyF7,                     // VK_F7               0x0026         
    70         /* 0x027 */ kKeyF8,                     // VK_F8               0x0027         
    71         /* 0x028 */ kKeyF9,                     // VK_F9               0x0028         
    72         /* 0x029 */ kKeyF10,            // VK_F10              0x0029         
    73         /* 0x02a */ kKeyF11,            // VK_F11              0x002a         
    74         /* 0x02b */ kKeyF12,            // VK_F12              0x002b         
    75         /* 0x02c */ kKeyF13,            // VK_F13              0x002c         
    76         /* 0x02d */ kKeyF14,            // VK_F14              0x002d         
    77         /* 0x02e */ kKeyF15,            // VK_F15              0x002e         
    78         /* 0x02f */ kKeyF16,            // VK_F16              0x002f         
    79         /* 0x030 */ kKeyF17,            // VK_F17              0x0030         
    80         /* 0x031 */ kKeyF18,            // VK_F18              0x0031         
    81         /* 0x032 */ kKeyF19,            // VK_F19              0x0032         
    82         /* 0x033 */ kKeyF20,            // VK_F20              0x0033         
    83         /* 0x034 */ kKeyF21,            // VK_F21              0x0034         
    84         /* 0x035 */ kKeyF22,            // VK_F22              0x0035         
    85         /* 0x036 */ kKeyF23,            // VK_F23              0x0036         
    86         /* 0x037 */ kKeyF24,            // VK_F24              0x0037         
    87         /* 0x038 */ kKeyNone,           // VK_ENDDRAG          0x0038         
    88         /* 0x039 */ kKeyClear,          // VK_CLEAR            0x0039         
    89         /* 0x03a */ kKeyNone,           // VK_EREOF            0x003a         
    90         /* 0x03b */ kKeyNone,           // VK_PA1              0x003b         
    91         /* 0x03c */ kKeyNone,           // VK_ATTN             0x003c         
    92         /* 0x03d */ kKeyNone,           // VK_CRSEL            0x003d         
    93         /* 0x03e */ kKeyNone,           // VK_EXSEL            0x003e         
    94         /* 0x03f */ kKeyNone,           // VK_COPY             0x003f         
    95         /* 0x040 */ kKeyNone,           // VK_BLK1             0x0040         
    96         /* 0x041 */ kKeyNone            // VK_BLK2             0x0041         
     41        /* 0x00a */ kKeyControl_L,      // VK_CTRL
     42        /* 0x00b */ kKeyAlt_L,          // VK_ALT
     43        /* 0x00c */ kKeyAltGr,          // VK_ALTGRAF
     44        /* 0x00d */ kKeyPause,          // VK_PAUSE
     45        /* 0x00e */ kKeyCapsLock,       // VK_CAPSLOCK
     46        /* 0x00f */ kKeyEscape,         // VK_ESC
     47        /* 0x010 */ kKeyNone,           // VK_SPACE
     48        /* 0x011 */ kKeyPageUp,         // VK_PAGEUP
     49        /* 0x012 */ kKeyPageDown,       // VK_PAGEDOWN
     50        /* 0x013 */ kKeyEnd,            // VK_END
     51        /* 0x014 */ kKeyHome,           // VK_HOME
     52        /* 0x015 */ kKeyLeft,           // VK_LEFT
     53        /* 0x016 */ kKeyUp,                     // VK_UP
     54        /* 0x017 */ kKeyRight,          // VK_RIGHT
     55        /* 0x018 */ kKeyDown,           // VK_DOWN
     56        /* 0x019 */ kKeyNone,           // VK_PRINTSCRN
     57        /* 0x01a */ kKeyInsert,         // VK_INSERT
     58        /* 0x01b */ kKeyDelete,         // VK_DELETE
     59        /* 0x01c */ kKeyScrollLock,     // VK_SCRLLOCK
     60        /* 0x01d */ kKeyNumLock,        // VK_NUMLOCK
     61        /* 0x01e */ kKeyKP_Enter,       // VK_ENTER
     62        /* 0x01f */ kKeySysReq,         // VK_SYSRQ
     63        /* 0x020 */ kKeyF1,                     // VK_F1
     64        /* 0x021 */ kKeyF2,                     // VK_F2
     65        /* 0x022 */ kKeyF3,                     // VK_F3
     66        /* 0x023 */ kKeyF4,                     // VK_F4
     67        /* 0x024 */ kKeyF5,                     // VK_F5
     68        /* 0x025 */ kKeyF6,                     // VK_F6
     69        /* 0x026 */ kKeyF7,                     // VK_F7
     70        /* 0x027 */ kKeyF8,                     // VK_F8
     71        /* 0x028 */ kKeyF9,                     // VK_F9
     72        /* 0x029 */ kKeyF10,            // VK_F10
     73        /* 0x02a */ kKeyF11,            // VK_F11
     74        /* 0x02b */ kKeyF12,            // VK_F12
     75        /* 0x02c */ kKeyF13,            // VK_F13
     76        /* 0x02d */ kKeyF14,            // VK_F14
     77        /* 0x02e */ kKeyF15,            // VK_F15
     78        /* 0x02f */ kKeyF16,            // VK_F16
     79        /* 0x030 */ kKeyF17,            // VK_F17
     80        /* 0x031 */ kKeyF18,            // VK_F18
     81        /* 0x032 */ kKeyF19,            // VK_F19
     82        /* 0x033 */ kKeyF20,            // VK_F20
     83        /* 0x034 */ kKeyF21,            // VK_F21
     84        /* 0x035 */ kKeyF22,            // VK_F22
     85        /* 0x036 */ kKeyF23,            // VK_F23
     86        /* 0x037 */ kKeyF24,            // VK_F24
     87        /* 0x038 */ kKeyNone,           // VK_ENDDRAG
     88        /* 0x039 */ kKeyClear,          // VK_CLEAR
     89        /* 0x03a */ kKeyNone,           // VK_EREOF
     90        /* 0x03b */ kKeyNone,           // VK_PA1
     91        /* 0x03c */ kKeyNone,           // VK_ATTN
     92        /* 0x03d */ kKeyNone,           // VK_CRSEL
     93        /* 0x03e */ kKeyNone,           // VK_EXSEL
     94        /* 0x03f */ kKeyNone,           // VK_COPY
     95        /* 0x040 */ kKeyNone,           // VK_BLK1
     96        /* 0x041 */ kKeyNone            // VK_BLK2
    9797};
    9898
     
    114114        m_eventTarget(eventTarget),
    115115        m_fixTimer(NULL),
    116         m_lastDown(0),
     116        m_lastDown(kKeyNone),
    117117        m_useSavedModifiers(false),
    118118        m_savedModifiers(0),
     
    135135                m_fixTimer = NULL;
    136136        }
    137         m_lastDown = 0;
     137        m_lastDown = kKeyNone;
    138138}
    139139
     
    147147CPMKeyState::testAutoRepeat(bool press, bool isRepeat, KeyButton button)
    148148{
    149         if (!isRepeat) {
    150                 isRepeat = (press && m_lastDown != 0 && button == m_lastDown);
    151         }
    152         if (press) {
    153                 m_lastDown = button;
    154         }
    155         else {
    156                 m_lastDown = 0;
    157         }
     149        if (!isRepeat)
     150                isRepeat = press && button == m_lastDown && button != kKeyNone;
     151        m_lastDown = press ? button : kKeyNone;
    158152        return isRepeat;
    159153}
     
    174168                        // transfer any modifier state changes to CKeyState's state
    175169                        KeyModifierMask mask = m_originalSavedModifiers ^ m_savedModifiers;
    176                         getActiveModifiersRValue() =
    177                                 (getActiveModifiers() & ~mask) | (m_savedModifiers & mask);
     170                        getActiveModifiersRValue() = (getActiveModifiers() & ~mask) | (m_savedModifiers & mask);
    178171                }
    179172        }
     
    181174
    182175KeyID
    183 CPMKeyState::mapKeyFromEvent(MPARAM charAndVirtKey, MPARAM info, KeyModifierMask* maskOut) const
    184 {
     176CPMKeyState::mapKeyFromEvent(USHORT fsFlags, UCHAR ucRepeat, UCHAR ucScanCode, USHORT usch, USHORT usvk, KeyModifierMask* maskOut) const
     177{
     178#if 0 /** @todo */
    185179        static const KeyModifierMask s_controlAlt = KeyModifierControl | KeyModifierAlt;
    186180
     
    228222                *maskOut = active;
    229223        }
    230 
    231224        return id;
    232 }
    233 
    234 bool
    235 CPMKeyState::didGroupsChange() const
    236 {
    237         GroupList groups;
    238         return (getGroups(groups) && groups != m_groups);
    239 }
    240 
    241 UINT
     225#else
     226        return kKeyNone;
     227#endif
     228}
     229
     230ULONG
    242231CPMKeyState::mapKeyToVirtualKey(KeyID key) const
    243232{
    244         if (key == kKeyNone) {
     233        if (key == kKeyNone)
    245234                return 0;
    246         }
    247235        KeyToVKMap::const_iterator i = m_keyToVKMap.find(key);
    248         if (i == m_keyToVKMap.end()) {
     236        if (i == m_keyToVKMap.end())
    249237                return 0;
    250         }
    251         else {
    252                 return i->second;
    253         }
     238        return i->second;
    254239}
    255240
     
    272257                // send key
    273258                if (press && !isAutoRepeat) {
    274                         CKeyState::sendKeyEvent(target, true, false,
    275                                                         key, mask, 1, button);
     259                        CKeyState::sendKeyEvent(target, true, false, key, mask, 1, button);
    276260                        if (count > 0) {
    277261                                --count;
     
    279263                }
    280264                if (count >= 1) {
    281                         CKeyState::sendKeyEvent(target, true, true,
    282                                                         key, mask, count, button);
     265                        CKeyState::sendKeyEvent(target, true, true, key, mask, count, button);
    283266                }
    284267        }
     
    290273
    291274void
    292 CPMKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask,
    293                                 KeyButton button)
     275CPMKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton button)
    294276{
    295277        CKeyState::fakeKeyDown(id, mask, button);
     
    297279
    298280void
    299 CPMKeyState::fakeKeyRepeat(KeyID id, KeyModifierMask mask,
    300                                 SInt32 count, KeyButton button)
     281CPMKeyState::fakeKeyRepeat(KeyID id, KeyModifierMask mask, SInt32 count, KeyButton button)
    301282{
    302283        CKeyState::fakeKeyRepeat(id, mask, count, button);
     
    323304
    324305        // we can get toggle modifiers from the system
    325         if (WinGetKeyState(HWND_DESKTOP, VK_CAPITAL) & 1) {
     306        if (WinGetKeyState(HWND_DESKTOP, VK_CAPSLOCK) & 1)
    326307                state |= KeyModifierCapsLock;
    327         }
    328         if (WinGetKeyState(HWND_DESKTOP, VK_NUMLOCK) & 1) {
     308        if (WinGetKeyState(HWND_DESKTOP, VK_NUMLOCK) & 1)
    329309                state |= KeyModifierNumLock;
    330         }
    331         if (WinGetKeyState(HWND_DESKTOP, VK_SCROLL) & 1) {
     310        if (WinGetKeyState(HWND_DESKTOP, VK_SCRLLOCK) & 1)
    332311                state |= KeyModifierScrollLock;
    333         }
    334 
    335312        return state;
    336313}
     
    623600                                                        }
    624601                                                }
    625                                                
     602
    626603                                                // save each key.  the map will automatically discard
    627604                                                // duplicates, like an unshift and shifted version of
     
    742719}
    743720
    744 bool
    745 CPMKeyState::getGroups(GroupList& groups) const
    746 {
    747         // get keyboard layouts
    748         UInt32 newNumLayouts = GetKeyboardLayoutList(0, NULL);
    749         if (newNumLayouts == 0) {
    750                 LOG((CLOG_DEBUG1 "can't get keyboard layouts"));
    751                 return false;
    752         }
    753         HKL* newLayouts = new HKL[newNumLayouts];
    754         newNumLayouts = GetKeyboardLayoutList(newNumLayouts, newLayouts);
    755         if (newNumLayouts == 0) {
    756                 LOG((CLOG_DEBUG1 "can't get keyboard layouts"));
    757                 delete[] newLayouts;
    758                 return false;
    759         }
    760 
    761         groups.clear();
    762         groups.insert(groups.end(), newLayouts, newLayouts + newNumLayouts);
    763         delete[] newLayouts;
    764         return true;
    765 }
    766 
    767 void
    768 CPMKeyState::setWindowGroup(SInt32 group)
    769 {
    770         HWND targetWindow = GetForegroundWindow();
    771 
    772         bool sysCharSet = true;
    773         // XXX -- determine if m_groups[group] can be used with the system
    774         // character set.
    775 
    776         PostMessage(targetWindow, WM_INPUTLANGCHANGEREQUEST,
    777                                                                 sysCharSet ? 1 : 0, (LPARAM)m_groups[group]);
    778 
    779         // XXX -- use a short delay to let the target window process the message
    780         // before it sees the keyboard events.  i'm not sure why this is
    781         // necessary since the messages should arrive in order.  if we don't
    782         // delay, though, some of our keyboard events may disappear.
    783         Sleep(100);
    784 }
    785 
    786721void
    787722CPMKeyState::fixKeys()
     
    822757                                LOG((CLOG_DEBUG1 "event: fake key release left windows key (0x%03x)", leftButton));
    823758                                CKeyState::onKey(leftButton, false, state);
    824                                 CKeyState::sendKeyEvent(m_eventTarget, false, false,
    825                                                                 kKeySuper_L, state, 1, leftButton);
     759                                CKeyState::sendKeyEvent(m_eventTarget, false, false, kKeySuper_L, state, 1, leftButton);
    826760                        }
    827761                        if (rightDown && !rightAsyncDown) {
    828762                                LOG((CLOG_DEBUG1 "event: fake key release right windows key (0x%03x)", rightButton));
    829763                                CKeyState::onKey(rightButton, false, state);
    830                                 CKeyState::sendKeyEvent(m_eventTarget, false, false,
    831                                                                 kKeySuper_R, state, 1, rightButton);
     764                                CKeyState::sendKeyEvent(m_eventTarget, false, false, kKeySuper_R, state, 1, rightButton);
    832765                        }
    833766                }
     
    910843        }
    911844}
     845
     846/*
     847 * Local Variables:
     848 *  mode: c
     849 *  c-file-style: "k&r"
     850 *  c-basic-offset: 4
     851 *  tab-width: 4
     852 *  indent-tabs-mode: t
     853 * End:
     854 */
     855
  • trunk/synergy/lib/platform/CPMKeyState.h

    r2752 r2755  
    33 * Copyright (C) 2003 Chris Schoeneman
    44 * Copyright (C) 2006 Knut St. Osmundsen
    5  * 
     5 *
    66 * This package is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU General Public License
    88 * found in the file COPYING that should have accompanied this file.
    9  * 
     9 *
    1010 * This package is distributed in the hope that it will be useful,
    1111 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    9090        to a modifier mask.
    9191        */
    92         KeyID                           mapKeyFromEvent(MPARAM charAndVirtKey, MPARAM info, KeyModifierMask* maskOut) const;
     92        KeyID               mapKeyFromEvent(USHORT fsFlags, UCHAR ucRepeat, UCHAR ucScanCode, USHORT usch, USHORT usvk, KeyModifierMask* maskOut) const;
    9393
    9494        //! Check if keyboard groups have changed
     
    183183};
    184184
     185/*
     186 * Local Variables:
     187 *  mode: c
     188 *  c-file-style: "k&r"
     189 *  c-basic-offset: 4
     190 *  tab-width: 4
     191 *  indent-tabs-mode: t
     192 * End:
     193 */
     194
     195
    185196#endif
  • trunk/synergy/lib/platform/CPMScreen.cpp

    r2754 r2755  
    3434#include "CPMUtil.h"
    3535#include <string.h>
     36#include <unistd.h>
    3637
    3738//
     
    4445        m_isPrimary(isPrimary),
    4546        m_isOnScreen(m_isPrimary),
    46         m_class(0),
    4747        m_x(0), m_y(0),
    4848        m_cx(0), m_cy(0),
     
    5353        m_mark(0),
    5454        m_markReceived(0),
    55         m_fixTimer(NULL),
    5655        m_screensaver(NULL),
    5756        m_screensaverNotify(false),
     
    7372
    7473        s_screen = this;
     74
     75        // query curren thread bits.
     76        m_threadID = _gettid();
     77        m_hab = WinQueryAnchorBlock(HWND_DESKTOP);
     78        m_hmq = WinQueueFromID(m_hab, getpid(), _gettid());
     79        if (m_hab == NULLHANDLE || m_hmq == NULLHANDLE) {
     80                LOG((CLOG_CRIT "couldn't get the hab/hmq of the current thread!\n"));
     81                throw XScreenOpenFailure();
     82        }
     83
    7584        try {
    76                 if (m_isPrimary) {
     85                if (m_isPrimary)
    7786                        m_hmodHook = openHookLibrary("synrgyhk");
    78                 }
    7987                m_screensaver = new CPMScreenSaver();
    8088                m_keyState    = new CPMKeyState(getEventTarget());
    8189                updateScreenShape();
    82                 m_class       = createWindowClass();
    83                 m_window      = createWindow(m_class, "Synergy");
     90                m_window      = createWindow("Synergy");
    8491                forceShowCursor();
    8592                LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_cx, m_cy, m_multimon ? "(multi-monitor)" : ""));
    8693                LOG((CLOG_DEBUG "window is 0x%08x", m_window));
    87         }
    88         catch (...) {
     94        } catch (...) {
    8995                delete m_keyState;
    9096                delete m_screensaver;
    9197                destroyWindow(m_window);
    92                 destroyClass(m_class);
    9398                closeHookLibrary(m_hmodHook);
    9499                s_screen = NULL;
     
    98103        // install event handlers
    99104        EVENTQUEUE->adoptHandler(CEvent::kSystem, IEventQueue::getSystemTarget(),
    100                                                         new TMethodEventJob<CPMScreen>(this,
    101                                                                 &CPMScreen::handleSystemEvent));
     105                                                        new TMethodEventJob<CPMScreen>(this, &CPMScreen::handleSystemEvent));
    102106
    103107        // install the platform event queue
     
    115119        delete m_screensaver;
    116120        destroyWindow(m_window);
    117         destroyClass(m_class);
    118121        closeHookLibrary(m_hmodHook);
    119122        s_screen = NULL;
     
    124127{
    125128        assert(m_isOnScreen == m_isPrimary);
    126 
    127         // we need to poll some things to fix them
    128         m_fixTimer = EVENTQUEUE->newTimer(1.0, NULL);
    129         EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer,
    130                                                          new TMethodEventJob<CPMScreen>(this, &CPMScreen::handleFixes));
    131129
    132130        // install our clipboard snooper
     
    135133    WinSetClipbrdViewer(hab, m_window);
    136134
    137 /// @todo start here!
    138         // track the active desk and (re)install the hooks
    139         m_desks->enable();
    140 
    141135        if (m_isPrimary) {
    142136                // set jump zones
     
    151145CPMScreen::disable()
    152146{
    153         // stop tracking the active desk
    154         m_desks->disable();
    155 
    156147        if (m_isPrimary) {
    157148                // disable hooks
     
    166157        m_nextClipboardWindow = NULL;
    167158
    168         // uninstall fix timer
    169         if (m_fixTimer != NULL) {
    170                 EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer);
    171                 EVENTQUEUE->deleteTimer(m_fixTimer);
    172                 m_fixTimer = NULL;
    173         }
    174 
    175159        m_isOnScreen = m_isPrimary;
    176160        forceShowCursor();
     
    180164CPMScreen::enter()
    181165{
    182         m_desks->enter();
     166        // show the pointer (?), hide the synergy window and restore focus.
     167        WinShowPointer(HWND_DESKTOP, TRUE);
     168        WinSetWindowPos(m_window, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDE);
     169        //?? WinSetFocus(
     170        //?? WinEnableWindow
     171
    183172        if (m_isPrimary) {
    184173                // watch jump zones
     
    197186CPMScreen::leave()
    198187{
     188        /// @todo save focus window.
     189
    199190        if (m_isPrimary) {
    200191                // warp to center
     
    252243{
    253244        m_screensaverNotify = notify;
    254         if (!m_screensaverNotify) {
     245        if (!m_screensaverNotify)
    255246                m_screensaver->disable();
    256         }
    257247}
    258248
     
    260250CPMScreen::closeScreensaver()
    261251{
    262         if (!m_screensaverNotify) {
     252        if (!m_screensaverNotify)
    263253                m_screensaver->enable();
    264         }
    265254}
    266255
     
    268257CPMScreen::screensaver(bool activate)
    269258{
    270     if (activate) {
     259    if (activate)
    271260        m_screensaver->activate();
    272     }
    273     else {
     261    else
    274262        m_screensaver->deactivate();
    275     }
    276263}
    277264
     
    321308CPMScreen::getShape(SInt32& x, SInt32& y, SInt32& cx, SInt32& cy) const
    322309{
    323         assert(m_class != 0);
    324 
    325310        x = m_x;
    326311        y = m_y;
     
    356341        // remove all input events before and including warp
    357342        QMSG qmsg;
    358         while (WinPeekMsg(m_hab, &qmsg, NULLHANDLE, SYNERGY_MSG_INPUT_FIRST, SYNERGY_MSG_INPUT_LAST, PM_REMOVE)) {
     343        while (WinPeekMsg(m_hab, &qmsg, NULLHANDLE, SYNERGY_PM_MSG_INPUT_FIRST, SYNERGY_PM_MSG_INPUT_LAST, PM_REMOVE)) {
    359344                // do nothing
    360345        }
     
    483468                m_keyState->useSavedModifiers(true);
    484469        }
    485         m_desks->fakeInputBegin();
     470        //m_desks->fakeInputBegin();
    486471}
    487472
     
    491476        assert(m_isPrimary);
    492477
    493         m_desks->fakeInputEnd();
     478        //m_desks->fakeInputEnd();
    494479        if (!m_isOnScreen) {
    495480                m_keyState->useSavedModifiers(false);
     
    535520CPMScreen::fakeMouseButton(ButtonID id, bool press) const
    536521{
    537         m_desks->fakeMouseButton(id, press);
     522        //m_desks->fakeMouseButton(id, press);
    538523}
    539524
     
    541526CPMScreen::fakeMouseMove(SInt32 x, SInt32 y) const
    542527{
    543         m_desks->fakeMouseMove(x, y);
     528        //m_desks->fakeMouseMove(x, y);
    544529}
    545530
     
    547532CPMScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
    548533{
    549         m_desks->fakeMouseRelativeMove(dx, dy);
     534        //m_desks->fakeMouseRelativeMove(dx, dy);
    550535}
    551536
     
    553538CPMScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
    554539{
    555         m_desks->fakeMouseWheel(xDelta, yDelta);
     540        //m_desks->fakeMouseWheel(xDelta, yDelta);
    556541}
    557542
     
    559544CPMScreen::updateKeys()
    560545{
    561         m_desks->updateKeys();
     546        //m_desks->updateKeys();
    562547}
    563548
     
    592577}
    593578
    594 HINSTANCE
     579HMODULE
    595580CPMScreen::openHookLibrary(const char* name)
    596581{
    597582        // load the hook library
    598         HINSTANCE hookLibrary = LoadLibrary(name);
    599         if (hookLibrary == NULL) {
    600                 LOG((CLOG_ERR "Failed to load hook library;  %s.dll is missing", name));
     583        HMODULE hmod;
     584        APIRET rc = DosLoadModule(NULL, 0, (PCSZ)name, &hmod);
     585        if (rc != NO_ERROR) {
     586                LOG((CLOG_ERR "Failed to load hook library (%s), rc=%d ", name, rc));
    601587                throw XScreenOpenFailure();
    602588        }
    603589
    604590        // look up functions
    605         m_setSides  = (SetSidesFunc)GetProcAddress(hookLibrary, "setSides");
    606         m_setZone   = (SetZoneFunc)GetProcAddress(hookLibrary, "setZone");
    607         m_setMode   = (SetModeFunc)GetProcAddress(hookLibrary, "setMode");
    608         m_init      = (InitFunc)GetProcAddress(hookLibrary, "init");
    609         m_cleanup   = (CleanupFunc)GetProcAddress(hookLibrary, "cleanup");
    610         if (m_setSides             == NULL ||
    611                 m_setZone              == NULL ||
    612                 m_setMode              == NULL ||
    613                 m_init                 == NULL ||
    614                 m_cleanup              == NULL) {
    615                 LOG((CLOG_ERR "Invalid hook library;  use a newer %s.dll", name));
     591        if (    (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setSides",      (PPFN)&m_setSides)) != NO_ERROR
     592                ||      (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setZone",       (PPFN)&m_setZone )) != NO_ERROR
     593                ||      (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setMode",       (PPFN)&m_setMode )) != NO_ERROR
     594                ||      (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_init",          (PPFN)&m_init    )) != NO_ERROR
     595                ||      (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_cleanup",       (PPFN)&m_cleanup )) != NO_ERROR) {
     596                LOG((CLOG_ERR "Invalid hook library;  use a newer %s.dll (rc=%d)", name, rc));
     597                DosFreeModule(hmod);
    616598                throw XScreenOpenFailure();
    617599        }
    618600
    619601        // initialize hook library
    620         if (m_init(GetCurrentThreadId()) == 0) {
    621                 LOG((CLOG_ERR "Cannot initialize hook library;  is synergy already running?"));
     602        if (m_init(m_hmq, _gettid(), getpid()) == 0) {
     603                LOG((CLOG_ERR "Cannot initialize hook library; is synergy already running?"));
     604                DosFreeModule(hmod);
    622605                throw XScreenOpenFailure();
    623606        }
    624 
    625         return hookLibrary;
    626 }
    627 
    628 void
    629 CPMScreen::closeHookLibrary(HINSTANCE hookLibrary) const
    630 {
    631         if (hookLibrary != NULL) {
    632                 m_cleanup();
    633                 FreeLibrary(hookLibrary);
    634         }
    635 }
    636 
    637 ATOM
    638 CPMScreen::createWindowClass() const
    639 {
    640         WNDCLASSEX classInfo;
    641         classInfo.cbSize        = sizeof(classInfo);
    642         classInfo.style         = CS_DBLCLKS | CS_NOCLOSE;
    643         classInfo.lpfnWndProc   = &CPMScreen::wndProc;
    644         classInfo.cbClsExtra    = 0;
    645         classInfo.cbWndExtra    = 0;
    646         classInfo.hInstance     = s_instance;
    647         classInfo.hIcon         = NULL;
    648         classInfo.hCursor       = NULL;
    649         classInfo.hbrBackground = NULL;
    650         classInfo.lpszMenuName  = NULL;
    651         classInfo.lpszClassName = "Synergy";
    652         classInfo.hIconSm       = NULL;
    653         return RegisterClassEx(&classInfo);
    654 }
    655 
    656 void
    657 CPMScreen::destroyClass(ATOM windowClass) const
    658 {
    659         if (windowClass != 0) {
    660                 UnregisterClass(reinterpret_cast<LPCTSTR>(windowClass), s_instance);
     607        return hmod;
     608}
     609
     610void
     611CPMScreen::closeHookLibrary(HMODULE hmod) const
     612{
     613        if (hmod != NULL) {
     614                m_cleanup(m_hab);
     615                DosFreeModule(hmod);
    661616        }
    662617}
    663618
    664619HWND
    665 CPMScreen::createWindow(ATOM windowClass, const char* name) const
    666 {
    667         HWND window = CreateWindowEx(WS_EX_TOPMOST |
    668                                                                         WS_EX_TRANSPARENT |
    669                                                                         WS_EX_TOOLWINDOW,
    670                                                                 reinterpret_cast<LPCTSTR>(windowClass),
    671                                                                 name,
    672                                                                 WS_POPUP,
     620CPMScreen::createWindow(const char* name)
     621{
     622        WinRegisterClass(m_hab, (PCSZ)"Synergy", CPMScreen::wndProc, CS_MOVENOTIFY, sizeof(uintptr_t));
     623        HWND hwnd = WinCreateWindow(HWND_DESKTOP,
     624                                                                (PCSZ)"Synergy",
     625                                                                NULL,
     626                                                                0, //WS_?,
    673627                                                                0, 0, 1, 1,
    674                                                                 NULL, NULL,
    675                                                                 s_instance,
     628                                                                HWND_DESKTOP,
     629                                                                NULLHANDLE,
     630                                                                0,
     631                                                                this,
    676632                                                                NULL);
    677         if (window == NULL) {
    678                 LOG((CLOG_ERR "failed to create window: %d", GetLastError()));
     633        if (hwnd == NULLHANDLE) {
     634                LOG((CLOG_ERR "failed to create window: %ld", WinGetLastError(m_hab)));
    679635                throw XScreenOpenFailure();
    680636        }
    681         return window;
     637        return hwnd;
    682638}
    683639
     
    686642{
    687643        if (hwnd != NULL) {
    688                 DestroyWindow(hwnd);
     644                WinDestroyWindow(hwnd);
    689645        }
    690646}
     
    708664CPMScreen::handleSystemEvent(const CEvent& event, void*)
    709665{
    710         MSG* msg = reinterpret_cast<MSG*>(event.getData());
    711         assert(msg != NULL);
    712 
    713         if (CArchMiscWindows::processDialog(msg)) {
     666        PQMSG pqmsg = (PQMSG)event.getData();
     667        assert(pqmsg != NULL);
     668        if (onPreDispatch(pqmsg->hwnd, pqmsg->msg, pqmsg->mp1, pqmsg->mp2))
    714669                return;
    715         }
    716         if (onPreDispatch(msg->hwnd, msg->message, msg->wParam, msg->lParam)) {
    717                 return;
    718         }
    719         TranslateMessage(msg);
    720         DispatchMessage(msg);
     670        WinDispatchMsg(CPMUtil::getHAB(), pqmsg);
    721671}
    722672
     
    724674CPMScreen::updateButtons()
    725675{
    726         int numButtons               = GetSystemMetrics(SM_CMOUSEBUTTONS);
    727676        m_buttons[kButtonNone]       = false;
    728         m_buttons[kButtonLeft]       = (GetKeyState(VK_LBUTTON)  < 0);
    729         m_buttons[kButtonRight]      = (GetKeyState(VK_RBUTTON)  < 0);
    730         m_buttons[kButtonMiddle]     = (GetKeyState(VK_MBUTTON)  < 0);
    731         m_buttons[kButtonExtra0 + 0] = (numButtons >= 4) &&
    732                                                                    (GetKeyState(VK_XBUTTON1) < 0);
    733         m_buttons[kButtonExtra0 + 1] = (numButtons >= 5) &&
    734                                                                    (GetKeyState(VK_XBUTTON2) < 0);
     677        m_buttons[kButtonLeft]       = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) != 0;
     678        m_buttons[kButtonRight]      = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) != 0;
     679        m_buttons[kButtonMiddle]     = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) != 0;
     680        m_buttons[kButtonExtra0 + 0] = false;
     681        m_buttons[kButtonExtra0 + 1] = false;
    735682}
    736683
     
    742689
    743690bool
    744 CPMScreen::onPreDispatch(HWND hwnd,
    745                                 UINT message, WPARAM wParam, LPARAM lParam)
     691CPMScreen::onPreDispatch(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    746692{
    747693        // handle event
    748         switch (message) {
    749         case SYNERGY_MSG_SCREEN_SAVER:
    750                 return onScreensaver(wParam != 0);
    751 
    752         case SYNERGY_MSG_DEBUG:
    753                 LOG((CLOG_DEBUG1 "hook: 0x%08x 0x%08x", wParam, lParam));
     694        switch (msg) {
     695        case SYNERGY_PM_MSG_DEBUG:
     696                LOG((CLOG_DEBUG1 "hook: 0x%08x 0x%08x", mp1, mp2));
    754697                return true;
    755698        }
    756699
    757700        if (m_isPrimary) {
    758                 return onPreDispatchPrimary(hwnd, message, wParam, lParam);
     701                return onPreDispatchPrimary(hwnd, msg, mp1, mp2);
    759702        }
    760703
     
    763706
    764707bool
    765 CPMScreen::onPreDispatchPrimary(HWND,
    766                                 UINT message, WPARAM wParam, LPARAM lParam)
     708CPMScreen::onPreDispatchPrimary(HWND, ULONG msg, MPARAM mp1, MPARAM mp2)
    767709{
    768710        // handle event
    769         switch (message) {
    770         case SYNERGY_MSG_MARK:
    771                 return onMark(static_cast<UInt32>(wParam));
    772 
    773         case SYNERGY_MSG_KEY:
    774                 return onKey(wParam, lParam);
    775 
    776         case SYNERGY_MSG_MOUSE_BUTTON:
    777                 return onMouseButton(wParam, lParam);
    778 
    779         case SYNERGY_MSG_MOUSE_MOVE:
    780                 return onMouseMove(static_cast<SInt32>(wParam),
    781                                                         static_cast<SInt32>(lParam));
    782 
    783         case SYNERGY_MSG_MOUSE_WHEEL:
    784                 // XXX -- support x-axis scrolling
    785                 return onMouseWheel(0, static_cast<SInt32>(wParam));
    786 
    787         case SYNERGY_MSG_PRE_WARP:
     711        switch (msg) {
     712        case SYNERGY_PM_MSG_MARK:
     713                return onMark((uintptr_t)mp1);
     714
     715        case SYNERGY_PM_MSG_KEY:
     716                return onKey(SHORT1FROMMP(mp1), CHAR3FROMMP(mp1), CHAR4FROMMP(mp1), SHORT1FROMMP(mp2), SHORT2FROMMP(mp2));
     717
     718        case SYNERGY_PM_MSG_MOUSE_BUTTON:
     719                return onMouseButton(SHORT1FROMMP(mp1), (SHORT)SHORT1FROMMP(mp2), m_cy - (SHORT)SHORT2FROMMP(mp2));
     720
     721        case SYNERGY_PM_MSG_MOUSE_MOVE:
     722                return onMouseMove(SHORT1FROMMP(mp1), (SHORT)SHORT1FROMMP(mp2), m_cy - (SHORT)SHORT2FROMMP(mp2));
     723
     724        case SYNERGY_PM_MSG_PRE_WARP:
    788725                {
    789                         // save position to compute delta of next motion
    790                         m_xCursor = static_cast<SInt32>(wParam);
    791                         m_yCursor = static_cast<SInt32>(lParam);
    792 
    793                         // we warped the mouse.  discard events until we find the
    794                         // matching post warp event.  see warpCursorNoFlush() for
    795                         // where the events are sent.  we discard the matching
     726                        // Save position to compute delta of next motion
     727                        m_xCursor = (SInt32)mp1;
     728                        m_yCursor = (SInt32)mp2;
     729
     730                        // We warped the mouse. Discard events until we find the
     731                        // matching post warp event. See warpCursorNoFlush() for
     732                        // where the events are sent. We discard the matching
    796733                        // post warp event and can be sure we've skipped the warp
    797734                        // event.
    798                         MSG msg;
    799                         do {
    800                                 GetMessage(&msg, NULL, SYNERGY_MSG_MOUSE_MOVE,
    801                                                                                 SYNERGY_MSG_POST_WARP);
    802                         } while (msg.message != SYNERGY_MSG_POST_WARP);
     735                        QMSG qmsg;
     736                        while (   WinGetMsg(m_hab, &qmsg, NULLHANDLE, SYNERGY_PM_MSG_MOUSE_MOVE, SYNERGY_PM_MSG_POST_WARP)
     737                                   && qmsg.msg != SYNERGY_PM_MSG_POST_WARP)
     738                                /* nothing */;
    803739                }
    804740                return true;
    805741
    806         case SYNERGY_MSG_POST_WARP:
     742        case SYNERGY_PM_MSG_POST_WARP:
    807743                LOG((CLOG_WARN "unmatched post warp"));
    808744                return true;
    809 
    810         case WM_HOTKEY:
    811                 // we discard these messages.  we'll catch the hot key in the
    812                 // regular key event handling, where we can detect both key
    813                 // press and release.  we only register the hot key so no other
    814                 // app will act on the key combination.
    815                 break;
    816745        }
    817746
     
    820749
    821750bool
    822 CPMScreen::onEvent(HWND, UINT msg,
    823                                 WPARAM wParam, LPARAM lParam, LRESULT* result)
     751CPMScreen::onEvent(HWND, ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT *result)
    824752{
    825753        switch (msg) {
    826         case WM_QUERYENDSESSION:
    827                 if (m_is95Family) {
    828                         *result = TRUE;
    829                         return true;
    830                 }
    831                 break;
    832 
    833         case WM_ENDSESSION:
    834                 if (m_is95Family) {
    835                         if (wParam == TRUE && lParam == 0) {
    836                                 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
    837                         }
    838                         return true;
    839                 }
    840                 break;
    841 
    842754        case WM_DRAWCLIPBOARD:
    843                 // first pass on the message
    844                 if (m_nextClipboardWindow != NULL) {
    845                         SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
    846                 }
     755                //// first pass on the message
     756                //if (m_nextClipboardWindow != NULL) {
     757                //      WinSendMessage(m_nextClipboardWindow, msg, mp1, mp2);
     758                //}
    847759
    848760                // now handle the message
    849761                return onClipboardChange();
    850 
    851         case WM_CHANGECBCHAIN:
    852                 if (m_nextClipboardWindow == (HWND)wParam) {
    853                         m_nextClipboardWindow = (HWND)lParam;
    854                         LOG((CLOG_DEBUG "clipboard chain: new next: 0x%08x", m_nextClipboardWindow));
    855                 }
    856                 else if (m_nextClipboardWindow != NULL) {
    857                         SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
    858                 }
    859                 return true;
    860 
    861         case WM_DISPLAYCHANGE:
    862                 return onDisplayChange();
    863 
    864         case WM_POWERBROADCAST:
    865                 switch (wParam) {
    866                 case PBT_APMRESUMEAUTOMATIC:
    867                 case PBT_APMRESUMECRITICAL:
    868                 case PBT_APMRESUMESUSPEND:
    869                         EVENTQUEUE->addEvent(CEvent(IScreen::getResumeEvent(),
    870                                                         getEventTarget(), NULL,
    871                                                         CEvent::kDeliverImmediately));
    872                         break;
    873 
    874                 case PBT_APMSUSPEND:
    875                         EVENTQUEUE->addEvent(CEvent(IScreen::getSuspendEvent(),
    876                                                         getEventTarget(), NULL,
    877                                                         CEvent::kDeliverImmediately));
    878                         break;
    879                 }
    880                 *result = TRUE;
    881                 return true;
    882762        }
    883763
     
    893773
    894774bool
    895 CPMScreen::onKey(WPARAM wParam, LPARAM lParam)
    896 {
    897         static const KeyModifierMask s_ctrlAlt =
    898                 KeyModifierControl | KeyModifierAlt;
    899 
    900         LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, lParam=0x%08x", (wParam & 0xff00u) >> 8, wParam & 0xffu, (wParam & 0x10000u) ? 1 : 0, lParam));
     775CPMScreen::onKey(USHORT fsFlags, UCHAR ucRepeat, UCHAR ucScanCode, USHORT usch, USHORT usvk)
     776{
     777#if 0
     778        static const KeyModifierMask s_ctrlAlt = KeyModifierControl | KeyModifierAlt;
     779
     780        LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, mp2=0x%08x", (mp1 & 0xff00u) >> 8, mp1 & 0xffu, (mp1 & 0x10000u) ? 1 : 0, mp2));
    901781
    902782        // get event info
    903         KeyButton button         = (KeyButton)((lParam & 0x01ff0000) >> 16);
    904         bool down                = ((lParam & 0x80000000u) == 0x00000000u);
     783        KeyButton button         = (KeyButton)((mp2 & 0x01ff0000) >> 16);
     784        bool down                = ((mp2 & 0x80000000u) == 0x00000000u);
    905785        bool wasDown             = isKeyDown(button);
    906786        KeyModifierMask oldState = pollActiveModifiers();
    907787
    908788        // check for autorepeat
    909         if (m_keyState->testAutoRepeat(down, (lParam & 0x40000000u) == 1, button)) {
    910                 lParam |= 0x40000000u;
     789        if (m_keyState->testAutoRepeat(down, (mp2 & 0x40000000u) == 1, button)) {
     790                mp2 |= 0x40000000u;
    911791        }
    912792
     
    916796        // alternatively, we could just throw these events out.
    917797        if (button == 0) {
    918                 button = m_keyState->virtualKeyToButton(wParam & 0xffu);
     798                button = m_keyState->virtualKeyToButton(mp1 & 0xffu);
    919799                if (button == 0) {
    920800                        return true;
     
    950830        if (oldState != state) {
    951831                // modifier key was pressed/released
    952                 if (onHotKey(0, lParam)) {
     832                if (onHotKey(0, mp2)) {
    953833                        return true;
    954834                }
     
    956836        else {
    957837                // non-modifier was pressed/released
    958                 if (onHotKey(wParam, lParam)) {
     838                if (onHotKey(mp1, mp2)) {
    959839                        return true;
    960840                }
     
    965845                // check for ctrl+alt+del.  we do not want to pass that to the
    966846                // client.  the user can use ctrl+alt+pause to emulate it.
    967                 UINT virtKey = (wParam & 0xffu);
     847                UINT virtKey = (mp1 & 0xffu);
    968848                if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) {
    969849                        LOG((CLOG_DEBUG "discard ctrl+alt+del"));
     
    975855                        (state & s_ctrlAlt) == s_ctrlAlt) {
    976856                        LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
    977                         // switch wParam and lParam to be as if VK_DELETE was
     857                        // switch mp1 and mp2 to be as if VK_DELETE was
    978858                        // pressed or released.  when mapping the key we require that
    979                         // we not use AltGr (the 0x10000 flag in wParam) and we not
    980                         // use the keypad delete key (the 0x01000000 flag in lParam).
    981                         wParam  = VK_DELETE | 0x00010000u;
    982                         lParam &= 0xfe000000;
    983                         lParam |= m_keyState->virtualKeyToButton(wParam & 0xffu) << 16;
    984                         lParam |= 0x01000001;
     859                        // we not use AltGr (the 0x10000 flag in mp1) and we not
     860                        // use the keypad delete key (the 0x01000000 flag in mp2).
     861                        mp1  = VK_DELETE | 0x00010000u;
     862                        mp2 &= 0xfe000000;
     863                        mp2 |= m_keyState->virtualKeyToButton(mp1 & 0xffu) << 16;
     864                        mp2 |= 0x01000001;
    985865                }
    986866
    987867                // process key
    988868                KeyModifierMask mask;
    989                 KeyID key = m_keyState->mapKeyFromEvent(wParam, lParam, &mask);
    990                 button    = static_cast<KeyButton>((lParam & 0x01ff0000u) >> 16);
     869                KeyID key = m_keyState->mapKeyFromEvent((ULONG)mp1, (ULONG)mp2, &mask);
     870                button    = static_cast<KeyButton>((mp2 & 0x01ff0000u) >> 16);
    991871                if (key != kKeyNone) {
    992872                        // fix key up.  if the key isn't down according to
     
    1023903                        // do it
    1024904                        m_keyState->sendKeyEvent(getEventTarget(),
    1025                                                         ((lParam & 0x80000000u) == 0),
    1026                                                         ((lParam & 0x40000000u) != 0),
    1027                                                         key, mask, (SInt32)(lParam & 0xffff), button);
     905                                                        ((mp2 & 0x80000000u) == 0),
     906                                                        ((mp2 & 0x40000000u) != 0),
     907                                                        key, mask, (SInt32)(mp2 & 0xffff), button);
    1028908                }
    1029909                else {
     
    1031911                }
    1032912        }
    1033 
     913#endif
    1034914        return true;
    1035915}
    1036916
    1037917bool
    1038 CPMScreen::onHotKey(WPARAM wParam, LPARAM lParam)
    1039 {
     918CPMScreen::onHotKey(MPARAM mp1, MPARAM mp2)
     919{
     920#if 0
    1040921        // get the key info
    1041922        KeyModifierMask state = getActiveModifiers();
    1042         UINT virtKey   = (wParam & 0xffu);
     923        UINT virtKey   = (mp1 & 0xffu);
    1043924        UINT modifiers = 0;
    1044925        if ((state & KeyModifierShift) != 0) {
     
    1064945        // find what kind of event
    1065946        CEvent::Type type;
    1066         if ((lParam & 0x80000000u) == 0u) {
    1067                 if ((lParam & 0x40000000u) != 0u) {
     947        if ((mp2 & 0x80000000u) == 0u) {
     948                if ((mp2 & 0x40000000u) != 0u) {
    1068949                        // ignore key repeats but it counts as a hot key
    1069950                        return true;
     
    1079960                                                        CHotKeyInfo::alloc(i->second)));
    1080961
     962#endif
    1081963        return true;
    1082964}
    1083965
    1084966bool
    1085 CPMScreen::onMouseButton(WPARAM wParam, LPARAM lParam)
     967CPMScreen::onMouseButton(ULONG msg, SInt32 ax, SInt32 ay)
    1086968{
    1087969        // get which button
    1088         bool pressed    = mapPressFromEvent((ULONG)wParam, lParam);
    1089         ButtonID button = mapButtonFromEvent((ULONG)wParam, lParam);
     970        bool pressed    = mapPressFromEvent(msg);
     971        ButtonID button = mapButtonFromEvent(msg);
    1090972
    1091973        // keep our shadow key state up to date
     
    11221004
    11231005bool
    1124 CPMScreen::onMouseMove(SInt32 mx, SInt32 my)
     1006CPMScreen::onMouseMove(ULONG msg, SInt32 ax, SInt32 ay)
    11251007{
    11261008        // compute motion delta (relative to the last known
    11271009        // mouse position)
    1128         SInt32 x = mx - m_xCursor;
    1129         SInt32 y = my - m_yCursor;
     1010        SInt32 x = ax - m_xCursor;
     1011        SInt32 y = ay - m_yCursor;
    11301012
    11311013        // ignore if the mouse didn't move or if message posted prior
     
    11361018
    11371019        // save position to compute delta of next motion
    1138         m_xCursor = mx;
    1139         m_yCursor = my;
     1020        m_xCursor = ax;
     1021        m_yCursor = ay;
    11401022
    11411023        if (m_isOnScreen) {
    11421024                // motion on primary screen
    1143                 sendEvent(getMotionOnPrimaryEvent(),
    1144                                                         CMotionInfo::alloc(m_xCursor, m_yCursor));
     1025                sendEvent(getMotionOnPrimaryEvent(), CMotionInfo::alloc(m_xCursor, m_yCursor));
    11451026        }
    11461027        else {
     
    11711052
    11721053bool
    1173 CPMScreen::onMouseWheel(SInt32 xDelta, SInt32 yDelta)
    1174 {
    1175         // ignore message if posted prior to last mark change
    1176         if (!ignore()) {
    1177                 LOG((CLOG_DEBUG1 "event: button wheel delta=%+d,%+d", xDelta, yDelta));
    1178                 sendEvent(getWheelEvent(), CWheelInfo::alloc(xDelta, yDelta));
    1179         }
    1180         return true;
    1181 }
    1182 
    1183 bool
    1184 CPMScreen::onScreensaver(bool activated)
    1185 {
    1186         // ignore this message if there are any other screen saver
    1187         // messages already in the queue.  this is important because
    1188         // our checkStarted() function has a deliberate delay, so it
    1189         // can't respond to events at full CPU speed and will fall
    1190         // behind if a lot of screen saver events are generated.
    1191         // that can easily happen because windows will continually
    1192         // send SC_SCREENSAVE until the screen saver starts, even if
    1193         // the screen saver is disabled!
    1194         MSG msg;
    1195         if (PeekMessage(&msg, NULL, SYNERGY_MSG_SCREEN_SAVER,
    1196                                                 SYNERGY_MSG_SCREEN_SAVER, PM_NOREMOVE)) {
    1197                 return true;
    1198         }
    1199 
    1200         if (activated) {
    1201                 if (!m_screensaverActive &&
    1202                         m_screensaver->checkStarted(SYNERGY_MSG_SCREEN_SAVER, FALSE, 0)) {
    1203                         m_screensaverActive = true;
    1204                         sendEvent(getScreensaverActivatedEvent());
    1205 
    1206                         // enable display power down
    1207                         CArchMiscWindows::removeBusyState(CArchMiscWindows::kDISPLAY);
    1208                 }
    1209         }
    1210         else {
    1211                 if (m_screensaverActive) {
    1212                         m_screensaverActive = false;
    1213                         sendEvent(getScreensaverDeactivatedEvent());
    1214 
    1215                         // disable display power down
    1216                         CArchMiscWindows::addBusyState(CArchMiscWindows::kDISPLAY);
    1217                 }
    1218         }
    1219 
    1220         return true;
    1221 }
    1222 
    1223 bool
    1224 CPMScreen::onDisplayChange()
    1225 {
    1226         // screen resolution may have changed.  save old shape.
    1227         SInt32 xOld = m_x, yOld = m_y, wOld = m_cx, hOld = m_cy;
    1228 
    1229         // update shape
    1230         updateScreenShape();
    1231 
    1232         // do nothing if resolution hasn't changed
    1233         if (xOld != m_x || yOld != m_y || wOld != m_cx || hOld != m_cy) {
    1234                 if (m_isPrimary) {
    1235                         // warp mouse to center if off screen
    1236                         if (!m_isOnScreen) {
    1237                                 warpCursor(m_xCenter, m_yCenter);
    1238                         }
    1239 
    1240                         // tell hook about resize if on screen
    1241                         else {
    1242                                 m_setZone(m_x, m_y, m_cx, m_cy, getJumpZoneSize());
    1243                         }
    1244                 }
    1245 
    1246                 // send new screen info
    1247                 sendEvent(getShapeChangedEvent());
    1248 
    1249                 LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_cx, m_cy, m_multimon ? "(multi-monitor)" : ""));
    1250         }
    1251 
    1252         return true;
    1253 }
    1254 
    1255 bool
    12561054CPMScreen::onClipboardChange()
    12571055{
     
    12781076{
    12791077        // send an event that we can recognize before the mouse warp
    1280     WinPostQueueMsg(m_hmq, SYNERGY_MSG_PRE_WARP, (MPARAM)x, (MPARAM)y);
     1078    WinPostQueueMsg(m_hmq, SYNERGY_PM_MSG_PRE_WARP, (MPARAM)x, (MPARAM)y);
    12811079
    12821080        // warp mouse.  hopefully this inserts a mouse motion event
     
    13031101
    13041102        // send an event that we can recognize after the mouse warp
    1305     WinPostQueueMsg(m_hmq, SYNERGY_MSG_POST_WARP, 0, 0);
     1103    WinPostQueueMsg(m_hmq, SYNERGY_PM_MSG_POST_WARP, 0, 0);
    13061104}
    13071105
     
    13131111
    13141112        // mark point in message queue where the mark was changed
    1315     WinPostQueueMsg(m_hmq, SYNERGY_MSG_MARK, (MPARAM)m_mark, 0);
     1113    WinPostQueueMsg(m_hmq, SYNERGY_PM_MSG_MARK, (MPARAM)m_mark, 0);
    13161114}
    13171115
     
    13391137}
    13401138
    1341 void
    1342 CPMScreen::handleFixes(const CEvent&, void*)
    1343 {
    1344         // update keys if keyboard layouts have changed
    1345         if (m_keyState->didGroupsChange()) {
    1346                 updateKeys();
    1347         }
    1348 }
    1349 
    13501139ButtonID
    1351 CPMScreen::mapButtonFromEvent(ULONG msg, MPARAM button) const
     1140CPMScreen::mapButtonFromEvent(ULONG msg) const
    13521141{
    13531142    /** @todo query which is left and which is right. */
     
    13771166
    13781167bool
    1379 CPMScreen::mapPressFromEvent(ULONG msg, LPARAM) const
     1168CPMScreen::mapPressFromEvent(ULONG msg) const
    13801169{
    13811170        switch (msg) {
     
    14111200        }
    14121201
    1413         // update layouts if necessary
    1414         if (m_keyState->didGroupsChange()) {
    1415                 CPlatformScreen::updateKeyMap();
    1416         }
    1417 
    14181202        // now update the keyboard state
    14191203        CPlatformScreen::updateKeyState();
     
    14541238}
    14551239
    1456 HRESULT EXPENTRY
    1457 CPMScreen::wndProc(HWND hwnd, UINT msg, MPARAM mp1, MPARAM mp2)
     1240MRESULT EXPENTRY
     1241CPMScreen::wndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    14581242{
    14591243        assert(s_screen != NULL);
    14601244
    1461         HRESULT mr = 0;
    1462         if (!s_screen->onEvent(hwnd, msg, mp1, mp2, &result)) {
     1245        MRESULT mr = 0;
     1246        if (!s_screen->onEvent(hwnd, msg, mp1, mp2, &mr)) {
    14631247                mr = WinDefWindowProc(hwnd, msg, mp1, mp2);
    14641248        }
     
    14721256//
    14731257
    1474 CPMScreen::CHotKeyItem::CHotKeyItem(UINT keycode, UINT mask) :
     1258CPMScreen::CHotKeyItem::CHotKeyItem(ULONG keycode, ULONG mask) :
    14751259        m_keycode(keycode),
    14761260        m_mask(mask)
     
    14791263}
    14801264
    1481 UINT
     1265ULONG
    14821266CPMScreen::CHotKeyItem::getVirtualKey() const
    14831267{
  • trunk/synergy/lib/platform/CPMScreen.h

    r2752 r2755  
    33 * Copyright (C) 2002 Chris Schoeneman
    44 * Copyright (C) 2006 Knut St. Osmundsen
    5  * 
     5 *
    66 * This package is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU General Public License
    88 * found in the file COPYING that should have accompanied this file.
    9  * 
     9 *
    1010 * This package is distributed in the hope that it will be useful,
    1111 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    9898        HMODULE                         openHookLibrary(const char* name);
    9999        void                            closeHookLibrary(HMODULE hookLibrary) const;
    100         ATOM                            createWindowClass() const;
    101         ATOM                            createDeskWindowClass(bool isPrimary) const;
    102         void                            destroyClass(ATOM windowClass) const;
    103         HWND                            createWindow(ATOM windowClass, const char* name) const;
     100        HWND                            createWindow(const char* name);
    104101        void                            destroyWindow(HWND) const;
    105102
     
    122119        // message handlers
    123120        bool                            onMark(UInt32 mark);
    124         bool                            onKey(MPARAM, MPARAM);
     121        bool                            onKey(USHORT fsFlags, UCHAR ucRepeat, UCHAR ucScanCode, USHORT usch, USHORT usvk);
    125122        bool                            onHotKey(MPARAM, MPARAM);
    126         bool                            onMouseButton(MPARAM, MPARAM);
    127         bool                            onMouseMove(SInt32 x, SInt32 y);
    128         bool                            onMouseWheel(SInt32 xDelta, SInt32 yDelta);
    129         bool                            onScreensaver(bool activated);
    130         bool                            onDisplayChange();
     123        bool                            onMouseButton(ULONG msg, SInt32 ax, SInt32 ay);
     124        bool                            onMouseMove(ULONG msg, SInt32 ax, SInt32 ay);
    131125        bool                            onClipboardChange();
    132126
     
    150144
    151145        // map a button event to a button ID
    152         ButtonID                        mapButtonFromEvent(ULONG msg, MPARAM button) const;
     146        ButtonID                        mapButtonFromEvent(ULONG msg) const;
    153147
    154148        // map a button event to a press (true) or release (false)
    155         bool                            mapPressFromEvent(ULONG msg, MPARAM button) const;
     149        bool                            mapPressFromEvent(ULONG msg) const;
    156150
    157151        // job to update the key state
     
    192186        bool                            m_isOnScreen;
    193187
    194         // our resources
    195         ATOM                            m_class;
    196 
    197188        // screen shape stuff
    198189        SInt32                          m_x, m_y;
     
    213204        UInt32                          m_markReceived;
    214205
    215         // the main loop's thread id
     206        // the main loop's thread id, anchor block and message queue.
    216207        int                                     m_threadID;
    217 
    218         // timer for periodically checking stuff that requires polling
    219         CEventQueueTimer*       m_fixTimer;
     208        HAB                                     m_hab;
     209        HMQ                 m_hmq;
    220210
    221211        // screen saver stuff
    222         CPMScreenSaver* m_screensaver;
    223         bool                                    m_screensaverNotify;
    224         bool                                    m_screensaverActive;
     212        CPMScreenSaver*         m_screensaver;
     213        bool                            m_screensaverNotify;
     214        bool                            m_screensaverActive;
    225215
    226216        // clipboard stuff.  our window is used mainly as a clipboard
     
    255245};
    256246
     247/*
     248 * Local Variables:
     249 *  mode: c
     250 *  c-file-style: "k&r"
     251 *  c-basic-offset: 4
     252 *  tab-width: 4
     253 *  indent-tabs-mode: t
     254 * End:
     255 */
     256
    257257#endif
  • trunk/synergy/lib/platform/CPMSynergyHook.cpp

    r2752 r2755  
    22 * synergy -- mouse and keyboard sharing utility
    33 * Copyright (C) 2002 Chris Schoeneman
    4  *
     4 * Copyright (C) 2006 Knut St. Osmundsen
     5 *
    56 * This package is free software; you can redistribute it and/or
    67 * modify it under the terms of the GNU General Public License
    78 * found in the file COPYING that should have accompanied this file.
    8  * 
     9 *
    910 * This package is distributed in the hope that it will be useful,
    1011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1314 */
    1415
    15 #include "CSynergyHook.h"
     16#include "CPMSynergyHook.h"
    1617#include "ProtocolTypes.h"
    17 #include <zmouse.h>
    18 
    19 //
    20 // debugging compile flag.  when not zero the server doesn't grab
    21 // the keyboard when the mouse leaves the server screen.  this
    22 // makes it possible to use the debugger (via the keyboard) when
    23 // all user input would normally be caught by the hook procedures.
    24 //
    25 #define NO_GRAB_KEYBOARD 0
    26 
    27 //
    28 // debugging compile flag.  when not zero the server will not
    29 // install low level hooks.
    30 //
    31 #define NO_LOWLEVEL_HOOKS 0
    32 
    33 //
    34 // extra mouse wheel stuff
    35 //
    36 
    37 enum EWheelSupport {
    38         kWheelNone,
    39         kWheelOld,
    40         kWheelWin2000,
    41         kWheelModern
    42 };
    43 
    44 // declare extended mouse hook struct.  useable on win2k
    45 typedef struct tagMOUSEHOOKSTRUCTWin2000 {
    46         MOUSEHOOKSTRUCT mhs;
    47         DWORD mouseData;
    48 } MOUSEHOOKSTRUCTWin2000;
    49 
    50 #if !defined(SM_MOUSEWHEELPRESENT)
    51 #define SM_MOUSEWHEELPRESENT 75
    52 #endif
    53 
    54 // X button stuff
    55 #if !defined(WM_XBUTTONDOWN)
    56 #define WM_XBUTTONDOWN          0x020B
    57 #define WM_XBUTTONUP            0x020C
    58 #define WM_XBUTTONDBLCLK        0x020D
    59 #define WM_NCXBUTTONDOWN        0x00AB
    60 #define WM_NCXBUTTONUP          0x00AC
    61 #define WM_NCXBUTTONDBLCLK      0x00AD
    62 #define MOUSEEVENTF_XDOWN       0x0080
    63 #define MOUSEEVENTF_XUP         0x0100
    64 #define XBUTTON1                        0x0001
    65 #define XBUTTON2                        0x0002
    66 #endif
    67 
    68 
    69 //
    70 // globals
    71 //
    72 
    73 #if defined(_MSC_VER)
    74 #pragma comment(linker, "-section:shared,rws")
    75 #pragma data_seg("shared")
    76 #endif
    77 // all data in this shared section *must* be initialized
    78 
    79 static HINSTANCE                g_hinstance       = NULL;
    80 static DWORD                    g_processID       = 0;
    81 static EWheelSupport    g_wheelSupport    = kWheelNone;
    82 static UINT                             g_wmMouseWheel    = 0;
    83 static DWORD                    g_threadID        = 0;
    84 static HHOOK                    g_keyboard        = NULL;
    85 static HHOOK                    g_mouse           = NULL;
    86 static HHOOK                    g_getMessage      = NULL;
    87 static HHOOK                    g_keyboardLL      = NULL;
    88 static HHOOK                    g_mouseLL         = NULL;
    89 static bool                             g_screenSaver     = false;
    90 static EHookMode                g_mode            = kHOOK_DISABLE;
    91 static UInt32                   g_zoneSides       = 0;
    92 static SInt32                   g_zoneSize        = 0;
    93 static SInt32                   g_xScreen         = 0;
    94 static SInt32                   g_yScreen         = 0;
    95 static SInt32                   g_wScreen         = 0;
    96 static SInt32                   g_hScreen         = 0;
    97 static WPARAM                   g_deadVirtKey     = 0;
    98 static LPARAM                   g_deadLParam      = 0;
    99 static BYTE                             g_deadKeyState[256] = { 0 };
    100 static DWORD                    g_hookThread      = 0;
    101 static DWORD                    g_attachedThread  = 0;
    102 static bool                             g_fakeInput       = false;
    103 
    104 #if defined(_MSC_VER)
    105 #pragma data_seg()
    106 #endif
    107 
    108 // keep linker quiet about floating point stuff.  we don't use any
    109 // floating point operations but our includes may define some
    110 // (unused) floating point values.
    111 #ifndef _DEBUG
     18#include <sys/builtin.h>
     19#include <stdlib.h>
     20#include <unistd.h>
     21
     22//
     23// globals - system wide (defined in .asm)
     24//
    11225extern "C" {
    113 int _fltused=0;
    114 }
    115 #endif
    116 
    117 
    118 //
    119 // internal functions
    120 //
    121 
    122 static
    123 void
    124 detachThread()
    125 {
    126         if (g_attachedThread != 0 && g_hookThread != g_attachedThread) {
    127                 AttachThreadInput(g_hookThread, g_attachedThread, FALSE);
    128                 g_attachedThread = 0;
    129         }
    130 }
    131 
    132 static
    133 bool
    134 attachThreadToForeground()
    135 {
    136         // only attach threads if using low level hooks.  a low level hook
    137         // runs in the thread that installed the hook but we have to make
    138         // changes that require being attached to the target thread (which
    139         // should be the foreground window).  a regular hook runs in the
    140         // thread that just removed the event from its queue so we're
    141         // already in the right thread.
    142         if (g_hookThread != 0) {
    143                 HWND window    = GetForegroundWindow();
    144                 DWORD threadID = GetWindowThreadProcessId(window, NULL);
    145                 // skip if no change
    146                 if (g_attachedThread != threadID) {
    147                         // detach from previous thread
    148                         detachThread();
    149 
    150                         // attach to new thread
    151                         if (threadID != 0 && threadID != g_hookThread) {
    152                                 AttachThreadInput(g_hookThread, threadID, TRUE);
    153                                 g_attachedThread = threadID;
    154                         }
    155                         return true;
    156                 }
    157         }
    158         return false;
    159 }
    160 
    161 #if !NO_GRAB_KEYBOARD
    162 static
    163 WPARAM
    164 makeKeyMsg(UINT virtKey, char c, bool noAltGr)
    165 {
    166         return MAKEWPARAM(MAKEWORD(virtKey & 0xff, (BYTE)c), noAltGr ? 1 : 0);
    167 }
    168 
    169 static
    170 void
    171 keyboardGetState(BYTE keys[256])
    172 {
    173         // we have to use GetAsyncKeyState() rather than GetKeyState() because
    174         // we don't pass through most keys so the event synchronous state
    175         // doesn't get updated.  we do that because certain modifier keys have
    176         // side effects, like alt and the windows key.
    177         SHORT key;
    178         for (int i = 0; i < 256; ++i) {
    179                 key     = GetAsyncKeyState(i);
    180                 keys[i] = (BYTE)((key < 0) ? 0x80u : 0);
    181         }
    182         key = GetKeyState(VK_CAPITAL);
    183         keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1));
    184 }
    185 
    186 static
    187 bool
    188 doKeyboardHookHandler(WPARAM wParam, LPARAM lParam)
    189 {
    190         // check for special events indicating if we should start or stop
    191         // passing events through and not report them to the server.  this
    192         // is used to allow the server to synthesize events locally but
    193         // not pick them up as user events.
    194         if (wParam == SYNERGY_HOOK_FAKE_INPUT_VIRTUAL_KEY &&
    195                 ((lParam >> 16) & 0xffu) == SYNERGY_HOOK_FAKE_INPUT_SCANCODE) {
    196                 // update flag
    197                 g_fakeInput = ((lParam & 0x80000000u) == 0);
    198                 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
    199                                                                 0xff000000u | wParam, lParam);
    200 
    201                 // discard event
    202                 return true;
    203         }
    204 
    205         // if we're expecting fake input then just pass the event through
    206         // and do not forward to the server
    207         if (g_fakeInput) {
    208                 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
    209                                                                 0xfe000000u | wParam, lParam);
    210                 return false;
    211         }
    212 
    213         // VK_RSHIFT may be sent with an extended scan code but right shift
    214         // is not an extended key so we reset that bit.
    215         if (wParam == VK_RSHIFT) {
    216                 lParam &= ~0x01000000u;
    217         }
    218 
    219         // tell server about event
    220         PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, wParam, lParam);
    221 
    222         // ignore dead key release
    223         if (g_deadVirtKey == wParam &&
    224                 (lParam & 0x80000000u) != 0) {
    225                 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
    226                                                 wParam | 0x04000000, lParam);
    227                 return false;
    228         }
    229 
    230         // we need the keyboard state for ToAscii()
    231         BYTE keys[256];
    232         keyboardGetState(keys);
    233 
    234         // ToAscii() maps ctrl+letter to the corresponding control code
    235         // and ctrl+backspace to delete.  we don't want those translations
    236         // so clear the control modifier state.  however, if we want to
    237         // simulate AltGr (which is ctrl+alt) then we must not clear it.
    238         UINT control = keys[VK_CONTROL] | keys[VK_LCONTROL] | keys[VK_RCONTROL];
    239         UINT menu    = keys[VK_MENU] | keys[VK_LMENU] | keys[VK_RMENU];
    240         if ((control & 0x80) == 0 || (menu & 0x80) == 0) {
    241                 keys[VK_LCONTROL] = 0;
    242                 keys[VK_RCONTROL] = 0;
    243                 keys[VK_CONTROL]  = 0;
    244         }
    245         else {
    246                 keys[VK_LCONTROL] = 0x80;
    247                 keys[VK_RCONTROL] = 0x80;
    248                 keys[VK_CONTROL]  = 0x80;
    249                 keys[VK_LMENU]    = 0x80;
    250                 keys[VK_RMENU]    = 0x80;
    251                 keys[VK_MENU]     = 0x80;
    252         }
    253 
    254         // ToAscii() needs to know if a menu is active for some reason.
    255         // we don't know and there doesn't appear to be any way to find
    256         // out.  so we'll just assume a menu is active if the menu key
    257         // is down.
    258         // FIXME -- figure out some way to check if a menu is active
    259         UINT flags = 0;
    260         if ((menu & 0x80) != 0)
    261                 flags |= 1;
    262 
    263         // if we're on the server screen then just pass numpad keys with alt
    264         // key down as-is.  we won't pick up the resulting character but the
    265         // local app will.  if on a client screen then grab keys as usual;
    266         // if the client is a windows system it'll synthesize the expected
    267         // character.  if not then it'll probably just do nothing.
    268         if (g_mode != kHOOK_RELAY_EVENTS) {
    269                 // we don't use virtual keys because we don't know what the
    270                 // state of the numlock key is.  we'll hard code the scan codes
    271                 // instead.  hopefully this works across all keyboards.
    272                 UINT sc = (lParam & 0x01ff0000u) >> 16;
    273                 if (menu &&
    274                         (sc >= 0x47u && sc <= 0x52u && sc != 0x4au && sc != 0x4eu)) {
    275                         return false;
    276                 }
    277         }
    278 
    279         // map the key event to a character.  we have to put the dead
    280         // key back first and this has the side effect of removing it.
    281         if (g_deadVirtKey != 0) {
    282                 WORD c = 0;
    283                 ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
    284                                                                 g_deadKeyState, &c, flags);
    285         }
    286         WORD c        = 0;
    287         UINT scanCode = ((lParam & 0x10ff0000u) >> 16);
    288         int n         = ToAscii(wParam, scanCode, keys, &c, flags);
    289 
    290         // if mapping failed and ctrl and alt are pressed then try again
    291         // with both not pressed.  this handles the case where ctrl and
    292         // alt are being used as individual modifiers rather than AltGr.
    293         // we note that's the case in the message sent back to synergy
    294         // because there's no simple way to deduce it after the fact.
    295         // we have to put the dead key back first, if there was one.
    296         bool noAltGr = false;
    297         if (n == 0 && (control & 0x80) != 0 && (menu & 0x80) != 0) {
    298                 noAltGr = true;
    299                 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
    300                                                         wParam | 0x05000000, lParam);
    301                 if (g_deadVirtKey != 0) {
    302                         ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
    303                                                         g_deadKeyState, &c, flags);
    304                 }
    305                 BYTE keys2[256];
    306                 for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++i) {
    307                         keys2[i] = keys[i];
    308                 }
    309                 keys2[VK_LCONTROL] = 0;
    310                 keys2[VK_RCONTROL] = 0;
    311                 keys2[VK_CONTROL]  = 0;
    312                 keys2[VK_LMENU]    = 0;
    313                 keys2[VK_RMENU]    = 0;
    314                 keys2[VK_MENU]     = 0;
    315                 n = ToAscii(wParam, scanCode, keys2, &c, flags);
    316         }
    317 
    318         PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
    319                                                         wParam | ((c & 0xff) << 8) |
    320                                                         ((n & 0xff) << 16) | 0x06000000,
    321                                                         lParam);
    322         WPARAM charAndVirtKey = 0;
    323         bool clearDeadKey = false;
    324         switch (n) {
    325         default:
    326                 // key is a dead key
    327                 g_deadVirtKey = wParam;
    328                 g_deadLParam  = lParam;
    329                 for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++i) {
    330                         g_deadKeyState[i] = keys[i];
    331                 }
    332                 break;
    333 
    334         case 0:
    335                 // key doesn't map to a character.  this can happen if
    336                 // non-character keys are pressed after a dead key.
    337                 charAndVirtKey = makeKeyMsg(wParam, (char)0, noAltGr);
    338                 break;
    339 
    340         case 1:
    341                 // key maps to a character composed with dead key
    342                 charAndVirtKey = makeKeyMsg(wParam, (char)LOBYTE(c), noAltGr);
    343                 clearDeadKey   = true;
    344                 break;
    345 
    346         case 2: {
    347                 // previous dead key not composed.  send a fake key press
    348                 // and release for the dead key to our window.
    349                 WPARAM deadCharAndVirtKey =
    350                                                         makeKeyMsg(g_deadVirtKey, (char)LOBYTE(c), noAltGr);
    351                 PostThreadMessage(g_threadID, SYNERGY_MSG_KEY,
    352                                                         deadCharAndVirtKey, g_deadLParam & 0x7fffffffu);
    353                 PostThreadMessage(g_threadID, SYNERGY_MSG_KEY,
    354                                                         deadCharAndVirtKey, g_deadLParam | 0x80000000u);
    355 
    356                 // use uncomposed character
    357                 charAndVirtKey = makeKeyMsg(wParam, (char)HIBYTE(c), noAltGr);
    358                 clearDeadKey   = true;
    359                 break;
    360         }
    361         }
    362 
    363         // put back the dead key, if any, for the application to use
    364         if (g_deadVirtKey != 0) {
    365                 ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
    366                                                         g_deadKeyState, &c, flags);
    367         }
    368 
    369         // clear out old dead key state
    370         if (clearDeadKey) {
    371                 g_deadVirtKey = 0;
    372                 g_deadLParam  = 0;
    373         }
    374 
    375         // forward message to our window.  do this whether or not we're
    376         // forwarding events to clients because this'll keep our thread's
    377         // key state table up to date.  that's important for querying
    378         // the scroll lock toggle state.
    379         // XXX -- with hot keys for actions we may only need to do this when
    380         // forwarding.
    381         if (charAndVirtKey != 0) {
    382                 PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG,
    383                                                         charAndVirtKey | 0x07000000, lParam);
    384                 PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, charAndVirtKey, lParam);
    385         }
    386 
    387         if (g_mode == kHOOK_RELAY_EVENTS) {
    388                 // let certain keys pass through
    389                 switch (wParam) {
    390                 case VK_CAPITAL:
    391                 case VK_NUMLOCK:
    392                 case VK_SCROLL:
    393                         // pass event on.  we want to let these through to
    394                         // the window proc because otherwise the keyboard
    395                         // lights may not stay synchronized.
    396                         break;
    397 
    398                 case VK_HANGUL:
    399                         // pass these modifiers if using a low level hook, discard
    400                         // them if not.
    401                         if (g_hookThread == 0) {
    402                                 return true;
    403                         }
    404                         break;
    405 
    406                 default:
    407                         // discard
    408                         return true;
    409                 }
    410         }
    411 
    412         return false;
    413 }
    414 
    415 static
    416 bool
    417 keyboardHookHandler(WPARAM wParam, LPARAM lParam)
    418 {
    419         attachThreadToForeground();
    420         return doKeyboardHookHandler(wParam, lParam);
    421 }
    422 #endif
    423 
    424 static
    425 bool
    426 doMouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
    427 {
    428         switch (wParam) {
    429         case WM_LBUTTONDOWN:
    430         case WM_MBUTTONDOWN:
    431         case WM_RBUTTONDOWN:
    432         case WM_XBUTTONDOWN:
    433         case WM_LBUTTONDBLCLK:
    434         case WM_MBUTTONDBLCLK:
    435         case WM_RBUTTONDBLCLK:
    436         case WM_XBUTTONDBLCLK:
    437         case WM_LBUTTONUP:
    438         case WM_MBUTTONUP:
    439         case WM_RBUTTONUP:
    440         case WM_XBUTTONUP:
    441         case WM_NCLBUTTONDOWN:
    442         case WM_NCMBUTTONDOWN:
    443         case WM_NCRBUTTONDOWN:
    444         case WM_NCXBUTTONDOWN:
    445         case WM_NCLBUTTONDBLCLK:
    446         case WM_NCMBUTTONDBLCLK:
    447         case WM_NCRBUTTONDBLCLK:
    448         case WM_NCXBUTTONDBLCLK:
    449         case WM_NCLBUTTONUP:
    450         case WM_NCMBUTTONUP:
    451         case WM_NCRBUTTONUP:
    452         case WM_NCXBUTTONUP:
    453                 // always relay the event.  eat it if relaying.
    454                 PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_BUTTON, wParam, data);
    455                 return (g_mode == kHOOK_RELAY_EVENTS);
    456 
    457         case WM_MOUSEWHEEL:
    458                 if (g_mode == kHOOK_RELAY_EVENTS) {
    459                         // relay event
    460                         PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_WHEEL, data, 0);
    461                 }
    462                 return (g_mode == kHOOK_RELAY_EVENTS);
    463 
    464         case WM_NCMOUSEMOVE:
    465         case WM_MOUSEMOVE:
    466                 if (g_mode == kHOOK_RELAY_EVENTS) {
    467                         // relay and eat event
    468                         PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_MOVE, x, y);
    469                         return true;
    470                 }
    471                 else if (g_mode == kHOOK_WATCH_JUMP_ZONE) {
    472                         // low level hooks can report bogus mouse positions that are
    473                         // outside of the screen.  jeez.  naturally we end up getting
    474                         // fake motion in the other direction to get the position back
    475                         // on the screen, which plays havoc with switch on double tap.
    476                         // CServer deals with that.  we'll clamp positions onto the
    477                         // screen.  also, if we discard events for positions outside
    478                         // of the screen then the mouse appears to get a bit jerky
    479                         // near the edge.  we can either accept that or pass the bogus
    480                         // events.  we'll try passing the events.
    481                         bool bogus = false;
    482                         if (x < g_xScreen) {
    483                                 x     = g_xScreen;
    484                                 bogus = true;
    485                         }
    486                         else if (x >= g_xScreen + g_wScreen) {
    487                                 x     = g_xScreen + g_wScreen - 1;
    488                                 bogus = true;
    489                         }
    490                         if (y < g_yScreen) {
    491                                 y     = g_yScreen;
    492                                 bogus = true;
    493                         }
    494                         else if (y >= g_yScreen + g_hScreen) {
    495                                 y     = g_yScreen + g_hScreen - 1;
    496                                 bogus = true;
    497                         }
    498 
    499                         // check for mouse inside jump zone
    500                         bool inside = false;
    501                         if (!inside && (g_zoneSides & kLeftMask) != 0) {
    502                                 inside = (x < g_xScreen + g_zoneSize);
    503                         }
    504                         if (!inside && (g_zoneSides & kRightMask) != 0) {
    505                                 inside = (x >= g_xScreen + g_wScreen - g_zoneSize);
    506                         }
    507                         if (!inside && (g_zoneSides & kTopMask) != 0) {
    508                                 inside = (y < g_yScreen + g_zoneSize);
    509                         }
    510                         if (!inside && (g_zoneSides & kBottomMask) != 0) {
    511                                 inside = (y >= g_yScreen + g_hScreen - g_zoneSize);
    512                         }
    513 
    514                         // relay the event
    515                         PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_MOVE, x, y);
    516 
    517                         // if inside and not bogus then eat the event
    518                         return inside && !bogus;
    519                 }
    520         }
    521 
    522         // pass the event
    523         return false;
    524 }
    525 
    526 static
    527 bool
    528 mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
    529 {
    530 //      attachThreadToForeground();
    531         return doMouseHookHandler(wParam, x, y, data);
    532 }
    533 
    534 #if !NO_GRAB_KEYBOARD
    535 static
    536 LRESULT CALLBACK
    537 keyboardHook(int code, WPARAM wParam, LPARAM lParam)
    538 {
    539         if (code >= 0) {
    540                 // handle the message
    541                 if (keyboardHookHandler(wParam, lParam)) {
    542                         return 1;
    543                 }
    544         }
    545 
    546         return CallNextHookEx(g_keyboard, code, wParam, lParam);
    547 }
    548 #endif
    549 
    550 static
    551 LRESULT CALLBACK
    552 mouseHook(int code, WPARAM wParam, LPARAM lParam)
    553 {
    554         if (code >= 0) {
    555                 // decode message
    556                 const MOUSEHOOKSTRUCT* info = (const MOUSEHOOKSTRUCT*)lParam;
    557                 SInt32 x = (SInt32)info->pt.x;
    558                 SInt32 y = (SInt32)info->pt.y;
    559                 SInt32 w = 0;
    560                 if (wParam == WM_MOUSEWHEEL) {
    561                         // win2k and other systems supporting WM_MOUSEWHEEL in
    562                         // the mouse hook are gratuitously different (and poorly
    563                         // documented).  if a low-level mouse hook is in place
    564                         // it should capture these events so we'll never see
    565                         // them.
    566                         switch (g_wheelSupport) {
    567                         case kWheelModern:
    568                                 w = static_cast<SInt16>(LOWORD(info->dwExtraInfo));
    569                                 break;
    570 
    571                         case kWheelWin2000: {
    572                                 const MOUSEHOOKSTRUCTWin2000* info2k =
    573                                                 (const MOUSEHOOKSTRUCTWin2000*)lParam;
    574                                 w = static_cast<SInt16>(HIWORD(info2k->mouseData));
    575                                 break;
    576                         }
    577 
    578                         default:
    579                                 break;
    580                         }
    581                 }
    582 
    583                 // handle the message.  note that we don't handle X buttons
    584                 // here.  that's okay because they're only supported on
    585                 // win2k and winxp and up and on those platforms we'll get
    586                 // get the mouse events through the low level hook.
    587                 if (mouseHookHandler(wParam, x, y, w)) {
    588                         return 1;
    589                 }
    590         }
    591 
    592         return CallNextHookEx(g_mouse, code, wParam, lParam);
    593 }
    594 
    595 static
    596 LRESULT CALLBACK
    597 getMessageHook(int code, WPARAM wParam, LPARAM lParam)
    598 {
    599         if (code >= 0) {
    600                 if (g_screenSaver) {
    601                         MSG* msg = reinterpret_cast<MSG*>(lParam);
    602                         if (msg->message == WM_SYSCOMMAND &&
    603                                 msg->wParam  == SC_SCREENSAVE) {
    604                                 // broadcast screen saver started message
    605                                 PostThreadMessage(g_threadID,
    606                                                                 SYNERGY_MSG_SCREEN_SAVER, TRUE, 0);
    607                         }
    608                 }
    609                 if (g_mode == kHOOK_RELAY_EVENTS) {
    610                         MSG* msg = reinterpret_cast<MSG*>(lParam);
    611                         if (g_wheelSupport == kWheelOld && msg->message == g_wmMouseWheel) {
    612                                 // post message to our window
    613                                 PostThreadMessage(g_threadID,
    614                                                                 SYNERGY_MSG_MOUSE_WHEEL,
    615                                                                 static_cast<SInt16>(msg->wParam & 0xffffu), 0);
    616 
    617                                 // zero out the delta in the message so it's (hopefully)
    618                                 // ignored
    619                                 msg->wParam = 0;
    620                         }
    621                 }
    622         }
    623 
    624         return CallNextHookEx(g_getMessage, code, wParam, lParam);
    625 }
    626 
    627 #if (_WIN32_WINNT >= 0x0400) && defined(_MSC_VER) && !NO_LOWLEVEL_HOOKS
    628 
    629 //
    630 // low-level keyboard hook -- this allows us to capture and handle
    631 // alt+tab, alt+esc, ctrl+esc, and windows key hot keys.  on the down
    632 // side, key repeats are not reported to us.
    633 //
    634 
    635 #if !NO_GRAB_KEYBOARD
    636 static
    637 LRESULT CALLBACK
    638 keyboardLLHook(int code, WPARAM wParam, LPARAM lParam)
    639 {
    640         if (code >= 0) {
    641                 // decode the message
    642                 KBDLLHOOKSTRUCT* info = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
    643                 WPARAM wParam = info->vkCode;
    644                 LPARAM lParam = 1;                                                      // repeat code
    645                 lParam      |= (info->scanCode << 16);          // scan code
    646                 if (info->flags & LLKHF_EXTENDED) {
    647                         lParam  |= (1lu << 24);                                 // extended key
    648                 }
    649                 if (info->flags & LLKHF_ALTDOWN) {
    650                         lParam  |= (1lu << 29);                                 // context code
    651                 }
    652                 if (info->flags & LLKHF_UP) {
    653                         lParam  |= (1lu << 31);                                 // transition
    654                 }
    655                 // FIXME -- bit 30 should be set if key was already down but
    656                 // we don't know that info.  as a result we'll never generate
    657                 // key repeat events.
    658 
    659                 // handle the message
    660                 if (keyboardHookHandler(wParam, lParam)) {
    661                         return 1;
    662                 }
    663         }
    664 
    665         return CallNextHookEx(g_keyboardLL, code, wParam, lParam);
    666 }
    667 #endif
    668 
    669 //
    670 // low-level mouse hook -- this allows us to capture and handle mouse
    671 // events very early.  the earlier the better.
    672 //
    673 
    674 static
    675 LRESULT CALLBACK
    676 mouseLLHook(int code, WPARAM wParam, LPARAM lParam)
    677 {
    678         if (code >= 0) {
    679                 // decode the message
    680                 MSLLHOOKSTRUCT* info = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
    681                 SInt32 x = static_cast<SInt32>(info->pt.x);
    682                 SInt32 y = static_cast<SInt32>(info->pt.y);
    683                 SInt32 w = static_cast<SInt16>(HIWORD(info->mouseData));
    684 
    685                 // handle the message
    686                 if (mouseHookHandler(wParam, x, y, w)) {
    687                         return 1;
    688                 }
    689         }
    690 
    691         return CallNextHookEx(g_mouseLL, code, wParam, lParam);
    692 }
    693 
    694 #endif
    695 
    696 static
    697 EWheelSupport
    698 getWheelSupport()
    699 {
    700         // get operating system
    701         OSVERSIONINFO info;
    702         info.dwOSVersionInfoSize = sizeof(info);
    703         if (!GetVersionEx(&info)) {
    704                 return kWheelNone;
    705         }
    706 
    707         // see if modern wheel is present
    708         if (GetSystemMetrics(SM_MOUSEWHEELPRESENT)) {
    709                 // note if running on win2k
    710                 if (info.dwPlatformId   == VER_PLATFORM_WIN32_NT &&
    711                         info.dwMajorVersion == 5 &&
    712                         info.dwMinorVersion == 0) {
    713                         return kWheelWin2000;
    714                 }
    715                 return kWheelModern;
    716         }
    717 
    718         // not modern.  see if we've got old-style support.
    719 #if defined(MSH_WHEELSUPPORT)
    720         UINT wheelSupportMsg    = RegisterWindowMessage(MSH_WHEELSUPPORT);
    721         HWND wheelSupportWindow = FindWindow(MSH_WHEELMODULE_CLASS,
    722                                                                                 MSH_WHEELMODULE_TITLE);
    723         if (wheelSupportWindow != NULL && wheelSupportMsg != 0) {
    724                 if (SendMessage(wheelSupportWindow, wheelSupportMsg, 0, 0) != 0) {
    725                         g_wmMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
    726                         if (g_wmMouseWheel != 0) {
    727                                 return kWheelOld;
    728                         }
    729                 }
    730         }
    731 #endif
    732 
    733         // assume modern.  we don't do anything special in this case
    734         // except respond to WM_MOUSEWHEEL messages.  GetSystemMetrics()
    735         // can apparently return FALSE even if a mouse wheel is present
    736         // though i'm not sure exactly when it does that (WinME returns
    737         // FALSE for my logitech USB trackball).
    738         return kWheelModern;
     26/** @name The synergy server/client thread
     27 * @{ */
     28extern HMQ                  g_hmqSynergy;
     29extern int                  g_pidSynergy;
     30extern int                  g_tidSynergy;
     31/** @} */
     32
     33/** The current mode.*/
     34extern EHookMode volatile   g_enmMode;
     35
     36/** Which sides do we have warp zones on. */
     37extern UInt32               g_zoneSides;
     38/** The warp zone size in pixels. */
     39extern SInt32               g_zoneSize;
     40/** @name The screen size.
     41 * @{ */
     42extern SInt32               g_xScreen;
     43extern SInt32               g_yScreen;
     44extern SInt32               g_cxScreen;
     45extern SInt32               g_cyScreen;
     46/** @} */
     47
     48/** Set if the hook is installed. */
     49extern bool                 g_fInputHookInstalled;
     50/** Set if we're faking input. */
     51extern bool                 g_fFakingInput;
     52
     53} /* extern "C" */
     54
     55
     56//
     57// Globals - per process.
     58//
     59
     60/** The handle of the hook dll. */
     61static HMODULE  g_hmod = NULLHANDLE;
     62/** The pid of the current process. */
     63static int      g_pid = 0;
     64
     65
     66/**
     67 * Deal with keyboard messages.
     68 *
     69 * @param pQmsg     The WM_CHAR message.
     70 */
     71static bool InputHookKeyboardMsg(PQMSG pQmsg)
     72{
     73    /*
     74     * Check for special events indicating if we should start or stop
     75     * passing events through and not report them to the server.
     76     *
     77     * This is used to allow the server to synthesize events locally but
     78     * not pick them up as user events.
     79     */
     80    if (pQmsg->mp1 == SYNERGY_PM_HOOK_FAKE_INPUT_MP1_FIXED) {
     81        if (pQmsg->mp2 == SYNERGY_PM_HOOK_FAKE_INPUT_MP2_SET) {
     82            g_fFakingInput = true;
     83            return true;
     84        }
     85        if (pQmsg->mp2 == SYNERGY_PM_HOOK_FAKE_INPUT_MP2_CLEAR) {
     86            g_fFakingInput = false;
     87            return true;
     88        }
     89    }
     90
     91    /*
     92     * If we're expecting fake input then just pass the event through
     93     * and do not forward to the server
     94     */
     95    if (g_fFakingInput)
     96        return false;
     97
     98    /*
     99     * Send the key to the server without any more work.
     100     * This is probably to simplified, but it'll have to do for now because I'm lazy.
     101     */
     102    WinPostQueueMsg(g_hmqSynergy, SYNERGY_PM_MSG_KEY, pQmsg->mp1, pQmsg->mp2);
     103    return true;
     104}
     105
     106
     107/**
     108 * Checks if the specified mouse position is in a jump zone.
     109 *
     110 * @returns true if we're in the jump zone, false if we aren't
     111 * @param   x   X coordinate.
     112 * @param   y   Y coordinate. (1st quadrant)
     113 */
     114static bool isInJumpZone(SInt32 x, SInt32 y)
     115{
     116    /* any jump zones at all? */
     117    if (g_zoneSides == 0)
     118        return false;
     119
     120    /*
     121     * Normalize the coordinates.
     122     */
     123    bool fBogus = false;
     124    if (x < g_xScreen) {
     125        x     = g_xScreen;
     126        fBogus = true;
     127    } else if (x >= g_xScreen + g_cxScreen) {
     128        x      = g_xScreen + g_cxScreen - 1;
     129        fBogus = true;
     130    }
     131
     132    if (y < g_yScreen) {
     133        y      = g_yScreen;
     134        fBogus = true;
     135    } else if (y >= g_yScreen + g_cyScreen) {
     136        y      = g_yScreen + g_cyScreen - 1;
     137        fBogus = true;
     138    }
     139
     140    /*
     141     * check if the mouse is in any of the jump zones.
     142     */
     143    bool fJump = false;
     144    if (g_zoneSides & kLeftMask)
     145        fJump |= (unsigned)x - (unsigned)g_xScreen < (unsigned)g_zoneSize;
     146    if (g_zoneSides & kRightMask)
     147        fJump |= (unsigned)(g_xScreen + g_cxScreen) - (unsigned)x < (unsigned)g_zoneSize;
     148    if (g_zoneSides & kTopMask)
     149        fJump |= (unsigned)(g_yScreen + g_cyScreen) - (unsigned)y < (unsigned)g_zoneSize;
     150    if (g_zoneSides & kBottomMask)
     151        fJump |= (unsigned)y - (unsigned)(g_yScreen) < (unsigned)g_zoneSize;
     152
     153    return fJump && !fBogus;
     154}
     155
     156
     157/**
     158 * The input hook procedure (any context).
     159 *
     160 * @returns Processed indicator; TRUE if processed and should be discarded, FALSE if should be passed on.
     161 *
     162 * @param   hab     The anchor block of the current thread.
     163 * @param   pQmsg   The message structure containing the message we're called for.
     164 * @param   fs      The removal options (PM_REMOVE / PM_NOREMOVE).
     165 */
     166BOOL EXPENTRY InputHook(HAB hab, PQMSG pQmsg, ULONG fs)
     167{
     168    /*
     169     * Get hook mode and check if it's enabled.
     170     */
     171    const EHookMode enmMode = g_enmMode;
     172    if (enmMode == kHOOK_DISABLE)
     173        return FALSE;
     174
     175
     176    switch (pQmsg->msg) {
     177        /*
     178         * Keyboard message.
     179         */
     180        case WM_CHAR:
     181            if (enmMode == kHOOK_RELAY_EVENTS)
     182                return InputHookKeyboardMsg(pQmsg);
     183            break;
     184
     185        /*
     186         * Mouse message.
     187         */
     188        case WM_MOUSEMOVE:
     189            if (    enmMode == kHOOK_RELAY_EVENTS
     190                ||  enmMode == kHOOK_WATCH_JUMP_ZONE) {
     191                WinPostQueueMsg(g_hmqSynergy, SYNERGY_PM_MSG_MOUSE_MOVE, MPFROM2SHORT(pQmsg->msg, 0), MPFROM2SHORT(pQmsg->ptl.x, pQmsg->ptl.y));
     192                return enmMode == kHOOK_RELAY_EVENTS
     193                    || isInJumpZone(pQmsg->ptl.x, pQmsg->ptl.y);
     194            }
     195            break;
     196
     197        /*
     198         * Mouse click message.
     199         */
     200        case WM_BUTTON1DOWN:
     201        case WM_BUTTON1UP:
     202        case WM_BUTTON1DBLCLK:
     203        case WM_BUTTON2DOWN:
     204        case WM_BUTTON2UP:
     205        case WM_BUTTON2DBLCLK:
     206        case WM_BUTTON3DOWN:
     207        case WM_BUTTON3UP:
     208        case WM_BUTTON3DBLCLK:
     209            if (    enmMode == kHOOK_RELAY_EVENTS
     210                ||  enmMode == kHOOK_WATCH_JUMP_ZONE) {
     211                WinPostQueueMsg(g_hmqSynergy, SYNERGY_PM_MSG_MOUSE_BUTTON, MPFROM2SHORT(pQmsg->msg, 0), MPFROM2SHORT(pQmsg->ptl.x, pQmsg->ptl.y));
     212                return enmMode == kHOOK_RELAY_EVENTS;
     213            }
     214            break;
     215
     216        /*
     217         * If I understand it correctly these messages are created
     218         * from the ones above and should be discarded. (If I'm wrong,
     219         * we'll not be able to drag stuff or open the window list.)
     220         */
     221        case WM_CHORD:
     222        case WM_BUTTON1MOTIONSTART:
     223        case WM_BUTTON1MOTIONEND:
     224        case WM_BUTTON1CLICK:
     225        case WM_BUTTON2MOTIONSTART:
     226        case WM_BUTTON2MOTIONEND:
     227        case WM_BUTTON2CLICK:
     228        case WM_BUTTON3MOTIONSTART:
     229        case WM_BUTTON3MOTIONEND:
     230        case WM_BUTTON3CLICK:
     231            if (enmMode == kHOOK_RELAY_EVENTS) {
     232                return true;
     233            }
     234            break;
     235
     236        default:
     237            // log these.
     238            break;
     239    }
     240
     241    /* don't eat it. */
     242    return false;
    739243}
    740244
     
    744248//
    745249
    746 BOOL WINAPI
    747 DllMain(HINSTANCE instance, DWORD reason, LPVOID)
    748 {
    749         if (reason == DLL_PROCESS_ATTACH) {
    750                 DisableThreadLibraryCalls(instance);
    751                 if (g_processID == 0) {
    752                         g_hinstance = instance;
    753                         g_processID = GetCurrentProcessId();
    754                 }
    755         }
    756         else if (reason == DLL_PROCESS_DETACH) {
    757                 if (g_processID == GetCurrentProcessId()) {
    758                         uninstall();
    759                         uninstallScreenSaver();
    760                         g_processID = 0;
    761                         g_hinstance = NULL;
    762                 }
    763         }
    764         return TRUE;
    765 }
    766 
    767 extern "C" {
    768 
    769 int
    770 init(DWORD threadID)
    771 {
    772         assert(g_hinstance != NULL);
    773 
    774         // try to open process that last called init() to see if it's
    775         // still running or if it died without cleaning up.
    776         if (g_processID != 0 && g_processID != GetCurrentProcessId()) {
    777                 HANDLE process = OpenProcess(STANDARD_RIGHTS_REQUIRED,
    778                                                                 FALSE, g_processID);
    779                 if (process != NULL) {
    780                         // old process (probably) still exists so refuse to
    781                         // reinitialize this DLL (and thus steal it from the
    782                         // old process).
    783                         CloseHandle(process);
    784                         return 0;
    785                 }
    786 
    787                 // clean up after old process.  the system should've already
    788                 // removed the hooks so we just need to reset our state.
    789                 g_hinstance       = GetModuleHandle("synrgyhk");
    790                 g_processID       = GetCurrentProcessId();
    791                 g_wheelSupport    = kWheelNone;
    792                 g_threadID        = 0;
    793                 g_keyboard        = NULL;
    794                 g_mouse           = NULL;
    795                 g_getMessage      = NULL;
    796                 g_keyboardLL      = NULL;
    797                 g_mouseLL         = NULL;
    798                 g_screenSaver     = false;
    799         }
    800 
    801         // save thread id.  we'll post messages to this thread's
    802         // message queue.
    803         g_threadID  = threadID;
    804 
    805         // set defaults
    806         g_mode      = kHOOK_DISABLE;
    807         g_zoneSides = 0;
    808         g_zoneSize  = 0;
    809         g_xScreen   = 0;
    810         g_yScreen   = 0;
    811         g_wScreen   = 0;
    812         g_hScreen   = 0;
    813 
    814         return 1;
    815 }
    816 
    817 int
    818 cleanup(void)
    819 {
    820         assert(g_hinstance != NULL);
    821 
    822         if (g_processID == GetCurrentProcessId()) {
    823                 g_threadID = 0;
    824         }
    825 
    826         return 1;
    827 }
    828 
    829 EHookResult
    830 install()
    831 {
    832         assert(g_hinstance  != NULL);
    833         assert(g_keyboard   == NULL);
    834         assert(g_mouse      == NULL);
    835         assert(g_getMessage == NULL || g_screenSaver);
    836 
    837         // must be initialized
    838         if (g_threadID == 0) {
    839                 return kHOOK_FAILED;
    840         }
    841 
    842         // discard old dead keys
    843         g_deadVirtKey = 0;
    844         g_deadLParam  = 0;
    845 
    846         // reset fake input flag
    847         g_fakeInput = false;
    848 
    849         // check for mouse wheel support
    850         g_wheelSupport = getWheelSupport();
    851 
    852         // install GetMessage hook (unless already installed)
    853         if (g_wheelSupport == kWheelOld && g_getMessage == NULL) {
    854                 g_getMessage = SetWindowsHookEx(WH_GETMESSAGE,
    855                                                                 &getMessageHook,
    856                                                                 g_hinstance,
    857                                                                 0);
    858         }
    859 
    860         // install low-level hooks.  we require that they both get installed.
    861 #if (_WIN32_WINNT >= 0x0400) && defined(_MSC_VER) && !NO_LOWLEVEL_HOOKS
    862         g_mouseLL = SetWindowsHookEx(WH_MOUSE_LL,
    863                                                                 &mouseLLHook,
    864                                                                 g_hinstance,
    865                                                                 0);
    866 #if !NO_GRAB_KEYBOARD
    867         g_keyboardLL = SetWindowsHookEx(WH_KEYBOARD_LL,
    868                                                                 &keyboardLLHook,
    869                                                                 g_hinstance,
    870                                                                 0);
    871         if (g_mouseLL == NULL || g_keyboardLL == NULL) {
    872                 if (g_keyboardLL != NULL) {
    873                         UnhookWindowsHookEx(g_keyboardLL);
    874                         g_keyboardLL = NULL;
    875                 }
    876                 if (g_mouseLL != NULL) {
    877                         UnhookWindowsHookEx(g_mouseLL);
    878                         g_mouseLL = NULL;
    879                 }
    880         }
    881 #endif
    882 #endif
    883 
    884         // install regular hooks
    885         if (g_mouseLL == NULL) {
    886                 g_mouse = SetWindowsHookEx(WH_MOUSE,
    887                                                                 &mouseHook,
    888                                                                 g_hinstance,
    889                                                                 0);
    890         }
    891 #if !NO_GRAB_KEYBOARD
    892         if (g_keyboardLL == NULL) {
    893                 g_keyboard = SetWindowsHookEx(WH_KEYBOARD,
    894                                                                 &keyboardHook,
    895                                                                 g_hinstance,
    896                                                                 0);
    897         }
    898 #endif
    899 
    900         // check that we got all the hooks we wanted
    901         if ((g_getMessage == NULL && g_wheelSupport == kWheelOld) ||
    902 #if !NO_GRAB_KEYBOARD
    903                 (g_keyboardLL == NULL && g_keyboard     == NULL) ||
    904 #endif
    905                 (g_mouseLL    == NULL && g_mouse        == NULL)) {
    906                 uninstall();
    907                 return kHOOK_FAILED;
    908         }
    909 
    910         if (g_keyboardLL != NULL || g_mouseLL != NULL) {
    911                 g_hookThread = GetCurrentThreadId();
    912                 return kHOOK_OKAY_LL;
    913         }
    914 
    915         return kHOOK_OKAY;
    916 }
    917 
    918 int
    919 uninstall(void)
    920 {
    921         assert(g_hinstance != NULL);
    922 
    923         // discard old dead keys
    924         g_deadVirtKey = 0;
    925         g_deadLParam  = 0;
    926 
    927         // detach from thread
    928         detachThread();
    929 
    930         // uninstall hooks
    931         if (g_keyboardLL != NULL) {
    932                 UnhookWindowsHookEx(g_keyboardLL);
    933                 g_keyboardLL = NULL;
    934         }
    935         if (g_mouseLL != NULL) {
    936                 UnhookWindowsHookEx(g_mouseLL);
    937                 g_mouseLL = NULL;
    938         }
    939         if (g_keyboard != NULL) {
    940                 UnhookWindowsHookEx(g_keyboard);
    941                 g_keyboard = NULL;
    942         }
    943         if (g_mouse != NULL) {
    944                 UnhookWindowsHookEx(g_mouse);
    945                 g_mouse = NULL;
    946         }
    947         if (g_getMessage != NULL && !g_screenSaver) {
    948                 UnhookWindowsHookEx(g_getMessage);
    949                 g_getMessage = NULL;
    950         }
    951         g_wheelSupport = kWheelNone;
    952 
    953         return 1;
    954 }
    955 
    956 int
    957 installScreenSaver(void)
    958 {
    959         assert(g_hinstance != NULL);
    960 
    961         // must be initialized
    962         if (g_threadID == 0) {
    963                 return 0;
    964         }
    965 
    966         // generate screen saver messages
    967         g_screenSaver = true;
    968 
    969         // install hook unless it's already installed
    970         if (g_getMessage == NULL) {
    971                 g_getMessage = SetWindowsHookEx(WH_GETMESSAGE,
    972                                                                 &getMessageHook,
    973                                                                 g_hinstance,
    974                                                                 0);
    975         }
    976 
    977         return (g_getMessage != NULL) ? 1 : 0;
    978 }
    979 
    980 int
    981 uninstallScreenSaver(void)
    982 {
    983         assert(g_hinstance != NULL);
    984 
    985         // uninstall hook unless the mouse wheel hook is installed
    986         if (g_getMessage != NULL && g_wheelSupport != kWheelOld) {
    987                 UnhookWindowsHookEx(g_getMessage);
    988                 g_getMessage = NULL;
    989         }
    990 
    991         // screen saver hook is no longer installed
    992         g_screenSaver = false;
    993 
    994         return 1;
    995 }
    996 
    997 void
    998 setSides(UInt32 sides)
    999 {
    1000         g_zoneSides = sides;
    1001 }
    1002 
    1003 void
    1004 setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h, SInt32 jumpZoneSize)
    1005 {
    1006         g_zoneSize = jumpZoneSize;
    1007         g_xScreen  = x;
    1008         g_yScreen  = y;
    1009         g_wScreen  = w;
    1010         g_hScreen  = h;
    1011 }
    1012 
    1013 void
    1014 setMode(EHookMode mode)
    1015 {
    1016         if (mode == g_mode) {
    1017                 // no change
    1018                 return;
    1019         }
    1020         g_mode = mode;
    1021 }
    1022 
    1023 }
     250/**
     251 * The DLL init/term function.
     252 */
     253ULONG _System _DLL_InitTerm(HMODULE hmod, ULONG ulReason)
     254{
     255    switch (ulReason) {
     256    /* init */
     257    case 0:
     258        g_hmod = hmod;
     259        g_pid = getpid();
     260        break;
     261
     262    /* term */
     263    case 1:
     264        g_pid = 0;
     265        g_hmod = NULLHANDLE;
     266        break;
     267
     268    default:
     269        break;
     270    }
     271    return TRUE;
     272}
     273
     274
     275
     276/**
     277 * Initialize the hook dll (shared data mainly) in the synergy context.
     278 *
     279 * @returns success indicator (true/false)
     280 * @param   hmqSynergy
     281 * @param   tidSynergy
     282 * @param   pidSynergy
     283 */
     284CSYNERGYHOOK_API bool init(HMQ hmqSynergy, int tidSynergy, int pidSynergy)
     285{
     286    /*
     287     * Check that there isn't any synergy instance already running.
     288     * If the verification fails, we will take the place dead synergy instance.
     289     */
     290    if (   g_pidSynergy
     291        && g_tidSynergy
     292        && DosVerifyPidTid(g_pidSynergy, g_tidSynergy) == NO_ERROR)
     293        return false;
     294
     295    /*
     296     * Initialize the globals.
     297     */
     298    g_hmqSynergy = hmqSynergy;
     299    g_pidSynergy = pidSynergy;
     300    g_tidSynergy = tidSynergy;
     301
     302    /* only do this if the hook is inactive. */
     303    if (g_enmMode == kHOOK_DISABLE) {
     304        g_enmMode      = kHOOK_DISABLE;
     305        g_zoneSides = 0;
     306        g_zoneSize  = 0;
     307        g_xScreen   = 0;
     308        g_yScreen   = 0;
     309        g_cxScreen  = 0;
     310        g_cyScreen  = 0;
     311    }
     312
     313    return true;
     314}
     315
     316
     317/**
     318 * Cleanup before unloading the dll (synergy context).
     319 *
     320 * @returns success indicator (true/false)
     321 * @param   hab     The anchor block.
     322 */
     323CSYNERGYHOOK_API bool cleanup(HAB hab)
     324{
     325    assert(g_hmod != NULLHANDLE);
     326
     327    /*
     328     * If we're the synergy process or if it's dead, shut down everything.
     329     */
     330    if (    (   g_pidSynergy != getpid()
     331            ||  g_tidSynergy != _gettid())
     332        &&  DosVerifyPidTid(g_pidSynergy, g_tidSynergy) == NO_ERROR)
     333        return false;
     334
     335    /* parnaoia */
     336    uninstall(hab);
     337
     338    g_hmqSynergy = NULLHANDLE;
     339    g_pidSynergy = 0;
     340    g_tidSynergy = 0;
     341    return true;
     342}
     343
     344
     345CSYNERGYHOOK_API EHookResult install(HAB hab)
     346{
     347    // must be initialized
     348    if (g_tidSynergy == 0) {
     349        return kHOOK_FAILED;
     350    }
     351    assert(g_pidSynergy == getpid());
     352    assert(g_tidSynergy == _gettid());
     353
     354    //// discard old dead keys
     355    //g_deadVirtKey = 0;
     356    //g_deadLParam  = 0;
     357
     358    //// reset fake input flag
     359    //g_fakeInput = false;
     360
     361    /*
     362     * Install the hook.
     363     */
     364    if (    !g_fInputHookInstalled
     365        &&  WinSetHook(hab, NULLHANDLE, HK_INPUT, (PFN)InputHook, g_hmod))
     366        __atomic_xchg((unsigned volatile *)&g_fInputHookInstalled, true);
     367
     368    if (g_fInputHookInstalled)
     369        return kHOOK_OKAY;
     370
     371    uninstall(hab);
     372    return kHOOK_FAILED;
     373}
     374
     375
     376/**
     377 * Uninstall the hooks.
     378 *
     379 * @returns
     380 * @param   hab
     381 */
     382CSYNERGYHOOK_API bool uninstall(HAB hab)
     383{
     384    assert(g_pidSynergy == getpid());
     385    assert(g_tidSynergy == _gettid());
     386
     387    //// discard old dead keys
     388    //g_deadVirtKey = 0;
     389    //g_deadLParam  = 0;
     390
     391    /*
     392     * Release the hooks.
     393     */
     394    if (    g_fInputHookInstalled
     395        &&  WinReleaseHook(hab, NULLHANDLE, HK_INPUT, (PFN)InputHook, g_hmod))
     396        __atomic_xchg((unsigned volatile *)&g_fInputHookInstalled, false);
     397
     398    return !g_fInputHookInstalled;
     399}
     400
     401
     402/**
     403 * Sets the sides we should be watching out for jumps in.
     404 *
     405 * @param   sides   The new sides flags.
     406 */
     407CSYNERGYHOOK_API void setSides(UInt32 sides)
     408{
     409    assert(g_pidSynergy == getpid());
     410    assert(g_tidSynergy == _gettid());
     411    __atomic_xchg((unsigned volatile *)&g_zoneSides, (unsigned)sides);
     412}
     413
     414
     415/**
     416 * Set the jump zone size and screen size.
     417 *
     418 * @param x     The screen x coordinate.
     419 * @param y     The screen y coordinate.
     420 * @param cx    The screen width.
     421 * @param cy    The screen heigth.
     422 * @param jumpZoneSize  The width of the jump zone (pixels).
     423 */
     424CSYNERGYHOOK_API void setZone(SInt32 x, SInt32 y, SInt32 cx, SInt32 cy, SInt32 jumpZoneSize)
     425{
     426    assert(g_pidSynergy == getpid());
     427    assert(g_tidSynergy == _gettid());
     428    __atomic_xchg((unsigned volatile *)&g_zoneSize, (unsigned)jumpZoneSize);
     429    __atomic_xchg((unsigned volatile *)&g_xScreen,  (unsigned)x);
     430    __atomic_xchg((unsigned volatile *)&g_yScreen,  (unsigned)y);
     431    __atomic_xchg((unsigned volatile *)&g_cxScreen, (unsigned)cx);
     432    __atomic_xchg((unsigned volatile *)&g_cyScreen, (unsigned)cy);
     433}
     434
     435
     436/**
     437 * Check the mode of operation.
     438 *
     439 * @param   mode    The new mode.
     440 */
     441CSYNERGYHOOK_API void setMode(EHookMode mode)
     442{
     443    assert(g_pidSynergy == getpid());
     444    assert(g_tidSynergy == _gettid());
     445    if (mode != g_enmMode) {
     446        switch (mode) {
     447        case kHOOK_DISABLE:
     448        case kHOOK_WATCH_JUMP_ZONE:
     449        case kHOOK_RELAY_EVENTS:
     450            __atomic_xchg((unsigned volatile *)&g_enmMode, (unsigned)mode);
     451            break;
     452        default:
     453            __atomic_xchg((unsigned volatile *)&g_enmMode, kHOOK_DISABLE);
     454            break;
     455        }
     456    }
     457}
     458
  • trunk/synergy/lib/platform/CPMSynergyHook.h

    r2752 r2755  
    22 * synergy -- mouse and keyboard sharing utility
    33 * Copyright (C) 2002 Chris Schoeneman
    4  *
     4 * Copyright (C) 2006 Knut St. Osmundsen
     5 *
    56 * This package is free software; you can redistribute it and/or
    67 * modify it under the terms of the GNU General Public License
    78 * found in the file COPYING that should have accompanied this file.
    8  * 
     9 *
    910 * This package is distributed in the hope that it will be useful,
    1011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    2324
    2425#if defined(SYNRGYHK_EXPORTS)
    25 # define CSYNERGYHOOK_API __declspec(dllexport)
     26# define CSYNERGYHOOK_API extern "C" __declspec(dllexport)
    2627#else
    27 # define CSYNERGYHOOK_API __declspec(dllimport)
     28# define CSYNERGYHOOK_API extern "C" __declspec(dllimport)
    2829#endif
    2930
    30 #define SYNERGY_MSG_MARK                        WM_USER + 0x0011        // mark id; <unused>
    31 #define SYNERGY_MSG_KEY                         WM_USER + 0x0012        // vk code; key data
    32 #define SYNERGY_MSG_MOUSE_BUTTON        WM_USER + 0x0013        // button msg; <unused>
    33 #define SYNERGY_MSG_MOUSE_WHEEL         WM_USER + 0x0014        // delta; <unused>
    34 #define SYNERGY_MSG_MOUSE_MOVE          WM_USER + 0x0015        // x; y
    35 #define SYNERGY_MSG_POST_WARP           WM_USER + 0x0016        // <unused>; <unused>
    36 #define SYNERGY_MSG_PRE_WARP            WM_USER + 0x0017        // x; y
    37 #define SYNERGY_MSG_SCREEN_SAVER        WM_USER + 0x0018        // activated; <unused>
    38 #define SYNERGY_MSG_DEBUG                       WM_USER + 0x0019        // data, data
    39 #define SYNERGY_MSG_INPUT_FIRST         SYNERGY_MSG_KEY
    40 #define SYNERGY_MSG_INPUT_LAST          SYNERGY_MSG_PRE_WARP
    41 #define SYNERGY_HOOK_LAST_MSG           SYNERGY_MSG_DEBUG
     31/** @name The messages posted from the input hook on the synergy message queue.
     32 * @{
     33 */
     34#define SYNERGY_PM_MSG_MARK             WM_USER + 20    // mark id; <unused>
     35#define SYNERGY_PM_MSG_KEY              WM_USER + 21    // vk code; key data
     36/**
     37 * mp1.s1: msg
     38 * mp1.s2: 0 reserved.
     39 * mp2.s1: mouse x
     40 * mp2.s2: mouse y
     41 */
     42#define SYNERGY_PM_MSG_MOUSE_BUTTON     WM_USER + 22
     43/** WM_MOUSEMOVE mp1 and mp2. */
     44#define SYNERGY_PM_MSG_MOUSE_MOVE       WM_USER + 23
    4245
    43 #define SYNERGY_HOOK_FAKE_INPUT_VIRTUAL_KEY     VK_CANCEL
    44 #define SYNERGY_HOOK_FAKE_INPUT_SCANCODE        0
     46#define SYNERGY_PM_MSG_POST_WARP        WM_USER + 24    // <unused>; <unused>
     47#define SYNERGY_PM_MSG_PRE_WARP         WM_USER + 25    // x; y
     48#define SYNERGY_PM_MSG_DEBUG            WM_USER + 27    // data, data
    4549
    46 extern "C" {
     50#define SYNERGY_PM_MSG_FIRST            SYNERGY_PM_MSG_MARK     /**< The first message. */
     51#define SYNERGY_PM_MSG_LAST             SYNERGY_PM_MSG_DEBUG    /**< The last message. */
     52#define SYNERGY_PM_MSG_INPUT_FIRST      SYNERGY_PM_MSG_KEY      /**< The first input message. */
     53#define SYNERGY_PM_MSG_INPUT_LAST       SYNERGY_PM_MSG_PRE_WARP /**< The last input message. */
     54/** @} */
     55
     56#define SYNERGY_PM_HOOK_FAKE_INPUT_MP1_FIXED    MPFROM2SHORT(KC_VIRTUALKEY | KC_SCANCODE, 0)
     57#define SYNERGY_PM_HOOK_FAKE_INPUT_MP2_SET      MPFROM2SHORT(0x8f70, 0x708f)
     58#define SYNERGY_PM_HOOK_FAKE_INPUT_MP2_CLEAR    MPFROM2SHORT(0x9f70, 0x708f)
    4759
    4860enum EHookResult {
    49         kHOOK_FAILED,
    50         kHOOK_OKAY,
    51         kHOOK_OKAY_LL
     61    kHOOK_FAILED,
     62    kHOOK_OKAY,
     63    kHOOK_OKAY_LL
    5264};
    5365
    5466enum EHookMode {
    55         kHOOK_DISABLE,
    56         kHOOK_WATCH_JUMP_ZONE,
    57         kHOOK_RELAY_EVENTS
     67    kHOOK_DISABLE,
     68    kHOOK_WATCH_JUMP_ZONE,
     69    kHOOK_RELAY_EVENTS
    5870};
    5971
    60 typedef int                             (*InitFunc)(HMQ hmq, int tid, int pid);
    61 typedef int                             (*CleanupFunc)(void);
    62 typedef EHookResult             (*InstallFunc)(void);
    63 typedef int                             (*UninstallFunc)(void);
    64 typedef int                             (*InstallScreenSaverFunc)(void);
    65 typedef int                             (*UninstallScreenSaverFunc)(void);
    66 typedef void                    (*SetSidesFunc)(UInt32);
    67 typedef void                    (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32);
    68 typedef void                    (*SetModeFunc)(int);
     72typedef bool            (*InitFunc)(HMQ hmq, int tid, int pid);
     73typedef bool            (*CleanupFunc)(HAB hab);
     74typedef EHookResult     (*InstallFunc)(HAB hab);
     75typedef bool            (*UninstallFunc)(HAB hab);
     76typedef void            (*SetSidesFunc)(UInt32);
     77typedef void            (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32);
     78typedef void            (*SetModeFunc)(int);
    6979
    70 CSYNERGYHOOK_API int    init(HMQ hmq, int tid, int pid);
    71 CSYNERGYHOOK_API int    cleanup(void);
    72 CSYNERGYHOOK_API EHookResult    install(void);
    73 CSYNERGYHOOK_API int    uninstall(void);
    74 CSYNERGYHOOK_API int    installScreenSaver(void);
    75 CSYNERGYHOOK_API int    uninstallScreenSaver(void);
    76 CSYNERGYHOOK_API void   setSides(UInt32 sides);
    77 CSYNERGYHOOK_API void   setZone(SInt32 x, SInt32 y, SInt32 cx, SInt32 cy, SInt32 jumpZoneSize);
    78 CSYNERGYHOOK_API void   setMode(EHookMode mode);
    79 
    80 }
     80CSYNERGYHOOK_API bool   init(HMQ hmq, int tid, int pid);
     81CSYNERGYHOOK_API bool   cleanup(HAB hab);
     82CSYNERGYHOOK_API EHookResult install(HAB hab);
     83CSYNERGYHOOK_API bool   uninstall(HAB hab);
     84CSYNERGYHOOK_API void   setSides(UInt32 sides);
     85CSYNERGYHOOK_API void   setZone(SInt32 x, SInt32 y, SInt32 cx, SInt32 cy, SInt32 jumpZoneSize);
     86CSYNERGYHOOK_API void   setMode(EHookMode mode);
    8187
    8288#endif
Note: See TracChangeset for help on using the changeset viewer.