home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************\
- * PC2.c *
- * Copyright (C) by Stangl Roman, 1993, 1994, 1995 *
- * This Code may be freely distributed, provided the Copyright isn't *
- * removed. *
- * *
- * Pc2Hook.c Hook the input queue to filter certain messages. *
- * *
- \***********************************************************************/
-
- static char RCSID[]="@(#) $Header: Pc2Hook.c Version 1.90 05,1995 $ (LBL)";
-
- #define _FILE_ "PC/2 - PC2Hook.c V1.90"
-
- #include "PC2.h" /* User include files */
- #include "Error.h"
-
- /* Reroute message from original desktionation
- to NULLHANDLE and return TRUE no to pass message
- to next hook in chain */
- #define REROUTEMSGTONULL() pqmsg->hwnd=NULLHANDLE; \
- return(TRUE);
-
- /*--------------------------------------------------------------------------------------*\
- * The following functions are exported in PC2Hook.def *
- \*--------------------------------------------------------------------------------------*/
- void EXPENTRY PC2DLL_SetParameters(void);
- BOOL EXPENTRY PC2DLL_Hook(HAB hab, PQMSG pqmsg, ULONG option);
-
- /*--------------------------------------------------------------------------------------*\
- * The following datastructures are exported in PC2Hook.def *
- \*--------------------------------------------------------------------------------------*/
- HOOKPARAMETERS HookParameters; /* Central control structure for PC/2 */
- KEYDATA KeyData[KEYDATACOUNT]={ /* Hotkeys defined within PC/2 */
- {KC_CTRL, '0', 0x0B, FALSE, NULL}, {KC_CTRL, '1', 0x02, FALSE, NULL}, {KC_CTRL, '2', 0x03, FALSE, NULL},
- {KC_CTRL, '3', 0x04, FALSE, NULL}, {KC_CTRL, '4', 0x05, FALSE, NULL}, {KC_CTRL, '5', 0x06, FALSE, NULL},
- {KC_CTRL, '6', 0x07, FALSE, NULL}, {KC_CTRL, '7', 0x08, FALSE, NULL}, {KC_CTRL, '8', 0x09, FALSE, NULL},
- {KC_CTRL, '9', 0x0A, FALSE, NULL},
- {KC_CTRL, 'A', 0x1E, FALSE, NULL}, {KC_CTRL, 'B', 0x30, FALSE, NULL}, {KC_CTRL, 'C', 0x2E, FALSE, NULL},
- {KC_CTRL, 'D', 0x20, FALSE, NULL}, {KC_CTRL, 'E', 0x12, FALSE, NULL}, {KC_CTRL, 'F', 0x21, FALSE, NULL},
- {KC_CTRL, 'G', 0x22, FALSE, NULL}, {KC_CTRL, 'H', 0x23, FALSE, NULL}, {KC_CTRL, 'I', 0x17, FALSE, NULL},
- {KC_CTRL, 'J', 0x24, FALSE, NULL}, {KC_CTRL, 'K', 0x25, FALSE, NULL}, {KC_CTRL, 'L', 0x26, FALSE, NULL},
- {KC_CTRL, 'M', 0x32, FALSE, NULL}, {KC_CTRL, 'N', 0x31, FALSE, NULL}, {KC_CTRL, 'O', 0x18, FALSE, NULL},
- {KC_CTRL, 'P', 0x19, FALSE, NULL}, {KC_CTRL, 'Q', 0x10, FALSE, NULL}, {KC_CTRL, 'R', 0x13, FALSE, NULL},
- {KC_CTRL, 'S', 0x1F, FALSE, NULL}, {KC_CTRL, 'T', 0x14, FALSE, NULL}, {KC_CTRL, 'U', 0x16, FALSE, NULL},
- {KC_CTRL, 'V', 0x2F, FALSE, NULL}, {KC_CTRL, 'W', 0x11, FALSE, NULL}, {KC_CTRL, 'X', 0x2D, FALSE, NULL},
- {KC_CTRL, 'Y', 0x15, FALSE, NULL}, {KC_CTRL, 'Z', 0x2C, FALSE, NULL},
- {KC_ALT, '0', 0x0B, FALSE, NULL}, {KC_ALT, '1', 0x02, FALSE, NULL}, {KC_ALT, '2', 0x03, FALSE, NULL},
- {KC_ALT, '3', 0x04, FALSE, NULL}, {KC_ALT, '4', 0x05, FALSE, NULL}, {KC_ALT, '5', 0x06, FALSE, NULL},
- {KC_ALT, '6', 0x07, FALSE, NULL}, {KC_ALT, '7', 0x08, FALSE, NULL}, {KC_ALT, '8', 0x09, FALSE, NULL},
- {KC_ALT, '9', 0x0A, FALSE, NULL},
- {KC_ALT, 'A', 0x1E, FALSE, NULL}, {KC_ALT, 'B', 0x30, FALSE, NULL}, {KC_ALT, 'C', 0x2E, FALSE, NULL},
- {KC_ALT, 'D', 0x20, FALSE, NULL}, {KC_ALT, 'E', 0x12, FALSE, NULL}, {KC_ALT, 'F', 0x21, FALSE, NULL},
- {KC_ALT, 'G', 0x22, FALSE, NULL}, {KC_ALT, 'H', 0x23, FALSE, NULL}, {KC_ALT, 'I', 0x17, FALSE, NULL},
- {KC_ALT, 'J', 0x24, FALSE, NULL}, {KC_ALT, 'K', 0x25, FALSE, NULL}, {KC_ALT, 'L', 0x26, FALSE, NULL},
- {KC_ALT, 'M', 0x32, FALSE, NULL}, {KC_ALT, 'N', 0x31, FALSE, NULL}, {KC_ALT, 'O', 0x18, FALSE, NULL},
- {KC_ALT, 'P', 0x19, FALSE, NULL}, {KC_ALT, 'Q', 0x10, FALSE, NULL}, {KC_ALT, 'R', 0x13, FALSE, NULL},
- {KC_ALT, 'S', 0x1F, FALSE, NULL}, {KC_ALT, 'T', 0x14, FALSE, NULL}, {KC_ALT, 'U', 0x16, FALSE, NULL},
- {KC_ALT, 'V', 0x2F, FALSE, NULL}, {KC_ALT, 'W', 0x11, FALSE, NULL}, {KC_ALT, 'X', 0x2D, FALSE, NULL},
- {KC_ALT, 'Y', 0x15, FALSE, NULL}, {KC_ALT, 'Z', 0x2C, FALSE, NULL} };
-
- /*--------------------------------------------------------------------------------------*\
- * The following datastructures are local for in PC2Hook.dll but shared for all *
- * processes in whose context this hook gets called. *
- \*--------------------------------------------------------------------------------------*/
- ULONG ulMoveFlag; /* xxxxxxxx (<-Bit 0)
- | Move all windows in x direction
- | Move in -x direction
- | Move in y direction
- | Move in -y direction
- | Click required to move */
- QUERYRECFROMRECT QueryRect; /* Rectangle to query underlaying containers */
- ULONG ulButtonDown; /* Last button down on PM, either WM_BUTTON1DOWN
- or WM_BUTTON2DOWN or 0 if pointer is not over
- PM */
- UCHAR ucClassname[32]; /* Window class e.g. #1 for WC_FRAME */
- UCHAR ucWindowText[64]; /* Window name e.g. OS/2 2.0 Desktop */
- HWND hwndActiveWindow; /* Window handle of active frame class window on Desktop */
- HWND hwndLastActiveWindow; /* Window handle of last frame class window set active */
- HWND hwndApplication; /* Window handle of application under mouse pointer */
- /* Window handle of application's parent window */
- HWND hwndApplicationParent;
- HWND hwndTitlebar; /* Window handle of application's titlebar */
- HWND hwndLastControl; /* Window handle of last window set active by moving
- mouse pointer onto it */
- HWND hwndActiveControl; /* Window handle of window below mouse pointer */
- HWND hwndFrameClick; /* Parent window handle of the window we clicked on */
- HWND hwndWindow; /* The window that wants to top op z-order */
- HWND hwndOwner; /* Its owner */
- USHORT usFlags; /* KC_* flags */
- UCHAR ucScanCode; /* Keyboard scan code of character pressed */
- KEYDATA *pKeyDataIndex; /* Pointer to KEYDATA structure in array */
- ULONG ulKeyDataIndex; /* Array index */
-
- /*--------------------------------------------------------------------------------------*\
- * This procedure saves the data used in the PC/2 main procedure for use within the *
- * DLL. *
- * Req: *
- * none *
- * Returns: *
- * none *
- \*--------------------------------------------------------------------------------------*/
- void EXPENTRY PC2DLL_SetParameters(void)
- {
- /* Initialize to query the topmost underlaying
- container, that is partially hit by a rectangle
- around the pointer */
- QueryRect.cb=sizeof(QUERYRECFROMRECT);
- QueryRect.fsSearch=CMA_PARTIAL | CMA_ZORDER;
- ulButtonDown=0;
- }
-
- /*--------------------------------------------------------------------------------------*\
- * This procedure implements the hook of the input queue into the system queue. *
- * Req: *
- * hab ........... Anchor block handle *
- * pqmsg ......... Pointer to system QMSG structure *
- * option ........ PM_REMOVE ..... message is being removed *
- * PM_NOREMOVE ... message is not being removed *
- * Returns: *
- * FALSE ......... OS/2 should process QMSG in the normal way passing to next hook *
- * or to the application *
- * TRUE .......... OS/2 doesn't pass the message to next hook or the application *
- \*--------------------------------------------------------------------------------------*/
- BOOL EXPENTRY PC2DLL_InputHook(HAB hab, PQMSG pqmsg, ULONG option)
- {
-
- /* Return if mouse is captured */
- if(WinQueryCapture(HWND_DESKTOP)!=NULLHANDLE) return(FALSE);
- /* *\
- * Here we catch mouse button clicks on the PM to be able to send PC/2 a message when *
- * it should display the window list, because the window list is only displayed if the *
- * mouse is clicked on the WPS (not displaying the window list on PM). *
- * The window list is invoked (like on the WPS) when one mouse button is down, and the *
- * other mouse button is pressed down too, but only if we are over PM. *
- \* */
- switch(pqmsg->msg)
- {
- case WM_BUTTON1DOWN:
- /* If user clicked on the Desktop switch focus to Desktop */
- if(pqmsg->hwnd==HookParameters.hwndDesktop)
- {
- /* Get the currently active top level window, so that
- PC/2 can switch back to this window, when the session
- started needed only be started in background. Be sure
- that the top level window gets saved, but not the WPS,
- because when the Popup-Menu gets activated with a double
- click, the first click switches the focus to the WPS,
- and the active window for the second click would then
- be the WPS (and activated afterwards which we want to
- avoid) */
- hwndActiveWindow=WinQueryActiveWindow(HWND_DESKTOP);
- if(hwndActiveWindow!=HookParameters.hwndDesktop)
- HookParameters.hwndActiveWindow=hwndActiveWindow;
- WinFocusChange(HWND_DESKTOP, pqmsg->hwnd, 0);
- }
- /* If user clicked on the WPS, ensure we keep the top level
- window stored, that had the focus before the WPS */
- if(pqmsg->hwnd==HookParameters.hwndWPS)
- {
- hwndActiveWindow=WinQueryActiveWindow(HWND_DESKTOP);
- if(hwndActiveWindow!=WinQueryWindow(HookParameters.hwndDesktop, QW_PARENT))
- HookParameters.hwndActiveWindow=hwndActiveWindow;
- }
- /* If one button is down and other button was down before
- save it because window list requires second button
- down too */
- if(ulButtonDown!=WM_BUTTON2DOWN)
- ulButtonDown=WM_BUTTON1DOWN;
- else
- {
- ulButtonDown=WM_WINDOWLIST;
- /* If the user holds down both mouse buttons on PM display Window List */
- if(pqmsg->hwnd==HookParameters.hwndDesktop)
- {
- WinPostMsg(HookParameters.hwndClient, WM_WINDOWLIST, MPFROMLONG(pqmsg->mp1), NULL);
- REROUTEMSGTONULL()
- }
- }
- break;
-
- case WM_BUTTON2DOWN:
- if(pqmsg->hwnd==HookParameters.hwndDesktop)
- WinFocusChange(HWND_DESKTOP, pqmsg->hwnd, 0);
- if(ulButtonDown!=WM_BUTTON1DOWN)
- ulButtonDown=WM_BUTTON2DOWN;
- else
- {
- ulButtonDown=WM_WINDOWLIST;
- if(pqmsg->hwnd==HookParameters.hwndDesktop)
- {
- WinPostMsg(HookParameters.hwndClient, WM_WINDOWLIST, MPFROMLONG(pqmsg->mp1), NULL);
- REROUTEMSGTONULL()
- }
- }
- break;
-
- case WM_MOUSEMOVE:
- /* If the mouse is not over PM reset window list flag */
- if(pqmsg->hwnd!=HookParameters.hwndDesktop)
- ulButtonDown=0;
- break;
-
- case WM_BUTTON1UP:
- case WM_BUTTON2UP:
- /* If the mouse is released reset window list flag */
- ulButtonDown=0;
- break;
- }
- /* *\
- * Here we catch all WM_BUTTON2DOWN messages. If it was clicked on any window's *
- * titlebar then set this window to the bottom of the Desktop. WM_BUTTON2DOWN is used *
- * to prevent the moving frame to be drawn (which is the default action of a *
- * WM_BUTTON2DOWN message on a window's titlebar. *
- * This function using WM_BUTTON2DBLCLK was first implemented by Robert Mahoney's *
- * utiltiy WinBack, modified by Rolf Knebel to add this functionality to PC/2. However *
- * using a doubleclick with mouse button 2 has the drawback that the window is brought *
- * into the foreground first (because clicking on the titlebar activates a window) and *
- * then moved to the bottom (causing many unnecessary drawings). *
- \* */
- if((pqmsg->msg==WM_BUTTON2DOWN) && (HookParameters.ulStatusFlag & BUTTON2ZORDER))
- {
- /* Parent window handle of the window we clicked on */
- hwndFrameClick=WinQueryWindow(pqmsg->hwnd, QW_PARENT);
-
- /* If we click on a titlebar the current window handle
- equals the parent's titlebar window handle. If the
- ALT key is pressed we pass this message to the titlebar
- instead of processing to change its z-order */
- if((pqmsg->hwnd==WinWindowFromID(hwndFrameClick, FID_TITLEBAR)) &&
- (!(WinGetKeyState(HWND_DESKTOP, VK_ALT) & 0x8000)))
- { /* Set it to the bottom of all windows */
- WinSetWindowPos(hwndFrameClick, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER|SWP_DEACTIVATE);
- /* Only activate window immediately under mouse if
- the CTRL key is not pressed */
- if(!(WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000))
- {
- /* For some unknown reasons querying and activating the
- new window immediately under the mouse pointer does not
- work here. The same code in PC/2's client window procedure
- works, I assume it has something to with that the hook
- blocks the message queue until it returns. */
- WinPostMsg(HookParameters.hwndClient, WM_ZORDER, MPFROMLONG(pqmsg->mp1), MPFROMHWND(pqmsg->hwnd));
- }
- REROUTEMSGTONULL()
- }
- }
- /* *\
- * Here we catch all WM_CHAR messages filtering them for hotkeys. Found hotkeys are *
- * sent to PC/2. *
- \* */
- if(pqmsg->msg == WM_CHAR)
- {
- /* KC_* flags */
- usFlags=SHORT1FROMMP(pqmsg->mp1);
- /* Keyboard scan code of character pressed */
- ucScanCode=CHAR4FROMMP(pqmsg->mp1);
-
- /* If the key was depressed, ignore */
- if(usFlags&KC_KEYUP) return(FALSE);
- /* If no scan code is available for key, ignore. We
- need to have the scan code, because this is the
- only common part of WM_CHAR between PM and
- WINDOWCOMPAT sessions. To be able to use the Hotkey
- feature in WINDOWCOMPAT sessions too, we test for
- the scan code (which is NLS-dependent, sorry) instead
- of the ASCII value as we did in versions 1.80 and
- before (which was NLS-independent) */
- if(!(usFlags&KC_SCANCODE)) return(FALSE);
- /* We now have a pressed key's scan code, now we are
- only interested if a ALT or CTRL key was pressed
- and hold before and if SHIFT was pressed too. */
- usFlags&=(KC_ALT|KC_CTRL|KC_SHIFT);
- /* It can only be a Hotkey when either a ALT or
- CTRL key was pressed, but SHIFT was not pressed. */
- if((usFlags==KC_CTRL) || (usFlags==KC_ALT))
- {
- /* If the user wants the Hotkeys detected only when
- either PC/2, the Window List or the WPS is active
- determine the active window */
- if(HookParameters.ulStatusFlag & HOTKEY4PC2ONLY)
- {
- /* Query the currently active window, where HWND_DESKTOP
- is the parent window. It will be a WC_FRAME class
- window */
- hwndActiveWindow=WinQueryActiveWindow(HWND_DESKTOP);
- WinQueryWindowText(hwndActiveWindow, sizeof(ucWindowText), ucWindowText);
- while(TRUE)
- {
- /* We can accept the WPS having the focus */
- if(strstr(ucWindowText, HookParameters.ucDesktopName))
- break;
- /* We can accept PM having the focus */
- if(hwndActiveWindow==HookParameters.hwndDesktop)
- break;
- /* We can accept the Window List having the focus */
- if(strstr(ucWindowText, HookParameters.ucWindowListName))
- break;
- /* We can accept any PC/2 Window having the focus */
- if(strstr(ucWindowText, "PC/2"))
- break;
- /* We can accept no window having the focus */
- if(hwndActiveWindow==NULLHANDLE)
- break;
- /* The active window is not one of the required ones,
- so don't handle this message further, but pass it
- on to the next hook in the chain */
- return(FALSE);
- }
- }
- pKeyDataIndex=KeyData;
- ulKeyDataIndex=0;
- /* Now try to find the key */
- for( ;ulKeyDataIndex<=KEYDATACOUNT; ulKeyDataIndex++, pKeyDataIndex++)
- if((pKeyDataIndex->usFlags==usFlags) && (pKeyDataIndex->ucScanCode==ucScanCode))
- {
- if(pKeyDataIndex->bUsed==TRUE)
- {
- WinPostMsg(HookParameters.hwndClient, WM_HOTKEY,
- MPFROM2SHORT(usFlags, pKeyDataIndex->usCh), MPFROMLONG(ulKeyDataIndex));
- REROUTEMSGTONULL()
- }
- else break; /* If our key is not used we don't need any
- further search */
- }
- }
- }
- /* *\
- * Here we catch mouse button 1 clicks, either the move the Desktop or to display the *
- * Popup-Menu. *
- \* */
- while(pqmsg->msg==HookParameters.ulClickFlag)
- {
- /* *\
- * If the user clicked on at least one of the surrounding rows or columns of the *
- * display, we shift the physical Desktop on the virtual Desktop. The flag MOVED4CLICK *
- * is set, if the user click on the display borders. *
- \* */
- if(ulMoveFlag & MOVED4CLICK)
- {
- WinPostMsg(HookParameters.hwndClient, WM_MOVEREQUEST,
- MPFROM2SHORT(pqmsg->ptl.x, pqmsg->ptl.y), MPFROMLONG(ulMoveFlag));
- ulMoveFlag&=~MOVED4CLICK; /* Reset flag, because only a move before
- a click may set it */
- REROUTEMSGTONULL()
- }
- /* *\
- * If the user clicked on the WPS or PM window, send PC/2 a message to display the *
- * Popup-Menu, however not if stroke was part of the Window List activation. *
- \* */
- if((pqmsg->hwnd==HookParameters.hwndWPS) &&
- (ulButtonDown!=WM_WINDOWLIST))
- { /* The user clicked on WPS "Desktop" window.
- We construct a small rectangle around the
- current position of the pointer, relative to
- the WPS window (not the screen) */
- QueryRect.rect.xLeft=(ULONG)SHORT1FROMMP(pqmsg->mp1);
- QueryRect.rect.xRight=QueryRect.rect.xLeft+1;
- QueryRect.rect.yBottom=(ULONG)SHORT2FROMMP(pqmsg->mp1);
- QueryRect.rect.yTop=QueryRect.rect.yBottom+1;
- if(WinSendMsg(HookParameters.hwndWPS, CM_QUERYRECORDFROMRECT,
- MPFROMLONG(CMA_FIRST), &QueryRect)==NULL)
- /* If no container is under the rectangle of the
- mouse pointer, we can display our Popup-Menu.
- The type of container is unknown, but because
- we test only on the WPS, they should usually
- be the icons (but not the minimized programs,
- which are windows with a different window handle). */
- /* Pass the pointer position in coordinates relative
- to the screen (not WPS window) and the handle of
- that window. */
- {
- WinPostMsg(HookParameters.hwndClient, WM_POPUPMENU,
- MPFROM2SHORT((USHORT)pqmsg->ptl.x, (USHORT)pqmsg->ptl.y), MPFROMHWND(pqmsg->hwnd));
- REROUTEMSGTONULL()
- }
- break; /* If clicked on an container, pass message to WPS */
- }
- if((pqmsg->hwnd==HookParameters.hwndDesktop) &&
- (ulButtonDown!=WM_WINDOWLIST))
- { /* The user clicked on the PM "Desktop" window.
- If the WPS isn't installed we only get the PM
- windows. We can now display our Popup-Menu.
- Pass the pointer position in coordinates relative
- to the screen (not WPS window) and the handle of
- that window. */
- WinPostMsg(HookParameters.hwndClient, WM_POPUPMENU,
- MPFROM2SHORT((USHORT)pqmsg->ptl.x, (USHORT)pqmsg->ptl.y), MPFROMHWND(pqmsg->hwnd));
- REROUTEMSGTONULL()
- }
- break; /* Break out of while loop */
- }
- /* *\
- * If enabled, here we catch all mouse movements, to set the window under the mouse *
- * pointer as the active one, if it isn't currently active or the window list or *
- * optionally the Desktop window. *
- \* */
- while((pqmsg->msg==WM_MOUSEMOVE) && (HookParameters.ulStatusFlag & SLIDINGFOCUS))
- { /* If enabled, use sliding focus to activate window
- under the mouse pointer (with some exceptions).
- Caution! Menus have a class WC_MENU, but their
- parent is not the frame window WC_FRAME but the
- Desktop itself. */
- /* Don't process message as possible focus change for PC/2,
- if SHIFT is pressed */
- if((WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000))
- return(FALSE);
- /* If the mouse pointer is moving over the same window
- as for the last move, we don't need to do anything */
- if(hwndLastControl==(hwndActiveControl=pqmsg->hwnd))
- break;
- /* Query the currently active window, where HWND_DESKTOP
- is the parent window. It will be a WC_FRAME class
- window */
- hwndActiveWindow=WinQueryActiveWindow(HWND_DESKTOP);
- /* Don't switch away from Window List */
- if(hwndActiveWindow==HookParameters.hwndWindowList) break;
- hwndApplication=pqmsg->hwnd; /* Get message target window */
- if((hwndApplication==HookParameters.hwndDesktop) || (hwndApplication==HookParameters.hwndWPS))
- break; /* If the window under the mouse pointer is one of the
- Desktops, don't do any changes */
- /* Get parent window of current window */
- hwndApplicationParent=WinQueryWindow(hwndApplication, QW_PARENT);
- while(hwndApplicationParent!=HookParameters.hwndDesktop)
- { /* Loop until we get the Desktop window handle. The
- previous child window of the Desktop is then the
- WC_FRAME class window of the point under the mouse
- pointer which is not the Desktop. */
- hwndApplication=hwndApplicationParent;
- hwndApplicationParent=WinQueryWindow(hwndApplication, QW_PARENT);
- }
- /* Sort with expected descending probability, to avoid
- unnecessary cpu load */
- /* Query the class of the frame window of the
- designated target of WM_MOUSEMOVE */
- WinQueryClassName(hwndApplication, sizeof(ucClassname), ucClassname);
- /* Don't switch to a menu class windows */
- if(!strcmp(ucClassname, "#4")) return(FALSE);
- /* Don't switch to a combobox's listbox windows */
- if(!strcmp(ucClassname, "#7")) return(FALSE);
- /* Don't switch between frame windows if previous frame window
- equals the current one */
- /* Query the frame window name of the designated
- target of WM_MOUSEMOVE */
- WinQueryWindowText(hwndApplication, sizeof(ucWindowText), ucWindowText);
- /* Don't switch to seamless WIN-OS2 menus */
- if(strstr(ucWindowText, "Seamless")) return(FALSE);
- /* If current frame is not equal than last frame we have
- to activate current frame window */
- /* Don't switch to the WC_FRAME class window of PC/2 */
- if(strstr(ucWindowText, "PC/2")) return(FALSE);
- if(hwndLastActiveWindow!=hwndApplication)
- {
- hwndLastActiveWindow=hwndApplication;
- if(HookParameters.ulStatusFlag & PRESERVEZORDER)
- { /* Change focus, but preserve Z-order */
- /* Don't send WM_ACTIVATE to window with new focus */
- WinFocusChange(HWND_DESKTOP, WinWindowFromID(hwndApplication, FID_CLIENT), FC_NOSETACTIVE);
- /* Activate new window */
- if((hwndTitlebar=WinWindowFromID(hwndApplication, FID_TITLEBAR))!=NULLHANDLE)
- WinPostMsg(hwndApplication, WM_ACTIVATE, MPFROMSHORT(TRUE), MPFROMHWND(hwndTitlebar));
- }
- else /* Now switch to the new frame window, causing
- a new Z-order. It will generate all messages
- of deactivating old and activating the
- new window. */
- WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwndApplication, FID_CLIENT));
- }
- /* If current window below mouse pointer is not the one
- being the last, deactivate last one and activate
- current one, but only if the ALT key is not pressed */
- if((WinGetKeyState(HWND_DESKTOP, VK_ALT) & 0x8000)==(LONG)FALSE)
- {
- WinFocusChange(HWND_DESKTOP, hwndActiveControl, FC_NOSETACTIVE);
- hwndLastControl=hwndActiveControl;
- }
- REROUTEMSGTONULL()
- }
- /* *\
- * If enabled, here we catch all mouse movements that are on the surrounding rows and *
- * columns of the physical Desktop, to adjust the position of the physical Desktop *
- * within the virtual Desktop. *
- \* */
- while((pqmsg->msg==WM_MOUSEMOVE) && (HookParameters.ulStatusFlag & VIRTUALDESKTOP))
- {
- ulMoveFlag=0;
- if(pqmsg->ptl.x<=0)
- { /* If we are on the left border of our physical
- Desktop, move all windows right as we shift
- it leftwards on the virtual Desktop */
- ulMoveFlag|=MOVEXR;
- /* If we're in the lower left corner, also move
- all windows up and shift downwards on the
- virtual Desktop */
- if(pqmsg->ptl.y<=HookParameters.LLHotBorder.y) ulMoveFlag|=MOVEYU;
- /* If we're in the upper left corner, also move
- all windows down and shift upwards on the
- virtual Desktop */
- if(pqmsg->ptl.y>=HookParameters.URHotBorder.y) ulMoveFlag|=MOVEYD;
- }
- if(pqmsg->ptl.x>=HookParameters.DesktopSize.x-1)
- { /* If we are on the right border of our physical
- Desktop, move all windows left as we shift
- it rightwards on the virtual Desktop */
- ulMoveFlag|=MOVEXL;
- if(pqmsg->ptl.y<=HookParameters.LLHotBorder.y) ulMoveFlag|=MOVEYU;
- if(pqmsg->ptl.y>=HookParameters.URHotBorder.y) ulMoveFlag|=MOVEYD;
- }
- if(pqmsg->ptl.y<=0)
- { /* If we are on the bottom border of our physical
- Desktop, move all windows up as we shift
- it downwards on the virtual Desktop */
- ulMoveFlag|=MOVEYU;
- if(pqmsg->ptl.x<=HookParameters.LLHotBorder.x) ulMoveFlag|=MOVEXR;
- if(pqmsg->ptl.x>=HookParameters.URHotBorder.x) ulMoveFlag|=MOVEXL;
- }
- if(pqmsg->ptl.y>=HookParameters.DesktopSize.y-1)
- { /* If we are on the top border of our physical
- Desktop, move all windows down as we shift
- it upwards on the virtual Desktop */
- ulMoveFlag|=MOVEYD;
- if(pqmsg->ptl.x<=HookParameters.LLHotBorder.x) ulMoveFlag|=MOVEXR;
- if(pqmsg->ptl.x>=HookParameters.URHotBorder.x) ulMoveFlag|=MOVEXL;
- }
- if(ulMoveFlag==0) break; /* If there is no window to move, don't do any
- further processing and exit loop. As no flags
- are set, the click loop will not find
- the necessity to move */
- ulMoveFlag|=MOVED4CLICK; /* We're now about to move, but if the user
- selected to click before move, we exit this
- loop with the flags set. The click loop
- will then use these flags */
- if(HookParameters.ulStatusFlag & CLICK2MOVE) break;
- WinPostMsg(HookParameters.hwndClient, WM_MOVEREQUEST,
- MPFROM2SHORT(pqmsg->ptl.x, pqmsg->ptl.y), MPFROMLONG(ulMoveFlag));
- REROUTEMSGTONULL()
- }
- return(FALSE); /* Process the message in the normal way */
- }
-
-
- /*--------------------------------------------------------------------------------------*\
- * This procedure implements the hook of WinSendMsg() calls in the system message *
- * queue. *
- * Req: *
- * hab ........... Anchor block handle *
- * pSmh .......... Pointer to send message hook structure *
- * bInterTask .... TRUE .... Message is sent between tasks (intertask) *
- * FALSE ... Message is sent within task (intratask) *
- * Returns: *
- \*--------------------------------------------------------------------------------------*/
- void EXPENTRY PC2DLL_WinSendMsgHook(HAB hab, PSMHSTRUCT pSmh, BOOL bInterTask)
- {
- /* *\
- * Tracking frame window creation, moving, sizing. If PC/2 should be on top of Z-order *
- * ensure this too. *
- \* */
- if((pSmh->msg==WM_ADJUSTWINDOWPOS) && (WinQueryWindow(pSmh->hwnd, QW_PARENT)==HookParameters.hwndDesktop))
- {
- /* Don't change Z-order of (Popup) menus otherwise
- e.g. the Window List's menu gets wrong Z-order */
- WinQueryClassName(pSmh->hwnd, sizeof(ucClassname), ucClassname);
- if(!strcmp(ucClassname, "#4")) return;
- /* If PC/2 should be on Z-order top, we need some
- rearranging */
- if(HookParameters.ulStatusFlag & KEEPONTOP)
- {
- if((pSmh->hwnd!=HookParameters.hwndFrame) && (pSmh->hwnd!=HookParameters.hwndWindowList))
- { /* If this is a frame not being PC/2 or the Window List
- set it behind PC/2 instead of HWND_TOP */
- if(((SWP *)(pSmh->mp1))->hwndInsertBehind==HWND_TOP)
- { /* But only when HWND_TOP is requested */
- /* Get the window's owner window, until either PC/2
- is the owner, or the Desktop */
- hwndOwner=WinQueryWindow(pSmh->hwnd, QW_OWNER);
- while(hwndOwner!=NULLHANDLE)
- {
- /* If PC/2 is the owner, we don't change the z-order,
- because a window is top of z-order to its owner,
- and PC/2's overview window can't be on top of
- z-order relative to its owned windows.
- Ignoring this eats up CPU in 2.11 and traps or
- causes IPE's in Warp */
- if(hwndOwner==HookParameters.hwndFrame)
- {
- return;
- }
- hwndWindow=hwndOwner;
- hwndOwner=WinQueryWindow(hwndWindow, QW_OWNER);
- }
- /* Is PC/2 on top of Z-order */
- if(WinQueryWindow(HWND_DESKTOP, QW_TOP)!=HookParameters.hwndFrame)
- { /* If not set PC/2 to top */
- WinSetWindowPos(HookParameters.hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
- }
- /* Set window immediately behind PC/2 */
- ((SWP *)(pSmh->mp1))->hwndInsertBehind=HookParameters.hwndFrame;
- ((SWP *)(pSmh->mp1))->fl|=SWP_ZORDER;
- }
- }
- else
- { /* If it is PC/2 itself or the Window List, set
- it to top of Z-order */
- ((SWP *)(pSmh->mp1))->hwndInsertBehind=HWND_TOP;
- ((SWP *)(pSmh->mp1))->fl|=SWP_ZORDER;
- }
- }
- /* Post this message to PC/2 because to reflect
- a window's creation, resizing, moving or destruction */
- WinPostMsg(HookParameters.hwndClient, WM_SETUPSIZEPOSITION,
- MPFROMLONG(WM_MOVE), MPFROMHWND(pSmh->hwnd));
- }
- }
-