MsgRouting AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic) { if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd()) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject target = GetTarget(env); env->CallStaticVoidMethod (AwtKeyboardFocusManager::keyboardFocusManagerCls, AwtKeyboardFocusManager::heavyweightButtonDownMID, target, ((jlong)msg->time) & 0xFFFFFFFF); env->DeleteLocalRef(target); AwtSetFocus(); } // Left button press was already routed to default window // procedure in the WmMouseDown above. Propagating synthetic // press seems like a bad idea as internal message loop // doesn't know how to unwrap synthetic release. delete msg; return mrConsume; } else { return AwtComponent::HandleEvent(msg, synthetic); } }
// Work around a windows bug descrbed in KB article Q73839. Reset // focus on scrollbars to update focus indicator. The article advises // to disable/enable the scrollbar. void AwtScrollbar::UpdateFocusIndicator() { if (IsFocusable()) { // todo: doesn't work SendMessage((WPARAM)ESB_DISABLE_BOTH); SendMessage((WPARAM)ESB_ENABLE_BOTH); } }
void STabCtrl::OnPaint(IRenderTarget *pRT) { SPainter painter; BeforePaint(pRT,painter); CRect rcItem,rcItemPrev; CRect rcSplit; DWORD dwState; CRect rcTitle=GetTitleRect(); pRT->PushClipRect(&rcTitle,RGN_AND); for(size_t i=0; i<GetItemCount(); i++) { dwState=WndState_Normal; if(i == m_nCurrentPage) dwState=WndState_PushDown; else if(i== m_nHoverTabItem) dwState=WndState_Hover; GetItemRect(i,rcItem); //画分隔线 if(i>0 && m_pSkinTabInter) { rcSplit=rcItem; if(m_nTabAlign==AlignLeft) { rcSplit.top=rcItemPrev.bottom; rcSplit.bottom = rcSplit.top + m_nTabInterSize; } else { rcSplit.left=rcItemPrev.right; rcSplit.right=rcSplit.left + m_nTabInterSize; } m_pSkinTabInter->Draw(pRT,rcSplit,0); } DrawItem(pRT,rcItem,i,dwState); rcItemPrev=rcItem; } pRT->PopClip(); if (m_pSkinFrame) { CRect rcPage = GetChildrenLayoutRect(); m_pSkinFrame->Draw(pRT, rcPage, WndState_Normal); } if(IsFocused() && IsFocusable() && m_bDrawFocusRect) { CRect rc; GetItemRect(m_nCurrentPage,rc); rc.DeflateRect(2,2); DrawDefFocusRect(pRT,&rc); } AfterPaint(pRT,painter); }
// Work around a windows bug descrbed in KB article Q73839. Reset // focus on scrollbars to update focus indicator. The article advises // to disable/enable the scrollbar, but simply resetting the focus is // sufficient. void AwtScrollbar::UpdateFocusIndicator() { if (IsFocusable()) { m_ignoreFocusEvents = TRUE; ::SetFocus(NULL); AwtSetFocus(); m_ignoreFocusEvents = FALSE; } }
gfx::Insets Label::GetInsets() const { gfx::Insets insets = View::GetInsets(); if(IsFocusable() || has_focus_border_) { insets += gfx::Insets(kFocusBorderPadding, kFocusBorderPadding, kFocusBorderPadding, kFocusBorderPadding); } return insets; }
void Widget::LoadStyle(const std::string& style) { ResourceManager* rm = ResourceManager::Get(); StyleProperties& properties = rm->GetStyle(style); if (properties["from"] != "") LoadStyle(properties["from"]); SetX(rm->GetValue(properties["x"], GetPosition().x)); SetY(rm->GetValue(properties["y"], GetPosition().y)); mAlignOffset.x = rm->GetValue(properties["x"], mAlignOffset.x); mAlignOffset.y = rm->GetValue(properties["y"], mAlignOffset.y); SetWidth(rm->GetValue(properties["width"], GetWidth())); SetHeight(rm->GetValue(properties["height"], GetHeight())); // Detect alignement if (properties["align"] != "") { std::string strA = properties["align"]; if (strA == "top_left") mAlign = Align::TOP_LEFT; else if (strA == "top_center") mAlign = Align::TOP_CENTER; else if (strA == "top_right") mAlign = Align::TOP_RIGHT; else if (strA == "left") mAlign = Align::LEFT; else if (strA == "center") mAlign = Align::CENTER; else if (strA == "right") mAlign = Align::RIGHT; else if (strA == "bottom_left") mAlign = Align::BOTTOM_LEFT; else if (strA == "bottom_center") mAlign = Align::BOTTOM_CENTER; else if (strA == "bottom_right") mAlign = Align::BOTTOM_RIGHT; else mAlign = Align::NONE; } SetColor(rm->GetColorValue(properties["color"], GetColor())); SetBorderColor(rm->GetColorValue(properties["borderColor"], GetBorderColor())); SetEnabled(rm->GetValue(properties["enabled"], IsEnabled())); SetVisible(rm->GetValue(properties["visible"], IsVisible())); SetFocusable(rm->GetValue(properties["focusable"], IsFocusable())); UpdatePosition(); }
void SCaption::OnLButtonDown( UINT nFlags, CPoint point ) { if(IsFocusable()) SetFocus(); HWND hHost=GetContainer()->GetHostHwnd(); if (WS_MAXIMIZE == (GetWindowLong(hHost,GWL_STYLE) & WS_MAXIMIZE)) { m_bIsMaxDown = TRUE; return; } ::SendMessage(hHost,WM_SYSCOMMAND, SC_MOVE | HTCAPTION,0); }
MsgRouting AwtCheckbox::HandleEvent(MSG *msg, BOOL synthetic) { if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd() && (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK)) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject target = GetTarget(env); env->CallStaticVoidMethod (AwtKeyboardFocusManager::keyboardFocusManagerCls, AwtKeyboardFocusManager::heavyweightButtonDownMID, target, ((jlong)msg->time) & 0xFFFFFFFF); env->DeleteLocalRef(target); } return AwtComponent::HandleEvent(msg, synthetic); }
// Strategy for finding the previous focusable view: // - keep going down on the right until you reach a view with no children, if it // it is a good candidate return it. // - start the search on the left sibling. // - if there are no left sibling, start the search on the parent (without going // down). View* FocusSearch::FindPreviousFocusableViewImpl( View* starting_view, bool check_starting_view, bool can_go_up, bool can_go_down, int skip_group_id, FocusTraversable** focus_traversable, View** focus_traversable_view) { // Let's go down and right as much as we can. if(can_go_down) { // Before we go into the direct children, we have to check if this view has // a FocusTraversable. *focus_traversable = starting_view->GetFocusTraversable(); if(*focus_traversable) { *focus_traversable_view = starting_view; return NULL; } if(starting_view->GetChildViewCount() > 0) { View* view = starting_view->GetChildViewAt( starting_view->GetChildViewCount()-1); View* v = FindPreviousFocusableViewImpl(view, true, false, true, skip_group_id, focus_traversable, focus_traversable_view); if(v || *focus_traversable) { return v; } } } // Then look at this view. Here, we do not need to see if the view has // a FocusTraversable, since we do not want to go down any more. if(check_starting_view && IsViewFocusableCandidate(starting_view, skip_group_id)) { View* v = FindSelectedViewForGroup(starting_view); // The selected view might not be focusable (if it is disabled for // example). if(IsFocusable(v)) { return v; } } // Then try the left sibling. View* sibling = starting_view->GetPreviousFocusableView(); if(sibling) { return FindPreviousFocusableViewImpl(sibling, true, true, true, skip_group_id, focus_traversable, focus_traversable_view); } // Then go up the parent. if(can_go_up) { View* parent = GetParent(starting_view); if(parent) { return FindPreviousFocusableViewImpl(parent, true, true, false, skip_group_id, focus_traversable, focus_traversable_view); } } // We found nothing. return NULL; }
// Strategy for finding the next focusable view: // - keep going down the first child, stop when you find a focusable view or // a focus traversable view (in that case return it) or when you reach a view // with no children. // - go to the right sibling and start the search from there (by invoking // FindNextFocusableViewImpl on that view). // - if the view has no right sibling, go up the parents until you find a parent // with a right sibling and start the search from there. View* FocusSearch::FindNextFocusableViewImpl( View* starting_view, bool check_starting_view, bool can_go_up, bool can_go_down, int skip_group_id, FocusTraversable** focus_traversable, View** focus_traversable_view) { if(check_starting_view) { if(IsViewFocusableCandidate(starting_view, skip_group_id)) { View* v = FindSelectedViewForGroup(starting_view); // The selected view might not be focusable (if it is disabled for // example). if(IsFocusable(v)) { return v; } } *focus_traversable = starting_view->GetFocusTraversable(); if(*focus_traversable) { *focus_traversable_view = starting_view; return NULL; } } // First let's try the left child. if(can_go_down) { if(starting_view->GetChildViewCount() > 0) { View* v = FindNextFocusableViewImpl(starting_view->GetChildViewAt(0), true, false, true, skip_group_id, focus_traversable, focus_traversable_view); if(v || *focus_traversable) { return v; } } } // Then try the right sibling. View* sibling = starting_view->GetNextFocusableView(); if(sibling) { View* v = FindNextFocusableViewImpl(sibling, true, false, true, skip_group_id, focus_traversable, focus_traversable_view); if(v || *focus_traversable) { return v; } } // Then go up to the parent sibling. if(can_go_up) { View* parent = GetParent(starting_view); while(parent) { sibling = parent->GetNextFocusableView(); if(sibling) { return FindNextFocusableViewImpl(sibling, true, true, true, skip_group_id, focus_traversable, focus_traversable_view); } parent = GetParent(parent); } } // We found nothing. return NULL; }
View* FocusSearch::FindNextFocusableView(View* starting_view, bool reverse, Direction direction, bool check_starting_view, FocusTraversable** focus_traversable, View** focus_traversable_view) { *focus_traversable = NULL; *focus_traversable_view = NULL; if(root_->GetChildViewCount() == 0) { NOTREACHED(); // Nothing to focus on here. return NULL; } View* initial_starting_view = starting_view; int starting_view_group = -1; if(starting_view) { starting_view_group = starting_view->GetGroup(); } if(!starting_view) { // Default to the first/last child starting_view = reverse ? root_->GetChildViewAt( root_->GetChildViewCount()-1) : root_->GetChildViewAt(0); // If there was no starting view, then the one we select is a potential // focus candidate. check_starting_view = true; } else { // The starting view should be a direct or indirect child of the root. DCHECK(root_->IsParentOf(starting_view)); } View* v = NULL; if(!reverse) { v = FindNextFocusableViewImpl(starting_view, check_starting_view, true, (direction == DOWN) ? true : false, starting_view_group, focus_traversable, focus_traversable_view); } else { // If the starting view is focusable, we don't want to go down, as we are // traversing the view hierarchy tree bottom-up. bool can_go_down = (direction == DOWN) && !IsFocusable(starting_view); v = FindPreviousFocusableViewImpl(starting_view, check_starting_view, true, can_go_down, starting_view_group, focus_traversable, focus_traversable_view); } // Don't set the focus to something outside of this view hierarchy. if(v && v!=root_ && !root_->IsParentOf(v)) { v = NULL; } // If |cycle_| is true, prefer to keep cycling rather than returning NULL. if(cycle_ && !v && initial_starting_view) { v = FindNextFocusableView(NULL, reverse, direction, check_starting_view, focus_traversable, focus_traversable_view); DCHECK(IsFocusable(v)); return v; } // Doing some sanity checks. if(v) { DCHECK(IsFocusable(v)); return v; } if(*focus_traversable) { DCHECK(*focus_traversable_view); return NULL; } // Nothing found. return NULL; }
bool FocusSearch::IsViewFocusableCandidate(View* v, int skip_group_id) { return IsFocusable(v) && (v->IsGroupFocusTraversable() || skip_group_id==-1 || v->GetGroup()!=skip_group_id); }
MsgRouting AwtTextField::HandleEvent(MSG *msg, BOOL synthetic) { MsgRouting returnVal; /* * RichEdit 1.0 control starts internal message loop if the * left mouse button is pressed while the cursor is not over * the current selection or the current selection is empty. * Because of this we don't receive WM_MOUSEMOVE messages * while the left mouse button is pressed. To work around * this behavior we process the relevant mouse messages * by ourselves. * By consuming WM_MOUSEMOVE messages we also don't give * the RichEdit control a chance to recognize a drag gesture * and initiate its own drag-n-drop operation. */ /** * In non-focusable mode we don't pass mouse messages to native window thus making user unable * to select the text. Below is the code from awt_TextArea.cpp which implements selection * functionality. For safety this code is only being executed in non-focusable mode. */ if (!IsFocusable()) { if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { CHARRANGE cr; LONG lCurPos = EditGetCharFromPos(msg->pt); EditGetSel(cr); /* * NOTE: Plain EDIT control always clears selection on mouse * button press. We are clearing the current selection only if * the mouse pointer is not over the selected region. * In this case we sacrifice backward compatibility * to allow dnd of the current selection. */ if (msg->message == WM_LBUTTONDBLCLK) { SetStartSelectionPos(static_cast<LONG>(SendMessage( EM_FINDWORDBREAK, WB_MOVEWORDLEFT, lCurPos))); SetEndSelectionPos(static_cast<LONG>(SendMessage( EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, lCurPos))); } else { SetStartSelectionPos(lCurPos); SetEndSelectionPos(lCurPos); } cr.cpMin = GetStartSelectionPos(); cr.cpMax = GetEndSelectionPos(); EditSetSel(cr); delete msg; return mrConsume; } else if (msg->message == WM_LBUTTONUP) { /* * If the left mouse button is pressed on the selected region * we don't clear the current selection. We clear it on button * release instead. This is to allow dnd of the current selection. */ if (GetStartSelectionPos() == -1 && GetEndSelectionPos() == -1) { CHARRANGE cr; LONG lCurPos = EditGetCharFromPos(msg->pt); cr.cpMin = lCurPos; cr.cpMax = lCurPos; EditSetSel(cr); } /* * Cleanup the state variables when left mouse button is released. * These state variables are designed to reflect the selection state * while the left mouse button is pressed and be set to -1 otherwise. */ SetStartSelectionPos(-1); SetEndSelectionPos(-1); SetLastSelectionPos(-1); delete msg; return mrConsume; } else if (msg->message == WM_MOUSEMOVE && (msg->wParam & MK_LBUTTON)) { /* * We consume WM_MOUSEMOVE while the left mouse button is pressed, * so we have to simulate autoscrolling when mouse is moved outside * of the client area. */ POINT p; RECT r; BOOL bScrollLeft = FALSE; BOOL bScrollRight = FALSE; BOOL bScrollUp = FALSE; BOOL bScrollDown = FALSE; p.x = msg->pt.x; p.y = msg->pt.y; VERIFY(::GetClientRect(GetHWnd(), &r)); if (p.x < 0) { bScrollLeft = TRUE; p.x = 0; } else if (p.x > r.right) { bScrollRight = TRUE; p.x = r.right - 1; } LONG lCurPos = EditGetCharFromPos(p); if (GetStartSelectionPos() != -1 && GetEndSelectionPos() != -1 && lCurPos != GetLastSelectionPos()) { CHARRANGE cr; SetLastSelectionPos(lCurPos); cr.cpMin = GetStartSelectionPos(); cr.cpMax = GetLastSelectionPos(); EditSetSel(cr); } if (bScrollLeft == TRUE || bScrollRight == TRUE) { SCROLLINFO si; memset(&si, 0, sizeof(si)); si.cbSize = sizeof(si); si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; VERIFY(::GetScrollInfo(GetHWnd(), SB_HORZ, &si)); if (bScrollLeft == TRUE) { si.nPos = si.nPos - si.nPage / 2; si.nPos = max(si.nMin, si.nPos); } else if (bScrollRight == TRUE) { si.nPos = si.nPos + si.nPage / 2; si.nPos = min(si.nPos, si.nMax); } /* * Okay to use 16-bit position since RichEdit control adjusts * its scrollbars so that their range is always 16-bit. */ DASSERT(abs(si.nPos) < 0x8000); SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, LOWORD(si.nPos))); } delete msg; return mrConsume; } } /* * Store the 'synthetic' parameter so that the WM_PASTE security check * happens only for synthetic events. */ m_synthetic = synthetic; returnVal = AwtComponent::HandleEvent(msg, synthetic); m_synthetic = FALSE; return returnVal; }