| // Copyright 2014 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "xfa/fwl/core/ifwl_form.h" |
| |
| #include <utility> |
| |
| #include "third_party/base/ptr_util.h" |
| #include "xfa/fde/tto/fde_textout.h" |
| #include "xfa/fwl/core/cfwl_app.h" |
| #include "xfa/fwl/core/cfwl_evtclose.h" |
| #include "xfa/fwl/core/cfwl_msgmouse.h" |
| #include "xfa/fwl/core/cfwl_notedriver.h" |
| #include "xfa/fwl/core/cfwl_noteloop.h" |
| #include "xfa/fwl/core/cfwl_sysbtn.h" |
| #include "xfa/fwl/core/cfwl_themebackground.h" |
| #include "xfa/fwl/core/cfwl_themepart.h" |
| #include "xfa/fwl/core/cfwl_themetext.h" |
| #include "xfa/fwl/core/cfwl_widgetmgr.h" |
| #include "xfa/fwl/core/ifwl_formproxy.h" |
| #include "xfa/fwl/core/ifwl_themeprovider.h" |
| #include "xfa/fwl/theme/cfwl_widgettp.h" |
| |
| namespace { |
| |
| const int kSystemButtonSize = 21; |
| const int kSystemButtonMargin = 5; |
| const int kSystemButtonSpan = 2; |
| |
| } // namespace |
| |
| namespace { |
| |
| const uint8_t kCornerEnlarge = 10; |
| |
| } // namespace |
| |
| IFWL_Form::IFWL_Form(const CFWL_App* app, |
| std::unique_ptr<CFWL_WidgetProperties> properties, |
| IFWL_Widget* pOuter) |
| : IFWL_Widget(app, std::move(properties), pOuter), |
| #if (_FX_OS_ == _FX_MACOSX_) |
| m_bMouseIn(false), |
| #endif |
| m_pCloseBox(nullptr), |
| m_pMinBox(nullptr), |
| m_pMaxBox(nullptr), |
| m_pSubFocus(nullptr), |
| m_fCXBorder(0), |
| m_fCYBorder(0), |
| m_iCaptureBtn(-1), |
| m_iSysBox(0), |
| m_bLButtonDown(false), |
| m_bMaximized(false), |
| m_bSetMaximize(false), |
| m_bDoModalFlag(false) { |
| m_rtRelative.Reset(); |
| m_rtRestore.Reset(); |
| |
| RegisterForm(); |
| RegisterEventTarget(nullptr); |
| } |
| |
| IFWL_Form::~IFWL_Form() { |
| UnregisterEventTarget(); |
| UnRegisterForm(); |
| RemoveSysButtons(); |
| } |
| |
| FWL_Type IFWL_Form::GetClassID() const { |
| return FWL_Type::Form; |
| } |
| |
| bool IFWL_Form::IsInstance(const CFX_WideStringC& wsClass) const { |
| if (wsClass == CFX_WideStringC(FWL_CLASS_Form)) |
| return true; |
| return IFWL_Widget::IsInstance(wsClass); |
| } |
| |
| void IFWL_Form::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) { |
| if (!bAutoSize) { |
| rect = m_pProperties->m_rtWidget; |
| return; |
| } |
| |
| rect.Reset(); |
| FX_FLOAT fCXBorder = GetBorderSize(true); |
| FX_FLOAT fCYBorder = GetBorderSize(false); |
| FX_FLOAT fEdge = GetEdgeWidth(); |
| rect.height += fCYBorder + fEdge + fEdge; |
| rect.width += fCXBorder + fCXBorder + fEdge + fEdge; |
| } |
| |
| void IFWL_Form::GetClientRect(CFX_RectF& rect) { |
| rect = m_pProperties->m_rtWidget; |
| rect.Offset(-rect.left, -rect.top); |
| } |
| |
| void IFWL_Form::Update() { |
| if (m_iLock > 0) |
| return; |
| if (!m_pProperties->m_pThemeProvider) |
| m_pProperties->m_pThemeProvider = GetAvailableTheme(); |
| |
| Layout(); |
| } |
| |
| FWL_WidgetHit IFWL_Form::HitTest(FX_FLOAT fx, FX_FLOAT fy) { |
| GetAvailableTheme(); |
| |
| if (m_pCloseBox && m_pCloseBox->m_rtBtn.Contains(fx, fy)) |
| return FWL_WidgetHit::CloseBox; |
| if (m_pMaxBox && m_pMaxBox->m_rtBtn.Contains(fx, fy)) |
| return FWL_WidgetHit::MaxBox; |
| if (m_pMinBox && m_pMinBox->m_rtBtn.Contains(fx, fy)) |
| return FWL_WidgetHit::MinBox; |
| |
| CFX_RectF rtCap; |
| rtCap.Set(m_fCYBorder, m_fCXBorder, |
| 0 - kSystemButtonSize * m_iSysBox - 2 * m_fCYBorder, |
| 0 - m_fCXBorder); |
| if (rtCap.Contains(fx, fy)) |
| return FWL_WidgetHit::Titlebar; |
| if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) && |
| (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_FRM_Resize)) { |
| FX_FLOAT fWidth = m_rtRelative.width - 2 * (m_fCYBorder + kCornerEnlarge); |
| FX_FLOAT fHeight = m_rtRelative.height - 2 * (m_fCXBorder + kCornerEnlarge); |
| |
| CFX_RectF rt; |
| rt.Set(0, m_fCXBorder + kCornerEnlarge, m_fCYBorder, fHeight); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::Left; |
| |
| rt.Set(m_rtRelative.width - m_fCYBorder, m_fCXBorder + kCornerEnlarge, |
| m_fCYBorder, fHeight); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::Right; |
| |
| rt.Set(m_fCYBorder + kCornerEnlarge, 0, fWidth, m_fCXBorder); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::Top; |
| |
| rt.Set(m_fCYBorder + kCornerEnlarge, m_rtRelative.height - m_fCXBorder, |
| fWidth, m_fCXBorder); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::Bottom; |
| |
| rt.Set(0, 0, m_fCYBorder + kCornerEnlarge, m_fCXBorder + kCornerEnlarge); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::LeftTop; |
| |
| rt.Set(0, m_rtRelative.height - m_fCXBorder - kCornerEnlarge, |
| m_fCYBorder + kCornerEnlarge, m_fCXBorder + kCornerEnlarge); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::LeftBottom; |
| |
| rt.Set(m_rtRelative.width - m_fCYBorder - kCornerEnlarge, 0, |
| m_fCYBorder + kCornerEnlarge, m_fCXBorder + kCornerEnlarge); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::RightTop; |
| |
| rt.Set(m_rtRelative.width - m_fCYBorder - kCornerEnlarge, |
| m_rtRelative.height - m_fCXBorder - kCornerEnlarge, |
| m_fCYBorder + kCornerEnlarge, m_fCXBorder + kCornerEnlarge); |
| if (rt.Contains(fx, fy)) |
| return FWL_WidgetHit::RightBottom; |
| } |
| return FWL_WidgetHit::Client; |
| } |
| |
| void IFWL_Form::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { |
| if (!pGraphics) |
| return; |
| if (!m_pProperties->m_pThemeProvider) |
| return; |
| |
| IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; |
| bool bInactive = !IsActive(); |
| int32_t iState = bInactive ? CFWL_PartState_Inactive : CFWL_PartState_Normal; |
| if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_FRM_NoDrawClient) == 0) |
| DrawBackground(pGraphics, pTheme); |
| |
| #ifdef FWL_UseMacSystemBorder |
| return; |
| #endif |
| CFWL_ThemeBackground param; |
| param.m_pWidget = this; |
| param.m_dwStates = iState; |
| param.m_pGraphics = pGraphics; |
| param.m_rtPart = m_rtRelative; |
| if (pMatrix) |
| param.m_matrix.Concat(*pMatrix); |
| if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) { |
| param.m_iPart = CFWL_Part::Border; |
| pTheme->DrawBackground(¶m); |
| } |
| if ((m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_EdgeMask) != |
| FWL_WGTSTYLE_EdgeNone) { |
| CFX_RectF rtEdge; |
| GetEdgeRect(rtEdge); |
| param.m_iPart = CFWL_Part::Edge; |
| param.m_rtPart = rtEdge; |
| param.m_dwStates = iState; |
| pTheme->DrawBackground(¶m); |
| } |
| |
| #if (_FX_OS_ == _FX_MACOSX_) |
| { |
| if (m_pCloseBox) { |
| param.m_iPart = CFWL_Part::CloseBox; |
| param.m_dwStates = m_pCloseBox->GetPartState(); |
| if (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) |
| param.m_dwStates = CFWL_PartState_Disabled; |
| else if (CFWL_PartState_Normal == param.m_dwStates && m_bMouseIn) |
| param.m_dwStates = CFWL_PartState_Hovered; |
| param.m_rtPart = m_pCloseBox->m_rtBtn; |
| pTheme->DrawBackground(¶m); |
| } |
| if (m_pMaxBox) { |
| param.m_iPart = CFWL_Part::MaximizeBox; |
| param.m_dwStates = m_pMaxBox->GetPartState(); |
| if (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) |
| param.m_dwStates = CFWL_PartState_Disabled; |
| else if (CFWL_PartState_Normal == param.m_dwStates && m_bMouseIn) |
| param.m_dwStates = CFWL_PartState_Hovered; |
| param.m_rtPart = m_pMaxBox->m_rtBtn; |
| param.m_bMaximize = m_bMaximized; |
| pTheme->DrawBackground(¶m); |
| } |
| if (m_pMinBox) { |
| param.m_iPart = CFWL_Part::MinimizeBox; |
| param.m_dwStates = m_pMinBox->GetPartState(); |
| if (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) |
| param.m_dwStates = CFWL_PartState_Disabled; |
| else if (CFWL_PartState_Normal == param.m_dwStates && m_bMouseIn) |
| param.m_dwStates = CFWL_PartState_Hovered; |
| param.m_rtPart = m_pMinBox->m_rtBtn; |
| pTheme->DrawBackground(¶m); |
| } |
| m_bMouseIn = false; |
| } |
| #else |
| { |
| if (m_pCloseBox) { |
| param.m_iPart = CFWL_Part::CloseBox; |
| param.m_dwStates = m_pCloseBox->GetPartState(); |
| param.m_rtPart = m_pCloseBox->m_rtBtn; |
| pTheme->DrawBackground(¶m); |
| } |
| if (m_pMaxBox) { |
| param.m_iPart = CFWL_Part::MaximizeBox; |
| param.m_dwStates = m_pMaxBox->GetPartState(); |
| param.m_rtPart = m_pMaxBox->m_rtBtn; |
| param.m_bMaximize = m_bMaximized; |
| pTheme->DrawBackground(¶m); |
| } |
| if (m_pMinBox) { |
| param.m_iPart = CFWL_Part::MinimizeBox; |
| param.m_dwStates = m_pMinBox->GetPartState(); |
| param.m_rtPart = m_pMinBox->m_rtBtn; |
| pTheme->DrawBackground(¶m); |
| } |
| } |
| #endif |
| } |
| |
| IFWL_Widget* IFWL_Form::DoModal() { |
| const CFWL_App* pApp = GetOwnerApp(); |
| if (!pApp) |
| return nullptr; |
| |
| CFWL_NoteDriver* pDriver = pApp->GetNoteDriver(); |
| if (!pDriver) |
| return nullptr; |
| |
| m_pNoteLoop = pdfium::MakeUnique<CFWL_NoteLoop>(); |
| m_pNoteLoop->SetMainForm(this); |
| |
| pDriver->PushNoteLoop(m_pNoteLoop.get()); |
| m_bDoModalFlag = true; |
| SetStates(FWL_WGTSTATE_Invisible, false); |
| pDriver->Run(); |
| |
| #if _FX_OS_ != _FX_MACOSX_ |
| pDriver->PopNoteLoop(); |
| #endif |
| |
| m_pNoteLoop.reset(); |
| return nullptr; |
| } |
| |
| void IFWL_Form::EndDoModal() { |
| if (!m_pNoteLoop) |
| return; |
| |
| m_bDoModalFlag = false; |
| |
| #if (_FX_OS_ == _FX_MACOSX_) |
| m_pNoteLoop->EndModalLoop(); |
| const CFWL_App* pApp = GetOwnerApp(); |
| if (!pApp) |
| return; |
| |
| CFWL_NoteDriver* pDriver = |
| static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); |
| if (!pDriver) |
| return; |
| |
| pDriver->PopNoteLoop(); |
| SetStates(FWL_WGTSTATE_Invisible, true); |
| #else |
| SetStates(FWL_WGTSTATE_Invisible, true); |
| m_pNoteLoop->EndModalLoop(); |
| #endif |
| } |
| |
| void IFWL_Form::DrawBackground(CFX_Graphics* pGraphics, |
| IFWL_ThemeProvider* pTheme) { |
| CFWL_ThemeBackground param; |
| param.m_pWidget = this; |
| param.m_iPart = CFWL_Part::Background; |
| param.m_pGraphics = pGraphics; |
| param.m_rtPart = m_rtRelative; |
| param.m_rtPart.Deflate(m_fCYBorder, m_fCXBorder, m_fCYBorder, m_fCXBorder); |
| pTheme->DrawBackground(¶m); |
| } |
| |
| void IFWL_Form::RemoveSysButtons() { |
| delete m_pCloseBox; |
| m_pCloseBox = nullptr; |
| delete m_pMinBox; |
| m_pMinBox = nullptr; |
| delete m_pMaxBox; |
| m_pMaxBox = nullptr; |
| } |
| |
| CFWL_SysBtn* IFWL_Form::GetSysBtnAtPoint(FX_FLOAT fx, FX_FLOAT fy) { |
| if (m_pCloseBox && m_pCloseBox->m_rtBtn.Contains(fx, fy)) |
| return m_pCloseBox; |
| if (m_pMaxBox && m_pMaxBox->m_rtBtn.Contains(fx, fy)) |
| return m_pMaxBox; |
| if (m_pMinBox && m_pMinBox->m_rtBtn.Contains(fx, fy)) |
| return m_pMinBox; |
| return nullptr; |
| } |
| |
| CFWL_SysBtn* IFWL_Form::GetSysBtnByState(uint32_t dwState) { |
| if (m_pCloseBox && (m_pCloseBox->m_dwState & dwState)) |
| return m_pCloseBox; |
| if (m_pMaxBox && (m_pMaxBox->m_dwState & dwState)) |
| return m_pMaxBox; |
| if (m_pMinBox && (m_pMinBox->m_dwState & dwState)) |
| return m_pMinBox; |
| return nullptr; |
| } |
| |
| CFWL_SysBtn* IFWL_Form::GetSysBtnByIndex(int32_t nIndex) { |
| if (nIndex < 0) |
| return nullptr; |
| |
| CFX_ArrayTemplate<CFWL_SysBtn*> arrBtn; |
| if (m_pMinBox) |
| arrBtn.Add(m_pMinBox); |
| if (m_pMaxBox) |
| arrBtn.Add(m_pMaxBox); |
| if (m_pCloseBox) |
| arrBtn.Add(m_pCloseBox); |
| return arrBtn[nIndex]; |
| } |
| |
| int32_t IFWL_Form::GetSysBtnIndex(CFWL_SysBtn* pBtn) { |
| CFX_ArrayTemplate<CFWL_SysBtn*> arrBtn; |
| if (m_pMinBox) |
| arrBtn.Add(m_pMinBox); |
| if (m_pMaxBox) |
| arrBtn.Add(m_pMaxBox); |
| if (m_pCloseBox) |
| arrBtn.Add(m_pCloseBox); |
| return arrBtn.Find(pBtn); |
| } |
| |
| void IFWL_Form::GetEdgeRect(CFX_RectF& rtEdge) { |
| rtEdge = m_rtRelative; |
| if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) { |
| FX_FLOAT fCX = GetBorderSize(); |
| FX_FLOAT fCY = GetBorderSize(false); |
| rtEdge.Deflate(fCX, fCY, fCX, fCY); |
| } |
| } |
| |
| void IFWL_Form::SetWorkAreaRect() { |
| m_rtRestore = m_pProperties->m_rtWidget; |
| CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr(); |
| if (!pWidgetMgr) |
| return; |
| |
| m_bSetMaximize = true; |
| Repaint(&m_rtRelative); |
| } |
| |
| void IFWL_Form::Layout() { |
| GetRelativeRect(m_rtRelative); |
| |
| #ifndef FWL_UseMacSystemBorder |
| ResetSysBtn(); |
| #endif |
| } |
| |
| void IFWL_Form::ResetSysBtn() { |
| m_fCXBorder = |
| *static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::CXBorder)); |
| m_fCYBorder = |
| *static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::CYBorder)); |
| RemoveSysButtons(); |
| |
| m_iSysBox = 0; |
| if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_CloseBox) { |
| m_pCloseBox = new CFWL_SysBtn; |
| m_pCloseBox->m_rtBtn.Set( |
| m_rtRelative.right() - kSystemButtonMargin - kSystemButtonSize, |
| kSystemButtonMargin, kSystemButtonSize, kSystemButtonSize); |
| m_iSysBox++; |
| } |
| if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_MaximizeBox) { |
| m_pMaxBox = new CFWL_SysBtn; |
| if (m_pCloseBox) { |
| m_pMaxBox->m_rtBtn.Set( |
| m_pCloseBox->m_rtBtn.left - kSystemButtonSpan - kSystemButtonSize, |
| m_pCloseBox->m_rtBtn.top, kSystemButtonSize, kSystemButtonSize); |
| } else { |
| m_pMaxBox->m_rtBtn.Set( |
| m_rtRelative.right() - kSystemButtonMargin - kSystemButtonSize, |
| kSystemButtonMargin, kSystemButtonSize, kSystemButtonSize); |
| } |
| m_iSysBox++; |
| } |
| if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_MinimizeBox) { |
| m_pMinBox = new CFWL_SysBtn; |
| if (m_pMaxBox) { |
| m_pMinBox->m_rtBtn.Set( |
| m_pMaxBox->m_rtBtn.left - kSystemButtonSpan - kSystemButtonSize, |
| m_pMaxBox->m_rtBtn.top, kSystemButtonSize, kSystemButtonSize); |
| } else if (m_pCloseBox) { |
| m_pMinBox->m_rtBtn.Set( |
| m_pCloseBox->m_rtBtn.left - kSystemButtonSpan - kSystemButtonSize, |
| m_pCloseBox->m_rtBtn.top, kSystemButtonSize, kSystemButtonSize); |
| } else { |
| m_pMinBox->m_rtBtn.Set( |
| m_rtRelative.right() - kSystemButtonMargin - kSystemButtonSize, |
| kSystemButtonMargin, kSystemButtonSize, kSystemButtonSize); |
| } |
| m_iSysBox++; |
| } |
| } |
| |
| void IFWL_Form::RegisterForm() { |
| const CFWL_App* pApp = GetOwnerApp(); |
| if (!pApp) |
| return; |
| |
| CFWL_NoteDriver* pDriver = |
| static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); |
| if (!pDriver) |
| return; |
| |
| pDriver->RegisterForm(this); |
| } |
| |
| void IFWL_Form::UnRegisterForm() { |
| const CFWL_App* pApp = GetOwnerApp(); |
| if (!pApp) |
| return; |
| |
| CFWL_NoteDriver* pDriver = |
| static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); |
| if (!pDriver) |
| return; |
| |
| pDriver->UnRegisterForm(this); |
| } |
| |
| void IFWL_Form::OnProcessMessage(CFWL_Message* pMessage) { |
| #ifndef FWL_UseMacSystemBorder |
| if (!pMessage) |
| return; |
| |
| switch (pMessage->GetClassID()) { |
| case CFWL_MessageType::Mouse: { |
| CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); |
| switch (pMsg->m_dwCmd) { |
| case FWL_MouseCommand::LeftButtonDown: |
| OnLButtonDown(pMsg); |
| break; |
| case FWL_MouseCommand::LeftButtonUp: |
| OnLButtonUp(pMsg); |
| break; |
| case FWL_MouseCommand::Move: |
| OnMouseMove(pMsg); |
| break; |
| case FWL_MouseCommand::Leave: |
| OnMouseLeave(pMsg); |
| break; |
| case FWL_MouseCommand::LeftButtonDblClk: |
| OnLButtonDblClk(pMsg); |
| break; |
| default: |
| break; |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| #endif // FWL_UseMacSystemBorder |
| } |
| |
| void IFWL_Form::OnDrawWidget(CFX_Graphics* pGraphics, |
| const CFX_Matrix* pMatrix) { |
| DrawWidget(pGraphics, pMatrix); |
| } |
| |
| void IFWL_Form::OnLButtonDown(CFWL_MsgMouse* pMsg) { |
| SetGrab(true); |
| m_bLButtonDown = true; |
| |
| CFWL_SysBtn* pPressBtn = GetSysBtnAtPoint(pMsg->m_fx, pMsg->m_fy); |
| m_iCaptureBtn = GetSysBtnIndex(pPressBtn); |
| |
| if (!pPressBtn) |
| return; |
| |
| pPressBtn->SetPressed(); |
| Repaint(&pPressBtn->m_rtBtn); |
| } |
| |
| void IFWL_Form::OnLButtonUp(CFWL_MsgMouse* pMsg) { |
| SetGrab(false); |
| m_bLButtonDown = false; |
| CFWL_SysBtn* pPointBtn = GetSysBtnAtPoint(pMsg->m_fx, pMsg->m_fy); |
| CFWL_SysBtn* pPressedBtn = GetSysBtnByIndex(m_iCaptureBtn); |
| if (!pPressedBtn || pPointBtn != pPressedBtn) |
| return; |
| if (pPressedBtn == GetSysBtnByState(FWL_SYSBUTTONSTATE_Pressed)) |
| pPressedBtn->SetNormal(); |
| if (pPressedBtn == m_pMaxBox) { |
| if (m_bMaximized) { |
| SetWidgetRect(m_rtRestore); |
| Update(); |
| Repaint(); |
| } else { |
| SetWorkAreaRect(); |
| Update(); |
| } |
| m_bMaximized = !m_bMaximized; |
| } else if (pPressedBtn != m_pMinBox) { |
| CFWL_EvtClose eClose; |
| eClose.m_pSrcTarget = this; |
| DispatchEvent(&eClose); |
| } |
| } |
| |
| void IFWL_Form::OnMouseMove(CFWL_MsgMouse* pMsg) { |
| if (m_bLButtonDown) |
| return; |
| |
| CFX_RectF rtInvalidate; |
| rtInvalidate.Reset(); |
| CFWL_SysBtn* pPointBtn = GetSysBtnAtPoint(pMsg->m_fx, pMsg->m_fy); |
| CFWL_SysBtn* pOldHover = GetSysBtnByState(FWL_SYSBUTTONSTATE_Hover); |
| |
| #if _FX_OS_ == _FX_MACOSX_ |
| { |
| if (pOldHover && pPointBtn != pOldHover) |
| pOldHover->SetNormal(); |
| if (pPointBtn && pPointBtn != pOldHover) |
| pPointBtn->SetHover(); |
| if (m_pCloseBox) |
| rtInvalidate = m_pCloseBox->m_rtBtn; |
| if (m_pMaxBox) { |
| if (rtInvalidate.IsEmpty()) |
| rtInvalidate = m_pMaxBox->m_rtBtn; |
| else |
| rtInvalidate.Union(m_pMaxBox->m_rtBtn); |
| } |
| if (m_pMinBox) { |
| if (rtInvalidate.IsEmpty()) |
| rtInvalidate = m_pMinBox->m_rtBtn; |
| else |
| rtInvalidate.Union(m_pMinBox->m_rtBtn); |
| } |
| if (!rtInvalidate.IsEmpty() && |
| rtInvalidate.Contains(pMsg->m_fx, pMsg->m_fy)) { |
| m_bMouseIn = true; |
| } |
| } |
| #else |
| { |
| if (pOldHover && pPointBtn != pOldHover) { |
| pOldHover->SetNormal(); |
| rtInvalidate = pOldHover->m_rtBtn; |
| } |
| if (pPointBtn && pPointBtn != pOldHover) { |
| pPointBtn->SetHover(); |
| if (rtInvalidate.IsEmpty()) |
| rtInvalidate = pPointBtn->m_rtBtn; |
| else |
| rtInvalidate.Union(pPointBtn->m_rtBtn); |
| } |
| } |
| #endif |
| |
| if (!rtInvalidate.IsEmpty()) |
| Repaint(&rtInvalidate); |
| } |
| |
| void IFWL_Form::OnMouseLeave(CFWL_MsgMouse* pMsg) { |
| CFWL_SysBtn* pHover = GetSysBtnByState(FWL_SYSBUTTONSTATE_Hover); |
| if (!pHover) |
| return; |
| |
| pHover->SetNormal(); |
| Repaint(&pHover->m_rtBtn); |
| } |
| |
| void IFWL_Form::OnLButtonDblClk(CFWL_MsgMouse* pMsg) { |
| if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_FRM_Resize) && |
| HitTest(pMsg->m_fx, pMsg->m_fy) == FWL_WidgetHit::Titlebar) { |
| if (m_bMaximized) |
| SetWidgetRect(m_rtRestore); |
| else |
| SetWorkAreaRect(); |
| |
| Update(); |
| m_bMaximized = !m_bMaximized; |
| } |
| } |