Steps to reproduce: * Create a new database using the HSQLDB embedded backend (although it will probably happen with any backend) * Click on “Create Table in Design View…” * Type “MyField” in the “field name” column of the first row. Leave the type as the default. * Close the window * It will ask you if you want to save the changes. Press “yes”. * It will ask you to name the table. Click “ok”. * It will ask you if you want to create a primary key. Click “yes”. * Back in the main window, right click on “Table1” which is the only table in the list of tables * Click “Edit…” * Click on the row for the “MyField” field * Click on the text box for the “Default value” so that the cursor is inside * Close the window It should now crash. I looked into the problem a bit: The dispose method of FieldDescControl hides all of the controls. This causes the focus lost signal to be emitted before the dispose method completes. The handler for this ends up calling some pure virtual methods such as GetFormatter. If the disposal is invoked during the destructor this causes problems because C++ is defined to call the implementation of the method of the class whose destructor is currently being invoked. For GetFormatter the method is pure virtual and there is no implementation so the process aborts. I thought maybe one way to avoid the crash might be to just set a flag while we’re disposing and then return from the focus lost handler immediately if the flag is set. This avoids the crash but then there is the problem that any pending changes in the text box are lost when the window closes. I guess we want the suspend method of the window to try and make the text boxes all lose focus or make a more explicit way to flush the pending changes. I will try to look into this further. Reproduced with git master: Version: 26.2.0.0.alpha0+ (X86_64) / LibreOffice Community Build ID: 5eccc8085190a7c2b04848108b95b69cb0319022 CPU threads: 8; OS: Linux 6.16; UI render: default; VCL: gtk3 Locale: fr-FR (fr_FR.UTF-8); UI: en-US Calc: threaded and the version of LibreOffice shipped with Fedora: Version: 25.2.6.2 (X86_64) Build ID: 520(Build:2) CPU threads: 8; OS: Linux 6.16; UI render: default; VCL: gtk3 Locale: en-US (fr_FR.UTF-8); UI: fr-FR Calc: threaded
Tested following all the steps with Version: 25.8.2.2 (X86_64) Build ID: d401f2107ccab8f924a8e2df40f573aab7605b6f CPU threads: 6; OS: Linux 6.4; UI render: default; VCL: kf5 (cairo+xcb) Locale: de-DE (de_DE.UTF-8); UI: de-DE Calc: threaded Couldn't reproduce a crash with new internal HSQLDB. Might be a special gtk3 bug.
Thanks for checking that. Yeah, I can’t reproduce the bug on my Mac either, so it must be a GTK3 problem. Version: 26.2.0.0.alpha0+ (X86_64) / LibreOffice Community Build ID: a9fe7eaa6501e41a01158ae412d4051c6441595b CPU threads: 4; OS: macOS 15.6.1; UI render: Skia/Metal; VCL: osx Locale: fr-FR (fr_FR.UTF-8); UI: en-US Calc: threaded On the Mac the focus is lost before calling the destructor so everything works correctly without ending up invoking a non-existant pure-virtual override. The focus is lost because of this line in OTableController::suspend if ( getView() ) static_cast<OTableDesignView*>(getView())->GrabFocus(); There’s no comment about what that is trying to achieve, but we can get some information from the commit message. It was added in 568af9ac86c8eee3531ff9cb718aeba240f274be. That has a whole bunch of changes bundled together but one of them is: r263362 : #i93383# grabFocus in suspend to get allmodified cells So I think that line was explicitly added to try and get the controls to flush their pending changes. So I guess one way to fix it could be to figure out why that call doesn’t make the control lose focus on GTK3. Or another way could be to replace that with a more explicit function to make the controls flush their state.
It looks like the focus handling on the GTK3 backend is a bit buggy and that’s why the table controls never get the lost focus event when GrabFocus() is called. With that backend ImplGetSVData()->mpWinData->mpFocusWin is always null so when GrabFocus is called it doesn’t know who to send the event to. It also doesn’t keep track of whether a toplevel window is focused so WindowImpl->mbFrameData->mbHasFocus is always false for all frames. That makes GrabFocus bail out early and just raise the window to the top instead of changing the focus. I think the backend is meant to set mbFrameData->mbHasFocus by sending SalEvent::GetFocus when the frame gets focus. It looks like there is code to handle this (see the bottom of GtkSalFrame::signalFocus) but it’s tracking the keyboard focus instead of the toplevel window focus. I think it doesn’t work because the widget for the toplevel window never gets the keyboard focus itself so the code always thinks another window has the focus and only sends SalEvent::LoseFocus. I think this should be implemented by tracking the GDK_WINDOW_STATE_FOCUS state instead because that directly corresponds to the toplevel window focus. On the MacOS backend the event is sent in response to the [windowDidBecomeKey] message which I think is the equivalent of GDK_WINDOW_STATE_FOCUS. On the GTK4 backend the toplevel window focus also seems to use the keyboard focus to track the window focus, but I think it ends up working because the keyboard focus events bubble up to the toplevel window widget. If any child widget has the keyboard focus then it will end up considering the window to have focus as well. It would probably be more robust to track GDK_TOPLEVEL_STATE_FOCUS instead though. For ImplGetSVData()->mpWinData->mpFocusWin, on the MacOS backend it looks like this gets set by the controls themselves by calling GrabFocus in response to mouse click events. On the GTK backend, the controls are directly created with GtkBuilder so as far as I can tell it doesn’t actually construct an Edit::Edit control so nothing registers to listen for the mouse clicks and nothing calls GrabFocus. My preferred option so far then is to try to add a more explicit way to make OFieldDescControl flush its input instead of relying on only the focus leave events seeing as they don’t seem very reliable.
Note that since 037a9b4e3ccd0f3978f613c5a2feef44d9b2668d on git master, in order to trigger the crash you have to type a character into the text box for the default value just before closing the window as the last step. The crash can also be triggered on the wizards to create a new table or to copy a table.
Neil Roberts committed a patch related to this issue. It has been pushed to "master": https://git.libreoffice.org/core/commit/3431eb08cd3f84c589f78791a1daedf309566cbc tdf#168970 OFieldDescControl: Add explicit method to flush changes It will be available in 26.2.0. The patch should be included in the daily builds available at https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More information about daily builds can be found at: https://wiki.documentfoundation.org/Testing_Daily_Builds Affected users are encouraged to test the fix and report feedback.
Neil Roberts committed a patch related to this issue. It has been pushed to "master": https://git.libreoffice.org/core/commit/f368b81bfb741bd9a206a2a09d47b9ec38d35ae4 tdf#168970 Remove {OFieldDescControl,OTableFieldControl}::dispose It will be available in 26.2.0. The patch should be included in the daily builds available at https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More information about daily builds can be found at: https://wiki.documentfoundation.org/Testing_Daily_Builds Affected users are encouraged to test the fix and report feedback.