emu_window.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include "common/common.h"
  6. #include "common/scm_rev.h"
  7. #include "common/string_util.h"
  8. #include "common/key_map.h"
  9. /**
  10. * Abstraction class used to provide an interface between emulation code and the frontend
  11. * (e.g. SDL, QGLWidget, GLFW, etc...).
  12. *
  13. * Design notes on the interaction between EmuWindow and the emulation core:
  14. * - Generally, decisions on anything visible to the user should be left up to the GUI.
  15. * For example, the emulation core should not try to dictate some window title or size.
  16. * This stuff is not the core's business and only causes problems with regards to thread-safety
  17. * anyway.
  18. * - Under certain circumstances, it may be desirable for the core to politely request the GUI
  19. * to set e.g. a minimum window size. However, the GUI should always be free to ignore any
  20. * such hints.
  21. * - EmuWindow may expose some of its state as read-only to the emulation core, however care
  22. * should be taken to make sure the provided information is self-consistent. This requires
  23. * some sort of synchronization (most of this is still a TODO).
  24. * - DO NOT TREAT THIS CLASS AS A GUI TOOLKIT ABSTRACTION LAYER. That's not what it is. Please
  25. * re-read the upper points again and think about it if you don't see this.
  26. */
  27. class EmuWindow
  28. {
  29. public:
  30. /// Data structure to store emuwindow configuration
  31. struct WindowConfig {
  32. bool fullscreen;
  33. int res_width;
  34. int res_height;
  35. std::pair<unsigned,unsigned> min_client_area_size;
  36. };
  37. /// Swap buffers to display the next frame
  38. virtual void SwapBuffers() = 0;
  39. /// Polls window events
  40. virtual void PollEvents() = 0;
  41. /// Makes the graphics context current for the caller thread
  42. virtual void MakeCurrent() = 0;
  43. /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
  44. virtual void DoneCurrent() = 0;
  45. virtual void ReloadSetKeymaps() = 0;
  46. /// Signals a key press action to the HID module
  47. static void KeyPressed(KeyMap::HostDeviceKey key);
  48. /// Signals a key release action to the HID module
  49. static void KeyReleased(KeyMap::HostDeviceKey key);
  50. /**
  51. * Returns currently active configuration.
  52. * @note Accesses to the returned object need not be consistent because it may be modified in another thread
  53. */
  54. const WindowConfig& GetActiveConfig() const {
  55. return active_config;
  56. }
  57. /**
  58. * Requests the internal configuration to be replaced by the specified argument at some point in the future.
  59. * @note This method is thread-safe, because it delays configuration changes to the GUI event loop. Hence there is no guarantee on when the requested configuration will be active.
  60. */
  61. void SetConfig(const WindowConfig& val) {
  62. config = val;
  63. }
  64. /**
  65. * Gets the framebuffer size in pixels.
  66. * @note This method is thread-safe
  67. */
  68. const std::pair<unsigned,unsigned> GetFramebufferSize() const {
  69. return framebuffer_size;
  70. }
  71. /**
  72. * Gets window client area width in logical coordinates.
  73. * @note For high-DPI systems, this is smaller than the framebuffer size.
  74. * @note This method is thread-safe
  75. */
  76. std::pair<unsigned,unsigned> GetClientAreaSize() const {
  77. return std::make_pair(client_area_width, client_area_height);
  78. }
  79. protected:
  80. EmuWindow()
  81. {
  82. // TODO: Find a better place to set this.
  83. config.min_client_area_size = std::make_pair(400u, 480u);
  84. active_config = config;
  85. }
  86. virtual ~EmuWindow() {}
  87. /**
  88. * Processes any pending configuration changes from the last SetConfig call.
  89. * This method invokes OnMinimalClientAreaChangeRequest if the corresponding configuration
  90. * field changed.
  91. * @note Implementations will usually want to call this from the GUI thread.
  92. * @todo Actually call this in existing implementations.
  93. */
  94. void ProcessConfigurationChanges() {
  95. // TODO: For proper thread safety, we should eventually implement a proper
  96. // multiple-writer/single-reader queue...
  97. if (config.min_client_area_size != active_config.min_client_area_size) {
  98. OnMinimalClientAreaChangeRequest(config.min_client_area_size);
  99. config.min_client_area_size = active_config.min_client_area_size;
  100. }
  101. }
  102. /**
  103. * Update internal framebuffer size with the given parameter.
  104. * @note EmuWindow implementations will usually use this in window resize event handlers.
  105. */
  106. void NotifyFramebufferSizeChanged(const std::pair<unsigned,unsigned>& size) {
  107. framebuffer_size = size;
  108. }
  109. /**
  110. * Update internal client area size with the given parameter.
  111. * @note EmuWindow implementations will usually use this in window resize event handlers.
  112. */
  113. void NotifyClientAreaSizeChanged(const std::pair<unsigned,unsigned>& size) {
  114. client_area_width = size.first;
  115. client_area_height = size.second;
  116. }
  117. private:
  118. /**
  119. * Handler called when the minimal client area was requested to be changed via SetConfig.
  120. * For the request to be honored, EmuWindow implementations will usually reimplement this function.
  121. */
  122. virtual void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) {
  123. // By default, ignore this request and do nothing.
  124. }
  125. std::pair<unsigned,unsigned> framebuffer_size;
  126. unsigned client_area_width; ///< Current client width, should be set by window impl.
  127. unsigned client_area_height; ///< Current client height, should be set by window impl.
  128. WindowConfig config; ///< Internal configuration (changes pending for being applied in ProcessConfigurationChanges)
  129. WindowConfig active_config; ///< Internal active configuration
  130. };