/ src / modules / ShortcutGuide / ShortcutGuide / tasklist_positions.cpp
tasklist_positions.cpp
  1  #include "pch.h"
  2  #include "tasklist_positions.h"
  3  
  4  void Tasklist::update()
  5  {
  6      // Get HWND of the tasklist
  7      auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr);
  8      if (!tasklist_hwnd)
  9          return;
 10      tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr);
 11      if (!tasklist_hwnd)
 12          return;
 13      tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr);
 14      if (!tasklist_hwnd)
 15          return;
 16      tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr);
 17      if (!tasklist_hwnd)
 18          return;
 19      if (!automation)
 20      {
 21          winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation,
 22                                                nullptr,
 23                                                CLSCTX_INPROC_SERVER,
 24                                                IID_IUIAutomation,
 25                                                automation.put_void()));
 26          winrt::check_hresult(automation->CreateTrueCondition(true_condition.put()));
 27      }
 28      element = nullptr;
 29      winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put()));
 30  }
 31  
 32  bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons)
 33  {
 34      if (!automation || !element)
 35      {
 36          return false;
 37      }
 38      winrt::com_ptr<IUIAutomationElementArray> elements;
 39      if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0)
 40          return false;
 41      if (!elements)
 42          return false;
 43      int count;
 44      if (elements->get_Length(&count) < 0)
 45          return false;
 46      winrt::com_ptr<IUIAutomationElement> child;
 47      std::vector<TasklistButton> found_buttons;
 48      found_buttons.reserve(count);
 49      for (int i = 0; i < count; ++i)
 50      {
 51          child = nullptr;
 52          if (elements->GetElement(i, child.put()) < 0)
 53              return false;
 54          TasklistButton button;
 55          if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0)
 56          {
 57              if (var_rect.vt == (VT_R8 | VT_ARRAY))
 58              {
 59                  LONG pos;
 60                  double value;
 61                  pos = 0;
 62                  SafeArrayGetElement(var_rect.parray, &pos, &value);
 63                  button.x = static_cast<long>(value);
 64                  pos = 1;
 65                  SafeArrayGetElement(var_rect.parray, &pos, &value);
 66                  button.y = static_cast<long>(value);
 67                  pos = 2;
 68                  SafeArrayGetElement(var_rect.parray, &pos, &value);
 69                  button.width = static_cast<long>(value);
 70                  pos = 3;
 71                  SafeArrayGetElement(var_rect.parray, &pos, &value);
 72                  button.height = static_cast<long>(value);
 73              }
 74              VariantClear(&var_rect);
 75          }
 76          else
 77          {
 78              return false;
 79          }
 80          if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0)
 81          {
 82              button.name = automation_id;
 83              SysFreeString(automation_id);
 84          }
 85          found_buttons.push_back(button);
 86      }
 87      // assign keynums
 88      buttons.clear();
 89      for (auto& button : found_buttons)
 90      {
 91          if (buttons.empty())
 92          {
 93              button.keynum = 1;
 94              buttons.push_back(std::move(button));
 95          }
 96          else
 97          {
 98              if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row
 99                  break;
100              if (button.name == buttons.back().name)
101                  continue; // skip buttons from the same app
102              button.keynum = buttons.back().keynum + 1;
103              buttons.push_back(std::move(button));
104              if (buttons.back().keynum == 10)
105                  break; // no more than 10 buttons
106          }
107      }
108      return true;
109  }
110  
111  std::vector<TasklistButton> Tasklist::get_buttons()
112  {
113      std::vector<TasklistButton> buttons;
114      update_buttons(buttons);
115      return buttons;
116  }