+ 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)
+ {
+ // doesn't work correctly
+ // wxMenu *firstMenu = (wxMenu*) node->Data();
+ // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
+ // ret = TRUE;
+ break;
+ }
+ }
+ }
+ ancestor = ancestor->GetParent();
+ }
+ }
+#endif
+
+/*
+ Damn, I forgot why this didn't work, but it didn't work.
+
+ // win is a panel: up can be propagated to the panel
+ if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
+ (gdk_event->keyval == GDK_Up))
+ {
+ win->m_parent->SetFocus();
+ ret = TRUE;
+ }
+
+ // win is a panel: left/right can be propagated to the panel
+ if ((!ret) && (win->m_wxwindow) &&
+ ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
+ (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
+ {
+ wxNavigationKeyEvent new_event;
+ new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
+ new_event.SetCurrentFocus( win );
+ ret = win->GetEventHandler()->ProcessEvent( new_event );
+ }
+*/
+
+ 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 )
+{
+ 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;
+}
+
+//-----------------------------------------------------------------------------
+// "button_press_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+/*
+ wxPrintf( _T("1) OnButtonPress from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( _T(".\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( _T("GrabFocus from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( _T(".\n") );
+*/
+
+ }
+ }
+
+/*
+ wxPrintf( _T("2) OnButtonPress from ") );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( _T(".\n") );
+*/
+
+ wxEventType event_type = wxEVT_LEFT_DOWN;
+
+ 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;
+ }
+ }
+
+ 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 = (long)gdk_event->x;
+ event.m_y = (long)gdk_event->y;
+
+ // Some control don't have their own X window and thus cannot get
+ // any events.
+
+ if (!g_captureWindow)
+ {
+ wxNode *node = win->GetChildren().First();
+ while (node)
+ {
+ wxWindow *child = (wxWindow*)node->Data();
+
+ if (child->m_isStaticBox)
+ {
+ // wxStaticBox is transparent in the box itself
+ int x = event.m_x;
+ int y = event.m_y;
+ 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 <= event.m_x) &&
+ (child->m_y <= event.m_y) &&
+ (child->m_x+child->m_width >= event.m_x) &&
+ (child->m_y+child->m_height >= event.m_y))
+ {
+ win = child;
+ event.m_x -= child->m_x;
+ event.m_y -= child->m_y;
+ break;
+ }
+ }
+ node = node->Next();
+ }
+ }
+
+ event.SetEventObject( win );
+
+ gs_timeLastClick = gdk_event->time;
+
+ 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 )
+{
+ 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;
+ }
+
+ 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 = (long)gdk_event->x;
+ event.m_y = (long)gdk_event->y;
+
+ // Some control don't have their own X window and thus cannot get
+ // any events.
+
+ if (!g_captureWindow)
+ {
+ wxNode *node = win->GetChildren().First();
+ while (node)
+ {
+ wxWindow *child = (wxWindow*)node->Data();
+
+ if (child->m_isStaticBox)
+ {
+ // wxStaticBox is transparent in the box itself
+ int x = event.m_x;
+ int y = event.m_y;
+ 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 <= event.m_x) &&
+ (child->m_y <= event.m_y) &&
+ (child->m_x+child->m_width >= event.m_x) &&
+ (child->m_y+child->m_height >= event.m_y))
+ {
+ win = child;
+ event.m_x -= child->m_x;
+ event.m_y -= child->m_y;
+ break;
+ }
+ }
+ node = node->Next();
+ }
+ }
+
+ 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 )
+{
+ 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;
+ gdk_event->state = state;
+ }
+
+/*
+ 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 = (long)gdk_event->x;
+ event.m_y = (long)gdk_event->y;
+
+ // Some control don't have their own X window and thus cannot get
+ // any events.
+
+ if (!g_captureWindow)
+ {
+ wxNode *node = win->GetChildren().First();
+ while (node)
+ {
+ wxWindow *child = (wxWindow*)node->Data();
+
+ if (child->m_isStaticBox)
+ {
+ // wxStaticBox is transparent in the box itself
+ int x = event.m_x;
+ int y = event.m_y;
+ 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 <= event.m_x) &&
+ (child->m_y <= event.m_y) &&
+ (child->m_x+child->m_width >= event.m_x) &&
+ (child->m_y+child->m_height >= event.m_y))
+ {
+ win = child;
+ event.m_x -= child->m_x;
+ event.m_y -= child->m_y;
+ break;
+ }
+ }
+ node = node->Next();
+ }
+ }
+
+ 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 )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+ g_focusWindow = win;
+
+ if (win->m_wxwindow)
+ {
+ if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
+ {
+ GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
+/*
+ printf( "SetFocus flag from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ printf( win->GetClassInfo()->GetClassName() );
+ printf( ".\n" );
+*/
+ }
+ }
+
+
+/*
+ printf( "OnSetFocus from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ printf( win->GetClassInfo()->GetClassName() );
+ printf( " " );
+ printf( WXSTRINGCAST win->GetLabel() );
+ printf( ".\n" );
+*/
+
+ 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 )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+ if (win->m_wxwindow)
+ {
+ if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
+ GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
+ }
+
+/*
+ printf( "OnKillFocus from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ printf( win->GetClassInfo()->GetClassName() );
+ printf( ".\n" );
+*/
+
+ 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 )
+{
+ 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 = (long)x;
+ event.m_y = (long)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 )
+{
+ 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 = (long)x;
+ event.m_y = (long)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( GtkWidget *WXUNUSED(widget), wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (g_blockEventsOnDrag) return;
+
+ if (!win->m_hasVMT) return;
+
+ float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
+ if (fabs(diff) < 0.2) return;
+ win->m_oldVerticalPos = win->m_vAdjust->value;
+
+ wxEventType command = wxEVT_NULL;
+
+ float line_step = win->m_vAdjust->step_increment;
+ float page_step = win->m_vAdjust->page_increment;
+
+ if (win->IsScrolling())
+ {
+ command = wxEVT_SCROLLWIN_THUMBTRACK;
+ }
+ else
+ {
+ if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
+ else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
+ else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
+ else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
+ else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
+ else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
+ else command = wxEVT_SCROLLWIN_THUMBTRACK;
+ }
+
+ int value = (int)(win->m_vAdjust->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( GtkWidget *WXUNUSED(widget), wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (g_blockEventsOnDrag) return;
+ if (!win->m_hasVMT) return;
+
+ float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
+ if (fabs(diff) < 0.2) return;
+ win->m_oldHorizontalPos = win->m_hAdjust->value;
+
+ wxEventType command = wxEVT_NULL;
+
+ float line_step = win->m_hAdjust->step_increment;
+ float page_step = win->m_hAdjust->page_increment;
+
+ if (win->IsScrolling())
+ {
+ command = wxEVT_SCROLLWIN_THUMBTRACK;
+ }
+ else
+ {
+ if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLLWIN_BOTTOM;
+ else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLLWIN_TOP;
+ else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEDOWN;
+ else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLLWIN_LINEUP;
+ else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEDOWN;
+ else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLLWIN_PAGEUP;
+ else command = wxEVT_SCROLLWIN_THUMBTRACK;
+ }
+
+ int value = (int)(win->m_hAdjust->value+0.5);
+
+ wxScrollWinEvent event( command, value, wxHORIZONTAL );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+}
+
+//-----------------------------------------------------------------------------
+// "changed" from m_vAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (g_blockEventsOnDrag) return;
+ if (!win->m_hasVMT) return;
+
+ wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
+ int value = (int)(win->m_vAdjust->value+0.5);
+
+ wxScrollWinEvent event( command, value, wxVERTICAL );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+}
+
+//-----------------------------------------------------------------------------
+// "changed" from m_hAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (g_blockEventsOnDrag) return;
+ if (!win->m_hasVMT) return;
+
+ wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
+ int value = (int)(win->m_hAdjust->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 *WXUNUSED(widget),
+ GdkEventButton *WXUNUSED(gdk_event),
+ wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+// don't test here as we can release the mouse while being over
+// a different window then the slider
+//
+// if (gdk_event->window != widget->slider) return FALSE;
+
+ win->SetScrolling( TRUE );
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "button_release_event" from scrollbar
+//-----------------------------------------------------------------------------
+
+static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
+ GdkEventButton *WXUNUSED(gdk_event),
+ wxWindow *win )
+{
+
+// don't test here as we can release the mouse while being over
+// a different window then the slider
+//
+// if (gdk_event->window != widget->slider) return FALSE;
+
+ GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
+
+ if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
+ gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
+ else
+ gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
+
+ win->SetScrolling( 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, fonts and cursors before the widget has
+ been realized, so we do this directly after realization */
+
+static gint
+gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (win->m_delayedFont)
+ win->SetFont( win->GetFont() );
+
+ if (win->m_delayedBackgroundColour)
+ win->SetBackgroundColour( win->GetBackgroundColour() );
+
+ if (win->m_delayedForegroundColour)
+ win->SetForegroundColour( win->GetForegroundColour() );
+
+ win->SetCursor( win->GetCursor() );
+
+ wxWindowCreateEvent event( win );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// InsertChild for wxWindow.
+//-----------------------------------------------------------------------------
+
+/* Callback for wxWindow. This very strange beast has to be used because
+ * C++ has no virtual methods in a constructor. We have to emulate a
+ * virtual function here as wxNotebook requires a different way to insert
+ * a child in it. I had opted for creating a wxNotebookPage window class
+ * which would have made this superfluous (such in the MDI window system),
+ * but no-one was listening to me... */
+
+static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
+{
+ gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
+ GTK_WIDGET(child->m_widget),
+ child->m_x,
+ child->m_y,
+ child->m_width,
+ child->m_height );
+
+ if (parent->HasFlag(wxTAB_TRAVERSAL))
+ {
+ /* we now allow a window to get the focus as long as it
+ doesn't have any children. */
+ GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// global functions
+//-----------------------------------------------------------------------------
+
+wxWindow* wxGetActiveWindow()
+{
+ return g_focusWindow;
+}
+
+//-----------------------------------------------------------------------------
+// wxWindow
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+
+void wxWindow::Init()
+{
+ // common init
+ InitBase();
+
+ // GTK specific
+ m_widget = (GtkWidget *) NULL;
+ m_wxwindow = (GtkWidget *) NULL;
+
+ // position/size
+ m_x = 0;
+ m_y = 0;
+ m_width = 0;
+ m_height = 0;
+
+ m_sizeSet = FALSE;
+ m_hasVMT = FALSE;
+ m_needParent = TRUE;
+ m_isBeingDeleted = FALSE;
+
+ m_hasScrolling = FALSE;
+ m_isScrolling = FALSE;
+
+ m_hAdjust = (GtkAdjustment*) NULL;
+ m_vAdjust = (GtkAdjustment*) NULL;
+ m_oldHorizontalPos = 0.0;
+ m_oldVerticalPos = 0.0;
+
+ m_resizing = FALSE;
+ m_scrollGC = (GdkGC*) NULL;
+ m_widgetStyle = (GtkStyle*) NULL;
+
+ m_insertCallback = (wxInsertChildFunction) NULL;
+
+ m_isStaticBox = FALSE;
+ m_isRadioButton = FALSE;
+ m_acceptsFocus = FALSE;
+}
+
+wxWindow::wxWindow()
+{
+ Init();
+}
+
+wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
+ const wxPoint &pos, const wxSize &size,
+ long style, const wxString &name )
+{
+ Init();
+
+ Create( parent, id, pos, size, style, name );
+}
+
+bool wxWindow::Create( wxWindow *parent, wxWindowID id,
+ const wxPoint &pos, const wxSize &size,
+ long style, const wxString &name )
+{
+ if (!PreCreation( parent, pos, size ) ||
+ !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
+ {
+ wxFAIL_MSG( _T("wxWindow creation failed") );
+ return FALSE;
+ }
+
+ m_insertCallback = wxInsertChildInWindow;
+
+ m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
+ GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
+
+#ifdef __WXDEBUG__
+ debug_focus_in( m_widget, _T("wxWindow::m_widget"), name );
+#endif
+
+ GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
+
+#ifdef __WXDEBUG__
+ debug_focus_in( scrolledWindow->hscrollbar, _T("wxWindow::hsrcollbar"), name );
+ debug_focus_in( scrolledWindow->vscrollbar, _T("wxWindow::vsrcollbar"), name );
+#endif
+
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+ scroll_class->scrollbar_spacing = 0;
+
+ gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
+
+ m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
+ m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
+
+ m_wxwindow = gtk_myfixed_new();
+
+#ifdef __WXDEBUG__
+ debug_focus_in( m_wxwindow, _T("wxWindow::m_wxwindow"), name );
+#endif
+
+ gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
+
+#if (GTK_MINOR_VERSION > 0)
+ GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
+
+ if (HasFlag(wxRAISED_BORDER))
+ {
+ gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_OUT );
+ }
+ else if (HasFlag(wxSUNKEN_BORDER))
+ {
+ gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_IN );
+ }
+ else
+ {
+ gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_NONE );
+ }
+#else // GTK_MINOR_VERSION == 0
+ GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
+
+ if (HasFlag(wxRAISED_BORDER))
+ {
+ gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
+ }
+ else if (HasFlag(wxSUNKEN_BORDER))
+ {
+ gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
+ }
+ else
+ {
+ gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
+ }
+#endif // GTK_MINOR_VERSION
+
+ if (HasFlag(wxTAB_TRAVERSAL))
+ {
+ /* we now allow a window to get the focus as long as it
+ doesn't have any children. */
+ GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
+ m_acceptsFocus = FALSE;
+ }
+ else
+ {
+ GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
+ m_acceptsFocus = TRUE;
+ }
+
+#if (GTK_MINOR_VERSION == 0)
+ // shut the viewport up
+ gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
+ gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
+#endif // GTK_MINOR_VERSION == 0
+
+ // I _really_ don't want scrollbars in the beginning
+ m_vAdjust->lower = 0.0;
+ m_vAdjust->upper = 1.0;
+ m_vAdjust->value = 0.0;
+ m_vAdjust->step_increment = 1.0;
+ m_vAdjust->page_increment = 1.0;
+ m_vAdjust->page_size = 5.0;
+ gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
+ m_hAdjust->lower = 0.0;
+ m_hAdjust->upper = 1.0;
+ m_hAdjust->value = 0.0;
+ m_hAdjust->step_increment = 1.0;
+ m_hAdjust->page_increment = 1.0;
+ m_hAdjust->page_size = 5.0;
+ gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
+
+ // these handlers block mouse events to any window during scrolling such as
+ // motion events and prevent GTK and wxWindows from fighting over where the
+ // slider should be
+
+ gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
+ (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
+
+ gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
+ (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
+
+ gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
+ (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
+
+ gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
+ (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
+
+ // these handlers get notified when screen updates are required either when
+ // scrolling or when the window size (and therefore scrollbar configuration)
+ // has changed
+
+ gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
+ (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
+ gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
+ (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
+
+ gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
+ (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
+ gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
+ (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
+
+ gtk_widget_show( m_wxwindow );
+
+ if (m_parent)
+ m_parent->DoAddChild( this );
+
+ PostCreation();
+
+ Show( TRUE );
+
+ return TRUE;
+}
+
+wxWindow::~wxWindow()
+{
+ m_isBeingDeleted = TRUE;
+ m_hasVMT = FALSE;
+
+ if (m_widget)
+ Show( FALSE );
+
+ DestroyChildren();
+
+ if (m_parent)
+ m_parent->RemoveChild( this );
+
+ if (m_widgetStyle)
+ {
+ gtk_style_unref( m_widgetStyle );
+ m_widgetStyle = (GtkStyle*) NULL;
+ }
+
+ if (m_scrollGC)
+ {
+ gdk_gc_unref( m_scrollGC );
+ m_scrollGC = (GdkGC*) NULL;
+ }
+
+ if (m_wxwindow)
+ {
+ gtk_widget_destroy( m_wxwindow );
+ m_wxwindow = (GtkWidget*) NULL;
+ }
+
+ if (m_widget)
+ {
+ gtk_widget_destroy( m_widget );
+ m_widget = (GtkWidget*) NULL;
+ }
+}
+
+bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
+{
+ wxCHECK_MSG( !m_needParent || parent, FALSE, _T("Need complete parent.") );
+
+ /* this turns -1 into 20 so that a minimal window is
+ visible even although -1,-1 has been given as the
+ size of the window. the same trick is used in other
+ ports and should make debugging easier */
+ m_width = WidthDefault(size.x);
+ m_height = HeightDefault(size.y);
+
+ m_x = (int)pos.x;
+ m_y = (int)pos.y;
+
+ /* some reasonable defaults */
+ if (!parent)
+ {
+ if (m_x == -1)
+ {
+ m_x = (gdk_screen_width () - m_width) / 2;
+ if (m_x < 10) m_x = 10;
+ }
+ if (m_y == -1)
+ {
+ m_y = (gdk_screen_height () - m_height) / 2;
+ if (m_y < 10) m_y = 10;
+ }
+ }