+ 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;
+
+ 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;
+}
+
+// ============================================================================
+// the mouse events
+// ============================================================================
+
+// init wxMouseEvent with the info from gdk_event
+#define InitMouseEvent(event, gdk_event) \
+ event.SetTimestamp( gdk_event->time ); \
+ event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
+ event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
+ event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
+ event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
+ event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
+ event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
+ event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
+\
+ event.m_x = (wxCoord)gdk_event->x; \
+ event.m_y = (wxCoord)gdk_event->y \
+
+//-----------------------------------------------------------------------------
+// "motion_notify_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_motion_notify_callback( GtkWidget *widget,
+ GdkEventMotion *gdk_event,
+ wxWindowGTK *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+ 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 );
+ InitMouseEvent(event, gdk_event);
+
+ if ( g_captureWindow )
+ {
+ // synthetize a mouse enter or leave event if needed
+ GdkWindow *winUnderMouse = gdk_window_at_pointer(NULL, NULL);
+ bool hasMouse = winUnderMouse == gdk_event->window;
+ if ( hasMouse != g_captureWindowHasMouse )
+ {
+ // the mouse changed window
+ g_captureWindowHasMouse = hasMouse;
+
+ wxMouseEvent event(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW
+ : wxEVT_LEAVE_WINDOW);
+ InitMouseEvent(event, gdk_event);
+ event.SetEventObject(win);
+ win->GetEventHandler()->ProcessEvent(event);
+ }
+ }
+ 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;
+ }
+ }
+ }
+ }
+
+ 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, synthetize 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_focusWindowLast =
+ g_focusWindow = win;
+
+#if 0
+ wxPrintf( "OnSetFocus from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( ".\n" );
+#endif
+
+ // notify the parent keeping track of focus for the kbd navigation
+ // purposes that we got it
+ wxChildFocusEvent eventFocus(win);
+ (void)win->GetEventHandler()->ProcessEvent(eventFocus);
+
+#ifdef HAVE_XIM
+ if (win->m_ic)
+ gdk_im_begin(win->m_ic, win->m_wxwindow->window);
+#endif
+
+#if wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = win->GetCaret();
+ if ( caret )
+ {
+ caret->OnSetFocus();
+ }
+#endif // wxUSE_CARET
+
+ wxWindowGTK *active = wxGetTopLevelParent(win);
+ if ( active != g_activeFrame )
+ {
+ if ( g_activeFrame )
+ {
+ wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame);
+ wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
+ event.SetEventObject(g_activeFrame);
+ g_activeFrame->GetEventHandler()->ProcessEvent(event);
+ }
+
+ wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active);
+ g_activeFrame = active;
+ wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId());
+ event.SetEventObject(g_activeFrame);
+ g_activeFrame->GetEventHandler()->ProcessEvent(event);
+ }
+ g_activeFrameLostFocus = FALSE;
+
+
+ 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 GtkWidget *gs_widgetLastFocus = NULL;
+
+static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindowGTK *win )
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasVMT) return FALSE;
+ if (g_blockEventsOnDrag) return FALSE;
+
+ // VZ: this is really weird but GTK+ seems to call us from inside
+ // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
+ // this widget and then "focus_in". This is totally unexpected and
+ // completely breaks wxUniv code so ignore this dummy event (we can't
+ // be losing focus if we're about to acquire it!)
+ if ( widget == gs_widgetLastFocus )
+ {
+ gs_widgetLastFocus = NULL;
+
+ return FALSE;
+ }
+
+ if ( !g_activeFrameLostFocus && g_activeFrame )
+ {
+ // VZ: commenting this out because it does happen (although not easy
+ // to reproduce, I only see it when using wxMiniFrame and not
+ // always) and makes using Mahogany quite annoying
+#if 0
+ wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame,
+ wxT("unfocusing window that hasn't gained focus properly") )
+#endif // 0
+
+ g_activeFrameLostFocus = TRUE;
+ }
+
+ // 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;
+
+ wxWindowGTK *winFocus = wxFindFocusedChild(win);
+ if ( winFocus )
+ win = winFocus;
+
+ g_focusWindow = (wxWindowGTK *)NULL;
+
+#if 0
+ wxPrintf( "OnKillFocus from " );
+ if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+ wxPrintf( win->GetClassInfo()->GetClassName() );
+ wxPrintf( ".\n" );
+#endif
+
+#ifdef HAVE_XIM
+ if (win->m_ic)
+ gdk_im_end();
+#endif
+
+#if 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, wxWindowGTK *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 );
+ event.SetTimestamp( gdk_event->time );
+ event.SetEventObject( win );
+
+ int x = 0;
+ int y = 0;
+ GdkModifierType state = (GdkModifierType)0;
+
+ gdk_window_get_pointer( widget->window, &x, &y, &state );
+
+ InitMouseEvent(event, gdk_event);
+
+ 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, wxWindowGTK *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 );
+ event.SetTimestamp( gdk_event->time );
+ 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, wxWindowGTK *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, wxWindowGTK *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,
+ wxWindowGTK *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),
+ wxWindowGTK *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()
+{
+ // the cast is necessary when we compile in wxUniversal mode
+ return (wxWindow *)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),
+ wxWindowGTK* WXUNUSED_UNLESS_XIM(win) )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+#ifdef HAVE_XIM
+ if (!win->m_ic)
+ return;
+
+ if (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION)
+ {
+ gint width, height;
+
+ gdk_window_get_size (widget->window, &width, &height);
+ win->m_icattr->preedit_area.width = width;
+ win->m_icattr->preedit_area.height = height;
+ gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
+ }
+#endif // HAVE_XIM
+}
+
+//-----------------------------------------------------------------------------
+// "realize" from m_wxwindow
+//-----------------------------------------------------------------------------
+
+/* Initialize XIM support */
+
+static gint
+gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
+ wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+#ifdef HAVE_XIM
+ if (win->m_ic) return FALSE;
+ if (!widget) return FALSE;
+ if (!gdk_im_ready()) return FALSE;
+
+ win->m_icattr = gdk_ic_attr_new();
+ if (!win->m_icattr) return FALSE;
+
+ gint width, height;
+ GdkEventMask mask;
+ GdkColormap *colormap;
+ GdkICAttr *attr = win->m_icattr;
+ unsigned attrmask = GDK_IC_ALL_REQ;
+ GdkIMStyle style;
+ GdkIMStyle supported_style = (GdkIMStyle)
+ (GDK_IM_PREEDIT_NONE |
+ GDK_IM_PREEDIT_NOTHING |
+ GDK_IM_PREEDIT_POSITION |
+ GDK_IM_STATUS_NONE |
+ GDK_IM_STATUS_NOTHING);
+
+ if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+ supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
+
+ attr->style = style = gdk_im_decide_style (supported_style);
+ attr->client_window = widget->window;
+
+ if ((colormap = gtk_widget_get_colormap (widget)) !=
+ gtk_widget_get_default_colormap ())
+ {
+ attrmask |= GDK_IC_PREEDIT_COLORMAP;
+ attr->preedit_colormap = colormap;
+ }
+
+ attrmask |= GDK_IC_PREEDIT_FOREGROUND;
+ attrmask |= GDK_IC_PREEDIT_BACKGROUND;
+ attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
+ attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
+
+ switch (style & GDK_IM_PREEDIT_MASK)
+ {
+ case GDK_IM_PREEDIT_POSITION:
+ if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+ {
+ g_warning ("over-the-spot style requires fontset");
+ break;
+ }
+
+ gdk_window_get_size (widget->window, &width, &height);
+
+ attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
+ attr->spot_location.x = 0;
+ attr->spot_location.y = height;
+ attr->preedit_area.x = 0;
+ attr->preedit_area.y = 0;
+ attr->preedit_area.width = width;
+ attr->preedit_area.height = height;
+ attr->preedit_fontset = widget->style->font;
+
+ break;
+ }
+
+ win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
+
+ if (win->m_ic == NULL)
+ g_warning ("Can't create input context.");
+ else
+ {
+ mask = gdk_window_get_events (widget->window);
+ mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
+ gdk_window_set_events (widget->window, mask);
+
+ if (GTK_WIDGET_HAS_FOCUS(widget))
+ gdk_im_begin (win->m_ic, widget->window);
+ }
+#endif // HAVE_XIM
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// InsertChild for wxWindowGTK.
+//-----------------------------------------------------------------------------
+
+/* Callback for wxWindowGTK. 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( wxWindowGTK* parent, wxWindowGTK* child )
+{
+ /* the window might have been scrolled already, do we
+ have to adapt the position */
+ GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
+ child->m_x += pizza->xoffset;
+ child->m_y += pizza->yoffset;
+
+ gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
+ GTK_WIDGET(child->m_widget),
+ child->m_x,
+ child->m_y,
+ child->m_width,
+ child->m_height );
+}
+
+//-----------------------------------------------------------------------------
+// global functions
+//-----------------------------------------------------------------------------
+
+wxWindow *wxGetActiveWindow()
+{
+ // the cast is necessary when we compile in wxUniversal mode
+ return (wxWindow *)g_focusWindow;
+}
+
+//-----------------------------------------------------------------------------
+// wxWindowGTK
+//-----------------------------------------------------------------------------
+
+// in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
+// method
+#ifdef __WXUNIVERSAL__
+ IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK, wxWindowBase)
+#else // __WXGTK__
+ IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+#endif // __WXUNIVERSAL__/__WXGTK__
+
+void wxWindowGTK::Init()
+{
+ // common init
+ InitBase();
+
+ // GTK specific
+ m_widget = (GtkWidget *) NULL;
+ m_wxwindow = (GtkWidget *) NULL;
+ m_focusWidget = (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_noExpose = FALSE;
+ m_nativeSizeEvent = 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_widgetStyle = (GtkStyle*) NULL;
+
+ m_insertCallback = (wxInsertChildFunction) NULL;
+
+ m_isStaticBox = FALSE;
+ m_isRadioButton = FALSE;
+ m_isListBox = FALSE;
+ m_isFrame = FALSE;
+ m_acceptsFocus = FALSE;
+
+ m_clipPaintRegion = FALSE;
+
+ m_cursor = *wxSTANDARD_CURSOR;
+
+ m_delayedForegroundColour = FALSE;
+ m_delayedBackgroundColour = FALSE;
+
+#ifdef HAVE_XIM
+ m_ic = (GdkIC*) NULL;
+ m_icattr = (GdkICAttr*) NULL;
+#endif
+}
+
+wxWindowGTK::wxWindowGTK()
+{
+ Init();
+}
+
+wxWindowGTK::wxWindowGTK( wxWindow *parent,
+ wxWindowID id,
+ const wxPoint &pos,
+ const wxSize &size,
+ long style,
+ const wxString &name )
+{
+ Init();
+
+ Create( parent, id, pos, size, style, name );
+}
+
+bool wxWindowGTK::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( wxT("wxWindowGTK 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 );
+
+ GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
+
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
+ 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_pizza_new();
+
+ gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
+
+#ifndef __WXUNIVERSAL__
+#if (GTK_MINOR_VERSION > 0)
+ GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
+
+ if (HasFlag(wxRAISED_BORDER))
+ {
+ gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
+ }
+ else if (HasFlag(wxSUNKEN_BORDER))
+ {
+ gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN );
+ }
+ else if (HasFlag(wxSIMPLE_BORDER))
+ {
+ gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN );
+ }
+ else
+ {
+ gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_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
+#endif // __WXUNIVERSAL__
+
+ 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_widget_show( m_wxwindow );
+
+ if (m_parent)
+ m_parent->DoAddChild( this );
+
+ m_focusWidget = m_wxwindow;
+
+ PostCreation();
+
+ Show( TRUE );
+
+ return TRUE;
+}
+
+wxWindowGTK::~wxWindowGTK()
+{
+ if (g_focusWindow == this)
+ g_focusWindow = NULL;
+
+ if (g_activeFrame == this)
+ g_activeFrame = NULL;
+
+ m_isBeingDeleted = TRUE;
+ m_hasVMT = FALSE;
+
+ if (m_widget)
+ Show( FALSE );
+
+ DestroyChildren();
+
+ if (m_parent)
+ m_parent->RemoveChild( this );
+
+#ifdef HAVE_XIM
+ if (m_ic)
+ gdk_ic_destroy (m_ic);
+ if (m_icattr)
+ gdk_ic_attr_destroy (m_icattr);
+#endif
+
+ if (m_widgetStyle)
+ {
+#if DISABLE_STYLE_IF_BROKEN_THEME
+ // don't delete if it's a pixmap theme style
+ if (!m_widgetStyle->engine_data)
+ gtk_style_unref( m_widgetStyle );
+#endif
+ m_widgetStyle = (GtkStyle*) 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 wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos, const wxSize &size )
+{
+ wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("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;
+ }
+ }
+
+ return TRUE;
+}
+
+void wxWindowGTK::PostCreation()
+{
+ wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
+
+ if (m_wxwindow)
+ {
+ if (!m_noExpose)
+ {
+ // these get reported to wxWindows -> wxPaintEvent
+
+ gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
+
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
+ GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
+ GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
+
+ if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
+ {
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
+ GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
+ }
+ }
+
+ // these are called when the "sunken" or "raised" borders are drawn */
+ gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
+ GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
+ GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
+ }
+
+ // focus handling
+
+ if (m_focusWidget == NULL)
+ m_focusWidget = m_widget;
+
+#if 0
+ if (GetClassInfo() && GetClassInfo()->GetClassName())
+ wxPrintf( GetClassInfo()->GetClassName() );
+ wxPrintf( ".\n" );
+#endif
+
+ gtk_signal_connect( GTK_OBJECT(m_focusWidget), "focus_in_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(m_focusWidget), "focus_out_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+
+ // connect to the various key and mouse handlers
+
+ GtkWidget *connect_widget = GetConnectWidget();
+
+ ConnectWidget( connect_widget );
+
+ /* We cannot set colours, fonts and cursors before the widget has
+ been realized, so we do this directly after realization */
+ gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
+ GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
+
+ if (m_wxwindow)
+ {
+ // Catch native resize events
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
+ GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
+
+ // Initialize XIM support
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
+ GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
+
+ // And resize XIM window
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
+ GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
+ }
+
+ if (!GTK_IS_COMBO(m_widget))
+ {
+ // This is needed if we want to add our windows into native
+ // GTK control, such as the toolbar. With this callback, the
+ // toolbar gets to know the correct size (the one set by the
+ // programmer). Sadly, it misbehaves for wxComboBox. FIXME
+ // when moving to GTK 2.0.
+ gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
+ GTK_SIGNAL_FUNC(gtk_window_size_request_callback), (gpointer) this );
+ }
+
+ m_hasVMT = TRUE;
+}
+
+void wxWindowGTK::ConnectWidget( GtkWidget *widget )
+{
+ gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
+ GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
+ GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
+ GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
+ GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
+ GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
+ GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
+ GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
+}
+
+bool wxWindowGTK::Destroy()
+{
+ wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
+
+ m_hasVMT = FALSE;
+
+ return wxWindowBase::Destroy();
+}
+
+void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
+{
+ gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
+}
+
+void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
+{
+ wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
+ wxASSERT_MSG( (m_parent != NULL), wxT("wxWindowGTK::SetSize requires parent.\n") );
+
+/*
+ printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
+*/
+
+ if (m_resizing) return; /* I don't like recursions */
+ m_resizing = TRUE;
+
+ int currentX, currentY;
+ GetPosition(¤tX, ¤tY);
+ if (x == -1)
+ x = currentX;
+ if (y == -1)
+ y = currentY;
+ AdjustForParentClientOrigin(x, y, sizeFlags);
+
+ if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
+ {
+ /* don't set the size for children of wxNotebook, just take the values. */
+ m_x = x;
+ m_y = y;
+ m_width = width;
+ m_height = height;
+ }
+ else
+ {
+ GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
+
+ if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
+ {
+ if (x != -1) m_x = x + pizza->xoffset;
+ if (y != -1) m_y = y + pizza->yoffset;
+ if (width != -1) m_width = width;
+ if (height != -1) m_height = height;
+ }
+ else
+ {
+ m_x = x + pizza->xoffset;
+ m_y = y + pizza->yoffset;
+ m_width = width;
+ m_height = height;
+ }
+
+ if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
+ {
+ if (width == -1) m_width = 80;
+ }
+
+ if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
+ {
+ if (height == -1) m_height = 26;
+ }
+
+ if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
+ if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
+ if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
+ if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
+
+ int border = 0;
+ int bottom_border = 0;
+
+ if (GTK_WIDGET_CAN_DEFAULT(m_widget))
+ {
+ /* the default button has a border around it */
+ border = 6;
+ bottom_border = 5;
+ }
+
+ DoMoveWindow( m_x-border,
+ m_y-border,
+ m_width+2*border,
+ m_height+border+bottom_border );
+ }
+
+ if (m_hasScrolling)
+ {
+ /* Sometimes the client area changes size without the
+ whole windows's size changing, but if the whole
+ windows's size doesn't change, no wxSizeEvent will
+ normally be sent. Here we add an extra test if
+ the client test has been changed and this will
+ be used then. */
+ GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
+ }
+
+/*
+ wxPrintf( "OnSize sent from " );
+ if (GetClassInfo() && GetClassInfo()->GetClassName())
+ wxPrintf( GetClassInfo()->GetClassName() );
+ wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
+*/
+
+ if (!m_nativeSizeEvent)
+ {
+ wxSizeEvent event( wxSize(m_width,m_height), GetId() );
+ event.SetEventObject( this );
+ GetEventHandler()->ProcessEvent( event );
+ }
+
+ m_resizing = FALSE;
+}
+
+void wxWindowGTK::OnInternalIdle()
+{
+ if ( g_sendActivateEvent != -1 )
+ {
+ bool activate = g_sendActivateEvent != 0;
+
+ // do it only once
+ g_sendActivateEvent = -1;
+
+ wxTheApp->SetActive(activate, (wxWindow *)g_focusWindowLast);
+ }
+
+ if ( g_activeFrameLostFocus )
+ {
+ if ( g_activeFrame )
+ {
+ wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame);
+ wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
+ event.SetEventObject(g_activeFrame);
+ g_activeFrame->GetEventHandler()->ProcessEvent(event);
+ g_activeFrame = NULL;
+ }
+ g_activeFrameLostFocus = FALSE;
+ }
+
+ wxCursor cursor = m_cursor;
+ if (g_globalCursor.Ok()) cursor = g_globalCursor;
+
+ if (cursor.Ok())
+ {
+ /* I now set the cursor anew in every OnInternalIdle call
+ as setting the cursor in a parent window also effects the
+ windows above so that checking for the current cursor is
+ not possible. */
+
+ if (m_wxwindow)
+ {
+ GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
+ if (window)
+ gdk_window_set_cursor( window, cursor.GetCursor() );
+
+ if (!g_globalCursor.Ok())
+ cursor = *wxSTANDARD_CURSOR;
+
+ window = m_widget->window;
+ if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
+ gdk_window_set_cursor( window, cursor.GetCursor() );
+
+ }
+ else
+ {
+
+ GdkWindow *window = m_widget->window;
+ if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
+ gdk_window_set_cursor( window, cursor.GetCursor() );
+
+ }
+ }
+
+ UpdateWindowUI();
+}
+
+void wxWindowGTK::DoGetSize( int *width, int *height ) const
+{
+ wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
+
+ if (width) (*width) = m_width;
+ if (height) (*height) = m_height;
+}
+
+void wxWindowGTK::DoSetClientSize( int width, int height )
+{
+ wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
+
+ if (!m_wxwindow)
+ {
+ SetSize( width, height );
+ }
+ else
+ {
+ int dw = 0;
+ int dh = 0;
+
+#ifndef __WXUNIVERSAL__
+ if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
+ {
+ /* when using GTK 1.2 we set the shadow border size to 2 */
+ dw += 2 * 2;
+ dh += 2 * 2;
+ }
+ if (HasFlag(wxSIMPLE_BORDER))
+ {
+ /* when using GTK 1.2 we set the simple border size to 1 */
+ dw += 1 * 2;
+ dh += 1 * 2;
+ }
+#endif // __WXUNIVERSAL__
+
+ if (m_hasScrolling)
+ {
+ GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
+
+ GtkRequisition vscroll_req;
+ vscroll_req.width = 2;
+ vscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
+ (scroll_window->vscrollbar, &vscroll_req );
+
+ GtkRequisition hscroll_req;
+ hscroll_req.width = 2;
+ hscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
+ (scroll_window->hscrollbar, &hscroll_req );
+
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
+
+ if (scroll_window->vscrollbar_visible)
+ {
+ dw += vscroll_req.width;
+ dw += scroll_class->scrollbar_spacing;
+ }
+
+ if (scroll_window->hscrollbar_visible)
+ {
+ dh += hscroll_req.height;
+ dh += scroll_class->scrollbar_spacing;
+ }
+ }
+
+ SetSize( width+dw, height+dh );
+ }
+}
+
+void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
+{
+ wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
+
+ if (!m_wxwindow)
+ {
+ if (width) (*width) = m_width;
+ if (height) (*height) = m_height;
+ }
+ else
+ {
+ int dw = 0;
+ int dh = 0;
+
+#ifndef __WXUNIVERSAL__
+ if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
+ {
+ /* when using GTK 1.2 we set the shadow border size to 2 */
+ dw += 2 * 2;
+ dh += 2 * 2;
+ }
+ if (HasFlag(wxSIMPLE_BORDER))
+ {
+ /* when using GTK 1.2 we set the simple border size to 1 */
+ dw += 1 * 2;
+ dh += 1 * 2;
+ }
+#endif // __WXUNIVERSAL__
+
+ if (m_hasScrolling)
+ {
+ GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
+
+ GtkRequisition vscroll_req;
+ vscroll_req.width = 2;
+ vscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
+ (scroll_window->vscrollbar, &vscroll_req );
+
+ GtkRequisition hscroll_req;
+ hscroll_req.width = 2;
+ hscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
+ (scroll_window->hscrollbar, &hscroll_req );
+
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
+
+ if (scroll_window->vscrollbar_visible)
+ {
+ dw += vscroll_req.width;
+ dw += scroll_class->scrollbar_spacing;
+ }
+
+ if (scroll_window->hscrollbar_visible)
+ {
+ dh += hscroll_req.height;
+ dh += scroll_class->scrollbar_spacing;
+ }
+ }
+
+ if (width) (*width) = m_width - dw;
+ if (height) (*height) = m_height - dh;
+ }
+
+/*
+ printf( "GetClientSize, name %s ", GetName().c_str() );
+ if (width) printf( " width = %d", (*width) );
+ if (height) printf( " height = %d", (*height) );
+ printf( "\n" );
+*/
+}
+
+void wxWindowGTK::DoGetPosition( int *x, int *y ) const
+{
+ wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
+
+ int dx = 0;
+ int dy = 0;
+ if (m_parent && m_parent->m_wxwindow)
+ {
+ GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
+ dx = pizza->xoffset;
+ dy = pizza->yoffset;