diff --git a/src/modules/gui.cpp b/src/modules/gui.cpp index e7625f4e4..e74d2f835 100644 --- a/src/modules/gui.cpp +++ b/src/modules/gui.cpp @@ -28,13 +28,15 @@ #include "console.h" #include "document_wrappers.h" #include "drop_files.h" -#include "gfxmode.h" #include "ini_file.h" #include "modules/editors.h" #include "modules/gfx.h" #include "modules/gui.h" #include "modules/palettes.h" #include "raster/sprite.h" +#include "she/display.h" +#include "she/surface.h" +#include "she/system.h" #include "skin/button_icon_impl.h" #include "skin/skin_property.h" #include "skin/skin_theme.h" @@ -60,9 +62,6 @@ #include #endif -#define REFRESH_FULL_SCREEN 1 -#define SYSTEM_WINDOW_RESIZE 2 - #define SPRITEDITOR_ACTION_COPYSELECTION "CopySelection" #define SPRITEDITOR_ACTION_SNAPTOGRID "SnapToGrid" #define SPRITEDITOR_ACTION_ANGLESNAP "AngleSnap" @@ -88,8 +87,6 @@ static struct static int try_depths[] = { 32, 24, 16, 15 }; -static GfxMode lastWorkingGfxMode; - ////////////////////////////////////////////////////////////////////// enum ShortcutType { Shortcut_ExecuteCommand, @@ -141,178 +138,71 @@ static Theme* ase_theme = NULL; static std::vector* shortcuts = NULL; -static bool ji_screen_created = false; - -static volatile int next_idle_flags = 0; - static volatile int restored_width = 0; static volatile int restored_height = 0; // Default GUI screen configuration -static bool double_buffering; static int screen_scaling; static void reload_default_font(); // Load & save graphics configuration -static void load_gui_config(int& w, int& h, int& bpp, bool& fullscreen, bool& maximized); +static void load_gui_config(int& w, int& h, bool& maximized); static void save_gui_config(); static bool button_with_icon_msg_proc(Widget* widget, Message* msg); static void on_palette_change_signal(); -// Used by set_display_switch_callback(SWITCH_IN, ...). -static void display_switch_in_callback() -{ - next_idle_flags |= REFRESH_FULL_SCREEN; -} - -END_OF_STATIC_FUNCTION(display_switch_in_callback); - -#ifdef ALLEGRO4_WITH_RESIZE_PATCH -// Called when the window is resized -static void resize_callback(RESIZE_DISPLAY_EVENT *ev) -{ - if (ev->is_maximized) { - restored_width = ev->old_w; - restored_height = ev->old_h; - } - next_idle_flags |= SYSTEM_WINDOW_RESIZE; -} -#endif // ALLEGRO4_WITH_RESIZE_PATCH - // Initializes GUI. int init_module_gui() { - int min_possible_dsk_res = 0; - int c, w, h, bpp, autodetect; - bool fullscreen; + int c, w, h, min_possible_dsk_res = 0; bool maximized; shortcuts = new std::vector; - // Install the mouse - if (install_mouse() < 0) - throw base::Exception("Error installing mouse handler"); - - // Install the keyboard - if (install_keyboard() < 0) - throw base::Exception("Error installing keyboard handler"); - - // Disable Ctrl+Shift+End in non-DOS -#if !defined(ALLEGRO_DOS) - three_finger_flag = false; -#endif - three_finger_flag = true; // TODO remove this line - // Set the graphics mode... - load_gui_config(w, h, bpp, fullscreen, maximized); + load_gui_config(w, h, maximized); - autodetect = fullscreen ? GFX_AUTODETECT_FULLSCREEN: - GFX_AUTODETECT_WINDOWED; - - // Default resolution - if (!w || !h) { - bool has_desktop = false; - int dsk_w, dsk_h; - - has_desktop = get_desktop_resolution(&dsk_w, &dsk_h) == 0; - -#ifndef FULLSCREEN_PLATFORM - // We must extract some space for the windows borders - dsk_w -= 16; - dsk_h -= 32; -#endif - - // Try to get desktop resolution - if (has_desktop) { - for (c=0; try_resolutions[c].width; ++c) { - if (try_resolutions[c].width <= dsk_w && - try_resolutions[c].height <= dsk_h) { - min_possible_dsk_res = c; - fullscreen = false; - w = try_resolutions[c].width; - h = try_resolutions[c].height; - screen_scaling = try_resolutions[c].scale; - break; - } - } - } - // Full screen - else { - fullscreen = true; - w = 320; - h = 200; - screen_scaling = 1; - } + she::Display* display = NULL; + try { + display = she::Instance()->createDisplay(w, h, screen_scaling); } - - // Default color depth - if (!bpp) { - bpp = desktop_color_depth(); - if (!bpp) - bpp = 16; - } - - for (;;) { - if (bpp == 8) - throw base::Exception("You cannot use ASEPRITE in 8 bits per pixel"); - - // Original - set_color_depth(bpp); - if (set_gfx_mode(autodetect, w, h, 0, 0) == 0) - break; - + catch (const she::DisplayCreationException&) { for (c=min_possible_dsk_res; try_resolutions[c].width; ++c) { - if (set_gfx_mode(autodetect, - try_resolutions[c].width, - try_resolutions[c].height, 0, 0) == 0) { + try { + display = she::Instance()->createDisplay(try_resolutions[c].width, + try_resolutions[c].height, + try_resolutions[c].scale); + screen_scaling = try_resolutions[c].scale; - goto gfx_done; - } - } - - if (bpp == 15) - throw base::Exception("Error setting graphics mode\n%s\n" - "Try \"ase -res WIDTHxHEIGHTxBPP\"\n", allegro_error); - - for (c=0; try_depths[c]; ++c) { - if (bpp == try_depths[c]) { - bpp = try_depths[c+1]; break; } + catch (const she::DisplayCreationException&) { + // Ignore + } } } -gfx_done:; + if (!display) { + allegro_message("Unable to create a user-interface display.\n"); + return -1; + } // Create the default-manager manager = new CustomizedGuiManager(); + manager->setDisplay(display); // Setup the GUI theme for all widgets CurrentTheme::set(ase_theme = new SkinTheme()); -#ifdef ALLEGRO4_WITH_RESIZE_PATCH - // Setup the handler for window-resize events - set_resize_callback(resize_callback); -#endif - - #ifdef ALLEGRO_WINDOWS - if (maximized) { - ShowWindow(win_get_window(), SW_MAXIMIZE); - } - #endif + if (maximized) + display->maximize(); // Configure ji_screen gui_setup_screen(true); - // Add a hook to display-switch so when the user returns to the - // screen it's completelly refreshed/redrawn. - LOCK_VARIABLE(next_idle_flags); - LOCK_FUNCTION(display_switch_in_callback); - set_display_switch_callback(SWITCH_IN, display_switch_in_callback); - // Set graphics options for next time save_gui_config(); @@ -334,15 +224,6 @@ void exit_module_gui() delete shortcuts; shortcuts = NULL; - if (double_buffering) { - BITMAP *old_bmp = ji_screen; - ji_set_screen(screen, SCREEN_W, SCREEN_H); - - if (ji_screen_created) - destroy_bitmap(old_bmp); - ji_screen_created = false; - } - delete manager; // Now we can destroy theme @@ -353,46 +234,24 @@ void exit_module_gui() remove_mouse(); } -static void load_gui_config(int& w, int& h, int& bpp, bool& fullscreen, bool& maximized) +static void load_gui_config(int& w, int& h, bool& maximized) { w = get_config_int("GfxMode", "Width", 0); h = get_config_int("GfxMode", "Height", 0); - bpp = get_config_int("GfxMode", "Depth", 0); - fullscreen = get_config_bool("GfxMode", "FullScreen", -#ifdef FULLSCREEN_PLATFORM - true -#else - false -#endif - ); screen_scaling = get_config_int("GfxMode", "ScreenScale", 2); screen_scaling = MID(1, screen_scaling, 4); maximized = get_config_bool("GfxMode", "Maximized", false); - - // Avoid 8 bpp - if (bpp == 8) - bpp = 32; } static void save_gui_config() { - bool is_maximized = false; - -#ifdef WIN32 - is_maximized = (GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false); -#endif - - set_config_bool("GfxMode", "Maximized", is_maximized); - - if (screen) { - set_config_int("GfxMode", "Width", is_maximized ? restored_width: SCREEN_W); - set_config_int("GfxMode", "Height", is_maximized ? restored_height: SCREEN_H); + she::Display* display = Manager::getDefault()->getDisplay(); + if (display) { + set_config_bool("GfxMode", "Maximized", display->isMaximized()); + set_config_int("GfxMode", "Width", display->originalWidth()); + set_config_int("GfxMode", "Height", display->originalHeight()); set_config_int("GfxMode", "Depth", bitmap_color_depth(screen)); } - - if (gfx_driver) - set_config_bool("GfxMode", "FullScreen", gfx_driver->windowed ? false: true); - set_config_int("GfxMode", "ScreenScale", screen_scaling); } @@ -443,70 +302,14 @@ void gui_run() void gui_feedback() { -#ifdef ALLEGRO4_WITH_RESIZE_PATCH - if (next_idle_flags & SYSTEM_WINDOW_RESIZE) { - next_idle_flags ^= SYSTEM_WINDOW_RESIZE; - - if (acknowledge_resize() < 0) - set_gfx_mode(GFX_AUTODETECT_WINDOWED, 320, 240, 0, 0); + jmouse_draw_cursor(); + if (!Manager::getDefault()->getDisplay()->flip()) { + // In case that the display was resized. gui_setup_screen(false); App::instance()->getMainWindow()->remap_window(); Manager::getDefault()->invalidate(); } -#endif - - if (next_idle_flags & REFRESH_FULL_SCREEN) { - next_idle_flags ^= REFRESH_FULL_SCREEN; - - try { - const ActiveDocumentReader document(UIContext::instance()); - update_screen_for_document(document); - } - catch (...) { - // do nothing - } - } - - gui_flip_screen(); -} - -void gui_flip_screen() -{ - // Double buffering? - if (double_buffering && ji_screen && screen) { - jmouse_draw_cursor(); - - if (ji_dirty_region) { - ji_flip_dirty_region(); - } - else { - if (JI_SCREEN_W == SCREEN_W && JI_SCREEN_H == SCREEN_H) { - blit(ji_screen, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); - } - else { - stretch_blit(ji_screen, screen, - 0, 0, JI_SCREEN_W, JI_SCREEN_H, - 0, 0, SCREEN_W, SCREEN_H); - } - } - } - // This is a strange Allegro bug where the "screen" pointer is lost, - // so we have to reconstruct it changing the gfx mode again - else if (screen == NULL) { - PRINTF("Gfx mode lost, trying to restore gfx mode...\n"); - - if (!lastWorkingGfxMode.setGfxMode()) { - PRINTF("Fatal error\n"); - set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); - allegro_message("FATAL ERROR: Unable to restore the old graphics mode!\n"); - exit(1); - } - - PRINTF("Successfully restored\n"); - } - else - lastWorkingGfxMode.updateWithCurrentMode(); } // Sets the ji_screen variable. This routine should be called @@ -516,27 +319,8 @@ void gui_setup_screen(bool reload_font) bool regen = false; bool reinit = false; - // Double buffering is required when screen scaling is used - double_buffering = (screen_scaling > 1); - - // Is double buffering active? - if (double_buffering) { - BITMAP *old_bmp = ji_screen; - int new_w = SCREEN_W / screen_scaling; - int new_h = SCREEN_H / screen_scaling; - BITMAP *new_bmp = create_bitmap(new_w, new_h); - - ji_set_screen(new_bmp, new_w, new_h); - - if (ji_screen_created) - destroy_bitmap(old_bmp); - - ji_screen_created = true; - } - else { - ji_set_screen(screen, SCREEN_W, SCREEN_H); - ji_screen_created = false; - } + Manager::getDefault()->getDisplay()->setScale(screen_scaling); + ui::SetDisplay(Manager::getDefault()->getDisplay()); // Update guiscale factor int old_guiscale = jguiscale(); diff --git a/src/modules/gui.h b/src/modules/gui.h index 0868702ae..fea4f4d1f 100644 --- a/src/modules/gui.h +++ b/src/modules/gui.h @@ -51,7 +51,6 @@ void update_screen_for_document(const Document* document); void gui_run(); void gui_feedback(); -void gui_flip_screen(); void gui_setup_screen(bool reload_font); void load_window_pos(ui::Widget* window, const char *section); diff --git a/src/she/capabilities.h b/src/she/capabilities.h new file mode 100644 index 000000000..c0211ebf4 --- /dev/null +++ b/src/she/capabilities.h @@ -0,0 +1,20 @@ +// SHE library +// Copyright (C) 2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef SHE_CAPABILITIES_H_INCLUDED +#define SHE_CAPABILITIES_H_INCLUDED + +namespace she { + + enum Capabilities { + kMultipleDisplaysCapability = 1, + kCanResizeDisplayCapability = 2, + kDisplayScaleCapability = 4 + }; + +} // namespace she + +#endif diff --git a/src/she/display.h b/src/she/display.h new file mode 100644 index 000000000..f8f86c094 --- /dev/null +++ b/src/she/display.h @@ -0,0 +1,50 @@ +// SHE library +// Copyright (C) 2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef SHE_DISPLAY_H_INCLUDED +#define SHE_DISPLAY_H_INCLUDED + +namespace she { + + class Surface; + + // A display or window to show graphics. + class Display { + public: + virtual ~Display() { } + virtual void dispose() = 0; + + // Returns the real and current display's size (without scale applied). + virtual int width() const = 0; + virtual int height() const = 0; + + // Returns the display when it was not maximized. + virtual int originalWidth() const = 0; + virtual int originalHeight() const = 0; + + // Changes the scale (each pixel will be SCALExSCALE in the screen). + // The available surface size will be (Display::width() / scale, + // Display::height() / scale) + virtual void setScale(int scale) = 0; + + // Returns the main surface to draw into this display. + virtual Surface* getSurface() = 0; + + // Flips all graphics in the surface to the real display. Returns + // false if the flip couldn't be done because the display was + // resized. + virtual bool flip() = 0; + + virtual void maximize() = 0; + virtual bool isMaximized() const = 0; + + // Returns the HWND on Windows. + virtual void* nativeHandle() = 0; + }; + +} // namespace she + +#endif diff --git a/src/she/locked_surface.h b/src/she/locked_surface.h new file mode 100644 index 000000000..efe162b3c --- /dev/null +++ b/src/she/locked_surface.h @@ -0,0 +1,22 @@ +// SHE library +// Copyright (C) 2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef SHE_LOCKED_SURFACE_H_INCLUDED +#define SHE_LOCKED_SURFACE_H_INCLUDED + +namespace she { + + class LockedSurface { + public: + virtual ~LockedSurface() { } + virtual void unlock() = 0; + virtual void clear() = 0; + virtual void blitTo(LockedSurface* dest, int x, int y) const = 0; + }; + +} // namespace she + +#endif diff --git a/src/she/scoped_handle.h b/src/she/scoped_handle.h new file mode 100644 index 000000000..4c4a85816 --- /dev/null +++ b/src/she/scoped_handle.h @@ -0,0 +1,30 @@ +// SHE library +// Copyright (C) 2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef SHE_SCOPED_HANDLE_H_INCLUDED +#define SHE_SCOPED_HANDLE_H_INCLUDED + +namespace she { + + template + class ScopedHandle { + public: + ScopedHandle(T* handle) : m_handle(handle) { } + ~ScopedHandle() { m_handle->dispose(); } + + T* operator->() { return m_handle; } + operator T*() { return m_handle; } + private: + T* m_handle; + + // Cannot copy + ScopedHandle(const ScopedHandle&); + ScopedHandle& operator=(const ScopedHandle&); + }; + +} // namespace she + +#endif diff --git a/src/she/scoped_surface_lock.h b/src/she/scoped_surface_lock.h new file mode 100644 index 000000000..af66d8ccc --- /dev/null +++ b/src/she/scoped_surface_lock.h @@ -0,0 +1,28 @@ +// SHE library +// Copyright (C) 2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef SHE_SCOPED_SURFACE_LOCK_H_INCLUDED +#define SHE_SCOPED_SURFACE_LOCK_H_INCLUDED + +#include "she/surface.h" +#include "she/locked_surface.h" + +namespace she { + + class ScopedSurfaceLock { + public: + ScopedSurfaceLock(Surface* surface) : m_lock(surface->lock()) { } + ~ScopedSurfaceLock() { m_lock->unlock(); } + + LockedSurface* operator->() { return m_lock; } + operator LockedSurface*() { return m_lock; } + private: + LockedSurface* m_lock; + }; + +} // namespace she + +#endif diff --git a/src/she/she.h b/src/she/she.h index b0004212a..a8cb6eada 100644 --- a/src/she/she.h +++ b/src/she/she.h @@ -7,29 +7,11 @@ #ifndef SHE_H_INCLUDED #define SHE_H_INCLUDED -namespace she { - - class System { - public: - virtual ~System() { } - virtual void dispose() = 0; - }; - - System* CreateSystem(); - - template - class ScopedHandle { - public: - ScopedHandle(T* handle) : m_handle(handle) { } - ~ScopedHandle() { m_handle->dispose(); } - private: - T* m_handle; - - // Cannot copy - ScopedHandle(const ScopedHandle&); - ScopedHandle& operator=(const ScopedHandle&); - }; - -} // namespace she +#include "she/display.h" +#include "she/locked_surface.h" +#include "she/scoped_handle.h" +#include "she/scoped_surface_lock.h" +#include "she/surface.h" +#include "she/system.h" #endif diff --git a/src/she/she_alleg4.cpp b/src/she/she_alleg4.cpp index 666a41951..3d71f8fa7 100644 --- a/src/she/she_alleg4.cpp +++ b/src/she/she_alleg4.cpp @@ -11,12 +11,246 @@ #include "she.h" #include +#ifdef ALLEGRO_WINDOWS + #include +#endif #include "loadpng.h" #include +#define DISPLAY_FLAG_FULL_REFRESH 1 +#define DISPLAY_FLAG_WINDOW_RESIZE 2 + +static volatile int display_flags = 0; +static volatile int original_width = 0; +static volatile int original_height = 0; + +// Used by set_display_switch_callback(SWITCH_IN, ...). +static void display_switch_in_callback() +{ + display_flags |= DISPLAY_FLAG_FULL_REFRESH; +} + +END_OF_STATIC_FUNCTION(display_switch_in_callback); + +#ifdef ALLEGRO4_WITH_RESIZE_PATCH +// Called when the window is resized +static void resize_callback(RESIZE_DISPLAY_EVENT* ev) +{ + if (ev->is_maximized) { + original_width = ev->old_w; + original_height = ev->old_h; + } + display_flags |= DISPLAY_FLAG_WINDOW_RESIZE; +} +#endif // ALLEGRO4_WITH_RESIZE_PATCH + namespace she { +class Alleg4Surface : public Surface + , public LockedSurface { +public: + Alleg4Surface(BITMAP* bmp) + : m_bmp(bmp) + , m_destroy(false) + { + } + + Alleg4Surface(int width, int height) + : m_bmp(create_bitmap(width, height)) + , m_destroy(true) + { + } + + ~Alleg4Surface() { + if (m_destroy) + destroy_bitmap(m_bmp); + } + + // Surface implementation + + void dispose() { + delete this; + } + + int width() const { + return m_bmp->w; + } + + int height() const { + return m_bmp->h; + } + + LockedSurface* lock() { + acquire_bitmap(m_bmp); + return this; + } + + void* nativeHandle() { + return reinterpret_cast(m_bmp); + } + + // LockedSurface implementation + + void unlock() { + release_bitmap(m_bmp); + } + + void clear() { + clear_to_color(m_bmp, 0); + } + + void blitTo(LockedSurface* dest, int x, int y) const { + ASSERT(m_bmp); + ASSERT(dest); + ASSERT(static_cast(dest)->m_bmp); + + blit(m_bmp, + static_cast(dest)->m_bmp, + 0, 0, + x, y, + m_bmp->w, m_bmp->h); + } + +private: + BITMAP* m_bmp; + bool m_destroy; +}; + +class Alleg4Display : public Display { +public: + Alleg4Display(int width, int height, int scale) + : m_surface(NULL) + , m_scale(0) { + if (install_mouse() < 0) throw DisplayCreationException(allegro_error); + if (install_keyboard() < 0) throw DisplayCreationException(allegro_error); + +#ifdef FULLSCREEN_PLATFORM + set_color_depth(16); // TODO Try all color depths for fullscreen platforms +#else + set_color_depth(desktop_color_depth()); +#endif + + if (set_gfx_mode( +#ifdef FULLSCREEN_PLATFORM + GFX_AUTODETECT_FULLSCREEN, +#else + GFX_AUTODETECT_WINDOWED, +#endif + width, height, 0, 0) < 0) + throw DisplayCreationException(allegro_error); + + setScale(scale); + + // Add a hook to display-switch so when the user returns to the + // screen it's completelly refreshed/redrawn. + LOCK_VARIABLE(display_flags); + LOCK_FUNCTION(display_switch_in_callback); + set_display_switch_callback(SWITCH_IN, display_switch_in_callback); + +#ifdef ALLEGRO4_WITH_RESIZE_PATCH + // Setup the handler for window-resize events + set_resize_callback(resize_callback); +#endif + } + + ~Alleg4Display() { + m_surface->dispose(); + set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); + } + + void dispose() { + delete this; + } + + int width() const { + return SCREEN_W; + } + + int height() const { + return SCREEN_H; + } + + int originalWidth() const { + return original_width > 0 ? original_width: width(); + } + + int originalHeight() const { + return original_height > 0 ? original_height: height(); + } + + void setScale(int scale) { + ASSERT(scale >= 1); + + if (m_scale == scale) + return; + + m_scale = scale; + Surface* newSurface = new Alleg4Surface(SCREEN_W/m_scale, + SCREEN_H/m_scale); + if (m_surface) + m_surface->dispose(); + m_surface = newSurface; + } + + Surface* getSurface() { + return m_surface; + } + + bool flip() { +#ifdef ALLEGRO4_WITH_RESIZE_PATCH + if (display_flags & DISPLAY_FLAG_WINDOW_RESIZE) { + display_flags ^= DISPLAY_FLAG_WINDOW_RESIZE; + + acknowledge_resize(); + + int scale = m_scale; + m_scale = 0; + setScale(scale); + return false; + } +#endif + + BITMAP* bmp = reinterpret_cast(m_surface->nativeHandle()); + if (m_scale == 1) { + blit(bmp, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); + } + else { + stretch_blit(bmp, screen, + 0, 0, bmp->w, bmp->h, + 0, 0, SCREEN_W, SCREEN_H); + } + + return true; + } + + void maximize() { +#ifdef WIN32 + ::ShowWindow(win_get_window(), SW_MAXIMIZE); +#endif + } + + bool isMaximized() const { +#ifdef WIN32 + return (::GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false); +#else + return false; +#endif + } + + void* nativeHandle() { +#ifdef WIN32 + return reinterpret_cast(win_get_window()); +#else + return NULL; +#endif + } + +private: + Surface* m_surface; + int m_scale; +}; + class Alleg4System : public System { public: Alleg4System() { @@ -37,12 +271,31 @@ public: delete this; } + Capabilities capabilities() const { + return kCanResizeDisplayCapability; + } + + Display* createDisplay(int width, int height, int scale) { + return new Alleg4Display(width, height, scale); + } + + Surface* createSurface(int width, int height) { + return new Alleg4Surface(width, height); + } + }; +static System* g_instance; + System* CreateSystem() { - return new Alleg4System(); + return g_instance = new Alleg4System(); } - + +System* Instance() +{ + return g_instance; +} + } #ifdef main diff --git a/src/she/surface.h b/src/she/surface.h new file mode 100644 index 000000000..de1a56f8b --- /dev/null +++ b/src/she/surface.h @@ -0,0 +1,26 @@ +// SHE library +// Copyright (C) 2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef SHE_SURFACE_H_INCLUDED +#define SHE_SURFACE_H_INCLUDED + +namespace she { + + class LockedSurface; + + class Surface { + public: + virtual ~Surface() { } + virtual void dispose() = 0; + virtual int width() const = 0; + virtual int height() const = 0; + virtual LockedSurface* lock() = 0; + virtual void* nativeHandle() = 0; + }; + +} // namespace she + +#endif diff --git a/src/she/system.h b/src/she/system.h new file mode 100644 index 000000000..a73f0f7b2 --- /dev/null +++ b/src/she/system.h @@ -0,0 +1,38 @@ +// SHE library +// Copyright (C) 2012 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef SHE_SYSTEM_H_INCLUDED +#define SHE_SYSTEM_H_INCLUDED + +#include "she/capabilities.h" +#include + +namespace she { + + class Surface; + class Display; + + class DisplayCreationException : std::runtime_error { + public: + DisplayCreationException(const char* msg) throw() + : std::runtime_error(msg) { } + }; + + class System { + public: + virtual ~System() { } + virtual void dispose() = 0; + virtual Capabilities capabilities() const = 0; + virtual Display* createDisplay(int width, int height, int scale) = 0; + virtual Surface* createSurface(int width, int height) = 0; + }; + + System* CreateSystem(); + System* Instance(); + +} // namespace she + +#endif diff --git a/src/ui/draw.cpp b/src/ui/draw.cpp index 79f524aa8..37d231333 100644 --- a/src/ui/draw.cpp +++ b/src/ui/draw.cpp @@ -203,12 +203,6 @@ void ji_move_region(JRegion region, int dx, int dy) int c, nrects = JI_REGION_NUM_RECTS(region); JRect rc; - if (ji_dirty_region) { - jregion_translate(region, dx, dy); - ji_add_dirty_region(region); - jregion_translate(region, -dx, -dy); - } - // Blit directly screen to screen. if (is_linear_bitmap(ji_screen) && nrects == 1) { rc = JI_REGION_RECTS(region); diff --git a/src/ui/manager.cpp b/src/ui/manager.cpp index 54a8056fa..57624625b 100644 --- a/src/ui/manager.cpp +++ b/src/ui/manager.cpp @@ -112,9 +112,6 @@ Manager::Manager() : Widget(JI_MANAGER) { if (!m_defaultManager) { - if (!ji_screen) - ji_set_screen(screen, SCREEN_W, SCREEN_H); - // Hook the window close message want_close_stage = STAGE_NORMAL; set_close_button_callback(allegro_window_close_hook); @@ -1102,10 +1099,6 @@ void Manager::pumpQueue() if (msg->type == JM_DRAW) { set_clip_rect(ji_screen, 0, 0, JI_SCREEN_W-1, JI_SCREEN_H-1); - /* dirty rectangles */ - if (ji_dirty_region) - ji_add_dirty_rect(&msg->draw.rect); - release_bitmap(ji_screen); jmouse_show(); } diff --git a/src/ui/manager.h b/src/ui/manager.h index a3acd38ee..47f71c797 100644 --- a/src/ui/manager.h +++ b/src/ui/manager.h @@ -10,6 +10,8 @@ #include "base/compiler_specific.h" #include "ui/widget.h" +namespace she { class Display; } + namespace ui { class LayoutIO; @@ -24,6 +26,9 @@ namespace ui { Manager(); ~Manager(); + she::Display* getDisplay() { return m_display; } + void setDisplay(she::Display* display) { m_display = display; } + void run(); // Returns true if there are messages in the queue to be @@ -85,6 +90,7 @@ namespace ui { static Manager* m_defaultManager; WidgetsList m_garbage; + she::Display* m_display; }; } // namespace ui diff --git a/src/ui/paint_event.cpp b/src/ui/paint_event.cpp index 4dc302097..e691057dc 100644 --- a/src/ui/paint_event.cpp +++ b/src/ui/paint_event.cpp @@ -24,8 +24,8 @@ PaintEvent::~PaintEvent() Graphics* PaintEvent::getGraphics() { - // If someone requests the graphics pointer, it means that this - // "someone" will paint something. + // If someone requested the graphics pointer, it means that this + // "someone" has painted the widget. m_painted = true; return m_graphics; } diff --git a/src/ui/system.cpp b/src/ui/system.cpp index e27033c18..f2484441e 100644 --- a/src/ui/system.cpp +++ b/src/ui/system.cpp @@ -6,6 +6,17 @@ #include "config.h" +#include "ui/system.h" + +#include "she/display.h" +#include "she/surface.h" +#include "ui/intern.h" +#include "ui/manager.h" +#include "ui/rect.h" +#include "ui/region.h" +#include "ui/theme.h" +#include "ui/widget.h" + #include #if defined(ALLEGRO_WINDOWS) #include @@ -13,19 +24,11 @@ #include #endif -#include "ui/intern.h" -#include "ui/manager.h" -#include "ui/rect.h" -#include "ui/region.h" -#include "ui/system.h" -#include "ui/theme.h" -#include "ui/widget.h" - namespace ui { /* Global output bitmap. */ -BITMAP *ji_screen = NULL; +BITMAP* ji_screen = NULL; JRegion ji_dirty_region = NULL; int ji_screen_w = 0; int ji_screen_h = 0; @@ -83,9 +86,6 @@ static void set_cursor(BITMAP *bmp, int x, int y) int _ji_system_init() { - /* Update screen pointer. */ - ji_set_screen(screen, SCREEN_W, SCREEN_H); - /* Install timer related stuff. */ LOCK_VARIABLE(ji_clock); LOCK_VARIABLE(m_b); @@ -105,103 +105,38 @@ int _ji_system_init() void _ji_system_exit() { - ji_set_screen(NULL, 0, 0); + SetDisplay(NULL); remove_int(clock_inc); } -void ji_set_screen(BITMAP *bmp, int width, int height) +void SetDisplay(she::Display* display) { - int cursor = jmouse_get_cursor(); /* get mouse cursor */ + int cursor = jmouse_get_cursor(); jmouse_set_cursor(JI_CURSOR_NULL); - ji_screen = bmp; - ji_screen_w = width; - ji_screen_h = height; + ji_screen = (display ? reinterpret_cast(display->getSurface()->nativeHandle()): NULL); + ji_screen_w = (ji_screen ? ji_screen->w: 0); + ji_screen_h = (ji_screen ? ji_screen->h: 0); if (ji_screen != NULL) { Manager* manager = Manager::getDefault(); + if (manager) { + manager->setDisplay(display); - /* update default-manager size */ - if (manager && (jrect_w(manager->rc) != JI_SCREEN_W || - jrect_h(manager->rc) != JI_SCREEN_H)) { - JRect rect = jrect_new(0, 0, JI_SCREEN_W, JI_SCREEN_H); - jwidget_set_rect(manager, rect); - jrect_free(rect); - - if (ji_dirty_region) - jregion_reset(ji_dirty_region, manager->rc); + // Update default-manager size + if ((jrect_w(manager->rc) != JI_SCREEN_W || + jrect_h(manager->rc) != JI_SCREEN_H)) { + JRect rect = jrect_new(0, 0, JI_SCREEN_W, JI_SCREEN_H); + jwidget_set_rect(manager, rect); + jrect_free(rect); + } } jmouse_set_cursor(cursor); /* restore mouse cursor */ } } -void ji_add_dirty_rect(JRect rect) -{ - JRegion reg1; - - ASSERT(ji_dirty_region != NULL); - - reg1 = jregion_new(rect, 1); - jregion_union(ji_dirty_region, ji_dirty_region, reg1); - jregion_free(reg1); -} - -void ji_add_dirty_region(JRegion region) -{ - ASSERT(ji_dirty_region != NULL); - - jregion_union(ji_dirty_region, ji_dirty_region, region); -} - -void ji_flip_dirty_region() -{ - int c, nrects; - JRect rc; - - ASSERT(ji_dirty_region != NULL); - - nrects = JI_REGION_NUM_RECTS(ji_dirty_region); - - if (nrects == 1) { - rc = JI_REGION_RECTS(ji_dirty_region); - ji_flip_rect(rc); - } - else if (nrects > 1) { - for (c=0, rc=JI_REGION_RECTS(ji_dirty_region); - cx1, rect->y1, - rect->x1, rect->y1, - jrect_w(rect), - jrect_h(rect)); - } - else { - stretch_blit(ji_screen, screen, - rect->x1, - rect->y1, - jrect_w(rect), - jrect_h(rect), - rect->x1 * SCREEN_W / JI_SCREEN_W, - rect->y1 * SCREEN_H / JI_SCREEN_H, - jrect_w(rect) * SCREEN_W / JI_SCREEN_W, - jrect_h(rect) * SCREEN_H / JI_SCREEN_H); - } -} - int jmouse_get_cursor() { return m_cursor; @@ -257,10 +192,6 @@ void jmouse_draw_cursor() ji_get_default_manager()->invalidateRect(rect); /* rectfill(ji_screen, rect->x1, rect->y1, rect->x2-1, rect->y2-1, makecol(0, 0, 255)); */ draw_sprite(ji_screen, sprite_cursor, x, y); - - if (ji_dirty_region) - ji_add_dirty_rect(rect); - jrect_free(rect); } #endif @@ -273,14 +204,6 @@ void jmouse_draw_cursor() capture_covered_area(); draw_sprite(ji_screen, sprite_cursor, x, y); - - if (ji_dirty_region) { - JRect rect = jrect_new(x, y, - x+sprite_cursor->w, - y+sprite_cursor->h); - ji_add_dirty_rect(rect); - jrect_free(rect); - } } } diff --git a/src/ui/system.h b/src/ui/system.h index b025bd4f9..85df4efb2 100644 --- a/src/ui/system.h +++ b/src/ui/system.h @@ -12,6 +12,8 @@ struct BITMAP; +namespace she { class Display; } + namespace ui { /***********************************************************************/ @@ -20,17 +22,11 @@ namespace ui { #define JI_SCREEN_W ji_screen_w #define JI_SCREEN_H ji_screen_h - extern struct BITMAP *ji_screen; - extern JRegion ji_dirty_region; + extern struct BITMAP* ji_screen; extern int ji_screen_w; extern int ji_screen_h; - void ji_set_screen(BITMAP *bmp, int width, int height); - - void ji_add_dirty_rect(JRect rect); - void ji_add_dirty_region(JRegion region); - void ji_flip_dirty_region(); - void ji_flip_rect(JRect rect); + void SetDisplay(she::Display* display); /***********************************************************************/ /* timer related */