/////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "window.h"
#endif
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
#ifdef __VMS
#define XWarpPointer XWARPPOINTER
#endif
-#include "wx/defs.h"
#include "wx/window.h"
#include "wx/dcclient.h"
#include "wx/frame.h"
// send any activate events at all
static int g_sendActivateEvent = -1;
-/* hack: we need something to pass to gtk_menu_popup, so we store the time of
- the last click here */
-static guint32 gs_timeLastClick = 0;
+// hack: we need something to pass to gtk_menu_popup, so we store the time of
+// the last click here
+static guint32 gs_timeLastClick = 0;
extern bool g_mainThreadLocked;
if ( winFocus == win )
return (wxWindow *)win;
- for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+ for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
node;
node = node->GetNext() )
{
// "size_request" of m_widget
//-----------------------------------------------------------------------------
-static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
+// make it extern because wxStatitText needs to disconnect this one
+extern "C"
+void wxgtk_window_size_request_callback(GtkWidget *widget,
+ GtkRequisition *requisition,
+ wxWindow *win)
{
- int w,h;
+ int w, h;
win->GetSize( &w, &h );
- if (w < 2) w = 2;
- if (h < 2) h = 2;
+ if (w < 2)
+ w = 2;
+ if (h < 2)
+ h = 2;
requisition->height = h;
requisition->width = w;
(int)gdk_event->area.width,
(int)gdk_event->area.height );
}
+
+ gtk_paint_box
+ (
+ win->m_wxwindow->style,
+ pizza->bin_window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ (GdkRectangle*) NULL,
+ win->m_wxwindow,
+ (char *)"button", // const_cast
+ 20,20,24,24
+ );
#endif
win->GetUpdateRegion() = wxRegion( gdk_event->region );
if (g_isIdle)
wxapp_install_idle_handler();
- // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
- // there are no child windows.
- if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
- (win->GetChildren().GetCount() == 0))
+ // if there are any children we must refresh everything
+ //
+ // VZ: why?
+ if ( !win->HasFlag(wxFULL_REPAINT_ON_RESIZE) &&
+ win->GetChildren().IsEmpty() )
{
return;
}
#ifdef __WXGTK20__
static void gtk_wxwindow_commit_cb (GtkIMContext *context,
- const gchar *str,
- wxWindow *window)
+ const gchar *str,
+ wxWindow *window)
{
bool ret = FALSE;
event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
if (event.GetEventType()==wxEVT_MOUSEWHEEL) \
{ \
+ event.m_linesPerAction = 3; \
if (((GdkEventButton*)gdk_event)->button == 4) \
event.m_wheelRotation = 120; \
else if (((GdkEventButton*)gdk_event)->button == 5) \
yy += pizza->yoffset;
}
- wxWindowList::Node *node = win->GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
while (node)
{
wxWindowGTK *child = node->GetData();
GdkEvent *peek_event = gdk_event_peek();
if (peek_event)
{
- if (peek_event->type == GDK_2BUTTON_PRESS)
+ if ((peek_event->type == GDK_2BUTTON_PRESS) ||
+ (peek_event->type == GDK_3BUTTON_PRESS))
{
gdk_event_free( peek_event );
return TRUE;
wxEventType event_type = wxEVT_NULL;
+ // GdkDisplay is a GTK+ 2.1.0 thing
+#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 1, 0)
+ if ( gdk_event->type == GDK_2BUTTON_PRESS &&
+ gdk_event->button >= 1 && gdk_event->button <= 3 )
+ {
+ // Reset GDK internal timestamp variables in order to disable GDK
+ // triple click events. GDK will then next time believe no button has
+ // been clicked just before, and send a normal button click event.
+ GdkDisplay* display = gtk_widget_get_display (widget);
+ display->button_click_time[1] = 0;
+ display->button_click_time[0] = 0;
+ }
+#endif // GTK 2+
+
if (gdk_event->button == 1)
{
+ // note that GDK generates triple click events which are not supported
+ // by wxWindows but still have to be passed to the app as otherwise
+ // clicks would simply go missing
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;
+ // we shouldn't get triple clicks at all for GTK2 because we
+ // suppress them artificially using the code above but we still
+ // should map them to something for GTK1 and not just ignore them
+ // as this would lose clicks
+ case GDK_3BUTTON_PRESS: // we could also map this to DCLICK...
+ case GDK_BUTTON_PRESS:
+ event_type = wxEVT_LEFT_DOWN;
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ event_type = wxEVT_LEFT_DCLICK;
+ break;
+
+ default:
+ // just to silence gcc warnings
+ ;
}
}
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;
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_PRESS:
+ event_type = wxEVT_MIDDLE_DOWN;
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ event_type = wxEVT_MIDDLE_DCLICK;
+ break;
+
+ default:
+ ;
}
}
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;
- }
- }
- else if (gdk_event->button == 4)
- {
- switch (gdk_event->type)
- {
- case GDK_BUTTON_PRESS: event_type = wxEVT_MOUSEWHEEL; break;
- default: break;
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_PRESS:
+ event_type = wxEVT_RIGHT_DOWN;
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ event_type = wxEVT_RIGHT_DCLICK;
+ break;
+
+ default:
+ ;
}
}
- else if (gdk_event->button == 5)
+ else if (gdk_event->button == 4 || gdk_event->button == 5)
{
- switch (gdk_event->type)
+ if (gdk_event->type == GDK_BUTTON_PRESS )
{
- case GDK_BUTTON_PRESS: event_type = wxEVT_MOUSEWHEEL; break;
- default: break;
+ event_type = wxEVT_MOUSEWHEEL;
}
}
return FALSE;
}
+#ifdef __WXGTK20__
+//-----------------------------------------------------------------------------
+// "mouse_wheel_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_window_wheel_callback (GtkWidget * widget,
+ GdkEventScroll * gdk_event,
+ wxWindowGTK * win)
+{
+ DEBUG_MAIN_THREAD
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ wxEventType event_type = wxEVT_NULL;
+ if (gdk_event->direction == GDK_SCROLL_UP)
+ event_type = wxEVT_MOUSEWHEEL;
+ else if (gdk_event->direction == GDK_SCROLL_DOWN)
+ event_type = wxEVT_MOUSEWHEEL;
+ else
+ return FALSE;
+
+ wxMouseEvent event( event_type );
+ // Can't use InitMouse macro because scroll events don't have button
+ 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_linesPerAction = 3;
+ if (gdk_event->direction == GDK_SCROLL_UP)
+ event.m_wheelRotation = 120;
+ else
+ event.m_wheelRotation = -120;
+
+ wxPoint pt = win->GetClientAreaOrigin();
+ event.m_x = (wxCoord)gdk_event->x - pt.x;
+ event.m_y = (wxCoord)gdk_event->y - pt.y;
+
+ event.SetEventObject( win );
+ event.SetId( win->GetId() );
+ event.SetTimestamp( gdk_event->time );
+
+ if (win->GetEventHandler()->ProcessEvent( event ))
+ {
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "scroll_event" );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif
+
//-----------------------------------------------------------------------------
// "focus_in_event"
//-----------------------------------------------------------------------------
if (g_isIdle)
wxapp_install_idle_handler();
-
- if (win->m_delayedBackgroundColour)
+
+ if (win->m_delayedBackgroundColour && !win->GetThemeEnabled())
win->GtkSetBackgroundColour( win->GetBackgroundColour() );
- if (win->m_delayedForegroundColour)
+ if (win->m_delayedForegroundColour && !win->GetThemeEnabled())
win->GtkSetForegroundColour( win->GetForegroundColour() );
#ifdef __WXGTK20__
void wxWindowGTK::Init()
{
- // common init
- InitBase();
-
// GTK specific
m_widget = (GtkWidget *) NULL;
m_wxwindow = (GtkWidget *) NULL;
m_hAdjust = (GtkAdjustment*) NULL;
m_vAdjust = (GtkAdjustment*) NULL;
- m_oldHorizontalPos = 0.0;
+ m_oldHorizontalPos =
m_oldVerticalPos = 0.0;
+ m_oldClientWidth =
+ m_oldClientHeight = 0;
m_resizing = FALSE;
m_widgetStyle = (GtkStyle*) NULL;
DestroyChildren();
- if (m_parent)
- m_parent->RemoveChild( this );
-
#ifdef HAVE_XIM
if (m_ic)
gdk_ic_destroy (m_ic);
{
wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
- // This turns -1 into 30 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.
+ // Use either the given size, or the default if -1 is given.
+ // See wxWindowBase for these functions.
m_width = WidthDefault(size.x) ;
m_height = HeightDefault(size.y);
gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
- if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
+ if (!HasFlag(wxFULL_REPAINT_ON_RESIZE))
{
gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
}
#else
- // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ) );
+ // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
#endif
#ifdef __WXGTK20__
GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
}
- if (!GTK_IS_COMBO(m_widget))
+ 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
// 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 );
+ GTK_SIGNAL_FUNC(wxgtk_window_size_request_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 );
+#ifdef __WXGTK20__
+ gtk_signal_connect( GTK_OBJECT(widget), "scroll_event",
+ GTK_SIGNAL_FUNC(gtk_window_wheel_callback), (gpointer)this );
+#endif
+
gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
int currentX, currentY;
GetPosition(¤tX, ¤tY);
- if (x == -1)
+ if (x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
x = currentX;
- if (y == -1)
+ if (y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
y = currentY;
AdjustForParentClientOrigin(x, y, sizeFlags);
m_x = x + pizza->xoffset;
m_y = y + pizza->yoffset;
}
- if (width != -1) m_width = width;
- if (height != -1) m_height = height;
- if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
+ // calculate the best size if we should auto size the window
+ if ( (sizeFlags & wxSIZE_AUTO_WIDTH) ||
+ (sizeFlags & wxSIZE_AUTO_HEIGHT) )
{
- if (width == -1) m_width = 80;
+ const wxSize sizeBest = GetBestSize();
+ if ( sizeFlags & wxSIZE_AUTO_WIDTH )
+ width = sizeBest.x;
+ if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
+ height = sizeBest.y;
}
- if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
- {
- if (height == -1) m_height = 26;
- }
+ if (width != -1)
+ m_width = width;
+ if (height != -1)
+ m_height = height;
int minWidth = GetMinWidth(),
minHeight = GetMinHeight(),
}
}
- UpdateWindowUI();
+ if (wxUpdateUIEvent::CanUpdate(this))
+ UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
void wxWindowGTK::DoGetSize( int *width, int *height ) const
// Recurse, so that children have the opportunity to Do The Right Thing
// and reset colours that have been messed up by a parent's (really ancestor's)
// Enable call
- for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+ for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
node;
node = node->GetNext() )
{
PangoFontDescription *desc = m_font.GetNativeFontInfo()->description;
PangoLayout *layout = pango_layout_new(context);
pango_layout_set_font_description(layout, desc);
- pango_layout_set_text(layout, "H", 1);
+ pango_layout_set_text(layout, "g", 1);
PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
PangoRectangle rect;
#else
GdkFont *font = m_font.GetInternalFont( 1.0 );
- return gdk_string_width( font, "H" );
+ return gdk_string_width( font, "g" );
#endif
}
m_updateRegion.Clear();
}
-void wxWindowGTK::Clear()
+void wxWindowGTK::ClearBackground()
{
wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
{
- gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
+ wxString tmp( tip );
+ gtk_tooltips_set_tip( tips, GetConnectWidget(), wxGTK_CONV(tmp), (gchar*) NULL );
}
#endif // wxUSE_TOOLTIPS
{
#ifdef __WXGTK20__
pango_font_description_free( style->font_desc );
- pango_font_description_copy( m_font.GetNativeFontInfo()->description );
+ style->font_desc = pango_font_description_copy( m_font.GetNativeFontInfo()->description );
#else
gdk_font_unref( style->font );
style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
static void SetInvokingWindow( wxMenu *menu, wxWindowGTK *win )
{
menu->SetInvokingWindow( win );
- wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+ wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
while (node)
{
wxMenuItem *menuitem = node->GetData();
wxPopupMenuPositionCallback, // function to position it
NULL, // client data
0, // button used to activate it
+#ifdef __WXGTK20__
+ gtk_get_current_event_time()
+#else
gs_timeLastClick // the time of activation
+#endif
);
while (is_waiting)
{
- while (gtk_events_pending())
- gtk_main_iteration();
+ gtk_main_iteration();
}
return TRUE;
bool wxWindowGTK::SetFont( const wxFont &font )
{
- wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
-
- if (!wxWindowBase::SetFont(font))
+ if (!wxWindowBase::SetFont(font) || !m_widget)
{
return FALSE;
}