mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
This commit is contained in:
parent
cad4da738d
commit
b07a263c18
@ -120,7 +120,7 @@ Buffer const & Dialog::documentBuffer() const
|
||||
}
|
||||
|
||||
|
||||
void Dialog::showData(string const & data)
|
||||
void Dialog::showData(string const & data, Qt::FocusReason reason)
|
||||
{
|
||||
if (isBufferDependent() && !isBufferAvailable())
|
||||
return;
|
||||
@ -131,7 +131,7 @@ void Dialog::showData(string const & data)
|
||||
return;
|
||||
}
|
||||
|
||||
showView();
|
||||
showView(reason);
|
||||
}
|
||||
|
||||
|
||||
@ -169,25 +169,26 @@ void Dialog::prepareView()
|
||||
}
|
||||
|
||||
|
||||
void Dialog::showView()
|
||||
void Dialog::showView(Qt::FocusReason reason)
|
||||
{
|
||||
prepareView();
|
||||
|
||||
QWidget * w = asQWidget();
|
||||
if (!w->isVisible())
|
||||
w->show();
|
||||
if (!w->isVisible()) {
|
||||
w->setFocus(reason);
|
||||
w->show();
|
||||
}
|
||||
w->raise();
|
||||
w->activateWindow();
|
||||
if (wantInitialFocus())
|
||||
w->setFocus();
|
||||
w->setFocus(reason);
|
||||
else {
|
||||
lyxview_.raise();
|
||||
lyxview_.activateWindow();
|
||||
lyxview_.setFocus();
|
||||
lyxview_.setFocus(reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dialog::hideView()
|
||||
{
|
||||
QWidget * w = asQWidget();
|
||||
|
@ -88,7 +88,18 @@ public:
|
||||
//@{
|
||||
/// \param data is a string encoding of the data to be displayed.
|
||||
/// It is passed to the Controller to be translated into a usable form.
|
||||
virtual void showData(std::string const & data);
|
||||
virtual void showData(std::string const & data)
|
||||
{
|
||||
return showData(data, Qt::PopupFocusReason);
|
||||
}
|
||||
|
||||
/// \param data is a string encoding of the data to be displayed.
|
||||
/// It is passed to the Controller to be translated into a usable form.
|
||||
/// \param reason provides the focus reason of the dialog.
|
||||
/// E.g. dialog "findreplaceadv" requires special treatment after
|
||||
/// obtaining focus in terms of the input method item transformation,
|
||||
/// so should be marked as reason = Qt::OtherFocusReason.
|
||||
virtual void showData(std::string const & data, Qt::FocusReason reason);
|
||||
//@}
|
||||
|
||||
/// \return inset at current cursor location.
|
||||
@ -121,7 +132,14 @@ public:
|
||||
void hideView();
|
||||
|
||||
/// Prepare dialog and display it.
|
||||
void showView();
|
||||
void showView() { return showView(Qt::PopupFocusReason); }
|
||||
|
||||
/// Prepare dialog and display it.
|
||||
/// \param reason provides the focus reason of the dialog.
|
||||
/// E.g. dialog "findreplaceadv" requires special treatment after
|
||||
/// obtaining focus in terms of the input method item transformation,
|
||||
/// so should be marked as reason = Qt::OtherFocusReason.
|
||||
void showView(Qt::FocusReason reason);
|
||||
|
||||
/// Prepare dialog before view.
|
||||
void prepareView();
|
||||
|
@ -122,7 +122,7 @@ bool FindAndReplaceWidget::eventFilter(QObject * obj, QEvent * event)
|
||||
FuncRequest func = theTopLevelKeymap().getBinding(seq);
|
||||
if (!getStatus(func).enabled()) {
|
||||
LYXERR(Debug::FINDVERBOSE, "Focusing replace WA");
|
||||
replace_work_area_->setFocus();
|
||||
replace_work_area_->setFocus(Qt::TabFocusReason);
|
||||
LYXERR(Debug::FINDVERBOSE, "Selecting entire replace buffer");
|
||||
dispatch(FuncRequest(LFUN_BUFFER_BEGIN));
|
||||
dispatch(FuncRequest(LFUN_BUFFER_END_SELECT));
|
||||
@ -138,7 +138,7 @@ bool FindAndReplaceWidget::eventFilter(QObject * obj, QEvent * event)
|
||||
FuncRequest func = theTopLevelKeymap().getBinding(seq);
|
||||
if (!getStatus(func).enabled()) {
|
||||
LYXERR(Debug::FINDVERBOSE, "Focusing find WA");
|
||||
find_work_area_->setFocus();
|
||||
find_work_area_->setFocus(Qt::BacktabFocusReason);
|
||||
LYXERR(Debug::FINDVERBOSE, "Selecting entire find buffer");
|
||||
dispatch(FuncRequest(LFUN_BUFFER_BEGIN));
|
||||
dispatch(FuncRequest(LFUN_BUFFER_END_SELECT));
|
||||
|
@ -1217,6 +1217,13 @@ void GuiView::setFocus()
|
||||
}
|
||||
|
||||
|
||||
void GuiView::setFocus(Qt::FocusReason reason)
|
||||
{
|
||||
LYXERR(Debug::DEBUG, "GuiView::setFocus()" << this << " reason = " << reason);
|
||||
QMainWindow::setFocus(reason);
|
||||
}
|
||||
|
||||
|
||||
bool GuiView::hasFocus() const
|
||||
{
|
||||
if (currentWorkArea())
|
||||
@ -1234,11 +1241,11 @@ void GuiView::focusInEvent(QFocusEvent * e)
|
||||
// Make sure guiApp points to the correct view.
|
||||
guiApp->setCurrentView(this);
|
||||
if (currentWorkArea())
|
||||
currentWorkArea()->setFocus();
|
||||
currentWorkArea()->setFocus(e->reason());
|
||||
else if (currentMainWorkArea())
|
||||
currentMainWorkArea()->setFocus();
|
||||
currentMainWorkArea()->setFocus(e->reason());
|
||||
else
|
||||
d.bg_widget_->setFocus();
|
||||
d.bg_widget_->setFocus(e->reason());
|
||||
}
|
||||
|
||||
|
||||
@ -1571,6 +1578,9 @@ void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
|
||||
connectBufferView(wa->bufferView());
|
||||
connectBuffer(wa->bufferView().buffer());
|
||||
d.current_work_area_ = wa;
|
||||
// The below specifies that the input method item transformation will
|
||||
// not reset
|
||||
wa->setFocus(Qt::OtherFocusReason);
|
||||
QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
|
||||
this, SLOT(updateWindowTitle(GuiWorkArea *)));
|
||||
QObject::connect(wa, SIGNAL(busy(bool)),
|
||||
@ -1736,7 +1746,7 @@ bool GuiView::event(QEvent * e)
|
||||
case QEvent::WindowActivate: {
|
||||
GuiView * old_view = guiApp->currentView();
|
||||
if (this == old_view) {
|
||||
setFocus();
|
||||
setFocus(Qt::ActiveWindowFocusReason);
|
||||
return QMainWindow::event(e);
|
||||
}
|
||||
if (old_view && old_view->currentBufferView()) {
|
||||
@ -1749,7 +1759,7 @@ bool GuiView::event(QEvent * e)
|
||||
on_currentWorkAreaChanged(d.current_work_area_);
|
||||
else
|
||||
resetWindowTitle();
|
||||
setFocus();
|
||||
setFocus(Qt::ActiveWindowFocusReason);
|
||||
return QMainWindow::event(e);
|
||||
}
|
||||
|
||||
@ -4836,6 +4846,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
|
||||
|
||||
case LFUN_DIALOG_HIDE: {
|
||||
guiApp->hideDialogs(to_utf8(cmd.argument()), nullptr);
|
||||
setFocus(Qt::PopupFocusReason);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -5361,7 +5372,10 @@ void GuiView::doShowDialog(QString const & qname, QString const & qdata,
|
||||
Dialog * dialog = findOrBuild(name, false);
|
||||
if (dialog) {
|
||||
bool const visible = dialog->isVisibleView();
|
||||
dialog->showData(sdata);
|
||||
if (name == "findreplaceadv")
|
||||
dialog->showData(sdata, Qt::OtherFocusReason);
|
||||
else
|
||||
dialog->showData(sdata);
|
||||
if (currentBufferView())
|
||||
currentBufferView()->editInset(name, inset);
|
||||
// We only set the focus to the new dialog if it was not yet
|
||||
|
@ -131,6 +131,7 @@ public:
|
||||
|
||||
///
|
||||
void setFocus();
|
||||
void setFocus(Qt::FocusReason reason);
|
||||
bool hasFocus() const;
|
||||
|
||||
///
|
||||
|
@ -220,8 +220,14 @@ void GuiWorkArea::init()
|
||||
// Enables input methods for asian languages.
|
||||
// Must be set when creating custom text editing widgets.
|
||||
setAttribute(Qt::WA_InputMethodEnabled, true);
|
||||
// obtain transformation information to reset it when LyX gets refocus
|
||||
d->im_item_trans_ = d->im_->inputItemTransform();
|
||||
|
||||
// Initialize d->im_cursor_rect_
|
||||
Point point;
|
||||
Dimension dim;
|
||||
d->buffer_view_->caretPosAndDim(point, dim);
|
||||
int cur_x = point.x_ - dim.width();
|
||||
int cur_y = point.y_ + dim.height();
|
||||
d->im_cursor_rect_ = QRectF(cur_x, (cur_y - dim.height()) , 1, dim.height() );
|
||||
}
|
||||
|
||||
|
||||
@ -280,6 +286,9 @@ void GuiWorkArea::close()
|
||||
void GuiWorkArea::setFullScreen(bool full_screen)
|
||||
{
|
||||
d->buffer_view_->setFullScreen(full_screen);
|
||||
|
||||
queryInputItemTransform();
|
||||
|
||||
if (full_screen && lyxrc.full_screen_scrollbar)
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
else
|
||||
@ -684,12 +693,22 @@ void GuiWorkArea::contextMenuEvent(QContextMenuEvent * e)
|
||||
|
||||
void GuiWorkArea::focusInEvent(QFocusEvent * e)
|
||||
{
|
||||
LYXERR(Debug::DEBUG, "GuiWorkArea::focusInEvent(): " << this << endl);
|
||||
LYXERR(Debug::DEBUG, "GuiWorkArea::focusInEvent(): " << this << " reason() = " << e->reason() << endl);
|
||||
if (d->lyx_view_->currentWorkArea() != this) {
|
||||
d->lyx_view_->setCurrentWorkArea(this);
|
||||
d->lyx_view_->currentWorkArea()->bufferView().buffer().updateBuffer();
|
||||
}
|
||||
|
||||
// needs to reset IM item coordinates when focus in from dialogs or other apps
|
||||
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;
|
||||
} else {
|
||||
// Switched from advanced search dialog or else (e.g. mouse event)
|
||||
d->item_trans_needs_reset_ = false;
|
||||
}
|
||||
|
||||
startBlinkingCaret();
|
||||
QAbstractScrollArea::focusInEvent(e);
|
||||
}
|
||||
@ -1119,28 +1138,85 @@ void GuiWorkArea::resizeEvent(QResizeEvent * ev)
|
||||
}
|
||||
|
||||
|
||||
void GuiWorkArea::queryInputItemTransform()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#define DEBUG_PREEDIT
|
||||
|
||||
void GuiWorkArea::Private::paintPreeditText(GuiPainter & pain)
|
||||
{
|
||||
if (preedit_string_.empty())
|
||||
#ifdef DEBUG_PREEDIT
|
||||
// check the language that current input method uses
|
||||
QLocale::Language lang = im_->locale().language();
|
||||
if (lang != im_lang_) {
|
||||
LYXERR0("QLocale = " << QLocale::languageToString(lang));
|
||||
im_lang_ = lang;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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)
|
||||
return;
|
||||
|
||||
// FIXME: shall we use real_current_font here? (see #10478)
|
||||
FontInfo const font = buffer_view_->cursor().getFont().fontInfo();
|
||||
FontMetrics const & fm = theFontMetrics(font);
|
||||
// lower margin of the preedit area to separate the candidate window
|
||||
// report to IM the height of preedit rectangle larger than the actual by
|
||||
// preedit_lower_margin so that the conversion suggestion window does not
|
||||
// hide the underline of the preedit text
|
||||
int preedit_lower_margin = 1;
|
||||
|
||||
Point point;
|
||||
Dimension dim;
|
||||
buffer_view_->caretPosAndDim(point, dim);
|
||||
int cur_x = point.x_ - dim.width();
|
||||
int cur_y = point.y_ + dim.height();
|
||||
// lower margin of the preedit area to separate the candidate window
|
||||
// report to IM the height of preedit rectangle larger than the actual by
|
||||
// preedit_lower_margin so that the conversion suggestion window does not
|
||||
// hide the underline of the preedit text
|
||||
int preedit_lower_margin = 3;
|
||||
// reset item transformation since it gets wrong after the item get
|
||||
// lost and regain focus.
|
||||
im_->setInputItemTransform(im_item_trans_);
|
||||
|
||||
if (preedit_string_.empty()) {
|
||||
// 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);
|
||||
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();
|
||||
|
||||
// FIXME: shall we use real_current_font here? (see #10478)
|
||||
FontInfo const font = buffer_view_->cursor().getFont().fontInfo();
|
||||
FontMetrics const & fm = theFontMetrics(font);
|
||||
|
||||
// force fulldraw to remove previous paint remaining on screen
|
||||
// FIXME: This is costly to do
|
||||
buffer_view_->processUpdateFlags(Update::ForceDraw);
|
||||
|
||||
// get attributes of input method cursor.
|
||||
@ -1782,7 +1858,7 @@ bool TabWorkArea::setCurrentWorkArea(GuiWorkArea * work_area)
|
||||
else
|
||||
// Switch to the work area.
|
||||
setCurrentIndex(index);
|
||||
work_area->setFocus();
|
||||
work_area->setFocus(Qt::OtherFocusReason);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1809,6 +1885,11 @@ GuiWorkArea * TabWorkArea::addWorkArea(Buffer & buffer, GuiView & view)
|
||||
|
||||
updateTabTexts();
|
||||
|
||||
// obtain new input item coordinates in the new and old work areas
|
||||
wa->queryInputItemTransform();
|
||||
if (currentWorkArea())
|
||||
currentWorkArea()->queryInputItemTransform();
|
||||
|
||||
view.setBusy(false);
|
||||
|
||||
return wa;
|
||||
@ -1835,6 +1916,7 @@ bool TabWorkArea::removeWorkArea(GuiWorkArea * work_area)
|
||||
else
|
||||
// Show tabbar only if there's more than one tab.
|
||||
showBar(count() > 1);
|
||||
currentWorkArea()->queryInputItemTransform();
|
||||
} else
|
||||
lastWorkAreaRemoved();
|
||||
|
||||
|
@ -67,6 +67,8 @@ 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();
|
||||
|
||||
bool inDialogMode() const;
|
||||
void setDialogMode(bool mode);
|
||||
|
@ -100,6 +100,9 @@ struct GuiWorkArea::Private
|
||||
/// Change the cursor when the mouse hovers over a clickable inset
|
||||
void updateCursorShape();
|
||||
|
||||
/// Restore coordinate transformation information
|
||||
void resetInputItemTransform();
|
||||
/// Paint preedit text provided by the platform input method
|
||||
void paintPreeditText(GuiPainter & pain);
|
||||
|
||||
/// Prepare screen for next painting
|
||||
@ -136,6 +139,7 @@ struct GuiWorkArea::Private
|
||||
///
|
||||
bool need_resize_ = false;
|
||||
|
||||
/// provides access to the platform input method
|
||||
QInputMethod * im_ = QGuiApplication::inputMethod();
|
||||
/// the current preedit text of the input method
|
||||
docstring preedit_string_;
|
||||
@ -145,7 +149,10 @@ struct GuiWorkArea::Private
|
||||
QList<QInputMethodEvent::Attribute> preedit_attr_;
|
||||
QRectF im_cursor_rect_;
|
||||
QRectF im_anchor_rect_;
|
||||
QTransform im_item_trans_;
|
||||
QTransform item_trans_;
|
||||
bool item_trans_needs_reset_ = false;
|
||||
/// for debug
|
||||
QLocale::Language im_lang_;
|
||||
|
||||
/// Ratio between physical pixels and device-independent pixels
|
||||
/// We save the last used value to detect changes of the
|
||||
|
Loading…
Reference in New Issue
Block a user