+ wxPrintf( wxT("OnExpose from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
+ (int)gdk_event->area.y,
+ (int)gdk_event->area.width,
+ (int)gdk_event->area.height );
+ }
+*/
+
+ win->GetUpdateRegion().Union( gdk_event->area.x,
+ gdk_event->area.y,
+ gdk_event->area.width,
+ gdk_event->area.height );
+
+ if (gdk_event->count == 0)
+ {
+ wxEraseEvent eevent( win->GetId() );
+ eevent.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent(eevent);
+
+ wxPaintEvent event( win->GetId() );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+
+ win->GetUpdateRegion().Clear();
+ }
+
+ /* The following code will result in all window-less widgets
+ being redrawn if the wxWindows class is given a chance to
+ paint *anything* because it will then be allowed to paint
+ over the window-less widgets */
+
+ GtkPizza *pizza = GTK_PIZZA (widget);
+
+ GList *children = pizza->children;
+ while (children)
+ {
+ GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+ children = children->next;
+
+ GdkEventExpose child_event = *gdk_event;
+
+ if (GTK_WIDGET_NO_WINDOW (child->widget) &&
+ GTK_WIDGET_DRAWABLE (child->widget) /* &&
+ gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
+ {
+ child_event.area.x = child->widget->allocation.x;
+ child_event.area.y = child->widget->allocation.y;
+ child_event.area.width = child->widget->allocation.width;
+ child_event.area.height = child->widget->allocation.height;
+ gtk_widget_event (child->widget, (GdkEvent*) &child_event);
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// "event" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+/* GTK thinks it is clever and filters out a certain amount of "unneeded"
+ expose events. We need them, of course, so we override the main event
+ procedure in GtkWidget by giving our own handler for all system events.
+ There, we look for expose events ourselves whereas all other events are
+ handled normally. */
+
+gint gtk_window_event_event_callback( GtkWidget *widget, GdkEventExpose *event, wxWindow *win )
+{
+ if (event->type == GDK_EXPOSE)
+ {
+ gint ret = gtk_window_expose_callback( widget, event, win );
+ return ret;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "draw" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+/* This callback is a complete replacement of the gtk_pizza_draw() function,
+ which disabled. */
+
+static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+/*
+ if (win->GetName() == wxT("panel"))
+ {
+ wxPrintf( wxT("OnDraw from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
+ (int)rect->y,
+ (int)rect->width,
+ (int)rect->height );
+ }
+*/
+
+ GtkPizza *pizza = GTK_PIZZA (widget);
+
+ if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
+ (pizza->clear_on_draw))
+ {
+ gdk_window_clear_area( pizza->bin_window,
+ rect->x, rect->y, rect->width, rect->height);
+ }
+
+ win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
+
+ win->m_clipPaintRegion = TRUE;
+
+ wxEraseEvent eevent( win->GetId() );
+ eevent.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent(eevent);
+
+ wxPaintEvent event( win->GetId() );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+
+ win->GetUpdateRegion().Clear();
+
+ win->m_clipPaintRegion = FALSE;
+
+
+ GList *children = pizza->children;
+ while (children)
+ {
+ GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+ children = children->next;
+
+ GdkRectangle child_area;
+ if (gtk_widget_intersect (child->widget, rect, &child_area))
+ {
+ gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// "key_press_event" from any window
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+
+/*
+ wxString tmp;
+ tmp += (char)gdk_event->keyval;
+ printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
+ printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
+*/
+
+ int x = 0;
+ int y = 0;
+ GdkModifierType state;
+ if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+
+ bool ret = FALSE;
+
+ long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+ /* sending unknown key events doesn't really make sense */
+ if (key_code == 0) return FALSE;
+
+ wxKeyEvent event( wxEVT_KEY_DOWN );
+ 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_keyCode = key_code;
+ event.m_scanCode = gdk_event->keyval;
+ event.m_x = x;
+ event.m_y = y;
+ event.SetEventObject( win );
+ ret = win->GetEventHandler()->ProcessEvent( event );
+
+#if wxUSE_ACCEL
+ if (!ret)
+ {
+ wxWindow *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
+
+ /* wxMSW doesn't send char events with Alt pressed */
+ /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
+ will only be sent if it is not in an accelerator table. */
+ key_code = map_to_wx_keysym( gdk_event->keyval );
+
+ if ( (!ret) &&
+ (key_code != 0))
+ {
+ wxKeyEvent event2( wxEVT_CHAR );
+ event2.SetTimestamp( gdk_event->time );
+ event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
+ event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
+ event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
+ event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
+ event2.m_keyCode = key_code;
+ event2.m_scanCode = gdk_event->keyval;
+ event2.m_x = x;
+ event2.m_y = y;
+ event2.SetEventObject( win );
+ ret = win->GetEventHandler()->ProcessEvent( event2 );
+ }
+
+ /* 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
+#if 0
+ (!win->HasFlag(wxTE_PROCESS_TAB)) &&
+#endif // 0
+ (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) )
+ {
+ wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
+ new_event.SetEventObject( win );
+ ret = win->GetEventHandler()->ProcessEvent( new_event );
+ }
+
+#if (GTK_MINOR_VERSION > 0)
+ /* Pressing F10 will activate the menu bar of the top frame. */
+ /* Doesn't work. */
+/*
+ if ( (!ret) &&
+ (gdk_event->keyval == GDK_F10) )
+ {
+ wxWindow *ancestor = win;
+ while (ancestor)
+ {
+ if (wxIsKindOf(ancestor,wxFrame))
+ {
+ wxFrame *frame = (wxFrame*) ancestor;
+ wxMenuBar *menubar = frame->GetMenuBar();
+ if (menubar)
+ {
+ wxNode *node = menubar->GetMenus().First();
+ if (node)
+ {
+ wxMenu *firstMenu = (wxMenu*) node->Data();
+ gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+ ancestor = ancestor->GetParent();
+ }
+ }
+*/
+#endif
+
+ if (ret)
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "key_release_event" from any window
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+/*
+ printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
+ if (gdk_event->state & GDK_SHIFT_MASK)
+ printf( "ShiftDown.\n" );
+ else
+ printf( "ShiftUp.\n" );
+ if (gdk_event->state & GDK_CONTROL_MASK)
+ printf( "ControlDown.\n" );
+ else
+ printf( "ControlUp.\n" );
+ printf( "\n" );
+*/
+
+ long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+
+ /* sending unknown key events doesn't really make sense */
+ if (key_code == 0) return FALSE;
+
+ int x = 0;
+ int y = 0;
+ GdkModifierType state;
+ if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+
+ wxKeyEvent event( wxEVT_KEY_UP );
+ 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_keyCode = key_code;
+ event.m_scanCode = gdk_event->keyval;
+ event.m_x = x;
+ event.m_y = y;
+ event.SetEventObject( win );
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// ----------------------------------------------------------------------------
+// mouse event processing helper
+// ----------------------------------------------------------------------------
+
+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
+ switch ( event.GetEventType() )
+ {
+ case wxEVT_LEFT_DOWN:
+ case wxEVT_LEFT_DCLICK:
+ case wxEVT_LEFT_UP:
+ event.m_leftDown = !event.m_leftDown;
+ break;
+
+ case wxEVT_MIDDLE_DOWN:
+ case wxEVT_MIDDLE_DCLICK:
+ case wxEVT_MIDDLE_UP:
+ event.m_middleDown = !event.m_middleDown;
+ break;
+
+ case wxEVT_RIGHT_DOWN:
+ case wxEVT_RIGHT_DCLICK:
+ case wxEVT_RIGHT_UP:
+ event.m_rightDown = !event.m_rightDown;
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// "button_press_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+/*
+ wxPrintf( wxT("1) OnButtonPress from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( wxT(".\n") );
+*/
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return TRUE;
+ if (g_blockEventsOnScroll) return TRUE;
+
+ if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+
+ if (win->m_wxwindow)
+ {
+ if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
+ {
+ gtk_widget_grab_focus (win->m_wxwindow);
+
+/*
+ wxPrintf( wxT("GrabFocus from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( wxT(".\n") );
+*/
+
+ }
+ }
+
+ wxEventType event_type = wxEVT_NULL;
+
+ if (gdk_event->button == 1)
+ {
+ switch (gdk_event->type)
+ {
+ case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
+ case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
+ default: break;
+ }
+ }
+ else if (gdk_event->button == 2)
+ {
+ switch (gdk_event->type)
+ {
+ case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
+ case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
+ default: break;
+ }
+ }
+ else if (gdk_event->button == 3)
+ {
+ switch (gdk_event->type)
+ {
+ case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
+ case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
+ default: break;
+ }
+ }
+
+ if ( event_type == wxEVT_NULL )
+ {
+ // unknown mouse button or click type
+ return FALSE;
+ }
+
+ wxMouseEvent event( event_type );
+ 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);
+
+ event.m_x = (wxCoord)gdk_event->x;
+ event.m_y = (wxCoord)gdk_event->y;
+
+ AdjustEventButtonState(event);
+
+ // 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)
+ {
+ wxWindow *child = (wxWindow*)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;
+ }
+ }
+ }
+ }
+
+ event.SetEventObject( win );
+
+ gs_timeLastClick = gdk_event->time;
+
+/*
+ wxPrintf( wxT("2) OnButtonPress from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( wxT(".\n") );
+*/
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "button_release_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+ if (g_blockEventsOnScroll) return FALSE;
+
+ if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+
+/*
+ printf( "OnButtonRelease from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ printf( win->GetClassInfo()->GetClassName() );
+ printf( ".\n" );
+*/
+
+ wxEventType event_type = wxEVT_NULL;
+
+ switch (gdk_event->button)
+ {
+ case 1: event_type = wxEVT_LEFT_UP; break;
+ case 2: event_type = wxEVT_MIDDLE_UP; break;
+ case 3: event_type = wxEVT_RIGHT_UP; break;
+ default: return FALSE;
+ }
+
+ wxMouseEvent event( event_type );
+ 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);
+ event.m_x = (wxCoord)gdk_event->x;
+ event.m_y = (wxCoord)gdk_event->y;
+
+ AdjustEventButtonState(event);
+
+ // 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)
+ {
+ wxWindow *child = (wxWindow*)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;
+ }
+ }
+ }
+ }
+
+ event.SetEventObject( win );
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "motion_notify_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+ if (g_blockEventsOnScroll) return FALSE;
+
+ if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+
+ if (gdk_event->is_hint)
+ {
+ int x = 0;
+ int y = 0;
+ GdkModifierType state;
+ gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+ gdk_event->x = x;
+ gdk_event->y = y;
+ }
+
+/*
+ printf( "OnMotion from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ printf( win->GetClassInfo()->GetClassName() );
+ printf( ".\n" );
+*/
+
+ wxMouseEvent event( wxEVT_MOTION );
+ 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);
+
+ event.m_x = (wxCoord)gdk_event->x;
+ event.m_y = (wxCoord)gdk_event->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)
+ {
+ wxWindow *child = (wxWindow*)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;
+ }
+ }
+ }
+ }
+
+ event.SetEventObject( win );
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "focus_in_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+ switch ( g_sendActivateEvent )
+ {
+ case -1:
+ // we've got focus from outside, synthtize wxActivateEvent
+ g_sendActivateEvent = 1;
+ break;
+
+ case 0:
+ // another our window just lost focus, it was already ours before
+ // - don't send any wxActivateEvent
+ g_sendActivateEvent = -1;
+ break;
+ }
+
+ g_focusWindow = win;
+
+/*
+ printf( "OnSetFocus from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ printf( win->GetClassInfo()->GetClassName() );
+ printf( " " );
+ printf( WXSTRINGCAST win->GetLabel() );
+ printf( ".\n" );
+*/
+
+ wxPanel *panel = wxDynamicCast(win->GetParent(), wxPanel);
+ if (panel)
+ {
+ panel->SetLastFocus(win);
+ }
+
+#ifdef HAVE_XIM
+ if (win->m_ic)
+ gdk_im_begin(win->m_ic, win->m_wxwindow->window);
+#endif
+
+#ifdef wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = win->GetCaret();
+ if ( caret )
+ {
+ caret->OnSetFocus();
+ }
+#endif // wxUSE_CARET
+
+ wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
+ event.SetEventObject( win );
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "focus_out_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+ // if the focus goes out of our app alltogether, OnIdle() will send
+ // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
+ // g_sendActivateEvent to -1
+ g_sendActivateEvent = 0;
+
+ wxWindow *winFocus = FindFocusedChild(win);
+ if ( winFocus )
+ win = winFocus;
+
+ g_focusWindow = (wxWindow *)NULL;
+
+/*
+ printf( "OnKillFocus from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ printf( win->GetClassInfo()->GetClassName() );
+ printf( ".\n" );
+*/
+
+#ifdef HAVE_XIM
+ if (win->m_ic)
+ gdk_im_end();
+#endif
+
+#ifdef wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = win->GetCaret();
+ if ( caret )
+ {
+ caret->OnKillFocus();
+ }
+#endif // wxUSE_CARET
+
+ 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;
+}
+
+//-----------------------------------------------------------------------------
+// "enter_notify_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+ if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+
+ wxMouseEvent event( wxEVT_ENTER_WINDOW );
+#if (GTK_MINOR_VERSION > 0)
+ event.SetTimestamp( gdk_event->time );
+#endif
+ event.SetEventObject( win );
+
+ int x = 0;
+ int y = 0;
+ GdkModifierType state = (GdkModifierType)0;
+
+ gdk_window_get_pointer( widget->window, &x, &y, &state );
+
+ event.m_shiftDown = (state & GDK_SHIFT_MASK);
+ event.m_controlDown = (state & GDK_CONTROL_MASK);
+ event.m_altDown = (state & GDK_MOD1_MASK);
+ event.m_metaDown = (state & GDK_MOD2_MASK);
+ event.m_leftDown = (state & GDK_BUTTON1_MASK);
+ event.m_middleDown = (state & GDK_BUTTON2_MASK);
+ event.m_rightDown = (state & GDK_BUTTON3_MASK);
+
+ event.m_x = x;
+ event.m_y = y;
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "leave_notify_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+ if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+
+ wxMouseEvent event( wxEVT_LEAVE_WINDOW );
+#if (GTK_MINOR_VERSION > 0)
+ event.SetTimestamp( gdk_event->time );
+#endif
+ event.SetEventObject( win );
+
+ int x = 0;
+ int y = 0;
+ GdkModifierType state = (GdkModifierType)0;
+
+ gdk_window_get_pointer( widget->window, &x, &y, &state );
+
+ event.m_shiftDown = (state & GDK_SHIFT_MASK);
+ event.m_controlDown = (state & GDK_CONTROL_MASK);
+ event.m_altDown = (state & GDK_MOD1_MASK);
+ event.m_metaDown = (state & GDK_MOD2_MASK);
+ event.m_leftDown = (state & GDK_BUTTON1_MASK);
+ event.m_middleDown = (state & GDK_BUTTON2_MASK);
+ event.m_rightDown = (state & GDK_BUTTON3_MASK);
+
+ event.m_x = x;
+ event.m_y = y;
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "value_changed" from m_vAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (g_blockEventsOnDrag) return;
+
+ if (!win->m_hasVMT) return;
+
+ float diff = adjust->value - win->m_oldVerticalPos;
+ if (fabs(diff) < 0.2) return;
+
+ win->m_oldVerticalPos = adjust->value;
+
+ GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
+ GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
+
+ wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
+ if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
+ else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
+ else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
+ else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
+
+ int value = (int)(adjust->value+0.5);
+
+ wxScrollWinEvent event( command, value, wxVERTICAL );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+}
+
+//-----------------------------------------------------------------------------
+// "value_changed" from m_hAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (g_blockEventsOnDrag) return;
+ if (!win->m_hasVMT) return;
+
+ float diff = adjust->value - win->m_oldHorizontalPos;
+ if (fabs(diff) < 0.2) return;
+
+ win->m_oldHorizontalPos = adjust->value;
+
+ GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
+ GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
+
+ wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
+ if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
+ else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
+ else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
+ else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
+
+ int value = (int)(adjust->value+0.5);
+
+ wxScrollWinEvent event( command, value, wxHORIZONTAL );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+}
+
+//-----------------------------------------------------------------------------
+// "button_press_event" from scrollbar
+//-----------------------------------------------------------------------------
+
+static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
+ GdkEventButton *gdk_event,
+ wxWindow *win)
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+
+ g_blockEventsOnScroll = TRUE;
+ win->m_isScrolling = (gdk_event->window == widget->slider);
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "button_release_event" from scrollbar
+//-----------------------------------------------------------------------------
+
+static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
+ GdkEventButton *WXUNUSED(gdk_event),
+ wxWindow *win)
+{
+ DEBUG_MAIN_THREAD
+
+// don't test here as we can release the mouse while being over
+// a different window than the slider
+//
+// if (gdk_event->window != widget->slider) return FALSE;
+
+ g_blockEventsOnScroll = FALSE;
+
+ if (win->m_isScrolling)
+ {
+ wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
+ int value = -1;
+ int dir = -1;
+
+ GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
+ if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
+ {
+ value = (int)(win->m_hAdjust->value+0.5);
+ dir = wxHORIZONTAL;
+ }
+ if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
+ {
+ value = (int)(win->m_vAdjust->value+0.5);
+ dir = wxVERTICAL;
+ }
+
+ wxScrollWinEvent event( command, value, dir );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+ }
+
+ win->m_isScrolling = FALSE;
+
+ return FALSE;
+}
+
+// ----------------------------------------------------------------------------
+// this wxWindowBase function is implemented here (in platform-specific file)
+// because it is static and so couldn't be made virtual
+// ----------------------------------------------------------------------------
+
+wxWindow *wxWindowBase::FindFocus()
+{
+ return g_focusWindow;
+}
+
+//-----------------------------------------------------------------------------
+// "realize" from m_widget
+//-----------------------------------------------------------------------------
+
+/* We cannot set colours and fonts before the widget has
+ been realized, so we do this directly after realization. */
+
+static gint
+gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (win->m_delayedBackgroundColour)
+ win->SetBackgroundColour( win->GetBackgroundColour() );
+
+ if (win->m_delayedForegroundColour)
+ win->SetForegroundColour( win->GetForegroundColour() );
+
+ wxWindowCreateEvent event( win );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "size_allocate"
+//-----------------------------------------------------------------------------
+
+static
+void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
+ GtkAllocation *WXUNUSED(alloc),
+ wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasScrolling) return;
+
+ int client_width = 0;
+ int client_height = 0;
+ win->GetClientSize( &client_width, &client_height );
+ if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
+ return;
+
+ win->m_oldClientWidth = client_width;
+ win->m_oldClientHeight = client_height;
+
+ if (!win->m_nativeSizeEvent)
+ {
+ wxSizeEvent event( win->GetSize(), win->GetId() );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+ }
+}
+
+
+#ifdef HAVE_XIM
+ #define WXUNUSED_UNLESS_XIM(param) param
+#else
+ #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
+#endif
+
+/* Resize XIM window */
+
+static
+void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
+ GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
+ wxWindow* WXUNUSED_UNLESS_XIM(win) )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+#ifdef HAVE_XIM
+ if (!win->m_ic)