2014-04-08 23:18:23 -04:00
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
2013-09-04 21:00:29 -04:00
2014-04-08 23:18:23 -04:00
# pragma once
2013-09-04 21:00:29 -04:00
2014-04-08 23:18:23 -04:00
# include "common/common.h"
2014-04-23 18:43:57 -07:00
# include "common/scm_rev.h"
2014-10-23 21:17:01 -07:00
# include "common/string_util.h"
2014-09-03 18:12:58 -07:00
# include "common/key_map.h"
2014-11-13 18:12:27 +01:00
/**
* Abstraction class used to provide an interface between emulation code and the frontend
* (e.g. SDL, QGLWidget, GLFW, etc...).
*
* Design notes on the interaction between EmuWindow and the emulation core:
* - Generally, decisions on anything visible to the user should be left up to the GUI.
* For example, the emulation core should not try to dictate some window title or size.
* This stuff is not the core's business and only causes problems with regards to thread-safety
* anyway.
* - Under certain circumstances, it may be desirable for the core to politely request the GUI
* to set e.g. a minimum window size. However, the GUI should always be free to ignore any
* such hints.
* - EmuWindow may expose some of its state as read-only to the emulation core, however care
* should be taken to make sure the provided information is self-consistent. This requires
* some sort of synchronization (most of this is still a TODO).
*/
2013-09-04 21:00:29 -04:00
class EmuWindow
{
public :
2014-11-13 18:12:27 +01:00
/// Data structure to store emuwindow configuration
2014-09-12 17:06:13 -07:00
struct WindowConfig {
2013-09-04 21:00:29 -04:00
bool fullscreen ;
int res_width ;
int res_height ;
2014-10-12 22:46:33 +02:00
std : : pair < unsigned , unsigned > min_client_area_size ;
2013-09-04 21:00:29 -04:00
} ;
/// Swap buffers to display the next frame
virtual void SwapBuffers ( ) = 0 ;
2014-04-01 18:20:08 -04:00
/// Polls window events
virtual void PollEvents ( ) = 0 ;
2013-09-04 21:00:29 -04:00
/// Makes the graphics context current for the caller thread
virtual void MakeCurrent ( ) = 0 ;
/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
virtual void DoneCurrent ( ) = 0 ;
2014-09-12 17:06:13 -07:00
virtual void ReloadSetKeymaps ( ) = 0 ;
2014-09-08 21:46:02 -07:00
/// Signals a key press action to the HID module
static void KeyPressed ( KeyMap : : HostDeviceKey key ) ;
2014-09-03 18:12:58 -07:00
2014-09-08 21:46:02 -07:00
/// Signals a key release action to the HID module
static void KeyReleased ( KeyMap : : HostDeviceKey key ) ;
2014-09-03 18:12:58 -07:00
2014-11-13 18:12:27 +01:00
/**
* Returns currently active configuration.
* @note Accesses to the returned object need not be consistent because it may be modified in another thread
*/
2014-10-12 22:46:33 +02:00
const WindowConfig & GetActiveConfig ( ) const {
return active_config ;
2014-04-08 23:18:23 -04:00
}
2014-11-13 18:12:27 +01:00
/**
* Requests the internal configuration to be replaced by the specified argument at some point in the future.
* @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.
*/
2014-09-12 17:06:13 -07:00
void SetConfig ( const WindowConfig & val ) {
2014-10-12 18:14:57 +02:00
config = val ;
2014-04-08 23:18:23 -04:00
}
2014-08-29 22:23:12 -07:00
2014-10-12 18:14:57 +02:00
/**
2014-11-13 18:12:27 +01:00
* Gets the framebuffer size in pixels.
* @note This method is thread-safe
2014-10-12 18:14:57 +02:00
*/
const std : : pair < unsigned , unsigned > GetFramebufferSize ( ) const {
return framebuffer_size ;
2014-04-08 23:18:23 -04:00
}
2013-09-04 21:00:29 -04:00
2014-10-12 18:14:57 +02:00
/**
2014-11-13 18:12:27 +01:00
* Gets window client area width in logical coordinates.
* @note For high-DPI systems, this is smaller than the framebuffer size.
* @note This method is thread-safe
2014-10-12 18:14:57 +02:00
*/
std : : pair < unsigned , unsigned > GetClientAreaSize ( ) const {
return std : : make_pair ( client_area_width , client_area_height ) ;
2014-04-08 23:18:23 -04:00
}
2013-09-04 21:00:29 -04:00
protected :
2014-11-13 18:17:39 +01:00
EmuWindow ( )
2014-10-12 22:46:33 +02:00
{
// TODO
config . min_client_area_size = std : : make_pair ( 300u , 500u ) ;
active_config = config ;
}
2013-09-04 21:00:29 -04:00
virtual ~ EmuWindow ( ) { }
2014-11-13 18:12:27 +01:00
/**
* Processes any pending configuration changes from the last SetConfig call.
2014-11-13 18:24:15 +01:00
* This method invokes OnMinimalClientAreaChangeRequest if the corresponding configuration
* field changed.
2014-11-13 18:12:27 +01:00
* @note Implementations will usually want to call this from the GUI thread.
2014-11-13 20:31:34 +01:00
* @todo Actually call this in existing implementations.
2014-11-13 18:12:27 +01:00
*/
void ProcessConfigurationChanges ( ) {
// TODO: For proper thread safety, we should eventually implement a proper
// multiple-writer/single-reader queue...
if ( config . min_client_area_size ! = active_config . min_client_area_size ) {
OnMinimalClientAreaChangeRequest ( config . min_client_area_size ) ;
config . min_client_area_size = active_config . min_client_area_size ;
}
}
/**
* Update internal framebuffer size with the given parameter.
* @note EmuWindow implementations will usually use this in window resize event handlers.
*/
void NotifyFramebufferSizeChanged ( const std : : pair < unsigned , unsigned > & size ) {
2014-10-12 18:14:57 +02:00
framebuffer_size = size ;
}
2013-09-04 21:00:29 -04:00
2014-11-13 18:12:27 +01:00
/**
* Update internal client area size with the given parameter.
* @note EmuWindow implementations will usually use this in window resize event handlers.
*/
2014-10-12 22:46:33 +02:00
void NotifyClientAreaSizeChanged ( const std : : pair < unsigned , unsigned > & size ) {
2014-10-12 18:14:57 +02:00
client_area_width = size . first ;
client_area_height = size . second ;
}
2013-09-04 21:00:29 -04:00
private :
2014-11-13 18:24:15 +01:00
/**
* Handler called when the minimal client area was requested to be changed via SetConfig.
* For the request to be honored, EmuWindow implementations will usually reimplement this function.
*/
2014-10-12 22:46:33 +02:00
virtual void OnMinimalClientAreaChangeRequest ( const std : : pair < unsigned , unsigned > & minimal_size ) {
2014-11-13 18:24:15 +01:00
// By default, ignore this request and do nothing.
2014-10-12 22:46:33 +02:00
}
2014-10-12 18:14:57 +02:00
std : : pair < unsigned , unsigned > framebuffer_size ;
unsigned client_area_width ; ///< Current client width, should be set by window impl.
unsigned client_area_height ; ///< Current client height, should be set by window impl.
2013-09-04 21:00:29 -04:00
2014-10-12 22:46:33 +02:00
WindowConfig config ; ///< Internal configuration (changes pending for being applied in ProcessConfigurationChanges)
WindowConfig active_config ; ///< Internal active configuration
2013-09-04 21:00:29 -04:00
} ;