APSIMInitiative / ApsimX

ApsimX is the next generation of APSIM
http://www.apsim.info
Other
133 stars 162 forks source link

Pop up menu on other screen #6447

Closed hut104 closed 8 months ago

hut104 commented 3 years ago

When running an external monitor on my Surface pro, and APSIM UI maximised on external monitor, right-clicking on the tree creates a pop-up menu. However, the menu appears on my PC screen rather than the external monitor. I am running .NET Core version in VS Studio. It appears to matter not which window VS is sitting.

hol430 commented 2 years ago

@hut104 - I have a tentative fix for this one. No idea if it works or not as I don't see the problem on my machine. I've committed the fix to a branch on my repo.

hol353 commented 2 years ago

@hol430 We tried your branch and it doesn't fix the problem. It can be reproduced (on Windows) by having two monitors where your primary monitor is on the right of the secondary monitor and extending the desktop across both e.g.:

image

My laptop (surface pro) is my primary monitor on the right. My external monitor is the secondary monitor on the left. In this configuration, the popup menu is always shown on the primary monitor regardless of whether the GUI is running on primary or secondary monitor. If I swap the orientation of the monitors in the above screen shot then it works correctly no matter where the GUI is running.

One thing I noticed is that the Left screen coordinate of the GUI window, when running on the secondary monitor, has negative values. This seems to be the way GTK coordinates work in this situation. I've tried manually positioning the popup menu and it kind of works. I can position the menu on the far left of either monitor but not anywhere in the middle.

Anyway, I suspect this is a bug in GTK. See: https://bugs.webkit.org/show_bug.cgi?id=170553

How do we upgrade GTK to newer version to see if the fix at the link above fixes the problem?

hol430 commented 2 years ago

The linked bug report was for a bug in gtk(/gdk) under x11 (ie Linux). So it may be a different bug, even if the symptoms are similar. Regardless, it seems their suggested patch is the same as what I did on my branch? ie use PopupAtPointer(), which was added in gtk 3.22. We are already using a newer version of gtk than this - 3.24.24 if I remember correctly. Apologies if I'm missing something here - I only skimmed that bug report.

Anyway, if using PopupAtPointer() (aka my branch) didn't fix the problem (maybe a silly question, but I assume you remembered to recompile after switching branches?), then perhaps there is a difference in coordinate systems happening here. Some interesting pieces of information to know about your setup might be (just evaluate these expressions somehow while stopped at a breakpoint inside any view object):

MasterView.MainWindow.GetOrigin(out int frameX, out int frameY);
Gdk.Rectangle workArea = Gdk.Display.Default.GetMonitorAtWindow(((ViewBase)MasterView).MainWidget.Window).Workarea; // what are the properties of this rectangle?

Depending on the results, maybe the coordinates need to be transformed in some way. Or perhaps you could try using one of the other Popup* methods - e.g. PopupAtRect() or PopupAtWidget().

peter-devoil commented 2 years ago

I can't reproduce this under linux/x11 (libgtk-3.so.0.2404.16)

hol353 commented 2 years ago

Since I posted the above comment. I installed a newer version of GTK (3.24.31) onto my computer and the problem is fixed! We release 3.24.24 through the installers. I then did a comparison of the coordinate system between these two versions:

MasterView.MainWindow.GetOrigin:
x = 7, y = 336                     GTK 3.24.31
x = -1853, y = 336              GTK 3.24.24

Gdk.Rectangle workArea = Gdk.Display.Default.GetMonitorAtWindow:
workArea: (width, height, left, top): {2133x1140+0+184}  GTK 3.24.31
workArea: (width, height, left, top): {1368x852+0+0}     GTK 3.24.24

You can see that MainWindows.GetOrigin returns a very different x value for the newer version so obviously something in GTK has been changed.

I notice in the netcoreapp3.1\windows\apsimx.iss file that we get the gtk versions from https://github.com/GtkSharp/Dependencies. They don't seem to have a gtk version later than 3.24.24. I could put the files onto our web site somewhere - seems a bit hacky though. Suggestions?

Another Q: How does the Apsim GUI find the gtk version. When I installed GTK it added it to my path. The APSIM installers seem to put the gtk files in C:\Users\hol353\AppData\Local\Gtk. In my directory I have 2 versions of gtk: 3.24.24 and 3.24.2. How does APSIM choose between these two if I don't have gtk on the path?

function InstallGtk(): Boolean;
begin
    DownloadPage.AbortButton.Caption := 'Cancel';
    DownloadPage.Clear;
    DownloadPage.Add(ExpandConstant('https://github.com/GtkSharp/Dependencies/raw/master/{#GtkArchive}'), ExpandConstant('{#GtkArchive}'), '');
    DownloadPage.Show;
    try
        try
            DownloadPage.Download();
            ForceDirectories(ExpandConstant('{#GtkInstallPath}'));
            UnZip(ExpandConstant('{tmp}\{#GtkArchive}'), ExpandConstant('{#GtkInstallPath}'));
            DeleteFile('{tmp}\{#GtkArchive}');
            Result:= True;
        except
            if DownloadPage.AbortedByUser then
            begin
                Log('Download aborted by user.');
                SuppressibleMsgBox('Download aborted by user.', mbCriticalError, MB_OK, IDOK);
            end
            else
                SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK);
            DelTree(ExpandConstant('{#GtkInstallPath}'), True, True, True);
            Result:= False;
        end;
    finally
        DownloadPage.Hide;
    end;
end;
hol430 commented 2 years ago

You can see the library loading code here. One way might be to file a bug report in the GtkSharp repo (+maybe a minimal reproducible example) and ask them to update the version of the libs in the Dependencies project. Note that their dependencies are built from this repo which already contains gtk 3.24.31.

The faster way would probably be to maintain your own version of the libs and download that in the windows installer, rather than using the one maintained by the GtkSharp project.

hol353 commented 2 years ago

From the library loading code of GTK# it looks like it will first try and find GTK on the path and then look for specific directories (e.g. 3.24.24) under C:\Users\\AppData\Local\Gtk. In Linux world it only looks on the path. On Windows, I think we should just install GTK as a normal piece of software (like on Linux) and rely on the path to find it i.e. same as on Linux. We could source the installers here: https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases. Our setup program could check gtk versions and install newer version if one is present.

This is more transparent i.e. it appears on 'Start' menu and in 'Add/Remove programs', we can see what version users are using. A downside is that the GTK installers require admin privileges. Thoughts?

peter-devoil commented 2 years ago

No. We dont want to be where we were in classic with having a hidden .NET install alongside apsim. Also, in a few years time, who knows how many different versions of gtk will be in the user's path?

Is there a snap/flatpak/appimage for windows?

hol353 commented 2 years ago

with having a hidden .NET install

I assume you mean 'hidden .GTK install'.

Also, in a few years time, who knows how many different versions of gtk will be in the user's path?

Are you arguing for not relying on the users path to find GTK? I'm somewhat uncomfortable with relying on the path as users can have multiple GTKs on the path. But it's either that or look in specific directories.

Is there a snap/flatpak/appimage for windows?

No, not really. The APSIM installer can do silent installs of GTK from the link I posted above (download the .exe and run it with a /S) if it can't find a GTK3 version installed. If it does find one but it is an old one should it offer to do an upgrade of GTK?

hol430 commented 2 years ago

One option might be to bundle the gtk libs with apsim. This is what we do on Mac. It avoids the need to have certain versions of gtk installed in certain locations. There are downsides such as increased installation size though.

peter-devoil commented 2 years ago

WRT bundling: installation size shouldnt be a problem (it still fits on a USB stick, right?); and we have one less way for installations to go wrong.

par456 commented 8 months ago

This is now being handled by #7962, so closing this.