X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ea1b0d6ccb7d492f93a4f48f600ae0b6b397cbd7..16d38102e8ad5534d185cc532b9aa8077a75e0a4:/src/univ/topluniv.cpp?ds=sidebyside diff --git a/src/univ/topluniv.cpp b/src/univ/topluniv.cpp index d79c39eba3..556873599f 100644 --- a/src/univ/topluniv.cpp +++ b/src/univ/topluniv.cpp @@ -26,11 +26,17 @@ #endif #include "wx/defs.h" + +#ifndef WX_PRECOMP + #include "wx/dcclient.h" + #include "wx/settings.h" +#endif + #include "wx/toplevel.h" #include "wx/univ/renderer.h" -#include "wx/dcclient.h" #include "wx/bitmap.h" #include "wx/image.h" +#include "wx/cshelp.h" // ---------------------------------------------------------------------------- @@ -44,7 +50,6 @@ END_EVENT_TABLE() WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow) - // ============================================================================ // implementation // ============================================================================ @@ -55,13 +60,14 @@ void wxTopLevelWindow::Init() { m_isActive = FALSE; m_windowStyle = 0; + m_pressedButton = 0; } bool wxTopLevelWindow::Create(wxWindow *parent, wxWindowID id, const wxString& title, const wxPoint& pos, - const wxSize& sizeOrig, + const wxSize& size, long style, const wxString &name) { @@ -70,9 +76,10 @@ bool wxTopLevelWindow::Create(wxWindow *parent, exstyleOrig = 0; if ( ms_drawDecorations == -1 ) - ms_drawDecorations = TRUE; - // FIXME_MGL -- this is temporary; we assume for now that native TLW - // can't do decorations, which is not true + ms_drawDecorations = !wxSystemSettings::HasFrameDecorations() || + wxGetEnv(wxT("WXDECOR"), NULL); + // FIXME -- wxUniv should provide a way to force non-native decorations! + // $WXDECOR is just a hack in absence of better wxUniv solution if ( ms_drawDecorations ) { @@ -80,16 +87,16 @@ bool wxTopLevelWindow::Create(wxWindow *parent, styleOrig = style; exstyleOrig = GetExtraStyle(); -// style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | -// wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW | -// wxTHICK_FRAME); -// style = wxSIMPLE_BORDER; -// SetExtraStyle(exstyleOrig & -// ~(wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP)); + style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | + wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW | + wxTHICK_FRAME); + style = wxSIMPLE_BORDER; + SetExtraStyle(exstyleOrig & + ~(wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP)); } - if ( !wxTopLevelWindowNative::Create(parent, id, title, pos, - sizeOrig, style, name) ) + if ( !wxTopLevelWindowNative::Create(parent, id, title, pos, + size, style, name) ) return FALSE; if ( ms_drawDecorations ) @@ -97,14 +104,14 @@ bool wxTopLevelWindow::Create(wxWindow *parent, m_windowStyle = styleOrig; m_exStyle = exstyleOrig; } - + return TRUE; } bool wxTopLevelWindow::ShowFullScreen(bool show, long style) { if ( show == IsFullScreen() ) return FALSE; - + if ( ms_drawDecorations ) { if ( show ) @@ -132,17 +139,24 @@ long wxTopLevelWindow::GetDecorationsStyle() const { style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE; if ( m_windowStyle & wxMINIMIZE_BOX ) - style |= wxTOPLEVEL_BUTTON_MINIMIZE; + style |= wxTOPLEVEL_BUTTON_ICONIZE; if ( m_windowStyle & wxMAXIMIZE_BOX ) - style |= wxTOPLEVEL_BUTTON_MAXIMIZE; + { + if ( IsMaximized() ) + style |= wxTOPLEVEL_BUTTON_RESTORE; + else + style |= wxTOPLEVEL_BUTTON_MAXIMIZE; + } +#if wxUSE_HELP if ( m_exStyle & (wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP)) style |= wxTOPLEVEL_BUTTON_HELP; +#endif } if ( (m_windowStyle & (wxSIMPLE_BORDER | wxNO_BORDER)) == 0 ) style |= wxTOPLEVEL_BORDER; if ( m_windowStyle & (wxRESIZE_BORDER | wxTHICK_FRAME) ) style |= wxTOPLEVEL_RESIZEABLE; - + if ( IsMaximized() ) style |= wxTOPLEVEL_MAXIMIZED; if ( GetIcon().Ok() ) @@ -153,6 +167,13 @@ long wxTopLevelWindow::GetDecorationsStyle() const return style; } +void wxTopLevelWindow::RefreshTitleBar() +{ + wxNcPaintEvent event(GetId()); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); +} + // ---------------------------------------------------------------------------- // client area handling // ---------------------------------------------------------------------------- @@ -165,7 +186,7 @@ wxPoint wxTopLevelWindow::GetClientAreaOrigin() const wxTopLevelWindowNative::DoGetClientSize(&w, &h); wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h)); - rect = m_renderer->GetFrameClientArea(rect, + rect = m_renderer->GetFrameClientArea(rect, GetDecorationsStyle()); return rect.GetPosition(); } @@ -183,7 +204,7 @@ void wxTopLevelWindow::DoGetClientSize(int *width, int *height) const wxTopLevelWindowNative::DoGetClientSize(&w, &h); wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h)); - rect = m_renderer->GetFrameClientArea(rect, + rect = m_renderer->GetFrameClientArea(rect, GetDecorationsStyle()); if ( width ) *width = rect.width; @@ -198,7 +219,7 @@ void wxTopLevelWindow::DoSetClientSize(int width, int height) { if ( ms_drawDecorations ) { - wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height), + wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height), GetDecorationsStyle()); wxTopLevelWindowNative::DoSetClientSize(size.x, size.y); } @@ -221,12 +242,23 @@ void wxTopLevelWindow::OnNcPaint(wxPaintEvent& event) rect.height = size.y; wxWindowDC dc(this); - m_renderer->DrawFrameTitleBar(dc, rect, + m_renderer->DrawFrameTitleBar(dc, rect, GetTitle(), m_titlebarIcon, - GetDecorationsStyle()); + GetDecorationsStyle(), + m_pressedButton, + wxCONTROL_PRESSED); } } +long wxTopLevelWindow::HitTest(const wxPoint& pt) const +{ + int w, h; + wxTopLevelWindowNative::DoGetClientSize(&w, &h); + wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h)); + + return m_renderer->HitTestFrame(rect, pt, GetDecorationsStyle()); +} + // ---------------------------------------------------------------------------- // icons // ---------------------------------------------------------------------------- @@ -234,25 +266,27 @@ void wxTopLevelWindow::OnNcPaint(wxPaintEvent& event) void wxTopLevelWindow::SetIcon(const wxIcon& icon) { wxTopLevelWindowNative::SetIcon(icon); - if ( !m_renderer ) return; - wxSize size = m_renderer->GetFrameIconSize(); - - if ( !icon.Ok() || size.x == -1 ) - m_titlebarIcon = icon; - else + if ( ms_drawDecorations && m_renderer ) { - wxBitmap bmp1; - bmp1.CopyFromIcon(icon); - if ( !bmp1.Ok() ) - m_titlebarIcon = wxNullIcon; - else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y ) + wxSize size = m_renderer->GetFrameIconSize(); + + if ( !icon.Ok() || size.x == -1 ) m_titlebarIcon = icon; else { - wxImage img = bmp1.ConvertToImage(); - img.Rescale(size.x, size.y); - m_titlebarIcon.CopyFromBitmap(wxBitmap(img)); + wxBitmap bmp1; + bmp1.CopyFromIcon(icon); + if ( !bmp1.Ok() ) + m_titlebarIcon = wxNullIcon; + else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y ) + m_titlebarIcon = icon; + else + { + wxImage img = bmp1.ConvertToImage(); + img.Rescale(size.x, size.y); + m_titlebarIcon.CopyFromBitmap(wxBitmap(img)); + } } } } @@ -261,23 +295,98 @@ void wxTopLevelWindow::SetIcon(const wxIcon& icon) // actions // ---------------------------------------------------------------------------- +void wxTopLevelWindow::ClickTitleBarButton(long button) +{ + switch ( button ) + { + case wxTOPLEVEL_BUTTON_CLOSE: + Close(); + break; + + case wxTOPLEVEL_BUTTON_ICONIZE: + Iconize(); + break; + + case wxTOPLEVEL_BUTTON_MAXIMIZE: + Maximize(); + break; + + case wxTOPLEVEL_BUTTON_RESTORE: + Restore(); + break; + + case wxTOPLEVEL_BUTTON_HELP: +#if wxUSE_HELP + { + wxContextHelp contextHelp(this); + } +#endif + break; + + default: + wxFAIL_MSG(wxT("incorrect button specification")); + } +} + bool wxTopLevelWindow::PerformAction(const wxControlAction& action, long numArg, const wxString& strArg) { + bool isActive = numArg != 0; + if ( action == wxACTION_TOPLEVEL_ACTIVATE ) { - if ( m_isActive != (bool)numArg ) + if ( m_isActive != isActive ) { - Refresh(); - m_isActive = (bool)numArg; - wxNcPaintEvent event(GetId()); - event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event); - printf("activation: %i\n", m_isActive); + m_isActive = isActive; + RefreshTitleBar(); } return TRUE; } + + else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS ) + { + m_pressedButton = numArg; + RefreshTitleBar(); + return TRUE; + } + + else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE ) + { + m_pressedButton = 0; + RefreshTitleBar(); + return TRUE; + } + + else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK ) + { + m_pressedButton = 0; + RefreshTitleBar(); + ClickTitleBarButton(numArg); + return TRUE; + } + + else if ( action == wxACTION_TOPLEVEL_MOVE ) + { + InteractiveMove(wxINTERACTIVE_MOVE); + return TRUE; + } + + else if ( action == wxACTION_TOPLEVEL_RESIZE ) + { + int flags = wxINTERACTIVE_RESIZE; + if ( numArg & wxHT_TOPLEVEL_BORDER_N ) + flags |= wxINTERACTIVE_RESIZE_N; + if ( numArg & wxHT_TOPLEVEL_BORDER_S ) + flags |= wxINTERACTIVE_RESIZE_S; + if ( numArg & wxHT_TOPLEVEL_BORDER_W ) + flags |= wxINTERACTIVE_RESIZE_W; + if ( numArg & wxHT_TOPLEVEL_BORDER_E ) + flags |= wxINTERACTIVE_RESIZE_E; + InteractiveMove(flags); + return TRUE; + } + else return FALSE; } @@ -290,23 +399,154 @@ bool wxTopLevelWindow::PerformAction(const wxControlAction& action, wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand) : wxStdInputHandler(inphand) { + m_winCapture = NULL; + m_winHitTest = 0; + m_winPressed = 0; + m_borderCursorOn = FALSE; } bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer, const wxMouseEvent& event) { + // the button has 2 states: pressed and normal with the following + // transitions between them: + // + // normal -> left down -> capture mouse and go to pressed state + // pressed -> left up inside -> generate click -> go to normal + // outside ------------------> + // + // the other mouse buttons are ignored + if ( event.Button(1) ) + { + if ( event.ButtonDown(1) ) + { + wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow); + long hit = w->HitTest(event.GetPosition()); + + if ( hit & wxHT_TOPLEVEL_ANY_BUTTON ) + { + m_winCapture = w; + m_winCapture->CaptureMouse(); + m_winHitTest = hit; + m_winPressed = hit; + consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed); + return TRUE; + } + else if ( hit & wxHT_TOPLEVEL_TITLEBAR ) + { + consumer->PerformAction(wxACTION_TOPLEVEL_MOVE); + return TRUE; + } + else if ( (consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER) + && (hit & wxHT_TOPLEVEL_ANY_BORDER) ) + { + consumer->PerformAction(wxACTION_TOPLEVEL_RESIZE, hit); + return TRUE; + } + } + + else // up + { + if ( m_winCapture ) + { + m_winCapture->ReleaseMouse(); + m_winCapture = NULL; + + if ( m_winHitTest == m_winPressed ) + { + consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed); + return TRUE; + } + } + //else: the mouse was released outside the window, this doesn't + // count as a click + } + } + return wxStdInputHandler::HandleMouse(consumer, event); } -bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer, +bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer, const wxMouseEvent& event) { + if ( event.GetEventObject() == m_winCapture ) + { + long hit = m_winCapture->HitTest(event.GetPosition()); + + if ( hit != m_winHitTest ) + { + if ( hit != m_winPressed ) + consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed); + else + consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed); + + m_winHitTest = hit; + return TRUE; + } + } + else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER ) + { + wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(), + wxTopLevelWindow); + long hit = win->HitTest(event.GetPosition()); + + if ( hit != m_winHitTest ) + { + m_winHitTest = hit; + + if ( m_borderCursorOn ) + { + m_borderCursorOn = FALSE; + win->SetCursor(m_origCursor); + } + + if ( hit & wxHT_TOPLEVEL_ANY_BORDER ) + { + m_borderCursorOn = TRUE; + wxCursor cur; + + switch (hit) + { + case wxHT_TOPLEVEL_BORDER_N: + case wxHT_TOPLEVEL_BORDER_S: + cur = wxCursor(wxCURSOR_SIZENS); + break; + case wxHT_TOPLEVEL_BORDER_W: + case wxHT_TOPLEVEL_BORDER_E: + cur = wxCursor(wxCURSOR_SIZEWE); + break; + case wxHT_TOPLEVEL_BORDER_NE: + case wxHT_TOPLEVEL_BORDER_SW: + cur = wxCursor(wxCURSOR_SIZENESW); + break; + case wxHT_TOPLEVEL_BORDER_NW: + case wxHT_TOPLEVEL_BORDER_SE: + cur = wxCursor(wxCURSOR_SIZENWSE); + break; + default: + m_borderCursorOn = FALSE; + break; + } + if ( m_borderCursorOn ) + { + m_origCursor = win->GetCursor(); + win->SetCursor(cur); + } + } + } + } + return wxStdInputHandler::HandleMouseMove(consumer, event); } -bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer, +bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer, bool activated) { + if ( m_borderCursorOn ) + { + consumer->GetInputWindow()->SetCursor(m_origCursor); + m_borderCursorOn = FALSE; + } consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated); return FALSE; }