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:
David Capello 2015-07-30 16:15:21 -03:00
parent f2d5242ff3
commit 32b12d17da
24 changed files with 1310 additions and 1086 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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)

View 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

View 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

View 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

View 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

View File

@ -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"

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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()

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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,

View File

@ -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()

View File

@ -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;
};

View File

@ -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",

View File

@ -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.