mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-10-06 07:00:16 +08:00
Merge branch 'ime-control'
Provide some control over IME and use it to fix wxGrid when using IME. See #27026.
This commit is contained in:
@@ -3223,6 +3223,10 @@ private:
|
||||
// the edit control is shown, but just supposes that it is.
|
||||
void DoSaveEditControlValue();
|
||||
|
||||
// Update the state of the IME when anything affecting it changed.
|
||||
void UpdateIME();
|
||||
|
||||
|
||||
// these sets contain the indices of fixed, i.e. non-resizable
|
||||
// interactively, grid rows or columns and are null if there are no fixed
|
||||
// elements (which is the default)
|
||||
|
||||
@@ -427,6 +427,10 @@ public:
|
||||
|
||||
wxGridWindowType GetType() const { return m_type; }
|
||||
|
||||
// Update the position of the input method windows to correspond to the
|
||||
// current cell.
|
||||
void UpdateIMECursorRect();
|
||||
|
||||
private:
|
||||
const wxGridWindowType m_type;
|
||||
|
||||
|
||||
@@ -339,6 +339,9 @@ public:
|
||||
// "commit" signal handler.
|
||||
bool GTKDoInsertTextFromIM(const char* text);
|
||||
|
||||
// Actual implementation of DoUpdateInputMethodCursorRect().
|
||||
void GTKUpdateIMCursorRect(GtkIMContext* imContext) const;
|
||||
|
||||
|
||||
// indices for the arrays below
|
||||
enum ScrollDir { ScrollDir_Horz, ScrollDir_Vert, ScrollDir_Max };
|
||||
@@ -416,6 +419,8 @@ protected:
|
||||
virtual void DoSetClientSize(int width, int height) override;
|
||||
virtual void DoMoveWindow(int x, int y, int width, int height) override;
|
||||
virtual void DoEnable(bool enable) override;
|
||||
virtual void DoEnableInputMethod(bool enable) override;
|
||||
virtual void DoUpdateInputMethodCursorRect() override;
|
||||
|
||||
#if wxUSE_MENUS_NATIVE
|
||||
virtual bool DoPopupMenu( wxMenu *menu, int x, int y ) override;
|
||||
|
||||
@@ -688,6 +688,7 @@ protected:
|
||||
virtual void DoReleaseMouse() override;
|
||||
|
||||
virtual void DoEnable(bool enable) override;
|
||||
virtual void DoEnableInputMethod(bool enable) override;
|
||||
|
||||
virtual void DoFreeze() override;
|
||||
virtual void DoThaw() override;
|
||||
|
||||
@@ -1304,6 +1304,27 @@ public:
|
||||
wxCaret *GetCaret() const { return m_caret; }
|
||||
#endif // wxUSE_CARET
|
||||
|
||||
// input method (IME) support
|
||||
// --------------------------
|
||||
|
||||
// enable or disable input method for this window, it's enabled by
|
||||
// default but can be disabled for windows not accepting text input
|
||||
void EnableInputMethod(bool enable = true);
|
||||
bool IsInputMethodEnabled() const { return m_enableIME; }
|
||||
|
||||
// set the rectangle, in client coordinates, where the text is being
|
||||
// input: the input method windows are positioned near it
|
||||
//
|
||||
// this must be called by the windows accepting text input whenever
|
||||
// this rectangle changes, e.g. because the insertion point moved or
|
||||
// the window was scrolled
|
||||
void UpdateInputMethodCursorRect(const wxRect& rect);
|
||||
|
||||
// return the rectangle set by the function above for this window, or
|
||||
// an empty rectangle, meaning that the input method default position
|
||||
// is used, if it wasn't set for it
|
||||
wxRect GetInputMethodCursorRect() const;
|
||||
|
||||
// get the (average) character size for the current font
|
||||
virtual int GetCharHeight() const = 0;
|
||||
virtual int GetCharWidth() const = 0;
|
||||
@@ -1799,6 +1820,15 @@ protected:
|
||||
// widgets state are necessary
|
||||
virtual void DoEnable(bool WXUNUSED(enable)) { }
|
||||
|
||||
// this method should be implemented to really enable or disable input
|
||||
// method for this window, it's only called if the state changes
|
||||
virtual void DoEnableInputMethod(bool WXUNUSED(enable)) { }
|
||||
|
||||
// this method can be implemented to really update the input method
|
||||
// windows position, using GetInputMethodCursorRect(), it's only called if
|
||||
// the input method is enabled
|
||||
virtual void DoUpdateInputMethodCursorRect() { }
|
||||
|
||||
|
||||
// the window id - a number which uniquely identifies a window among
|
||||
// its siblings unless it is wxID_ANY
|
||||
@@ -1890,6 +1920,9 @@ protected:
|
||||
bool m_disableFocusFromKbd:1;
|
||||
bool m_enableFocusFromKbd:1;
|
||||
|
||||
// flag controlling the use of IME (enabled by default)
|
||||
bool m_enableIME:1;
|
||||
|
||||
// window attributes
|
||||
long m_windowStyle,
|
||||
m_exStyle;
|
||||
@@ -2077,6 +2110,12 @@ private:
|
||||
// (i.e. not being updated) if it is positive
|
||||
unsigned int m_freezeCount;
|
||||
|
||||
// The window for which the input method cursor rectangle was set and the
|
||||
// rectangle itself: as only the window having the focus can use it, we
|
||||
// don't need to store it in every window.
|
||||
static const wxWindowBase* ms_imeCursorWindow;
|
||||
static wxRect ms_imeCursorRect;
|
||||
|
||||
wxDECLARE_ABSTRACT_CLASS(wxWindowBase);
|
||||
wxDECLARE_NO_COPY_CLASS(wxWindowBase);
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
||||
@@ -688,6 +688,13 @@ public:
|
||||
|
||||
If the key is F2 (special), editing will always start and this
|
||||
method will not be called at all (but StartingKey() will)
|
||||
|
||||
Note that this function must not change the editor contents: this should
|
||||
be only done in StartingKey() which will be called later.
|
||||
|
||||
Also note that this function is called with a special synthetic event
|
||||
for the letter "A" to check if the editor accepts text input and whether
|
||||
the IME should be enabled for it.
|
||||
*/
|
||||
virtual bool IsAcceptedKey(wxKeyEvent& event);
|
||||
|
||||
|
||||
@@ -603,6 +603,94 @@ public:
|
||||
///@}
|
||||
|
||||
|
||||
/**
|
||||
@name Input method functions
|
||||
|
||||
Input methods (IMEs) are used for entering text in languages such as
|
||||
Chinese or Japanese, in which a single character is typically composed
|
||||
using several key presses.
|
||||
|
||||
Native controls, such as wxTextCtrl, handle input methods on their own,
|
||||
but custom windows may need to use these functions to indicate whether
|
||||
they accept text input at all and where the IME window should be shown
|
||||
if they do.
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
Enable or disable input method for this window.
|
||||
|
||||
Input method is enabled for all windows by default, but it may be
|
||||
useful to disable it for custom windows which don't accept text input,
|
||||
as otherwise the input method windows may still be shown when the user
|
||||
types in them, even though the text entered in them is ignored.
|
||||
|
||||
Note that input method can be disabled or enabled at any time, e.g. a
|
||||
custom control could enable it only when its current item is
|
||||
editable.
|
||||
|
||||
This function is currently implemented for wxMSW, wxGTK and wxOSX. In
|
||||
wxGTK and wxOSX it doesn't affect native controls which always handle
|
||||
input method themselves.
|
||||
|
||||
@see IsInputMethodEnabled()
|
||||
|
||||
@since 3.3.4
|
||||
*/
|
||||
void EnableInputMethod(bool enable = true);
|
||||
|
||||
/**
|
||||
Return @true if input method is enabled for this window.
|
||||
|
||||
Note that this function simply returns @false if EnableInputMethod()
|
||||
was called with @false argument and doesn't check whether the input
|
||||
method is actually used by the window or not.
|
||||
|
||||
@since 3.3.4
|
||||
*/
|
||||
bool IsInputMethodEnabled() const;
|
||||
|
||||
/**
|
||||
Set the area where the text is being entered.
|
||||
|
||||
Custom windows accepting text input should call this function to let
|
||||
the input method know where to show its windows, e.g. the one with the
|
||||
text being composed or the list of candidates for it. For a custom
|
||||
text control, @a rect would be the rectangle corresponding to the
|
||||
current insertion point position.
|
||||
|
||||
This function must be called whenever this rectangle changes, e.g.
|
||||
when the insertion point moves or the window is scrolled. Note that
|
||||
it is not sufficient to update the rectangle when a key is pressed
|
||||
because some input methods, e.g. Fcitx under Linux, process the keys
|
||||
before the window receives them.
|
||||
|
||||
This function is currently implemented for wxMSW, wxGTK and wxOSX.
|
||||
|
||||
@param rect
|
||||
The rectangle in client coordinates or an empty rectangle to let
|
||||
the input method use its default position.
|
||||
|
||||
@see GetInputMethodCursorRect()
|
||||
|
||||
@since 3.3.4
|
||||
*/
|
||||
void UpdateInputMethodCursorRect(const wxRect& rect);
|
||||
|
||||
/**
|
||||
Return the area where the text is being entered.
|
||||
|
||||
This is the rectangle last passed to UpdateInputMethodCursorRect() for
|
||||
this window or an empty rectangle if it hadn't been called for it or
|
||||
if another window has called it since.
|
||||
|
||||
@since 3.3.4
|
||||
*/
|
||||
wxRect GetInputMethodCursorRect() const;
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
/**
|
||||
@name Child management functions
|
||||
*/
|
||||
|
||||
@@ -317,6 +317,8 @@ wxWindowBase::wxWindowBase()
|
||||
m_disableFocusFromKbd = false;
|
||||
m_enableFocusFromKbd = false;
|
||||
|
||||
m_enableIME = true;
|
||||
|
||||
#if wxUSE_DRAG_AND_DROP
|
||||
m_dropTarget = nullptr;
|
||||
#endif // wxUSE_DRAG_AND_DROP
|
||||
@@ -461,6 +463,9 @@ wxWindowBase::~wxWindowBase()
|
||||
// immediately: don't leave dangling pointers.
|
||||
wxPendingDelete.DeleteObject(this);
|
||||
|
||||
if ( ms_imeCursorWindow == this )
|
||||
ms_imeCursorWindow = nullptr;
|
||||
|
||||
// Just in case we've loaded a top-level window via LoadNativeDialog but
|
||||
// we weren't a dialog class
|
||||
wxTopLevelWindows.DeleteObject(this);
|
||||
@@ -1788,6 +1793,46 @@ void wxWindowBase::SetCaret(wxCaret *caret)
|
||||
}
|
||||
#endif // wxUSE_CARET
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// input method support
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxWindowBase::EnableInputMethod(bool enable)
|
||||
{
|
||||
if ( enable == m_enableIME )
|
||||
return;
|
||||
|
||||
m_enableIME = enable;
|
||||
|
||||
DoEnableInputMethod(enable);
|
||||
}
|
||||
|
||||
// Store just a single IME rectangle for all windows instead of adding wxRect
|
||||
// member to each window because only one window can have the IME focus at a
|
||||
// time and it would be wasteful to increase the size of all windows when we
|
||||
// can avoid it.
|
||||
const wxWindowBase* wxWindowBase::ms_imeCursorWindow = nullptr;
|
||||
wxRect wxWindowBase::ms_imeCursorRect;
|
||||
|
||||
wxRect wxWindowBase::GetInputMethodCursorRect() const
|
||||
{
|
||||
return ms_imeCursorWindow == this ? ms_imeCursorRect : wxRect();
|
||||
}
|
||||
|
||||
void wxWindowBase::UpdateInputMethodCursorRect(const wxRect& rect)
|
||||
{
|
||||
if ( ms_imeCursorWindow == this && rect == ms_imeCursorRect )
|
||||
return;
|
||||
|
||||
ms_imeCursorWindow = this;
|
||||
ms_imeCursorRect = rect;
|
||||
|
||||
// Don't bother updating the position if the input method is not used, it
|
||||
// will be updated when it is enabled.
|
||||
if ( m_enableIME )
|
||||
DoUpdateInputMethodCursorRect();
|
||||
}
|
||||
|
||||
#if wxUSE_VALIDATORS
|
||||
// ----------------------------------------------------------------------------
|
||||
// validators
|
||||
|
||||
@@ -2154,6 +2154,10 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
|
||||
m_count = -1;
|
||||
m_underMouse = nullptr;
|
||||
|
||||
// Disable IME for this window: it accepts focus but doesn't accept text
|
||||
// input, only in-place text controls created when editing do.
|
||||
EnableInputMethod(false);
|
||||
|
||||
UpdateDisplay();
|
||||
}
|
||||
|
||||
|
||||
@@ -2790,6 +2790,9 @@ void wxGrid::ScrollWindow( int dx, int dy, const wxRect *rect )
|
||||
|
||||
m_rowLabelWin->ScrollWindow( 0, dy, rect );
|
||||
m_colLabelWin->ScrollWindow( dx, 0, rect );
|
||||
|
||||
// The position of the current cell has changed.
|
||||
UpdateIME();
|
||||
}
|
||||
|
||||
void wxGridWindow::OnMouseEvent( wxMouseEvent& event )
|
||||
@@ -2853,10 +2856,40 @@ void wxGridWindow::OnFocus(wxFocusEvent& event)
|
||||
Refresh(true, &cursor);
|
||||
}
|
||||
|
||||
// Update IME state in case the current cell editability changed while we
|
||||
// didn't have focus.
|
||||
if ( event.GetEventType() == wxEVT_SET_FOCUS )
|
||||
m_owner->UpdateIME();
|
||||
|
||||
if ( !m_owner->ProcessWindowEvent( event ) )
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void wxGridWindow::UpdateIMECursorRect()
|
||||
{
|
||||
// We don't have any caret, so put the input method windows over the
|
||||
// current cell.
|
||||
const wxGridCellCoords& coords = m_owner->GetGridCursorCoords();
|
||||
if ( coords == wxGridNoCellCoords )
|
||||
{
|
||||
UpdateInputMethodCursorRect(wxRect());
|
||||
return;
|
||||
}
|
||||
|
||||
// The current cell may be in a different grid window when using frozen
|
||||
// rows or columns, so compute its position in this window coordinates.
|
||||
wxGridWindow* const cellWin = m_owner->CellToGridWindow(coords);
|
||||
|
||||
wxRect rect = m_owner->CellToRect(coords);
|
||||
rect.Offset(-m_owner->GetGridWindowOffset(cellWin));
|
||||
rect.SetPosition(m_owner->CalcGridWindowScrolledPosition(rect.GetPosition(),
|
||||
cellWin));
|
||||
if ( cellWin != this )
|
||||
rect.SetPosition(ScreenToClient(cellWin->ClientToScreen(rect.GetPosition())));
|
||||
|
||||
UpdateInputMethodCursorRect(rect);
|
||||
}
|
||||
|
||||
// Unlike XToCol() and YToRow() these macros always return a valid column/row,
|
||||
// so their results don't need to be checked, while the results of the public
|
||||
// functions always must be.
|
||||
@@ -6281,6 +6314,50 @@ void wxGrid::UpdateColours()
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// keyboard handling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Enable input method for the grid windows only if the current cell can be
|
||||
// edited: otherwise typing just shows the IME windows without doing anything.
|
||||
//
|
||||
// Also update the IME windows position, as it depends on the current cell.
|
||||
void wxGrid::UpdateIME()
|
||||
{
|
||||
bool enable = CanEnableCellControl();
|
||||
|
||||
if ( enable )
|
||||
{
|
||||
// Even if the current cell can be edited, its editor may not accept
|
||||
// any text at all, as is the case for the boolean editor, for
|
||||
// example, and showing IME for it would be useless. Check for this by
|
||||
// asking the editor whether it would start editing if a letter were
|
||||
// typed.
|
||||
wxKeyEvent event(wxEVT_CHAR);
|
||||
event.m_keyCode = 'a';
|
||||
event.m_uniChar = 'a';
|
||||
|
||||
enable = GetCurrentCellEditorPtr()->IsAcceptedKey(event);
|
||||
}
|
||||
|
||||
wxGridWindow* const allGridWindows[] =
|
||||
{
|
||||
m_gridWin,
|
||||
m_frozenCornerGridWin,
|
||||
m_frozenRowGridWin,
|
||||
m_frozenColGridWin,
|
||||
};
|
||||
|
||||
for ( wxGridWindow* win : allGridWindows )
|
||||
{
|
||||
if ( !win )
|
||||
continue;
|
||||
|
||||
win->EnableInputMethod(enable);
|
||||
win->UpdateIMECursorRect();
|
||||
}
|
||||
}
|
||||
|
||||
void wxGrid::OnKeyDown( wxKeyEvent& event )
|
||||
{
|
||||
// propagate the event up and see if it gets processed
|
||||
@@ -6603,6 +6680,18 @@ void wxGrid::OnChar( wxKeyEvent& event )
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
else if ( IsCellEditControlEnabled() )
|
||||
{
|
||||
// We can get here if more than one character is input at once, as it
|
||||
// happens when using IME: the first character starts editing, but the
|
||||
// subsequent ones are still sent to the grid window and not to the
|
||||
// editor, so forward them to it.
|
||||
wxGridCellEditorPtr editor = GetActiveCellEditorPtr();
|
||||
if ( editor->IsAcceptedKey(event) )
|
||||
editor->StartingKey(event);
|
||||
else
|
||||
event.Skip();
|
||||
}
|
||||
else
|
||||
{
|
||||
event.Skip();
|
||||
@@ -6698,6 +6787,8 @@ bool wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
|
||||
|
||||
m_currentCellCoords = coords;
|
||||
|
||||
UpdateIME();
|
||||
|
||||
RefreshBlock(coords);
|
||||
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
@@ -7927,6 +8018,8 @@ void wxGrid::EnableEditing( bool edit )
|
||||
if (!edit)
|
||||
EnableCellEditControl(edit);
|
||||
m_editable = edit;
|
||||
|
||||
UpdateIME();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10320,6 +10413,9 @@ void wxGrid::SetReadOnly(int row, int col, bool isReadOnly)
|
||||
if ( CanHaveAttributes() )
|
||||
{
|
||||
GetOrCreateCellAttrPtr(row, col)->SetReadOnly(isReadOnly);
|
||||
|
||||
if ( wxGridCellCoords(row, col) == m_currentCellCoords )
|
||||
UpdateIME();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,11 +147,17 @@ void wxScrollHelper::DoScrollOneDir(int orient,
|
||||
m_win->SetScrollPos(orient, pos);
|
||||
pos = m_win->GetScrollPos(orient);
|
||||
|
||||
const int diff = (*posOld - pos)*pixelsPerLine;
|
||||
|
||||
// Update the position before calling ScrollWindow(), as it may use
|
||||
// GetViewStart(), which must already return the new position, as it
|
||||
// does in the other ports.
|
||||
*posOld = pos;
|
||||
|
||||
const bool scrollingEnabled =
|
||||
orient == wxHORIZONTAL ? m_xScrollingEnabled : m_yScrollingEnabled;
|
||||
if ( scrollingEnabled )
|
||||
{
|
||||
int diff = (*posOld - pos)*pixelsPerLine;
|
||||
m_targetWindow->ScrollWindow(orient == wxHORIZONTAL ? diff : 0,
|
||||
orient == wxHORIZONTAL ? 0 : diff);
|
||||
}
|
||||
@@ -161,8 +167,6 @@ void wxScrollHelper::DoScrollOneDir(int orient,
|
||||
// physical move of the pixels is disabled.
|
||||
m_targetWindow->Refresh(true, GetScrollRect());
|
||||
}
|
||||
|
||||
*posOld = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+53
-4
@@ -1473,8 +1473,52 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
|
||||
|
||||
int wxWindowGTK::GTKIMFilterKeypress(GdkEventKey* event) const
|
||||
{
|
||||
return m_imContext ? gtk_im_context_filter_keypress(m_imContext, event)
|
||||
: FALSE;
|
||||
if ( !m_imContext || !IsInputMethodEnabled() )
|
||||
return FALSE;
|
||||
|
||||
// Note that the input method may handle the keys before we get them, e.g.
|
||||
// Fcitx does this by default, so updating the cursor location here is not
|
||||
// enough and UpdateInputMethodCursorRect() must be called when it
|
||||
// changes, but still do it here to be sure it's up to date.
|
||||
GTKUpdateIMCursorRect(m_imContext);
|
||||
|
||||
return gtk_im_context_filter_keypress(m_imContext, event);
|
||||
}
|
||||
|
||||
void wxWindowGTK::DoEnableInputMethod(bool enable)
|
||||
{
|
||||
// We don't need to do anything if we don't have the focus, as the input
|
||||
// method state will be taken into account when we get it.
|
||||
if ( !m_imContext || gs_currentFocus != this )
|
||||
return;
|
||||
|
||||
if ( enable )
|
||||
{
|
||||
GTKUpdateIMCursorRect(m_imContext);
|
||||
gtk_im_context_focus_in(m_imContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_im_context_reset(m_imContext);
|
||||
gtk_im_context_focus_out(m_imContext);
|
||||
}
|
||||
}
|
||||
|
||||
void wxWindowGTK::DoUpdateInputMethodCursorRect()
|
||||
{
|
||||
if ( m_imContext )
|
||||
GTKUpdateIMCursorRect(m_imContext);
|
||||
}
|
||||
|
||||
// Let the input method know where to show its windows, if we know it.
|
||||
void wxWindowGTK::GTKUpdateIMCursorRect(GtkIMContext* imContext) const
|
||||
{
|
||||
const wxRect rect = GetInputMethodCursorRect();
|
||||
if ( rect.IsEmpty() )
|
||||
return;
|
||||
|
||||
GdkRectangle area = { rect.x, rect.y, rect.width, rect.height };
|
||||
gtk_im_context_set_cursor_location(imContext, &area);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
@@ -5059,8 +5103,13 @@ bool wxWindowGTK::GTKHandleFocusIn()
|
||||
"handling focus_in event for %s",
|
||||
wxDumpWindow(this));
|
||||
|
||||
if (m_imContext)
|
||||
if (m_imContext && IsInputMethodEnabled())
|
||||
{
|
||||
// Set the cursor location before giving focus to the input method,
|
||||
// as it may use it immediately.
|
||||
GTKUpdateIMCursorRect(m_imContext);
|
||||
gtk_im_context_focus_in(m_imContext);
|
||||
}
|
||||
|
||||
gs_currentFocus = this;
|
||||
|
||||
@@ -5146,7 +5195,7 @@ void wxWindowGTK::GTKHandleFocusOutNoDeferring()
|
||||
|
||||
gs_lastFocus = this;
|
||||
|
||||
if (m_imContext)
|
||||
if (m_imContext && IsInputMethodEnabled())
|
||||
gtk_im_context_focus_out(m_imContext);
|
||||
|
||||
if ( gs_currentFocus != this )
|
||||
|
||||
+153
-29
File diff suppressed because it is too large
Load Diff
@@ -1085,8 +1085,38 @@ void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text);
|
||||
{
|
||||
wxUnusedVar(aRange);
|
||||
wxUnusedVar(actualRange);
|
||||
|
||||
// We don't support ranges, but at least return the position where the
|
||||
// text is being input, if the window provides it.
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( wxWindowMac* const win = impl ? impl->GetWXPeer() : nullptr )
|
||||
{
|
||||
const wxRect rect = win->GetInputMethodCursorRect();
|
||||
if ( !rect.IsEmpty() )
|
||||
{
|
||||
// This function must return the rectangle in screen coordinates.
|
||||
const wxRect rectScreen(win->ClientToScreen(rect.GetPosition()),
|
||||
rect.GetSize());
|
||||
return wxToNSRect(nil, rectScreen);
|
||||
}
|
||||
}
|
||||
|
||||
return NSMakeRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
- (NSTextInputContext *)inputContext
|
||||
{
|
||||
// Returning nil from here disables the input method for this view.
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( wxWindowMac* const win = impl ? impl->GetWXPeer() : nullptr )
|
||||
{
|
||||
if ( !win->IsInputMethodEnabled() )
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [super inputContext];
|
||||
}
|
||||
|
||||
- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
|
||||
{
|
||||
wxUnusedVar(aPoint);
|
||||
|
||||
@@ -156,21 +156,30 @@ public:
|
||||
|
||||
m_scrollWindowCallCount++;
|
||||
m_lastScrollWindowDelta = wxPoint(dx, dy);
|
||||
m_lastScrollWindowViewStart = GetViewStart();
|
||||
}
|
||||
|
||||
void ResetScrollWindowCalls()
|
||||
{
|
||||
m_scrollWindowCallCount = 0;
|
||||
m_lastScrollWindowDelta = wxPoint();
|
||||
m_lastScrollWindowViewStart = wxDefaultPosition;
|
||||
}
|
||||
|
||||
int GetScrollWindowCallCount() const { return m_scrollWindowCallCount; }
|
||||
|
||||
wxPoint GetLastScrollWindowDelta() const { return m_lastScrollWindowDelta; }
|
||||
|
||||
// Return the view start as it was during the last ScrollWindow() call.
|
||||
wxPoint GetLastScrollWindowViewStart() const
|
||||
{
|
||||
return m_lastScrollWindowViewStart;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_scrollWindowCallCount = 0;
|
||||
wxPoint m_lastScrollWindowDelta;
|
||||
wxPoint m_lastScrollWindowViewStart;
|
||||
};
|
||||
|
||||
#endif // wxUSE_SCROLLBAR
|
||||
@@ -216,6 +225,36 @@ TEST_CASE_METHOD(WindowTestCase, "Window::ScrolledWindowPhysicalScrolling",
|
||||
CHECK( win->GetLastScrollWindowDelta() == wxPoint(-10, 0) );
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(WindowTestCase, "Window::ScrolledWindowViewStart",
|
||||
"[window][scroll]")
|
||||
{
|
||||
auto win = make_unique<ScrollCountingWindow>(wxTheApp->GetTopWindow());
|
||||
|
||||
// ScrollWindow() must be called after updating the scroll position, so
|
||||
// that it can be used, e.g. to convert between logical and device
|
||||
// coordinates, in the overridden version of this function.
|
||||
win->Scroll(0, 3);
|
||||
|
||||
REQUIRE( win->GetScrollWindowCallCount() == 1 );
|
||||
CHECK( win->GetLastScrollWindowDelta() == wxPoint(0, -30) );
|
||||
CHECK( win->GetLastScrollWindowViewStart() == wxPoint(0, 3) );
|
||||
|
||||
win->ResetScrollWindowCalls();
|
||||
win->Scroll(2, -1);
|
||||
|
||||
REQUIRE( win->GetScrollWindowCallCount() == 1 );
|
||||
CHECK( win->GetLastScrollWindowDelta() == wxPoint(-20, 0) );
|
||||
CHECK( win->GetLastScrollWindowViewStart() == wxPoint(2, 3) );
|
||||
|
||||
// When scrolling in both directions, ScrollWindow() is called twice and
|
||||
// the view start must be fully updated by the time of the last call.
|
||||
win->ResetScrollWindowCalls();
|
||||
win->Scroll(1, 1);
|
||||
|
||||
REQUIRE( win->GetScrollWindowCallCount() == 2 );
|
||||
CHECK( win->GetLastScrollWindowViewStart() == wxPoint(1, 1) );
|
||||
}
|
||||
|
||||
#endif // wxUSE_SCROLLBAR
|
||||
|
||||
TEST_CASE_METHOD(WindowTestCase, "Window::ShowHideEvent", "[window]")
|
||||
|
||||
Reference in New Issue
Block a user