home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / utils / pc2 / source / pc2hook.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-31  |  22.6 KB  |  362 lines

  1. /***********************************************************************\
  2.  *                                PC2.c                                *
  3.  *                 Copyright (C) by Stangl Roman, 1993                 *
  4.  * This Code may be freely distributed, provided the Copyright isn't   *
  5.  * removed.                                                            *
  6.  *                                                                     *
  7.  * Pc2Hook.c    Hook the input queue to filter certain messages.       *
  8.  *                                                                     *
  9. \***********************************************************************/
  10.  
  11. static char RCSID[]="@(#) $Header: Pc2Hook.c Version 1.50 05,1993 $ (LBL)";
  12.  
  13. #define         _FILE_  "PC/2 - PC2Hook.c V1.50"
  14.  
  15. #include        "PC2.h"                 /* User include files */
  16. #include        "Error.h"
  17.  
  18. void EXPENTRY   PC2DLL_SetParameters(HOOKPARAMETERS *pHP);
  19. void EXPENTRY   PC2DLL_QueryParameters(HOOKPARAMETERS *pHP);
  20. BOOL EXPENTRY   PC2DLL_Hook(HAB hab, PQMSG pqmsg, ULONG option);
  21. BOOL            PC2DLL_MoveWindows(PQMSG pqmsg);
  22.  
  23. HOOKPARAMETERS          HookParameters; /* Copy of PC2HOOK.DLL control structure, because
  24.                                            DLL can't access original data in PC2.EXE */
  25. POINTL                  LLHotBorder;    /* Lower left coordinates that force sliding in
  26.                                            x & y direction */
  27. POINTL                  URHotBorder;    /* Upper right coordinates that force sliding in
  28.                                            -x & -y direction */
  29. ULONG                   ulMoveFlag;     /* xxxxxxxx (<-Bit 0)
  30.                                                   | Move all windows in x direction
  31.                                                  |  Move in -x direction
  32.                                                 |   Move in y direction
  33.                                                |    Move in -y direction
  34.                                               |     Click required to move */
  35. LONG                    SlidingXFactor; /* Slide in x direction in pixels */
  36. LONG                    SlidingYFactor; /* Slide in y direction in pixels */
  37. QUERYRECFROMRECT        QueryRect;      /* Rectangle to query underlaying containers */
  38.  
  39. /*--------------------------------------------------------------------------------------*\
  40.  * This procedure saves the data used in the PC/2 main procedure for use within the     *
  41.  * DLL.                                                                                 *
  42.  * Req:                                                                                 *
  43.  *      pHP............ Pointer to DLL initialization data                              *
  44.  * Returns:                                                                             *
  45.  *      none                                                                            *
  46. \*--------------------------------------------------------------------------------------*/
  47. void EXPENTRY   PC2DLL_SetParameters(HOOKPARAMETERS *pHP)
  48. {
  49.                                         /* Copy the passed parameters to a DLL local copy */
  50. memcpy(&HookParameters, pHP, sizeof(HOOKPARAMETERS));
  51. LLHotBorder.x=HookParameters.DesktopSize.x*0.15;
  52. LLHotBorder.y=HookParameters.DesktopSize.y*0.15;
  53. URHotBorder.x=HookParameters.DesktopSize.x*0.85;
  54. URHotBorder.y=HookParameters.DesktopSize.y*0.85;
  55.                                         /* Initialize to query the topmost underlaying
  56.                                            container, that is partially hit by a rectangle
  57.                                            around the pointer */
  58. QueryRect.cb=sizeof(QUERYRECFROMRECT);
  59. QueryRect.fsSearch=CMA_PARTIAL | CMA_ZORDER;
  60. }
  61.  
  62. /*--------------------------------------------------------------------------------------*\
  63.  * This procedure queries the data used within the DLL for use in the PC/2 main         *
  64.  * procedure.                                                                           *
  65.  * Req:                                                                                 *
  66.  *      pHP............ Pointer to return DLL data                                      *
  67.  * Returns:                                                                             *
  68.  *      none                                                                            *
  69. \*--------------------------------------------------------------------------------------*/
  70. void EXPENTRY   PC2DLL_QueryParameters(HOOKPARAMETERS *pHP)
  71. {
  72.                                         /* Copy from the DLL local copy to the passed parameters */
  73. memcpy(pHP, &HookParameters, sizeof(HOOKPARAMETERS));
  74. }
  75.  
  76. /*--------------------------------------------------------------------------------------*\
  77.  * This procedure implements the hook of the input queue.        .                      *
  78.  * Req:                                                                                 *
  79.  *      PQMSG ......... Pointer to system QMSG structure                                *
  80.  * Returns:                                                                             *
  81.  *      FALSE ......... OS/2 should process QMSG in the normal way                      *
  82. \*--------------------------------------------------------------------------------------*/
  83. BOOL EXPENTRY   PC2DLL_Hook(HAB hab, PQMSG pqmsg, ULONG option)
  84. {
  85.                                         /* Return if mouse is captured */
  86. if(WinQueryCapture(HWND_DESKTOP)!=NULLHANDLE) return(FALSE);
  87. /*                                                                                      *\
  88.  * Here we catch mouse button 1 clicks, either the move the Desktop or to display the   *
  89.  * Popup-Menu.                                                                          *
  90. \*                                                                                      */
  91. while(pqmsg->msg==HookParameters.ulClickFlag)
  92.     {
  93. /*                                                                                      *\
  94.  * If the user clicked on at least one of the surrounding rows or columns of the        *
  95.  * display, we shift the physical Desktop on the virtual Desktop. The flag MOVED4CLICK  *
  96.  * is set, if the user click on the display borders.                                    *
  97. \*                                                                                      */
  98.     if(ulMoveFlag & MOVED4CLICK)
  99.         {
  100.         PC2DLL_MoveWindows(pqmsg);      /* Now move the windows */
  101.         ulMoveFlag&=~MOVED4CLICK;       /* Reset flag, because only a move before
  102.                                            a click may set it */
  103.         return(TRUE);                   /* Don't pass this message to next hook in chain. */
  104.         }
  105. /*                                                                                      *\
  106.  * If the user clicked on the WPS or PM window, send PC/2 a message to display the      *
  107.  * Popup-Menu.                                                                          *
  108. \*                                                                                      */
  109.     if(pqmsg->hwnd==HookParameters.hwndWPS)
  110.         {                               /* The user clicked on WPS "Desktop" window.
  111.                                            We construct a small rectangle around the
  112.                                            current position of the pointer */
  113.         QueryRect.rect.xLeft=pqmsg->ptl.x;
  114.         QueryRect.rect.xRight=pqmsg->ptl.x+1;
  115.         QueryRect.rect.yBottom=pqmsg->ptl.y;
  116.         QueryRect.rect.yTop=pqmsg->ptl.y+1;
  117.         if(WinSendMsg(HookParameters.hwndWPS, CM_QUERYRECORDFROMRECT,
  118.             MPFROMLONG(CMA_FIRST), &QueryRect)==NULL)
  119.                                         /* If no container is under the rectangle of the
  120.                                            mouse pointer, we can display our Popup-Menu.
  121.                                            The type of container is unknown, but because
  122.                                            we test only on the WPS, they should usually
  123.                                            be the icons (but not the minimized programs,
  124.                                            which are windows with a different window handle). */
  125.                                         /* Pass the pointer position in coordinates relative
  126.                                            to the window and the handle of that window.
  127.                                            The coordinates must be translated from that
  128.                                            window to the display */
  129.             {
  130.             WinSendMsg(HookParameters.hwndPC2, WM_POPUPMENU,
  131.                 MPFROMLONG(pqmsg->mp1), MPFROMHWND(pqmsg->hwnd));
  132.             return(TRUE);               /* Don't pass this message to next hook in chain. */
  133.             }
  134.         break;                          /* If clicked on an container, pass message to WPS */
  135.         }
  136.     if(pqmsg->hwnd==HookParameters.hwndDesktop)
  137.         {                               /* The user clicked on the PM "Desktop" window.
  138.                                            If the WPS isn't installed we only get the PM
  139.                                            windows. We can now display our Popup-Menu.
  140.                                            Pass the pointer position in coordinates relative
  141.                                            to the window and the handle of that window.
  142.                                            The coordinates must be translated from that
  143.                                            window to the display */
  144.         WinSendMsg(HookParameters.hwndPC2, WM_POPUPMENU,
  145.             MPFROMLONG(pqmsg->mp1), MPFROMHWND(pqmsg->hwnd));
  146.         return(TRUE);                   /* Don't pass this message to next hook in chain. */
  147.         }
  148.     break;                              /* Break out of while loop */
  149.     }
  150. /*                                                                                      *\
  151.  * If enabled, here we catch all mouse movements, to set the window under the mouse     *
  152.  * pointer as the active one, if it isn't currently active or the window list or        *
  153.  * optionally the Desktop window.                                                       *
  154. \*                                                                                      */
  155. while((pqmsg->msg==WM_MOUSEMOVE) && (HookParameters.ulStatusFlag & SLIDINGFOCUS))
  156.     {                                   /* If enabled, use sliding focus to activate window
  157.                                            under the mouse pointer (with some exceptions).
  158.                                            Caution! Menus have a class WC_MENU, but their
  159.                                            parent is not the frame window WC_FRAME but the
  160.                                            Desktop itself. */
  161.     static UCHAR    ucClassname[7];     /* Window class f.e. #1 for WC_FRAME */
  162.     static UCHAR    ucWindowText[33];   /* Window name f.e. OS/2 2.0 Desktop */
  163.     static HWND     hwndActive;         /* Window handle of active frame class window on Desktop */
  164.     static HWND     hwndApplication;    /* Window handle of application under mouse pointer */
  165.                                         /* Window handle of applications parent window */
  166.     static HWND     hwndApplicationParent;
  167.  
  168.                                         /* Query the currently active window, where HWND_DESKTOP
  169.                                            is the parent window. It will be a WC_FRAME class
  170.                                            window */
  171.     hwndActive=WinQueryActiveWindow(HWND_DESKTOP);
  172.     WinQueryWindowText(hwndActive, sizeof(ucWindowText), ucWindowText);
  173.                                         /* Don't switch away from the WC_FRAME class tasklist */
  174.     if(!strcmp(ucWindowText, "Window List")) break;
  175.     hwndApplication=pqmsg->hwnd;        /* Get message target window */
  176.     if((hwndApplication==HookParameters.hwndDesktop) || (hwndApplication==HookParameters.hwndWPS))
  177.         break;                          /* If the window under the mouse pointer is one of the
  178.                                            Desktops, don't do any changes */
  179.                                         /* Get parent window of current window */
  180.     hwndApplicationParent=WinQueryWindow(hwndApplication, QW_PARENT);
  181.     while(hwndApplicationParent!=HookParameters.hwndDesktop)
  182.         {                               /* Loop until we get the Desktop window handle. The
  183.                                            previous child window of the Desktop is then the
  184.                                            WC_FRAME class window of the point under the mouse
  185.                                            pointer which is not the Desktop. */
  186.         hwndApplication=hwndApplicationParent;
  187.         hwndApplicationParent=WinQueryWindow(hwndApplication, QW_PARENT);
  188.         }
  189.                                         /* Query the class of the frame window of the
  190.                                            designated target of WM_MOUSEMOVE */
  191.     WinQueryClassName(hwndApplication, sizeof(ucClassname), ucClassname);
  192.                                         /* Query the frame window name of the designated
  193.                                            target of WM_MOUSEMOVE */
  194.     WinQueryWindowText(hwndApplication, sizeof(ucWindowText), ucWindowText);
  195.     while(TRUE)
  196.         {                               /* Sort with expected descending probability, to avoid
  197.                                            unnecessary cpu load */
  198.                                         /* Don't switch if previous windows equals current one */
  199.         if(hwndActive==hwndApplication) break;
  200.                                         /* Only switch to WC_FRAME class windows */
  201.         if(strcmp(ucClassname, "#1")) break;
  202.                                         /* Don't switch to the WC_FRAME class window of PC/2 */
  203.         if(!strcmp(ucWindowText, "PC/2")) break;
  204.                                         /* Now switch to the new frame window. It will generate
  205.                                            all messages of deactivating old and activating
  206.                                            new frame window */
  207.         WinFocusChange(HWND_DESKTOP, pqmsg->hwnd, 0);
  208.         return(TRUE);                   /* We changed the focus, don't pass this message to
  209.                                            the next hook in the chain */
  210.         }
  211.     break;                              /* Exit loop now */
  212.     }
  213. /*                                                                                      *\
  214.  * If enabled, here we catch all mouse movements that are on the surrounding rows and   *
  215.  * columns of the physical Desktop, to adjust the position of the physical Desktop      *
  216.  * within the virtual Desktop.                                                          *
  217. \*                                                                                      */
  218. while((pqmsg->msg==WM_MOUSEMOVE) && (HookParameters.ulStatusFlag & VIRTUALDESKTOP))
  219.     {
  220.     ulMoveFlag=0;
  221.     if(pqmsg->ptl.x<=0)
  222.         {                               /* If we are on the left border of our physical
  223.                                            Desktop, move all windows right as we shift
  224.                                            it leftwards on the virtual Desktop */
  225.         ulMoveFlag|=MOVEXR;
  226.                                         /* If we're in the lower left corner, also move
  227.                                            all windows up and shift downwards on the
  228.                                            virtual Desktop */
  229.         if(pqmsg->ptl.y<=LLHotBorder.y) ulMoveFlag|=MOVEYU;
  230.                                         /* If we're in the upper left corner, also move
  231.                                            all windows down and shift upwards on the
  232.                                            virtual Desktop */
  233.         if(pqmsg->ptl.y>=URHotBorder.y) ulMoveFlag|=MOVEYD;
  234.         }
  235.  
  236.     if(pqmsg->ptl.x>=HookParameters.DesktopSize.x-1)
  237.         {                               /* If we are on the right border of our physical
  238.                                            Desktop, move all windows left as we shift
  239.                                            it rightwards on the virtual Desktop */
  240.         ulMoveFlag|=MOVEXL;
  241.         if(pqmsg->ptl.y<=LLHotBorder.y) ulMoveFlag|=MOVEYU;
  242.         if(pqmsg->ptl.y>=URHotBorder.y) ulMoveFlag|=MOVEYD;
  243.         }
  244.     if(pqmsg->ptl.y<=0)
  245.         {                               /* If we are on the bottom border of our physical
  246.                                            Desktop, move all windows up as we shift
  247.                                            it downwards on the virtual Desktop */
  248.         ulMoveFlag|=MOVEYU;
  249.         if(pqmsg->ptl.x<=LLHotBorder.x) ulMoveFlag|=MOVEXR;
  250.         if(pqmsg->ptl.x>=URHotBorder.x) ulMoveFlag|=MOVEXL;
  251.         }
  252.     if(pqmsg->ptl.y>=HookParameters.DesktopSize.y-1)
  253.         {                               /* If we are on the top border of our physical
  254.                                            Desktop, move all windows down as we shift
  255.                                            it upwards on the virtual Desktop */
  256.         ulMoveFlag|=MOVEYD;
  257.         if(pqmsg->ptl.x<=LLHotBorder.x) ulMoveFlag|=MOVEXR;
  258.         if(pqmsg->ptl.x>=URHotBorder.x) ulMoveFlag|=MOVEXL;
  259.         }
  260.     if(ulMoveFlag==0) break;            /* If there is no window to move, don't do any
  261.                                            further processing and exit loop. As no flags
  262.                                            are set, the click loop will not find 
  263.                                            the necessity to move */
  264.     ulMoveFlag|=MOVED4CLICK;            /* We're now about to move, but if the user
  265.                                            selected to click before move, we exit this
  266.                                            loop with the flags set. The click loop
  267.                                            will then use these flags */
  268.     if(HookParameters.ulStatusFlag & CLICK2MOVE) break;
  269.     PC2DLL_MoveWindows(pqmsg);          /* Now move the windows */
  270.     return(TRUE);                       /* Exit from loop */
  271.     }
  272. return(FALSE);                          /* Process the message in the normal way */
  273. }
  274.  
  275. /*--------------------------------------------------------------------------------------*\
  276.  * This local procedure is called from the PC2DLL_Hook procedure to move the windows    *
  277.  * within the virtual Desktop on its behalf.                                            *
  278.  * Req:                                                                                 *
  279.  *      pqmsg.......... Pointer to QMSG passed to Hook procedure by OS/2                *
  280.  * Ref:                                                                                 *
  281.  *      ulMoveFlag..... Bitmapped flag to control move                                  *
  282.  *      SlidingXFactor. Offset to move horizontal which is passed to PC/2's window      *
  283.  *                      procedure                                                       *
  284.  *      SlidingYFactor. Offset to move vertical                                         *
  285.  *      HookParameters. DLL control structure                                           *
  286.  * Returns:                                                                             *
  287.  *      none                                                                            *
  288. \*--------------------------------------------------------------------------------------*/
  289. BOOL            PC2DLL_MoveWindows(PQMSG pqmsg)
  290. {
  291. LONG    lDiff;
  292.  
  293. SlidingXFactor=0;
  294. SlidingYFactor=0;
  295. if((ulMoveFlag&MOVEXR))
  296.     {                                   /* Move physical Desktop left, but not over the
  297.                                            left border of the virtual Desktop */
  298.     SlidingXFactor=HookParameters.SlidingXFactor;
  299.     HookParameters.VirtualDesktopPos.x-=HookParameters.SlidingXFactor;
  300.     lDiff=HookParameters.VirtualDesktopPos.x-HookParameters.VirtualDesktopMin.x;
  301.     if(lDiff<0)
  302.         {
  303.         HookParameters.VirtualDesktopPos.x-=lDiff;
  304.         SlidingXFactor+=lDiff;
  305.         }
  306.     }
  307. if((ulMoveFlag&MOVEXL))
  308.     {                                   /* Move physical Desktop right, but not over the
  309.                                            right border of the virtual Desktop */
  310.     SlidingXFactor=-HookParameters.SlidingXFactor;
  311.     HookParameters.VirtualDesktopPos.x+=HookParameters.SlidingXFactor;
  312.     lDiff=HookParameters.VirtualDesktopPos.x-HookParameters.VirtualDesktopMax.x;
  313.     if(lDiff>0)
  314.         {
  315.         HookParameters.VirtualDesktopPos.x-=lDiff;
  316.         SlidingXFactor+=lDiff;
  317.         }
  318.     }
  319. if((ulMoveFlag&MOVEYU))
  320.     {                                   /* Move physical Desktop down, but not under the
  321.                                            bottom border of the virtual Desktop */
  322.     SlidingYFactor=HookParameters.SlidingYFactor;
  323.     HookParameters.VirtualDesktopPos.y-=HookParameters.SlidingYFactor;
  324.     lDiff=HookParameters.VirtualDesktopPos.y-HookParameters.VirtualDesktopMin.y;
  325.     if(lDiff<0)
  326.         {
  327.         HookParameters.VirtualDesktopPos.y-=lDiff;
  328.         SlidingYFactor+=lDiff;
  329.         }
  330.     }
  331. if((ulMoveFlag&MOVEYD))
  332.     {                                   /* Move physical Desktop up, but not over the
  333.                                            top border of the virtual Desktop */
  334.     SlidingYFactor=-HookParameters.SlidingYFactor;
  335.     HookParameters.VirtualDesktopPos.y+=HookParameters.SlidingYFactor;
  336.     lDiff=HookParameters.VirtualDesktopPos.y-HookParameters.VirtualDesktopMax.y;
  337.     if(lDiff>0)
  338.         {
  339.         HookParameters.VirtualDesktopPos.y-=lDiff;
  340.         SlidingYFactor+=lDiff;
  341.         }
  342.     }
  343.                                         /* If there is nothing to move, because we are
  344.                                            on a border position, don't do further processing
  345.                                            but return */
  346. if(!SlidingXFactor && !SlidingYFactor) return(FALSE);
  347.                                         /* Move pointer so that it is on that pixel it
  348.                                            would be, if we hadn't moved the windows. Also
  349.                                            change the pixel which gets the message. */
  350. if(HookParameters.ulScrollPercentage==100)
  351.     WinSetPointerPos(HWND_DESKTOP, (pqmsg->ptl.x+=SlidingXFactor*0.5),
  352.         (pqmsg->ptl.y+=SlidingYFactor*0.5));
  353. else
  354.     WinSetPointerPos(HWND_DESKTOP, (pqmsg->ptl.x+=SlidingXFactor),
  355.         (pqmsg->ptl.y+=SlidingYFactor));
  356.                                         /* Inform PC/2 to move windows */
  357. WinSendMsg(HookParameters.hwndPC2, WM_DESKTOPMOVE,
  358.     MPFROMLONG(SlidingXFactor), MPFROMLONG(SlidingYFactor));
  359. return(TRUE);
  360. }
  361.  
  362.