winkeyhook.c revision 9ace9065
105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 2004 Harold L Hunt II All Rights Reserved.
305b261ecSmrg *
405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining
505b261ecSmrg * a copy of this software and associated documentation files (the
605b261ecSmrg *"Software"), to deal in the Software without restriction, including
705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish,
805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to
905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to
1005b261ecSmrg *the following conditions:
1105b261ecSmrg *
1205b261ecSmrg *The above copyright notice and this permission notice shall be
1305b261ecSmrg *included in all copies or substantial portions of the Software.
1405b261ecSmrg *
1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg *Except as contained in this notice, the name of Harold L Hunt II
2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use
2505b261ecSmrg *or other dealings in this Software without prior written authorization
2605b261ecSmrg *from Harold L Hunt II.
2705b261ecSmrg *
2805b261ecSmrg * Authors:	Harold L Hunt II
2905b261ecSmrg */
3005b261ecSmrg
3105b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3205b261ecSmrg#include <xwin-config.h>
3305b261ecSmrg#endif
3405b261ecSmrg#include "win.h"
3505b261ecSmrg
3605b261ecSmrg
379ace9065Smrgstatic HHOOK g_hhookKeyboardLL = NULL;
3805b261ecSmrg
3905b261ecSmrg
4005b261ecSmrg/*
4105b261ecSmrg * Function prototypes
4205b261ecSmrg */
4305b261ecSmrg
4405b261ecSmrgstatic LRESULT CALLBACK
4505b261ecSmrgwinKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam);
4605b261ecSmrg
4705b261ecSmrg
4805b261ecSmrg#ifndef LLKHF_EXTENDED
4905b261ecSmrg# define LLKHF_EXTENDED  0x00000001
5005b261ecSmrg#endif
5105b261ecSmrg#ifndef LLKHF_UP
5205b261ecSmrg# define LLKHF_UP  0x00000080
5305b261ecSmrg#endif
5405b261ecSmrg
5505b261ecSmrg
5605b261ecSmrg/*
5705b261ecSmrg * KeyboardMessageHook
5805b261ecSmrg */
5905b261ecSmrg
6005b261ecSmrgstatic LRESULT CALLBACK
6105b261ecSmrgwinKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam)
6205b261ecSmrg{
6305b261ecSmrg  BOOL			fPassKeystroke = FALSE;
6405b261ecSmrg  BOOL			fPassAltTab = TRUE;
6505b261ecSmrg  PKBDLLHOOKSTRUCT	p = (PKBDLLHOOKSTRUCT) lParam;
6605b261ecSmrg  HWND			hwnd = GetActiveWindow();
6705b261ecSmrg#ifdef XWIN_MULTIWINDOW
6805b261ecSmrg  WindowPtr		pWin = NULL;
6905b261ecSmrg  winPrivWinPtr	        pWinPriv = NULL;
7005b261ecSmrg  winPrivScreenPtr	pScreenPriv = NULL;
7105b261ecSmrg  winScreenInfo		*pScreenInfo = NULL;
7205b261ecSmrg
7305b261ecSmrg  /* Check if the Windows window property for our X window pointer is valid */
7405b261ecSmrg  if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
7505b261ecSmrg    {
7605b261ecSmrg      /* Get a pointer to our window privates */
7705b261ecSmrg      pWinPriv		= winGetWindowPriv(pWin);
7805b261ecSmrg
7905b261ecSmrg      /* Get pointers to our screen privates and screen info */
8005b261ecSmrg      pScreenPriv	= pWinPriv->pScreenPriv;
8105b261ecSmrg      pScreenInfo	= pScreenPriv->pScreenInfo;
8205b261ecSmrg
8305b261ecSmrg      if (pScreenInfo->fMultiWindow)
8405b261ecSmrg          fPassAltTab = FALSE;
8505b261ecSmrg    }
8605b261ecSmrg#endif
8705b261ecSmrg
8805b261ecSmrg  /* Pass keystrokes on to our main message loop */
8905b261ecSmrg  if (iCode == HC_ACTION)
9005b261ecSmrg    {
919ace9065Smrg      winDebug("winKeyboardMessageHook: vkCode: %08x scanCode: %08x\n", p->vkCode, p->scanCode);
9205b261ecSmrg
9305b261ecSmrg      switch (wParam)
9405b261ecSmrg	{
9505b261ecSmrg	case WM_KEYDOWN:  case WM_SYSKEYDOWN:
9605b261ecSmrg	case WM_KEYUP:    case WM_SYSKEYUP:
9705b261ecSmrg	  fPassKeystroke =
9805b261ecSmrg	    (fPassAltTab &&
9905b261ecSmrg                (p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0))
10005b261ecSmrg	    || (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)
10105b261ecSmrg	    ;
10205b261ecSmrg	  break;
10305b261ecSmrg	}
10405b261ecSmrg    }
10505b261ecSmrg
10605b261ecSmrg  /*
10705b261ecSmrg   * Pass message on to our main message loop.
10805b261ecSmrg   * We process this immediately with SendMessage so that the keystroke
10905b261ecSmrg   * appears in, hopefully, the correct order.
11005b261ecSmrg   */
11105b261ecSmrg  if (fPassKeystroke)
11205b261ecSmrg    {
11305b261ecSmrg      LPARAM		lParamKey = 0x0;
11405b261ecSmrg
11505b261ecSmrg      /* Construct the lParam from KBDLLHOOKSTRUCT */
11605b261ecSmrg      lParamKey = lParamKey | (0x0000FFFF & 0x00000001); /* Repeat count */
11705b261ecSmrg      lParamKey = lParamKey | (0x00FF0000 & (p->scanCode << 16));
11805b261ecSmrg      lParamKey = lParamKey
11905b261ecSmrg	| (0x01000000 & ((p->flags & LLKHF_EXTENDED) << 23));
12005b261ecSmrg      lParamKey = lParamKey
12105b261ecSmrg	| (0x20000000
12205b261ecSmrg	   & ((p->flags & LLKHF_ALTDOWN) << 24));
12305b261ecSmrg      lParamKey = lParamKey | (0x80000000 & ((p->flags & LLKHF_UP) << 24));
12405b261ecSmrg
12505b261ecSmrg      /* Send message to our main window that has the keyboard focus */
12605b261ecSmrg      PostMessage (hwnd,
12705b261ecSmrg		   (UINT) wParam,
12805b261ecSmrg		   (WPARAM) p->vkCode,
12905b261ecSmrg		   lParamKey);
13005b261ecSmrg
13105b261ecSmrg      return 1;
13205b261ecSmrg    }
13305b261ecSmrg
13405b261ecSmrg  /* Call next hook */
13505b261ecSmrg  return CallNextHookEx (NULL, iCode, wParam, lParam);
13605b261ecSmrg}
13705b261ecSmrg
13805b261ecSmrg
13905b261ecSmrg/*
14005b261ecSmrg * Attempt to install the keyboard hook, return FALSE if it was not installed
14105b261ecSmrg */
14205b261ecSmrg
14305b261ecSmrgBool
1446747b715SmrgwinInstallKeyboardHookLL (void)
14505b261ecSmrg{
14605b261ecSmrg  OSVERSIONINFO		osvi = {0};
14705b261ecSmrg
14805b261ecSmrg  /* Get operating system version information */
14905b261ecSmrg  osvi.dwOSVersionInfoSize = sizeof (osvi);
15005b261ecSmrg  GetVersionEx (&osvi);
15105b261ecSmrg
15205b261ecSmrg  /* Branch on platform ID */
15305b261ecSmrg  switch (osvi.dwPlatformId)
15405b261ecSmrg    {
15505b261ecSmrg    case VER_PLATFORM_WIN32_NT:
15605b261ecSmrg      /* Low-level is supported on NT 4.0 SP3+ only */
15705b261ecSmrg      /* TODO: Return FALSE on NT 4.0 with no SP, SP1, or SP2 */
15805b261ecSmrg      break;
15905b261ecSmrg
16005b261ecSmrg    case VER_PLATFORM_WIN32_WINDOWS:
16105b261ecSmrg      /* Low-level hook is not supported on non-NT */
16205b261ecSmrg      return FALSE;
16305b261ecSmrg    }
16405b261ecSmrg
16505b261ecSmrg  /* Install the hook only once */
16605b261ecSmrg  if (!g_hhookKeyboardLL)
16705b261ecSmrg    g_hhookKeyboardLL = SetWindowsHookEx (WH_KEYBOARD_LL,
16805b261ecSmrg					  winKeyboardMessageHookLL,
16905b261ecSmrg					  g_hInstance,
17005b261ecSmrg					  0);
17105b261ecSmrg
17205b261ecSmrg  return TRUE;
17305b261ecSmrg}
17405b261ecSmrg
17505b261ecSmrg
17605b261ecSmrg/*
17705b261ecSmrg * Remove the keyboard hook if it is installed
17805b261ecSmrg */
17905b261ecSmrg
18005b261ecSmrgvoid
1816747b715SmrgwinRemoveKeyboardHookLL (void)
18205b261ecSmrg{
18305b261ecSmrg  if (g_hhookKeyboardLL)
18405b261ecSmrg    UnhookWindowsHookEx (g_hhookKeyboardLL);
18505b261ecSmrg  g_hhookKeyboardLL = NULL;
18605b261ecSmrg}
187