[OSK] Restore the previous window coordination
authorBișoc George <fraizeraust99@gmail.com>
Sat, 2 Mar 2019 17:10:26 +0000 (18:10 +0100)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Sat, 23 Mar 2019 15:34:48 +0000 (16:34 +0100)
Implement the coordination dialog data saver. This allows OSK to launch using the previous placement values. Such behaviour can be seen with the XP's part of On-Screen Keyboard.

base/applications/osk/main.c
base/applications/osk/main.h
base/applications/osk/settings.c

index 972f8c8..92e1a05 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * PROJECT:         ReactOS On-Screen Keyboard
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            base/applications/osk/main.c
  * PURPOSE:         On-screen keyboard.
- * PROGRAMMERS:     Denis ROBERT
+ * COPYRIGHT:       Denis ROBERT
+ *                  Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com)
  */
 
 /* INCLUDES *******************************************************************/
@@ -138,7 +138,7 @@ int OSK_DlgInitDialog(HWND hDlg)
     HMONITOR monitor;
     MONITORINFO info;
     POINT Pt;
-    RECT rcWindow;
+    RECT rcWindow, rcDlgIntersect;
 
     /* Save handle */
     Globals.hMainWnd = hDlg;
@@ -178,17 +178,42 @@ int OSK_DlgInitDialog(HWND hDlg)
     monitor = MonitorFromPoint(Pt, MONITOR_DEFAULTTOPRIMARY);
     info.cbSize = sizeof(info);
     GetMonitorInfoW(monitor, &info);
-
-    /* Move the dialog on the bottom of main screen */
     GetWindowRect(hDlg, &rcWindow);
-    MoveWindow(hDlg,
-               (info.rcMonitor.left + info.rcMonitor.right) / 2 - // Center of screen
-                   (rcWindow.right - rcWindow.left) / 2,          // - half size of dialog
-               info.rcMonitor.bottom -               // Bottom of screen
-                   (rcWindow.bottom - rcWindow.top), // - size of window
-               rcWindow.right - rcWindow.left,     // Width
-               rcWindow.bottom - rcWindow.top,     // Height
-               TRUE);
+
+    /* 
+        If the coordination values are default then re-initialize using the specific formulas
+        to move the dialog at the bottom of the screen.
+    */
+    if (Globals.PosX == CW_USEDEFAULT && Globals.PosY == CW_USEDEFAULT)
+    {
+        Globals.PosX = (info.rcMonitor.left + info.rcMonitor.right - (rcWindow.right - rcWindow.left)) / 2;
+        Globals.PosY = info.rcMonitor.bottom - (rcWindow.bottom - rcWindow.top);
+    }
+
+    /*  
+        Calculate the intersection of two rectangle sources (dialog and work desktop area).
+        If such sources do not intersect, then the dialog is deemed as "off screen".
+    */
+    if (IntersectRect(&rcDlgIntersect, &rcWindow, &info.rcWork) == 0)
+    {
+        Globals.PosX = (info.rcMonitor.left + info.rcMonitor.right - (rcWindow.right - rcWindow.left)) / 2;
+        Globals.PosY = info.rcMonitor.bottom - (rcWindow.bottom - rcWindow.top);
+    }
+    else
+    {
+        /*
+            There's still some intersection but we're not for sure if it is sufficient (the dialog could also be partially hidden).
+            Therefore, check the remaining intersection if it's enough.
+        */
+        if (rcWindow.top < info.rcWork.top || rcWindow.left < info.rcWork.left || rcWindow.right > info.rcWork.right || rcWindow.bottom > info.rcWork.bottom)
+        {
+            Globals.PosX = (info.rcMonitor.left + info.rcMonitor.right - (rcWindow.right - rcWindow.left)) / 2;
+            Globals.PosY = info.rcMonitor.bottom - (rcWindow.bottom - rcWindow.top);
+        }
+    }
+
+    /* Move the dialog according to the placement coordination */
+    SetWindowPos(hDlg, HWND_TOP, Globals.PosX, Globals.PosY, 0, 0, SWP_NOSIZE);
 
     /* Set icon on visual buttons */
     OSK_SetImage(SCAN_CODE_15, IDI_BACK);
@@ -593,7 +618,7 @@ int WINAPI wWinMain(HINSTANCE hInstance,
 
     if (!hMutex)
     {
-        /* Mutex doesn\92t exist. This is the first instance so create the mutex. */
+        /* Mutex doesn't exist. This is the first instance so create the mutex. */
         hMutex = CreateMutexW(NULL, FALSE, L"osk");
 
         /* Create the modal box based on the configuration registry */
index 137cf5b..da4cf2a 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * PROJECT:         ReactOS On-Screen Keyboard
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            base/applications/osk/main.h
  * PURPOSE:         On screen keyboard.
- * PROGRAMMERS:     Denis ROBERT
+ * COPYRIGHT:       Denis ROBERT
+ *                  Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com)
  */
 
 #ifndef _OSKMAIN_H
@@ -26,6 +26,8 @@ typedef struct
     BOOL       bShowWarning;
     BOOL       bIsEnhancedKeyboard;
     BOOL       bSoundClick;
+    INT        PosX;
+    INT        PosY;
 } OSK_GLOBALS;
 
 /* DEFINES ********************************************************************/
index 03eb18f..d7dab32 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * PROJECT:         ReactOS On-Screen Keyboard
  * LICENSE:         GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
- * PURPOSE:         Settings file for warning dialog on startup
- * COPYRIGHT:       Copyright 2018 Bișoc George (fraizeraust99 at gmail dot com)
+ * PURPOSE:         Configuration settings of the application
+ * COPYRIGHT:       Copyright 2018-2019 Bișoc George (fraizeraust99 at gmail dot com)
  */
 
 /* INCLUDES *******************************************************************/
@@ -16,7 +16,7 @@ BOOL LoadDataFromRegistry()
 {
     HKEY hKey;
     LONG lResult;
-    DWORD dwShowWarningData, dwLayout, dwSoundOnClick;
+    DWORD dwShowWarningData, dwLayout, dwSoundOnClick, dwPositionLeft, dwPositionTop;
     DWORD cbData = sizeof(DWORD);
 
     /* Set the structure members to TRUE (and the bSoundClick member to FALSE) */
@@ -24,9 +24,13 @@ BOOL LoadDataFromRegistry()
     Globals.bIsEnhancedKeyboard = TRUE;
     Globals.bSoundClick = FALSE;
 
+    /* Set the coordinate values to default */
+    Globals.PosX = CW_USEDEFAULT;
+    Globals.PosY = CW_USEDEFAULT;
+
     /* Open the key, so that we can query it */
     lResult = RegOpenKeyExW(HKEY_CURRENT_USER,
-                            L"Software\\Microsoft\\osk",
+                            L"Software\\Microsoft\\Osk",
                             0,
                             KEY_READ,
                             &hKey);
@@ -75,7 +79,7 @@ BOOL LoadDataFromRegistry()
 
     /* Query the key */
     lResult = RegQueryValueExW(hKey,
-                               L"OnSoundClick",
+                               L"ClickSound",
                                0,
                                0,
                                (BYTE *)&dwSoundOnClick,
@@ -90,6 +94,41 @@ BOOL LoadDataFromRegistry()
 
     /* Load the sound on click value event */
     Globals.bSoundClick = (dwSoundOnClick != 0);
+
+    /* Query the key */
+    lResult = RegQueryValueExW(hKey,
+                               L"WindowLeft",
+                               0,
+                               0,
+                               (BYTE *)&dwPositionLeft,
+                               &cbData);
+
+    if (lResult != ERROR_SUCCESS)
+    {
+        /* Bail out and return FALSE if we fail */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
+    /* Load the X value data of the dialog's coordinate */
+    Globals.PosX = dwPositionLeft;
+
+    lResult = RegQueryValueExW(hKey,
+                               L"WindowTop",
+                               0,
+                               0,
+                               (BYTE *)&dwPositionTop,
+                               &cbData);
+
+    if (lResult != ERROR_SUCCESS)
+    {
+        /* Bail out and return FALSE if we fail */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
+    /* Load the Y value data of the dialog's coordinate */
+    Globals.PosY = dwPositionTop;
     
     /* If we're here then we succeed, close the key and return TRUE */
     RegCloseKey(hKey);
@@ -100,11 +139,16 @@ BOOL SaveDataToRegistry()
 {
     HKEY hKey;
     LONG lResult;
-    DWORD dwShowWarningData, dwLayout, dwSoundOnClick;
+    DWORD dwShowWarningData, dwLayout, dwSoundOnClick, dwPositionLeft, dwPositionTop;
+    WINDOWPLACEMENT wp;
+
+    /* Set the structure length and retrieve the dialog's placement */
+    wp.length = sizeof(WINDOWPLACEMENT);
+    GetWindowPlacement(Globals.hMainWnd, &wp);
 
     /* If no key has been made, create one */
     lResult = RegCreateKeyExW(HKEY_CURRENT_USER,
-                              L"Software\\Microsoft\\osk",
+                              L"Software\\Microsoft\\Osk",
                               0,
                               NULL,
                               0,
@@ -122,6 +166,7 @@ BOOL SaveDataToRegistry()
     /* The data value of the subkey will be appended to the warning dialog switch */
     dwShowWarningData = Globals.bShowWarning;
 
+    /* Welcome warning box value key */
     lResult = RegSetValueExW(hKey,
                              L"ShowWarning",
                              0,
@@ -139,6 +184,7 @@ BOOL SaveDataToRegistry()
     /* The value will be appended to the layout dialog */
     dwLayout = Globals.bIsEnhancedKeyboard;
 
+    /* Keyboard dialog switcher */
     lResult = RegSetValueExW(hKey,
                              L"IsEnhancedKeyboard",
                              0,
@@ -156,8 +202,9 @@ BOOL SaveDataToRegistry()
     /* The value will be appended to the sound on click event */
     dwSoundOnClick = Globals.bSoundClick;
 
+    /* "Sound on Click" switcher value key */
     lResult = RegSetValueExW(hKey,
-                             L"OnSoundClick",
+                             L"ClickSound",
                              0,
                              REG_DWORD,
                              (BYTE *)&dwSoundOnClick,
@@ -170,6 +217,42 @@ BOOL SaveDataToRegistry()
         return FALSE;
     }
 
+    /* The value will be appended to the X coordination dialog's placement */
+    dwPositionLeft = wp.rcNormalPosition.left;
+
+    /* Position X coordination of dialog's placement value key */
+    lResult = RegSetValueExW(hKey,
+                             L"WindowLeft",
+                             0,
+                             REG_DWORD,
+                             (BYTE *)&dwPositionLeft,
+                             sizeof(dwPositionLeft));
+
+    if (lResult != ERROR_SUCCESS)
+    {
+        /* Bail out and return FALSE if we fail */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
+    /* The value will be appended to the Y coordination dialog's placement */
+    dwPositionTop = wp.rcNormalPosition.top;
+
+    /* Position Y coordination of dialog's placement value key */
+    lResult = RegSetValueExW(hKey,
+                             L"WindowTop",
+                             0,
+                             REG_DWORD,
+                             (BYTE *)&dwPositionTop,
+                             sizeof(dwPositionTop));
+
+    if (lResult != ERROR_SUCCESS)
+    {
+        /* Bail out and return FALSE if we fail */
+        RegCloseKey(hKey);
+        return FALSE;
+    }
+
     /* If we're here then we succeed, close the key and return TRUE */
     RegCloseKey(hKey);
     return TRUE;