Merge remote-tracking branch 'cnjinhao/hotfix-1.5.5' into hotfix-1.5.5

This commit is contained in:
qPCR4vir 2017-10-10 14:39:31 +02:00
commit 2ccfda24d0
11 changed files with 223 additions and 174 deletions

View File

@ -91,6 +91,8 @@ namespace nana
substitute = 0x1A, //Ctrl+Z substitute = 0x1A, //Ctrl+Z
escape = 0x1B, escape = 0x1B,
space = 0x20, //Space space = 0x20, //Space
del = 0x7F, //Delete
os_del = del, //Deprecated
//The following names are intuitive name of ASCII control codes //The following names are intuitive name of ASCII control codes
select_all = start_of_headline, select_all = start_of_headline,
@ -106,7 +108,7 @@ namespace nana
os_ctrl = 0x11, os_ctrl = 0x11,
os_pageup = 0x21, os_pagedown, os_pageup = 0x21, os_pagedown,
os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down, os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down,
os_insert = 0x2D, os_del , os_insert = 0x2D,
os_end = 0x23, os_home //Pos 1 os_end = 0x23, os_home //Pos 1
}; };
}; };

View File

@ -1,7 +1,7 @@
/* /*
* Platform Implementation * Platform Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -66,11 +66,11 @@ namespace detail
static nana::point window_position(native_window_type); static nana::point window_position(native_window_type);
static void move_window(native_window_type, int x, int y); static void move_window(native_window_type, int x, int y);
static void move_window(native_window_type, const rectangle&); static bool move_window(native_window_type, const rectangle&);
static void bring_top(native_window_type, bool activated); static void bring_top(native_window_type, bool activated);
static void set_window_z_order(native_window_type, native_window_type wd_after, z_order_action action_if_no_wd_after); static void set_window_z_order(native_window_type, native_window_type wd_after, z_order_action action_if_no_wd_after);
static void window_size(native_window_type, const size&); static bool window_size(native_window_type, const size&);
static void get_window_rect(native_window_type, rectangle&); static void get_window_rect(native_window_type, rectangle&);
static void window_caption(native_window_type, const native_string_type&); static void window_caption(native_window_type, const native_string_type&);
static native_string_type window_caption(native_window_type); static native_string_type window_caption(native_window_type);

View File

@ -85,12 +85,14 @@ namespace nana
bool changed() const; ///< Returns true if the graphics object is operated bool changed() const; ///< Returns true if the graphics object is operated
bool empty() const; ///< Returns true if the graphics object does not refer to any resource. bool empty() const; ///< Returns true if the graphics object does not refer to any resource.
operator const void*() const; explicit operator bool() const noexcept;
drawable_type handle() const; drawable_type handle() const;
const void* pixmap() const; const void* pixmap() const;
const void* context() const; const void* context() const;
void swap(graphics& other) noexcept;
/// Creates a graphics/drawable resource /// Creates a graphics/drawable resource
/** /**
* @param sz The dimension of the graphics to be requested. If sz is empty, it performs as release(). * @param sz The dimension of the graphics to be requested. If sz is empty, it performs as release().

View File

@ -47,16 +47,6 @@ namespace detail
bool visible; bool visible;
}; };
struct move_window
{
enum { Pos = 1, Size = 2};
int x;
int y;
unsigned width;
unsigned height;
unsigned ignore; //determinate that pos or size would be ignored.
};
struct map_thread struct map_thread
{ {
rectangle update_area; rectangle update_area;
@ -77,7 +67,6 @@ namespace detail
async_set_focus, async_set_focus,
remote_flush_surface, remote_flush_surface,
remote_thread_destroy_window, remote_thread_destroy_window,
remote_thread_move_window,
operate_caret, //wParam: 1=Destroy, 2=SetPos operate_caret, //wParam: 1=Destroy, 2=SetPos
remote_thread_set_window_pos, remote_thread_set_window_pos,
remote_thread_set_window_text, remote_thread_set_window_text,

View File

@ -245,22 +245,31 @@ namespace detail
_m_event_filter(evt_code, wd, thrd); _m_event_filter(evt_code, wd, thrd);
} }
if(wd->other.upd_state == core_window_t::update_state::none) using update_state = basic_window::update_state;
wd->other.upd_state = core_window_t::update_state::lazy;
if(wd->other.upd_state == update_state::none)
wd->other.upd_state = update_state::lazy;
_m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal);
bool good_wd = false;
if(wd_manager().available(wd))
{
//A child of wd may not be drawn if it was out of wd's range before wd resized, //A child of wd may not be drawn if it was out of wd's range before wd resized,
//so refresh all children of wd when a resized occurs. //so refresh all children of wd when a resized occurs.
if(ask_update || (event_code::resized == evt_code)) if(ask_update || (event_code::resized == evt_code) || (update_state::refreshed == wd->other.upd_state))
{ {
wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code)); wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code));
} }
else if(wd_manager().available(wd)) else
wd->other.upd_state = core_window_t::update_state::none; wd->other.upd_state = update_state::none;
good_wd = true;
}
if(thrd) thrd->event_window = prev_wd; if(thrd) thrd->event_window = prev_wd;
return true; return good_wd;
} }
void assign_arg(arg_mouse& arg, basic_window* wd, unsigned msg, const XEvent& evt) void assign_arg(arg_mouse& arg, basic_window* wd, unsigned msg, const XEvent& evt)
@ -438,8 +447,8 @@ namespace detail
keysym = keyboard::os_arrow_left + (keysym - XK_Left); break; keysym = keyboard::os_arrow_left + (keysym - XK_Left); break;
case XK_Insert: case XK_Insert:
keysym = keyboard::os_insert; break; keysym = keyboard::os_insert; break;
case XK_Delete: case XK_Delete: case XK_KP_Delete:
keysym = keyboard::os_del; break; keysym = keyboard::del; break;
case XK_Shift_L: case XK_Shift_R: //shift case XK_Shift_L: case XK_Shift_R: //shift
keysym = keyboard::os_shift; break; keysym = keyboard::os_shift; break;
case XK_Control_L: case XK_Control_R: //ctrl case XK_Control_L: case XK_Control_R: //ctrl

View File

@ -601,40 +601,6 @@ namespace detail
::HeapFree(::GetProcessHeap(), 0, stru); ::HeapFree(::GetProcessHeap(), 0, stru);
} }
return true; return true;
case nana::detail::messages::remote_thread_move_window:
{
auto * mw = reinterpret_cast<nana::detail::messages::move_window*>(wParam);
::RECT r;
::GetWindowRect(wd, &r);
if(mw->ignore & mw->Pos)
{
mw->x = r.left;
mw->y = r.top;
}
else
{
HWND owner = ::GetWindow(wd, GW_OWNER);
if(owner)
{
::RECT owr;
::GetWindowRect(owner, &owr);
::POINT pos = {owr.left, owr.top};
::ScreenToClient(owner, &pos);
mw->x += (owr.left - pos.x);
mw->y += (owr.top - pos.y);
}
}
if(mw->ignore & mw->Size)
{
mw->width = r.right - r.left;
mw->height = r.bottom - r.top;
}
::MoveWindow(wd, mw->x, mw->y, mw->width, mw->height, true);
delete mw;
}
return true;
case nana::detail::messages::remote_thread_set_window_pos: case nana::detail::messages::remote_thread_set_window_pos:
::SetWindowPos(wd, reinterpret_cast<HWND>(wParam), 0, 0, 0, 0, static_cast<UINT>(lParam)); ::SetWindowPos(wd, reinterpret_cast<HWND>(wParam), 0, 0, 0, 0, static_cast<UINT>(lParam));
return true; return true;
@ -775,6 +741,19 @@ namespace detail
if (thrd) thrd->event_window = prev_event_wd; if (thrd) thrd->event_window = prev_event_wd;
} }
//Translate OS Virtual-Key into ASCII code
wchar_t translate_virtual_key(WPARAM vkey)
{
switch (vkey)
{
case VK_DELETE:
return 127;
case VK_DECIMAL:
return 46;
}
return static_cast<wchar_t>(vkey);
}
LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam)
{ {
LRESULT window_proc_value = 0; LRESULT window_proc_value = 0;
@ -1436,7 +1415,7 @@ namespace detail
arg.evt_code = event_code::key_press; arg.evt_code = event_code::key_press;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.ignore = false; arg.ignore = false;
arg.key = static_cast<wchar_t>(wParam); arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg); brock.get_key_state(arg);
brock.emit(event_code::key_press, msgwnd, arg, true, &context); brock.emit(event_code::key_press, msgwnd, arg, true, &context);
@ -1522,7 +1501,7 @@ namespace detail
arg_keyboard arg; arg_keyboard arg;
arg.evt_code = event_code::key_release; arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd); arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.key = static_cast<wchar_t>(wParam); arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg); brock.get_key_state(arg);
arg.ignore = false; arg.ignore = false;
brock.emit(event_code::key_release, msgwnd, arg, true, &context); brock.emit(event_code::key_release, msgwnd, arg, true, &context);
@ -1639,18 +1618,21 @@ namespace detail
_m_event_filter(evt_code, wd, thrd); _m_event_filter(evt_code, wd, thrd);
} }
if (wd->other.upd_state == core_window_t::update_state::none) using update_state = basic_window::update_state;
wd->other.upd_state = core_window_t::update_state::lazy;
if (update_state::none == wd->other.upd_state)
wd->other.upd_state = update_state::lazy;
_m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal);
bool good_wd = false; bool good_wd = false;
if (wd_manager().available(wd)) if (wd_manager().available(wd))
{ {
if (ask_update) //Ignore ask_update if update state is refreshed.
if (ask_update || (update_state::refreshed == wd->other.upd_state))
wd_manager().do_lazy_refresh(wd, false); wd_manager().do_lazy_refresh(wd, false);
else else
wd->other.upd_state = basic_window::update_state::none; wd->other.upd_state = update_state::none;
good_wd = true; good_wd = true;
} }

View File

@ -863,16 +863,6 @@ namespace nana{
void native_interface::move_window(native_window_type wd, int x, int y) void native_interface::move_window(native_window_type wd, int x, int y)
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
if(::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
{
nana::detail::messages::move_window * mw = new nana::detail::messages::move_window;
mw->x = x;
mw->y = y;
mw->ignore = mw->Size;
::PostMessage(reinterpret_cast<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(mw), 0);
}
else
{
::RECT r; ::RECT r;
::GetWindowRect(reinterpret_cast<HWND>(wd), &r); ::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER); HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER);
@ -885,8 +875,15 @@ namespace nana{
x += (owner_rect.left - pos.x); x += (owner_rect.left - pos.x);
y += (owner_rect.top - pos.y); y += (owner_rect.top - pos.y);
} }
if (::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
{
nana::internal_revert_guard irg;
::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.right - r.left, r.bottom - r.top, true); ::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.right - r.left, r.bottom - r.top, true);
} }
else
::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.right - r.left, r.bottom - r.top, true);
#elif defined(NANA_X11) #elif defined(NANA_X11)
Display * disp = restrict::spec.open_display(); Display * disp = restrict::spec.open_display();
@ -908,21 +905,10 @@ namespace nana{
#endif #endif
} }
void native_interface::move_window(native_window_type wd, const rectangle& r) bool native_interface::move_window(native_window_type wd, const rectangle& r)
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
if(::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
{
auto * mw = new nana::detail::messages::move_window;
mw->x = r.x;
mw->y = r.y;
mw->width = r.width;
mw->height = r.height;
mw->ignore = 0;
::PostMessage(reinterpret_cast<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(mw), 0);
}
else
{
int x = r.x; int x = r.x;
int y = r.y; int y = r.y;
HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER); HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER);
@ -941,8 +927,14 @@ namespace nana{
::GetWindowRect(reinterpret_cast<HWND>(wd), &wd_area); ::GetWindowRect(reinterpret_cast<HWND>(wd), &wd_area);
unsigned ext_w = (wd_area.right - wd_area.left) - client.right; unsigned ext_w = (wd_area.right - wd_area.left) - client.right;
unsigned ext_h = (wd_area.bottom - wd_area.top) - client.bottom; unsigned ext_h = (wd_area.bottom - wd_area.top) - client.bottom;
::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.width + ext_w, r.height + ext_h, true);
if (::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
{
nana::internal_revert_guard irg;
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.width + ext_w, r.height + ext_h, true));
} }
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.width + ext_w, r.height + ext_h, true));
#elif defined(NANA_X11) #elif defined(NANA_X11)
Display * disp = restrict::spec.open_display(); Display * disp = restrict::spec.open_display();
long supplied; long supplied;
@ -984,6 +976,7 @@ namespace nana{
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints); ::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height); ::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
return true;
#endif #endif
} }
@ -1062,19 +1055,9 @@ namespace nana{
#endif #endif
} }
void native_interface::window_size(native_window_type wd, const size& sz) bool native_interface::window_size(native_window_type wd, const size& sz)
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
if(::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
{
auto * mw = new nana::detail::messages::move_window;
mw->width = sz.width;
mw->height = sz.height;
mw->ignore = mw->Pos;
::PostMessage(reinterpret_cast<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(mw), 0);
}
else
{
::RECT r; ::RECT r;
::GetWindowRect(reinterpret_cast<HWND>(wd), &r); ::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER); HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER);
@ -1086,8 +1069,14 @@ namespace nana{
r.left = pos.x; r.left = pos.x;
r.top = pos.y; r.top = pos.y;
} }
::MoveWindow(reinterpret_cast<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(sz.height), true);
if (::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
{
nana::internal_revert_guard irg;
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(sz.height), true));
} }
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(sz.height), true));
#elif defined(NANA_X11) #elif defined(NANA_X11)
auto disp = restrict::spec.open_display(); auto disp = restrict::spec.open_display();
nana::detail::platform_scope_guard psg; nana::detail::platform_scope_guard psg;
@ -1104,6 +1093,7 @@ namespace nana{
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints); ::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
} }
::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height); ::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
return true;
#endif #endif
} }

View File

@ -953,24 +953,45 @@ namespace detail
if (wd->dimension == sz) if (wd->dimension == sz)
return false; return false;
//Before resiz the window, creates the new graphics
paint::graphics graph;
paint::graphics root_graph;
if (category::flags::lite_widget != wd->other.category)
{
//If allocation fails, here throws std::bad_alloc.
graph.make(sz);
if (category::flags::root == wd->other.category)
root_graph.make(sz);
}
auto pre_sz = wd->dimension;
wd->dimension = sz; wd->dimension = sz;
if(category::flags::lite_widget != wd->other.category) if(category::flags::lite_widget != wd->other.category)
{ {
bool graph_state = wd->drawer.graphics.empty(); bool graph_state = wd->drawer.graphics.empty();
wd->drawer.graphics.make(sz); wd->drawer.graphics.swap(graph);
//It shall make a typeface_changed() call when the graphics state is changing. //It shall make a typeface_changed() call when the graphics state is changing.
//Because when a widget is created with zero-size, it may get some wrong result in typeface_changed() call //Because when a widget is created with zero-size, it may get some wrong results in typeface_changed() call
//due to the invaliable graphics object. //due to the invaliable graphics object.
if(graph_state != wd->drawer.graphics.empty()) if(graph_state != wd->drawer.graphics.empty())
wd->drawer.typeface_changed(); wd->drawer.typeface_changed();
if(category::flags::root == wd->other.category) if(category::flags::root == wd->other.category)
{ {
wd->root_graph->make(sz); //wd->root_graph->make(sz);
wd->root_graph->swap(root_graph);
if(false == passive) if(false == passive)
native_interface::window_size(wd->root, sz + nana::size(wd->extra_width, wd->extra_height)); if (!native_interface::window_size(wd->root, sz + nana::size(wd->extra_width, wd->extra_height)))
{
wd->dimension = pre_sz;
wd->drawer.graphics.swap(graph);
wd->root_graph->swap(root_graph);
wd->drawer.typeface_changed();
return false;
}
} }
#ifndef WIDGET_FRAME_DEPRECATED #ifndef WIDGET_FRAME_DEPRECATED
else if(category::flags::frame == wd->other.category) else if(category::flags::frame == wd->other.category)

View File

@ -403,8 +403,15 @@ namespace nana
ess_->state.nullify_mouse = true; ess_->state.nullify_mouse = true;
auto & menu_ptr = ess_->state.menu; auto & menu_ptr = ess_->state.menu;
//menu_wd will be assigned with the handle of a menu window,
//It is used for checking whether the menu is closed. A menu handler
//may close the form, checking with the data member of this trigger
//is invalid, because the form is closed, the object of menubar may not exist.
window menu_wd = nullptr;
if(ess_->state.menu) if(ess_->state.menu)
{ {
menu_wd = menu_ptr->handle();
switch(arg.key) switch(arg.key)
{ {
case keyboard::os_arrow_down: case keyboard::os_arrow_down:
@ -467,7 +474,10 @@ namespace nana
case keyboard::os_arrow_down: case keyboard::os_arrow_down:
case keyboard::enter: case keyboard::enter:
if (ess_->open_menu(true)) if (ess_->open_menu(true))
{
menu_wd = menu_ptr->handle();
menu_ptr->goto_next(true); menu_ptr->goto_next(true);
}
break; break;
case keyboard::escape: case keyboard::escape:
if(essence::behavior::focus == ess_->state.behave) if(essence::behavior::focus == ess_->state.behave)
@ -482,15 +492,21 @@ namespace nana
{ {
ess_->state.active = index; ess_->state.active = index;
if (ess_->open_menu(true)) if (ess_->open_menu(true))
{
menu_wd = menu_ptr->handle();
menu_ptr->goto_next(true); menu_ptr->goto_next(true);
} }
}
break; break;
} }
} }
if (API::is_window(menu_wd))
{
refresh(graph); refresh(graph);
API::dev::lazy_refresh(); API::dev::lazy_refresh();
} }
}
void trigger::key_release(graph_reference graph, const arg_keyboard& arg) void trigger::key_release(graph_reference graph, const arg_keyboard& arg)
{ {

View File

@ -1233,7 +1233,7 @@ namespace nana{ namespace widgets
case keyboard::os_pagedown: case keyboard::os_pagedown:
_m_handle_move_key(arg); _m_handle_move_key(arg);
break; break;
case keyboard::os_del: case keyboard::del:
// send delete to set_accept function // send delete to set_accept function
if (this->attr().editable && (!impl_->capacities.pred_acceptive || impl_->capacities.pred_acceptive(key))) if (this->attr().editable && (!impl_->capacities.pred_acceptive || impl_->capacities.pred_acceptive(key)))
del(); del();
@ -1689,7 +1689,7 @@ namespace nana{ namespace widgets
impl_->try_refresh = sync_graph::refresh; impl_->try_refresh = sync_graph::refresh;
//_m_put calcs the lines //_m_put calcs the lines
_m_reset_content_size(false); _m_reset_content_size(true);
impl_->cview->sync(false); impl_->cview->sync(false);
} }
} }

View File

@ -269,7 +269,7 @@ namespace paint
return (!impl_->handle); return (!impl_->handle);
} }
graphics::operator const void *() const graphics::operator bool() const noexcept
{ {
return impl_->handle; return impl_->handle;
} }
@ -291,6 +291,12 @@ namespace paint
return (impl_->handle ? impl_->handle->context : nullptr); return (impl_->handle ? impl_->handle->context : nullptr);
} }
void graphics::swap(graphics& other) noexcept
{
if (context() != other.context())
impl_.swap(other.impl_);
}
void graphics::make(const ::nana::size& sz) void graphics::make(const ::nana::size& sz)
{ {
if (impl_->handle == nullptr || impl_->size != sz) if (impl_->handle == nullptr || impl_->size != sz)
@ -302,7 +308,8 @@ namespace paint
} }
//The object will be delete while dwptr_ is performing a release. //The object will be delete while dwptr_ is performing a release.
drawable_type dw = new nana::detail::drawable_impl_type; std::shared_ptr<nana::detail::drawable_impl_type> dw{ new nana::detail::drawable_impl_type, detail::drawable_deleter{} };
//Reuse the old font //Reuse the old font
if (impl_->platform_drawable) if (impl_->platform_drawable)
{ {
@ -314,8 +321,13 @@ namespace paint
dw->font = impl_->font_shadow.impl_->real_font; dw->font = impl_->font_shadow.impl_->real_font;
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
HDC hdc = ::GetDC(0); HDC hdc = ::GetDC(nullptr);
HDC cdc = ::CreateCompatibleDC(hdc); HDC cdc = ::CreateCompatibleDC(hdc);
if (nullptr == cdc)
{
::ReleaseDC(nullptr, hdc);
throw std::bad_alloc{};
}
BITMAPINFO bmi; BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
@ -328,34 +340,60 @@ namespace paint
HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast<void**>(&(dw->pixbuf_ptr)), 0, 0); HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast<void**>(&(dw->pixbuf_ptr)), 0, 0);
if(bmp) if (nullptr == bmp)
{ {
::DeleteDC(cdc);
::ReleaseDC(nullptr, hdc);
throw std::bad_alloc{};
}
::DeleteObject((HBITMAP)::SelectObject(cdc, bmp)); ::DeleteObject((HBITMAP)::SelectObject(cdc, bmp));
::DeleteObject(::SelectObject(cdc, dw->font->native_handle())); ::DeleteObject(::SelectObject(cdc, dw->font->native_handle()));
dw->context = cdc; dw->context = cdc;
dw->pixmap = bmp; dw->pixmap = bmp;
::SetBkMode(cdc, TRANSPARENT); ::SetBkMode(cdc, TRANSPARENT);
}
else
{
::DeleteDC(cdc);
delete dw;
dw = nullptr;
release();
}
::ReleaseDC(0, hdc); ::ReleaseDC(0, hdc);
#elif defined(NANA_X11) #elif defined(NANA_X11)
auto & spec = nana::detail::platform_spec::instance(); auto & spec = nana::detail::platform_spec::instance();
{
nana::detail::platform_scope_guard psg;
spec.set_error_handler();
Display* disp = spec.open_display(); Display* disp = spec.open_display();
int screen = DefaultScreen(disp); int screen = DefaultScreen(disp);
Window root = ::XRootWindow(disp, screen); Window root = ::XRootWindow(disp, screen);
dw->pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen)); auto pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen));
dw->context = ::XCreateGC(disp, dw->pixmap, 0, 0); if(spec.error_code)
{
spec.rev_error_handler();
throw std::bad_alloc();
}
auto context = ::XCreateGC(disp, pixmap, 0, 0);
if (spec.error_code)
{
::XFreePixmap(disp, pixmap);
spec.rev_error_handler();
throw std::bad_alloc();
}
# if defined(NANA_USE_XFT) # if defined(NANA_USE_XFT)
dw->xftdraw = ::XftDrawCreate(disp, dw->pixmap, spec.screen_visual(), spec.colormap()); auto xftdraw = ::XftDrawCreate(disp, pixmap, spec.screen_visual(), spec.colormap());
if (spec.error_code)
{
::XFreeGC(disp, context);
::XFreePixmap(disp, pixmap);
spec.rev_error_handler();
throw std::bad_alloc();
}
dw->xftdraw = xftdraw;
# endif # endif
dw->pixmap = pixmap;
dw->context = context;
}
#endif #endif
if(dw) if(dw)
{ {
@ -366,8 +404,8 @@ namespace paint
#else #else
dw->update_text_color(); dw->update_text_color();
#endif #endif
impl_->platform_drawable.reset(dw, detail::drawable_deleter{}); impl_->platform_drawable = dw;
impl_->handle = dw; impl_->handle = dw.get();
impl_->size = sz; impl_->size = sz;
impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width;