X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e1f14d226fceb8f77626a58bbddf7ace3b93d66c..bd996abe63a8ed6aa07b26856a0d7935002e3e81:/src/gtk1/toplevel.cpp diff --git a/src/gtk1/toplevel.cpp b/src/gtk1/toplevel.cpp index 0f65290104..7175f78411 100644 --- a/src/gtk1/toplevel.cpp +++ b/src/gtk1/toplevel.cpp @@ -38,41 +38,26 @@ #include "wx/gtk/win_gtk.h" +#include "wx/unix/utilsx11.h" + +// XA_CARDINAL +#include + // ---------------------------------------------------------------------------- // idle system // ---------------------------------------------------------------------------- extern void wxapp_install_idle_handler(); extern bool g_isIdle; -extern int g_openDialogs; - -// ---------------------------------------------------------------------------- -// event tables -// ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // data // ---------------------------------------------------------------------------- -extern wxList wxPendingDelete; - -// ---------------------------------------------------------------------------- -// debug -// ---------------------------------------------------------------------------- - -#ifdef __WXDEBUG__ +extern wxList wxPendingDelete; -extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ); - -#endif - -// ============================================================================ -// implementation -// ============================================================================ - -// ---------------------------------------------------------------------------- -// GTK callbacks -// ---------------------------------------------------------------------------- +extern int g_openDialogs; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "focus" from m_window @@ -129,7 +114,8 @@ static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WX wxapp_install_idle_handler(); if (win->IsEnabled() && - (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))) + (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) || + win->IsGrabbed())) win->Close(); return TRUE; @@ -146,7 +132,7 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX if (g_isIdle) wxapp_install_idle_handler(); - if (!win->m_hasVMT) + if (!win->m_hasVMT || !win->IsShown()) return FALSE; int x = 0; @@ -170,7 +156,8 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX // so we do this directly after realization static void -gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win ) +gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), + wxTopLevelWindowGTK *win ) { if (g_isIdle) wxapp_install_idle_handler(); @@ -189,27 +176,11 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK * gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1); // reset the icon - wxIcon iconOld = win->GetIcon(); - if ( iconOld != wxNullIcon ) + wxIconBundle iconsOld = win->GetIcons(); + if ( iconsOld.GetIcon(-1).Ok() ) { - wxIcon icon( iconOld ); win->SetIcon( wxNullIcon ); - win->SetIcon( icon ); - } - - // we set the focus to the child that accepts the focus. this - // doesn't really have to be done in "realize" but why not? - wxWindowList::Node *node = win->GetChildren().GetFirst(); - while (node) - { - wxWindow *child = node->GetData(); - if (child->AcceptsFocus()) - { - child->SetFocus(); - break; - } - - node = node->GetNext(); + win->SetIcons( iconsOld ); } } @@ -245,8 +216,13 @@ static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_ev { GtkPizza *pizza = GTK_PIZZA(widget); - gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL, - GTK_SHADOW_NONE, &gdk_event->area, win->m_widget, "base", 0, 0, -1, -1); + gtk_paint_flat_box (win->m_widget->style, + pizza->bin_window, GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + &gdk_event->area, + win->m_widget, + (char *)"base", + 0, 0, -1, -1); return TRUE; } @@ -255,15 +231,23 @@ static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_ev // "draw" of m_client //----------------------------------------------------------------------------- +#ifndef __WXGTK20__ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win ) { GtkPizza *pizza = GTK_PIZZA(widget); - gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL, - GTK_SHADOW_NONE, rect, win->m_widget, "base", 0, 0, -1, -1); + gtk_paint_flat_box (win->m_widget->style, + pizza->bin_window, GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + rect, + win->m_widget, + (char *)"base", + 0, 0, -1, -1); } +#endif // GTK+ 1.x + // ---------------------------------------------------------------------------- // wxTopLevelWindowGTK itself // ---------------------------------------------------------------------------- @@ -318,11 +302,11 @@ void wxTopLevelWindowGTK::Init() m_miniTitle = 0; m_mainWidget = (GtkWidget*) NULL; m_insertInClientArea = TRUE; - m_isFrame = TRUE; m_isIconized = FALSE; m_fsIsShowing = FALSE; m_themeEnabled = TRUE; m_gdkDecor = m_gdkFunc = 0; + m_grabbed = FALSE; } bool wxTopLevelWindowGTK::Create( wxWindow *parent, @@ -366,12 +350,19 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, win_type = GTK_WINDOW_POPUP; if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) + { + // there is no more GTK_WINDOW_DIALOG in 2.0 +#ifdef __WXGTK20__ + win_type = GTK_WINDOW_TOPLEVEL; +#else win_type = GTK_WINDOW_DIALOG; +#endif + } m_widget = gtk_window_new( win_type ); if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) && - (HasFlag(wxFRAME_FLOAT_ON_PARENT) || (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))) + (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) { gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) ); } @@ -379,10 +370,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if (!name.IsEmpty()) gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() ); -#ifdef __WXDEBUG__ - debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name ); -#endif - gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() ); GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); @@ -398,11 +385,9 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, // for m_mainWidget themes gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event", GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this ); +#ifndef __WXGTK20__ gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw", GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this ); - -#ifdef __WXDEBUG__ - debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name ); #endif // m_wxwindow only represents the client area without toolbar and menubar @@ -410,10 +395,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, gtk_widget_show( m_wxwindow ); gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow ); -#ifdef __WXDEBUG__ - debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name ); -#endif - // we donm't allow the frame to get the focus as otherwise // the frame will grab it at arbitrary focus changes GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); @@ -428,7 +409,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if ((m_x != -1) || (m_y != -1)) gtk_widget_set_uposition( m_widget, m_x, m_y ); - + gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height ); // we cannot set MWM hints and icons before the widget has @@ -496,8 +477,20 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, wxTopLevelWindowGTK::~wxTopLevelWindowGTK() { + if (m_grabbed) + { + wxASSERT_MSG( FALSE, "Window still grabbed"); + RemoveGrab(); + } + m_isBeingDeleted = TRUE; + // it may also be GtkScrolledWindow in the case of an MDI child + if (GTK_IS_WINDOW(m_widget)) + { + gtk_window_set_focus( GTK_WINDOW(m_widget), NULL ); + } + wxTopLevelWindows.DeleteObject( this ); if (wxTheApp->GetTopWindow() == this) @@ -510,10 +503,63 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK() } } + +// X11 ICCCM values for window layers +#define WIN_LAYER_NORMAL 4 +#define WIN_LAYER_ABOVE_DOCK 10 + +// X11 window manager property name +#define XA_WIN_LAYER "_WIN_LAYER" + +// X11 window manager property name atom +static Atom gs_XA_WIN_LAYER = 0; + + +static void wx_win_hints_set_layer(GtkWidget *window, int layer) +{ + XEvent xev; + GdkWindowPrivate *priv; + gint prev_error; + + prev_error = gdk_error_warnings; + gdk_error_warnings = 0; + priv = (GdkWindowPrivate*)(GTK_WIDGET(window)->window); + + if (GTK_WIDGET_MAPPED(window)) + { + xev.type = ClientMessage; + xev.xclient.type = ClientMessage; + xev.xclient.window = priv->xwindow; + xev.xclient.message_type = gs_XA_WIN_LAYER; + xev.xclient.format = 32; + xev.xclient.data.l[0] = (long)layer; + xev.xclient.data.l[1] = gdk_time_get(); + + XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), False, + SubstructureNotifyMask, (XEvent*) &xev); + } + else + { + long data[1]; + + data[0] = layer; + XChangeProperty(GDK_DISPLAY(), priv->xwindow, gs_XA_WIN_LAYER, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, + 1); + } + gdk_error_warnings = prev_error; +} + bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style ) { if (show == m_fsIsShowing) return FALSE; // return what? + if (gs_XA_WIN_LAYER == 0) + { + // Initialose X11 Atom only once + gs_XA_WIN_LAYER = XInternAtom( GDK_DISPLAY(), XA_WIN_LAYER, False ); + } + m_fsIsShowing = show; if (show) @@ -524,32 +570,26 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style ) GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y ); GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height ); - gtk_widget_hide( m_widget ); - gtk_widget_unrealize( m_widget ); - - m_gdkDecor = (long) GDK_DECOR_BORDER; - m_gdkFunc = (long) GDK_FUNC_MOVE; + int screen_width,screen_height; + wxDisplaySize( &screen_width, &screen_height ); + + gint client_x, client_y, root_x, root_y; + gint width, height; - int x; - int y; - wxDisplaySize( &x, &y ); - SetSize( 0, 0, x, y ); + gdk_window_get_origin (m_widget->window, &root_x, &root_y); + gdk_window_get_geometry (m_widget->window, &client_x, &client_y, + &width, &height, NULL); + + wx_win_hints_set_layer( m_widget, WIN_LAYER_ABOVE_DOCK ); - gtk_widget_realize( m_widget ); - gtk_widget_show( m_widget ); + gdk_window_move_resize (m_widget->window, -client_x, -client_y, + screen_width + 1, screen_height + 1); } else { - gtk_widget_hide( m_widget ); - gtk_widget_unrealize( m_widget ); - - m_gdkFunc = m_fsSaveGdkFunc; - m_gdkDecor = m_fsSaveGdkDecor; - + wx_win_hints_set_layer( m_widget, WIN_LAYER_NORMAL ); + SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height ); - - gtk_widget_realize( m_widget ); - gtk_widget_show( m_widget ); } return TRUE; @@ -603,16 +643,14 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si { if (x != -1) m_x = x; if (y != -1) m_y = y; - if (width != -1) m_width = width; - if (height != -1) m_height = height; } else { m_x = x; m_y = y; - m_width = width; - m_height = height; } + if (width != -1) m_width = width; + if (height != -1) m_height = height; /* if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH) @@ -626,10 +664,15 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si } */ - if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth; - if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight; - if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth; - if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight; + int minWidth = GetMinWidth(), + minHeight = GetMinHeight(), + maxWidth = GetMaxWidth(), + maxHeight = GetMaxHeight(); + + if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth; + if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight; + if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth; + if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight; if ((m_x != -1) || (m_y != -1)) { @@ -702,22 +745,50 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), skip the part which handles m_frameMenuBar, m_frameToolBar and (most importantly) m_mainWidget */ - if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth; - if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight; - if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth; - if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight; + int minWidth = GetMinWidth(), + minHeight = GetMinHeight(), + maxWidth = GetMaxWidth(), + maxHeight = GetMaxHeight(); + + if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth; + if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight; + if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth; + if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight; if (m_mainWidget) { // set size hints - gint flag = 0; // GDK_HINT_POS; - if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE; - if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE; - GdkGeometry geom; - geom.min_width = m_minWidth; - geom.min_height = m_minHeight; - geom.max_width = m_maxWidth; - geom.max_height = m_maxHeight; + gint flag = 0; // GDK_HINT_POS; + GdkGeometry geom; + + if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE; + if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE; + + geom.min_width = minWidth; + geom.min_height = minHeight; + + // Because of the way we set GDK_HINT_MAX_SIZE above, if either of + // maxHeight or maxWidth is set, we must set them both, else the + // remaining -1 will be taken literally. + + // I'm certain this also happens elsewhere, and is the probable + // cause of other such things as: + // Gtk-WARNING **: gtk_widget_size_allocate(): + // attempt to allocate widget with width 65535 and height 600 + // but I don't have time to track them all now.. + // + // Really we need to encapulate all this height/width business and + // stop any old method from ripping at the members directly and + // scattering -1's without regard for who might resolve them later. + + geom.max_width = ( maxHeight == -1 ) ? maxWidth + : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth() + : maxWidth ; + + geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here ) + : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight() + : maxHeight ; + gtk_window_set_geometry_hints( GTK_WINDOW(m_widget), (GtkWidget*) NULL, &geom, @@ -733,6 +804,7 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int client_y = m_miniEdge + m_miniTitle; int client_w = m_width - 2*m_miniEdge; int client_h = m_height - 2*m_miniEdge - m_miniTitle; + gtk_pizza_set_size( GTK_PIZZA(m_mainWidget), m_wxwindow, client_x, client_y, client_w, client_h ); @@ -765,10 +837,20 @@ void wxTopLevelWindowGTK::OnInternalIdle() return; } + // set the focus if not done yet and if we can already do it + if ( GTK_WIDGET_REALIZED(m_wxwindow) ) + { + if ( g_delayedFocus && + wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this ) + { + g_delayedFocus->SetFocus(); + g_delayedFocus = NULL; + } + } + wxWindow::OnInternalIdle(); } - // ---------------------------------------------------------------------------- // frame title/icon // ---------------------------------------------------------------------------- @@ -781,13 +863,9 @@ void wxTopLevelWindowGTK::SetTitle( const wxString &title ) gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() ); } -void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) +void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon ) { - wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); - - wxTopLevelWindowBase::SetIcon(icon); - - if ( !m_icon.Ok() ) + if ( !icon.Ok() ) return; if (!m_widget->window) @@ -800,6 +878,26 @@ void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm ); } +void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) +{ + SetIcons( wxIconBundle( icon ) ); +} + +void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons ) +{ + wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); + GdkWindow* window = m_widget->window; + + wxTopLevelWindowBase::SetIcons( icons ); + + DoSetIcon( icons.GetIcon( -1 ) ); + if ( window ) + { + wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ), + (WXWindow)GDK_WINDOW_XWINDOW( window ), icons ); + } +} + // ---------------------------------------------------------------------------- // frame state: maximized/iconized/normal // ---------------------------------------------------------------------------- @@ -851,3 +949,24 @@ void wxTopLevelWindowGTK::SetIconizeState(bool iconize) } } +void wxTopLevelWindowGTK::AddGrab() +{ + if (!m_grabbed) + { + m_grabbed = TRUE; + gtk_grab_add( m_widget ); + gtk_main(); + gtk_grab_remove( m_widget ); + } +} + +void wxTopLevelWindowGTK::RemoveGrab() +{ + if (m_grabbed) + { + gtk_main_quit(); + m_grabbed = FALSE; + } +} + +// vi:sts=4:sw=4:et