home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************\
- * PC2.c *
- * Copyright (C) by Stangl Roman, 1993 *
- * 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.50 05,1993 $ (LBL)";
-
- #define _FILE_ "PC/2 - PC2Hook.c V1.50"
-
- #include "PC2.h" /* User include files */
- #include "Error.h"
-
- void EXPENTRY PC2DLL_SetParameters(HOOKPARAMETERS *pHP);
- void EXPENTRY PC2DLL_QueryParameters(HOOKPARAMETERS *pHP);
- BOOL EXPENTRY PC2DLL_Hook(HAB hab, PQMSG pqmsg, ULONG option);
- BOOL PC2DLL_MoveWindows(PQMSG pqmsg);
-
- HOOKPARAMETERS HookParameters; /* Copy of PC2HOOK.DLL control structure, because
- DLL can't access original data in PC2.EXE */
- POINTL LLHotBorder; /* Lower left coordinates that force sliding in
- x & y direction */
- POINTL URHotBorder; /* Upper right coordinates that force sliding in
- -x & -y direction */
- 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 */
- LONG SlidingXFactor; /* Slide in x direction in pixels */
- LONG SlidingYFactor; /* Slide in y direction in pixels */
- QUERYRECFROMRECT QueryRect; /* Rectangle to query underlaying containers */
-
- /*--------------------------------------------------------------------------------------*\
- * This procedure saves the data used in the PC/2 main procedure for use within the *
- * DLL. *
- * Req: *
- * pHP............ Pointer to DLL initialization data *
- * Returns: *
- * none *
- \*--------------------------------------------------------------------------------------*/
- void EXPENTRY PC2DLL_SetParameters(HOOKPARAMETERS *pHP)
- {
- /* Copy the passed parameters to a DLL local copy */
- memcpy(&HookParameters, pHP, sizeof(HOOKPARAMETERS));
- LLHotBorder.x=HookParameters.DesktopSize.x*0.15;
- LLHotBorder.y=HookParameters.DesktopSize.y*0.15;
- URHotBorder.x=HookParameters.DesktopSize.x*0.85;
- URHotBorder.y=HookParameters.DesktopSize.y*0.85;
- /* 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;
- }
-
- /*--------------------------------------------------------------------------------------*\
- * This procedure queries the data used within the DLL for use in the PC/2 main *
- * procedure. *
- * Req: *
- * pHP............ Pointer to return DLL data *
- * Returns: *
- * none *
- \*--------------------------------------------------------------------------------------*/
- void EXPENTRY PC2DLL_QueryParameters(HOOKPARAMETERS *pHP)
- {
- /* Copy from the DLL local copy to the passed parameters */
- memcpy(pHP, &HookParameters, sizeof(HOOKPARAMETERS));
- }
-
- /*--------------------------------------------------------------------------------------*\
- * This procedure implements the hook of the input queue. . *
- * Req: *
- * PQMSG ......... Pointer to system QMSG structure *
- * Returns: *
- * FALSE ......... OS/2 should process QMSG in the normal way *
- \*--------------------------------------------------------------------------------------*/
- BOOL EXPENTRY PC2DLL_Hook(HAB hab, PQMSG pqmsg, ULONG option)
- {
- /* Return if mouse is captured */
- if(WinQueryCapture(HWND_DESKTOP)!=NULLHANDLE) return(FALSE);
- /* *\
- * 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)
- {
- PC2DLL_MoveWindows(pqmsg); /* Now move the windows */
- ulMoveFlag&=~MOVED4CLICK; /* Reset flag, because only a move before
- a click may set it */
- return(TRUE); /* Don't pass this message to next hook in chain. */
- }
- /* *\
- * If the user clicked on the WPS or PM window, send PC/2 a message to display the *
- * Popup-Menu. *
- \* */
- if(pqmsg->hwnd==HookParameters.hwndWPS)
- { /* The user clicked on WPS "Desktop" window.
- We construct a small rectangle around the
- current position of the pointer */
- QueryRect.rect.xLeft=pqmsg->ptl.x;
- QueryRect.rect.xRight=pqmsg->ptl.x+1;
- QueryRect.rect.yBottom=pqmsg->ptl.y;
- QueryRect.rect.yTop=pqmsg->ptl.y+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 window and the handle of that window.
- The coordinates must be translated from that
- window to the display */
- {
- WinSendMsg(HookParameters.hwndPC2, WM_POPUPMENU,
- MPFROMLONG(pqmsg->mp1), MPFROMHWND(pqmsg->hwnd));
- return(TRUE); /* Don't pass this message to next hook in chain. */
- }
- break; /* If clicked on an container, pass message to WPS */
- }
- if(pqmsg->hwnd==HookParameters.hwndDesktop)
- { /* 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 window and the handle of that window.
- The coordinates must be translated from that
- window to the display */
- WinSendMsg(HookParameters.hwndPC2, WM_POPUPMENU,
- MPFROMLONG(pqmsg->mp1), MPFROMHWND(pqmsg->hwnd));
- return(TRUE); /* Don't pass this message to next hook in chain. */
- }
- 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. */
- static UCHAR ucClassname[7]; /* Window class f.e. #1 for WC_FRAME */
- static UCHAR ucWindowText[33]; /* Window name f.e. OS/2 2.0 Desktop */
- static HWND hwndActive; /* Window handle of active frame class window on Desktop */
- static HWND hwndApplication; /* Window handle of application under mouse pointer */
- /* Window handle of applications parent window */
- static HWND hwndApplicationParent;
-
- /* Query the currently active window, where HWND_DESKTOP
- is the parent window. It will be a WC_FRAME class
- window */
- hwndActive=WinQueryActiveWindow(HWND_DESKTOP);
- WinQueryWindowText(hwndActive, sizeof(ucWindowText), ucWindowText);
- /* Don't switch away from the WC_FRAME class tasklist */
- if(!strcmp(ucWindowText, "Window List")) 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);
- }
- /* Query the class of the frame window of the
- designated target of WM_MOUSEMOVE */
- WinQueryClassName(hwndApplication, sizeof(ucClassname), ucClassname);
- /* Query the frame window name of the designated
- target of WM_MOUSEMOVE */
- WinQueryWindowText(hwndApplication, sizeof(ucWindowText), ucWindowText);
- while(TRUE)
- { /* Sort with expected descending probability, to avoid
- unnecessary cpu load */
- /* Don't switch if previous windows equals current one */
- if(hwndActive==hwndApplication) break;
- /* Only switch to WC_FRAME class windows */
- if(strcmp(ucClassname, "#1")) break;
- /* Don't switch to the WC_FRAME class window of PC/2 */
- if(!strcmp(ucWindowText, "PC/2")) break;
- /* Now switch to the new frame window. It will generate
- all messages of deactivating old and activating
- new frame window */
- WinFocusChange(HWND_DESKTOP, pqmsg->hwnd, 0);
- return(TRUE); /* We changed the focus, don't pass this message to
- the next hook in the chain */
- }
- break; /* Exit loop now */
- }
- /* *\
- * 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<=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>=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<=LLHotBorder.y) ulMoveFlag|=MOVEYU;
- if(pqmsg->ptl.y>=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<=LLHotBorder.x) ulMoveFlag|=MOVEXR;
- if(pqmsg->ptl.x>=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<=LLHotBorder.x) ulMoveFlag|=MOVEXR;
- if(pqmsg->ptl.x>=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;
- PC2DLL_MoveWindows(pqmsg); /* Now move the windows */
- return(TRUE); /* Exit from loop */
- }
- return(FALSE); /* Process the message in the normal way */
- }
-
- /*--------------------------------------------------------------------------------------*\
- * This local procedure is called from the PC2DLL_Hook procedure to move the windows *
- * within the virtual Desktop on its behalf. *
- * Req: *
- * pqmsg.......... Pointer to QMSG passed to Hook procedure by OS/2 *
- * Ref: *
- * ulMoveFlag..... Bitmapped flag to control move *
- * SlidingXFactor. Offset to move horizontal which is passed to PC/2's window *
- * procedure *
- * SlidingYFactor. Offset to move vertical *
- * HookParameters. DLL control structure *
- * Returns: *
- * none *
- \*--------------------------------------------------------------------------------------*/
- BOOL PC2DLL_MoveWindows(PQMSG pqmsg)
- {
- LONG lDiff;
-
- SlidingXFactor=0;
- SlidingYFactor=0;
- if((ulMoveFlag&MOVEXR))
- { /* Move physical Desktop left, but not over the
- left border of the virtual Desktop */
- SlidingXFactor=HookParameters.SlidingXFactor;
- HookParameters.VirtualDesktopPos.x-=HookParameters.SlidingXFactor;
- lDiff=HookParameters.VirtualDesktopPos.x-HookParameters.VirtualDesktopMin.x;
- if(lDiff<0)
- {
- HookParameters.VirtualDesktopPos.x-=lDiff;
- SlidingXFactor+=lDiff;
- }
- }
- if((ulMoveFlag&MOVEXL))
- { /* Move physical Desktop right, but not over the
- right border of the virtual Desktop */
- SlidingXFactor=-HookParameters.SlidingXFactor;
- HookParameters.VirtualDesktopPos.x+=HookParameters.SlidingXFactor;
- lDiff=HookParameters.VirtualDesktopPos.x-HookParameters.VirtualDesktopMax.x;
- if(lDiff>0)
- {
- HookParameters.VirtualDesktopPos.x-=lDiff;
- SlidingXFactor+=lDiff;
- }
- }
- if((ulMoveFlag&MOVEYU))
- { /* Move physical Desktop down, but not under the
- bottom border of the virtual Desktop */
- SlidingYFactor=HookParameters.SlidingYFactor;
- HookParameters.VirtualDesktopPos.y-=HookParameters.SlidingYFactor;
- lDiff=HookParameters.VirtualDesktopPos.y-HookParameters.VirtualDesktopMin.y;
- if(lDiff<0)
- {
- HookParameters.VirtualDesktopPos.y-=lDiff;
- SlidingYFactor+=lDiff;
- }
- }
- if((ulMoveFlag&MOVEYD))
- { /* Move physical Desktop up, but not over the
- top border of the virtual Desktop */
- SlidingYFactor=-HookParameters.SlidingYFactor;
- HookParameters.VirtualDesktopPos.y+=HookParameters.SlidingYFactor;
- lDiff=HookParameters.VirtualDesktopPos.y-HookParameters.VirtualDesktopMax.y;
- if(lDiff>0)
- {
- HookParameters.VirtualDesktopPos.y-=lDiff;
- SlidingYFactor+=lDiff;
- }
- }
- /* If there is nothing to move, because we are
- on a border position, don't do further processing
- but return */
- if(!SlidingXFactor && !SlidingYFactor) return(FALSE);
- /* Move pointer so that it is on that pixel it
- would be, if we hadn't moved the windows. Also
- change the pixel which gets the message. */
- if(HookParameters.ulScrollPercentage==100)
- WinSetPointerPos(HWND_DESKTOP, (pqmsg->ptl.x+=SlidingXFactor*0.5),
- (pqmsg->ptl.y+=SlidingYFactor*0.5));
- else
- WinSetPointerPos(HWND_DESKTOP, (pqmsg->ptl.x+=SlidingXFactor),
- (pqmsg->ptl.y+=SlidingYFactor));
- /* Inform PC/2 to move windows */
- WinSendMsg(HookParameters.hwndPC2, WM_DESKTOPMOVE,
- MPFROMLONG(SlidingXFactor), MPFROMLONG(SlidingYFactor));
- return(TRUE);
- }
-