return TRUE;
}
-#ifndef __WXGTK20__
+
static gint gtk_window_key_press_callback( GtkWidget *widget,
GdkEventKey *gdk_event,
wxWindow *win )
// will only be sent if it is not in an accelerator table.
if (!ret)
{
- // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+ long key_code;
KeySym keysym = gdk_event->keyval;
- long key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
- if ( !key_code )
+#ifdef __WXGTK20__
+ // In GTK 2.0, we need to hand over the key event to an input method
+ // and the IM will emit a "commit" event containing the actual utf8
+ // character. In that case the EVT_CHAR events will be sent from
+ // there. But only do it this way for non-KeySym keys.
+ key_code = wxTranslateKeySymToWXKey(gdk_event->keyval, FALSE /* isChar */);
+ if ( !key_code && win->m_imContext )
{
- if ( gdk_event->length == 1 )
- {
- key_code = (unsigned char)gdk_event->string[0];
- }
- else if ( wxIsAsciiKeysym(keysym) )
- {
- // ASCII key
- key_code = (unsigned char)keysym;
- }
+ gtk_im_context_filter_keypress ( (GtkIMContext*) win->m_imContext, gdk_event );
+ ret = TRUE;
}
-
- if ( key_code )
+ else
+#endif
{
- wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
-
- event.m_keyCode = key_code;
-
- // Implement OnCharHook by checking ancesteror top level windows
- wxWindow *parent = win;
- while (parent && !parent->IsTopLevel())
- parent = parent->GetParent();
- if (parent)
+ // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+ key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
+ if ( !key_code )
{
- event.SetEventType( wxEVT_CHAR_HOOK );
- ret = parent->GetEventHandler()->ProcessEvent( event );
+ if ( gdk_event->length == 1 )
+ {
+ key_code = (unsigned char)gdk_event->string[0];
+ }
+ else if ( wxIsAsciiKeysym(keysym) )
+ {
+ // ASCII key
+ key_code = (unsigned char)keysym;
+ }
}
- if (!ret)
+ if ( key_code )
{
- event.SetEventType(wxEVT_CHAR);
- ret = win->GetEventHandler()->ProcessEvent( event );
+ wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
+
+ event.m_keyCode = key_code;
+
+ // 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 );
+ }
}
}
}
return FALSE;
}
-#endif
#ifdef __WXGTK20__
-static gint gtk_window_key_press_callback( GtkWidget *widget,
- GdkEventKey *gdk_event,
- wxWindow *win )
-{
- if (g_isIdle)
- wxapp_install_idle_handler();
-
- if (!win->m_hasVMT)
- return FALSE;
- if (g_blockEventsOnDrag)
- return FALSE;
-
- bool ret = FALSE;
- bool dont_use_IM = FALSE;
-
- wxKeyEvent event( wxEVT_KEY_DOWN );
- long keycode = wxTranslateKeySymToWXKey( gdk_event->keyval, FALSE );
- if (keycode)
- {
- // We were able to decode the key press without
- // any input method, so don't use it.
- dont_use_IM = TRUE;
-
- // now fill all the other fields
- int x = 0;
- int y = 0;
- GdkModifierType state;
- if (gdk_event->window)
- gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
-
- event.SetTimestamp( gdk_event->time );
- event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK) != 0;
- event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0;
- event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0;
- event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK) != 0;
- event.m_keyCode = keycode;
- event.m_scanCode = gdk_event->keyval;
- event.m_rawCode = (wxUint32) gdk_event->keyval;
- event.m_rawFlags = 0;
- event.m_x = x;
- event.m_y = y;
- event.SetEventObject( win );
-
- // send key down event
- ret = win->GetEventHandler()->ProcessEvent( event );
-
- if (!ret)
- {
- // 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)) &&
- 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 );
- }
-
- if ( !ret &&
- (gdk_event->keyval == GDK_Escape) )
- {
- wxWindow *winForCancel = win, *btnCancel = NULL;
- while ( winForCancel )
- {
- btnCancel = winForCancel->FindWindow(wxID_CANCEL);
- if ( btnCancel ) break;
-
- if ( winForCancel->IsTopLevel() ) break;
-
- 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;
- }
-
- if (!dont_use_IM && win->m_imContext)
- {
- // In GTK 2.0, we need to hand over the key
- // event to an input method and the IM will
- // emit a "commit" event containing the
- // actual utf8 character.
- gtk_im_context_filter_keypress ( (GtkIMContext*) win->m_imContext, gdk_event );
-
- return TRUE;
- }
-
- return FALSE;
-}
-
static void gtk_wxwindow_commit_cb (GtkIMContext *context,
const gchar *str,
wxWindow *window)
event.m_keyCode = uniChar;
#endif
- if (!ret)
- {
- // Implement OnCharHook by checking ancesteror top level windows
- wxWindow *parent = window;
- while (parent && !parent->IsTopLevel())
+
+ // TODO: We still need to set all the extra attributes of the
+ // event, modifiers and such...
+
+
+ // Implement OnCharHook by checking ancestor top level windows
+ wxWindow *parent = window;
+ while (parent && !parent->IsTopLevel())
parent = parent->GetParent();
- if (parent)
- {
- event.SetEventType( wxEVT_CHAR_HOOK );
- ret = parent->GetEventHandler()->ProcessEvent( event );
- }
+ if (parent)
+ {
+ event.SetEventType( wxEVT_CHAR_HOOK );
+ ret = parent->GetEventHandler()->ProcessEvent( event );
+ }
- if (!ret)
- {
- event.SetEventType(wxEVT_CHAR);
- ret = window->GetEventHandler()->ProcessEvent( event );
- }
+ if (!ret)
+ {
+ event.SetEventType(wxEVT_CHAR);
+ ret = window->GetEventHandler()->ProcessEvent( event );
}
}
#endif
yy += pizza->yoffset;
}
- wxNode *node = win->GetChildren().First();
+ wxWindowList::Node *node = win->GetChildren().GetFirst();
while (node)
{
- wxWindowGTK *child = (wxWindowGTK*)node->Data();
+ wxWindowGTK *child = node->GetData();
- node = node->Next();
+ node = node->GetNext();
if (!child->IsShown())
continue;
int xx1 = child->m_x;
int yy1 = child->m_y;
int xx2 = child->m_x + child->m_width;
- int yy2 = child->m_x + child->m_height;
+ int yy2 = child->m_y + child->m_height;
// left
if (((xx >= xx1) && (xx <= xx1+10) && (yy >= yy1) && (yy <= yy2)) ||
wxPrintf( wxT(".\n") );
*/
+#ifndef __WXGTK20__
+ if (event_type == wxEVT_LEFT_DCLICK)
+ {
+ // GTK 1.2 crashes when intercepting double
+ // click events from both wxSpinButton and
+ // wxSpinCtrl
+ if (GTK_IS_SPIN_BUTTON(win->m_widget))
+ {
+ // Just disable this event for now.
+ return FALSE;
+ }
+ }
+#endif
+
if (win->GetEventHandler()->ProcessEvent( event ))
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
{
// synthetize a mouse enter or leave event if needed
GdkWindow *winUnderMouse = gdk_window_at_pointer(NULL, NULL);
+ // This seems to be necessary and actually been added to
+ // GDK itself in version 2.0.X
+ gdk_flush();
+
bool hasMouse = winUnderMouse == gdk_event->window;
if ( hasMouse != g_captureWindowHasMouse )
{
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
+ // Event was emitted after a grab
+ if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
+
if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
int x = 0;
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
+ // Event was emitted after an ungrab
+ if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
+
if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
wxMouseEvent event( wxEVT_LEAVE_WINDOW );
return (wxWindow *)g_focusWindow;
}
-//-----------------------------------------------------------------------------
-// "destroy" event
-//-----------------------------------------------------------------------------
-
-// VZ: Robert commented the code using out so it generates warnings: should
-// be either fixed or removed completely
-#if 0
-
-static void gtk_window_destroy_callback( GtkWidget* widget, wxWindow *win )
-{
- wxWindowDestroyEvent event(win);
- win->GetEventHandler()->ProcessEvent(event);
-}
-
-#endif // 0
//-----------------------------------------------------------------------------
// "realize" from m_widget
wxWindowGTK::~wxWindowGTK()
{
+ SendDestroyEvent();
+
if (g_focusWindow == this)
g_focusWindow = NULL;
gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
-
- // This keeps crashing on me. RR.
- //
- // gtk_signal_connect( GTK_OBJECT(widget), "destroy",
- // GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this );
}
bool wxWindowGTK::Destroy()
wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
+#ifdef __WXGTK20__
+ PangoContext *context = NULL;
+ if (m_widget)
+ context = gtk_widget_get_pango_context( m_widget );
+
+ if (!context)
+ return 0;
+
+ PangoFontDescription *desc = m_font.GetNativeFontInfo()->description;
+ PangoLayout *layout = pango_layout_new(context);
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, "H", 1);
+ PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+
+ PangoRectangle rect;
+ pango_layout_line_get_extents(line, NULL, &rect);
+
+ g_object_unref( G_OBJECT( layout ) );
+
+ return (int) (rect.height / PANGO_SCALE);
+#else
GdkFont *font = m_font.GetInternalFont( 1.0 );
return font->ascent + font->descent;
+#endif
}
int wxWindowGTK::GetCharWidth() const
wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
+#ifdef __WXGTK20__
+ PangoContext *context = NULL;
+ if (m_widget)
+ context = gtk_widget_get_pango_context( m_widget );
+
+ if (!context)
+ return 0;
+
+ PangoFontDescription *desc = m_font.GetNativeFontInfo()->description;
+ PangoLayout *layout = pango_layout_new(context);
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, "H", 1);
+ PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+
+ PangoRectangle rect;
+ pango_layout_line_get_extents(line, NULL, &rect);
+
+ g_object_unref( G_OBJECT( layout ) );
+
+ return (int) (rect.width / PANGO_SCALE);
+#else
GdkFont *font = m_font.GetInternalFont( 1.0 );
return gdk_string_width( font, "H" );
+#endif
}
void wxWindowGTK::GetTextExtent( const wxString& string,
if (m_font != wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ))
{
- SET_STYLE_FONT(style, m_font.GetInternalFont( 1.0 ));
+#ifdef __WXGTK20__
+ pango_font_description_free( style->font_desc );
+ pango_font_description_copy( m_font.GetNativeFontInfo()->description );
+#else
+ gdk_font_unref( style->font );
+ style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
+#endif
}
if (m_foregroundColour.Ok())
int x, y;
GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
- if (!windowAtPtr)
- return wxPoint(-999, -999);
- Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
+ Display *display = windowAtPtr ? GDK_WINDOW_XDISPLAY(windowAtPtr) : GDK_DISPLAY();
Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
Window rootReturn, childReturn;
int rootX, rootY, winX, winY;