diff --git a/base/applications/osk/main.c b/base/applications/osk/main.c index 972f8c8e9b9..92e1a05b5b8 100644 --- a/base/applications/osk/main.c +++ b/base/applications/osk/main.c @@ -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’t 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 */ diff --git a/base/applications/osk/main.h b/base/applications/osk/main.h index 137cf5b2ca7..da4cf2a7bae 100644 --- a/base/applications/osk/main.h +++ b/base/applications/osk/main.h @@ -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 ********************************************************************/ diff --git a/base/applications/osk/settings.c b/base/applications/osk/settings.c index 03eb18f62e8..d7dab32eaf7 100644 --- a/base/applications/osk/settings.c +++ b/base/applications/osk/settings.c @@ -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;