#define DEBUG_MAIN_THREAD
#endif // Debug
+// the trace mask used for the focus debugging messages
+#define TRACE_FOCUS _T("focus")
+
//-----------------------------------------------------------------------------
// missing gdk functions
//-----------------------------------------------------------------------------
gdk_event->area.y,
gdk_event->area.width,
gdk_event->area.height );
+ win->m_clearRegion.Union( gdk_event->area.x,
+ gdk_event->area.y,
+ gdk_event->area.width,
+ gdk_event->area.height );
// Actual redrawing takes place in idle time.
win->GtkUpdate();
if (g_blockEventsOnDrag)
return FALSE;
+
wxKeyEvent event( wxEVT_KEY_DOWN );
if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
{
return FALSE;
}
+ // Emit KEY_DOWN event
bool ret = win->GetEventHandler()->ProcessEvent( event );
#if wxUSE_ACCEL
}
#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 )
+ // 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)
{
+ // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
KeySym keysym = gdk_event->keyval;
long key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
if ( !key_code )
{
wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
- // reuse the same event object, just change its type and use the
- // translated keycode instead of the raw one
- event.SetEventType(wxEVT_CHAR);
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 );
+ }
- ret = win->GetEventHandler()->ProcessEvent( event );
+ if (!ret)
+ {
+ event.SetEventType(wxEVT_CHAR);
+ ret = win->GetEventHandler()->ProcessEvent( event );
+ }
}
}
- /* win is a control: tab can be propagated up */
+ // 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
{
wxNavigationKeyEvent new_event;
new_event.SetEventObject( win->GetParent() );
- /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
+ // 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 */
+ // 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) */
+ // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs)
if ( !ret &&
(gdk_event->keyval == GDK_Escape) )
{
ret = win->GetEventHandler()->ProcessEvent( new_event );
}
- /* Doesn't work. */
-#if 0 // (GTK_MINOR_VERSION > 0)
- /* Pressing F10 will activate the menu bar of the top frame. */
+ // Doesn't work.
+#if 0
+ // Pressing F10 will activate the menu bar of the top frame
if ( (!ret) &&
(gdk_event->keyval == GDK_F10) )
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
return TRUE;
}
-
+
return FALSE;
}
// the mouse events
// ============================================================================
+// ----------------------------------------------------------------------------
+// mouse event processing helpers
+// ----------------------------------------------------------------------------
+
// init wxMouseEvent with the info from gdk_event
#define InitMouseEvent(win, event, gdk_event) \
{ \
event.m_y = (wxCoord)gdk_event->y - pt.y; \
}
-// ----------------------------------------------------------------------------
-// mouse event processing helper
-// ----------------------------------------------------------------------------
-
static void AdjustEventButtonState(wxMouseEvent& event)
{
// GDK reports the old state of the button for a button press event, but
}
}
+// find the window to send the mouse event too
+static
+wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
+{
+ wxCoord xx = x;
+ wxCoord yy = y;
+
+ if (win->m_wxwindow)
+ {
+ GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
+ xx += pizza->xoffset;
+ yy += pizza->yoffset;
+ }
+
+ wxNode *node = win->GetChildren().First();
+ while (node)
+ {
+ wxWindowGTK *child = (wxWindowGTK*)node->Data();
+
+ node = node->Next();
+ if (!child->IsShown())
+ continue;
+
+ if (child->IsTransparentForMouse())
+ {
+ // wxStaticBox is transparent in the box itself
+ 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;
+
+ // left
+ if (((xx >= xx1) && (xx <= xx1+10) && (yy >= yy1) && (yy <= yy2)) ||
+ // right
+ ((xx >= xx2-10) && (xx <= xx2) && (yy >= yy1) && (yy <= yy2)) ||
+ // top
+ ((xx >= xx1) && (xx <= xx2) && (yy >= yy1) && (yy <= yy1+10)) ||
+ // bottom
+ ((xx >= xx1) && (xx <= xx2) && (yy >= yy2-1) && (yy <= yy2)))
+ {
+ win = child;
+ x -= child->m_x;
+ y -= child->m_y;
+ break;
+ }
+
+ }
+ else
+ {
+ if ((child->m_wxwindow == (GtkWidget*) NULL) &&
+ (child->m_x <= xx) &&
+ (child->m_y <= yy) &&
+ (child->m_x+child->m_width >= xx) &&
+ (child->m_y+child->m_height >= yy))
+ {
+ win = child;
+ x -= child->m_x;
+ y -= child->m_y;
+ break;
+ }
+ }
+ }
+
+ return win;
+}
+
//-----------------------------------------------------------------------------
// "button_press_event"
//-----------------------------------------------------------------------------
-static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win )
+static gint gtk_window_button_press_callback( GtkWidget *widget,
+ GdkEventButton *gdk_event,
+ wxWindowGTK *win )
{
DEBUG_MAIN_THREAD
AdjustEventButtonState(event);
- // wxListBox actually get mouse events from the item
-
- if (win->m_isListBox)
- {
- event.m_x += widget->allocation.x;
- event.m_y += widget->allocation.y;
- }
-
- // Some control don't have their own X window and thus cannot get
- // any events.
-
- if (!g_captureWindow)
- {
- wxCoord x = event.m_x;
- wxCoord y = event.m_y;
- if (win->m_wxwindow)
- {
- GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
- x += pizza->xoffset;
- y += pizza->yoffset;
- }
-
- wxNode *node = win->GetChildren().First();
- while (node)
- {
- wxWindowGTK *child = (wxWindowGTK*)node->Data();
-
- node = node->Next();
- if (!child->IsShown())
- continue;
+ // wxListBox actually get mouse events from the item, so we need to give it
+ // a chance to correct this
+ win->FixUpMouseEvent(widget, event.m_x, event.m_y);
- if (child->m_isStaticBox)
- {
- // wxStaticBox is transparent in the box itself
- 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;
-
- // left
- if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
- // right
- ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
- // top
- ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
- // bottom
- ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
- {
- win = child;
- event.m_x -= child->m_x;
- event.m_y -= child->m_y;
- break;
- }
-
- }
- else
- {
- if ((child->m_wxwindow == (GtkWidget*) NULL) &&
- (child->m_x <= x) &&
- (child->m_y <= y) &&
- (child->m_x+child->m_width >= x) &&
- (child->m_y+child->m_height >= y))
- {
- win = child;
- event.m_x -= child->m_x;
- event.m_y -= child->m_y;
- break;
- }
- }
- }
- }
+ // find the correct window to send the event too: it may be a different one
+ // from the one which got it at GTK+ level because some control don't have
+ // their own X window and thus cannot get any events.
+ if ( !g_captureWindow )
+ win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
event.SetEventObject( win );
AdjustEventButtonState(event);
- // wxListBox actually get mouse events from the item
-
- if (win->m_isListBox)
- {
- event.m_x += widget->allocation.x;
- event.m_y += widget->allocation.y;
- }
+ // same wxListBox hack as above
+ win->FixUpMouseEvent(widget, event.m_x, event.m_y);
- // Some control don't have their own X window and thus cannot get
- // any events.
-
- if (!g_captureWindow)
- {
- wxCoord x = event.m_x;
- wxCoord y = event.m_y;
- if (win->m_wxwindow)
- {
- GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
- x += pizza->xoffset;
- y += pizza->yoffset;
- }
-
- wxNode *node = win->GetChildren().First();
- while (node)
- {
- wxWindowGTK *child = (wxWindowGTK*)node->Data();
-
- node = node->Next();
- if (!child->IsShown())
- continue;
-
- if (child->m_isStaticBox)
- {
- // wxStaticBox is transparent in the box itself
- 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;
-
- // left
- if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
- // right
- ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
- // top
- ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
- // bottom
- ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
- {
- win = child;
- event.m_x -= child->m_x;
- event.m_y -= child->m_y;
- break;
- }
-
- }
- else
- {
- if ((child->m_wxwindow == (GtkWidget*) NULL) &&
- (child->m_x <= x) &&
- (child->m_y <= y) &&
- (child->m_x+child->m_width >= x) &&
- (child->m_y+child->m_height >= y))
- {
- win = child;
- event.m_x -= child->m_x;
- event.m_y -= child->m_y;
- break;
- }
- }
- }
- }
+ if ( !g_captureWindow )
+ win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
event.SetEventObject( win );
}
else // no capture
{
- // Some control don't have their own X window and thus cannot get
- // any events.
-
- wxCoord x = event.m_x;
- wxCoord y = event.m_y;
- if (win->m_wxwindow)
- {
- GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
- x += pizza->xoffset;
- y += pizza->yoffset;
- }
-
- wxNode *node = win->GetChildren().First();
- while (node)
- {
- wxWindowGTK *child = (wxWindowGTK*)node->Data();
-
- node = node->Next();
- if (!child->IsShown())
- continue;
-
- if (child->m_isStaticBox)
- {
- // wxStaticBox is transparent in the box itself
- 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;
-
- // left
- if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
- // right
- ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
- // top
- ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
- // bottom
- ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
- {
- win = child;
- event.m_x -= child->m_x;
- event.m_y -= child->m_y;
- break;
- }
-
- }
- else
- {
- if ((child->m_wxwindow == (GtkWidget*) NULL) &&
- (child->m_x <= x) &&
- (child->m_y <= y) &&
- (child->m_x+child->m_width >= x) &&
- (child->m_y+child->m_height >= y))
- {
- win = child;
- event.m_x -= child->m_x;
- event.m_y -= child->m_y;
- break;
- }
- }
- }
+ win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
}
event.SetEventObject( win );
g_focusWindowLast =
g_focusWindow = win;
-#if 0
- printf( "OnSetFocus 2 from %s\n", win->GetName().c_str() );
-#endif
+ wxLogTrace(TRACE_FOCUS,
+ _T("%s: focus in"), win->GetName().c_str());
#ifdef HAVE_XIM
if (win->m_ic)
// return TRUE;
}
- if ( DoSendFocusEvents(win) )
+ // does the window itself think that it has the focus?
+ if ( !win->m_hasFocus )
{
- gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
- return TRUE;
+ // not yet, notify it
+ win->m_hasFocus = TRUE;
+
+ if ( DoSendFocusEvents(win) )
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
+ return TRUE;
+ }
}
return FALSE;
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
-#if 0
- wxLogDebug( wxT("OnKillFocus from %s"), win->GetName().c_str() );
-#endif
+ wxLogTrace( TRACE_FOCUS,
+ _T("%s: focus out"), win->GetName().c_str() );
if ( !g_activeFrameLostFocus && g_activeFrame )
{
}
#endif // wxUSE_CARET
- wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
- event.SetEventObject( win );
-
- if (win->GetEventHandler()->ProcessEvent( event ))
+ // don't send the window a kill focus event if it thinks that it doesn't
+ // have focus already
+ if ( win->m_hasFocus )
{
- gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
- return TRUE;
+ win->m_hasFocus = FALSE;
+
+ wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
+ event.SetEventObject( win );
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
+ return TRUE;
+ }
}
return FALSE;
win->m_oldVerticalPos = adjust->value;
- wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget));
+ GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW(win->m_widget);
+ wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->vscrollbar));
int value = (int)(adjust->value+0.5);
float diff = adjust->value - win->m_oldHorizontalPos;
if (fabs(diff) < 0.2) return;
- wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget));
+ GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW(win->m_widget);
+ wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->hscrollbar));
win->m_oldHorizontalPos = adjust->value;
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
//-----------------------------------------------------------------------------
wxWindow *wxGetActiveWindow()
{
- // the cast is necessary when we compile in wxUniversal mode
- return (wxWindow *)g_focusWindow;
+ return wxWindow::FindFocus();
}
//-----------------------------------------------------------------------------
m_insertCallback = (wxInsertChildFunction) NULL;
- m_isStaticBox = FALSE;
- m_isRadioButton = FALSE;
- m_isListBox = FALSE;
- m_isFrame = FALSE;
m_acceptsFocus = FALSE;
+ m_hasFocus = FALSE;
m_clipPaintRegion = FALSE;
if (g_activeFrame == this)
g_activeFrame = NULL;
+ if ( g_delayedFocus == this )
+ g_delayedFocus = NULL;
+
m_isBeingDeleted = TRUE;
m_hasVMT = FALSE;
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()
void wxWindowGTK::SetFocus()
{
- wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
+ wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
+
+ if ( m_hasFocus )
+ {
+ // don't do anything if we already have focus
+ return;
+ }
if (m_wxwindow)
{
{
if (!GTK_WIDGET_REALIZED(m_widget))
{
- wxLogTrace(_T("focus"),
- _T("Delaying setting focus to %s(%s)\n"),
+ // we can't set the focus to the widget now so we remember that
+ // it should be focused and will do it later, during the idle
+ // time, as soon as we can
+ wxLogTrace(TRACE_FOCUS,
+ _T("Delaying setting focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str());
g_delayedFocus = this;
}
else
{
- wxLogTrace(_T("focus"),
- _T("Setting focus to %s(%s)\n"),
+ wxLogTrace(TRACE_FOCUS,
+ _T("Setting focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str());
gtk_widget_grab_focus (m_widget);
}
else
{
- // ?
+ wxLogTrace(TRACE_FOCUS,
+ _T("Can't set focus to %s(%s)"),
+ GetClassInfo()->GetClassName(), GetLabel().c_str());
}
}
-
- (void)DoSendFocusEvents(this);
}
bool wxWindowGTK::AcceptsFocus() const
while (parent && !parent->IsTopLevel())
parent = parent->GetParent();
if (!parent)
- parent = this;
+ parent = (wxWindow*)this;
wxRegionIterator upd( m_updateRegion );
while (upd)
wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
-
+
// No scrolling requested.
if ((dx == 0) && (dy == 0)) return;
GetClientSize( &cw, &ch );
m_clearRegion.Intersect( 0, 0, cw, ch );
}
-
m_clipPaintRegion = TRUE;
gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
gdk_gc_unref( g_eraseGC );
}
+// vi:sts=4:sw=4:et