mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
[client,SDL] Fix high-DPI handling and window sizing on scaled displays
This commit is contained in:
@@ -193,13 +193,8 @@ int sdl_list_monitors([[maybe_unused]] SdlContext* sdl)
|
||||
WINPR_ASSERT(rect.w > 0);
|
||||
WINPR_ASSERT(rect.h > 0);
|
||||
|
||||
bool highDpi = dpi > 100;
|
||||
|
||||
if (highDpi)
|
||||
// always enumerate fullscreen modes since SDL_GetDisplayBounds might return logical coords
|
||||
{
|
||||
// HighDPI is problematic with SDL: We can only get native resolution by creating a
|
||||
// window. Work around this by checking the supported resolutions (and keep maximum)
|
||||
// Also scale the DPI
|
||||
const SDL_Rect scaleRect = rect;
|
||||
int count = 0;
|
||||
auto modes = SDL_GetFullscreenDisplayModes(id, &count);
|
||||
@@ -234,8 +229,7 @@ int sdl_list_monitors([[maybe_unused]] SdlContext* sdl)
|
||||
const SDL_DisplayOrientation orientation = SDL_GetCurrentDisplayOrientation(id);
|
||||
const UINT32 rdp_orientation = sdl::utils::orientaion_to_rdp(orientation);
|
||||
|
||||
/* windows uses 96 dpi as 'default' and the scale factors are in percent. */
|
||||
const auto factor = dpi / 96.0f * 100.0f;
|
||||
const auto factor = dpi * 100.0f;
|
||||
monitor.orig_screen = id;
|
||||
monitor.x = rect.x;
|
||||
monitor.y = rect.y;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
@@ -27,12 +28,14 @@ SdlWindow::SdlWindow(SDL_DisplayID id, const std::string& title, const SDL_Rect&
|
||||
[[maybe_unused]] Uint32 flags)
|
||||
: _displayID(id)
|
||||
{
|
||||
// since scale not known until surface is mapped,
|
||||
// create 1×1 and sync to get scale, then resize to logical size
|
||||
auto props = SDL_CreateProperties();
|
||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title.c_str());
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, rect.x);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, rect.y);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, rect.w);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, rect.h);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, 1);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, 1);
|
||||
|
||||
if (flags & SDL_WINDOW_HIGH_PIXEL_DENSITY)
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, true);
|
||||
@@ -46,13 +49,22 @@ SdlWindow::SdlWindow(SDL_DisplayID id, const std::string& title, const SDL_Rect&
|
||||
_window = SDL_CreateWindowWithProperties(props);
|
||||
SDL_DestroyProperties(props);
|
||||
|
||||
auto sc = scale();
|
||||
const int iscale = static_cast<int>(sc * 100.0f);
|
||||
auto w = 100 * rect.w / iscale;
|
||||
auto h = 100 * rect.h / iscale;
|
||||
std::ignore = resize({ w, h });
|
||||
SDL_SetHint(SDL_HINT_APP_NAME, "");
|
||||
std::ignore = SDL_SyncWindow(_window);
|
||||
|
||||
if (!(flags & SDL_WINDOW_FULLSCREEN))
|
||||
{
|
||||
// windowed: convert physical pixels to logical coords
|
||||
auto sc = scale();
|
||||
if (sc < 1.0f)
|
||||
sc = 1.0f;
|
||||
auto logicalW = static_cast<int>(std::lroundf(static_cast<float>(rect.w) / sc));
|
||||
auto logicalH = static_cast<int>(std::lroundf(static_cast<float>(rect.h) / sc));
|
||||
std::ignore = resize({ logicalW, logicalH });
|
||||
std::ignore = SDL_SyncWindow(_window);
|
||||
}
|
||||
// fullscreen: SDL sizes the window to the display automatically
|
||||
|
||||
SDL_SetHint(SDL_HINT_APP_NAME, "");
|
||||
}
|
||||
|
||||
SdlWindow::SdlWindow(SdlWindow&& other) noexcept
|
||||
@@ -328,13 +340,18 @@ SdlWindow SdlWindow::create(SDL_DisplayID id, const std::string& title, Uint32 f
|
||||
{
|
||||
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||
|
||||
// width/height from caller is actual physical pixels
|
||||
SDL_Rect rect = { static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)),
|
||||
static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)), static_cast<int>(width),
|
||||
static_cast<int>(height) };
|
||||
|
||||
if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
|
||||
{
|
||||
std::ignore = SDL_GetDisplayBounds(id, &rect);
|
||||
// only use display bounds for positioning, let SDL handle fullscreen size
|
||||
SDL_Rect bounds = {};
|
||||
std::ignore = SDL_GetDisplayBounds(id, &bounds);
|
||||
rect.x = bounds.x;
|
||||
rect.y = bounds.y;
|
||||
}
|
||||
|
||||
SdlWindow window{ id, title, rect, flags };
|
||||
|
||||
Reference in New Issue
Block a user