delayed_activation.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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/delayed_activation.h"
  8. #include "ui/ui_utility.h"
  9. #include "base/call_delayed.h"
  10. #include "base/invoke_queued.h"
  11. #include "base/platform/base_platform_info.h"
  12. #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
  13. #include "base/platform/linux/base_linux_xcb_utilities.h"
  14. #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
  15. #include <QtCore/QPointer>
  16. #include <QtWidgets/QApplication>
  17. namespace Ui {
  18. namespace {
  19. constexpr auto kPreventTimeout = crl::time(100);
  20. bool Paused/* = false*/;
  21. bool Attempted/* = false*/;
  22. auto Window = QPointer<QWidget>();
  23. bool Unpause(bool force = false) {
  24. if (force || Attempted) {
  25. Attempted = false;
  26. Paused = false;
  27. return true;
  28. }
  29. return false;
  30. }
  31. } // namespace
  32. void ActivateWindow(not_null<QWidget*> widget) {
  33. const auto window = widget->window();
  34. window->raise();
  35. window->activateWindow();
  36. ActivateWindowDelayed(window);
  37. }
  38. void ActivateWindowDelayed(not_null<QWidget*> widget) {
  39. if (Paused) {
  40. Attempted = true;
  41. return;
  42. } else if (std::exchange(Window, widget.get())) {
  43. return;
  44. }
  45. #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
  46. const auto focusAncestor = [&] {
  47. const auto focusWidget = QApplication::focusWidget();
  48. if (!focusWidget || !widget->window()) {
  49. return false;
  50. }
  51. return widget->window()->isAncestorOf(focusWidget);
  52. }();
  53. #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
  54. crl::on_main(Window, [=] {
  55. const auto widget = base::take(Window);
  56. if (!widget) {
  57. return;
  58. }
  59. const auto window = widget->window();
  60. if (!window || window->isHidden()) {
  61. return;
  62. }
  63. window->raise();
  64. window->activateWindow();
  65. #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
  66. if (::Platform::IsX11() && focusAncestor) {
  67. const base::Platform::XCB::Connection connection;
  68. if (connection && !xcb_connection_has_error(connection)) {
  69. free(
  70. xcb_request_check(
  71. connection,
  72. xcb_set_input_focus_checked(
  73. connection,
  74. XCB_INPUT_FOCUS_PARENT,
  75. window->winId(),
  76. XCB_CURRENT_TIME)));
  77. }
  78. }
  79. #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
  80. });
  81. }
  82. void PreventDelayedActivation() {
  83. Window = nullptr;
  84. Paused = true;
  85. PostponeCall([] {
  86. if (Unpause()) {
  87. return;
  88. }
  89. InvokeQueued(qApp, [] {
  90. if (Unpause()) {
  91. return;
  92. }
  93. crl::on_main([] {
  94. if (Unpause()) {
  95. return;
  96. }
  97. base::call_delayed(kPreventTimeout, [] {
  98. Unpause(true);
  99. });
  100. });
  101. });
  102. });
  103. }
  104. } // namespace Ui