X-SLAYER / flutter_overlay_window

Flutter plugin for displaying flutter app over other apps on the screen
https://pub.dev/packages/flutter_overlay_window
MIT License
94 stars 98 forks source link

Values in resizeOverlay not coherent with values in showOverlay #82

Open jglatre opened 9 months ago

jglatre commented 9 months ago

I'm showing an overlay with parameters width: 500, height: 200 without any issue, then I try to double the height doing FlutterOverlayWindow.resizeOverlay(500, 400) and the window grows far too much, both in width and height. I've been trying with other values, trying to guess some correlation but to no avail, it seems like the two methods accept different units.

jglatre commented 9 months ago

Looking source code of OverlayService I see you are applying dpToPx to parameters of resizeOverlay buy not applying it to parameters of showOverlay. I hope that will be a hint.

rorystephenson commented 2 months ago

The initial width/height does not take in to account the display metrics whilst resizeOverlay does. A workaround is to apply the display metrics yourself when setting the initial width/height by multiplying your desired size by MediaQuery.devicePixelRatioOf(context). The result is not exactly identical as there seems to be a rounding difference but it should be within 1px.

EDIT: The rounding difference is avoidable. The resizeOverlay method applies the display metrics and then truncates (drops the decimal) the resulting width/height since it needs to be specified as an int. My setting of the initial width/height was rounding up to make sure I have at least as much space as I ask for. Two options to get a more consistent size:

  1. When applying the device pixel ratio to the original width/height, round down. This can result in a slightly lower size than desired.
  2. When calling resizeOverlay we can round up the width/height so that when it is multiplied by the device pixel ratio and then truncated it will be at least as large as our desired width/height. Unfortunately since the arguments to resizeOverlay are ints we cannot totally avoid unnecessary rounding up (without modifying the package). Here is an example method:
  static Future<bool?> resizeOverlay(BuildContext context, Size size) {
    final devicePixelRatio = MediaQuery.devicePixelRatioOf(context);

    final adjustedWidth =
        (((size.width * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();
    final adjustedHeight =
        (((size.height * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();

    return FlutterOverlayWindow.resizeOverlay(adjustedWidth, adjustedHeight);
  }