Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

al_resize_display issues #1514

Open
jarroddavis68 opened this issue Nov 26, 2023 · 1 comment
Open

al_resize_display issues #1514

jarroddavis68 opened this issue Nov 26, 2023 · 1 comment

Comments

@jarroddavis68
Copy link

This is the routine I use the scale the window to the current DPI:

procedure ScaleToDPI(ACenter: Boolean=False);
var
  x,y,w,h,dw,dh: Integer;
  LWnd: HWND;
begin
  LWnd := al_get_win_window_handle(display);
  FDpi := GetDpiForWindow(LWnd);
  FScale := FDpi / DEFAULT_DPI;

  w := Round(SCREEN_WIDTH*FScale);
  h := Round(SCREEN_HEIGHT*FScale);

  al_resize_display(display, w, h);

  dw := al_get_display_width(display) - w;
  dh := al_get_display_height(display) - h;

  if (dw <> 0) or (dh <> 0) then
    al_resize_display(display, w-dw, h-dh);

  al_acknowledge_resize(display);

  if ACenter then
  begin
    x := Round((GetSystemMetrics(SM_CXSCREEN) - al_get_display_width(display))/2);
    y := Round((GetSystemMetrics(SM_CYSCREEN) - al_get_display_height(display))/2);
    al_set_window_position(display, x, y);
  end;
end;

...
// called during a resize event to handle monitor change
ALLEGRO_EVENT_DISPLAY_RESIZE:
begin
  ScaleToDPI(False);
end;

...
// called to scale rendering to dpi
al_identity_transform(@transform);
al_scale_transform(@transform, FScale, FScale);
al_use_transform(@transform);

It now works because on my 4k monitor (144 dpi, 1.5 scale ratio I have set in Windows), after the first resize, al_get_display_width returns a value that is about 6 pixels larger than the expected value. So I have to get the delta width/height and resize it again so that current value return from al_get_display_width matches what is expected. Ok, so something must be going on with al_resize_display?

What made me aware of the issue was because I had to 100x100 rectangle drawn at the upper-right edge of the window, when I moved the window to a second monitor with a 96 dpi and thus a scale of 1, the same rect was not at the edge of screen. It was being resized but was not in the correct position, or so I thought. It turned out that al_resize_display was making the window larger than expected.

Any ideas?

@jarroddavis68
Copy link
Author

Ok, here are a few useful routines that I made to handle window resize/dpi moving across different monitors. I removed the win32 dependencies so as well so should be cross-platform. It takes into account the quark mentioned above. Seems to work (only tested on win64).

function al_get_display_dpi(const ADisplay: PALLEGRO_DISPLAY; AAdapter: PInteger): Integer;
var
  LAdapters, I, X, Y: Integer;
  LMonitorInfo: ALLEGRO_MONITOR_INFO;
begin
  Result := -1; // Default value if not found
  LAdapters := al_get_num_video_adapters();

  al_get_window_position(ADisplay, @X, @Y);

  for I := 0 to LAdapters - 1 do
  begin
    al_get_monitor_info(I, @LMonitorInfo);
    if (X >= LMonitorInfo.x1) and (X <= LMonitorInfo.x2) and (Y >= LMonitorInfo.y1) and (Y <= LMonitorInfo.y2) then
    begin
      Result := al_get_monitor_dpi(I);
      if Assigned(AAdapter) then
        AAdapter^ := I;
      Break;
    end;
  end;
end;

function al_scale_display_to_dpi(const ADisplay: PALLEGRO_DISPLAY; const ABaseWidth, ABaseHeight: Integer; ACenter: Boolean=False; ADpi: PInteger=nil; AScale: PSingle=nil; const ADefaultDPI: Integer=96): Boolean;
var
  X,Y: Integer;
  LWidth,LHeight: Integer;
  LDeltaWidth,LDeltaHeight: Integer;
  LAdaptor, LDpi: Integer;
  LScale: Single;
  LMonitorInfo: ALLEGRO_MONITOR_INFO;
  LMonitorWidth,LMonitorHeight: Integer;
begin
  Result := False;

  LDpi := al_get_display_dpi(ADisplay, @LAdaptor);
  if LDpi = -1 then Exit;

  if Assigned(ADpi) then
  begin
    ADpi^ := LDpi;
  end;

  LScale := LDpi / ADefaultDPI;
  if Assigned(AScale) then
  begin
    AScale^ := LScale;
  end;

  LWidth := Round(ABaseWidth*LScale);
  LHeight := Round(ABaseHeight*LScale);

  al_resize_display(ADisplay, LWidth, LHeight);

  LDeltaWidth := al_get_display_width(ADisplay) - LWidth;
  LDeltaHeight := al_get_display_height(ADisplay) - LHeight;

  if (LDeltaWidth <> 0) or (LDeltaHeight <> 0) then
    al_resize_display(ADisplay, LWidth-LDeltaWidth, LHeight-LDeltaHeight);

  al_acknowledge_resize(ADisplay);

  if ACenter then
  begin
    al_get_monitor_info(LAdaptor, @LMonitorInfo);
    LMonitorWidth := LMonitorInfo.x2 - LMonitorInfo.x1;
    LMonitorHeight := LMonitorInfo.y2 - LMonitorInfo.y1;

    X := Round((LMonitorWidth - al_get_display_width(ADisplay))/2);
    Y := Round((LMonitorHeight - al_get_display_height(ADisplay))/2);

    al_set_window_position(ADisplay, X, Y);
  end;

  Result := True;
end;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant