/////////////////////////////////////////////////////////////////////////////
-// Name: window.cpp
+// Name: gtk/window.cpp
// Purpose:
// Author: Robert Roebling
// Id: $Id$
#pragma implementation "window.h"
#endif
+#ifdef __VMS
+#define XWarpPointer XWARPPOINTER
+#endif
+
#include "wx/defs.h"
#include "wx/window.h"
#include "wx/dc.h"
#include "wx/tooltip.h"
#endif
+#if wxUSE_CARET
+ #include "wx/caret.h"
+#endif // wxUSE_CARET
+
#include "wx/menu.h"
#include "wx/statusbr.h"
#include "wx/intl.h"
#include <gtk/gtk.h>
#include <gdk/gdkprivate.h>
#include <gdk/gdkkeysyms.h>
-#include <wx/gtk/win_gtk.h>
-
#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkprivate.h>
+
+#include "wx/gtk/win_gtk.h"
+
//-----------------------------------------------------------------------------
// documentation on internals
//-----------------------------------------------------------------------------
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
+static wxWindow *FindFocusedChild(wxWindow *win)
+{
+ wxWindow *winFocus = wxWindow::FindFocus();
+ if ( !winFocus )
+ return (wxWindow *)NULL;
+
+ if ( winFocus == win )
+ return win;
+
+ for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindow *child = FindFocusedChild(node->GetData());
+ if ( child )
+ return child;
+ }
+
+ return (wxWindow *)NULL;
+}
+
static void draw_frame( GtkWidget *widget, wxWindow *win )
{
if (!win->m_hasVMT)
GtkRequisition vscroll_req;
vscroll_req.width = 2;
vscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
(scroll_window->vscrollbar, &vscroll_req );
GtkRequisition hscroll_req;
hscroll_req.width = 2;
hscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
(scroll_window->hscrollbar, &hscroll_req );
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
if (scroll_window->vscrollbar_visible)
{
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;
}
wxapp_install_idle_handler();
/*
- if (win->GetName() == wxT("status_line"))
+ if (win->GetName() == wxT("panel"))
{
wxPrintf( wxT("OnExpose from ") );
if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
}
*/
- if (!win->m_queuedFullRedraw)
- {
+ GtkPizza *pizza = GTK_PIZZA (widget);
- win->GetUpdateRegion().Union( gdk_event->area.x,
- gdk_event->area.y,
- gdk_event->area.width,
- gdk_event->area.height );
+ if (win->GetThemeEnabled())
+ {
+ wxWindow *parent = win->GetParent();
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (!parent)
+ parent = win;
- if (gdk_event->count == 0)
- {
- wxEraseEvent eevent( win->GetId() );
- eevent.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent(eevent);
+ 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 );
- wxPaintEvent event( win->GetId() );
- event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
+ if (gdk_event->count == 0)
+ {
+ wxEraseEvent eevent( win->GetId() );
+ eevent.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent(eevent);
- win->GetUpdateRegion().Clear();
- }
+ wxPaintEvent event( win->GetId() );
+ event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( event );
+
+ win->GetUpdateRegion().Clear();
+ }
/* 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 */
- GtkPizza *pizza = GTK_PIZZA (widget);
-
GList *children = pizza->children;
while (children)
{
gtk_widget_event (child->widget, (GdkEvent*) &child_event);
}
}
- }
return TRUE;
}
if (g_isIdle)
wxapp_install_idle_handler();
-
+
+ // this is supposed to take care of extra (and unneeded) frame repaints
+ if (win->GetChildren().GetCount() == 0)
+ return;
+
/*
- if (win->GetName() == wxT("status_line"))
+ if (win->GetName() == wxT("panel"))
{
wxPrintf( wxT("OnDraw from ") );
if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
*/
GtkPizza *pizza = GTK_PIZZA (widget);
+
+ if (win->GetThemeEnabled())
+ {
+ wxWindow *parent = win->GetParent();
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (!parent)
+ parent = win;
+
+ gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE, rect, parent->m_widget, "base", 0, 0, -1, -1);
+ }
+
- if (!win->m_queuedFullRedraw)
+ if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
+ (pizza->clear_on_draw))
{
- if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
- (pizza->clear_on_draw))
- {
- gdk_window_clear_area( pizza->bin_window,
+ 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->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
- win->m_clipPaintRegion = TRUE;
+ win->m_clipPaintRegion = TRUE;
wxEraseEvent eevent( win->GetId() );
eevent.SetEventObject( win );
gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
}
}
- }
}
//-----------------------------------------------------------------------------
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
+
/*
wxString tmp;
tmp += (char)gdk_event->keyval;
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)) )
{
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 );
// g_sendActivateEvent to -1
g_sendActivateEvent = 0;
+ wxWindow *winFocus = FindFocusedChild(win);
+ if ( winFocus )
+ win = winFocus;
+
g_focusWindow = (wxWindow *)NULL;
/*
gdk_im_end();
#endif
+#ifdef wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = win->GetCaret();
+ if ( caret )
+ {
+ caret->OnKillFocus();
+ }
+#endif // wxUSE_CARET
+
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
event.SetEventObject( win );
m_acceptsFocus = FALSE;
m_clipPaintRegion = FALSE;
- m_queuedFullRedraw = FALSE;
m_cursor = *wxSTANDARD_CURSOR;
+ m_delayedForegroundColour = FALSE;
+ m_delayedBackgroundColour = FALSE;
+
#ifdef HAVE_XIM
m_ic = (GdkIC*) NULL;
m_icattr = (GdkICAttr*) NULL;
GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
- 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 );
void wxWindow::DoMoveWindow(int x, int y, int width, int height)
{
- if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window)
- {
- /* Normally, GTK will send expose events only for the regions
- which actually got exposed. Sadly, wxMSW invalidates
- the whole window so we have to do that, too. We could
- simply add a complete refresh, but we would then get
- the normal GTK expose events in surplus, so we shut
- off the expose events and schedule a full redraw to
- be done in OnInternalIdle, where we restore the handling
- of expose events. */
-
- m_queuedFullRedraw = TRUE;
-
- GdkEventMask mask = gdk_window_get_events( GTK_PIZZA(m_wxwindow)->bin_window );
- mask = (GdkEventMask)(mask & ~GDK_EXPOSURE_MASK);
- gdk_window_set_events( GTK_PIZZA(m_wxwindow)->bin_window, mask );
- }
-
gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
}
}
UpdateWindowUI();
-
- if (m_queuedFullRedraw)
- {
- /* See also wxWindow::DoMoveWindow for explanation of this code. What
- we test here is if the requested size of the window is the same as
- the actual size of window, in which case all expose events that resulted
- from resizing the window have been sent (and discarded) and we can
- now do our full redraw and switch on expose event handling again. */
-
- if ((m_width == m_widget->allocation.width) && (m_height == m_widget->allocation.height))
- {
- m_queuedFullRedraw = FALSE;
- m_updateRegion.Clear();
- m_updateRegion.Union( 0,0,m_width,m_height );
- gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
-
- GdkEventMask mask = gdk_window_get_events( GTK_PIZZA(m_wxwindow)->bin_window );
- mask = (GdkEventMask)(mask | GDK_EXPOSURE_MASK);
- gdk_window_set_events( GTK_PIZZA(m_wxwindow)->bin_window, mask );
- }
- }
}
void wxWindow::DoGetSize( int *width, int *height ) const
GtkRequisition vscroll_req;
vscroll_req.width = 2;
vscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
(scroll_window->vscrollbar, &vscroll_req );
GtkRequisition hscroll_req;
hscroll_req.width = 2;
hscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
(scroll_window->hscrollbar, &hscroll_req );
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
if (scroll_window->vscrollbar_visible)
{
GtkRequisition vscroll_req;
vscroll_req.width = 2;
vscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
(scroll_window->vscrollbar, &vscroll_req );
GtkRequisition hscroll_req;
hscroll_req.width = 2;
hscroll_req.height = 2;
- (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+ (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
(scroll_window->hscrollbar, &hscroll_req );
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
if (scroll_window->vscrollbar_visible)
{
{
wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
- return wxWindowBase::SetCursor( cursor );
+ if (cursor == m_cursor)
+ return FALSE;
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ if (cursor == wxNullCursor)
+ return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
+ else
+ return wxWindowBase::SetCursor( cursor );
}
void wxWindow::WarpPointer( int x, int y )
if (m_widgetStyle)
{
GtkStyle *remake = gtk_style_copy( m_widgetStyle );
+#ifdef __WXGTK20__
+ /* FIXME: is this necessary? */
+ _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
+#else
remake->klass = m_widgetStyle->klass;
+#endif
gtk_style_unref( m_widgetStyle );
m_widgetStyle = remake;
def = gtk_widget_get_default_style();
m_widgetStyle = gtk_style_copy( def );
+#ifdef __WXGTK20__
+ /* FIXME: is this necessary? */
+ _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass);
+#else
m_widgetStyle->klass = def->klass;
+#endif
}
return m_widgetStyle;
style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
}
+ else
+ {
+ // Try to restore the gtk default style. This is still a little
+ // oversimplified for what is probably really needed here for controls
+ // other than buttons, but is better than not being able to (re)set a
+ // control's foreground colour to *wxBLACK -- RL
+ GtkStyle *def = gtk_rc_get_style( m_widget );
+
+ if (!def)
+ def = gtk_widget_get_default_style();
+
+ style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
+ style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
+ style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
+ }
}
if (m_backgroundColour.Ok())
style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
- }
+ }
+ else
+ {
+ // Try to restore the gtk default style. This is still a little
+ // oversimplified for what is probably really needed here for controls
+ // other than buttons, but is better than not being able to (re)set a
+ // control's background colour to default grey and means resetting a
+ // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
+ // behavior -- RL
+ GtkStyle *def = gtk_rc_get_style( m_widget );
+
+ if (!def)
+ def = gtk_widget_get_default_style();
+
+ style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
+ style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
+ style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
+ style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
+ style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
+ style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
+ style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
+ style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
+ }
}
}
if (!window) return;
+ wxCursor* cursor = & m_cursor;
+ if (!cursor->Ok())
+ cursor = wxSTANDARD_CURSOR;
+
gdk_pointer_grab( window, FALSE,
(GdkEventMask)
(GDK_BUTTON_PRESS_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_POINTER_MOTION_MASK),
(GdkWindow *) NULL,
- m_cursor.GetCursor(),
+ cursor->GetCursor(),
(guint32)GDK_CURRENT_TIME );
g_captureWindow = this;
}
}
*/
}
+
+// Find the wxWindow at the current mouse position, also returning the mouse
+// position.
+wxWindow* wxFindWindowAtPointer(wxPoint& pt)
+{
+ pt = wxGetMousePosition();
+ wxWindow* found = wxFindWindowAtPoint(pt);
+ return found;
+}
+
+// Get the current mouse position.
+wxPoint wxGetMousePosition()
+{
+ /* This crashes when used within wxHelpContext,
+ so we have to use the X-specific implementation below.
+ gint x, y;
+ GdkModifierType *mask;
+ (void) gdk_window_get_pointer(NULL, &x, &y, mask);
+
+ return wxPoint(x, y);
+ */
+
+ int x, y;
+ GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
+ if (!windowAtPtr)
+ return wxPoint(-999, -999);
+
+ Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
+ Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
+ Window rootReturn, childReturn;
+ int rootX, rootY, winX, winY;
+ unsigned int maskReturn;
+
+ XQueryPointer (display,
+ rootWindow,
+ &rootReturn,
+ &childReturn,
+ &rootX, &rootY, &winX, &winY, &maskReturn);
+ return wxPoint(rootX, rootY);
+
+}
+