Commit 5d29b7b3 authored by Davis King's avatar Davis King

Changed the gui core code around so that it should be safe to make window

objects at the global scope

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402526
parent 82be8506
...@@ -36,42 +36,6 @@ namespace dlib ...@@ -36,42 +36,6 @@ namespace dlib
namespace gui_core_kernel_1_globals namespace gui_core_kernel_1_globals
{ {
static logger dlog("dlib.gui_core");
static TCHAR window_class_name[] = TEXT ("w3049u6qc2d94thw9m34f4we0gvwa3-tgkser0-b9gm 05");
static HINSTANCE hInstance;
static HWND helper_window = NULL;
static bool core_has_been_initialized = false;
static bool quit_windows_loop = false;
static bool set_window_title_done = true;
static std::wstring window_title;
static bool move_window_done = true;
static HWND move_window_hwnd = NULL;
static int move_window_width = 0;
static int move_window_height = 0;
static int move_window_x = 0;
static int move_window_y = 0;
static bool request_new_window = false;
static DWORD dwStyle;
static HWND new_window = NULL;
static bool in_ime_composition = false;
// the window_table.get_mutex() mutex locks the above 11 variables
typedef sync_extension<binary_search_tree<HWND,base_window*>::kernel_1a>::kernel_1a
window_table_type;
// this variable holds a mapping from window handles to the base_window
// objects which represent them. Note that this objects mutex is always locked
// when inside the event loop.
static window_table_type window_table;
static rsignaler window_close_signaler(window_table.get_mutex());
static rsignaler et_signaler(window_table.get_mutex());
// note that this is the thread that will perform all the event
// processing.
thread_id_type event_thread_id;
struct user_event_type struct user_event_type
{ {
...@@ -80,8 +44,9 @@ namespace dlib ...@@ -80,8 +44,9 @@ namespace dlib
int i; int i;
}; };
typedef sync_extension<binary_search_tree<HWND,base_window*>::kernel_1a>::kernel_1a window_table_type;
typedef sync_extension<queue<user_event_type,memory_manager<char>::kernel_1b>::kernel_2a_c>::kernel_1a queue_of_user_events; typedef sync_extension<queue<user_event_type,memory_manager<char>::kernel_1b>::kernel_2a_c>::kernel_1a queue_of_user_events;
queue_of_user_events user_events;
enum USER_OFFSETS enum USER_OFFSETS
{ {
...@@ -96,6 +61,240 @@ namespace dlib ...@@ -96,6 +61,240 @@ namespace dlib
CALL_SET_WINDOW_TITLE CALL_SET_WINDOW_TITLE
}; };
// ----------------------------------------------------------------------------------------
class event_handler_thread : public threaded_object
{
public:
enum et_state
{
uninitialized,
initialized,
failure_to_init
};
et_state status;
queue_of_user_events user_events;
queue_of_user_events user_events_temp;
logger dlog;
HINSTANCE hInstance;
HWND helper_window;
const TCHAR* window_class_name;
bool should_destruct;
bool quit_windows_loop;
bool set_window_title_done;
std::wstring window_title;
bool move_window_done;
HWND move_window_hwnd;
int move_window_width;
int move_window_height;
int move_window_x;
int move_window_y;
bool request_new_window;
DWORD dwStyle;
HWND new_window;
bool in_ime_composition;
bool event_thread_started;
// the window_table.get_mutex() mutex locks the above 11 variables
// this variable holds a mapping from window handles to the base_window
// objects which represent them. Note that this objects mutex is always locked
// when inside the event loop.
window_table_type window_table;
rsignaler window_close_signaler;
rsignaler et_signaler;
// note that this is the thread that will perform all the event
// processing.
thread_id_type event_thread_id;
event_handler_thread(
) :
dlog("dlib.gui_core"),
hInstance(0),
helper_window(0),
window_class_name(TEXT ("w3049u6qc2d94thw9m34f4we0gvwa3-tgkser0-b9gm 05")),
should_destruct(false),
quit_windows_loop(false),
set_window_title_done(true),
move_window_done(true),
move_window_hwnd(0),
move_window_width(0),
move_window_height(0),
move_window_x(0),
move_window_y(0),
request_new_window(false),
dwStyle(0),
new_window(0),
in_ime_composition(false),
event_thread_started(false),
window_close_signaler(window_table.get_mutex()),
et_signaler(window_table.get_mutex())
{
status = uninitialized;
}
void start_event_thread (
)
/*!
we can't call this function from this objects constructor because
starting the event thread in windows involves sending messages to the
WndProc() and that requires this object to be fully constructed.
!*/
{
if (event_thread_started == false)
{
auto_mutex M(window_table.get_mutex());
if (event_thread_started == false)
{
event_thread_started = true;
// start up the event handler thread
start();
// wait for the event thread to get up and running
while (status == uninitialized)
et_signaler.wait();
if (status == failure_to_init)
throw gui_error("Failed to start event thread");
}
}
}
~event_handler_thread ()
{
using namespace gui_core_kernel_1_globals;
if (is_alive())
{
if (PostMessage(helper_window,WM_USER+QUIT_EVENT_HANDLER_THREAD,0,0)==0)
{
dlog << LERROR << "Unable to schedule function for execution in event handling thread.";
}
wait();
}
}
private:
void thread (
)
{
event_thread_id = get_thread_id();
hInstance = GetModuleHandle(NULL);
if (hInstance == NULL)
{
dlog << LFATAL << "Error gathering needed resources";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
// register the main window class
WNDCLASS wndclass ;
wndclass.style = CS_DBLCLKS;
wndclass.lpfnWndProc = dlib::gui_core_kernel_1_globals::WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = 0;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = window_class_name ;
if (!RegisterClass (&wndclass))
{
dlog << LFATAL << "Error registering window class";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
// make the helper window that is used to trigger events in the
// event handler loop from other threads
TCHAR nothing[] = TEXT("");
helper_window = CreateWindow(window_class_name,nothing,WS_DISABLED,0,0,0,0,HWND_MESSAGE,NULL,hInstance,NULL);
if (helper_window == NULL)
{
dlog << LFATAL << "Error gathering needed resources";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
// signal that the event thread is now up and running
window_table.get_mutex().lock();
status = initialized;
et_signaler.broadcast();
window_table.get_mutex().unlock();
// start the event handler loop.
/*
A note about this quit_windows_loop thing. If the user is holding
the mouse button down on the title bar of a window it will cause
the PostQuitMessage() function to be ignored!! This extra bool
is a work around to prevent that from happening.
*/
MSG msg;
while (GetMessage (&msg, NULL, 0, 0) &&
quit_windows_loop == false)
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
};
event_handler_thread& globals()
{
static event_handler_thread* p = new event_handler_thread;
p->start_event_thread();
return *p;
}
struct event_handler_thread_destruct_helper
{
~event_handler_thread_destruct_helper()
{
globals().window_table.get_mutex().lock();
// if there aren't any more gui windows then we can destroy the event handler thread
if (globals().window_table.size() == 0)
{
globals().window_table.get_mutex().unlock();
delete &globals();
}
else
{
globals().should_destruct = true;
globals().window_table.get_mutex().unlock();
}
}
};
static event_handler_thread_destruct_helper just_a_name;
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct ebh_param struct ebh_param
...@@ -460,13 +659,15 @@ namespace dlib ...@@ -460,13 +659,15 @@ namespace dlib
) )
{ {
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
queue_of_user_events user_events_temp;
// Make the event processing thread have a priority slightly above normal. // Make the event processing thread have a priority slightly above normal.
// This makes the GUI smother if you do heavy processing in other threads. // This makes the GUI smother if you do heavy processing in other threads.
HANDLE hand = OpenThread(THREAD_ALL_ACCESS,FALSE,GetCurrentThreadId()); HANDLE hand = OpenThread(THREAD_ALL_ACCESS,FALSE,GetCurrentThreadId());
SetThreadPriority(hand,THREAD_PRIORITY_ABOVE_NORMAL); SetThreadPriority(hand,THREAD_PRIORITY_ABOVE_NORMAL);
CloseHandle(hand); CloseHandle(hand);
window_table_type& window_table = globals().window_table;
HWND& helper_window = globals().helper_window;
auto_mutex M(window_table.get_mutex()); auto_mutex M(window_table.get_mutex());
try try
...@@ -481,7 +682,7 @@ namespace dlib ...@@ -481,7 +682,7 @@ namespace dlib
case WM_USER+QUIT_EVENT_HANDLER_THREAD: case WM_USER+QUIT_EVENT_HANDLER_THREAD:
if (hwnd == helper_window) if (hwnd == helper_window)
{ {
quit_windows_loop = true; globals().quit_windows_loop = true;
PostQuitMessage(0); PostQuitMessage(0);
} }
return 0; return 0;
...@@ -497,14 +698,14 @@ namespace dlib ...@@ -497,14 +698,14 @@ namespace dlib
if (hwnd == helper_window) if (hwnd == helper_window)
{ {
MoveWindow( MoveWindow(
move_window_hwnd, globals().move_window_hwnd,
move_window_x, globals().move_window_x,
move_window_y, globals().move_window_y,
move_window_width, globals().move_window_width,
move_window_height, globals().move_window_height,
TRUE); TRUE);
move_window_done = true; globals().move_window_done = true;
et_signaler.broadcast(); globals().et_signaler.broadcast();
} }
return 0; return 0;
...@@ -512,14 +713,14 @@ namespace dlib ...@@ -512,14 +713,14 @@ namespace dlib
if (hwnd == helper_window) if (hwnd == helper_window)
{ {
// this is the signal to look in the user_events queue // this is the signal to look in the user_events queue
user_events.lock(); globals().user_events.lock();
user_events.swap(user_events_temp); globals().user_events.swap(globals().user_events_temp);
user_events.unlock(); globals().user_events.unlock();
user_events_temp.reset(); globals().user_events_temp.reset();
// now dispatch all these user events // now dispatch all these user events
while (user_events_temp.move_next()) while (globals().user_events_temp.move_next())
{ {
base_window** win_ = window_table[user_events_temp.element().w]; base_window** win_ = window_table[globals().user_events_temp.element().w];
base_window* win; base_window* win;
// if this window exists in the window table then dispatch // if this window exists in the window table then dispatch
// its event. // its event.
...@@ -527,12 +728,12 @@ namespace dlib ...@@ -527,12 +728,12 @@ namespace dlib
{ {
win = *win_; win = *win_;
win->on_user_event( win->on_user_event(
user_events_temp.element().p, globals().user_events_temp.element().p,
user_events_temp.element().i globals().user_events_temp.element().i
); );
} }
} }
user_events_temp.clear(); globals().user_events_temp.clear();
} }
return 0; return 0;
...@@ -561,9 +762,9 @@ namespace dlib ...@@ -561,9 +762,9 @@ namespace dlib
case WM_USER+CALL_SET_WINDOW_TITLE: case WM_USER+CALL_SET_WINDOW_TITLE:
if (hwnd == helper_window) if (hwnd == helper_window)
{ {
SetWindowTextW((HWND)wParam,window_title.c_str()); SetWindowTextW((HWND)wParam,globals().window_title.c_str());
set_window_title_done = true; globals().set_window_title_done = true;
et_signaler.broadcast(); globals().et_signaler.broadcast();
} }
return 0; return 0;
...@@ -573,36 +774,36 @@ namespace dlib ...@@ -573,36 +774,36 @@ namespace dlib
{ {
// if this is stupposed to be a popup window then do the popup window thing // if this is stupposed to be a popup window then do the popup window thing
if (dwStyle == WS_CHILD) if (globals().dwStyle == WS_CHILD)
{ {
TCHAR nothing[] = TEXT(""); TCHAR nothing[] = TEXT("");
new_window = CreateWindowEx (WS_EX_TOOLWINDOW,window_class_name, nothing, globals().new_window = CreateWindowEx (WS_EX_TOOLWINDOW,globals().window_class_name, nothing,
dwStyle, globals().dwStyle,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
helper_window, NULL, hInstance, NULL); helper_window, NULL, globals().hInstance, NULL);
SetParent(new_window,NULL); SetParent(globals().new_window,NULL);
} }
else else
{ {
TCHAR nothing[] = TEXT(""); TCHAR nothing[] = TEXT("");
new_window = CreateWindow (window_class_name, nothing, globals().new_window = CreateWindow (globals().window_class_name, nothing,
dwStyle, globals().dwStyle,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL); NULL, NULL, globals().hInstance, NULL);
} }
// use the helper_window to indicate that CreateWindow failed // use the helper_window to indicate that CreateWindow failed
if (new_window == NULL) if (globals().new_window == NULL)
new_window = helper_window; globals().new_window = helper_window;
et_signaler.broadcast(); globals().et_signaler.broadcast();
} }
return 0; return 0;
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
case WM_KEYDOWN: case WM_KEYDOWN:
{ {
if (in_ime_composition) break; if (globals().in_ime_composition) break;
base_window** win_ = window_table[hwnd]; base_window** win_ = window_table[hwnd];
base_window* win; base_window* win;
...@@ -1123,7 +1324,7 @@ namespace dlib ...@@ -1123,7 +1324,7 @@ namespace dlib
window_table.destroy(hwnd); window_table.destroy(hwnd);
win->has_been_destroyed = true; win->has_been_destroyed = true;
win->hwnd = 0; win->hwnd = 0;
gui_core_kernel_1_globals::window_close_signaler.broadcast(); globals().window_close_signaler.broadcast();
} }
else else
{ {
...@@ -1137,12 +1338,12 @@ namespace dlib ...@@ -1137,12 +1338,12 @@ namespace dlib
return DefWindowProc (hwnd, message, wParam, lParam); return DefWindowProc (hwnd, message, wParam, lParam);
case WM_IME_STARTCOMPOSITION: case WM_IME_STARTCOMPOSITION:
in_ime_composition = true; globals().in_ime_composition = true;
break; break;
case WM_IME_COMPOSITION: case WM_IME_COMPOSITION:
{ {
in_ime_composition = false; globals().in_ime_composition = false;
base_window** win_ = window_table[hwnd]; base_window** win_ = window_table[hwnd];
base_window* win; base_window* win;
if (win_) if (win_)
...@@ -1180,12 +1381,12 @@ namespace dlib ...@@ -1180,12 +1381,12 @@ namespace dlib
catch (std::exception& e) catch (std::exception& e)
{ {
error_box("Exception thrown in event handler",e.what()); error_box("Exception thrown in event handler",e.what());
quit_windows_loop = true; globals().quit_windows_loop = true;
} }
catch (...) catch (...)
{ {
error_box("Exception thrown in event handler","Unknown Exception type."); error_box("Exception thrown in event handler","Unknown Exception type.");
quit_windows_loop = true; globals().quit_windows_loop = true;
} }
return DefWindowProc (hwnd, message, wParam, lParam) ; return DefWindowProc (hwnd, message, wParam, lParam) ;
...@@ -1199,7 +1400,7 @@ namespace dlib ...@@ -1199,7 +1400,7 @@ namespace dlib
) )
{ {
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
PostMessage(helper_window,WM_USER+SHOW_WINDOW_SHOW,(WPARAM)hwnd,0); PostMessage(globals().helper_window,WM_USER+SHOW_WINDOW_SHOW,(WPARAM)hwnd,0);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1209,7 +1410,7 @@ namespace dlib ...@@ -1209,7 +1410,7 @@ namespace dlib
) )
{ {
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
PostMessage(helper_window,WM_USER+SHOW_WINDOW_HIDE,(WPARAM)hwnd,0); PostMessage(globals().helper_window,WM_USER+SHOW_WINDOW_HIDE,(WPARAM)hwnd,0);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1223,7 +1424,7 @@ namespace dlib ...@@ -1223,7 +1424,7 @@ namespace dlib
!*/ !*/
{ {
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
PostMessage(helper_window,WM_USER+SET_ACTIVE_WINDOW,(WPARAM)hwnd,0); PostMessage(globals().helper_window,WM_USER+SET_ACTIVE_WINDOW,(WPARAM)hwnd,0);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1237,7 +1438,7 @@ namespace dlib ...@@ -1237,7 +1438,7 @@ namespace dlib
!*/ !*/
{ {
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
PostMessage(helper_window,WM_USER+DESTROY_WINDOW,(WPARAM)hwnd,0); PostMessage(globals().helper_window,WM_USER+DESTROY_WINDOW,(WPARAM)hwnd,0);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1258,56 +1459,56 @@ namespace dlib ...@@ -1258,56 +1459,56 @@ namespace dlib
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
// if we are running in the event handling thread then just call // if we are running in the event handling thread then just call
// CreateWindow directly // CreateWindow directly
if (get_thread_id() == gui_core_kernel_1_globals::event_thread_id) if (get_thread_id() == globals().event_thread_id)
{ {
// if this is stupposed to be a popup window then do the popup window thing // if this is stupposed to be a popup window then do the popup window thing
if (dwStyle_ == WS_CHILD) if (dwStyle_ == WS_CHILD)
{ {
TCHAR nothing[] = TEXT(""); TCHAR nothing[] = TEXT("");
HWND tmp = CreateWindowEx (WS_EX_TOOLWINDOW|WS_EX_TOPMOST, window_class_name, nothing, HWND tmp = CreateWindowEx (WS_EX_TOOLWINDOW|WS_EX_TOPMOST, globals().window_class_name, nothing,
dwStyle_, dwStyle_,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
helper_window, NULL, hInstance, NULL); globals().helper_window, NULL, globals().hInstance, NULL);
SetParent(tmp,NULL); SetParent(tmp,NULL);
return tmp; return tmp;
} }
else else
{ {
TCHAR nothing[] = TEXT(""); TCHAR nothing[] = TEXT("");
return CreateWindow (window_class_name, nothing, return CreateWindow (globals().window_class_name, nothing,
dwStyle_, dwStyle_,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL); NULL, NULL, globals().hInstance, NULL);
} }
} }
else else
{ {
auto_mutex M(window_table.get_mutex()); auto_mutex M(globals().window_table.get_mutex());
// wait for our chance to make a new window request // wait for our chance to make a new window request
while (request_new_window) while (globals().request_new_window)
et_signaler.wait(); globals().et_signaler.wait();
dwStyle = dwStyle_; globals().dwStyle = dwStyle_;
if (PostMessage(helper_window,WM_USER+CREATE_WINDOW,0,0)==0) if (PostMessage(globals().helper_window,WM_USER+CREATE_WINDOW,0,0)==0)
{ {
throw gui_error("Unable to schedule function for execution in event handling thread."); throw gui_error("Unable to schedule function for execution in event handling thread.");
} }
// wait for our request to be serviced // wait for our request to be serviced
while (new_window == NULL) while (globals().new_window == NULL)
et_signaler.wait(); globals().et_signaler.wait();
HWND temp = new_window; HWND temp = globals().new_window;
new_window = NULL; globals().new_window = NULL;
request_new_window = false; globals().request_new_window = false;
et_signaler.broadcast(); globals().et_signaler.broadcast();
// if make_window() returns the helper_window then it means it failed // if make_window() returns the helper_window then it means it failed
// to make a new window // to make a new window
if (temp == helper_window) if (temp == globals().helper_window)
temp = NULL; temp = NULL;
return temp; return temp;
...@@ -1316,151 +1517,6 @@ namespace dlib ...@@ -1316,151 +1517,6 @@ namespace dlib
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
class event_handler_thread : public threaded_object
{
public:
enum et_state
{
uninitialized,
initialized,
failure_to_init
};
et_state status;
event_handler_thread(
)
{
status = uninitialized;
}
~event_handler_thread ()
{
using namespace gui_core_kernel_1_globals;
if (is_alive())
{
if (PostMessage(helper_window,WM_USER+QUIT_EVENT_HANDLER_THREAD,0,0)==0)
{
dlog << LERROR << "Unable to schedule function for execution in event handling thread.";
}
wait();
}
}
private:
void thread (
)
{
event_thread_id = get_thread_id();
hInstance = GetModuleHandle(NULL);
if (hInstance == NULL)
{
dlog << LFATAL << "Error gathering needed resources";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
// register the main window class
WNDCLASS wndclass ;
wndclass.style = CS_DBLCLKS;
wndclass.lpfnWndProc = dlib::gui_core_kernel_1_globals::WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = 0;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = window_class_name ;
if (!RegisterClass (&wndclass))
{
dlog << LFATAL << "Error registering window class";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
// make the helper window that is used to trigger events in the
// event handler loop from other threads
TCHAR nothing[] = TEXT("");
helper_window = CreateWindow(window_class_name,nothing,WS_DISABLED,0,0,0,0,HWND_MESSAGE,NULL,hInstance,NULL);
if (helper_window == NULL)
{
dlog << LFATAL << "Error gathering needed resources";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
// signal that the event thread is now up and running
window_table.get_mutex().lock();
status = initialized;
et_signaler.broadcast();
window_table.get_mutex().unlock();
// start the event handler loop.
/*
A note about this quit_windows_loop thing. If the user is holding
the mouse button down on the title bar of a window it will cause
the PostQuitMessage() function to be ignored!! This extra bool
is a work around to prevent that from happening.
*/
MSG msg;
while (GetMessage (&msg, NULL, 0, 0) &&
quit_windows_loop == false)
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
};
// ----------------------------------------------------------------------------------------
static event_handler_thread event_handler;
void init_gui_core ()
{
using namespace dlib::gui_core_kernel_1_globals;
auto_mutex M(window_table.get_mutex());
if (core_has_been_initialized == false)
{
core_has_been_initialized = true;
// start up the event handler thread
event_handler.start();
// wait for the event thread to get up and running
while (event_handler.status == event_handler_thread::uninitialized)
et_signaler.wait();
if (event_handler.status == event_handler_thread::failure_to_init)
throw gui_error("Failed to start event thread");
}
}
} // end namespace gui_core_kernel_1_globals } // end namespace gui_core_kernel_1_globals
...@@ -1526,11 +1582,11 @@ namespace dlib ...@@ -1526,11 +1582,11 @@ namespace dlib
e.p = p; e.p = p;
e.i = i; e.i = i;
{ {
auto_mutex M(user_events.get_mutex()); auto_mutex M(globals().user_events.get_mutex());
user_events.enqueue(e); globals().user_events.enqueue(e);
} }
if (PostMessage(helper_window,WM_USER+USER_EVENTS_READY,0,0)==0) if (PostMessage(globals().helper_window,WM_USER+USER_EVENTS_READY,0,0)==0)
{ {
throw gui_error("Unable to schedule function for execution in event handling thread."); throw gui_error("Unable to schedule function for execution in event handling thread.");
} }
...@@ -1547,16 +1603,15 @@ namespace dlib ...@@ -1547,16 +1603,15 @@ namespace dlib
prevx(-1), prevx(-1),
prevy(-1), prevy(-1),
prev_state(0), prev_state(0),
wm(gui_core_kernel_1_globals::window_table.get_mutex()) wm(gui_core_kernel_1_globals::globals().window_table.get_mutex())
{ {
using namespace gui_core_kernel_1_globals;
DLIB_ASSERT(!(undecorated == true && resizable == true), DLIB_ASSERT(!(undecorated == true && resizable == true),
"\tbase_window::base_window()" "\tbase_window::base_window()"
<< "\n\tThere is no such thing as an undecorated window that is resizable by the user." << "\n\tThere is no such thing as an undecorated window that is resizable by the user."
<< "\n\tthis: " << this << "\n\tthis: " << this
); );
gui_core_kernel_1_globals::init_gui_core();
if (resizable) if (resizable)
style = WS_OVERLAPPEDWINDOW; style = WS_OVERLAPPEDWINDOW;
else if (undecorated) else if (undecorated)
...@@ -1575,7 +1630,7 @@ namespace dlib ...@@ -1575,7 +1630,7 @@ namespace dlib
HWND temp = hwnd; HWND temp = hwnd;
base_window* ttemp = this; base_window* ttemp = this;
gui_core_kernel_1_globals::window_table.add(temp,ttemp); globals().window_table.add(temp,ttemp);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1584,7 +1639,22 @@ namespace dlib ...@@ -1584,7 +1639,22 @@ namespace dlib
~base_window ( ~base_window (
) )
{ {
using namespace gui_core_kernel_1_globals;
close_window(); close_window();
// check if we were the last window to be destroyed and the program is
// ending. If so then destroy the event handler thread's global object
wm.lock();
if (globals().window_table.size() == 0 && globals().should_destruct == true)
{
wm.unlock();
delete &globals();
}
else
{
// don't do anything except remember to unlock the wm mutex
wm.unlock();
}
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1593,16 +1663,17 @@ namespace dlib ...@@ -1593,16 +1663,17 @@ namespace dlib
close_window ( close_window (
) )
{ {
using namespace gui_core_kernel_1_globals;
auto_mutex M(wm); auto_mutex M(wm);
if (has_been_destroyed == false) if (has_been_destroyed == false)
{ {
// do this just to make sure no one tries to call this window's // do this just to make sure no one tries to call this window's
// calbacks. // calbacks.
gui_core_kernel_1_globals::window_table.destroy(hwnd); globals().window_table.destroy(hwnd);
gui_core_kernel_1_globals::destroy_window(hwnd); gui_core_kernel_1_globals::destroy_window(hwnd);
hwnd = 0; hwnd = 0;
has_been_destroyed = true; has_been_destroyed = true;
gui_core_kernel_1_globals::window_close_signaler.broadcast(); globals().window_close_signaler.broadcast();
} }
} }
...@@ -1612,9 +1683,10 @@ namespace dlib ...@@ -1612,9 +1683,10 @@ namespace dlib
wait_until_closed ( wait_until_closed (
) const ) const
{ {
using namespace gui_core_kernel_1_globals;
auto_mutex M(wm); auto_mutex M(wm);
while (has_been_destroyed == false) while (has_been_destroyed == false)
gui_core_kernel_1_globals::window_close_signaler.wait(); globals().window_close_signaler.wait();
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1663,23 +1735,23 @@ namespace dlib ...@@ -1663,23 +1735,23 @@ namespace dlib
// do this to avoid possible deadlocks. // do this to avoid possible deadlocks.
auto_mutex M(wm); auto_mutex M(wm);
if (get_thread_id() == gui_core_kernel_1_globals::event_thread_id) if (get_thread_id() == globals().event_thread_id)
{ {
SetWindowTextW(hwnd,title.c_str()); SetWindowTextW(hwnd,title.c_str());
} }
else else
{ {
window_title = title; globals().window_title = title;
set_window_title_done = false; globals().set_window_title_done = false;
if (PostMessage(helper_window,WM_USER+CALL_SET_WINDOW_TITLE,(WPARAM)hwnd,0)==0) if (PostMessage(globals().helper_window,WM_USER+CALL_SET_WINDOW_TITLE,(WPARAM)hwnd,0)==0)
{ {
throw gui_error("Unable to schedule SetWindowText function for execution in event handling thread."); throw gui_error("Unable to schedule SetWindowText function for execution in event handling thread.");
} }
// wait for any SetWindowText() calls to finish // wait for any SetWindowText() calls to finish
while (set_window_title_done == false) while (globals().set_window_title_done == false)
et_signaler.wait(); globals().et_signaler.wait();
} }
} }
...@@ -1732,7 +1804,7 @@ namespace dlib ...@@ -1732,7 +1804,7 @@ namespace dlib
<< "\n\theight: " << height_ << "\n\theight: " << height_
); );
auto_mutex M(wm); auto_mutex M(wm);
if (get_thread_id() == gui_core_kernel_1_globals::event_thread_id) if (get_thread_id() == globals().event_thread_id)
{ {
RECT info; RECT info;
GetWindowRect(hwnd,&info); GetWindowRect(hwnd,&info);
...@@ -1784,21 +1856,21 @@ namespace dlib ...@@ -1784,21 +1856,21 @@ namespace dlib
// have to do this because the MoveWindow() apparently blocks // have to do this because the MoveWindow() apparently blocks
// until something happens in the event thread so we have to // until something happens in the event thread so we have to
// do this to avoid possible deadlocks. // do this to avoid possible deadlocks.
move_window_hwnd = hwnd; globals().move_window_hwnd = hwnd;
move_window_x = x; globals().move_window_x = x;
move_window_y = y; globals().move_window_y = y;
move_window_width = width; globals().move_window_width = width;
move_window_height = height; globals().move_window_height = height;
move_window_done = false; globals().move_window_done = false;
if (PostMessage(helper_window,WM_USER+CALL_MOVE_WINDOW,0,0)==0) if (PostMessage(globals().helper_window,WM_USER+CALL_MOVE_WINDOW,0,0)==0)
{ {
throw gui_error("Unable to schedule MoveWindow function for execution in event handling thread."); throw gui_error("Unable to schedule MoveWindow function for execution in event handling thread.");
} }
// wait for any MoveWindow calls to finish // wait for any MoveWindow calls to finish
while (move_window_done == false) while (globals().move_window_done == false)
et_signaler.wait(); globals().et_signaler.wait();
} }
} }
...@@ -1820,7 +1892,7 @@ namespace dlib ...@@ -1820,7 +1892,7 @@ namespace dlib
<< "\n\ty: " << y_ << "\n\ty: " << y_
); );
auto_mutex M(wm); auto_mutex M(wm);
if (get_thread_id() == gui_core_kernel_1_globals::event_thread_id) if (get_thread_id() == globals().event_thread_id)
{ {
RECT info; RECT info;
GetWindowRect(hwnd,&info); GetWindowRect(hwnd,&info);
...@@ -1849,21 +1921,21 @@ namespace dlib ...@@ -1849,21 +1921,21 @@ namespace dlib
// have to do this because the MoveWindow() apparently blocks // have to do this because the MoveWindow() apparently blocks
// until something happens in the event thread so we have to // until something happens in the event thread so we have to
// do this to avoid possible deadlocks. // do this to avoid possible deadlocks.
move_window_hwnd = hwnd; globals().move_window_hwnd = hwnd;
move_window_x = x_; globals().move_window_x = x_;
move_window_y = y_; globals().move_window_y = y_;
move_window_width = width; globals().move_window_width = width;
move_window_height = height; globals().move_window_height = height;
move_window_done = false; globals().move_window_done = false;
if (PostMessage(helper_window,WM_USER+CALL_MOVE_WINDOW,0,0)==0) if (PostMessage(globals().helper_window,WM_USER+CALL_MOVE_WINDOW,0,0)==0)
{ {
throw gui_error("Unable to schedule MoveWindow function for execution in event handling thread."); throw gui_error("Unable to schedule MoveWindow function for execution in event handling thread.");
} }
// wait for any MoveWindow calls to finish // wait for any MoveWindow calls to finish
while (move_window_done == false) while (globals().move_window_done == false)
et_signaler.wait(); globals().et_signaler.wait();
} }
} }
...@@ -2007,12 +2079,10 @@ namespace dlib ...@@ -2007,12 +2079,10 @@ namespace dlib
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
using namespace std; using namespace std;
init_gui_core(); if (OpenClipboard(globals().helper_window))
if (OpenClipboard(helper_window))
{ {
EmptyClipboard(); EmptyClipboard();
auto_mutex M(window_table.get_mutex()); auto_mutex M(globals().window_table.get_mutex());
const unsigned long newlines = count(str.begin(),str.end(),L'\n'); const unsigned long newlines = count(str.begin(),str.end(),L'\n');
...@@ -2075,10 +2145,8 @@ namespace dlib ...@@ -2075,10 +2145,8 @@ namespace dlib
using namespace gui_core_kernel_1_globals; using namespace gui_core_kernel_1_globals;
using namespace std; using namespace std;
init_gui_core(); auto_mutex M(globals().window_table.get_mutex());
if (OpenClipboard(globals().helper_window))
auto_mutex M(window_table.get_mutex());
if (OpenClipboard(helper_window))
{ {
HANDLE data = GetClipboardData(CF_UNICODETEXT); HANDLE data = GetClipboardData(CF_UNICODETEXT);
......
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
namespace dlib namespace dlib
{ {
scoped_ptr<default_font> default_font::f;
mutex default_font::m;
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
const std::string get_decoded_string_with_default_font_data() const std::string get_decoded_string_with_default_font_data()
......
...@@ -491,13 +491,14 @@ namespace dlib ...@@ -491,13 +491,14 @@ namespace dlib
default_font(default_font&); // copy constructor default_font(default_font&); // copy constructor
default_font& operator=(default_font&); // assignment operator default_font& operator=(default_font&); // assignment operator
static scoped_ptr<default_font> f;
static mutex m;
public: public:
static const font* get_font ( static const font* get_font (
) )
{ {
static mutex m;
static scoped_ptr<default_font> f;
auto_mutex M(m); auto_mutex M(m);
if (f.get() == 0) if (f.get() == 0)
f.reset(new default_font); f.reset(new default_font);
......
...@@ -771,13 +771,13 @@ private: ...@@ -771,13 +771,13 @@ private:
}; };
win w;
int main() int main()
{ {
try try
{ {
win w;
w.set_pos (100,200); w.set_pos (100,200);
w.set_title("test window"); w.set_title("test window");
w.show(); w.show();
......
...@@ -15,7 +15,7 @@ namespace dlib ...@@ -15,7 +15,7 @@ namespace dlib
static const unichar SURROGATE_FIRST_TOP = 0xD800; static const unichar SURROGATE_FIRST_TOP = 0xD800;
static const unichar SURROGATE_SECOND_TOP = 0xDC00; static const unichar SURROGATE_SECOND_TOP = 0xDC00;
static const unichar SURROGATE_CLEARING_MASK = 0x03FF; static const unichar SURROGATE_CLEARING_MASK = 0x03FF;
static const unichar &SURROGATE_TOP = SURROGATE_FIRST_TOP; static const unichar SURROGATE_TOP = SURROGATE_FIRST_TOP;
static const unichar SURROGATE_END = 0xE000; static const unichar SURROGATE_END = 0xE000;
static const unichar SMP_TOP = 0x10000; static const unichar SMP_TOP = 0x10000;
static const int VALID_BITS = 10; static const int VALID_BITS = 10;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment