/////////////////////////////////////////////////////////////////////////////
-// 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 "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 <gdk/gdkx.h>
-#include "gdk/gdkx.h"
+#include <gtk/gtk.h>
+#include <gtk/gtkprivate.h>
+
+#include "wx/gtk/win_gtk.h"
//-----------------------------------------------------------------------------
// documentation on internals
the last click here */
static guint32 gs_timeLastClick = 0;
+extern bool g_mainThreadLocked;
+
//-----------------------------------------------------------------------------
// debug
//-----------------------------------------------------------------------------
+#ifndef __WXGTK20__
+#define DISABLE_STYLE_IF_BROKEN_THEME 1
+#endif
+
#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
//-----------------------------------------------------------------------------
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)
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_GET_CLASS(scroll_window->vscrollbar) )->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_GET_CLASS(scroll_window->hscrollbar) )->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_GET_CLASS(widget) );
- 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;
}
// "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;
}
//-----------------------------------------------------------------------------
case GDK_F12: key_code = WXK_F12; break;
default:
{
- if (keysym <= 0xFF)
+ if ((keysym & 0xF000) == 0)
{
guint upper = gdk_keyval_to_upper( (guint)keysym );
keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
case GDK_F12: key_code = WXK_F12; break;
default:
{
- if (keysym <= 0xFF)
+ if ((keysym & 0xF000) == 0)
{
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 )
{
- if (!win->m_hasVMT)
- return;
+ DEBUG_MAIN_THREAD
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+/*
+ if (win->GetName() == wxT("panel"))
+ {
+ 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 );
+ }
+*/
+
+ 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)
- return;
+ if (gdk_event->count == 0)
+ {
+ win->m_clipPaintRegion = TRUE;
+
+ wxEraseEvent eevent( win->GetId() );
+ eevent.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent(eevent);
+
+ 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;
-/*
- 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 );
-*/
+ 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 (!win->m_hasVMT)
+ if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
+ (win->GetChildren().GetCount() == 0))
+ {
return;
-
- 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->GetName() == wxT("panel"))
+ {
+ 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 );
+ }
*/
+
+ 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, 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*/ );
+ }
+ }
}
//-----------------------------------------------------------------------------
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 (!win->m_hasVMT) return FALSE;
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;
ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
break;
}
- if (ancestor->m_isFrame)
+ if (ancestor->IsTopLevel())
break;
ancestor = ancestor->GetParent();
}
/* 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)) )
{
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
+
+ if ((event.GetEventType() == wxEVT_LEFT_DOWN) ||
+ (event.GetEventType() == wxEVT_LEFT_DCLICK) ||
+ (event.GetEventType() == wxEVT_LEFT_UP))
+ {
+ event.m_leftDown = !event.m_leftDown;
+ return;
+ }
+
+ if ((event.GetEventType() == wxEVT_MIDDLE_DOWN) ||
+ (event.GetEventType() == wxEVT_MIDDLE_DCLICK) ||
+ (event.GetEventType() == wxEVT_MIDDLE_UP))
+ {
+ event.m_middleDown = !event.m_middleDown;
+ return;
+ }
+
+ if ((event.GetEventType() == wxEVT_RIGHT_DOWN) ||
+ (event.GetEventType() == wxEVT_RIGHT_DCLICK) ||
+ (event.GetEventType() == wxEVT_RIGHT_UP))
+ {
+ event.m_rightDown = !event.m_rightDown;
+ return;
+ }
+}
+
//-----------------------------------------------------------------------------
// "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
+
+#ifdef wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = win->GetCaret();
+ if ( caret )
+ {
+ caret->OnSetFocus();
+ }
+#endif // wxUSE_CARET
+
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();
// g_sendActivateEvent to -1
g_sendActivateEvent = 0;
+ wxWindow *winFocus = FindFocusedChild(win);
+ if ( winFocus )
+ win = winFocus;
+
g_focusWindow = (wxWindow *)NULL;
/*
printf( ".\n" );
*/
+#ifdef HAVE_XIM
+ if (win->m_ic)
+ 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
+
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();
-
- 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
-//-----------------------------------------------------------------------------
+ DEBUG_MAIN_THREAD
-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_SCROLLWIN_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(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 *widget, wxWindow *win )
+gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
+ wxWindow * WXUNUSED_UNLESS_XIM(win) )
{
if (g_isIdle)
wxapp_install_idle_handler();
-#ifdef USE_XIM
+#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;
- GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
+ unsigned attrmask = GDK_IC_ALL_REQ;
GdkIMStyle style;
- GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE |
+ 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_STATUS_NOTHING);
if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
- 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 ())
{
- attrmask |= GDK_IC_PREEDIT_COLORMAP;
- attr->preedit_colormap = 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_fontset = widget->style->font;
break;
- }
-
- win->m_ic = gdk_ic_new (attr, attrmask);
-
+ }
+
+ 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 |= gdk_ic_get_events (win->m_ic);
+ 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)
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)
wxWindow::~wxWindow()
{
+ if (g_focusWindow == this)
+ g_focusWindow = NULL;
+
m_isBeingDeleted = TRUE;
m_hasVMT = FALSE;
if (m_widgetStyle)
{
- gtk_style_unref( 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)
{
// 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 );
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 );
-
- /* Initialize XIM support. */
+
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;
}
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") );
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. */
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)
+ {
+ /* 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 );
}
/*
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_GET_CLASS(scroll_window->vscrollbar) )->size_request )
+ (scroll_window->vscrollbar, &vscroll_req );
- GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+ 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 += 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_GET_CLASS(scroll_window->vscrollbar) )->size_request )
+ (scroll_window->vscrollbar, &vscroll_req );
- GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+ 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 += 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::SetFocus()
{
wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
+
if (m_wxwindow)
{
if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
{
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 )
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)
{
+
+/*
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_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 );
+#ifdef __WXGTK20__
+ /* FIXME: is this necessary? */
+ _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
+#else
+ remake->klass = m_widgetStyle->klass;
+#endif
- m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
+ 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( 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;
+ if (!s_warningPrinted)
+ {
+ printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
+ s_warningPrinted = TRUE;
+ }
+ m_widgetStyle = m_widget->style;
+ return;
+ }
+#endif
+
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();
+ }
+ 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())
{
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();
+ }
+ 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;
}
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;
+ m_clipPaintRegion = TRUE;
gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
-
-/*
- if (!m_scrollGC)
- {
- 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))
+ m_clipPaintRegion = FALSE;
+
+/*
+ if (m_children.GetCount() > 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)
+// Find the wxWindow at the current mouse position, also returning the mouse
+// position.
+wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
- m_isScrolling = g_blockEventsOnScroll = scroll;
+ 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);
+
+}
+