00001 #ifndef ANCHOR_WINDOW_IMPLEMENTATION_FILE
00002 #define ANCHOR_WINDOW_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "anchor_window.h"
00019
00020 #include <basis/array.cpp>
00021 #include <basis/convert_utf.h>
00022 #include <basis/istring.h>
00023 #include <basis/log_base.h>
00024 #include <basis/portable.h>
00025 #include <data_struct/static_memory_gremlin.h>
00026 #include <opsystem/filename.h>
00027
00028 #undef LOG
00029 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00030
00031 #ifdef __WIN32__
00032 const int STARTUP_MESSAGE = WM_USER + 123;
00033
00034
00035 const int TIMER_EVENT_ID = 23;
00036
00037
00038
00039
00040 struct window_association {
00041 window_handle _handle;
00042 anchor_window *_window_object;
00043
00044 window_association(window_handle wh = NIL, anchor_window *wo = NIL)
00045 : _handle(wh), _window_object(wo) {}
00046 };
00047
00048 class window_association_list
00049 : public array<window_association>, public virtual object_base
00050 {
00051 public:
00052 IMPLEMENT_CLASS_NAME("window_association_list");
00053 };
00054
00055
00056
00057
00058 SAFE_STATIC(window_association_list, associations, )
00059 #endif //win32
00060
00062
00063 anchor_window::anchor_window()
00064 #ifdef __LINUX__
00065 : shutdown_alerter()
00066 #endif
00067 #ifdef __WIN32__
00068 : _instance(NIL),
00069 _window_title(new istring),
00070 _window_class(new istring),
00071 _class_reg(NIL),
00072 _wind_handle(NIL),
00073 _cycle(0),
00074 _defunct(false)
00075 #endif
00076 {
00077 }
00078
00079 anchor_window::~anchor_window()
00080 {
00081 set_defunct();
00082 #ifdef __WIN32__
00083 WHACK(_window_title);
00084 WHACK(_window_class);
00085 _class_reg = NIL;
00086
00087 for (int i = 0; i < associations().length(); i++) {
00088 if (associations()[i]._handle == _wind_handle) {
00089 associations().zap(i, i);
00090 break;
00091 }
00092 }
00093 #endif
00094 }
00095
00096 void anchor_window::handle_startup() { }
00097
00098 void anchor_window::handle_timer() { }
00099
00100 void anchor_window::handle_shutdown() { }
00101
00102 bool anchor_window::close_this_program()
00103 {
00104 #ifdef __LINUX__
00105 shutdown_alerter::close_this_program();
00106 return true;
00107 #endif
00108 #ifdef __WIN32__
00109 bool to_return = false;
00110 for (int i = 0; i < associations().length(); i++) {
00111 window_handle win = associations()[i]._handle;
00112 int ret = PostMessage(win, WM_CLOSE, NIL, NIL);
00113
00114 if (ret) to_return = true;
00115 }
00116 return to_return;
00117 #endif
00118 }
00119
00120 bool anchor_window::defunct() const
00121 {
00122 #ifdef __LINUX__
00123 return shutdown_alerter::is_defunct();
00124 #endif
00125 #ifdef __WIN32__
00126 return _defunct;
00127 #endif
00128 }
00129
00130 void anchor_window::set_defunct()
00131 {
00132 #ifdef __LINUX__
00133 return shutdown_alerter::set_defunct();
00134 #endif
00135 #ifdef __WIN32__
00136 _defunct = true;
00137 #endif
00138 }
00139
00140 bool anchor_window::close_app_window(const istring &app_name)
00141 {
00142 FUNCDEF("close_app_window");
00143 #ifdef __LINUX__
00144 return shutdown_alerter::close_application(app_name);
00145 #endif
00146 #ifdef __WIN32__
00147 istring title = anchor_window::make_well_known_title(app_name);
00148 #ifdef DEBUG_PROCESS_MANAGER
00149 LOG(istring("title is: ") + title);
00150 #endif
00151
00152
00153 #ifdef __WIN32__
00154 window_handle win_found = FindWindow(NIL, to_unicode_temp(title));
00155 #ifdef DEBUG_PROCESS_MANAGER
00156 LOG(istring(istring::SPRINTF, "found window %lx", win_found));
00157 #endif
00158 if (!win_found) {
00159 LOG(istring("Failed to find special window for [") + app_name
00160 + istring("]"));
00161 return false;
00162 }
00163
00164
00165
00166
00167
00168 int ret = PostMessage(win_found, WM_CLOSE, NIL, NIL);
00169 if (!ret) {
00170 LOG(istring("Failed to send close message to [") + app_name
00171 + istring("]"));
00172 return false;
00173 }
00174
00175 LOG(istring("Sent close message to [") + app_name + istring("]"));
00176 #else
00177 #ifdef DEBUG_PROCESS_MANAGER
00178 LOG("graceful shutdown not implemented for this OS.");
00179 #endif
00180 return false;
00181 #endif
00182 return true;
00183 #endif //win32
00184 }
00185
00186 bool anchor_window::setup(application_instance instance,
00187 const istring &app_name, int cycle)
00188 {
00189 #ifdef __LINUX__
00190 if (instance) {}
00191 return shutdown_alerter::setup(app_name, cycle);
00192 #endif
00193 #ifdef __WIN32__
00194 if (_wind_handle) return true;
00195
00196 _instance = instance;
00197 _cycle = cycle;
00198 *_window_title = make_well_known_title(app_name);
00199 *_window_class = make_well_known_class(app_name);
00200 _class_reg = register_class();
00201 _wind_handle = CreateWindow(to_unicode_temp(*_window_class),
00202 to_unicode_temp(*_window_title), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
00203 0, CW_USEDEFAULT, 0, NIL, NIL, _instance, NIL);
00204 if (!_wind_handle) return false;
00205
00206 register_window(_wind_handle);
00207 ShowWindow(_wind_handle, SW_HIDE);
00208 UpdateWindow(_wind_handle);
00209 PostMessage(_wind_handle, STARTUP_MESSAGE, 0, 0);
00210 #endif //win32
00211 return true;
00212 }
00213
00214 void anchor_window::register_window(window_handle wind)
00215 {
00216 #ifdef __WIN32__
00217
00218 associations() += window_association(wind, this);
00219 #else
00220 if (wind) {}
00221 #endif
00222 }
00223
00224 #ifdef __WIN32__
00225 ATOM anchor_window::register_class()
00226 {
00227 WNDCLASSEX wcex;
00228
00229 wcex.cbSize = sizeof(WNDCLASSEX);
00230
00231 wcex.style = CS_HREDRAW | CS_VREDRAW;
00232 wcex.lpfnWndProc = (WNDPROC)WndProc;
00233 wcex.cbClsExtra = 0;
00234 wcex.cbWndExtra = 0;
00235 wcex.hInstance = _instance;
00236 wcex.hIcon = NIL;
00237 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
00238 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
00239 wcex.lpszMenuName = NIL;
00240 to_unicode_persist(hold_class, _window_class->s());
00241 wcex.lpszClassName = hold_class;
00242 wcex.hIconSm = NIL;
00243
00244 return RegisterClassEx(&wcex);
00245 }
00246 #endif
00247
00248 #ifdef __WIN32__
00249 LRESULT CALLBACK anchor_window::WndProc(HWND hWnd, UINT message,
00250 WPARAM wParam, LPARAM lParam)
00251 {
00252 switch (message) {
00253 case STARTUP_MESSAGE: {
00254 for (int i = 0; i < associations().length(); i++) {
00255 if (associations()[i]._handle == hWnd) {
00256 anchor_window &anch = *associations()[i]._window_object;
00257
00258 anch.handle_startup();
00259
00260
00261 if (anch._cycle)
00262 SetTimer(anch._wind_handle, TIMER_EVENT_ID, anch._cycle, 0);
00263 break;
00264 }
00265 }
00266 break;
00267 }
00268 case WM_CLOSE: {
00269 for (int i = 0; i < associations().length(); i++) {
00270 if (associations()[i]._handle == hWnd) {
00271
00272 associations()[i]._window_object->handle_shutdown();
00273 associations()[i]._window_object->set_defunct();
00274 break;
00275 }
00276 }
00277 return DefWindowProc(hWnd, message, wParam, lParam);
00278 break;
00279 }
00280 case WM_DESTROY: {
00281 PostQuitMessage(0);
00282 break;
00283 }
00284 case WM_TIMER: {
00285 bool found_window = false;
00286 for (int i = 0; i < associations().length(); i++)
00287 if (associations()[i]._handle == hWnd) {
00288
00289
00290 KillTimer(hWnd, TIMER_EVENT_ID);
00291
00292 associations()[i]._window_object->handle_timer();
00293 found_window = true;
00294
00295 SetTimer(hWnd, TIMER_EVENT_ID,
00296 associations()[i]._window_object->_cycle, 0);
00297 break;
00298 }
00299 bool to_return = 0;
00300
00301
00302 if (!found_window)
00303 to_return = DefWindowProc(hWnd, message, wParam, lParam);
00304 return to_return;
00305 }
00306 case WM_PAINT: {
00307 PAINTSTRUCT ps;
00308 HDC hdc = BeginPaint(hWnd, &ps);
00309
00310 EndPaint(hWnd, &ps);
00311 break;
00312 }
00313 default: return DefWindowProc(hWnd, message, wParam, lParam);
00314 }
00315 return 0;
00316 }
00317 #endif
00318
00319 #ifdef __WIN32__
00320 istring anchor_window::make_well_known_title(const istring &application_name)
00321 {
00322 filename app_short = application_name;
00323 return istring("Anchor_for_") + app_short.basename();
00324 }
00325 #endif
00326
00327 #ifdef __WIN32__
00328 istring anchor_window::make_well_known_class(const istring &application_name)
00329 {
00330 filename app_short = application_name;
00331 return istring("Dozeclass_for_") + app_short.basename();
00332 }
00333 #endif
00334
00335 bool anchor_window::launch(anchor_window &win, application_instance handle,
00336 const istring &application_name, int cycle)
00337 {
00338
00339 if (!win.setup(handle, application_name, cycle)) return false;
00340 #ifdef __LINUX__
00341 return shutdown_alerter::launch_console(win, application_name, cycle);
00342 #endif
00343 #ifdef __WIN32__
00344 MSG msg;
00345 msg.hwnd = 0; msg.message = 0; msg.wParam = 0; msg.lParam = 0;
00346 while (GetMessage(&msg, NIL, 0, 0)) {
00347 TranslateMessage(&msg);
00348 DispatchMessage(&msg);
00349 }
00350 #endif
00351 return true;
00352 }
00353
00354
00355 #endif //ANCHOR_WINDOW_IMPLEMENTATION_FILE
00356