mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-16 10:20:50 +00:00
Fix visual artifacts on Windows when the window is resized
Now when the user resizes the OS window (a she::Display), it generates a kDisplayResize she::Event, and this is processed by the UI layer to redraw the entire ui::Manager. With this change we remove the obscure "bool" return value in she::Display::flip() member function.
This commit is contained in:
parent
f2d5242ff3
commit
32b12d17da
@ -792,6 +792,11 @@ static BITMAP *gfx_directx_acknowledge_resize(void)
|
||||
|
||||
_enter_gfx_critical();
|
||||
|
||||
/* Copy current content in screen */
|
||||
BITMAP* tmp = create_bitmap_ex(color_depth, w, h);
|
||||
clear_bitmap(tmp);
|
||||
blit(gfx_directx_forefront_bitmap, tmp, 0, 0, 0, 0, w, h);
|
||||
|
||||
/* Destroy old screen */
|
||||
destroy_bitmap(gfx_directx_forefront_bitmap);
|
||||
_destroy_directx_forefront_bitmap_extras();
|
||||
@ -799,6 +804,11 @@ static BITMAP *gfx_directx_acknowledge_resize(void)
|
||||
/* Re-create the screen */
|
||||
new_screen = _create_directx_forefront_bitmap(w, h, color_depth);
|
||||
|
||||
/* Restore content in the new screen */
|
||||
clear_bitmap(new_screen);
|
||||
blit(tmp, new_screen, 0, 0, 0, 0, w, h);
|
||||
destroy_bitmap(tmp);
|
||||
|
||||
_exit_gfx_critical();
|
||||
|
||||
return new_screen;
|
||||
|
@ -311,7 +311,7 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
|
||||
{
|
||||
switch (msg->type()) {
|
||||
|
||||
case kCloseAppMessage:
|
||||
case kCloseDisplayMessage:
|
||||
{
|
||||
// Execute the "Exit" command.
|
||||
Command* command = CommandsModule::instance()->getCommandByName(CommandId::Exit);
|
||||
|
@ -7,6 +7,7 @@ set(SHE_SOURCES)
|
||||
# Allegro 4 backend
|
||||
|
||||
if(USE_ALLEG4_BACKEND)
|
||||
add_definitions(-DUSE_KEY_POLLER)
|
||||
if(WIN32)
|
||||
find_package(DXGuid)
|
||||
if(NOT DXGUID_FOUND)
|
||||
@ -17,11 +18,15 @@ if(USE_ALLEG4_BACKEND)
|
||||
endif()
|
||||
endif()
|
||||
include_directories(SYSTEM ${DXGUID_INCLUDE_DIR})
|
||||
else()
|
||||
add_definitions(-DUSE_MOUSE_POLLER)
|
||||
endif()
|
||||
|
||||
list(APPEND SHE_SOURCES
|
||||
alleg4/alleg_display.cpp
|
||||
alleg4/alleg_surface.cpp
|
||||
alleg4/clock.cpp
|
||||
alleg4/close_button.cpp
|
||||
alleg4/display_events.cpp
|
||||
alleg4/key_poller.cpp
|
||||
alleg4/mouse_poller.cpp
|
||||
alleg4/she.cpp)
|
||||
|
604
src/she/alleg4/alleg_display.cpp
Normal file
604
src/she/alleg4/alleg_display.cpp
Normal file
@ -0,0 +1,604 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/she.h"
|
||||
|
||||
#include "base/concurrent_queue.h"
|
||||
#include "base/exception.h"
|
||||
#include "base/string.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "she/alleg4/alleg_display.h"
|
||||
#include "she/alleg4/alleg_surface.h"
|
||||
#include "she/common/system.h"
|
||||
#include "she/logger.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <allegro/internal/aintern.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winalleg.h>
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <commctrl.h>
|
||||
|
||||
#if defined STRICT || defined __GNUC__
|
||||
typedef WNDPROC wndproc_t;
|
||||
#else
|
||||
typedef FARPROC wndproc_t;
|
||||
#endif
|
||||
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
|
||||
#elif defined ALLEGRO_UNIX
|
||||
|
||||
#include <xalleg.h>
|
||||
#ifdef None
|
||||
#undef None
|
||||
#define X11_None 0L
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "loadpng.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "she/alleg4/clock.h"
|
||||
#include "she/alleg4/display_events.h"
|
||||
|
||||
#ifdef USE_KEY_POLLER
|
||||
#include "she/alleg4/key_poller.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_MOUSE_POLLER
|
||||
#include "she/alleg4/mouse_poller.h"
|
||||
#endif
|
||||
|
||||
void* get_osx_window();
|
||||
|
||||
namespace she {
|
||||
|
||||
Alleg4Display* unique_display = NULL;
|
||||
int display_scale;
|
||||
|
||||
namespace {
|
||||
|
||||
#if _WIN32
|
||||
|
||||
wndproc_t base_wndproc = NULL;
|
||||
bool display_has_mouse = false;
|
||||
bool capture_mouse = false;
|
||||
|
||||
static LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
|
||||
case WM_DROPFILES: {
|
||||
HDROP hdrop = (HDROP)(wparam);
|
||||
Event::Files files;
|
||||
|
||||
int count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
|
||||
for (int index=0; index<count; ++index) {
|
||||
int length = DragQueryFile(hdrop, index, NULL, 0);
|
||||
if (length > 0) {
|
||||
std::vector<TCHAR> str(length+1);
|
||||
DragQueryFile(hdrop, index, &str[0], str.size());
|
||||
files.push_back(base::to_utf8(&str[0]));
|
||||
}
|
||||
}
|
||||
|
||||
DragFinish(hdrop);
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::DropFiles);
|
||||
ev.setFiles(files);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef USE_MOUSE_POLLER
|
||||
|
||||
case WM_MOUSEMOVE: {
|
||||
// Adjust capture
|
||||
if (capture_mouse) {
|
||||
if (GetCapture() != hwnd)
|
||||
SetCapture(hwnd);
|
||||
}
|
||||
else {
|
||||
if (GetCapture() == hwnd)
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
//PRINTF("GetCapture=%p hwnd=%p\n", GetCapture(), hwnd);
|
||||
|
||||
Event ev;
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
|
||||
if (!display_has_mouse) {
|
||||
display_has_mouse = true;
|
||||
|
||||
ev.setType(Event::MouseEnter);
|
||||
queue_event(ev);
|
||||
|
||||
// Track mouse to receive WM_MOUSELEAVE message.
|
||||
TRACKMOUSEEVENT tme;
|
||||
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
tme.dwFlags = TME_LEAVE;
|
||||
tme.hwndTrack = hwnd;
|
||||
_TrackMouseEvent(&tme);
|
||||
}
|
||||
|
||||
ev.setType(Event::MouseMove);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_NCMOUSEMOVE:
|
||||
case WM_MOUSELEAVE:
|
||||
if (display_has_mouse) {
|
||||
display_has_mouse = false;
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::MouseLeave);
|
||||
queue_event(ev);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseDown);
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONDOWN ? Event::LeftButton:
|
||||
msg == WM_RBUTTONDOWN ? Event::RightButton:
|
||||
msg == WM_MBUTTONDOWN ? Event::MiddleButton: Event::NoneButton);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseUp);
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONUP ? Event::LeftButton:
|
||||
msg == WM_RBUTTONUP ? Event::RightButton:
|
||||
msg == WM_MBUTTONUP ? Event::MiddleButton: Event::NoneButton);
|
||||
queue_event(ev);
|
||||
|
||||
// Avoid popup menu for scrollbars
|
||||
if (msg == WM_RBUTTONUP)
|
||||
return 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
case WM_RBUTTONDBLCLK: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseDoubleClick);
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONDBLCLK ? Event::LeftButton:
|
||||
msg == WM_RBUTTONDBLCLK ? Event::RightButton:
|
||||
msg == WM_MBUTTONDBLCLK ? Event::MiddleButton: Event::NoneButton);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_MOUSEHWHEEL: {
|
||||
POINT pos = { GET_X_LPARAM(lparam),
|
||||
GET_Y_LPARAM(lparam) };
|
||||
ScreenToClient(hwnd, &pos);
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::MouseWheel);
|
||||
ev.setPosition(gfx::Point(pos.x, pos.y) / display_scale);
|
||||
|
||||
int z = ((short)HIWORD(wparam)) / WHEEL_DELTA;
|
||||
gfx::Point delta(
|
||||
(msg == WM_MOUSEHWHEEL ? z: 0),
|
||||
(msg == WM_MOUSEWHEEL ? -z: 0));
|
||||
ev.setWheelDelta(delta);
|
||||
|
||||
//PRINTF("WHEEL: %d %d\n", delta.x, delta.y);
|
||||
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_HSCROLL:
|
||||
case WM_VSCROLL: {
|
||||
POINT pos;
|
||||
GetCursorPos(&pos);
|
||||
ScreenToClient(hwnd, &pos);
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::MouseWheel);
|
||||
ev.setPosition(gfx::Point(pos.x, pos.y) / display_scale);
|
||||
|
||||
int bar = (msg == WM_HSCROLL ? SB_HORZ: SB_VERT);
|
||||
int z = GetScrollPos(hwnd, bar);
|
||||
|
||||
switch (LOWORD(wparam)) {
|
||||
case SB_LEFT:
|
||||
case SB_LINELEFT:
|
||||
--z;
|
||||
break;
|
||||
case SB_PAGELEFT:
|
||||
z -= 2;
|
||||
break;
|
||||
case SB_RIGHT:
|
||||
case SB_LINERIGHT:
|
||||
++z;
|
||||
break;
|
||||
case SB_PAGERIGHT:
|
||||
z += 2;
|
||||
break;
|
||||
case SB_THUMBPOSITION:
|
||||
case SB_THUMBTRACK:
|
||||
case SB_ENDSCROLL:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
gfx::Point delta(
|
||||
(msg == WM_HSCROLL ? (z-50): 0),
|
||||
(msg == WM_VSCROLL ? (z-50): 0));
|
||||
ev.setWheelDelta(delta);
|
||||
|
||||
//PRINTF("SCROLL: %d %d\n", delta.x, delta.y);
|
||||
|
||||
SetScrollPos(hwnd, bar, 50, FALSE);
|
||||
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
case WM_NCCALCSIZE: {
|
||||
if (wparam) {
|
||||
// Scrollbars must be enabled and visible to get trackpad
|
||||
// events of old drivers. So we cannot use ShowScrollBar() to
|
||||
// hide them. This is a simple (maybe not so elegant)
|
||||
// solution: Expand the client area to we overlap the
|
||||
// scrollbars. In this way they are not visible, but we still
|
||||
// get their messages.
|
||||
NCCALCSIZE_PARAMS* cs = reinterpret_cast<NCCALCSIZE_PARAMS*>(lparam);
|
||||
cs->rgrc[0].right += GetSystemMetrics(SM_CYVSCROLL);
|
||||
cs->rgrc[0].bottom += GetSystemMetrics(SM_CYHSCROLL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_NCHITTEST: {
|
||||
LRESULT result = ::CallWindowProc(base_wndproc, hwnd, msg, wparam, lparam);
|
||||
gfx::Point pt(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
|
||||
|
||||
RECT rc;
|
||||
::GetClientRect(hwnd, &rc);
|
||||
::MapWindowPoints(hwnd, NULL, (POINT*)&rc, 2);
|
||||
gfx::Rect area(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
|
||||
|
||||
//PRINTF("NCHITTEST: %d %d - %d %d %d %d - %s\n", pt.x, pt.y, area.x, area.y, area.w, area.h, area.contains(pt) ? "true": "false");
|
||||
|
||||
// We ignore scrollbars so if the mouse is above them, we return
|
||||
// as it's in the window client or resize area. (Remember that
|
||||
// we have scroll bars are enabled and visible to receive
|
||||
// trackpad messages only.)
|
||||
if (result == HTHSCROLL) {
|
||||
result = (area.contains(pt) ? HTCLIENT: HTBOTTOM);
|
||||
}
|
||||
else if (result == HTVSCROLL) {
|
||||
result = (area.contains(pt) ? HTCLIENT: HTRIGHT);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
return ::CallWindowProc(base_wndproc, hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
void subclass_hwnd(HWND hwnd)
|
||||
{
|
||||
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_HSCROLL | WS_VSCROLL);
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_ACCEPTFILES);
|
||||
|
||||
SCROLLINFO si;
|
||||
si.cbSize = sizeof(SCROLLINFO);
|
||||
si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
|
||||
si.nMin = 0;
|
||||
si.nPos = 50;
|
||||
si.nMax = 100;
|
||||
si.nPage = 10;
|
||||
SetScrollInfo(hwnd, SB_HORZ, &si, FALSE);
|
||||
SetScrollInfo(hwnd, SB_VERT, &si, FALSE);
|
||||
|
||||
base_wndproc = (wndproc_t)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc);
|
||||
}
|
||||
|
||||
void unsubclass_hwnd(HWND hwnd)
|
||||
{
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)base_wndproc);
|
||||
base_wndproc = NULL;
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Alleg4Display::Alleg4Display(int width, int height, int scale)
|
||||
: m_surface(NULL)
|
||||
, m_scale(0)
|
||||
, m_nativeCursor(kNoCursor)
|
||||
, m_restoredWidth(0)
|
||||
, m_restoredHeight(0)
|
||||
{
|
||||
unique_display = this;
|
||||
|
||||
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);
|
||||
|
||||
show_mouse(NULL);
|
||||
setScale(scale);
|
||||
|
||||
#if _WIN32
|
||||
subclass_hwnd((HWND)nativeHandle());
|
||||
#endif
|
||||
}
|
||||
|
||||
Alleg4Display::~Alleg4Display()
|
||||
{
|
||||
unique_display = NULL;
|
||||
|
||||
#if _WIN32
|
||||
unsubclass_hwnd((HWND)nativeHandle());
|
||||
#endif
|
||||
|
||||
m_surface->dispose();
|
||||
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Alleg4Display::dispose()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
int Alleg4Display::width() const
|
||||
{
|
||||
return SCREEN_W;
|
||||
}
|
||||
|
||||
int Alleg4Display::height() const
|
||||
{
|
||||
return SCREEN_H;
|
||||
}
|
||||
|
||||
int Alleg4Display::originalWidth() const
|
||||
{
|
||||
return m_restoredWidth > 0 ? m_restoredWidth: width();
|
||||
}
|
||||
|
||||
int Alleg4Display::originalHeight() const
|
||||
{
|
||||
return m_restoredHeight > 0 ? m_restoredHeight: height();
|
||||
}
|
||||
|
||||
void Alleg4Display::setOriginalWidth(int width)
|
||||
{
|
||||
m_restoredWidth = width;
|
||||
}
|
||||
|
||||
void Alleg4Display::setOriginalHeight(int height)
|
||||
{
|
||||
m_restoredHeight = height;
|
||||
}
|
||||
|
||||
int Alleg4Display::scale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
void Alleg4Display::setScale(int scale)
|
||||
{
|
||||
ASSERT(scale >= 1);
|
||||
display_scale = scale;
|
||||
|
||||
if (m_scale == scale)
|
||||
return;
|
||||
|
||||
m_scale = scale;
|
||||
recreateSurface();
|
||||
}
|
||||
|
||||
void Alleg4Display::recreateSurface()
|
||||
{
|
||||
Surface* newSurface = new Alleg4Surface(
|
||||
SCREEN_W / m_scale,
|
||||
SCREEN_H / m_scale, Alleg4Surface::DeleteAndDestroy);
|
||||
if (m_surface)
|
||||
m_surface->dispose();
|
||||
m_surface = newSurface;
|
||||
}
|
||||
|
||||
NonDisposableSurface* Alleg4Display::getSurface()
|
||||
{
|
||||
return static_cast<NonDisposableSurface*>(m_surface);
|
||||
}
|
||||
|
||||
void Alleg4Display::flip()
|
||||
{
|
||||
if (is_display_resize_awaiting())
|
||||
return;
|
||||
|
||||
BITMAP* bmp = reinterpret_cast<BITMAP*>(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);
|
||||
}
|
||||
}
|
||||
|
||||
void Alleg4Display::maximize()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::ShowWindow(win_get_window(), SW_MAXIMIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Alleg4Display::isMaximized() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (::GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Alleg4Display::setTitleBar(const std::string& title)
|
||||
{
|
||||
set_window_title(title.c_str());
|
||||
}
|
||||
|
||||
NativeCursor Alleg4Display::nativeMouseCursor()
|
||||
{
|
||||
return m_nativeCursor;
|
||||
}
|
||||
|
||||
bool Alleg4Display::setNativeMouseCursor(NativeCursor cursor)
|
||||
{
|
||||
int newCursor = MOUSE_CURSOR_NONE;
|
||||
|
||||
switch (cursor) {
|
||||
case kNoCursor:
|
||||
newCursor = MOUSE_CURSOR_NONE;
|
||||
break;
|
||||
case kArrowCursor:
|
||||
newCursor = MOUSE_CURSOR_ARROW;
|
||||
break;
|
||||
case kIBeamCursor:
|
||||
newCursor = MOUSE_CURSOR_EDIT;
|
||||
break;
|
||||
case kWaitCursor:
|
||||
newCursor = MOUSE_CURSOR_BUSY;
|
||||
break;
|
||||
case kHelpCursor:
|
||||
newCursor = MOUSE_CURSOR_QUESTION;
|
||||
break;
|
||||
#ifdef ALLEGRO4_WITH_EXTRA_CURSORS
|
||||
case kForbiddenCursor: newCursor = MOUSE_CURSOR_FORBIDDEN; break;
|
||||
case kMoveCursor: newCursor = MOUSE_CURSOR_MOVE; break;
|
||||
case kLinkCursor: newCursor = MOUSE_CURSOR_LINK; break;
|
||||
case kSizeNSCursor: newCursor = MOUSE_CURSOR_SIZE_NS; break;
|
||||
case kSizeWECursor: newCursor = MOUSE_CURSOR_SIZE_WE; break;
|
||||
case kSizeNCursor: newCursor = MOUSE_CURSOR_SIZE_N; break;
|
||||
case kSizeNECursor: newCursor = MOUSE_CURSOR_SIZE_NE; break;
|
||||
case kSizeECursor: newCursor = MOUSE_CURSOR_SIZE_E; break;
|
||||
case kSizeSECursor: newCursor = MOUSE_CURSOR_SIZE_SE; break;
|
||||
case kSizeSCursor: newCursor = MOUSE_CURSOR_SIZE_S; break;
|
||||
case kSizeSWCursor: newCursor = MOUSE_CURSOR_SIZE_SW; break;
|
||||
case kSizeWCursor: newCursor = MOUSE_CURSOR_SIZE_W; break;
|
||||
case kSizeNWCursor: newCursor = MOUSE_CURSOR_SIZE_NW; break;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nativeCursor = cursor;
|
||||
return (show_os_cursor(newCursor) == 0);
|
||||
}
|
||||
|
||||
void Alleg4Display::setMousePosition(const gfx::Point& position)
|
||||
{
|
||||
position_mouse(
|
||||
m_scale * position.x,
|
||||
m_scale * position.y);
|
||||
}
|
||||
|
||||
void Alleg4Display::captureMouse()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
capture_mouse = true;
|
||||
|
||||
#elif defined(ALLEGRO_UNIX)
|
||||
|
||||
XGrabPointer(_xwin.display, _xwin.window, False,
|
||||
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
X11_None, X11_None, CurrentTime);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void Alleg4Display::releaseMouse()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
capture_mouse = false;
|
||||
|
||||
#elif defined(ALLEGRO_UNIX)
|
||||
|
||||
XUngrabPointer(_xwin.display, CurrentTime);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void* Alleg4Display::nativeHandle()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return reinterpret_cast<void*>(win_get_window());
|
||||
#elif defined __APPLE__
|
||||
return get_osx_window();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace she
|
54
src/she/alleg4/alleg_display.h
Normal file
54
src/she/alleg4/alleg_display.h
Normal file
@ -0,0 +1,54 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_ALLEG4_ALLEG_DISPLAY_H_INCLUDED
|
||||
#define SHE_ALLEG4_ALLEG_DISPLAY_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "she/display.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
class Alleg4Display : public Display {
|
||||
public:
|
||||
Alleg4Display(int width, int height, int scale);
|
||||
~Alleg4Display();
|
||||
|
||||
void dispose() override;
|
||||
int width() const override;
|
||||
int height() const override;
|
||||
int originalWidth() const override;
|
||||
int originalHeight() const override;
|
||||
void setOriginalWidth(int width);
|
||||
void setOriginalHeight(int height);
|
||||
int scale() const override;
|
||||
void setScale(int scale) override;
|
||||
void recreateSurface();
|
||||
NonDisposableSurface* getSurface() override;
|
||||
void flip() override;
|
||||
void maximize() override;
|
||||
bool isMaximized() const override;
|
||||
void setTitleBar(const std::string& title) override;
|
||||
NativeCursor nativeMouseCursor() override;
|
||||
bool setNativeMouseCursor(NativeCursor cursor) override;
|
||||
void setMousePosition(const gfx::Point& position) override;
|
||||
void captureMouse() override;
|
||||
void releaseMouse() override;
|
||||
void* nativeHandle() override;
|
||||
|
||||
private:
|
||||
Surface* m_surface;
|
||||
int m_scale;
|
||||
NativeCursor m_nativeCursor;
|
||||
int m_restoredWidth;
|
||||
int m_restoredHeight;
|
||||
};
|
||||
|
||||
extern Alleg4Display* unique_display;
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
391
src/she/alleg4/alleg_surface.cpp
Normal file
391
src/she/alleg4/alleg_surface.cpp
Normal file
@ -0,0 +1,391 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/alleg4/alleg_surface.h"
|
||||
|
||||
#include "base/string.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <allegro/internal/aintern.h>
|
||||
|
||||
namespace {
|
||||
|
||||
void checked_mode(int offset)
|
||||
{
|
||||
static BITMAP* pattern = NULL;
|
||||
int x, y, fg, bg;
|
||||
|
||||
if (offset < 0) {
|
||||
if (pattern) {
|
||||
destroy_bitmap(pattern);
|
||||
pattern = NULL;
|
||||
}
|
||||
drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pattern)
|
||||
pattern = create_bitmap(8, 8);
|
||||
|
||||
bg = makecol(0, 0, 0);
|
||||
fg = makecol(255, 255, 255);
|
||||
offset = 7 - (offset & 7);
|
||||
|
||||
clear_bitmap(pattern);
|
||||
|
||||
for (y=0; y<8; y++)
|
||||
for (x=0; x<8; x++)
|
||||
putpixel(pattern, x, y, ((x+y+offset)&7) < 4 ? fg: bg);
|
||||
|
||||
drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace she {
|
||||
|
||||
inline int to_allegro(int color_depth, gfx::Color color)
|
||||
{
|
||||
if (color_depth == 32) {
|
||||
return makeacol32(
|
||||
gfx::getr(color), gfx::getg(color), gfx::getb(color), gfx::geta(color));
|
||||
}
|
||||
else {
|
||||
if (gfx::is_transparent(color))
|
||||
return -1;
|
||||
else
|
||||
return makecol_depth(color_depth, gfx::getr(color), gfx::getg(color), gfx::getb(color));
|
||||
}
|
||||
}
|
||||
|
||||
inline gfx::Color from_allegro(int color_depth, int color)
|
||||
{
|
||||
return gfx::rgba(
|
||||
getr_depth(color_depth, color),
|
||||
getg_depth(color_depth, color),
|
||||
getb_depth(color_depth, color));
|
||||
}
|
||||
|
||||
Alleg4Surface::Alleg4Surface(BITMAP* bmp, DestroyFlag destroy)
|
||||
: m_bmp(bmp)
|
||||
, m_destroy(destroy)
|
||||
{
|
||||
}
|
||||
|
||||
Alleg4Surface::Alleg4Surface(int width, int height, DestroyFlag destroy)
|
||||
: m_bmp(create_bitmap(width, height))
|
||||
, m_destroy(destroy)
|
||||
{
|
||||
}
|
||||
|
||||
Alleg4Surface::Alleg4Surface(int width, int height, int bpp, DestroyFlag destroy)
|
||||
: m_bmp(create_bitmap_ex(bpp, width, height))
|
||||
, m_destroy(destroy)
|
||||
{
|
||||
}
|
||||
|
||||
Alleg4Surface::~Alleg4Surface()
|
||||
{
|
||||
if (m_destroy & DestroyHandle) {
|
||||
if (m_bmp)
|
||||
destroy_bitmap(m_bmp);
|
||||
}
|
||||
}
|
||||
|
||||
// Surface implementation
|
||||
|
||||
void Alleg4Surface::dispose()
|
||||
{
|
||||
if (m_destroy & DeleteThis)
|
||||
delete this;
|
||||
}
|
||||
|
||||
int Alleg4Surface::width() const
|
||||
{
|
||||
return m_bmp->w;
|
||||
}
|
||||
|
||||
int Alleg4Surface::height() const
|
||||
{
|
||||
return m_bmp->h;
|
||||
}
|
||||
|
||||
bool Alleg4Surface::isDirectToScreen() const
|
||||
{
|
||||
return m_bmp == screen;
|
||||
}
|
||||
|
||||
gfx::Rect Alleg4Surface::getClipBounds()
|
||||
{
|
||||
return gfx::Rect(
|
||||
m_bmp->cl,
|
||||
m_bmp->ct,
|
||||
m_bmp->cr - m_bmp->cl,
|
||||
m_bmp->cb - m_bmp->ct);
|
||||
}
|
||||
|
||||
void Alleg4Surface::setClipBounds(const gfx::Rect& rc)
|
||||
{
|
||||
set_clip_rect(m_bmp,
|
||||
rc.x,
|
||||
rc.y,
|
||||
rc.x+rc.w-1,
|
||||
rc.y+rc.h-1);
|
||||
}
|
||||
|
||||
bool Alleg4Surface::intersectClipRect(const gfx::Rect& rc)
|
||||
{
|
||||
add_clip_rect(m_bmp,
|
||||
rc.x,
|
||||
rc.y,
|
||||
rc.x+rc.w-1,
|
||||
rc.y+rc.h-1);
|
||||
|
||||
return
|
||||
(m_bmp->cl < m_bmp->cr &&
|
||||
m_bmp->ct < m_bmp->cb);
|
||||
}
|
||||
|
||||
LockedSurface* Alleg4Surface::lock()
|
||||
{
|
||||
acquire_bitmap(m_bmp);
|
||||
return this;
|
||||
}
|
||||
|
||||
void Alleg4Surface::setDrawMode(DrawMode mode, int param)
|
||||
{
|
||||
switch (mode) {
|
||||
case DrawMode::Solid: checked_mode(-1); break;
|
||||
case DrawMode::Xor: xor_mode(TRUE); break;
|
||||
case DrawMode::Checked: checked_mode(param); break;
|
||||
}
|
||||
}
|
||||
|
||||
void Alleg4Surface::applyScale(int scale)
|
||||
{
|
||||
if (scale < 2)
|
||||
return;
|
||||
|
||||
BITMAP* scaled =
|
||||
create_bitmap_ex(bitmap_color_depth(m_bmp),
|
||||
m_bmp->w*scale,
|
||||
m_bmp->h*scale);
|
||||
|
||||
for (int y=0; y<scaled->h; ++y)
|
||||
for (int x=0; x<scaled->w; ++x)
|
||||
putpixel(scaled, x, y, getpixel(m_bmp, x/scale, y/scale));
|
||||
|
||||
if (m_destroy & DestroyHandle)
|
||||
destroy_bitmap(m_bmp);
|
||||
|
||||
m_bmp = scaled;
|
||||
m_destroy = DestroyHandle;
|
||||
}
|
||||
|
||||
void* Alleg4Surface::nativeHandle()
|
||||
{
|
||||
return reinterpret_cast<void*>(m_bmp);
|
||||
}
|
||||
|
||||
// LockedSurface implementation
|
||||
|
||||
int Alleg4Surface::lockedWidth() const
|
||||
{
|
||||
return m_bmp->w;
|
||||
}
|
||||
|
||||
int Alleg4Surface::lockedHeight() const
|
||||
{
|
||||
return m_bmp->h;
|
||||
}
|
||||
|
||||
void Alleg4Surface::unlock()
|
||||
{
|
||||
release_bitmap(m_bmp);
|
||||
}
|
||||
|
||||
void Alleg4Surface::clear()
|
||||
{
|
||||
clear_to_color(m_bmp, 0);
|
||||
}
|
||||
|
||||
uint8_t* Alleg4Surface::getData(int x, int y) const
|
||||
{
|
||||
switch (bitmap_color_depth(m_bmp)) {
|
||||
case 8: return (uint8_t*)(((uint8_t*)bmp_write_line(m_bmp, y)) + x);
|
||||
case 15:
|
||||
case 16: return (uint8_t*)(((uint16_t*)bmp_write_line(m_bmp, y)) + x);
|
||||
case 24: return (uint8_t*)(((uint8_t*)bmp_write_line(m_bmp, y)) + x*3);
|
||||
case 32: return (uint8_t*)(((uint32_t*)bmp_write_line(m_bmp, y)) + x);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Alleg4Surface::getFormat(SurfaceFormatData* formatData) const
|
||||
{
|
||||
formatData->format = kRgbaSurfaceFormat;
|
||||
formatData->bitsPerPixel = bitmap_color_depth(m_bmp);
|
||||
|
||||
switch (formatData->bitsPerPixel) {
|
||||
case 8:
|
||||
formatData->redShift = 0;
|
||||
formatData->greenShift = 0;
|
||||
formatData->blueShift = 0;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 0;
|
||||
formatData->greenMask = 0;
|
||||
formatData->blueMask = 0;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 15:
|
||||
formatData->redShift = _rgb_r_shift_15;
|
||||
formatData->greenShift = _rgb_g_shift_15;
|
||||
formatData->blueShift = _rgb_b_shift_15;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 31 << _rgb_r_shift_15;
|
||||
formatData->greenMask = 31 << _rgb_g_shift_15;
|
||||
formatData->blueMask = 31 << _rgb_b_shift_15;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 16:
|
||||
formatData->redShift = _rgb_r_shift_16;
|
||||
formatData->greenShift = _rgb_g_shift_16;
|
||||
formatData->blueShift = _rgb_b_shift_16;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 31 << _rgb_r_shift_16;
|
||||
formatData->greenMask = 63 << _rgb_g_shift_16;
|
||||
formatData->blueMask = 31 << _rgb_b_shift_16;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 24:
|
||||
formatData->redShift = _rgb_r_shift_24;
|
||||
formatData->greenShift = _rgb_g_shift_24;
|
||||
formatData->blueShift = _rgb_b_shift_24;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 255 << _rgb_r_shift_24;
|
||||
formatData->greenMask = 255 << _rgb_g_shift_24;
|
||||
formatData->blueMask = 255 << _rgb_b_shift_24;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 32:
|
||||
formatData->redShift = _rgb_r_shift_32;
|
||||
formatData->greenShift = _rgb_g_shift_32;
|
||||
formatData->blueShift = _rgb_b_shift_32;
|
||||
formatData->alphaShift = _rgb_a_shift_32;
|
||||
formatData->redMask = 255 << _rgb_r_shift_32;
|
||||
formatData->greenMask = 255 << _rgb_g_shift_32;
|
||||
formatData->blueMask = 255 << _rgb_b_shift_32;
|
||||
formatData->alphaMask = 255 << _rgb_a_shift_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Color Alleg4Surface::getPixel(int x, int y) const
|
||||
{
|
||||
return from_allegro(
|
||||
bitmap_color_depth(m_bmp),
|
||||
getpixel(m_bmp, x, y));
|
||||
}
|
||||
|
||||
void Alleg4Surface::putPixel(gfx::Color color, int x, int y)
|
||||
{
|
||||
putpixel(m_bmp, x, y, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawHLine(gfx::Color color, int x, int y, int w)
|
||||
{
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
hline(m_bmp, x, y, x+w-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawVLine(gfx::Color color, int x, int y, int h)
|
||||
{
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
vline(m_bmp, x, y, y+h-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b)
|
||||
{
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
line(m_bmp, a.x, a.y, b.x, b.y, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawRect(gfx::Color color, const gfx::Rect& rc)
|
||||
{
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
rect(m_bmp, rc.x, rc.y, rc.x+rc.w-1, rc.y+rc.h-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void Alleg4Surface::fillRect(gfx::Color color, const gfx::Rect& rc)
|
||||
{
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
rectfill(m_bmp, rc.x, rc.y, rc.x+rc.w-1, rc.y+rc.h-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void Alleg4Surface::blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const
|
||||
{
|
||||
ASSERT(m_bmp);
|
||||
ASSERT(dest);
|
||||
ASSERT(static_cast<Alleg4Surface*>(dest)->m_bmp);
|
||||
|
||||
blit(m_bmp,
|
||||
static_cast<Alleg4Surface*>(dest)->m_bmp,
|
||||
srcx, srcy,
|
||||
dstx, dsty,
|
||||
width, height);
|
||||
}
|
||||
|
||||
void Alleg4Surface::scrollTo(const gfx::Rect& rc, int dx, int dy)
|
||||
{
|
||||
blit(m_bmp, m_bmp,
|
||||
rc.x, rc.y,
|
||||
rc.x+dx, rc.y+dy,
|
||||
rc.w, rc.h);
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawSurface(const LockedSurface* src, int dstx, int dsty)
|
||||
{
|
||||
draw_sprite(m_bmp, static_cast<const Alleg4Surface*>(src)->m_bmp, dstx, dsty);
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawRgbaSurface(const LockedSurface* src, int dstx, int dsty)
|
||||
{
|
||||
set_alpha_blender();
|
||||
draw_trans_sprite(m_bmp, static_cast<const Alleg4Surface*>(src)->m_bmp, dstx, dsty);
|
||||
}
|
||||
|
||||
} // namespace she
|
72
src/she/alleg4/alleg_surface.h
Normal file
72
src/she/alleg4/alleg_surface.h
Normal file
@ -0,0 +1,72 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_ALLEG4_ALLEG_SURFACE_H_INCLUDED
|
||||
#define SHE_ALLEG4_ALLEG_SURFACE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
#include "she/surface.h"
|
||||
#include "she/common/locked_surface.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
class Alleg4Surface : public Surface
|
||||
, public CommonLockedSurface {
|
||||
public:
|
||||
enum DestroyFlag {
|
||||
None = 0,
|
||||
DeleteThis = 1,
|
||||
DestroyHandle = 2,
|
||||
DeleteAndDestroy = DeleteThis | DestroyHandle,
|
||||
};
|
||||
|
||||
Alleg4Surface(BITMAP* bmp, DestroyFlag destroy);
|
||||
Alleg4Surface(int width, int height, DestroyFlag destroy);
|
||||
Alleg4Surface(int width, int height, int bpp, DestroyFlag destroy);
|
||||
~Alleg4Surface();
|
||||
|
||||
// Surface implementation
|
||||
void dispose() override;
|
||||
int width() const override;
|
||||
int height() const override;
|
||||
bool isDirectToScreen() const override;
|
||||
gfx::Rect getClipBounds() override;
|
||||
void setClipBounds(const gfx::Rect& rc) override;
|
||||
bool intersectClipRect(const gfx::Rect& rc) override;
|
||||
LockedSurface* lock() override;
|
||||
void setDrawMode(DrawMode mode, int param) override;
|
||||
void applyScale(int scale) override;
|
||||
void* nativeHandle() override;
|
||||
|
||||
// LockedSurface implementation
|
||||
int lockedWidth() const override;
|
||||
int lockedHeight() const override;
|
||||
void unlock() override;
|
||||
void clear() override;
|
||||
uint8_t* getData(int x, int y) const override;
|
||||
void getFormat(SurfaceFormatData* formatData) const override;
|
||||
gfx::Color getPixel(int x, int y) const override;
|
||||
void putPixel(gfx::Color color, int x, int y) override;
|
||||
void drawHLine(gfx::Color color, int x, int y, int w) override;
|
||||
void drawVLine(gfx::Color color, int x, int y, int h) override;
|
||||
void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) override;
|
||||
void drawRect(gfx::Color color, const gfx::Rect& rc) override;
|
||||
void fillRect(gfx::Color color, const gfx::Rect& rc) override;
|
||||
void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const override;
|
||||
void scrollTo(const gfx::Rect& rc, int dx, int dy) override;
|
||||
void drawSurface(const LockedSurface* src, int dstx, int dsty) override;
|
||||
void drawRgbaSurface(const LockedSurface* src, int dstx, int dsty) override;
|
||||
|
||||
private:
|
||||
BITMAP* m_bmp;
|
||||
DestroyFlag m_destroy;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -12,7 +12,7 @@
|
||||
#include <allegro/internal/aintern.h>
|
||||
#include <allegro/platform/aintosx.h>
|
||||
|
||||
#include "she/alleg4/internals.h"
|
||||
#include "she/alleg4/alleg_display.h"
|
||||
#include "she/event.h"
|
||||
#include "she/system.h"
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/alleg4/internals.h"
|
||||
#include "she/event.h"
|
||||
#include "she/system.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
namespace {
|
||||
|
||||
enum {
|
||||
STAGE_NORMAL,
|
||||
STAGE_WANT_CLOSE,
|
||||
};
|
||||
|
||||
// variable to handle the external close button in some Windows enviroments
|
||||
int want_close_stage;
|
||||
|
||||
// hooks the close-button in some platform with window support
|
||||
void allegro_window_close_hook()
|
||||
{
|
||||
if (want_close_stage == STAGE_NORMAL)
|
||||
want_close_stage = STAGE_WANT_CLOSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace she {
|
||||
|
||||
void close_button_init()
|
||||
{
|
||||
// Hook the window close message
|
||||
want_close_stage = STAGE_NORMAL;
|
||||
set_close_button_callback(allegro_window_close_hook);
|
||||
}
|
||||
|
||||
void close_button_generate_events()
|
||||
{
|
||||
// Generate Close message when the user press close button on the system window.
|
||||
if (want_close_stage == STAGE_WANT_CLOSE) {
|
||||
want_close_stage = STAGE_NORMAL;
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::CloseDisplay);
|
||||
ev.setDisplay(unique_display);
|
||||
queue_event(ev);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace she
|
@ -1,18 +0,0 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_ALLEG4_CLOSE_BUTTON_H_INCLUDED
|
||||
#define SHE_ALLEG4_CLOSE_BUTTON_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace she {
|
||||
|
||||
void close_button_init();
|
||||
void close_button_generate_events();
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
97
src/she/alleg4/display_events.cpp
Normal file
97
src/she/alleg4/display_events.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/alleg4/alleg_display.h"
|
||||
#include "she/display.h"
|
||||
#include "she/event.h"
|
||||
#include "she/system.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
namespace {
|
||||
|
||||
bool want_close = false;
|
||||
void close_callback() {
|
||||
want_close = true;
|
||||
}
|
||||
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
bool resized = false;
|
||||
int restored_width = 0;
|
||||
int restored_height = 0;
|
||||
|
||||
void resize_callback(RESIZE_DISPLAY_EVENT* ev) {
|
||||
if (ev->is_maximized) {
|
||||
restored_width = ev->old_w;
|
||||
restored_height = ev->old_h;
|
||||
}
|
||||
else {
|
||||
restored_width = 0;
|
||||
restored_height = 0;
|
||||
}
|
||||
resized = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
namespace she {
|
||||
|
||||
void display_events_init()
|
||||
{
|
||||
set_close_button_callback(close_callback);
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
set_resize_callback(resize_callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
void display_generate_events()
|
||||
{
|
||||
if (want_close) {
|
||||
want_close = false;
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::CloseDisplay);
|
||||
ev.setDisplay(unique_display);
|
||||
queue_event(ev);
|
||||
}
|
||||
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
if (resized) {
|
||||
resized = false;
|
||||
|
||||
acknowledge_resize();
|
||||
|
||||
Alleg4Display* display = unique_display;
|
||||
if (display) {
|
||||
display->setOriginalWidth(restored_width);
|
||||
display->setOriginalHeight(restored_height);
|
||||
display->recreateSurface();
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::ResizeDisplay);
|
||||
ev.setDisplay(display);
|
||||
queue_event(ev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_display_resize_awaiting()
|
||||
{
|
||||
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
|
||||
return resized;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace she
|
23
src/she/alleg4/display_events.h
Normal file
23
src/she/alleg4/display_events.h
Normal file
@ -0,0 +1,23 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_ALLEG4_DISPLAY_EVENTS_H_INCLUDED
|
||||
#define SHE_ALLEG4_DISPLAY_EVENTS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace she {
|
||||
|
||||
void display_events_init();
|
||||
void display_generate_events();
|
||||
|
||||
// Returns true if a resize event was received but the "screen"
|
||||
// variable wasn't recreated yet (i.e. acknowledge_resize() wasn't
|
||||
// called yet)
|
||||
bool is_display_resize_awaiting();
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_INTERNALS_H_INCLUDED
|
||||
#define SHE_INTERNALS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace she {
|
||||
|
||||
class Display;
|
||||
extern Display* unique_display;
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2014 David Capello
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -8,12 +8,12 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/alleg4/internals.h"
|
||||
#include "she/alleg4/alleg_display.h"
|
||||
#include "she/she.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
namespace {
|
||||
namespace {
|
||||
|
||||
static char old_readed_key[KEY_MAX]; // keyboard status of previous poll
|
||||
static unsigned key_repeated[KEY_MAX];
|
||||
@ -93,4 +93,3 @@ void key_poller_generate_events()
|
||||
}
|
||||
|
||||
} // namespace she
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/alleg4/internals.h"
|
||||
#include "she/alleg4/alleg_display.h"
|
||||
#include "she/clock.h"
|
||||
#include "she/display.h"
|
||||
#include "she/event.h"
|
||||
|
@ -14,18 +14,14 @@
|
||||
#include "base/exception.h"
|
||||
#include "base/string.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "she/alleg4/surface.h"
|
||||
#include "she/alleg4/alleg_display.h"
|
||||
#include "she/alleg4/alleg_surface.h"
|
||||
#include "she/common/system.h"
|
||||
#include "she/logger.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <allegro/internal/aintern.h>
|
||||
|
||||
#define USE_KEY_POLLER
|
||||
#ifndef _WIN32 // On Windows we generated events from the HWND procedure
|
||||
#define USE_MOUSE_POLLER
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winalleg.h>
|
||||
|
||||
@ -60,54 +56,23 @@
|
||||
#include <vector>
|
||||
|
||||
#include "she/alleg4/clock.h"
|
||||
#include "she/alleg4/close_button.h"
|
||||
|
||||
#include "she/alleg4/display_events.h"
|
||||
#ifdef USE_KEY_POLLER
|
||||
#include "she/alleg4/key_poller.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_MOUSE_POLLER
|
||||
#include "she/alleg4/mouse_poller.h"
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
static she::System* g_instance = nullptr;
|
||||
|
||||
void* get_osx_window();
|
||||
|
||||
namespace she {
|
||||
|
||||
class Alleg4EventQueue : public EventQueue {
|
||||
public:
|
||||
Alleg4EventQueue() {
|
||||
clock_init();
|
||||
close_button_init();
|
||||
display_events_init();
|
||||
|
||||
#ifdef USE_KEY_POLLER
|
||||
key_poller_init();
|
||||
@ -125,7 +90,7 @@ public:
|
||||
void getEvent(Event& event, bool canWait) override {
|
||||
(void)canWait; // Ignore this parameter
|
||||
|
||||
close_button_generate_events();
|
||||
display_generate_events();
|
||||
|
||||
#ifdef USE_KEY_POLLER
|
||||
key_poller_generate_events();
|
||||
@ -150,531 +115,6 @@ private:
|
||||
base::concurrent_queue<Event> m_events;
|
||||
};
|
||||
|
||||
Display* unique_display = NULL;
|
||||
int display_scale;
|
||||
|
||||
namespace {
|
||||
|
||||
#if _WIN32
|
||||
|
||||
wndproc_t base_wndproc = NULL;
|
||||
bool display_has_mouse = false;
|
||||
bool capture_mouse = false;
|
||||
|
||||
static LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
|
||||
case WM_DROPFILES: {
|
||||
HDROP hdrop = (HDROP)(wparam);
|
||||
Event::Files files;
|
||||
|
||||
int count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
|
||||
for (int index=0; index<count; ++index) {
|
||||
int length = DragQueryFile(hdrop, index, NULL, 0);
|
||||
if (length > 0) {
|
||||
std::vector<TCHAR> str(length+1);
|
||||
DragQueryFile(hdrop, index, &str[0], str.size());
|
||||
files.push_back(base::to_utf8(&str[0]));
|
||||
}
|
||||
}
|
||||
|
||||
DragFinish(hdrop);
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::DropFiles);
|
||||
ev.setFiles(files);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef USE_MOUSE_POLLER
|
||||
|
||||
case WM_MOUSEMOVE: {
|
||||
// Adjust capture
|
||||
if (capture_mouse) {
|
||||
if (GetCapture() != hwnd)
|
||||
SetCapture(hwnd);
|
||||
}
|
||||
else {
|
||||
if (GetCapture() == hwnd)
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
//PRINTF("GetCapture=%p hwnd=%p\n", GetCapture(), hwnd);
|
||||
|
||||
Event ev;
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
|
||||
if (!display_has_mouse) {
|
||||
display_has_mouse = true;
|
||||
|
||||
ev.setType(Event::MouseEnter);
|
||||
queue_event(ev);
|
||||
|
||||
// Track mouse to receive WM_MOUSELEAVE message.
|
||||
TRACKMOUSEEVENT tme;
|
||||
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
tme.dwFlags = TME_LEAVE;
|
||||
tme.hwndTrack = hwnd;
|
||||
_TrackMouseEvent(&tme);
|
||||
}
|
||||
|
||||
ev.setType(Event::MouseMove);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_NCMOUSEMOVE:
|
||||
case WM_MOUSELEAVE:
|
||||
if (display_has_mouse) {
|
||||
display_has_mouse = false;
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::MouseLeave);
|
||||
queue_event(ev);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseDown);
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONDOWN ? Event::LeftButton:
|
||||
msg == WM_RBUTTONDOWN ? Event::RightButton:
|
||||
msg == WM_MBUTTONDOWN ? Event::MiddleButton: Event::NoneButton);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseUp);
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONUP ? Event::LeftButton:
|
||||
msg == WM_RBUTTONUP ? Event::RightButton:
|
||||
msg == WM_MBUTTONUP ? Event::MiddleButton: Event::NoneButton);
|
||||
queue_event(ev);
|
||||
|
||||
// Avoid popup menu for scrollbars
|
||||
if (msg == WM_RBUTTONUP)
|
||||
return 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
case WM_RBUTTONDBLCLK: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseDoubleClick);
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / display_scale,
|
||||
GET_Y_LPARAM(lparam) / display_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONDBLCLK ? Event::LeftButton:
|
||||
msg == WM_RBUTTONDBLCLK ? Event::RightButton:
|
||||
msg == WM_MBUTTONDBLCLK ? Event::MiddleButton: Event::NoneButton);
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_MOUSEHWHEEL: {
|
||||
POINT pos = { GET_X_LPARAM(lparam),
|
||||
GET_Y_LPARAM(lparam) };
|
||||
ScreenToClient(hwnd, &pos);
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::MouseWheel);
|
||||
ev.setPosition(gfx::Point(pos.x, pos.y) / display_scale);
|
||||
|
||||
int z = ((short)HIWORD(wparam)) / WHEEL_DELTA;
|
||||
gfx::Point delta(
|
||||
(msg == WM_MOUSEHWHEEL ? z: 0),
|
||||
(msg == WM_MOUSEWHEEL ? -z: 0));
|
||||
ev.setWheelDelta(delta);
|
||||
|
||||
//PRINTF("WHEEL: %d %d\n", delta.x, delta.y);
|
||||
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_HSCROLL:
|
||||
case WM_VSCROLL: {
|
||||
POINT pos;
|
||||
GetCursorPos(&pos);
|
||||
ScreenToClient(hwnd, &pos);
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::MouseWheel);
|
||||
ev.setPosition(gfx::Point(pos.x, pos.y) / display_scale);
|
||||
|
||||
int bar = (msg == WM_HSCROLL ? SB_HORZ: SB_VERT);
|
||||
int z = GetScrollPos(hwnd, bar);
|
||||
|
||||
switch (LOWORD(wparam)) {
|
||||
case SB_LEFT:
|
||||
case SB_LINELEFT:
|
||||
--z;
|
||||
break;
|
||||
case SB_PAGELEFT:
|
||||
z -= 2;
|
||||
break;
|
||||
case SB_RIGHT:
|
||||
case SB_LINERIGHT:
|
||||
++z;
|
||||
break;
|
||||
case SB_PAGERIGHT:
|
||||
z += 2;
|
||||
break;
|
||||
case SB_THUMBPOSITION:
|
||||
case SB_THUMBTRACK:
|
||||
case SB_ENDSCROLL:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
gfx::Point delta(
|
||||
(msg == WM_HSCROLL ? (z-50): 0),
|
||||
(msg == WM_VSCROLL ? (z-50): 0));
|
||||
ev.setWheelDelta(delta);
|
||||
|
||||
//PRINTF("SCROLL: %d %d\n", delta.x, delta.y);
|
||||
|
||||
SetScrollPos(hwnd, bar, 50, FALSE);
|
||||
|
||||
queue_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
case WM_NCCALCSIZE: {
|
||||
if (wparam) {
|
||||
// Scrollbars must be enabled and visible to get trackpad
|
||||
// events of old drivers. So we cannot use ShowScrollBar() to
|
||||
// hide them. This is a simple (maybe not so elegant)
|
||||
// solution: Expand the client area to we overlap the
|
||||
// scrollbars. In this way they are not visible, but we still
|
||||
// get their messages.
|
||||
NCCALCSIZE_PARAMS* cs = reinterpret_cast<NCCALCSIZE_PARAMS*>(lparam);
|
||||
cs->rgrc[0].right += GetSystemMetrics(SM_CYVSCROLL);
|
||||
cs->rgrc[0].bottom += GetSystemMetrics(SM_CYHSCROLL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_NCHITTEST: {
|
||||
LRESULT result = ::CallWindowProc(base_wndproc, hwnd, msg, wparam, lparam);
|
||||
gfx::Point pt(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
|
||||
|
||||
RECT rc;
|
||||
::GetClientRect(hwnd, &rc);
|
||||
::MapWindowPoints(hwnd, NULL, (POINT*)&rc, 2);
|
||||
gfx::Rect area(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
|
||||
|
||||
//PRINTF("NCHITTEST: %d %d - %d %d %d %d - %s\n", pt.x, pt.y, area.x, area.y, area.w, area.h, area.contains(pt) ? "true": "false");
|
||||
|
||||
// We ignore scrollbars so if the mouse is above them, we return
|
||||
// as it's in the window client or resize area. (Remember that
|
||||
// we have scroll bars are enabled and visible to receive
|
||||
// trackpad messages only.)
|
||||
if (result == HTHSCROLL) {
|
||||
result = (area.contains(pt) ? HTCLIENT: HTBOTTOM);
|
||||
}
|
||||
else if (result == HTVSCROLL) {
|
||||
result = (area.contains(pt) ? HTCLIENT: HTRIGHT);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
return ::CallWindowProc(base_wndproc, hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
void subclass_hwnd(HWND hwnd)
|
||||
{
|
||||
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_HSCROLL | WS_VSCROLL);
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_ACCEPTFILES);
|
||||
|
||||
SCROLLINFO si;
|
||||
si.cbSize = sizeof(SCROLLINFO);
|
||||
si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
|
||||
si.nMin = 0;
|
||||
si.nPos = 50;
|
||||
si.nMax = 100;
|
||||
si.nPage = 10;
|
||||
SetScrollInfo(hwnd, SB_HORZ, &si, FALSE);
|
||||
SetScrollInfo(hwnd, SB_VERT, &si, FALSE);
|
||||
|
||||
base_wndproc = (wndproc_t)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc);
|
||||
}
|
||||
|
||||
void unsubclass_hwnd(HWND hwnd)
|
||||
{
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)base_wndproc);
|
||||
base_wndproc = NULL;
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class Alleg4Display : public Display {
|
||||
public:
|
||||
Alleg4Display(int width, int height, int scale)
|
||||
: m_surface(NULL)
|
||||
, m_scale(0)
|
||||
, m_nativeCursor(kNoCursor) {
|
||||
unique_display = this;
|
||||
|
||||
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);
|
||||
|
||||
show_mouse(NULL);
|
||||
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
|
||||
|
||||
#if _WIN32
|
||||
subclass_hwnd((HWND)nativeHandle());
|
||||
#endif
|
||||
}
|
||||
|
||||
~Alleg4Display() {
|
||||
unique_display = NULL;
|
||||
|
||||
#if _WIN32
|
||||
unsubclass_hwnd((HWND)nativeHandle());
|
||||
#endif
|
||||
|
||||
m_surface->dispose();
|
||||
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void dispose() override {
|
||||
delete this;
|
||||
}
|
||||
|
||||
int width() const override {
|
||||
return SCREEN_W;
|
||||
}
|
||||
|
||||
int height() const override {
|
||||
return SCREEN_H;
|
||||
}
|
||||
|
||||
int originalWidth() const override {
|
||||
return original_width > 0 ? original_width: width();
|
||||
}
|
||||
|
||||
int originalHeight() const override {
|
||||
return original_height > 0 ? original_height: height();
|
||||
}
|
||||
|
||||
void setScale(int scale) override {
|
||||
ASSERT(scale >= 1);
|
||||
display_scale = scale;
|
||||
|
||||
if (m_scale == scale)
|
||||
return;
|
||||
|
||||
m_scale = scale;
|
||||
Surface* newSurface = new Alleg4Surface(
|
||||
SCREEN_W / m_scale,
|
||||
SCREEN_H / m_scale, Alleg4Surface::DeleteAndDestroy);
|
||||
if (m_surface)
|
||||
m_surface->dispose();
|
||||
m_surface = newSurface;
|
||||
}
|
||||
|
||||
int scale() const override {
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
NonDisposableSurface* getSurface() override {
|
||||
return static_cast<NonDisposableSurface*>(m_surface);
|
||||
}
|
||||
|
||||
bool flip() override {
|
||||
#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<BITMAP*>(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() override {
|
||||
#ifdef _WIN32
|
||||
::ShowWindow(win_get_window(), SW_MAXIMIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isMaximized() const override {
|
||||
#ifdef _WIN32
|
||||
return (::GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setTitleBar(const std::string& title) override {
|
||||
set_window_title(title.c_str());
|
||||
}
|
||||
|
||||
NativeCursor nativeMouseCursor() override {
|
||||
return m_nativeCursor;
|
||||
}
|
||||
|
||||
bool setNativeMouseCursor(NativeCursor cursor) override {
|
||||
int newCursor = MOUSE_CURSOR_NONE;
|
||||
|
||||
switch (cursor) {
|
||||
case kNoCursor:
|
||||
newCursor = MOUSE_CURSOR_NONE;
|
||||
break;
|
||||
case kArrowCursor:
|
||||
newCursor = MOUSE_CURSOR_ARROW;
|
||||
break;
|
||||
case kIBeamCursor:
|
||||
newCursor = MOUSE_CURSOR_EDIT;
|
||||
break;
|
||||
case kWaitCursor:
|
||||
newCursor = MOUSE_CURSOR_BUSY;
|
||||
break;
|
||||
case kHelpCursor:
|
||||
newCursor = MOUSE_CURSOR_QUESTION;
|
||||
break;
|
||||
#ifdef ALLEGRO4_WITH_EXTRA_CURSORS
|
||||
case kForbiddenCursor: newCursor = MOUSE_CURSOR_FORBIDDEN; break;
|
||||
case kMoveCursor: newCursor = MOUSE_CURSOR_MOVE; break;
|
||||
case kLinkCursor: newCursor = MOUSE_CURSOR_LINK; break;
|
||||
case kSizeNSCursor: newCursor = MOUSE_CURSOR_SIZE_NS; break;
|
||||
case kSizeWECursor: newCursor = MOUSE_CURSOR_SIZE_WE; break;
|
||||
case kSizeNCursor: newCursor = MOUSE_CURSOR_SIZE_N; break;
|
||||
case kSizeNECursor: newCursor = MOUSE_CURSOR_SIZE_NE; break;
|
||||
case kSizeECursor: newCursor = MOUSE_CURSOR_SIZE_E; break;
|
||||
case kSizeSECursor: newCursor = MOUSE_CURSOR_SIZE_SE; break;
|
||||
case kSizeSCursor: newCursor = MOUSE_CURSOR_SIZE_S; break;
|
||||
case kSizeSWCursor: newCursor = MOUSE_CURSOR_SIZE_SW; break;
|
||||
case kSizeWCursor: newCursor = MOUSE_CURSOR_SIZE_W; break;
|
||||
case kSizeNWCursor: newCursor = MOUSE_CURSOR_SIZE_NW; break;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nativeCursor = cursor;
|
||||
return (show_os_cursor(newCursor) == 0);
|
||||
}
|
||||
|
||||
void setMousePosition(const gfx::Point& position) override {
|
||||
position_mouse(
|
||||
m_scale * position.x,
|
||||
m_scale * position.y);
|
||||
}
|
||||
|
||||
void captureMouse() {
|
||||
#ifdef _WIN32
|
||||
|
||||
capture_mouse = true;
|
||||
|
||||
#elif defined(ALLEGRO_UNIX)
|
||||
|
||||
XGrabPointer(_xwin.display, _xwin.window, False,
|
||||
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
X11_None, X11_None, CurrentTime);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void releaseMouse() {
|
||||
#ifdef _WIN32
|
||||
|
||||
capture_mouse = false;
|
||||
|
||||
#elif defined(ALLEGRO_UNIX)
|
||||
|
||||
XUngrabPointer(_xwin.display, CurrentTime);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void* nativeHandle() override {
|
||||
#ifdef _WIN32
|
||||
return reinterpret_cast<void*>(win_get_window());
|
||||
#elif defined __APPLE__
|
||||
return get_osx_window();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
Surface* m_surface;
|
||||
int m_scale;
|
||||
NativeCursor m_nativeCursor;
|
||||
};
|
||||
|
||||
class Alleg4System : public CommonSystem {
|
||||
public:
|
||||
Alleg4System()
|
||||
|
@ -1,375 +0,0 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_ALLEG4_SURFACE_H_INCLUDED
|
||||
#define SHE_ALLEG4_SURFACE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <allegro.h>
|
||||
#include <allegro/internal/aintern.h>
|
||||
|
||||
#include "base/string.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/common/locked_surface.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void checked_mode(int offset)
|
||||
{
|
||||
static BITMAP* pattern = NULL;
|
||||
int x, y, fg, bg;
|
||||
|
||||
if (offset < 0) {
|
||||
if (pattern) {
|
||||
destroy_bitmap(pattern);
|
||||
pattern = NULL;
|
||||
}
|
||||
drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pattern)
|
||||
pattern = create_bitmap(8, 8);
|
||||
|
||||
bg = makecol(0, 0, 0);
|
||||
fg = makecol(255, 255, 255);
|
||||
offset = 7 - (offset & 7);
|
||||
|
||||
clear_bitmap(pattern);
|
||||
|
||||
for (y=0; y<8; y++)
|
||||
for (x=0; x<8; x++)
|
||||
putpixel(pattern, x, y, ((x+y+offset)&7) < 4 ? fg: bg);
|
||||
|
||||
drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace she {
|
||||
|
||||
inline int to_allegro(int color_depth, gfx::Color color) {
|
||||
if (color_depth == 32) {
|
||||
return makeacol32(
|
||||
gfx::getr(color), gfx::getg(color), gfx::getb(color), gfx::geta(color));
|
||||
}
|
||||
else {
|
||||
if (gfx::is_transparent(color))
|
||||
return -1;
|
||||
else
|
||||
return makecol_depth(color_depth, gfx::getr(color), gfx::getg(color), gfx::getb(color));
|
||||
}
|
||||
}
|
||||
|
||||
inline gfx::Color from_allegro(int color_depth, int color) {
|
||||
return gfx::rgba(
|
||||
getr_depth(color_depth, color),
|
||||
getg_depth(color_depth, color),
|
||||
getb_depth(color_depth, color));
|
||||
}
|
||||
|
||||
class Alleg4Surface : public Surface
|
||||
, public CommonLockedSurface {
|
||||
public:
|
||||
enum DestroyFlag {
|
||||
None = 0,
|
||||
DeleteThis = 1,
|
||||
DestroyHandle = 2,
|
||||
DeleteAndDestroy = DeleteThis | DestroyHandle,
|
||||
};
|
||||
|
||||
Alleg4Surface(BITMAP* bmp, DestroyFlag destroy)
|
||||
: m_bmp(bmp)
|
||||
, m_destroy(destroy) {
|
||||
}
|
||||
|
||||
Alleg4Surface(int width, int height, DestroyFlag destroy)
|
||||
: m_bmp(create_bitmap(width, height))
|
||||
, m_destroy(destroy) {
|
||||
}
|
||||
|
||||
Alleg4Surface(int width, int height, int bpp, DestroyFlag destroy)
|
||||
: m_bmp(create_bitmap_ex(bpp, width, height))
|
||||
, m_destroy(destroy) {
|
||||
}
|
||||
|
||||
~Alleg4Surface() {
|
||||
if (m_destroy & DestroyHandle) {
|
||||
if (m_bmp)
|
||||
destroy_bitmap(m_bmp);
|
||||
}
|
||||
}
|
||||
|
||||
// Surface implementation
|
||||
|
||||
void dispose() override {
|
||||
if (m_destroy & DeleteThis)
|
||||
delete this;
|
||||
}
|
||||
|
||||
int width() const override {
|
||||
return m_bmp->w;
|
||||
}
|
||||
|
||||
int height() const override {
|
||||
return m_bmp->h;
|
||||
}
|
||||
|
||||
bool isDirectToScreen() const override {
|
||||
return m_bmp == screen;
|
||||
}
|
||||
|
||||
gfx::Rect getClipBounds() override {
|
||||
return gfx::Rect(
|
||||
m_bmp->cl,
|
||||
m_bmp->ct,
|
||||
m_bmp->cr - m_bmp->cl,
|
||||
m_bmp->cb - m_bmp->ct);
|
||||
}
|
||||
|
||||
void setClipBounds(const gfx::Rect& rc) override {
|
||||
set_clip_rect(m_bmp,
|
||||
rc.x,
|
||||
rc.y,
|
||||
rc.x+rc.w-1,
|
||||
rc.y+rc.h-1);
|
||||
}
|
||||
|
||||
bool intersectClipRect(const gfx::Rect& rc) override {
|
||||
add_clip_rect(m_bmp,
|
||||
rc.x,
|
||||
rc.y,
|
||||
rc.x+rc.w-1,
|
||||
rc.y+rc.h-1);
|
||||
|
||||
return
|
||||
(m_bmp->cl < m_bmp->cr &&
|
||||
m_bmp->ct < m_bmp->cb);
|
||||
}
|
||||
|
||||
LockedSurface* lock() override {
|
||||
acquire_bitmap(m_bmp);
|
||||
return this;
|
||||
}
|
||||
|
||||
void setDrawMode(DrawMode mode, int param) {
|
||||
switch (mode) {
|
||||
case DrawMode::Solid: checked_mode(-1); break;
|
||||
case DrawMode::Xor: xor_mode(TRUE); break;
|
||||
case DrawMode::Checked: checked_mode(param); break;
|
||||
}
|
||||
}
|
||||
|
||||
void applyScale(int scale) override {
|
||||
if (scale < 2)
|
||||
return;
|
||||
|
||||
BITMAP* scaled =
|
||||
create_bitmap_ex(bitmap_color_depth(m_bmp),
|
||||
m_bmp->w*scale,
|
||||
m_bmp->h*scale);
|
||||
|
||||
for (int y=0; y<scaled->h; ++y)
|
||||
for (int x=0; x<scaled->w; ++x)
|
||||
putpixel(scaled, x, y, getpixel(m_bmp, x/scale, y/scale));
|
||||
|
||||
if (m_destroy & DestroyHandle)
|
||||
destroy_bitmap(m_bmp);
|
||||
|
||||
m_bmp = scaled;
|
||||
m_destroy = DestroyHandle;
|
||||
}
|
||||
|
||||
void* nativeHandle() override {
|
||||
return reinterpret_cast<void*>(m_bmp);
|
||||
}
|
||||
|
||||
// LockedSurface implementation
|
||||
|
||||
int lockedWidth() const override {
|
||||
return m_bmp->w;
|
||||
}
|
||||
|
||||
int lockedHeight() const override {
|
||||
return m_bmp->h;
|
||||
}
|
||||
|
||||
void unlock() override {
|
||||
release_bitmap(m_bmp);
|
||||
}
|
||||
|
||||
void clear() override {
|
||||
clear_to_color(m_bmp, 0);
|
||||
}
|
||||
|
||||
uint8_t* getData(int x, int y) const override {
|
||||
switch (bitmap_color_depth(m_bmp)) {
|
||||
case 8: return (uint8_t*)(((uint8_t*)bmp_write_line(m_bmp, y)) + x);
|
||||
case 15:
|
||||
case 16: return (uint8_t*)(((uint16_t*)bmp_write_line(m_bmp, y)) + x);
|
||||
case 24: return (uint8_t*)(((uint8_t*)bmp_write_line(m_bmp, y)) + x*3);
|
||||
case 32: return (uint8_t*)(((uint32_t*)bmp_write_line(m_bmp, y)) + x);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void getFormat(SurfaceFormatData* formatData) const override {
|
||||
formatData->format = kRgbaSurfaceFormat;
|
||||
formatData->bitsPerPixel = bitmap_color_depth(m_bmp);
|
||||
|
||||
switch (formatData->bitsPerPixel) {
|
||||
case 8:
|
||||
formatData->redShift = 0;
|
||||
formatData->greenShift = 0;
|
||||
formatData->blueShift = 0;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 0;
|
||||
formatData->greenMask = 0;
|
||||
formatData->blueMask = 0;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 15:
|
||||
formatData->redShift = _rgb_r_shift_15;
|
||||
formatData->greenShift = _rgb_g_shift_15;
|
||||
formatData->blueShift = _rgb_b_shift_15;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 31 << _rgb_r_shift_15;
|
||||
formatData->greenMask = 31 << _rgb_g_shift_15;
|
||||
formatData->blueMask = 31 << _rgb_b_shift_15;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 16:
|
||||
formatData->redShift = _rgb_r_shift_16;
|
||||
formatData->greenShift = _rgb_g_shift_16;
|
||||
formatData->blueShift = _rgb_b_shift_16;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 31 << _rgb_r_shift_16;
|
||||
formatData->greenMask = 63 << _rgb_g_shift_16;
|
||||
formatData->blueMask = 31 << _rgb_b_shift_16;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 24:
|
||||
formatData->redShift = _rgb_r_shift_24;
|
||||
formatData->greenShift = _rgb_g_shift_24;
|
||||
formatData->blueShift = _rgb_b_shift_24;
|
||||
formatData->alphaShift = 0;
|
||||
formatData->redMask = 255 << _rgb_r_shift_24;
|
||||
formatData->greenMask = 255 << _rgb_g_shift_24;
|
||||
formatData->blueMask = 255 << _rgb_b_shift_24;
|
||||
formatData->alphaMask = 0;
|
||||
break;
|
||||
case 32:
|
||||
formatData->redShift = _rgb_r_shift_32;
|
||||
formatData->greenShift = _rgb_g_shift_32;
|
||||
formatData->blueShift = _rgb_b_shift_32;
|
||||
formatData->alphaShift = _rgb_a_shift_32;
|
||||
formatData->redMask = 255 << _rgb_r_shift_32;
|
||||
formatData->greenMask = 255 << _rgb_g_shift_32;
|
||||
formatData->blueMask = 255 << _rgb_b_shift_32;
|
||||
formatData->alphaMask = 255 << _rgb_a_shift_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Color getPixel(int x, int y) const override {
|
||||
return from_allegro(
|
||||
bitmap_color_depth(m_bmp),
|
||||
getpixel(m_bmp, x, y));
|
||||
}
|
||||
|
||||
void putPixel(gfx::Color color, int x, int y) override {
|
||||
putpixel(m_bmp, x, y, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
}
|
||||
|
||||
void drawHLine(gfx::Color color, int x, int y, int w) override {
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
hline(m_bmp, x, y, x+w-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void drawVLine(gfx::Color color, int x, int y, int h) override {
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
vline(m_bmp, x, y, y+h-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) override {
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
line(m_bmp, a.x, a.y, b.x, b.y, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void drawRect(gfx::Color color, const gfx::Rect& rc) override {
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
rect(m_bmp, rc.x, rc.y, rc.x+rc.w-1, rc.y+rc.h-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void fillRect(gfx::Color color, const gfx::Rect& rc) override {
|
||||
if (gfx::geta(color) < 255) {
|
||||
set_trans_blender(0, 0, 0, gfx::geta(color));
|
||||
drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
|
||||
}
|
||||
|
||||
rectfill(m_bmp, rc.x, rc.y, rc.x+rc.w-1, rc.y+rc.h-1, to_allegro(bitmap_color_depth(m_bmp), color));
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const override {
|
||||
ASSERT(m_bmp);
|
||||
ASSERT(dest);
|
||||
ASSERT(static_cast<Alleg4Surface*>(dest)->m_bmp);
|
||||
|
||||
blit(m_bmp,
|
||||
static_cast<Alleg4Surface*>(dest)->m_bmp,
|
||||
srcx, srcy,
|
||||
dstx, dsty,
|
||||
width, height);
|
||||
}
|
||||
|
||||
void scrollTo(const gfx::Rect& rc, int dx, int dy) override {
|
||||
blit(m_bmp, m_bmp,
|
||||
rc.x, rc.y,
|
||||
rc.x+dx, rc.y+dy,
|
||||
rc.w, rc.h);
|
||||
}
|
||||
|
||||
void drawSurface(const LockedSurface* src, int dstx, int dsty) override {
|
||||
draw_sprite(m_bmp, static_cast<const Alleg4Surface*>(src)->m_bmp, dstx, dsty);
|
||||
}
|
||||
|
||||
void drawRgbaSurface(const LockedSurface* src, int dstx, int dsty) override {
|
||||
set_alpha_blender();
|
||||
draw_trans_sprite(m_bmp, static_cast<const Alleg4Surface*>(src)->m_bmp, dstx, dsty);
|
||||
}
|
||||
|
||||
private:
|
||||
BITMAP* m_bmp;
|
||||
DestroyFlag m_destroy;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/string.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "she/font.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
|
@ -34,20 +34,22 @@ namespace she {
|
||||
virtual int originalWidth() const = 0;
|
||||
virtual int originalHeight() const = 0;
|
||||
|
||||
// Changes the scale (each pixel will be SCALExSCALE in the screen).
|
||||
// Returns the current display scale. Each pixel in the internal
|
||||
// display surface, is represented by SCALExSCALE pixels on the
|
||||
// screen.
|
||||
virtual int scale() const = 0;
|
||||
|
||||
// Changes the scale.
|
||||
// The available surface size will be (Display::width() / scale,
|
||||
// Display::height() / scale)
|
||||
virtual void setScale(int scale) = 0;
|
||||
virtual int scale() const = 0;
|
||||
|
||||
// Returns the main surface to draw into this display.
|
||||
// You must not dispose this surface.
|
||||
virtual NonDisposableSurface* 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;
|
||||
// Flips all graphics in the surface to the real display.
|
||||
virtual void flip() = 0;
|
||||
|
||||
virtual void maximize() = 0;
|
||||
virtual bool isMaximized() const = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2014 David Capello
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/size.h"
|
||||
#include "she/keys.h"
|
||||
|
||||
#include <string>
|
||||
@ -23,6 +24,7 @@ namespace she {
|
||||
enum Type {
|
||||
None,
|
||||
CloseDisplay,
|
||||
ResizeDisplay,
|
||||
DropFiles,
|
||||
MouseEnter,
|
||||
MouseLeave,
|
||||
|
@ -24,7 +24,6 @@ SkiaDisplay::SkiaDisplay(EventQueue* queue, int width, int height, int scale)
|
||||
m_surface->create(width, height);
|
||||
m_window.setScale(scale);
|
||||
m_window.setVisible(true);
|
||||
m_recreated = false;
|
||||
}
|
||||
|
||||
void SkiaDisplay::setSkiaSurface(SkiaSurface* surface)
|
||||
@ -42,7 +41,6 @@ void SkiaDisplay::resize(const gfx::Size& size)
|
||||
m_surface->dispose();
|
||||
m_surface = new SkiaSurface;
|
||||
m_surface->create(size.w, size.h);
|
||||
m_recreated = true;
|
||||
}
|
||||
|
||||
void SkiaDisplay::dispose()
|
||||
@ -70,16 +68,16 @@ int SkiaDisplay::originalHeight() const
|
||||
return m_window.restoredSize().h;
|
||||
}
|
||||
|
||||
void SkiaDisplay::setScale(int scale)
|
||||
{
|
||||
m_window.setScale(scale);
|
||||
}
|
||||
|
||||
int SkiaDisplay::scale() const
|
||||
{
|
||||
return m_window.scale();
|
||||
}
|
||||
|
||||
void SkiaDisplay::setScale(int scale)
|
||||
{
|
||||
m_window.setScale(scale);
|
||||
}
|
||||
|
||||
NonDisposableSurface* SkiaDisplay::getSurface()
|
||||
{
|
||||
return static_cast<NonDisposableSurface*>(m_surface);
|
||||
@ -88,15 +86,9 @@ NonDisposableSurface* SkiaDisplay::getSurface()
|
||||
// Flips all graphics in the surface to the real display. Returns
|
||||
// false if the flip couldn't be done because the display was
|
||||
// resized.
|
||||
bool SkiaDisplay::flip()
|
||||
void SkiaDisplay::flip()
|
||||
{
|
||||
if (m_recreated) {
|
||||
m_recreated = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_window.updateWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkiaDisplay::maximize()
|
||||
|
@ -33,17 +33,15 @@ public:
|
||||
int originalWidth() const override;
|
||||
int originalHeight() const override;
|
||||
|
||||
void setScale(int scale) override;
|
||||
int scale() const override;
|
||||
void setScale(int scale) override;
|
||||
|
||||
// Returns the main surface to draw into this display.
|
||||
// You must not dispose this surface.
|
||||
NonDisposableSurface* getSurface() override;
|
||||
|
||||
// Flips all graphics in the surface to the real display. Returns
|
||||
// false if the flip couldn't be done because the display was
|
||||
// resized.
|
||||
bool flip() override;
|
||||
// Flips all graphics in the surface to the real display.
|
||||
void flip() override;
|
||||
void maximize() override;
|
||||
bool isMaximized() const override;
|
||||
void setTitleBar(const std::string& title) override;
|
||||
@ -59,7 +57,6 @@ public:
|
||||
private:
|
||||
SkiaWindow m_window;
|
||||
SkiaSurface* m_surface;
|
||||
bool m_recreated;
|
||||
bool m_customSurface;
|
||||
NativeCursor m_nativeCursor;
|
||||
};
|
||||
|
@ -181,12 +181,9 @@ void Manager::flipDisplay()
|
||||
overlays->captureOverlappedAreas();
|
||||
overlays->drawOverlays();
|
||||
|
||||
if (!m_display->flip()) {
|
||||
// In case that the display was resized.
|
||||
onNewDisplayConfiguration();
|
||||
}
|
||||
else
|
||||
overlays->restoreOverlappedAreas();
|
||||
m_display->flip();
|
||||
|
||||
overlays->restoreOverlappedAreas();
|
||||
}
|
||||
|
||||
bool Manager::generateMessages()
|
||||
@ -272,7 +269,14 @@ void Manager::generateMessagesFromSheEvents()
|
||||
switch (sheEvent.type()) {
|
||||
|
||||
case she::Event::CloseDisplay: {
|
||||
Message* msg = new Message(kCloseAppMessage);
|
||||
Message* msg = new Message(kCloseDisplayMessage);
|
||||
msg->broadcastToChildren(this);
|
||||
enqueueMessage(msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case she::Event::ResizeDisplay: {
|
||||
Message* msg = new Message(kResizeDisplayMessage);
|
||||
msg->broadcastToChildren(this);
|
||||
enqueueMessage(msg);
|
||||
break;
|
||||
@ -469,10 +473,6 @@ void Manager::handleWindowZOrder()
|
||||
|
||||
void Manager::dispatchMessages()
|
||||
{
|
||||
// Add the "Queue Processing" message for the manager.
|
||||
enqueueMessage(newMouseMessage(kQueueProcessingMessage, this,
|
||||
get_mouse_position(), _internal_get_mouse_buttons()));
|
||||
|
||||
pumpQueue();
|
||||
flipDisplay();
|
||||
}
|
||||
@ -944,6 +944,10 @@ bool Manager::onProcessMessage(Message* msg)
|
||||
{
|
||||
switch (msg->type()) {
|
||||
|
||||
case kResizeDisplayMessage:
|
||||
onNewDisplayConfiguration();
|
||||
break;
|
||||
|
||||
case kKeyDownMessage:
|
||||
case kKeyUpMessage: {
|
||||
KeyMessage* keymsg = static_cast<KeyMessage*>(msg);
|
||||
@ -1054,6 +1058,7 @@ void Manager::onNewDisplayConfiguration()
|
||||
|
||||
_internal_set_mouse_display(m_display);
|
||||
invalidate();
|
||||
flushRedraw();
|
||||
}
|
||||
|
||||
void Manager::onPreferredSize(PreferredSizeEvent& ev)
|
||||
@ -1122,12 +1127,12 @@ void Manager::pumpQueue()
|
||||
static char *msg_name[] = {
|
||||
"kOpenMessage",
|
||||
"kCloseMessage",
|
||||
"kCloseAppMessage",
|
||||
"kCloseDisplayMessage",
|
||||
"kResizeDisplayMessage",
|
||||
"kPaintMessage",
|
||||
"kTimerMessage",
|
||||
"kDropFilesMessage",
|
||||
"kWinMoveMessage",
|
||||
"kQueueProcessingMessage",
|
||||
|
||||
"kKeyDownMessage",
|
||||
"kKeyUpMessage",
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013 David Capello
|
||||
// Copyright (C) 2001-2013, 2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -15,13 +15,12 @@ namespace ui {
|
||||
// General messages.
|
||||
kOpenMessage, // Windows is open.
|
||||
kCloseMessage, // Windows is closed.
|
||||
kCloseAppMessage, // The user wants to close the entire application.
|
||||
kCloseDisplayMessage, // The user wants to close the entire application.
|
||||
kResizeDisplayMessage,
|
||||
kPaintMessage, // Widget needs be repainted.
|
||||
kTimerMessage, // A timer timeout.
|
||||
kDropFilesMessage, // Drop files in the manager.
|
||||
kWinMoveMessage, // Window movement.
|
||||
kQueueProcessingMessage, // Only sent to manager which indicate
|
||||
// the last message in the queue.
|
||||
|
||||
// Keyboard related messages.
|
||||
kKeyDownMessage, // When a any key is pressed.
|
||||
|
Loading…
x
Reference in New Issue
Block a user