/////////////////////////////////////////////////////////////////////////////
-// Name: window.cpp
+// Name: gtk/window.cpp
// Purpose:
// Author: Robert Roebling
// Id: $Id$
#pragma implementation "window.h"
#endif
+#ifdef __VMS
+#define XWarpPointer XWARPPOINTER
+#endif
+
#include "wx/defs.h"
#include "wx/window.h"
#include "wx/dc.h"
#include "wx/tooltip.h"
#endif
+#if wxUSE_CARET
+ #include "wx/caret.h"
+#endif // wxUSE_CARET
+
#include "wx/menu.h"
#include "wx/statusbr.h"
#include "wx/intl.h"
#include <gtk/gtk.h>
#include <gdk/gdkprivate.h>
#include <gdk/gdkkeysyms.h>
-#include <wx/gtk/win_gtk.h>
-
#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkprivate.h>
+
+#include "wx/gtk/win_gtk.h"
+
//-----------------------------------------------------------------------------
// documentation on internals
//-----------------------------------------------------------------------------
// debug
//-----------------------------------------------------------------------------
+#ifndef __WXGTK20__
+#define DISABLE_STYLE_IF_BROKEN_THEME 1
+#endif
+
#ifdef __WXDEBUG__
#if wxUSE_THREADS
gint x,
gint y)
{
+#ifndef __WXGTK20__
GdkWindowPrivate *priv;
+#endif
if (!window)
- window = (GdkWindow*) &gdk_root_parent;
+ window = GDK_ROOT_PARENT();
+#ifdef __WXGTK20__
+ if (!GDK_WINDOW_DESTROYED(window))
+ {
+ XWarpPointer (GDK_WINDOW_XDISPLAY(window),
+ None, /* not source window -> move from anywhere */
+ GDK_WINDOW_XID(window), /* dest window */
+ 0, 0, 0, 0, /* not source window -> move from anywhere */
+ x, y );
+ }
+#else
priv = (GdkWindowPrivate*) window;
if (!priv->destroyed)
0, 0, 0, 0, /* not source window -> move from anywhere */
x, y );
}
+#endif
}
//-----------------------------------------------------------------------------
// local code (see below)
//-----------------------------------------------------------------------------
+// returns the child of win which currently has focus or NULL if not found
+// Note: can't be static, needed by textctrl.cpp.
+/* static */ wxWindow *FindFocusedChild(wxWindow *win)
+{
+ wxWindow *winFocus = wxWindow::FindFocus();
+ if ( !winFocus )
+ return (wxWindow *)NULL;
+
+ if ( winFocus == win )
+ return win;
+
+ for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindow *child = FindFocusedChild(node->GetData());
+ if ( child )
+ return child;
+ }
+
+ return (wxWindow *)NULL;
+}
+
static void draw_frame( GtkWidget *widget, wxWindow *win )
{
if (!win->m_hasVMT)
GtkRequisition vscroll_req;
vscroll_req.width = 2;
vscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (* 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(scroll_window->hscrollbar)->klass )->size_request )
+ (* 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(widget)->klass );
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
if (scroll_window->vscrollbar_visible)
{
// "expose_event" of m_widget
//-----------------------------------------------------------------------------
-static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
+gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
{
- if (gdk_event->count > 0) return;
+ if (gdk_event->count > 0) return FALSE;
+
draw_frame( widget, win );
+
+ return TRUE;
}
//-----------------------------------------------------------------------------
// key code mapping routines
//-----------------------------------------------------------------------------
-static long map_to_unmodified_wx_keysym( KeySym keysym )
+static long map_to_unmodified_wx_keysym( GdkEventKey *event )
{
+ KeySym keysym = event->keyval;
guint key_code = 0;
switch (keysym)
case GDK_F12: key_code = WXK_F12; break;
default:
{
- if (keysym <= 0xFF)
+ if (event->length == 1)
+ {
+ key_code = toupper( (unsigned char)*event->string );
+ }
+ else if ((keysym & 0xFF) == keysym)
{
guint upper = gdk_keyval_to_upper( (guint)keysym );
keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
return (key_code);
}
-static long map_to_wx_keysym( KeySym keysym )
+static long map_to_wx_keysym( GdkEventKey *event )
{
+ KeySym keysym = event->keyval;
guint key_code = 0;
switch (keysym)
case GDK_F12: key_code = WXK_F12; break;
default:
{
- if (keysym <= 0xFF)
+ if (event->length == 1)
+ {
+ key_code = (unsigned char)*event->string;
+ }
+ else if ((keysym & 0xFF) == keysym)
{
key_code = (guint)keysym;
}
return (key_code);
}
+//-----------------------------------------------------------------------------
+// "size_request" of m_widget
+//-----------------------------------------------------------------------------
+
+static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
+{
+ int w,h;
+ win->GetSize( &w, &h );
+ if (w < 2) w = 2;
+ if (h < 2) h = 2;
+
+ requisition->height = h;
+ requisition->width = w;
+}
+
//-----------------------------------------------------------------------------
// "expose_event" of m_wxwindow
//-----------------------------------------------------------------------------
-static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
+static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
{
DEBUG_MAIN_THREAD
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
/*
- if (win->GetName() == wxT("columntitles"))
+ if (win->GetName() == wxT("panel"))
{
wxPrintf( wxT("OnExpose from ") );
if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
}
*/
+ GtkPizza *pizza = GTK_PIZZA (widget);
+
+ if (win->GetThemeEnabled())
+ {
+ wxWindow *parent = win->GetParent();
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (!parent)
+ parent = win;
+
+ gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE, &gdk_event->area, parent->m_widget, "base", 0, 0, -1, -1);
+ }
+
win->GetUpdateRegion().Union( gdk_event->area.x,
gdk_event->area.y,
gdk_event->area.width,
gdk_event->area.height );
+ if (gdk_event->count == 0)
+ {
+ win->m_clipPaintRegion = TRUE;
+
+ wxEraseEvent eevent( win->GetId() );
+ eevent.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent(eevent);
- if (gdk_event->count > 0)
- return;
+ wxPaintEvent event( win->GetId() );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+
+ win->GetUpdateRegion().Clear();
+
+ win->m_clipPaintRegion = FALSE;
+ }
+
+ /* The following code will result in all window-less widgets
+ being redrawn if the wxWindows class is given a chance to
+ paint *anything* because it will then be allowed to paint
+ over the window-less widgets */
+
+ GList *children = pizza->children;
+ while (children)
+ {
+ GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+ children = children->next;
- if (!win->m_hasVMT)
- return;
+ GdkEventExpose child_event = *gdk_event;
- wxEraseEvent eevent( win->GetId() );
- eevent.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent(eevent);
+ if (GTK_WIDGET_NO_WINDOW (child->widget) &&
+ GTK_WIDGET_DRAWABLE (child->widget) /* &&
+ gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
+ {
+ child_event.area.x = child->widget->allocation.x;
+ child_event.area.y = child->widget->allocation.y;
+ child_event.area.width = child->widget->allocation.width;
+ child_event.area.height = child->widget->allocation.height;
+ gtk_widget_event (child->widget, (GdkEvent*) &child_event);
+ }
+ }
+
+ return TRUE;
+}
- wxPaintEvent event( win->GetId() );
- event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
+//-----------------------------------------------------------------------------
+// "event" of m_wxwindow
+//-----------------------------------------------------------------------------
- win->GetUpdateRegion().Clear();
+/* GTK thinks it is clever and filters out a certain amount of "unneeded"
+ expose events. We need them, of course, so we override the main event
+ procedure in GtkWidget by giving our own handler for all system events.
+ There, we look for expose events ourselves whereas all other events are
+ handled normally. */
+
+gint gtk_window_event_event_callback( GtkWidget *widget, GdkEventExpose *event, wxWindow *win )
+{
+ if (event->type == GDK_EXPOSE)
+ {
+ gint ret = gtk_window_expose_callback( widget, event, win );
+ return ret;
+ }
+
+ return FALSE;
}
//-----------------------------------------------------------------------------
// "draw" of m_wxwindow
//-----------------------------------------------------------------------------
-static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget),
- GdkRectangle *rect, wxWindow *win )
+/* This callback is a complete replacement of the gtk_pizza_draw() function,
+ which disabled. */
+
+static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
{
DEBUG_MAIN_THREAD
if (g_isIdle)
wxapp_install_idle_handler();
-
- if ((rect->x == 0) && (rect->y == 0) && (rect->width <= 1) && (rect->height <= 1))
+
+ if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
+ (win->GetChildren().GetCount() == 0))
+ {
return;
+ }
/*
- if (win->GetName() == wxT("columntitles"))
+ if (win->GetName() == wxT("panel"))
{
wxPrintf( wxT("OnDraw from ") );
if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
(int)rect->height );
}
*/
-
- win->GetUpdateRegion().Union( rect->x, rect->y,
- rect->width, rect->height );
+
+ GtkPizza *pizza = GTK_PIZZA (widget);
- if (!win->m_hasVMT)
- return;
+ if (win->GetThemeEnabled())
+ {
+ wxWindow *parent = win->GetParent();
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (!parent)
+ parent = win;
+
+ gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE, rect, parent->m_widget, "base", 0, 0, -1, -1);
+ }
+
+
+ if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
+ (pizza->clear_on_draw))
+ {
+ gdk_window_clear_area( pizza->bin_window,
+ rect->x, rect->y, rect->width, rect->height);
+ }
+
+ win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
+ win->m_clipPaintRegion = TRUE;
+
wxEraseEvent eevent( win->GetId() );
eevent.SetEventObject( win );
win->GetEventHandler()->ProcessEvent(eevent);
win->GetEventHandler()->ProcessEvent( event );
win->GetUpdateRegion().Clear();
+
+ win->m_clipPaintRegion = FALSE;
+
+
+ GList *children = pizza->children;
+ while (children)
+ {
+ GtkPizzaChild *child = (GtkPizzaChild*) children->data;
+ children = children->next;
+
+ GdkRectangle child_area;
+ if (gtk_widget_intersect (child->widget, rect, &child_area))
+ {
+ gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
+ }
+ }
}
//-----------------------------------------------------------------------------
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
+
/*
wxString tmp;
tmp += (char)gdk_event->keyval;
bool ret = FALSE;
- long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+ long key_code = map_to_unmodified_wx_keysym( gdk_event );
/* sending unknown key events doesn't really make sense */
if (key_code == 0) return FALSE;
ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
break;
}
- if (ancestor->m_isFrame)
+ if (ancestor->IsTopLevel())
break;
ancestor = ancestor->GetParent();
}
/* wxMSW doesn't send char events with Alt pressed */
/* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
will only be sent if it is not in an accelerator table. */
- key_code = map_to_wx_keysym( gdk_event->keyval );
+ key_code = map_to_wx_keysym( gdk_event );
if ( (!ret) &&
(key_code != 0))
/* win is a control: tab can be propagated up */
if ( (!ret) &&
((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
+// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
+// have this style, yet choose not to process this particular TAB in which
+// case TAB must still work as a navigational character
+#if 0
(!win->HasFlag(wxTE_PROCESS_TAB)) &&
+#endif // 0
(win->GetParent()) &&
(win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
{
printf( "\n" );
*/
- long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+ long key_code = map_to_unmodified_wx_keysym( gdk_event );
/* sending unknown key events doesn't really make sense */
if (key_code == 0) return FALSE;
// 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() )
+
+ if ((event.GetEventType() == wxEVT_LEFT_DOWN) ||
+ (event.GetEventType() == wxEVT_LEFT_DCLICK) ||
+ (event.GetEventType() == wxEVT_LEFT_UP))
{
- case wxEVT_LEFT_DOWN:
- case wxEVT_LEFT_DCLICK:
- case wxEVT_LEFT_UP:
- event.m_leftDown = !event.m_leftDown;
- break;
+ event.m_leftDown = !event.m_leftDown;
+ return;
+ }
- case wxEVT_MIDDLE_DOWN:
- case wxEVT_MIDDLE_DCLICK:
- case wxEVT_MIDDLE_UP:
- event.m_middleDown = !event.m_middleDown;
- break;
+ if ((event.GetEventType() == wxEVT_MIDDLE_DOWN) ||
+ (event.GetEventType() == wxEVT_MIDDLE_DCLICK) ||
+ (event.GetEventType() == wxEVT_MIDDLE_UP))
+ {
+ event.m_middleDown = !event.m_middleDown;
+ return;
+ }
- case wxEVT_RIGHT_DOWN:
- case wxEVT_RIGHT_DCLICK:
- case wxEVT_RIGHT_UP:
- event.m_rightDown = !event.m_rightDown;
- break;
+ if ((event.GetEventType() == wxEVT_RIGHT_DOWN) ||
+ (event.GetEventType() == wxEVT_RIGHT_DCLICK) ||
+ (event.GetEventType() == wxEVT_RIGHT_UP))
+ {
+ event.m_rightDown = !event.m_rightDown;
+ return;
}
}
gdk_im_begin(win->m_ic, win->m_wxwindow->window);
#endif
+#ifdef wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = win->GetCaret();
+ if ( caret )
+ {
+ caret->OnSetFocus();
+ }
+#endif // wxUSE_CARET
+
+ if (win->IsTopLevel())
+ {
+ wxActivateEvent event( wxEVT_ACTIVATE, TRUE, win->GetId() );
+ event.SetEventObject( win );
+
+ // ignore return value
+ win->GetEventHandler()->ProcessEvent( event );
+ }
+
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;
+ gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
+ return TRUE;
}
+
return FALSE;
}
// g_sendActivateEvent to -1
g_sendActivateEvent = 0;
+ wxWindow *winFocus = FindFocusedChild(win);
+ if ( winFocus )
+ win = winFocus;
+
g_focusWindow = (wxWindow *)NULL;
/*
gdk_im_end();
#endif
+#ifdef wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = win->GetCaret();
+ if ( caret )
+ {
+ caret->OnKillFocus();
+ }
+#endif // wxUSE_CARET
+
+ if (win->IsTopLevel())
+ {
+ wxActivateEvent event( wxEVT_ACTIVATE, FALSE, win->GetId() );
+ event.SetEventObject( win );
+
+ // ignore return value
+ win->GetEventHandler()->ProcessEvent( event );
+ }
+
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
event.SetEventObject( win );
if (g_isIdle)
wxapp_install_idle_handler();
+
g_blockEventsOnScroll = TRUE;
win->m_isScrolling = (gdk_event->window == widget->slider);
if (win->m_isScrolling)
{
- wxEventType command = wxEVT_SCROLL_THUMBRELEASE;
+ wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
int value = -1;
int dir = -1;
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);
+ 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);
+ 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 ())
+ gtk_widget_get_default_colormap ())
{
- attrmask |= GDK_IC_PREEDIT_COLORMAP;
- attr->preedit_colormap = colormap;
+ attrmask |= GDK_IC_PREEDIT_COLORMAP;
+ attr->preedit_colormap = colormap;
}
attrmask |= GDK_IC_PREEDIT_FOREGROUND;
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;
- }
+ 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);
+ 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;
+ 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;
+ break;
}
win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
if (win->m_ic == NULL)
- g_warning ("Can't create input context.");
+ 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);
- }
+ {
+ 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_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;
}
m_insertCallback = wxInsertChildInWindow;
-
+
m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
-#ifdef __WXDEBUG__
- debug_focus_in( m_widget, wxT("wxWindow::m_widget"), name );
-#endif
-
GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
-#ifdef __WXDEBUG__
- debug_focus_in( scrolledWindow->hscrollbar, wxT("wxWindow::hsrcollbar"), name );
- debug_focus_in( scrolledWindow->vscrollbar, wxT("wxWindow::vsrcollbar"), name );
-#endif
-
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+ 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_wxwindow = gtk_pizza_new();
-#ifdef __WXDEBUG__
- debug_focus_in( m_wxwindow, wxT("wxWindow::m_wxwindow"), name );
-#endif
-
gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
#if (GTK_MINOR_VERSION > 0)
wxWindow::~wxWindow()
{
+ if (g_focusWindow == this)
+ g_focusWindow = NULL;
+
m_isBeingDeleted = TRUE;
m_hasVMT = FALSE;
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_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 );
+ }
}
#if (GTK_MINOR_VERSION > 0)
else
{
// For dialogs and frames, we are interested mainly in
- // m_widget's focus.
+ // m_widget's focus.
gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
if (m_wxwindow)
{
- /* Catch native resize events. */
+ // 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. */
+ // Initialize XIM support
gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
- /* And resize XIM window. */
+ // 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;
}
if (m_resizing) return; /* I don't like recursions */
m_resizing = TRUE;
-
+
if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
{
/* don't set the size for children of wxNotebook, just take the values. */
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 );
}
// do it only once
g_sendActivateEvent = -1;
- wxActivateEvent event(wxEVT_ACTIVATE, activate, GetId());
+ wxActivateEvent event(wxEVT_ACTIVATE_APP, activate, GetId());
event.SetEventObject(this);
(void)GetEventHandler()->ProcessEvent(event);
GtkRequisition vscroll_req;
vscroll_req.width = 2;
vscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (* 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(scroll_window->hscrollbar)->klass )->size_request )
+ (* 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(m_widget)->klass );
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
if (scroll_window->vscrollbar_visible)
{
GtkRequisition vscroll_req;
vscroll_req.width = 2;
vscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (* 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(scroll_window->hscrollbar)->klass )->size_request )
+ (* 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(m_widget)->klass );
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
if (scroll_window->vscrollbar_visible)
{
return TRUE;
}
+static void wxWindowNotifyEnable(wxWindow* win, bool enable)
+{
+ win->OnParentEnable(enable);
+
+ // 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();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindow *child = node->GetData();
+ if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame)))
+ wxWindowNotifyEnable(child, enable);
+ }
+}
+
bool wxWindow::Enable( bool enable )
{
wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
if ( m_wxwindow )
gtk_widget_set_sensitive( m_wxwindow, enable );
+ wxWindowNotifyEnable(this, enable);
+
return TRUE;
}
{
wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
- return wxWindowBase::SetCursor( cursor );
+ if (cursor == m_cursor)
+ return FALSE;
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (cursor == wxNullCursor)
+ return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
+ else
+ return wxWindowBase::SetCursor( cursor );
}
void wxWindow::WarpPointer( int x, int y )
{
if (m_wxwindow)
{
+
+/*
GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
gboolean old_clear = pizza->clear_on_draw;
gtk_pizza_set_clear( pizza, FALSE );
-
gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
-
gtk_pizza_set_clear( pizza, old_clear );
+*/
+ GdkEventExpose gdk_event;
+ gdk_event.type = GDK_EXPOSE;
+ gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
+ gdk_event.count = 0;
+ gdk_event.area.x = 0;
+ gdk_event.area.y = 0;
+ gdk_event.area.width = m_wxwindow->allocation.width;
+ gdk_event.area.height = m_wxwindow->allocation.height;
+ gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
+
}
else
+ {
gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
+ }
}
else
{
- GdkRectangle gdk_rect;
- gdk_rect.x = rect->x;
- gdk_rect.y = rect->y;
- gdk_rect.width = rect->width;
- gdk_rect.height = rect->height;
if (m_wxwindow)
{
+/*
GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
gboolean old_clear = pizza->clear_on_draw;
gtk_pizza_set_clear( pizza, FALSE );
+ GdkRectangle gdk_rect;
+ gdk_rect.x = rect->x;
+ gdk_rect.y = rect->y;
+ gdk_rect.width = rect->width;
+ gdk_rect.height = rect->height;
gtk_widget_draw( m_wxwindow, &gdk_rect );
+ gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
gtk_pizza_set_clear( pizza, old_clear );
+*/
+ GdkEventExpose gdk_event;
+ gdk_event.type = GDK_EXPOSE;
+ gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
+ gdk_event.count = 0;
+ gdk_event.area.x = rect->x;
+ gdk_event.area.y = rect->y;
+ gdk_event.area.width = rect->width;
+ gdk_event.area.height = rect->height;
+ gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
}
else
+ {
+ GdkRectangle gdk_rect;
+ gdk_rect.x = rect->x;
+ gdk_rect.y = rect->y;
+ gdk_rect.width = rect->width;
+ gdk_rect.height = rect->height;
gtk_widget_draw( m_widget, &gdk_rect );
+ }
}
}
if (m_widgetStyle)
{
GtkStyle *remake = gtk_style_copy( m_widgetStyle );
+#ifdef __WXGTK20__
+ /* FIXME: is this necessary? */
+ _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
+#else
remake->klass = m_widgetStyle->klass;
+#endif
gtk_style_unref( m_widgetStyle );
m_widgetStyle = remake;
def = gtk_widget_get_default_style();
m_widgetStyle = gtk_style_copy( def );
+#ifdef __WXGTK20__
+ /* FIXME: is this necessary? */
+ _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass);
+#else
m_widgetStyle->klass = def->klass;
+#endif
}
return m_widgetStyle;
void wxWindow::SetWidgetStyle()
{
+#if DISABLE_STYLE_IF_BROKEN_THEM
if (m_widget->style->engine_data)
{
static bool s_warningPrinted = FALSE;
m_widgetStyle = m_widget->style;
return;
}
+#endif
GtkStyle *style = GetWidgetStyle();
style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
}
+ else
+ {
+ // Try to restore the gtk default style. This is still a little
+ // oversimplified for what is probably really needed here for controls
+ // other than buttons, but is better than not being able to (re)set a
+ // control's foreground colour to *wxBLACK -- RL
+ GtkStyle *def = gtk_rc_get_style( m_widget );
+
+ if (!def)
+ def = gtk_widget_get_default_style();
+
+ style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
+ style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
+ style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
+ }
}
if (m_backgroundColour.Ok())
style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
- }
+ }
+ else
+ {
+ // Try to restore the gtk default style. This is still a little
+ // oversimplified for what is probably really needed here for controls
+ // other than buttons, but is better than not being able to (re)set a
+ // control's background colour to default grey and means resetting a
+ // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
+ // behavior -- RL
+ GtkStyle *def = gtk_rc_get_style( m_widget );
+
+ if (!def)
+ def = gtk_widget_get_default_style();
+
+ style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
+ style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
+ style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
+ style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
+ style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
+ style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
+ style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
+ style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
+ }
}
}
if (!window) return;
+ wxCursor* cursor = & m_cursor;
+ if (!cursor->Ok())
+ cursor = wxSTANDARD_CURSOR;
+
gdk_pointer_grab( window, FALSE,
(GdkEventMask)
(GDK_BUTTON_PRESS_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_POINTER_MOTION_MASK),
(GdkWindow *) NULL,
- m_cursor.GetCursor(),
+ cursor->GetCursor(),
(guint32)GDK_CURRENT_TIME );
g_captureWindow = this;
}
if ((dx == 0) && (dy == 0)) return;
+ m_clipPaintRegion = TRUE;
gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
+ m_clipPaintRegion = FALSE;
/*
if (m_children.GetCount() > 0)
}
*/
}
+
+// Find the wxWindow at the current mouse position, also returning the mouse
+// position.
+wxWindow* wxFindWindowAtPointer(wxPoint& pt)
+{
+ pt = wxGetMousePosition();
+ wxWindow* found = wxFindWindowAtPoint(pt);
+ return found;
+}
+
+// Get the current mouse position.
+wxPoint wxGetMousePosition()
+{
+ /* This crashes when used within wxHelpContext,
+ so we have to use the X-specific implementation below.
+ gint x, y;
+ GdkModifierType *mask;
+ (void) gdk_window_get_pointer(NULL, &x, &y, mask);
+
+ return wxPoint(x, y);
+ */
+
+ int x, y;
+ GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
+ if (!windowAtPtr)
+ return wxPoint(-999, -999);
+
+ Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
+ Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
+ Window rootReturn, childReturn;
+ int rootX, rootY, winX, winY;
+ unsigned int maskReturn;
+
+ XQueryPointer (display,
+ rootWindow,
+ &rootReturn,
+ &childReturn,
+ &rootX, &rootY, &winX, &winY, &maskReturn);
+ return wxPoint(rootX, rootY);
+
+}
+