Commit 643cc535 authored by Davis King's avatar Davis King

Made the X11 version of the gui_core work with global window objects.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402527
parent 5d29b7b3
...@@ -32,10 +32,7 @@ namespace dlib ...@@ -32,10 +32,7 @@ namespace dlib
namespace gui_core_kernel_2_globals namespace gui_core_kernel_2_globals
{ {
static logger dlog("dlib.gui_core"); void init_keyboard_mod_masks();
void event_handler ();
void trigger_user_event_threadproc (void*);
struct x11_base_windowstuff struct x11_base_windowstuff
{ {
Window hwnd; Window hwnd;
...@@ -44,39 +41,290 @@ namespace dlib ...@@ -44,39 +41,290 @@ namespace dlib
XFontSet fs; XFontSet fs;
}; };
struct user_event_type
{
Window w;
void* p;
int i;
};
typedef sync_extension<queue<user_event_type,memory_manager<char>::kernel_1b>::kernel_2a_c>::kernel_1a queue_of_user_events;
typedef sync_extension<binary_search_tree<Window,base_window*>::kernel_1a>::kernel_1a typedef sync_extension<binary_search_tree<Window,base_window*>::kernel_1a>::kernel_1a
window_table_type; window_table_type;
int depth; // ----------------------------------------------------------------------------------------
Display* disp;
static XIM xim = NULL;
static XIMStyle xim_style;
static Screen* screen;
Atom delete_window; class event_handler_thread : public threaded_object
static Window exit_window; {
static std::wstring clipboard; public:
static bool core_has_been_initialized = false;
static int alt_mask = 0; enum et_state
static int meta_mask = 0; {
static int num_lock_mask = 0; uninitialized,
static int scroll_lock_mask = 0; initialized,
failure_to_init
};
static window_table_type window_table; et_state status;
static rsignaler window_close_signaler(window_table.get_mutex()); logger dlog;
static rsignaler et_signaler(window_table.get_mutex());
struct user_event_type // this is true if the application is trying to end
{ bool should_destruct;
Window w;
void* p; int depth;
int i; Display* disp;
XIM xim;
XIMStyle xim_style;
Screen* screen;
Atom delete_window;
Window exit_window;
std::wstring clipboard;
int alt_mask;
int meta_mask;
int num_lock_mask;
int scroll_lock_mask;
// the mutex in this object is the global mutex used to protect everything
// in the gui_core and gui_widgets components.
window_table_type window_table;
rsignaler window_close_signaler;
rsignaler et_signaler;
queue_of_user_events user_events;
queue_of_user_events user_events_temp;
event_handler_thread(
) :
dlog("dlib.gui_core"),
should_destruct(false),
depth(0),
disp(0),
xim(0),
screen(0),
alt_mask(0),
meta_mask(0),
num_lock_mask(0),
scroll_lock_mask(0),
window_close_signaler(window_table.get_mutex()),
et_signaler(window_table.get_mutex())
{
auto_mutex M(window_table.get_mutex());
status = uninitialized;
// 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 initialize X11 resources");
init_keyboard_mod_masks();
}
~event_handler_thread ()
{
if (is_alive())
{
if (status != failure_to_init)
{
XConfigureEvent event;
event.type = ConfigureNotify;
event.send_event = True;
event.display = disp;
event.window = exit_window;
event.x = 1;
XFlush(disp);
XPutBackEvent(disp,reinterpret_cast<XEvent*>(&event));
XFlush(disp);
// This should cause XNextEvent() to unblock so that it will see
// this ConfigureNotify event we are putting onto the event queue.
XSendEvent(disp,exit_window,False,0,reinterpret_cast<XEvent*>(&event));
XFlush(disp);
wait();
if (xim != NULL)
{
XCloseIM(xim);
}
XCloseDisplay(disp);
}
else
{
wait();
}
}
}
private:
void thread (
)
{
using namespace std;
using namespace dlib;
try
{
/*
// causes dead-lock when using with XIM
if (XInitThreads() == 0)
{
dlog << LFATAL << "Unable to initialize threading support.";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
*/
window_table.get_mutex().lock();
disp = XOpenDisplay(NULL);
window_table.get_mutex().unlock();
if (disp == 0)
{
window_table.get_mutex().lock();
disp = XOpenDisplay(":0.0");
window_table.get_mutex().unlock();
if (disp == 0)
{
dlog << LFATAL << "Unable to connect to the X display.";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
}
window_table.get_mutex().lock();
screen = DefaultScreenOfDisplay(disp);
depth = DefaultDepthOfScreen(screen);
delete_window = XInternAtom(disp,"WM_DELETE_WINDOW",1);
window_table.get_mutex().unlock();
xim = NULL;
window_table.get_mutex().lock();
if (setlocale( LC_CTYPE, "" ) && XSupportsLocale() && XSetLocaleModifiers("")){
xim = XOpenIM(disp, NULL, NULL, NULL);
}
window_table.get_mutex().unlock();
if (xim)
{
const static XIMStyle preedit_styles[] =
{XIMPreeditPosition, XIMPreeditNothing, XIMPreeditNone, 0};
const static XIMStyle status_styles[] =
{XIMStatusNothing, XIMStatusNone, 0};
xim_style = 0;
XIMStyles *xim_styles;
window_table.get_mutex().lock();
XGetIMValues (xim, XNQueryInputStyle, &xim_styles, NULL);
window_table.get_mutex().unlock();
std::set<XIMStyle> xims;
for (int i = 0; i < xim_styles->count_styles; ++i){
xims.insert(xim_styles->supported_styles[i]);
}
for (int j = 0; status_styles[j]; ++j){
for (int i = 0; preedit_styles[i]; ++i){
xim_style = (status_styles[j] | preedit_styles[i]);
if (xims.count(xim_style)) break;
}
if (xim_style) break;
}
XFree(xim_styles);
}
// make this window just so we can send messages to it and trigger
// events in the event thread
XSetWindowAttributes attr;
window_table.get_mutex().lock();
exit_window = XCreateWindow(
disp,
DefaultRootWindow(disp),
0,
0,
10, // this is the default width of a window
10, // this is the default width of a window
0,
depth,
InputOutput,
CopyFromParent,
0,
&attr
);
window_table.get_mutex().unlock();
// 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
event_handler();
}
catch (std::exception& e)
{
cout << "\nEXCEPTION THROWN: \n" << e.what() << endl;
abort();
}
catch (...)
{
cout << "UNKNOWN EXCEPTION THROWN.\n" << endl;
abort();
}
}
void event_handler();
void init_keyboard_mod_masks();
}; };
typedef sync_extension<queue<user_event_type,memory_manager<char>::kernel_1b>::kernel_2a_c>::kernel_1a queue_of_user_events; event_handler_thread& globals()
queue_of_user_events user_events; {
queue_of_user_events user_events_temp; static event_handler_thread* p = new event_handler_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;
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -361,7 +609,8 @@ namespace dlib ...@@ -361,7 +609,8 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
void event_handler ( void event_handler_thread::
event_handler (
) )
/*! /*!
ensures ensures
...@@ -477,7 +726,7 @@ namespace dlib ...@@ -477,7 +726,7 @@ namespace dlib
hints->max_width = win->width; hints->max_width = win->width;
hints->max_height = win->height; hints->max_height = win->height;
hints->min_height = win->height; hints->min_height = win->height;
XSetNormalHints(gui_core_kernel_2_globals::disp,win->x11_stuff.hwnd,hints); XSetNormalHints(disp,win->x11_stuff.hwnd,hints);
XFree(hints); XFree(hints);
} }
...@@ -485,18 +734,18 @@ namespace dlib ...@@ -485,18 +734,18 @@ namespace dlib
if (win->has_been_resized) if (win->has_been_resized)
{ {
XResizeWindow(gui_core_kernel_2_globals::disp,win->x11_stuff.hwnd,win->width,win->height); XResizeWindow(disp,win->x11_stuff.hwnd,win->width,win->height);
win->has_been_resized = false; win->has_been_resized = false;
win->on_window_resized(); win->on_window_resized();
} }
if (win->has_been_moved) if (win->has_been_moved)
{ {
XMoveWindow(gui_core_kernel_2_globals::disp,win->x11_stuff.hwnd,win->x,win->y); XMoveWindow(disp,win->x11_stuff.hwnd,win->x,win->y);
win->has_been_moved = false; win->has_been_moved = false;
win->on_window_moved(); win->on_window_moved();
} }
XFlush(gui_core_kernel_2_globals::disp); XFlush(disp);
} break; } break;
...@@ -760,7 +1009,7 @@ namespace dlib ...@@ -760,7 +1009,7 @@ namespace dlib
window_table.destroy(e->window); window_table.destroy(e->window);
XDestroyWindow(disp,e->window); XDestroyWindow(disp,e->window);
win->has_been_destroyed = true; win->has_been_destroyed = true;
gui_core_kernel_2_globals::window_close_signaler.broadcast(); window_close_signaler.broadcast();
} }
else else
{ {
...@@ -986,197 +1235,6 @@ namespace dlib ...@@ -986,197 +1235,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_2_globals;
if (is_alive())
{
if (status != failure_to_init)
{
using namespace gui_core_kernel_2_globals;
XConfigureEvent event;
event.type = ConfigureNotify;
event.send_event = True;
event.display = disp;
event.window = exit_window;
event.x = 1;
XFlush(disp);
XPutBackEvent(disp,reinterpret_cast<XEvent*>(&event));
XFlush(disp);
// This should cause XNextEvent() to unblock so that it will see
// this ConfigureNotify event we are putting onto the event queue.
XSendEvent(disp,exit_window,False,0,reinterpret_cast<XEvent*>(&event));
XFlush(disp);
wait();
if (xim != NULL)
{
XCloseIM(xim);
}
XCloseDisplay(disp);
}
else
{
wait();
}
}
}
private:
void thread (
)
{
using namespace std;
using namespace dlib;
using namespace gui_core_kernel_2_globals;
try
{
/*
// causes dead-lock when using with XIM
if (XInitThreads() == 0)
{
dlog << LFATAL << "Unable to initialize threading support.";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
*/
window_table.get_mutex().lock();
disp = XOpenDisplay(NULL);
window_table.get_mutex().unlock();
if (disp == 0)
{
window_table.get_mutex().lock();
disp = XOpenDisplay(":0.0");
window_table.get_mutex().unlock();
if (disp == 0)
{
dlog << LFATAL << "Unable to connect to the X display.";
// signal that an error has occurred
window_table.get_mutex().lock();
status = failure_to_init;
et_signaler.broadcast();
window_table.get_mutex().unlock();
return;
}
}
window_table.get_mutex().lock();
screen = DefaultScreenOfDisplay(disp);
depth = DefaultDepthOfScreen(screen);
delete_window = XInternAtom(disp,"WM_DELETE_WINDOW",1);
window_table.get_mutex().unlock();
xim = NULL;
window_table.get_mutex().lock();
if (setlocale( LC_CTYPE, "" ) && XSupportsLocale() && XSetLocaleModifiers("")){
xim = XOpenIM(disp, NULL, NULL, NULL);
}
window_table.get_mutex().unlock();
if (xim)
{
const static XIMStyle preedit_styles[] =
{XIMPreeditPosition, XIMPreeditNothing, XIMPreeditNone, 0};
const static XIMStyle status_styles[] =
{XIMStatusNothing, XIMStatusNone, 0};
xim_style = 0;
XIMStyles *xim_styles;
window_table.get_mutex().lock();
XGetIMValues (xim, XNQueryInputStyle, &xim_styles, NULL);
window_table.get_mutex().unlock();
std::set<XIMStyle> xims;
for (int i = 0; i < xim_styles->count_styles; ++i){
xims.insert(xim_styles->supported_styles[i]);
}
for (int j = 0; status_styles[j]; ++j){
for (int i = 0; preedit_styles[i]; ++i){
xim_style = (status_styles[j] | preedit_styles[i]);
if (xims.count(xim_style)) break;
}
if (xim_style) break;
}
XFree(xim_styles);
}
// make this window just so we can send messages to it and trigger
// events in the event thread
XSetWindowAttributes attr;
window_table.get_mutex().lock();
exit_window = XCreateWindow(
disp,
DefaultRootWindow(disp),
0,
0,
10, // this is the default width of a window
10, // this is the default width of a window
0,
depth,
InputOutput,
CopyFromParent,
0,
&attr
);
window_table.get_mutex().unlock();
// 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
event_handler();
}
catch (std::exception& e)
{
cout << "\nEXCEPTION THROWN: \n" << e.what() << endl;
abort();
}
catch (...)
{
cout << "UNKNOWN EXCEPTION THROWN.\n" << endl;
abort();
}
}
};
// ----------------------------------------------------------------------------------------
int index_to_modmask(unsigned long n) int index_to_modmask(unsigned long n)
{ {
...@@ -1194,7 +1252,8 @@ namespace dlib ...@@ -1194,7 +1252,8 @@ namespace dlib
return Mod5Mask; return Mod5Mask;
} }
void init_keyboard_mod_masks() void event_handler_thread::
init_keyboard_mod_masks()
{ {
XModifierKeymap* map = XGetModifierMapping( disp ); XModifierKeymap* map = XGetModifierMapping( disp );
KeyCode* codes = map->modifiermap + map->max_keypermod * Mod1MapIndex; KeyCode* codes = map->modifiermap + map->max_keypermod * Mod1MapIndex;
...@@ -1237,31 +1296,7 @@ namespace dlib ...@@ -1237,31 +1296,7 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
static event_handler_thread event_handler_thread_object;
void init_gui_core ()
{
using namespace dlib::gui_core_kernel_2_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_thread_object.start();
// wait for the event thread to get up and running
while (event_handler_thread_object.status == event_handler_thread::uninitialized)
et_signaler.wait();
if (event_handler_thread_object.status == event_handler_thread::failure_to_init)
throw gui_error("Failed to initialize X11 resources");
init_keyboard_mod_masks();
}
}
...@@ -1313,12 +1348,10 @@ namespace dlib ...@@ -1313,12 +1348,10 @@ namespace dlib
) )
{ {
using namespace gui_core_kernel_2_globals; using namespace gui_core_kernel_2_globals;
init_gui_core(); auto_mutex M(globals().window_table.get_mutex());
auto_mutex M(window_table.get_mutex()); globals().clipboard = str.c_str();
clipboard = str;
clipboard[0] = clipboard[0];
XSetSelectionOwner(disp,XA_PRIMARY,exit_window,CurrentTime); XSetSelectionOwner(globals().disp,XA_PRIMARY,globals().exit_window,CurrentTime);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1362,8 +1395,7 @@ namespace dlib ...@@ -1362,8 +1395,7 @@ namespace dlib
) )
{ {
using namespace gui_core_kernel_2_globals; using namespace gui_core_kernel_2_globals;
init_gui_core(); auto_mutex M(globals().window_table.get_mutex());
auto_mutex M(window_table.get_mutex());
str.clear(); str.clear();
unsigned char *data = 0; unsigned char *data = 0;
wchar_t **plist = 0; wchar_t **plist = 0;
...@@ -1375,13 +1407,12 @@ namespace dlib ...@@ -1375,13 +1407,12 @@ namespace dlib
try try
{ {
Atom atom_ct = XInternAtom(disp, "COMPOUND_TEXT", False); Atom atom_ct = XInternAtom(globals().disp, "COMPOUND_TEXT", False);
sown = XGetSelectionOwner (disp, XA_PRIMARY); sown = XGetSelectionOwner (globals().disp, XA_PRIMARY);
if (sown == exit_window) if (sown == globals().exit_window)
{ {
// if we are copying from ourselfs then don't fool with the Xwindows junk. // if we are copying from ourselfs then don't fool with the Xwindows junk.
str = clipboard; str = globals().clipboard.c_str();
str[0] = str[0];
} }
else if (sown != None) else if (sown != None)
{ {
...@@ -1389,15 +1420,15 @@ namespace dlib ...@@ -1389,15 +1420,15 @@ namespace dlib
// of the exit_window. It doesn't matter what window we put it in // of the exit_window. It doesn't matter what window we put it in
// so long as it is one under the control of this process and exit_window // so long as it is one under the control of this process and exit_window
// is easy to use here so that is what I'm using. // is easy to use here so that is what I'm using.
XConvertSelection (disp, XA_PRIMARY, atom_ct, XA_PRIMARY, XConvertSelection (globals().disp, XA_PRIMARY, atom_ct, XA_PRIMARY,
exit_window, CurrentTime); globals().exit_window, CurrentTime);
// This will wait until we get a SelectionNotify event which should happen // This will wait until we get a SelectionNotify event which should happen
// really soon. // really soon.
XPeekIfEvent(disp,&e,clip_peek_helper,0); XPeekIfEvent(globals().disp,&e,clip_peek_helper,0);
// See how much data we got // See how much data we got
XGetWindowProperty (disp, exit_window, XGetWindowProperty (globals().disp, globals().exit_window,
XA_PRIMARY, // Tricky.. XA_PRIMARY, // Tricky..
0, 0, // offset - len 0, 0, // offset - len
0, // Delete 0==FALSE 0, // Delete 0==FALSE
...@@ -1414,14 +1445,14 @@ namespace dlib ...@@ -1414,14 +1445,14 @@ namespace dlib
if (bytes_left > 0 && type == atom_ct) if (bytes_left > 0 && type == atom_ct)
{ {
XTextProperty p; XTextProperty p;
result = XGetWindowProperty (disp, exit_window, result = XGetWindowProperty (globals().disp, globals().exit_window,
XA_PRIMARY, 0,bytes_left,0, XA_PRIMARY, 0,bytes_left,0,
AnyPropertyType, &p.encoding,&p.format, AnyPropertyType, &p.encoding,&p.format,
&p.nitems, &dummy, &p.value); &p.nitems, &dummy, &p.value);
if (result == Success && p.encoding == atom_ct) if (result == Success && p.encoding == atom_ct)
{ {
int n; int n;
XwcTextPropertyToTextList(disp, &p, &plist, &n); XwcTextPropertyToTextList(globals().disp, &p, &plist, &n);
str = plist[0]; str = plist[0];
} }
if (plist) if (plist)
...@@ -1452,18 +1483,18 @@ namespace dlib ...@@ -1452,18 +1483,18 @@ namespace dlib
void* void*
) )
{ {
auto_mutex M(window_table.get_mutex()); auto_mutex M(globals().window_table.get_mutex());
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_ = globals().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.
...@@ -1471,12 +1502,12 @@ namespace dlib ...@@ -1471,12 +1502,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();
} }
} }
...@@ -1492,12 +1523,12 @@ namespace dlib ...@@ -1492,12 +1523,12 @@ 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);
// we only need to start a thread to deal with this if there isn't already // we only need to start a thread to deal with this if there isn't already
// one out working on the queue // one out working on the queue
if (user_events.size() == 1) if (globals().user_events.size() == 1)
create_new_thread (trigger_user_event_threadproc,0); create_new_thread (trigger_user_event_threadproc,0);
} }
} }
...@@ -1515,15 +1546,14 @@ namespace dlib ...@@ -1515,15 +1546,14 @@ namespace dlib
has_been_destroyed(false), has_been_destroyed(false),
has_been_resized(false), has_been_resized(false),
has_been_moved(false), has_been_moved(false),
wm(gui_core_kernel_2_globals::window_table.get_mutex()) wm(gui_core_kernel_2_globals::globals().window_table.get_mutex())
{ {
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
); );
using namespace gui_core_kernel_2_globals;
gui_core_kernel_2_globals::init_gui_core();
auto_mutex M(wm); auto_mutex M(wm);
...@@ -1542,15 +1572,16 @@ namespace dlib ...@@ -1542,15 +1572,16 @@ namespace dlib
valuemask = CWOverrideRedirect; valuemask = CWOverrideRedirect;
} }
x11_stuff.hwnd = XCreateWindow( x11_stuff.hwnd = XCreateWindow(
gui_core_kernel_2_globals::disp, globals().disp,
DefaultRootWindow(gui_core_kernel_2_globals::disp), DefaultRootWindow(globals().disp),
0, 0,
0, 0,
10, // this is the default width of a window 10, // this is the default width of a window
10, // this is the default width of a window 10, // this is the default width of a window
0, 0,
gui_core_kernel_2_globals::depth, globals().depth,
InputOutput, InputOutput,
CopyFromParent, CopyFromParent,
valuemask, valuemask,
...@@ -1558,7 +1589,7 @@ namespace dlib ...@@ -1558,7 +1589,7 @@ namespace dlib
); );
x11_stuff.xic = NULL; x11_stuff.xic = NULL;
if (gui_core_kernel_2_globals::xim) if (globals().xim)
{ {
XVaNestedList xva_nlist; XVaNestedList xva_nlist;
XPoint xpoint; XPoint xpoint;
...@@ -1569,13 +1600,13 @@ namespace dlib ...@@ -1569,13 +1600,13 @@ namespace dlib
char fontset[256]; char fontset[256];
const long native_font_height = 12; const long native_font_height = 12;
sprintf(fontset, "-*-*-medium-r-normal--%lu-*-*-*-", native_font_height); sprintf(fontset, "-*-*-medium-r-normal--%lu-*-*-*-", native_font_height);
x11_stuff.fs = XCreateFontSet(gui_core_kernel_2_globals::disp, fontset, &mlist, &mcount, &def_str); x11_stuff.fs = XCreateFontSet(globals().disp, fontset, &mlist, &mcount, &def_str);
xpoint.x = 0; xpoint.x = 0;
xpoint.y = 0; xpoint.y = 0;
xva_nlist = XVaCreateNestedList(0, XNSpotLocation, &xpoint, XNFontSet, x11_stuff.fs, NULL); xva_nlist = XVaCreateNestedList(0, XNSpotLocation, &xpoint, XNFontSet, x11_stuff.fs, NULL);
x11_stuff.xic = XCreateIC( x11_stuff.xic = XCreateIC(
gui_core_kernel_2_globals::xim, globals().xim,
XNInputStyle, gui_core_kernel_2_globals::xim_style, XNInputStyle, globals().xim_style,
XNClientWindow, x11_stuff.hwnd, XNClientWindow, x11_stuff.hwnd,
XNPreeditAttributes, xva_nlist, XNPreeditAttributes, xva_nlist,
NULL NULL
...@@ -1586,7 +1617,7 @@ namespace dlib ...@@ -1586,7 +1617,7 @@ namespace dlib
Window temp = x11_stuff.hwnd; Window temp = x11_stuff.hwnd;
base_window* ttemp = this; base_window* ttemp = this;
gui_core_kernel_2_globals::window_table.add(temp,ttemp); globals().window_table.add(temp,ttemp);
// query event mask required by input method // query event mask required by input method
unsigned long event_xim = 0; unsigned long event_xim = 0;
...@@ -1594,7 +1625,7 @@ namespace dlib ...@@ -1594,7 +1625,7 @@ namespace dlib
XGetICValues( x11_stuff.xic, XNFilterEvents, &event_xim, NULL ); XGetICValues( x11_stuff.xic, XNFilterEvents, &event_xim, NULL );
XSelectInput( XSelectInput(
gui_core_kernel_2_globals::disp, globals().disp,
x11_stuff.hwnd, x11_stuff.hwnd,
StructureNotifyMask|ExposureMask|ButtonPressMask|ButtonReleaseMask| StructureNotifyMask|ExposureMask|ButtonPressMask|ButtonReleaseMask|
PointerMotionMask|LeaveWindowMask|EnterWindowMask|KeyPressMask| PointerMotionMask|LeaveWindowMask|EnterWindowMask|KeyPressMask|
...@@ -1602,9 +1633,9 @@ namespace dlib ...@@ -1602,9 +1633,9 @@ namespace dlib
); );
XSetWMProtocols( XSetWMProtocols(
gui_core_kernel_2_globals::disp, globals().disp,
x11_stuff.hwnd, x11_stuff.hwnd,
&gui_core_kernel_2_globals::delete_window, &globals().delete_window,
1 1
); );
...@@ -1623,7 +1654,7 @@ namespace dlib ...@@ -1623,7 +1654,7 @@ namespace dlib
hints->max_width = width; hints->max_width = width;
hints->max_height = height; hints->max_height = height;
hints->min_height = height; hints->min_height = height;
XSetNormalHints(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,hints); XSetNormalHints(globals().disp,x11_stuff.hwnd,hints);
XFree(hints); XFree(hints);
} }
} }
...@@ -1634,8 +1665,23 @@ namespace dlib ...@@ -1634,8 +1665,23 @@ namespace dlib
~base_window ( ~base_window (
) )
{ {
using namespace gui_core_kernel_2_globals;
close_window(); close_window();
delete &x11_stuff; delete &x11_stuff;
// 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();
}
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1644,22 +1690,23 @@ namespace dlib ...@@ -1644,22 +1690,23 @@ namespace dlib
close_window ( close_window (
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex M(wm); auto_mutex M(wm);
if (has_been_destroyed == false) if (has_been_destroyed == false)
{ {
has_been_destroyed = true; has_been_destroyed = true;
gui_core_kernel_2_globals::window_table.destroy(x11_stuff.hwnd); globals().window_table.destroy(x11_stuff.hwnd);
if (gui_core_kernel_2_globals::xim != NULL) if (globals().xim != NULL)
{ {
XDestroyIC(x11_stuff.xic); XDestroyIC(x11_stuff.xic);
x11_stuff.xic = 0; x11_stuff.xic = 0;
XFreeFontSet(gui_core_kernel_2_globals::disp,x11_stuff.fs); XFreeFontSet(globals().disp,x11_stuff.fs);
} }
XDestroyWindow(gui_core_kernel_2_globals::disp,x11_stuff.hwnd); XDestroyWindow(globals().disp,x11_stuff.hwnd);
x11_stuff.hwnd = 0; x11_stuff.hwnd = 0;
gui_core_kernel_2_globals::window_close_signaler.broadcast(); globals().window_close_signaler.broadcast();
} }
} }
...@@ -1696,6 +1743,7 @@ namespace dlib ...@@ -1696,6 +1743,7 @@ namespace dlib
const std::wstring& title_ const std::wstring& title_
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex M(wm); auto_mutex M(wm);
DLIB_ASSERT(is_closed() == false, DLIB_ASSERT(is_closed() == false,
"\tvoid base_window::set_title" "\tvoid base_window::set_title"
...@@ -1706,10 +1754,10 @@ namespace dlib ...@@ -1706,10 +1754,10 @@ namespace dlib
// it isn't const anymore. // it isn't const anymore.
wchar_t *title = const_cast<wchar_t *>(title_.c_str()); wchar_t *title = const_cast<wchar_t *>(title_.c_str());
XTextProperty property; XTextProperty property;
XwcTextListToTextProperty(gui_core_kernel_2_globals::disp,&title,1,XStdICCTextStyle, &property); XwcTextListToTextProperty(globals().disp,&title,1,XStdICCTextStyle, &property);
XSetWMName(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,&property); XSetWMName(globals().disp,x11_stuff.hwnd,&property);
XFree(property.value); XFree(property.value);
XFlush(gui_core_kernel_2_globals::disp); XFlush(globals().disp);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1718,14 +1766,15 @@ namespace dlib ...@@ -1718,14 +1766,15 @@ namespace dlib
show ( show (
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex M(wm); auto_mutex M(wm);
DLIB_ASSERT(is_closed() == false, DLIB_ASSERT(is_closed() == false,
"\tvoid base_window::show" "\tvoid base_window::show"
<< "\n\tYou can't do this to a window that has been closed." << "\n\tYou can't do this to a window that has been closed."
<< "\n\tthis: " << this << "\n\tthis: " << this
); );
XMapRaised(gui_core_kernel_2_globals::disp,x11_stuff.hwnd); XMapRaised(globals().disp,x11_stuff.hwnd);
XFlush(gui_core_kernel_2_globals::disp); XFlush(globals().disp);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1734,9 +1783,10 @@ namespace dlib ...@@ -1734,9 +1783,10 @@ namespace dlib
wait_until_closed ( wait_until_closed (
) const ) const
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex M(wm); auto_mutex M(wm);
while (has_been_destroyed == false) while (has_been_destroyed == false)
gui_core_kernel_2_globals::window_close_signaler.wait(); globals().window_close_signaler.wait();
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1745,14 +1795,15 @@ namespace dlib ...@@ -1745,14 +1795,15 @@ namespace dlib
hide ( hide (
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex M(wm); auto_mutex M(wm);
DLIB_ASSERT(is_closed() == false, DLIB_ASSERT(is_closed() == false,
"\tvoid base_window::hide" "\tvoid base_window::hide"
<< "\n\tYou can't do this to a window that has been closed." << "\n\tYou can't do this to a window that has been closed."
<< "\n\tthis: " << this << "\n\tthis: " << this
); );
XUnmapWindow(gui_core_kernel_2_globals::disp,x11_stuff.hwnd); XUnmapWindow(globals().disp,x11_stuff.hwnd);
XFlush(gui_core_kernel_2_globals::disp); XFlush(globals().disp);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1763,6 +1814,7 @@ namespace dlib ...@@ -1763,6 +1814,7 @@ namespace dlib
int height_ int height_
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex a(wm); auto_mutex a(wm);
DLIB_ASSERT(is_closed() == false, DLIB_ASSERT(is_closed() == false,
"\tvoid base_window::set_size" "\tvoid base_window::set_size"
...@@ -1790,13 +1842,13 @@ namespace dlib ...@@ -1790,13 +1842,13 @@ namespace dlib
hints->max_width = width; hints->max_width = width;
hints->max_height = height; hints->max_height = height;
hints->min_height = height; hints->min_height = height;
XSetNormalHints(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,hints); XSetNormalHints(globals().disp,x11_stuff.hwnd,hints);
XFree(hints); XFree(hints);
} }
XResizeWindow(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,width,height); XResizeWindow(globals().disp,x11_stuff.hwnd,width,height);
XFlush(gui_core_kernel_2_globals::disp); XFlush(globals().disp);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1807,6 +1859,7 @@ namespace dlib ...@@ -1807,6 +1859,7 @@ namespace dlib
long y_ long y_
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex a(wm); auto_mutex a(wm);
DLIB_ASSERT(is_closed() == false, DLIB_ASSERT(is_closed() == false,
"\tvoid base_window::set_pos" "\tvoid base_window::set_pos"
...@@ -1821,8 +1874,8 @@ namespace dlib ...@@ -1821,8 +1874,8 @@ namespace dlib
has_been_moved = true; has_been_moved = true;
XMoveWindow(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,x,y); XMoveWindow(globals().disp,x11_stuff.hwnd,x,y);
XFlush(gui_core_kernel_2_globals::disp); XFlush(globals().disp);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1833,6 +1886,7 @@ namespace dlib ...@@ -1833,6 +1886,7 @@ namespace dlib
long& y_ long& y_
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex a(wm); auto_mutex a(wm);
DLIB_ASSERT(is_closed() == false, DLIB_ASSERT(is_closed() == false,
"\tvoid base_window::get_pos" "\tvoid base_window::get_pos"
...@@ -1844,9 +1898,9 @@ namespace dlib ...@@ -1844,9 +1898,9 @@ namespace dlib
// will have reported bogus values back in the ConfigureNotify event. So just to be // will have reported bogus values back in the ConfigureNotify event. So just to be
// on the safe side we will use XTranslateCoordinates() // on the safe side we will use XTranslateCoordinates()
int rx, ry; int rx, ry;
Window desktop_window = DefaultRootWindow(gui_core_kernel_2_globals::disp); Window desktop_window = DefaultRootWindow(globals().disp);
Window junk; Window junk;
XTranslateCoordinates(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,desktop_window,0,0,&rx, &ry, &junk); XTranslateCoordinates(globals().disp,x11_stuff.hwnd,desktop_window,0,0,&rx, &ry, &junk);
x_ = rx; x_ = rx;
y_ = ry; y_ = ry;
x = rx; x = rx;
...@@ -1880,6 +1934,7 @@ namespace dlib ...@@ -1880,6 +1934,7 @@ namespace dlib
unsigned long& height_ unsigned long& height_
) const ) const
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex M(wm); auto_mutex M(wm);
DLIB_ASSERT(is_closed() == false, DLIB_ASSERT(is_closed() == false,
"\tvoid base_window::get_display_size" "\tvoid base_window::get_display_size"
...@@ -1887,10 +1942,9 @@ namespace dlib ...@@ -1887,10 +1942,9 @@ namespace dlib
<< "\n\tthis: " << this << "\n\tthis: " << this
); );
using namespace gui_core_kernel_2_globals; int screen_number = XScreenNumberOfScreen(globals().screen);
int screen_number = XScreenNumberOfScreen(screen); width_ = DisplayWidth(globals().disp, screen_number);
width_ = DisplayWidth(disp, screen_number); height_ = DisplayHeight(globals().disp, screen_number);
height_ = DisplayHeight(disp, screen_number);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1900,6 +1954,7 @@ namespace dlib ...@@ -1900,6 +1954,7 @@ namespace dlib
const rectangle& rect const rectangle& rect
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex a(wm); auto_mutex a(wm);
if (is_mapped == false) if (is_mapped == false)
return; return;
...@@ -1911,8 +1966,8 @@ namespace dlib ...@@ -1911,8 +1966,8 @@ namespace dlib
const unsigned long width = rect.width(); const unsigned long width = rect.width();
const unsigned long height = rect.height(); const unsigned long height = rect.height();
XClearArea(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,x,y,width,height,1); XClearArea(globals().disp,x11_stuff.hwnd,x,y,width,height,1);
XFlush(gui_core_kernel_2_globals::disp); XFlush(globals().disp);
} }
} }
...@@ -1924,8 +1979,9 @@ namespace dlib ...@@ -1924,8 +1979,9 @@ namespace dlib
long y long y
) )
{ {
using namespace gui_core_kernel_2_globals;
auto_mutex a(wm); auto_mutex a(wm);
if (!x11_stuff.xic || !(gui_core_kernel_2_globals::xim_style & XIMPreeditPosition)) return; if (!x11_stuff.xic || !(globals().xim_style & XIMPreeditPosition)) return;
XVaNestedList xva_nlist; XVaNestedList xva_nlist;
XPoint xpoint; XPoint xpoint;
......
...@@ -31,7 +31,7 @@ namespace dlib ...@@ -31,7 +31,7 @@ namespace dlib
namespace gui_core_kernel_2_globals namespace gui_core_kernel_2_globals
{ {
void event_handler (); class event_handler_thread;
void trigger_user_event_threadproc (void*); void trigger_user_event_threadproc (void*);
// This is a forward declaration for a struct that contains any // This is a forward declaration for a struct that contains any
...@@ -109,7 +109,8 @@ namespace dlib ...@@ -109,7 +109,8 @@ namespace dlib
private: private:
friend void gui_core_kernel_2_globals::event_handler (); friend class gui_core_kernel_2_globals::event_handler_thread;
canvas ( canvas (
unsigned char* bits__, unsigned char* bits__,
...@@ -152,7 +153,7 @@ namespace dlib ...@@ -152,7 +153,7 @@ namespace dlib
class base_window class base_window
{ {
friend void gui_core_kernel_2_globals::event_handler (); friend class gui_core_kernel_2_globals::event_handler_thread;
friend void gui_core_kernel_2_globals::trigger_user_event_threadproc (void*); friend void gui_core_kernel_2_globals::trigger_user_event_threadproc (void*);
public: public:
......
...@@ -41,11 +41,6 @@ namespace dlib ...@@ -41,11 +41,6 @@ namespace dlib
base_window base_window
All methods for this class are thread safe. You may call them All methods for this class are thread safe. You may call them
from any thread and do not need to serialize access. from any thread and do not need to serialize access.
GENERAL WARNING
You can't make base_window objects before main() has been entered or
call get_from_clipboard() or put_on_clipboard() before
main() has been entered.
!*/ !*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
...@@ -771,7 +771,7 @@ private: ...@@ -771,7 +771,7 @@ private:
}; };
win w; win w;
int main() int main()
{ {
......
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