]> git.lyx.org Git - lyx.git/commitdiff
Fix IM window position for a new window (#13094) master
authorKoji Yokota <koji.yokota@meisei-u.ac.jp>
Mon, 30 Sep 2024 00:00:56 +0000 (09:00 +0900)
committerKoji Yokota <koji.yokota@meisei-u.ac.jp>
Mon, 30 Sep 2024 00:00:56 +0000 (09:00 +0900)
src/frontends/qt/GuiApplication.cpp
src/frontends/qt/GuiApplication.h
src/frontends/qt/GuiWorkArea.cpp
src/frontends/qt/GuiWorkArea.h
src/frontends/qt/GuiWorkArea_Private.h

index fb974f7e1ddbf32f3ccf4237081ed2b2b21dd907..37623cbc60cdd8b82fe6dabf82b5eaab3cae98ac 100644 (file)
@@ -1083,6 +1083,13 @@ struct GuiApplication::Private
        ///
        KeyModifier meta_fake_bit;
 
+       /// input method uses this to preserve initial input item transform
+       bool first_work_area = true;
+       /// geometry of the input item of the first working area
+       QRectF item_rect_base_;
+       /// input item transformation of the first working area
+       QTransform item_trans_base_;
+
        /// The result of last dispatch action
        DispatchResult dispatch_result_;
 
@@ -2301,6 +2308,42 @@ docstring GuiApplication::viewStatusMessage()
 }
 
 
+bool GuiApplication::isFirstWorkArea() const
+{
+       return d->first_work_area;
+}
+
+
+void GuiApplication::firstWorkAreaDone()
+{
+       d->first_work_area = false;
+}
+
+
+QRectF GuiApplication::baseInputItemRectangle()
+{
+       return d->item_rect_base_;
+}
+
+
+void GuiApplication::setBaseInputItemRectangle(QRectF rect)
+{
+       d->item_rect_base_ = rect;
+}
+
+
+QTransform GuiApplication::baseInputItemTransform()
+{
+       return d->item_trans_base_;
+}
+
+
+void GuiApplication::setBaseInputItemTransform(QTransform trans)
+{
+       d->item_trans_base_ = trans;
+}
+
+
 string GuiApplication::inputLanguageCode() const
 {
        QLocale loc = inputMethod()->locale();
@@ -2586,6 +2629,11 @@ void GuiApplication::createView(bool autoShow, int view_id)
        if (d->global_menubar_)
                d->global_menubar_->releaseKeyboard();
 
+       // need to reset system input method coords with the preserved one
+       // when the new view is the second one or later
+       if (d->views_.size() > 0)
+               current_view_->currentWorkArea()->resetInputItemGeometry(true);
+
        // create new view
        int id = view_id;
        while (d->views_.find(id) != d->views_.end())
index 22e35c7d9fe2a1cc3a48a676ed6a1b9261b6989b..239a7e8a02bf2dd3e2499d3c84bffca24cd1c39d 100644 (file)
@@ -185,6 +185,19 @@ public:
        /// return the status bar state string
        docstring viewStatusMessage();
 
+       /// if current work area is the first one in the lyx application
+       bool isFirstWorkArea() const;
+       /// mark first work area is already set up
+       void firstWorkAreaDone();
+       /// input item rectangle of the base view
+       QRectF baseInputItemRectangle();
+       /// set input item rectangle of the base view
+       void setBaseInputItemRectangle(QRectF rect);
+       /// input item transform of the base view
+       QTransform baseInputItemTransform();
+       /// set input item transform of the base view
+       void setBaseInputItemTransform(QTransform trans);
+
        /// \name Methods to process FuncRequests
        //@{
        /// process the func request
index cc92408943d87df5739318bd2ff4ef9933c9d52a..4c71d17c070598ff970f2071d6d98001f0a7fd50 100644 (file)
@@ -286,7 +286,7 @@ void GuiWorkArea::setFullScreen(bool full_screen)
 {
        d->buffer_view_->setFullScreen(full_screen);
 
-       queryInputItemTransform();
+       queryInputItemGeometry();
 
        if (full_screen && lyxrc.full_screen_scrollbar)
                setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@@ -705,10 +705,10 @@ void GuiWorkArea::focusInEvent(QFocusEvent * e)
        if ((e->reason() == Qt::PopupFocusReason || e->reason() == Qt::ActiveWindowFocusReason) &&
                !(this->inDialogMode())) {
                // Switched from most of dialogs or other apps, and not on a dialog (e.g. findreplaceadv)
-               d->item_trans_needs_reset_ = true;
+               d->item_geom_needs_reset_ = true;
        } else {
                // Switched from advanced search dialog or else (e.g. mouse event)
-               d->item_trans_needs_reset_ = false;
+               d->item_geom_needs_reset_ = false;
        }
 
        startBlinkingCaret();
@@ -1142,33 +1142,111 @@ void GuiWorkArea::resizeEvent(QResizeEvent * ev)
 }
 
 
-void GuiWorkArea::queryInputItemTransform()
+void GuiWorkArea::queryInputItemGeometry()
 {
        LYXERR(
-                  Debug::DEBUG,
-                  "item_trans_ is aquired: dx() = " << d->item_trans_.dx() <<
-                  " -> " << d->im_->inputItemTransform().dx() <<
-                  ", dy() = " << d->item_trans_.dy() <<
-                  " -> " << d->im_->inputItemTransform().dy()
-                  );
-
-       d->item_trans_ = d->im_->inputItemTransform();
-}
-
+               Debug::DEBUG,
+               "item_rect_  is aquired:  x() = " << d->item_rect_.x() <<
+                       " -> " << d->sys_im_->inputItemRectangle().x() <<
+                       ",  y() = " << d->item_rect_.y() <<
+                       " -> " << d->sys_im_->inputItemRectangle().y() <<
+                       ", width() = " << d->item_rect_.width() <<
+                       " -> " << d->sys_im_->inputItemRectangle().width() <<
+                       ", height() = " << d->item_rect_.height() <<
+                       " -> " << d->sys_im_->inputItemRectangle().height()
+       );
+       LYXERR(
+          Debug::DEBUG,
+          "item_trans_ is aquired: dx() = " << d->item_trans_.dx() <<
+          " -> " << d->sys_im_->inputItemTransform().dx() <<
+          ", dy() = " << d->item_trans_.dy() <<
+          " -> " << d->sys_im_->inputItemTransform().dy()
+       );
+
+       d->item_rect_  = d->sys_im_->inputItemRectangle();
+       d->item_trans_ = d->sys_im_->inputItemTransform();
+
+       // save coordinates of the base working area for later use necessary to
+       // creat new GuiViews
+       if (guiApp->isFirstWorkArea()) {
+               guiApp->setBaseInputItemRectangle(d->item_rect_);
+               guiApp->setBaseInputItemTransform(d->item_trans_);
+               guiApp->firstWorkAreaDone();
 
-void GuiWorkArea::Private::resetInputItemTransform()
-{
-       if (item_trans_needs_reset_) {
                LYXERR(
-                          Debug::DEBUG,
-                          "(" << this <<
-                          ") item_trans_ is reset: dx() = " << im_->inputItemTransform().dx() <<
-                          " -> " << item_trans_.dx() <<
-                          ", dy() = " << im_->inputItemTransform().dy() <<
-                          " -> " << item_trans_.dy()
-                          );
-               im_->setInputItemTransform(item_trans_);
-               item_trans_needs_reset_ = false;
+                       Debug::DEBUG,
+                       "base inputItemRectangle x = " <<
+                                       guiApp->baseInputItemRectangle().x() <<
+                       ",  y = " << guiApp->baseInputItemRectangle().y() <<
+                       ", width = " << guiApp->baseInputItemRectangle().width() <<
+                       ", height = " << guiApp->baseInputItemRectangle().height()
+               );
+               LYXERR(
+                       Debug::DEBUG,
+                       "base inputItemTransform dx = " <<
+                                       guiApp->baseInputItemTransform().dx() <<
+                       ",  dy = " << guiApp->baseInputItemTransform().dy()
+               );
+       }
+}
+
+
+void GuiWorkArea::resetInputItemGeometry()
+{
+       resetInputItemGeometry(false);
+}
+
+void GuiWorkArea::resetInputItemGeometry(bool is_new_view)
+{
+       if (d->item_geom_needs_reset_) {
+               if (is_new_view) {
+                       LYXERR(
+                               Debug::DEBUG,
+                               "QInputMethod::inputItemRectangle is reset: x = " <<
+                                       d->sys_im_->inputItemRectangle().x() <<
+                                       " -> " << guiApp->baseInputItemRectangle().x() <<
+                                       ",  y = " << d->sys_im_->inputItemRectangle().y() <<
+                                       " -> " << guiApp->baseInputItemRectangle().y() <<
+                                       ", width = " << d->sys_im_->inputItemRectangle().width() <<
+                                       " -> " << guiApp->baseInputItemRectangle().width() <<
+                                       ", height = " << d->sys_im_->inputItemRectangle().height() <<
+                                       " -> " << guiApp->baseInputItemRectangle().height()
+                       );
+                       LYXERR(
+                               Debug::DEBUG,
+                               "QInputMethod::inputItemTransform is reset: dx = " <<
+                                       d->sys_im_->inputItemTransform().dx() <<
+                                       " -> " << guiApp->baseInputItemTransform().dx() <<
+                                       ", dy = " << d->sys_im_->inputItemTransform().dy() <<
+                                       " -> " << guiApp->baseInputItemTransform().dy()
+                       );
+                       d->sys_im_->setInputItemRectangle(guiApp->baseInputItemRectangle());
+                       d->sys_im_->setInputItemTransform(guiApp->baseInputItemTransform());
+               } else {
+                       LYXERR(
+                               Debug::DEBUG,
+                               "QInputMethod::inputItemRectangle is reset:  x = " <<
+                                       d->sys_im_->inputItemRectangle().x() <<
+                                       " -> " << d->item_rect_.x() <<
+                                       ",  y = " << d->sys_im_->inputItemRectangle().y() <<
+                                       " -> " << d->item_rect_.y() <<
+                                       ", width = " << d->sys_im_->inputItemRectangle().width() <<
+                                       " -> " << d->item_rect_.width() <<
+                                       ", height = " << d->sys_im_->inputItemRectangle().height() <<
+                                       " -> " << d->item_rect_.height()
+                       );
+                       LYXERR(
+                               Debug::DEBUG,
+                               "QInputMethod::inputItemTransform is reset: dx = " <<
+                                       d->sys_im_->inputItemTransform().dx() <<
+                                       " -> " << d->item_trans_.dx() <<
+                                       ", dy = " << d->sys_im_->inputItemTransform().dy() <<
+                                       " -> " << d->item_trans_.dy()
+                       );
+                       d->sys_im_->setInputItemRectangle(d->item_rect_);
+                       d->sys_im_->setInputItemTransform(d->item_trans_);
+               }
+               d->item_geom_needs_reset_ = false;
        }
 }
 
@@ -1179,7 +1257,7 @@ void GuiWorkArea::Private::paintPreeditText(GuiPainter & pain)
 {
 #ifdef DEBUG_PREEDIT
        // check the language that current input method uses
-       QLocale::Language lang = im_->locale().language();
+       QLocale::Language lang = sys_im_->locale().language();
        if (lang != im_lang_) {
                LYXERR0("QLocale = " << QLocale::languageToString(lang));
                im_lang_ = lang;
@@ -1188,7 +1266,7 @@ void GuiWorkArea::Private::paintPreeditText(GuiPainter & pain)
 
        // Chinese IM may want cursor position even when preedit string is empty
        // such a case is handled below
-       if (preedit_string_.empty() && im_->locale().language() != QLocale::Chinese)
+       if (preedit_string_.empty() && sys_im_->locale().language() != QLocale::Chinese)
                return;
 
        // lower margin of the preedit area to separate the candidate window
@@ -1207,13 +1285,13 @@ void GuiWorkArea::Private::paintPreeditText(GuiPainter & pain)
                // Chinese input methods may exit here just obtaining im_cursor_rect
                im_cursor_rect_ =
                        QRectF(cur_x, cur_y - dim.height(), 1, dim.height() + preedit_lower_margin);
-               im_->update(Qt::ImCursorRectangle);
+               sys_im_->update(Qt::ImCursorRectangle);
                return;
        }
 
        // reset item transformation since it can go wrong after the item gets
        // lost and regains focus or after a new tab (dis)appears etc.
-       resetInputItemTransform();
+       p->resetInputItemGeometry();
 
        // FIXME: shall we use real_current_font here? (see #10478)
        FontInfo const font = buffer_view_->cursor().getFont().fontInfo();
@@ -1360,7 +1438,7 @@ void GuiWorkArea::Private::paintPreeditText(GuiPainter & pain)
        }
        // Urge platform input method to make inputMethodQuery to check the values
        // set above
-       im_->update(Qt::ImQueryInput);
+       sys_im_->update(Qt::ImQueryInput);
 }
 
 
@@ -1910,9 +1988,9 @@ GuiWorkArea * TabWorkArea::addWorkArea(Buffer & buffer, GuiView & view)
        updateTabTexts();
 
        // obtain new input item coordinates in the new and old work areas
-       wa->queryInputItemTransform();
+       wa->queryInputItemGeometry();
        if (currentWorkArea())
-               currentWorkArea()->queryInputItemTransform();
+               currentWorkArea()->queryInputItemGeometry();
 
        view.setBusy(false);
 
@@ -1940,7 +2018,7 @@ bool TabWorkArea::removeWorkArea(GuiWorkArea * work_area)
                else
                        // Show tabbar only if there's more than one tab.
                        showBar(count() > 1);
-               currentWorkArea()->queryInputItemTransform();
+               currentWorkArea()->queryInputItemGeometry();
        } else
                lastWorkAreaRemoved();
 
index 391c31124306be2099fa5e3fec3608401142bc8c..446253248aaa859be1098cd3c59507db5ec1213a 100644 (file)
@@ -69,8 +69,14 @@ public:
 
        /// return true if the key is part of a shortcut
        bool queryKeySym(KeySymbol const & key, KeyModifier mod) const;
-       /// Ask relative position of input item coordinates against the main coordinates
-       void queryInputItemTransform();
+
+       /// Ask relative position of the input item coordinates against the main
+       /// coordinates to the system input method
+       void queryInputItemGeometry();
+       /// Restore coordinate transformation information
+       void resetInputItemGeometry();
+       /// Restore coordinate transformation information
+       void resetInputItemGeometry(bool is_new_view);
 
        bool inDialogMode() const;
        void setDialogMode(bool mode);
index 05bc1d8d777bd681538b6c20dee47c6aaae20a98..a7b278f59d9eb37d17d2d3346043153b0c39f823 100644 (file)
@@ -137,7 +137,7 @@ struct GuiWorkArea::Private
        bool need_resize_ = false;
 
        /// provides access to the platform input method
-       QInputMethod * im_ = QGuiApplication::inputMethod();
+       QInputMethod * sys_im_ = QGuiApplication::inputMethod();
        /// the current preedit text of the input method
        docstring preedit_string_;
        /// Number of lines used by preedit text
@@ -146,8 +146,12 @@ struct GuiWorkArea::Private
        QList<QInputMethodEvent::Attribute> preedit_attr_;
        QRectF im_cursor_rect_;
        QRectF im_anchor_rect_;
+       /// geometry of the input item
+       QRectF item_rect_;
+       /// transformation from input item coordinates to the working area
        QTransform item_trans_;
-       bool item_trans_needs_reset_ = false;
+       /// whether item_rect_ and item_trans need to be reset
+       bool item_geom_needs_reset_ = false;
        /// for debug
        QLocale::Language im_lang_ = QLocale::AnyLanguage;