/////////////////////////////////////////////////////////////////////////////
-// 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 <gtk/gtk.h>
+#include <gtk/gtkprivate.h>
-#include "gdk/gdkx.h"
+#include "wx/gtk/win_gtk.h"
//-----------------------------------------------------------------------------
// documentation on internals
If the m_wxwindow field is set, then all input to this widget is inter-
cepted and sent to the wxWindows class. If not, all input to the widget
that gets pointed to by m_widget gets intercepted and sent to the class.
-
+
II)
-
+
The design of scrolling in wxWindows is markedly different from that offered
by the GTK itself and therefore we cannot simply take it as it is. In GTK,
clicking on a scrollbar belonging to scrolled window will inevitably move
memorizes how much it has been scrolled but that wxWindows forgets this
so that the two coordinates systems have to be kept in synch. This is done
in various places using the pizza->xoffset and pizza->yoffset values.
-
- III)
-
+
+ III)
+
Singularily the most broken code in GTK is the code that is supposes to
inform subwindows (child windows) about new positions. Very often, duplicate
events are sent without changes in size or position, equally often no
GTK).
IV)
-
+
If someone at some point of time feels the immense desire to have a look at,
change or attempt to optimse the Refresh() logic, this person will need an
intimate understanding of what a "draw" and what an "expose" events are and
what there are used for, in particular when used in connection with GTK's
own windowless widgets. Beware.
-
+
V)
-
+
Cursors, too, have been a constant source of pleasure. The main difficulty
is that a GdkWindow inherits a cursor if the programmer sets a new cursor
for the parent. To prevent this from doing too much harm, I use idle time
and ending with the youngest generation (speaking of parent and child windows).
Also don't forget that cursors (like much else) are connected to GdkWindows,
not GtkWidgets and that the "window" field of a GtkWidget might very well
- point to the GdkWindow of the parent widget (-> "window less widget") and
+ point to the GdkWindow of the parent widget (-> "window less widget") and
that the two obviously have very different meanings.
*/
extern bool g_blockEventsOnScroll;
extern wxCursor g_globalCursor;
static wxWindow *g_captureWindow = (wxWindow*) NULL;
- wxWindow *g_focusWindow = (wxWindow*) NULL;
+
+/* extern */ wxWindow *g_focusWindow = (wxWindow*) NULL;
+
+// if we detect that the app has got/lost the focus, we set this variable to
+// either TRUE or FALSE and an activate event will be sent during the next
+// OnIdle() call and it is reset to -1: this value means that we shouldn't
+// 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;
+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;
}
-
+
if (win->HasFlag(wxSIMPLE_BORDER))
{
GdkGC *gc;
- gc = gdk_gc_new( widget->window );
+ gc = gdk_gc_new( widget->window );
gdk_gc_set_foreground( gc, &widget->style->black );
- gdk_draw_rectangle( widget->window, gc, FALSE,
+ 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;
}
//-----------------------------------------------------------------------------
// 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( keysym );
+ guint upper = gdk_keyval_to_upper( (guint)keysym );
keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
- key_code = keysym;
+ key_code = (guint)keysym;
}
}
}
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 = 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 )
{
- 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);
-
- wxPaintEvent event( win->GetId() );
- event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
+ 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;
+}
- win->GetUpdateRegion().Clear();
+//-----------------------------------------------------------------------------
+// "event" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+/* 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
//-----------------------------------------------------------------------------
+/* 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);
-
+
wxPaintEvent event( win->GetId() );
event.SetEventObject( win );
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;
if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
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)
- break;
+ 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)) &&
- (win->GetParent()) &&
- (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
+#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) */
*/
#endif
-/*
- Damn, I forgot why this didn't work, but it didn't work.
-
- // win is a panel: up can be propagated to the panel
- if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
- (gdk_event->keyval == GDK_Up))
- {
- win->m_parent->SetFocus();
- ret = TRUE;
- }
-
- // win is a panel: left/right can be propagated to the panel
- if ((!ret) && (win->m_wxwindow) &&
- ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
- (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
- {
- wxNavigationKeyEvent new_event;
- new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
- new_event.SetCurrentFocus( win );
- ret = win->GetEventHandler()->ProcessEvent( new_event );
- }
-*/
-
if (ret)
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
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;
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.
if (!g_captureWindow)
{
- int x = event.m_x;
- int y = event.m_y;
+ wxCoord x = event.m_x;
+ wxCoord y = event.m_y;
if (win->m_wxwindow)
{
GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
- x += pizza->xoffset;
- y += pizza->yoffset;
+ x += pizza->xoffset;
+ y += pizza->yoffset;
}
wxNode *node = win->GetChildren().First();
while (node)
{
wxWindow *child = (wxWindow*)node->Data();
-
+
node = node->Next();
- if (!child->IsShown())
- continue;
+ if (!child->IsShown())
+ continue;
if (child->m_isStaticBox)
{
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.
if (!g_captureWindow)
{
- int x = event.m_x;
- int y = event.m_y;
+ wxCoord x = event.m_x;
+ wxCoord y = event.m_y;
if (win->m_wxwindow)
{
GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
- x += pizza->xoffset;
- y += pizza->yoffset;
+ x += pizza->xoffset;
+ y += pizza->yoffset;
}
wxNode *node = win->GetChildren().First();
wxWindow *child = (wxWindow*)node->Data();
node = node->Next();
- if (!child->IsShown())
- continue;
+ if (!child->IsShown())
+ continue;
if (child->m_isStaticBox)
{
static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *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;
if (g_blockEventsOnScroll) return FALSE;
-
+
if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
if (gdk_event->is_hint)
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.
if (!g_captureWindow)
{
- int x = event.m_x;
- int y = event.m_y;
+ wxCoord x = event.m_x;
+ wxCoord y = event.m_y;
if (win->m_wxwindow)
{
GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
- x += pizza->xoffset;
- y += pizza->yoffset;
+ x += pizza->xoffset;
+ y += pizza->yoffset;
}
wxNode *node = win->GetChildren().First();
wxWindow *child = (wxWindow*)node->Data();
node = node->Next();
- if (!child->IsShown())
- continue;
+ if (!child->IsShown())
+ continue;
if (child->m_isStaticBox)
{
static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
+ switch ( g_sendActivateEvent )
+ {
+ case -1:
+ // we've got focus from outside, synthtize wxActivateEvent
+ g_sendActivateEvent = 1;
+ break;
+
+ case 0:
+ // another our window just lost focus, it was already ours before
+ // - don't send any wxActivateEvent
+ g_sendActivateEvent = -1;
+ break;
+ }
+
g_focusWindow = win;
/*
{
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
+
+ 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;
}
static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
+ // if the focus goes out of our app alltogether, OnIdle() will send
+ // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
+ // g_sendActivateEvent to -1
+ g_sendActivateEvent = 0;
+
+ wxWindow *winFocus = FindFocusedChild(win);
+ if ( winFocus )
+ win = winFocus;
+
+ g_focusWindow = (wxWindow *)NULL;
+
/*
printf( "OnKillFocus from " );
if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
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
+
+ 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 );
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();
if (g_blockEventsOnDrag) return;
if (!win->m_hasVMT) return;
-
+
float diff = adjust->value - win->m_oldVerticalPos;
if (fabs(diff) < 0.2) return;
-
+
win->m_oldVerticalPos = adjust->value;
GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
-
+
wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
-
+
int value = (int)(adjust->value+0.5);
wxScrollWinEvent event( command, value, wxVERTICAL );
static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
float diff = adjust->value - win->m_oldHorizontalPos;
if (fabs(diff) < 0.2) return;
-
+
win->m_oldHorizontalPos = adjust->value;
GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
-
+
wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
-
+
int value = (int)(adjust->value+0.5);
wxScrollWinEvent event( command, value, wxHORIZONTAL );
}
//-----------------------------------------------------------------------------
-// "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 );
-}
+ DEBUG_MAIN_THREAD
-//-----------------------------------------------------------------------------
-// "changed" from m_hAdjust
-//-----------------------------------------------------------------------------
-
-static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
-{
if (g_isIdle)
wxapp_install_idle_handler();
- if (g_blockEventsOnDrag) return;
- if (!win->m_hasVMT) return;
- wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
- int value = (int)(win->m_hAdjust->value+0.5);
+ g_blockEventsOnScroll = TRUE;
+ win->m_isScrolling = (gdk_event->window == widget->slider);
- wxScrollWinEvent event( command, value, wxHORIZONTAL );
- event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
+ return FALSE;
}
//-----------------------------------------------------------------------------
-// "button_press_event" from scrollbar
+// "button_release_event" from scrollbar
//-----------------------------------------------------------------------------
-static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
- GdkEventButton *WXUNUSED(gdk_event),
- wxWindow *win )
+static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
+ GdkEventButton *WXUNUSED(gdk_event),
+ wxWindow *win)
{
- if (g_isIdle)
- wxapp_install_idle_handler();
+ DEBUG_MAIN_THREAD
// don't test here as we can release the mouse while being over
// a different window than the slider
//
// if (gdk_event->window != widget->slider) return FALSE;
- win->SetScrolling( TRUE );
-
- return FALSE;
-}
+ g_blockEventsOnScroll = 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(widget), wxWindow *win )
+gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
{
+ DEBUG_MAIN_THREAD
+
if (g_isIdle)
wxapp_install_idle_handler();
- if (win->m_delayedFont)
- win->SetFont( win->GetFont() );
-
if (win->m_delayedBackgroundColour)
win->SetBackgroundColour( win->GetBackgroundColour() );
wxWindowCreateEvent event( win );
event.SetEventObject( win );
win->GetEventHandler()->ProcessEvent( event );
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "size_allocate"
+//-----------------------------------------------------------------------------
+
+static
+void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
+ GtkAllocation *WXUNUSED(alloc),
+ wxWindow *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (!win->m_hasScrolling) return;
+
+ int client_width = 0;
+ int client_height = 0;
+ win->GetClientSize( &client_width, &client_height );
+ if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
+ return;
+
+ win->m_oldClientWidth = client_width;
+ win->m_oldClientHeight = client_height;
+
+ if (!win->m_nativeSizeEvent)
+ {
+ wxSizeEvent event( win->GetSize(), win->GetId() );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+ }
+}
+
+
+#ifdef HAVE_XIM
+ #define WXUNUSED_UNLESS_XIM(param) param
+#else
+ #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
+#endif
+
+/* Resize XIM window */
+
+static
+void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
+ GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
+ wxWindow* WXUNUSED_UNLESS_XIM(win) )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+#ifdef HAVE_XIM
+ if (!win->m_ic)
+ return;
+
+ if (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION)
+ {
+ gint width, height;
+
+ gdk_window_get_size (widget->window, &width, &height);
+ win->m_icattr->preedit_area.width = width;
+ win->m_icattr->preedit_area.height = height;
+ gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
+ }
+#endif // HAVE_XIM
+}
+
+//-----------------------------------------------------------------------------
+// "realize" from m_wxwindow
+//-----------------------------------------------------------------------------
+
+/* Initialize XIM support */
+
+static gint
+gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
+ wxWindow * WXUNUSED_UNLESS_XIM(win) )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+#ifdef HAVE_XIM
+ if (win->m_ic) return FALSE;
+ if (!widget) return FALSE;
+ if (!gdk_im_ready()) return FALSE;
+
+ win->m_icattr = gdk_ic_attr_new();
+ if (!win->m_icattr) return FALSE;
+
+ gint width, height;
+ GdkEventMask mask;
+ GdkColormap *colormap;
+ GdkICAttr *attr = win->m_icattr;
+ unsigned attrmask = GDK_IC_ALL_REQ;
+ GdkIMStyle style;
+ GdkIMStyle supported_style = (GdkIMStyle)
+ (GDK_IM_PREEDIT_NONE |
+ GDK_IM_PREEDIT_NOTHING |
+ GDK_IM_PREEDIT_POSITION |
+ GDK_IM_STATUS_NONE |
+ GDK_IM_STATUS_NOTHING);
+
+ if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+ supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
+
+ attr->style = style = gdk_im_decide_style (supported_style);
+ attr->client_window = widget->window;
+
+ if ((colormap = gtk_widget_get_colormap (widget)) !=
+ gtk_widget_get_default_colormap ())
+ {
+ attrmask |= GDK_IC_PREEDIT_COLORMAP;
+ attr->preedit_colormap = colormap;
+ }
+
+ attrmask |= GDK_IC_PREEDIT_FOREGROUND;
+ attrmask |= GDK_IC_PREEDIT_BACKGROUND;
+ attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
+ attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
+
+ switch (style & GDK_IM_PREEDIT_MASK)
+ {
+ case GDK_IM_PREEDIT_POSITION:
+ if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+ {
+ g_warning ("over-the-spot style requires fontset");
+ break;
+ }
+
+ gdk_window_get_size (widget->window, &width, &height);
+
+ attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
+ attr->spot_location.x = 0;
+ attr->spot_location.y = height;
+ attr->preedit_area.x = 0;
+ attr->preedit_area.y = 0;
+ attr->preedit_area.width = width;
+ attr->preedit_area.height = height;
+ attr->preedit_fontset = widget->style->font;
+
+ break;
+ }
+
+ win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
+
+ if (win->m_ic == NULL)
+ g_warning ("Can't create input context.");
+ else
+ {
+ mask = gdk_window_get_events (widget->window);
+ mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
+ gdk_window_set_events (widget->window, mask);
+
+ if (GTK_WIDGET_HAS_FOCUS(widget))
+ gdk_im_begin (win->m_ic, widget->window);
+ }
+#endif
return FALSE;
}
GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
child->m_x += pizza->xoffset;
child->m_y += pizza->yoffset;
-
+
gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
GTK_WIDGET(child->m_widget),
child->m_x,
m_hasVMT = FALSE;
m_needParent = TRUE;
m_isBeingDeleted = FALSE;
-
+
m_noExpose = FALSE;
m_nativeSizeEvent = FALSE;
-
+
m_hasScrolling = FALSE;
m_isScrolling = FALSE;
m_isRadioButton = FALSE;
m_isFrame = FALSE;
m_acceptsFocus = FALSE;
-
+
+ m_clipPaintRegion = FALSE;
+
m_cursor = *wxSTANDARD_CURSOR;
+
+ m_delayedForegroundColour = FALSE;
+ m_delayedBackgroundColour = FALSE;
+
+#ifdef HAVE_XIM
+ m_ic = (GdkIC*) NULL;
+ m_icattr = (GdkICAttr*) NULL;
+#endif
}
wxWindow::wxWindow()
!CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
{
wxFAIL_MSG( wxT("wxWindow creation failed") );
- return FALSE;
+ return FALSE;
}
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_parent)
m_parent->RemoveChild( this );
+#ifdef HAVE_XIM
+ if (m_ic)
+ gdk_ic_destroy (m_ic);
+ if (m_icattr)
+ gdk_ic_attr_destroy (m_icattr);
+#endif
+
if (m_widgetStyle)
{
- gtk_style_unref( m_widgetStyle );
+#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;
}
m_y = (int)pos.y;
/* some reasonable defaults */
- if (!parent)
+ if (!parent)
{
if (m_x == -1)
{
if (m_y < 10) m_y = 10;
}
}
-
+
return TRUE;
}
if (m_wxwindow)
{
if (!m_noExpose)
- {
+ {
/* these get reported to wxWindows -> wxPaintEvent */
+
+ gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
+
gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
- }
-
+
+ if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
+ {
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
+ GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
+ }
+ }
+
#if (GTK_MINOR_VERSION > 0)
/* these are called when the "sunken" or "raised" borders are drawn */
gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
#endif
}
+ if (m_wxwindow && m_needParent)
+ {
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+ }
+ else
+ {
+ // For dialogs and frames, we are interested mainly in
+ // m_widget's focus.
+
+ gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
+
+ gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
+ GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+ }
+
GtkWidget *connect_widget = GetConnectWidget();
ConnectWidget( connect_widget );
- /* we cannot set colours, fonts and cursors before the widget has
+ /* We cannot set colours, fonts and cursors before the widget has
been realized, so we do this directly after realization */
gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
+ if (m_wxwindow)
+ {
+ // Catch native resize events
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
+ GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
+
+ // Initialize XIM support
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
+ GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
+
+ // And resize XIM window
+ gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
+ GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
+ }
+
+ 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;
}
gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
- gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
- GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
-
- gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
- GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
-
gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
return wxWindowBase::Destroy();
}
+void wxWindow::DoMoveWindow(int x, int y, int width, int height)
+{
+ gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
+}
+
void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
{
wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
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. */
else
{
GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
-
+
if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
{
if (x != -1) m_x = x + pizza->xoffset;
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 );
+ }
+
/*
wxPrintf( "OnSize sent from " );
if (GetClassInfo() && GetClassInfo()->GetClassName())
void wxWindow::OnInternalIdle()
{
+ if ( g_sendActivateEvent != -1 )
+ {
+ bool activate = g_sendActivateEvent != 0;
+
+ // do it only once
+ g_sendActivateEvent = -1;
+
+ wxActivateEvent event(wxEVT_ACTIVATE_APP, activate, GetId());
+ event.SetEventObject(this);
+
+ (void)GetEventHandler()->ProcessEvent(event);
+ }
+
wxCursor cursor = m_cursor;
if (g_globalCursor.Ok()) cursor = g_globalCursor;
if (cursor.Ok())
{
/* I now set the cursor anew in every OnInternalIdle call
- as setting the cursor in a parent window also effects the
- windows above so that checking for the current cursor is
- not possible. */
-
+ as setting the cursor in a parent window also effects the
+ windows above so that checking for the current cursor is
+ not possible. */
+
if (m_wxwindow)
{
GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
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;
}
}
if (m_parent && m_parent->m_wxwindow)
{
GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
- dx = pizza->xoffset;
- dy = pizza->yoffset;
+ dx = pizza->xoffset;
+ dy = pizza->yoffset;
}
if (x) (*x) = m_x - dx;
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;
}
if (m_wxwindow)
{
- gtk_widget_grab_focus (m_wxwindow);
+ if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
+ gtk_widget_grab_focus (m_wxwindow);
return;
}
if (m_widget)
{
- if (GTK_WIDGET_CAN_FOCUS(m_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
+ if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
{
gtk_widget_grab_focus (m_widget);
}
}
else
{
- // ?
+ // ?
}
}
}
/* reverse: prevent GTK from deleting the widget arbitrarily */
gtk_widget_unref( m_widget );
-
+
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 )
/* we provide this function ourselves as it is
missing in GDK (top of this file) */
-
+
GdkWindow *window = (GdkWindow*) NULL;
if (m_wxwindow)
window = GTK_PIZZA(m_wxwindow)->bin_window;
else
window = GetConnectWidget()->window;
-
+
if (window)
gdk_window_warp_pointer( window, x, 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 (!rect)
{
if (m_wxwindow)
- {
- GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
- gboolean old_clear = pizza->clear_on_draw;
- gtk_pizza_set_clear( pizza, FALSE );
-
+ {
+
+/*
+ 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 );
- }
+ 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 );
-
+ {
+/*
+ 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_pizza_set_clear( pizza, old_clear );
- }
+ 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 );
}
}
window = GTK_PIZZA(m_wxwindow)->bin_window;
else
window = GetConnectWidget()->window;
-
+
if (!window)
{
// indicate that a new style has been set
// 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;
}
window = GTK_PIZZA(m_wxwindow)->bin_window;
else
window = GetConnectWidget()->window;
-
+
if (!window)
{
// indicate that a new style has been set
// 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( gdk_window_get_colormap( m_widget->window ) );
- style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
- style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
- style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
+ m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
+ 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( gdk_window_get_colormap( m_widget->window ) );
- style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
+ m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
+ 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];
+ }
}
}
static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
{
menu->SetInvokingWindow( win );
- wxNode *node = menu->GetItems().First();
+ wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
while (node)
{
- wxMenuItem *menuitem = (wxMenuItem*)node->Data();
+ wxMenuItem *menuitem = node->GetData();
if (menuitem->IsSubMenu())
{
SetInvokingWindow( menuitem->GetSubMenu(), win );
}
- node = node->Next();
+
+ node = node->GetNext();
}
}
gs_pop_y = y;
bool is_waiting = TRUE;
-
+
gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
0, // button used to activate it
gs_timeLastClick // the time of activation
);
-
+
while (is_waiting)
{
while (gtk_events_pending())
bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
{
- if (m_wxwindow)
+ if (m_wxwindow)
return (window == GTK_PIZZA(m_wxwindow)->bin_window);
-
+
return (window == m_widget->window);
}
if (!wxWindowBase::SetFont(font))
{
- // don't leave if the GTK widget has just
- // been realized
- if (!m_delayedFont) return FALSE;
- }
-
- GdkWindow *window = (GdkWindow*) NULL;
- if (m_wxwindow)
- window = GTK_PIZZA(m_wxwindow)->bin_window;
- else
- window = GetConnectWidget()->window;
-
- if (!window)
- {
- // indicate that a new style has been set
- // but it couldn't get applied as the
- // widget hasn't been realized yet.
- m_delayedFont = TRUE;
-
- // pretend we have done something
- return TRUE;
+ return FALSE;
}
wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
window = GTK_PIZZA(m_wxwindow)->bin_window;
else
window = GetConnectWidget()->window;
-
+
if (!window) return;
+ wxCursor* cursor = & m_cursor;
+ if (!cursor->Ok())
+ cursor = wxSTANDARD_CURSOR;
+
gdk_pointer_grab( window, FALSE,
(GdkEventMask)
(GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_HINT_MASK |
+ GDK_POINTER_MOTION_HINT_MASK |
GDK_POINTER_MOTION_MASK),
(GdkWindow *) NULL,
- m_cursor.GetCursor(),
- GDK_CURRENT_TIME );
+ cursor->GetCursor(),
+ (guint32)GDK_CURRENT_TIME );
g_captureWindow = this;
}
window = GTK_PIZZA(m_wxwindow)->bin_window;
else
window = GetConnectWidget()->window;
-
- if (!window) return;
- gdk_pointer_ungrab ( GDK_CURRENT_TIME );
+ if (!window)
+ return;
+
+ gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
g_captureWindow = (wxWindow*) NULL;
}
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)
+{
+ pt = wxGetMousePosition();
+ wxWindow* found = wxFindWindowAtPoint(pt);
+ return found;
+}
+
+// Get the current mouse position.
+wxPoint wxGetMousePosition()
{
- m_isScrolling = g_blockEventsOnScroll = scroll;
+ /* 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);
+
}
+