#include "wx/settings.h"
#include "wx/log.h"
+#ifdef __WXDEBUG__
+ #include "wx/thread.h"
+#endif
+
#include <math.h>
-#include "gdk/gdk.h"
-#include "gtk/gtk.h"
-#include "gdk/gdkprivate.h"
-#include "gdk/gdkkeysyms.h"
-#include "wx/gtk/win_gtk.h"
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkprivate.h>
+#include <gdk/gdkkeysyms.h>
+#include <wx/gtk/win_gtk.h>
-#include "gdk/gdkx.h"
+#include <gdk/gdkx.h>
//-----------------------------------------------------------------------------
// documentation on internals
the last click here */
static guint32 gs_timeLastClick = 0;
+extern bool g_mainThreadLocked;
+
//-----------------------------------------------------------------------------
// debug
//-----------------------------------------------------------------------------
#ifdef __WXDEBUG__
+#if wxUSE_THREADS
+# define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
+#else
+# define DEBUG_MAIN_THREAD
+#endif
+
static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
GdkEvent *WXUNUSED(event),
const wxChar *WXUNUSED(name) )
void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window )
{
- wxString tmp = name;
- tmp += wxT(" FROM ");
- tmp += window;
+ // suppress warnings about gtk_debug_focus_in_callback being unused with
+ // this "if ( 0 )"
+ if ( 0 )
+ {
+ wxString tmp = name;
+ tmp += wxT(" FROM ");
+ tmp += window;
- wxChar *s = new wxChar[tmp.Length()+1];
+ wxChar *s = new wxChar[tmp.Length()+1];
- wxStrcpy( s, tmp );
+ wxStrcpy( s, tmp );
- gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
- GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
+ gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
+ GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
+ }
}
+#else
+#define DEBUG_MAIN_THREAD
#endif // Debug
//-----------------------------------------------------------------------------
int dw = 0;
int dh = 0;
- if (win->HasScrolling())
+ if (win->m_hasScrolling)
{
- GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
+ GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
-/*
- GtkWidget *hscrollbar = scroll_window->hscrollbar;
- GtkWidget *vscrollbar = scroll_window->vscrollbar;
+ GtkRequisition vscroll_req;
+ vscroll_req.width = 2;
+ vscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (scroll_window->vscrollbar, &vscroll_req );
- we use this instead: range.slider_width = 11 + 2*2pts edge
-*/
+ GtkRequisition hscroll_req;
+ hscroll_req.width = 2;
+ hscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+ (scroll_window->hscrollbar, &hscroll_req );
- if (scroll_window->vscrollbar_visible)
- {
- dw += 15; /* dw += vscrollbar->allocation.width; */
- dw += scroll_class->scrollbar_spacing;
- }
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
- if (scroll_window->hscrollbar_visible)
- {
- dh += 15; /* dh += hscrollbar->allocation.height; */
- dh += scroll_class->scrollbar_spacing;
- }
+ 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;
+ }
}
int dx = 0;
GTK_STATE_NORMAL,
GTK_SHADOW_OUT,
dx, dy,
- win->m_width-dw, win->m_height-dh );
+ widget->allocation.width-dw, widget->allocation.height-dh );
return;
}
GTK_STATE_NORMAL,
GTK_SHADOW_IN,
dx, dy,
- win->m_width-dw, win->m_height-dh );
+ widget->allocation.width-dw, widget->allocation.height-dh );
return;
}
gdk_gc_set_foreground( gc, &widget->style->black );
gdk_draw_rectangle( widget->window, gc, FALSE,
dx, dy,
- win->m_width-dw-1, win->m_height-dh-1 );
+ widget->allocation.width-dw-1, widget->allocation.height-dh-1 );
gdk_gc_unref( gc );
return;
}
static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
{
- if (!win->m_hasVMT)
- return;
+ DEBUG_MAIN_THREAD
+/*
+ if (win->GetName() == wxT("grid window"))
+ {
+ 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)
return;
-/*
- wxPrintf( "OnExpose from " );
- if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
- wxPrintf( win->GetClassInfo()->GetClassName() );
- wxPrintf( " %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 );
-*/
+ if (!win->m_hasVMT)
+ return;
wxEraseEvent eevent( win->GetId() );
eevent.SetEventObject( win );
static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget),
GdkRectangle *rect, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
-
- if (!win->m_hasVMT)
+
+ if ((rect->x == 0) && (rect->y == 0) && (rect->width <= 1) && (rect->height <= 1))
return;
+/*
+ if (win->GetName() == wxT("grid window"))
+ {
+ 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 );
+ }
+*/
+
win->GetUpdateRegion().Union( rect->x, rect->y,
rect->width, rect->height );
-/*
- wxPrintf( "OnDraw from " );
- if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
- printf( win->GetClassInfo()->GetClassName() );
- wxPrintf( " %d %d %d %d\n", (int)rect->x,
- (int)rect->y,
- (int)rect->width,
- (int)rect->height );
-*/
+ if (!win->m_hasVMT)
+ return;
wxEraseEvent eevent( win->GetId() );
eevent.SetEventObject( win );
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 (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 );
- 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" );
*/
+
int x = 0;
int y = 0;
GdkModifierType state;
(win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
{
wxNavigationKeyEvent new_event;
- new_event.SetEventObject( win );
+ 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->GetEventHandler()->ProcessEvent( new_event );
+ ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
}
/* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
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();
}
}
- wxEventType event_type = wxEVT_LEFT_DOWN;
+ wxEventType event_type = wxEVT_NULL;
if (gdk_event->button == 1)
{
}
}
+ 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_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;
+ 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.
static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
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.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;
+ 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.
static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
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;
+ 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.
static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
panel->SetLastFocus(win);
}
+#ifdef HAVE_XIM
+ if (win->m_ic)
+ gdk_im_begin(win->m_ic, win->m_wxwindow->window);
+#endif
+
wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
event.SetEventObject( win );
static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
printf( ".\n" );
*/
+#ifdef HAVE_XIM
+ if (win->m_ic)
+ gdk_im_end();
+#endif
+
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
event.SetEventObject( win );
static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
event.m_middleDown = (state & GDK_BUTTON2_MASK);
event.m_rightDown = (state & GDK_BUTTON3_MASK);
- event.m_x = (long)x;
- event.m_y = (long)y;
+ event.m_x = x;
+ event.m_y = y;
if (win->GetEventHandler()->ProcessEvent( event ))
{
static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
event.m_middleDown = (state & GDK_BUTTON2_MASK);
event.m_rightDown = (state & GDK_BUTTON3_MASK);
- event.m_x = (long)x;
- event.m_y = (long)y;
+ event.m_x = x;
+ event.m_y = y;
if (win->GetEventHandler()->ProcessEvent( event ))
{
static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
}
//-----------------------------------------------------------------------------
-// "changed" from m_vAdjust
+// "button_press_event" from scrollbar
//-----------------------------------------------------------------------------
-static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
+static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
+ GdkEventButton *gdk_event,
+ wxWindow *win)
{
- if (g_isIdle)
- wxapp_install_idle_handler();
+ DEBUG_MAIN_THREAD
- 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);
+ g_blockEventsOnScroll = TRUE;
+ win->m_isScrolling = (gdk_event->window == widget->slider);
- wxScrollWinEvent event( command, value, wxHORIZONTAL );
- event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
+ return FALSE;
}
//-----------------------------------------------------------------------------
-// "button_press_event" from scrollbar
+// "button_release_event" from scrollbar
//-----------------------------------------------------------------------------
-static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
- GdkEventButton *WXUNUSED(gdk_event),
- wxWindow *win )
+static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
+ GdkEventButton *WXUNUSED(gdk_event),
+ wxWindow *win)
{
- if (g_isIdle)
- wxapp_install_idle_handler();
+ 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;
- win->SetScrolling( TRUE );
+ g_blockEventsOnScroll = FALSE;
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// "button_release_event" from scrollbar
-//-----------------------------------------------------------------------------
+ if (win->m_isScrolling)
+ {
+ wxEventType command = wxEVT_SCROLL_THUMBRELEASE;
+ int value = -1;
+ int dir = -1;
-static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget),
- GdkEventButton *WXUNUSED(gdk_event),
- wxWindow *win )
-{
+ 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;
+ }
-// 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;
+ wxScrollWinEvent event( command, value, dir );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+ }
- win->SetScrolling( FALSE );
+ win->m_isScrolling = FALSE;
return FALSE;
}
// "realize" from m_widget
//-----------------------------------------------------------------------------
-/* we cannot set colours and fonts before the widget has
- been realized, so we do this directly after realization */
+/* 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(widget), wxWindow *win )
+gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
- if (win->m_delayedFont)
- win->SetFont( win->GetFont() );
-
if (win->m_delayedBackgroundColour)
win->SetBackgroundColour( win->GetBackgroundColour() );
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)
+ 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),
+ wxWindow * 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
return FALSE;
}
m_acceptsFocus = FALSE;
m_cursor = *wxSTANDARD_CURSOR;
+
+#ifdef HAVE_XIM
+ m_ic = (GdkIC*) NULL;
+ m_icattr = (GdkICAttr*) NULL;
+#endif
}
wxWindow::wxWindow()
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)
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)
{
- gtk_style_unref( m_widgetStyle );
+ // don't delete if it's a pixmap theme style
+ if (!m_widgetStyle->engine_data)
+ gtk_style_unref( m_widgetStyle );
+
m_widgetStyle = (GtkStyle*) NULL;
}
#endif
}
+ if (m_wxwindow && m_needParent)
+ {
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+ }
+ else
+ {
+ // For dialogs and frames, we are interested mainly in
+ // m_widget's focus.
+
+ gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+ }
+
GtkWidget *connect_widget = GetConnectWidget();
ConnectWidget( connect_widget );
- /* we cannot set colours, fonts and cursors before the widget has
+ /* 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 );
+ }
+
m_hasVMT = TRUE;
}
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), "focus_in_event",
- GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
-
- gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
- GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
-
gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
return wxWindowBase::Destroy();
}
+void wxWindow::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 wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
{
wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
bottom_border = 5;
}
- gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow),
- m_widget,
- m_x-border,
- m_y-border,
- m_width+2*border,
- m_height+border+bottom_border );
+ DoMoveWindow( m_x-border,
+ m_y-border,
+ m_width+2*border,
+ m_height+border+bottom_border );
+ }
+
+ if (m_hasScrolling)
+ {
+ GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
}
/*
int dw = 0;
int dh = 0;
-#if (GTK_MINOR_VERSION == 0)
- if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
- {
- if (HasScrolling())
- {
- GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-#if 0 // unused - if this is ok, just remove this line (VZ)
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
-#endif // 0
-
- GtkWidget *viewport = scroll_window->viewport;
- GtkStyleClass *viewport_class = viewport->style->klass;
-
- dw += 2 * viewport_class->xthickness;
- dh += 2 * viewport_class->ythickness;
- }
- }
-#else
if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
{
/* when using GTK 1.2 we set the shadow border size to 2 */
dw += 1 * 2;
dh += 1 * 2;
}
-#endif
- if (HasScrolling())
+ if (m_hasScrolling)
{
-/*
- GtkWidget *hscrollbar = scroll_window->hscrollbar;
- GtkWidget *vscrollbar = scroll_window->vscrollbar;
+ GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
- we use this instead: range.slider_width = 11 + 2*2pts edge
-*/
+ GtkRequisition vscroll_req;
+ vscroll_req.width = 2;
+ vscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (scroll_window->vscrollbar, &vscroll_req );
+
+ GtkRequisition hscroll_req;
+ hscroll_req.width = 2;
+ hscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+ (scroll_window->hscrollbar, &hscroll_req );
- GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
if (scroll_window->vscrollbar_visible)
{
- dw += 15; /* dw += vscrollbar->allocation.width; */
+ dw += vscroll_req.width;
dw += scroll_class->scrollbar_spacing;
}
if (scroll_window->hscrollbar_visible)
{
- dh += 15; /* dh += hscrollbar->allocation.height; */
+ dh += hscroll_req.height;
dh += scroll_class->scrollbar_spacing;
}
- }
+ }
SetSize( width+dw, height+dh );
}
int dw = 0;
int dh = 0;
-#if (GTK_MINOR_VERSION == 0)
- if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
- {
- if (HasScrolling())
- {
- GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-#if 0 // unused - if this is ok, just remove this line (VZ)
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
-#endif // 0
-
- GtkWidget *viewport = scroll_window->viewport;
- GtkStyleClass *viewport_class = viewport->style->klass;
-
- dw += 2 * viewport_class->xthickness;
- dh += 2 * viewport_class->ythickness;
- }
- }
-#else
if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
{
/* when using GTK 1.2 we set the shadow border size to 2 */
dw += 1 * 2;
dh += 1 * 2;
}
-#endif
- if (HasScrolling())
+
+ if (m_hasScrolling)
{
-/*
- GtkWidget *hscrollbar = scroll_window->hscrollbar;
- GtkWidget *vscrollbar = scroll_window->vscrollbar;
+ GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
- we use this instead: range.slider_width = 11 + 2*2pts edge
-*/
+ GtkRequisition vscroll_req;
+ vscroll_req.width = 2;
+ vscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (scroll_window->vscrollbar, &vscroll_req );
+
+ GtkRequisition hscroll_req;
+ hscroll_req.width = 2;
+ hscroll_req.height = 2;
+ (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+ (scroll_window->hscrollbar, &hscroll_req );
- GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
if (scroll_window->vscrollbar_visible)
{
- dw += 15; /* dw += vscrollbar->allocation.width; */
+ dw += vscroll_req.width;
dw += scroll_class->scrollbar_spacing;
}
if (scroll_window->hscrollbar_visible)
{
- dh += 15; /* dh += hscrollbar->allocation.height; */
+ dh += hscroll_req.height;
dh += scroll_class->scrollbar_spacing;
}
}
void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
{
- wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
+ if (!m_widget) return;
if (!m_widget->window) return;
if (eraseBackground && m_wxwindow && m_wxwindow->window)
if (m_wxwindow && m_wxwindow->window)
{
- gdk_window_clear( m_wxwindow->window );
+// gdk_window_clear( m_wxwindow->window );
}
}
// but it couldn't get applied as the
// widget hasn't been realized yet.
m_delayedBackgroundColour = TRUE;
-
- // pretend we have done something
- return TRUE;
}
- if (m_wxwindow)
+ if ((m_wxwindow) &&
+ (m_wxwindow->window) &&
+ (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE)))
{
/* wxMSW doesn't clear the window here. I don't do that either to
provide compatibility. call Clear() to do the job. */
gdk_window_set_background( window, m_backgroundColour.GetColor() );
}
- wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
- if (sysbg == m_backgroundColour)
- {
- m_backgroundColour = wxNullColour;
- ApplyWidgetStyle();
- m_backgroundColour = sysbg;
- }
- else
- {
- ApplyWidgetStyle();
- }
+ ApplyWidgetStyle();
return TRUE;
}
// but it couldn't get applied as the
// widget hasn't been realized yet.
m_delayedForegroundColour = TRUE;
-
- // pretend we have done something
- return TRUE;
}
- wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
- if ( sysbg == m_backgroundColour )
- {
- m_backgroundColour = wxNullColour;
- ApplyWidgetStyle();
- m_backgroundColour = sysbg;
- }
- else
- {
- ApplyWidgetStyle();
- }
+ ApplyWidgetStyle();
return TRUE;
}
GtkStyle *wxWindow::GetWidgetStyle()
{
- if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
+ if (m_widgetStyle)
+ {
+ GtkStyle *remake = gtk_style_copy( m_widgetStyle );
+ remake->klass = m_widgetStyle->klass;
+
+ gtk_style_unref( m_widgetStyle );
+ m_widgetStyle = remake;
+ }
+ else
+ {
+ GtkStyle *def = gtk_rc_get_style( m_widget );
+
+ if (!def)
+ def = gtk_widget_get_default_style();
- m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
+ m_widgetStyle = gtk_style_copy( def );
+ m_widgetStyle->klass = def->klass;
+ }
return m_widgetStyle;
}
void wxWindow::SetWidgetStyle()
{
+ if (m_widget->style->engine_data)
+ {
+ static bool s_warningPrinted = FALSE;
+ if (!s_warningPrinted)
+ {
+ printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
+ s_warningPrinted = TRUE;
+ }
+ m_widgetStyle = m_widget->style;
+ return;
+ }
+
GtkStyle *style = GetWidgetStyle();
- gdk_font_unref( style->font );
- style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
+ if (m_font != wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ))
+ {
+ gdk_font_unref( style->font );
+ style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
+ }
if (m_foregroundColour.Ok())
{
m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
- style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
- style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
- style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
+ if (m_foregroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT))
+ {
+ style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
+ style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
+ style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
+ }
}
if (m_backgroundColour.Ok())
{
m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
- style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
+ if (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE))
+ {
+ style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
+ style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
+ style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
+ style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
+ style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
+ style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
+ style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
+ style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
+ }
}
}
m_vAdjust->value = fpos;
}
-/*
- if (!m_isScrolling)
+ if (m_wxwindow->window)
{
-*/
- if (m_wxwindow->window)
+ if (orient == wxHORIZONTAL)
{
- if (orient == wxHORIZONTAL)
- gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
- else
- gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
+ gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
+ (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
+
+ gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
+
+ gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
+ (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
+ }
+ else
+ {
+ gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
+ (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
+
+ gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
+
+ gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
+ (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
}
-/*
}
-*/
}
int wxWindow::GetScrollThumb( int orient ) const
wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
+
+ if ((dx == 0) && (dy == 0)) return;
gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
-
-/*
- if (!m_scrollGC)
+
+/*
+ if (m_children.GetCount() > 0)
{
- m_scrollGC = gdk_gc_new( m_wxwindow->window );
- gdk_gc_set_exposures( m_scrollGC, TRUE );
- }
-
- wxNode *node = m_children.First();
- while (node)
- {
- wxWindow *child = (wxWindow*) node->Data();
- int sx = 0;
- int sy = 0;
- child->GetSize( &sx, &sy );
- child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
- node = node->Next();
- }
-
- int cw = 0;
- int ch = 0;
- GetClientSize( &cw, &ch );
- int w = cw - abs(dx);
- int h = ch - abs(dy);
-
- if ((h < 0) || (w < 0))
- {
- Refresh();
+ gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
}
else
{
- int s_x = 0;
- int s_y = 0;
- if (dx < 0) s_x = -dx;
- if (dy < 0) s_y = -dy;
- int d_x = 0;
- int d_y = 0;
- if (dx > 0) d_x = dx;
- if (dy > 0) d_y = dy;
-
- gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
- m_wxwindow->window, s_x, s_y, w, h );
+ GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
+
+ pizza->xoffset -= dx;
+ pizza->yoffset -= dy;
+
+ GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
+ gdk_gc_set_exposures( m_scrollGC, TRUE );
- wxRect rect;
- if (dx < 0) rect.x = cw+dx; else rect.x = 0;
- if (dy < 0) rect.y = ch+dy; else rect.y = 0;
- if (dy != 0) rect.width = cw; else rect.width = abs(dx);
- if (dx != 0) rect.height = ch; else rect.height = abs(dy);
+ int cw = 0;
+ int ch = 0;
+ GetClientSize( &cw, &ch );
+ int w = cw - abs(dx);
+ int h = ch - abs(dy);
- Refresh( TRUE, &rect );
+ if ((h < 0) || (w < 0))
+ {
+ Refresh();
+ }
+ else
+ {
+ int s_x = 0;
+ int s_y = 0;
+ if (dx < 0) s_x = -dx;
+ if (dy < 0) s_y = -dy;
+ int d_x = 0;
+ int d_y = 0;
+ if (dx > 0) d_x = dx;
+ if (dy > 0) d_y = dy;
+
+ gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
+ pizza->bin_window, s_x, s_y, w, h );
+
+ wxRect rect;
+ if (dx < 0) rect.x = cw+dx; else rect.x = 0;
+ if (dy < 0) rect.y = ch+dy; else rect.y = 0;
+ if (dy != 0) rect.width = cw; else rect.width = abs(dx);
+ if (dx != 0) rect.height = ch; else rect.height = abs(dy);
+
+ Refresh( TRUE, &rect );
+ }
+
+ gdk_gc_unref( m_scrollGC );
}
*/
}
-
-void wxWindow::SetScrolling(bool scroll)
-{
- m_isScrolling = g_blockEventsOnScroll = scroll;
-}