quint64 KbPerf::pushDpi(const QPoint& newDpi){ if(pushedDpis.isEmpty()) // Push original DPI pushedDpis[0] = curDpi(); quint64 index = runningPushIdx++; if(runningPushIdx == 0) runningPushIdx = 1; pushedDpis[index] = newDpi; _curDpi(newDpi); return index; }
KbPerf::KbPerf(KbMode* parent, const KbPerf& other) : QObject(parent), dpiCurX(other.dpiCurX), dpiCurY(other.dpiCurY), dpiCurIdx(other.dpiCurIdx), dpiLastIdx(other.dpiLastIdx), runningPushIdx(1), _iOpacity(other._iOpacity), light100Color(other.light100Color), muteNAColor(other.muteNAColor), _dpiIndicator(other._dpiIndicator), _liftHeight(other._liftHeight), _angleSnap(other._angleSnap), _needsUpdate(true), _needsSave(true) { memcpy(dpiX, other.dpiX, sizeof(dpiX)); memcpy(dpiY, other.dpiY, sizeof(dpiY)); for(int i = 0; i < DPI_COUNT + 1; i++) dpiClr[i] = other.dpiClr[i]; memcpy(dpiOn, other.dpiOn, sizeof(dpiOn)); for(int i = 0; i < I_COUNT; i++){ iColor[i][0] = other.iColor[i][0]; iColor[i][1] = other.iColor[i][1]; } memcpy(iEnable, other.iEnable, sizeof(iEnable)); memcpy(hwIType, other.hwIType, sizeof(hwIType)); // Don't copy pushed DPI states. If the other mode has any, restore the original DPI if(!other.pushedDpis.isEmpty()) curDpi(other.pushedDpis[0]); }
const KbPerf& KbPerf::operator= (const KbPerf& other){ dpiCurX = other.dpiCurX; dpiCurY = other.dpiCurY; dpiCurIdx = other.dpiCurIdx; dpiLastIdx = other.dpiLastIdx; runningPushIdx = 1; _iOpacity = other._iOpacity; light100Color = other.light100Color; muteNAColor = other.muteNAColor; _dpiIndicator = other._dpiIndicator; _liftHeight = other._liftHeight; _angleSnap = other._angleSnap; _needsUpdate = true; _needsSave = true; memcpy(dpiX, other.dpiX, sizeof(dpiX)); memcpy(dpiY, other.dpiY, sizeof(dpiY)); for(int i = 0; i < DPI_COUNT + 1; i++) dpiClr[i] = other.dpiClr[i]; memcpy(dpiOn, other.dpiOn, sizeof(dpiOn)); for(int i = 0; i < I_COUNT; i++){ iColor[i][0] = other.iColor[i][0]; iColor[i][1] = other.iColor[i][1]; } memcpy(iEnable, other.iEnable, sizeof(iEnable)); memcpy(hwIType, other.hwIType, sizeof(hwIType)); // Don't copy pushed DPI states. If the other mode has any, restore the original DPI if(!other.pushedDpis.isEmpty()) curDpi(other.pushedDpis[0]); return other; }
bool CDpiForDialog::SetDialogDPI(const DpiValue& newDpi, LPRECT lprcSuggested /*= NULL*/) { if (mn_InSet > 0) return false; if (newDpi.Ydpi <= 0 || newDpi.Xdpi <= 0) return false; if (m_CurDpi.Ydpi <= 0 || m_CurDpi.Xdpi <= 0) return false; if (m_CurDpi.Equals(newDpi)) return false; bool bRc = false; MArray<DlgItem>* p = NULL; DpiValue curDpi(m_CurDpi); HFONT hf = NULL; wchar_t szClass[100]; #ifdef _DEBUG LOGFONT lftest1 = {}, lftest2 = {}; HFONT hftest; int itest1, itest2; #endif // To avoid several nested passes InterlockedIncrement(&mn_InSet); m_CurDpi.SetDpi(newDpi); _wsprintf(szClass, SKIPLEN(countof(szClass)) L"CDpiForDialog::SetDialogDPI(x%08X, {%i,%i})", (DWORD)(DWORD_PTR)mh_Dlg, newDpi.Xdpi, newDpi.Ydpi); LogString(szClass); // Eval mn_CurFontHeight = (mn_InitFontHeight * newDpi.Ydpi / 96); mlf_CurFont = mlf_InitFont; mlf_CurFont.lfHeight = mn_CurFontHeight; mlf_CurFont.lfWidth = 0; // Font mapper fault if (mn_CurFontHeight == 0 || mn_InitFontHeight == 0) goto wrap; if (!m_Items.Get(newDpi.Ydpi, &p)) { MArray<DlgItem>* pOrig = NULL; int iOrigDpi = 0; if (!m_Items.GetNext(NULL, &iOrigDpi, &pOrig) || !pOrig || (iOrigDpi <= 0)) goto wrap; int iNewDpi = newDpi.Ydpi; p = new MArray<DlgItem>(); DWORD dwStyle = GetWindowLong(mh_Dlg, GWL_STYLE); DWORD dwStyleEx = GetWindowLong(mh_Dlg, GWL_EXSTYLE); RECT rcClient = {}, rcCurWnd = {}; if (!GetClientRect(mh_Dlg, &rcClient) || !GetWindowRect(mh_Dlg, &rcCurWnd)) { delete p; goto wrap; } _ASSERTE(rcClient.left==0 && rcClient.top==0); int calcDlgWidth = rcClient.right * newDpi.Xdpi / curDpi.Xdpi; int calcDlgHeight = rcClient.bottom * newDpi.Ydpi / curDpi.Ydpi; DlgItem i = {mh_Dlg}; // Windows DWM manager do not resize NonClient areas of per-monitor dpi aware applications // So, we can not use AdjustWindowRectEx to determine full window rectangle // Just use current NonClient dimensions i.r.right = calcDlgWidth + ((rcCurWnd.right - rcCurWnd.left) - rcClient.right); i.r.bottom = calcDlgHeight + ((rcCurWnd.bottom - rcCurWnd.top) - rcClient.bottom); // .right and .bottom are width and height of the dialog _ASSERTE(i.r.left==0 && i.r.top==0); p->push_back(i); for (INT_PTR k = 1; k < pOrig->size(); k++) { const DlgItem& iOrig = (*pOrig)[k]; i.h = iOrig.h; i.r.left = iOrig.r.left * iNewDpi / iOrigDpi; i.r.top = iOrig.r.top * iNewDpi / iOrigDpi; i.r.right = iOrig.r.right * iNewDpi / iOrigDpi; i.r.bottom = iOrig.r.bottom * iNewDpi / iOrigDpi; p->push_back(i); } m_Items.Set(iNewDpi, p); } hf = CreateFontIndirect(&mlf_CurFont); if (hf == NULL) { goto wrap; } for (INT_PTR k = p->size() - 1; k >= 0; k--) { const DlgItem& di = (*p)[k]; GetClassName(di.h, szClass, countof(szClass)); DWORD nCtrlID = GetWindowLong(di.h, GWL_ID); DWORD nStyles = GetWindowLong(di.h, GWL_STYLE); bool bResizeCombo = (lstrcmpi(szClass, L"ComboBox") == 0); int iComboFieldHeight = 0, iComboWasHeight = 0; if (bResizeCombo && (nStyles & CBS_OWNERDRAWFIXED)) { RECT rcCur = {}; GetWindowRect(di.h, &rcCur); iComboWasHeight = (rcCur.bottom - rcCur.top); LONG_PTR lFieldHeight = SendMessage(di.h, CB_GETITEMHEIGHT, -1, 0); if (lFieldHeight < iComboWasHeight) { iComboFieldHeight = lFieldHeight; } } int newW = di.r.right - di.r.left; int newH = di.r.bottom - di.r.top; MoveWindow(di.h, di.r.left, di.r.top, newW, newH, FALSE); SendMessage(di.h, WM_SETFONT, (WPARAM)hf, FALSE/*immediately*/); if (bResizeCombo) { if ((nStyles & CBS_OWNERDRAWFIXED) && (iComboWasHeight > 0) && (iComboFieldHeight > 0)) SendMessage(di.h, CB_SETITEMHEIGHT, -1, newH*iComboFieldHeight/iComboWasHeight); SendMessage(di.h, CB_SETEDITSEL, 0, MAKELPARAM(-1,0)); } EditIconHint_ResChanged(di.h); InvalidateRect(di.h, NULL, TRUE); #ifdef _DEBUG itest1 = GetObject(hf, sizeof(lftest1), &lftest1); hftest = (HFONT)SendMessage(di.h, WM_GETFONT, 0, 0); itest2 = GetObject(hftest, sizeof(lftest2), &lftest2); #endif } if (p->size() > 0) { const DlgItem& di = (*p)[0]; SendMessage(mh_Dlg, WM_SETFONT, (WPARAM)hf, FALSE); DWORD nWndFlags = SWP_NOZORDER | (lprcSuggested ? 0 : SWP_NOMOVE); SetWindowPos(mh_Dlg, NULL, lprcSuggested ? lprcSuggested->left : 0, lprcSuggested ? lprcSuggested->top : 0, di.r.right, di.r.bottom, nWndFlags); RECT rc = {}; GetClientRect(mh_Dlg, &rc); InvalidateRect(mh_Dlg, NULL, TRUE); RedrawWindow(mh_Dlg, &rc, NULL, /*RDW_ERASE|*/RDW_ALLCHILDREN/*|RDW_INVALIDATE|RDW_UPDATENOW|RDW_INTERNALPAINT*/); } if (mh_CurFont != hf) DeleteObject(mh_CurFont); mh_CurFont = hf; bRc = true; wrap: InterlockedDecrement(&mn_InSet); return bRc; }
bool CDpiForDialog::SetDialogDPI(const DpiValue& newDpi, LPRECT lprcSuggested /*= NULL*/) { wchar_t szLog[160]; RECT rcClient = {}, rcCurWnd = {}; #ifdef _DEBUG if (gbSkipSetDialogDPI) { GetClientRect(mh_Dlg, &rcClient); GetWindowRect(mh_Dlg, &rcCurWnd); _wsprintf(szLog, SKIPCOUNT(szLog) L"SKIPPED CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, CurSize={%i,%i}, CurClient={%i,%i}", (DWORD)(DWORD_PTR)mh_Dlg, m_CurDpi.Xdpi, m_CurDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi, (rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top), (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top)); LogString(szLog); return false; } #endif if (mn_InSet > 0) return false; if (newDpi.Ydpi <= 0 || newDpi.Xdpi <= 0) return false; if (m_CurDpi.Ydpi <= 0 || m_CurDpi.Xdpi <= 0) return false; // When overall DPI is very large but new dpi is small // (example: primary mon is 192 high-dpi, new mon is 96 dpi) // Windows goes crazy... HUGE caption, scrollbars, checkbox marks and so on... // So huge difference makes dialog unattractive, let's try to smooth that DpiValue setDpi(newDpi); if (m_InitDpi.Ydpi > MulDiv(setDpi.Ydpi, 144, 96)) { // Increase DPI one step up setDpi.Ydpi = MulDiv(setDpi.Ydpi, 120, 96); setDpi.Xdpi = MulDiv(setDpi.Xdpi, 120, 96); // Log it _wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X forces larger dpi value from {%i,%i} to {%i,%i}", (DWORD)(DWORD_PTR)mh_Dlg, newDpi.Xdpi, newDpi.Ydpi, setDpi.Xdpi, setDpi.Ydpi); LogString(szLog); } if (m_CurDpi.Equals(setDpi)) return false; bool bRc = false; MArray<DlgItem>* p = NULL; DpiValue curDpi(m_CurDpi); HFONT hf = NULL; wchar_t szClass[100]; #ifdef _DEBUG LOGFONT lftest1 = {}, lftest2 = {}; HFONT hftest; int itest1, itest2; #endif // To avoid several nested passes InterlockedIncrement(&mn_InSet); m_CurDpi.SetDpi(setDpi); // Eval mn_CurFontHeight = GetFontSizeForDpi(NULL, m_CurDpi.Ydpi); //(m_CurDpi.Ydpi && m_InitDpi.Ydpi) ? (mn_InitFontHeight * m_CurDpi.Ydpi / m_InitDpi.Ydpi) : -11; mlf_CurFont = mlf_InitFont; mlf_CurFont.lfHeight = mn_CurFontHeight; mlf_CurFont.lfWidth = 0; // Font mapper fault if (mn_CurFontHeight == 0) goto wrap; if (!m_Items.Get(m_CurDpi.Ydpi, &p)) { MArray<DlgItem>* pOrig = NULL; int iOrigDpi = 0; if (!m_Items.GetNext(NULL, &iOrigDpi, &pOrig) || !pOrig || (iOrigDpi <= 0)) goto wrap; int iNewDpi = m_CurDpi.Ydpi; p = new MArray<DlgItem>(); DWORD dwStyle = GetWindowLong(mh_Dlg, GWL_STYLE); DWORD dwStyleEx = GetWindowLong(mh_Dlg, GWL_EXSTYLE); if (!GetClientRect(mh_Dlg, &rcClient) || !GetWindowRect(mh_Dlg, &rcCurWnd)) { delete p; goto wrap; } _ASSERTE(rcClient.left==0 && rcClient.top==0); int calcDlgWidth = rcClient.right * m_CurDpi.Xdpi / curDpi.Xdpi; int calcDlgHeight = rcClient.bottom * m_CurDpi.Ydpi / curDpi.Ydpi; DlgItem i = {mh_Dlg}; // Windows DWM manager do not resize NonClient areas of per-monitor dpi aware applications // So, we can not use AdjustWindowRectEx to determine full window rectangle // Just use current NonClient dimensions i.r.right = calcDlgWidth + ((rcCurWnd.right - rcCurWnd.left) - rcClient.right); i.r.bottom = calcDlgHeight + ((rcCurWnd.bottom - rcCurWnd.top) - rcClient.bottom); // .right and .bottom are width and height of the dialog _ASSERTE(i.r.left==0 && i.r.top==0); p->push_back(i); for (INT_PTR k = 1; k < pOrig->size(); k++) { const DlgItem& iOrig = (*pOrig)[k]; i.h = iOrig.h; i.r.left = iOrig.r.left * iNewDpi / iOrigDpi; i.r.top = iOrig.r.top * iNewDpi / iOrigDpi; i.r.right = iOrig.r.right * iNewDpi / iOrigDpi; i.r.bottom = iOrig.r.bottom * iNewDpi / iOrigDpi; p->push_back(i); } m_Items.Set(iNewDpi, p); } if (p->size() <= 0) { _ASSERTE(FALSE && "No elements"); goto wrap; } else { const DlgItem& di = (*p)[0]; _wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, OldSize={%i,%i}, NewSize={%i,%i}, NewFont=%i", (DWORD)(DWORD_PTR)mh_Dlg, curDpi.Xdpi, curDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi, (rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top), di.r.right, di.r.bottom, mlf_CurFont.lfHeight); LogString(szLog); } hf = CreateFontIndirect(&mlf_CurFont); if (hf == NULL) { goto wrap; } for (INT_PTR k = p->size() - 1; k >= 1; k--) { const DlgItem& di = (*p)[k]; GetClassName(di.h, szClass, countof(szClass)); DWORD nCtrlID = GetWindowLong(di.h, GWL_ID); DWORD nStyles = GetWindowLong(di.h, GWL_STYLE); bool bResizeCombo = (lstrcmpi(szClass, L"ComboBox") == 0); int iComboFieldHeight = 0, iComboWasHeight = 0; LONG_PTR lFieldHeight = 0, lNewHeight = 0; RECT rcCur = {}; HWND hComboEdit = NULL; RECT rcEdit = {}, rcClient = {}; if (bResizeCombo && (nStyles & CBS_OWNERDRAWFIXED)) { GetWindowRect(di.h, &rcCur); hComboEdit = FindWindowEx(di.h, NULL, L"Edit", NULL); GetClientRect(di.h, &rcClient); GetClientRect(hComboEdit, &rcEdit); iComboWasHeight = (rcCur.bottom - rcCur.top); lFieldHeight = SendMessage(di.h, CB_GETITEMHEIGHT, -1, 0); if (lFieldHeight < iComboWasHeight) { iComboFieldHeight = lFieldHeight; } } int newW = di.r.right - di.r.left; int newH = di.r.bottom - di.r.top; MoveWindow(di.h, di.r.left, di.r.top, newW, newH, FALSE); SendMessage(di.h, WM_SETFONT, (WPARAM)hf, FALSE/*immediately*/); if (bResizeCombo) { if ((nStyles & CBS_OWNERDRAWFIXED) && (iComboWasHeight > 0) && (iComboFieldHeight > 0)) { RECT rcEdit2 = {}, rcClient2 = {}; GetClientRect(di.h, &rcClient2); GetClientRect(hComboEdit, &rcEdit2); lNewHeight = newH*iComboFieldHeight/iComboWasHeight; _wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::Combo height changed - OldHeight=%i, ItemHeight=%i, NewHeight=%i, NewItemHeight=%i", (rcCur.bottom - rcCur.top), lFieldHeight, newH, lNewHeight); LogString(szLog); SendMessage(di.h, CB_SETITEMHEIGHT, -1, lNewHeight); } SendMessage(di.h, CB_SETEDITSEL, 0, MAKELPARAM(-1,0)); } EditIconHint_ResChanged(di.h); InvalidateRect(di.h, NULL, TRUE); #ifdef _DEBUG itest1 = GetObject(hf, sizeof(lftest1), &lftest1); hftest = (HFONT)SendMessage(di.h, WM_GETFONT, 0, 0); itest2 = GetObject(hftest, sizeof(lftest2), &lftest2); #endif } if (p->size() > 0) { const DlgItem& di = (*p)[0]; SendMessage(mh_Dlg, WM_SETFONT, (WPARAM)hf, FALSE); DWORD nWndFlags = SWP_NOZORDER | (lprcSuggested ? 0 : SWP_NOMOVE); SetWindowPos(mh_Dlg, NULL, lprcSuggested ? lprcSuggested->left : 0, lprcSuggested ? lprcSuggested->top : 0, di.r.right, di.r.bottom, nWndFlags); RECT rc = {}; GetClientRect(mh_Dlg, &rc); InvalidateRect(mh_Dlg, NULL, TRUE); RedrawWindow(mh_Dlg, &rc, NULL, /*RDW_ERASE|*/RDW_ALLCHILDREN/*|RDW_INVALIDATE|RDW_UPDATENOW|RDW_INTERNALPAINT*/); } if (mh_CurFont != hf) DeleteObject(mh_CurFont); mh_CurFont = hf; bRc = true; wrap: InterlockedDecrement(&mn_InSet); return bRc; }
void KbPerf::load(CkbSettings& settings){ pushedDpis.clear(); runningPushIdx = 1; _needsSave = false; bool readIndicators = true; if(!settings.containsGroup("Performance/Indicators")){ // Read old indicator settings from the lighting group, if present // (ckb <= v0.2.0) SGroup group(settings, "Lighting"); if(settings.contains("InactiveIndicators")){ bool inOk = false; int inactive = settings.value("InactiveIndicators").toInt(&inOk); if(!inOk || inactive > 2) inactive = 2; if(inactive == 1) _iOpacity = 0.75f; else if(inactive == 0) _iOpacity = 0.5f; else if(inactive < 0){ // Indicators disabled iEnable[MODE] = iEnable[MACRO] = iEnable[LIGHT] = iEnable[LOCK] = iEnable[MUTE] = false; } bool showMute = (settings.value("ShowMute").toInt(&inOk) != 0); if(inOk && !showMute) iEnable[MUTE] = false; readIndicators = false; } } SGroup group(settings, "Performance"); // Read DPI settings { SGroup group(settings, "DPI"); for(int i = 0; i < DPI_COUNT; i++){ QString iStr = QString::number(i); QPoint value = settings.value(iStr).toPoint(); if(value.isNull()) continue; dpiX[i] = value.x(); dpiY[i] = value.y(); QColor color = settings.value(iStr + "RGB").toString(); if(color.isValid()) dpiClr[i] = color; if(i != 0) dpiOn[i] = !settings.value(iStr + "Disabled").toBool(); } QColor color = settings.value("6RGB").toString(); if(color.isValid()) dpiClr[OTHER] = color; if(settings.contains("LastIdx")){ dpiLastIdx = settings.value("LastIdx").toInt(); if(dpiLastIdx >= DPI_COUNT || dpiLastIdx < 0) dpiLastIdx = 1; } QPoint value = settings.value("Current").toPoint(); if(!value.isNull()) curDpi(value); } // Read misc. mouse settings _liftHeight = (height)settings.value("LiftHeight").toInt(); if(_liftHeight < LOW || _liftHeight > HIGH) _liftHeight = MEDIUM; _angleSnap = settings.value("AngleSnap").toBool(); if(settings.contains("NoIndicator")){ // ckb <= v0.2.0 _dpiIndicator = !settings.value("NoIndicator").toBool(); } else { _dpiIndicator = settings.value("Indicators/DPI", true).toBool(); } // Read indicator settings if(readIndicators){ SGroup group(settings, "Indicators"); _iOpacity = settings.value("Opacity", 100).toInt() / 100.f; for(int i = 0; i < I_COUNT; i++){ SGroup group(settings, QString::number(i)); QColor color = settings.value("RGB0").toString(); if(color.isValid()) iColor[i][0] = color; color = settings.value("RGB1").toString(); if(color.isValid()) iColor[i][1] = color; if(i == LIGHT){ color = settings.value("RGB2").toString(); if(color.isValid()) light100Color = color; } else if(i == MUTE){ color = settings.value("RGB2").toString(); if(color.isValid()) muteNAColor = color; } if(i <= HW_IMAX){ iEnable[i] = settings.value("Enable", false).toBool(); hwIType[i] = (i_hw)settings.value("Hardware", (int)NORMAL).toInt(); } else { iEnable[i] = settings.value("Enable", true).toBool(); } } } emit didLoad(); }