click_handler.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "ui/click_handler.h"
  8. #include "base/algorithm.h"
  9. #include "ui/text/text_entity.h"
  10. #include "ui/integration.h"
  11. #include <QtCore/QPointer>
  12. namespace {
  13. ClickHandlerPtr &ClickHandlerActive() {
  14. static auto result = ClickHandlerPtr();
  15. return result;
  16. }
  17. ClickHandlerPtr &ClickHandlerPressed() {
  18. static auto result = ClickHandlerPtr();
  19. return result;
  20. }
  21. } // namespace
  22. ClickHandlerHost *ClickHandler::_activeHost = nullptr;
  23. ClickHandlerHost *ClickHandler::_pressedHost = nullptr;
  24. ClickHandlerHost::~ClickHandlerHost() {
  25. ClickHandler::hostDestroyed(this);
  26. }
  27. bool ClickHandler::setActive(
  28. const ClickHandlerPtr &p,
  29. ClickHandlerHost *host) {
  30. auto &active = ClickHandlerActive();
  31. auto &pressed = ClickHandlerPressed();
  32. if (active == p) {
  33. return false;
  34. }
  35. // emit clickHandlerActiveChanged only when there is no
  36. // other pressed click handler currently, if there is
  37. // this method will be called when it is unpressed
  38. if (active) {
  39. const auto emitClickHandlerActiveChanged = false
  40. || !pressed
  41. || (pressed == active);
  42. const auto wasactive = base::take(active);
  43. if (_activeHost) {
  44. if (emitClickHandlerActiveChanged) {
  45. _activeHost->clickHandlerActiveChanged(wasactive, false);
  46. }
  47. _activeHost = nullptr;
  48. }
  49. }
  50. if (p) {
  51. active = p;
  52. if ((_activeHost = host)) {
  53. bool emitClickHandlerActiveChanged = (!pressed || pressed == active);
  54. if (emitClickHandlerActiveChanged) {
  55. _activeHost->clickHandlerActiveChanged(active, true);
  56. }
  57. }
  58. }
  59. return true;
  60. }
  61. bool ClickHandler::clearActive(ClickHandlerHost *host) {
  62. if (host && _activeHost != host) {
  63. return false;
  64. }
  65. return setActive(ClickHandlerPtr(), host);
  66. }
  67. void ClickHandler::pressed() {
  68. auto &active = ClickHandlerActive();
  69. auto &pressed = ClickHandlerPressed();
  70. unpressed();
  71. if (!active) {
  72. return;
  73. }
  74. pressed = active;
  75. if ((_pressedHost = _activeHost)) {
  76. _pressedHost->clickHandlerPressedChanged(pressed, true);
  77. }
  78. }
  79. ClickHandlerPtr ClickHandler::unpressed() {
  80. auto &active = ClickHandlerActive();
  81. auto &pressed = ClickHandlerPressed();
  82. if (pressed) {
  83. const auto activated = (active == pressed);
  84. const auto waspressed = base::take(pressed);
  85. if (_pressedHost) {
  86. _pressedHost->clickHandlerPressedChanged(waspressed, false);
  87. _pressedHost = nullptr;
  88. }
  89. if (activated) {
  90. return active;
  91. } else if (active && _activeHost) {
  92. // emit clickHandlerActiveChanged for current active
  93. // click handler, which we didn't emit while we has
  94. // a pressed click handler
  95. _activeHost->clickHandlerActiveChanged(active, true);
  96. }
  97. }
  98. return ClickHandlerPtr();
  99. }
  100. ClickHandlerPtr ClickHandler::getActive() {
  101. return ClickHandlerActive();
  102. }
  103. ClickHandlerPtr ClickHandler::getPressed() {
  104. return ClickHandlerPressed();
  105. }
  106. bool ClickHandler::showAsActive(const ClickHandlerPtr &p) {
  107. auto &active = ClickHandlerActive();
  108. auto &pressed = ClickHandlerPressed();
  109. return p && (p == active) && (!pressed || (p == pressed));
  110. }
  111. bool ClickHandler::showAsPressed(const ClickHandlerPtr &p) {
  112. auto &active = ClickHandlerActive();
  113. auto &pressed = ClickHandlerPressed();
  114. return p && (p == active) && (p == pressed);
  115. }
  116. void ClickHandler::hostDestroyed(ClickHandlerHost *host) {
  117. auto &active = ClickHandlerActive();
  118. auto &pressed = ClickHandlerPressed();
  119. if (_activeHost == host) {
  120. active = nullptr;
  121. _activeHost = nullptr;
  122. }
  123. if (_pressedHost == host) {
  124. pressed = nullptr;
  125. _pressedHost = nullptr;
  126. }
  127. }
  128. auto ClickHandler::getTextEntity() const -> TextEntity {
  129. return { EntityType::Invalid };
  130. }
  131. void ClickHandler::setProperty(int id, QVariant value) {
  132. _properties[id] = std::move(value);
  133. }
  134. const QVariant &ClickHandler::property(int id) const {
  135. static const QVariant kEmpty;
  136. const auto i = _properties.find(id);
  137. return (i != end(_properties)) ? i->second : kEmpty;
  138. }
  139. void ActivateClickHandler(
  140. not_null<QWidget*> guard,
  141. ClickHandlerPtr handler,
  142. ClickContext context) {
  143. crl::on_main(guard, [=, weak = std::weak_ptr<ClickHandler>(handler)] {
  144. if (const auto strong = weak.lock()) {
  145. // if (Ui::Integration::Instance().allowClickHandlerActivation(strong, context)) {
  146. strong->onClick(context);
  147. // }
  148. }
  149. });
  150. }
  151. void ActivateClickHandler(
  152. not_null<QWidget*> guard,
  153. ClickHandlerPtr handler,
  154. Qt::MouseButton button) {
  155. ActivateClickHandler(guard, handler, ClickContext{ button });
  156. }