window.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,007 行 · 第 1/5 页
CPP
2,007 行
}
}
#endif
if (return_after_IM)
return false;
#ifndef __WXGTK20__
// This is for GTK+ 1.2 only. The char event generatation for GTK+ 2.0 is done
// in the "commit" handler.
// 2005.02.02 modified by Hong Jen Yee (hzysoft@sina.com.tw).
// In GTK+ 1.2, strings sent by IMs are also regarded as key_press events whose
// keyCodes cannot be recognized by wxWidgets. These MBCS strings, however, are
// composed of more than one character, which means gdk_event->length will always
// greater than one. When gtk_event->length == 1, this may be an ASCII character
// and can be translated by wx. However, when MBCS characters are sent by IM,
// gdk_event->length will >= 2. So neither should we pass it to accelerator table,
// nor should we pass it to controls. The following explanation was excerpted
// from GDK documentation.
// gint length : the length of string.
// gchar *string : a null-terminated multi-byte string containing the composed
// characters resulting from the key press. When text is being input, in a GtkEntry
// for example, it is these characters which should be added to the input buffer.
// When using Input Methods to support internationalized text input, the composed
// characters appear here after the pre-editing has been completed.
if ( (!ret) && (gdk_event->length > 1) ) // If this event contains a pre-edited string from IM.
{
// We should translate this key event into wxEVT_CHAR not wxEVT_KEY_DOWN.
#if wxUSE_UNICODE // GTK+ 1.2 is not UTF-8 based.
const wxWCharBuffer string = wxConvLocal.cMB2WC( gdk_event->string );
if( !string )
return false;
#else
const char* string = gdk_event->string;
#endif
// Implement OnCharHook by checking ancesteror top level windows
wxWindow *parent = win;
while (parent && !parent->IsTopLevel())
parent = parent->GetParent();
for( const wxChar* pstr = string; *pstr; pstr++ )
{
#if wxUSE_UNICODE
event.m_uniChar = *pstr;
// Backward compatible for ISO-8859-1
event.m_keyCode = *pstr < 256 ? event.m_uniChar : 0;
#else
event.m_keyCode = *pstr;
#endif
if (parent)
{
event.SetEventType( wxEVT_CHAR_HOOK );
ret = parent->GetEventHandler()->ProcessEvent( event );
}
if (!ret)
{
event.SetEventType(wxEVT_CHAR);
win->GetEventHandler()->ProcessEvent( event );
}
}
return true;
}
#endif // #ifndef __WXGTK20__
#if wxUSE_ACCEL
if (!ret)
{
wxWindowGTK *ancestor = win;
while (ancestor)
{
int command = ancestor->GetAcceleratorTable()->GetCommand( event );
if (command != -1)
{
wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
break;
}
if (ancestor->IsTopLevel())
break;
ancestor = ancestor->GetParent();
}
}
#endif // wxUSE_ACCEL
// Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
// will only be sent if it is not in an accelerator table.
if (!ret)
{
long key_code;
KeySym keysym = gdk_event->keyval;
// Find key code for EVT_CHAR and EVT_CHAR_HOOK events
key_code = wxTranslateKeySymToWXKey(keysym, true /* isChar */);
if ( !key_code )
{
if ( wxIsAsciiKeysym(keysym) )
{
// ASCII key
key_code = (unsigned char)keysym;
}
// gdk_event->string is actually deprecated
else if ( gdk_event->length == 1 )
{
key_code = (unsigned char)gdk_event->string[0];
}
}
if ( key_code )
{
wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
event.m_keyCode = key_code;
// To conform to the docs we need to translate Ctrl-alpha
// characters to values in the range 1-26.
if (event.ControlDown() && key_code >= 'a' && key_code <= 'z' )
{
event.m_keyCode = key_code - 'a' + 1;
}
#if wxUSE_UNICODE
event.m_uniChar = event.m_keyCode;
#endif
// Implement OnCharHook by checking ancesteror top level windows
wxWindow *parent = win;
while (parent && !parent->IsTopLevel())
parent = parent->GetParent();
if (parent)
{
event.SetEventType( wxEVT_CHAR_HOOK );
ret = parent->GetEventHandler()->ProcessEvent( event );
}
if (!ret)
{
event.SetEventType(wxEVT_CHAR);
ret = win->GetEventHandler()->ProcessEvent( event );
}
}
}
// win is a control: tab can be propagated up
if ( !ret &&
((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
// have this style, yet choose not to process this particular TAB in which
// case TAB must still work as a navigational character
// JS: enabling again to make consistent with other platforms
// (with wxTE_PROCESS_TAB you have to call Navigate to get default
// navigation behaviour)
#if wxUSE_TEXTCTRL
(! (win->HasFlag(wxTE_PROCESS_TAB) && win->IsKindOf(CLASSINFO(wxTextCtrl)) )) &&
#endif
win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
{
wxNavigationKeyEvent new_event;
new_event.SetEventObject( win->GetParent() );
// GDK reports GDK_ISO_Left_Tab for SHIFT-TAB
new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
// CTRL-TAB changes the (parent) window, i.e. switch notebook page
new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
new_event.SetCurrentFocus( win );
ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
}
// generate wxID_CANCEL if <esc> has been pressed (typically in dialogs)
if ( !ret &&
(gdk_event->keyval == GDK_Escape) )
{
// however only do it if we have a Cancel button in the dialog,
// otherwise the user code may get confused by the events from a
// non-existing button and, worse, a wxButton might get button event
// from another button which is not really expected
wxWindow *winForCancel = win,
*btnCancel = NULL;
while ( winForCancel )
{
btnCancel = winForCancel->FindWindow(wxID_CANCEL);
if ( btnCancel )
{
// found a cancel button
break;
}
if ( winForCancel->IsTopLevel() )
{
// no need to look further
break;
}
// maybe our parent has a cancel button?
winForCancel = winForCancel->GetParent();
}
if ( btnCancel )
{
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
event.SetEventObject(btnCancel);
ret = btnCancel->GetEventHandler()->ProcessEvent(event);
}
}
if (ret)
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
return TRUE;
}
return FALSE;
}
}
#ifdef __WXGTK20__
extern "C" {
static void gtk_wxwindow_commit_cb (GtkIMContext *context,
const gchar *str,
wxWindow *window)
{
wxKeyEvent event( wxEVT_KEY_DOWN );
// take modifiers, cursor position, timestamp etc. from the last
// key_press_event that was fed into Input Method:
if (window->m_imData->lastKeyEvent)
{
wxFillOtherKeyEventFields(event,
window, window->m_imData->lastKeyEvent);
}
#if wxUSE_UNICODE
const wxWCharBuffer data = wxConvUTF8.cMB2WC( (char*)str );
#else
const wxWCharBuffer wdata = wxConvUTF8.cMB2WC( (char*)str );
const wxCharBuffer data = wxConvLocal.cWC2MB( wdata );
#endif // wxUSE_UNICODE
if( !(const wxChar*)data )
return;
bool ret = false;
// Implement OnCharHook by checking ancestor top level windows
wxWindow *parent = window;
while (parent && !parent->IsTopLevel())
parent = parent->GetParent();
for( const wxChar* pstr = data; *pstr; pstr++ )
{
#if wxUSE_UNICODE
event.m_uniChar = *pstr;
// Backward compatible for ISO-8859-1
event.m_keyCode = *pstr < 256 ? event.m_uniChar : 0;
wxLogTrace(TRACE_KEYS, _T("IM sent character '%c'"), event.m_uniChar);
#else
event.m_keyCode = *pstr;
#endif // wxUSE_UNICODE
// To conform to the docs we need to translate Ctrl-alpha
// characters to values in the range 1-26.
if (event.ControlDown() && *pstr >= 'a' && *pstr <= 'z' )
{
event.m_keyCode = *pstr - 'a' + 1;
#if wxUSE_UNICODE
event.m_uniChar = event.m_keyCode;
#endif
}
if (parent)
{
event.SetEventType( wxEVT_CHAR_HOOK );
ret = parent->GetEventHandler()->ProcessEvent( event );
}
if (!ret)
{
event.SetEventType(wxEVT_CHAR);
ret = window->GetEventHandler()->ProcessEvent( event );
}
}
}
}
#endif
//-----------------------------------------------------------------------------
// "key_release_event" from any window
//-----------------------------------------------------------------------------
extern "C" {
static gint gtk_window_key_release_callback( GtkWidget *widget,
GdkEventKey *gdk_event,
wxWindowGTK *win )
{
DEBUG_MAIN_THREAD
if (g_isIdle)
wxapp_install_idle_handler();
if (!win->m_hasVMT)
return FALSE;
if (g_blockEventsOnDrag)
return FALSE;
wxKeyEvent event( wxEVT_KEY_UP );
if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
{
// unknown key pressed, ignore (the event would be useless anyhow
return FALSE;
}
if ( !win->GetEventHandler()->ProcessEvent( event ) )
return FALSE;
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
return TRUE;
}
}
// ============================================================================
// the mouse events
// ============================================================================
// ----------------------------------------------------------------------------
// mouse event processing helpers
// ----------------------------------------------------------------------------
// init wxMouseEvent with the info from GdkEventXXX struct
template<typename T> void InitMouseEvent(wxWindowGTK *win,
wxMouseEvent& event,
T *gdk_event)
{
event.SetTimestamp( gdk_event->time );
event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
if (event.GetEventType() == wxEVT_MOUSEWHEEL)
{
event.m_linesPerAction = 3;
event.m_wheelDelta = 120;
if (((GdkEventButton*)gdk_event)->button == 4)
event.m_wheelRotation = 120;
else if (((GdkEventButton*)gdk_event)->button == 5)
event.m_wheelRotation = -120;
}
wxPoint pt = win->GetClientAreaOrigin();
event.m_x = (wxCoord)gdk_event->x - pt.x;
event.m_y = (wxCoord)gdk_event->y - pt.y;
event.SetEventObject( win );
event.SetId( win->GetId() );
event.SetTimestamp( gdk_event->time );
}
static void AdjustEventButtonState(wxMouseEvent& event)
{
// GDK reports the old state of the button for a button press event, but
// for compatibility with MSW and common sense we want m_leftDown be TRUE
// for a LEFT_DOWN event, not FALSE, so we will invert
// left/right/middleDown for the corresponding click events
if ((event.GetEventType() == wxEVT_LEFT_DOWN) ||
(event.GetEventType() == wxEVT_LEFT_DCLICK) ||
(event.GetEventType() == wxEVT_LEFT_UP))
{
event.m_leftDown = !event.m_leftDown;
return;
}
if ((event.GetEventType() == wxEVT_MIDDLE_DOWN) ||
(event.GetEventType() == wxEVT_MIDDLE_DCLICK) ||
(event.GetEventType() == wxEVT_MIDDLE_UP))
{
event.m_middleDown = !event.m_middleDown;
return;
}
if ((event.GetEventType() == wxEVT_RIGHT_DOWN) ||
(event.GetEventType() == wxEVT_RIGHT_DCLICK) ||
(event.GetEventType() == wxEVT_RIGHT_UP))
{
event.m_rightDown = !event.m_rightDown;
return;
}
}
// find the window to send the mouse event too
static
wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
{
wxCoord xx = x;
wxCoord yy = y;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?