285 { |
285 { |
286 if (w == NULL) return; |
286 if (w == NULL) return; |
287 SetDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height); |
287 SetDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height); |
288 } |
288 } |
289 |
289 |
|
290 /** Find the Window whose parent pointer points to this window |
|
291 * @parent w Window to find child of |
|
292 * @return return a Window pointer that is the child of w, or NULL otherwise */ |
|
293 static Window *FindChildWindow(const Window *w) |
|
294 { |
|
295 Window* const *wz; |
|
296 |
|
297 FOR_ALL_WINDOWS(wz) { |
|
298 Window *v = *wz; |
|
299 if (v->parent == w) return v; |
|
300 } |
|
301 |
|
302 return NULL; |
|
303 } |
|
304 |
290 /** Find the z-value of a window. A window must already be open |
305 /** Find the z-value of a window. A window must already be open |
291 * or the behaviour is undefined but function should never fail */ |
306 * or the behaviour is undefined but function should never fail */ |
292 Window **FindWindowZPosition(const Window *w) |
307 Window **FindWindowZPosition(const Window *w) |
293 { |
308 { |
294 Window **wz; |
309 Window **wz; |
295 |
310 |
296 for (wz = _z_windows;; wz++) { |
311 for (wz = _z_windows; wz != _last_z_window; wz++) { |
297 assert(wz < _last_z_window); |
|
298 if (*wz == w) return wz; |
312 if (*wz == w) return wz; |
299 } |
313 } |
|
314 |
|
315 DEBUG(misc, 3, "Window (class %d, number %d) is not open, probably removed by recursive calls", |
|
316 w->window_class, w->window_number); |
|
317 return NULL; |
300 } |
318 } |
301 |
319 |
302 void DeleteWindow(Window *w) |
320 void DeleteWindow(Window *w) |
303 { |
321 { |
|
322 Window *v; |
304 Window **wz; |
323 Window **wz; |
305 if (w == NULL) return; |
324 if (w == NULL) return; |
|
325 |
|
326 /* Delete any children a window might have in a head-recursive manner */ |
|
327 v = FindChildWindow(w); |
|
328 if (v != NULL) DeleteWindow(v); |
306 |
329 |
307 if (_thd.place_mode != VHM_NONE && |
330 if (_thd.place_mode != VHM_NONE && |
308 _thd.window_class == w->window_class && |
331 _thd.window_class == w->window_class && |
309 _thd.window_number == w->window_number) { |
332 _thd.window_number == w->window_number) { |
310 ResetObjectToPlace(); |
333 ResetObjectToPlace(); |
315 |
338 |
316 SetWindowDirty(w); |
339 SetWindowDirty(w); |
317 free(w->widget); |
340 free(w->widget); |
318 w->widget = NULL; |
341 w->widget = NULL; |
319 w->widget_count = 0; |
342 w->widget_count = 0; |
|
343 w->parent = NULL; |
320 |
344 |
321 /* Find the window in the z-array, and effectively remove it |
345 /* Find the window in the z-array, and effectively remove it |
322 * by moving all windows after it one to the left */ |
346 * by moving all windows after it one to the left */ |
323 wz = FindWindowZPosition(w); |
347 wz = FindWindowZPosition(w); |
|
348 if (wz == NULL) return; |
324 memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz); |
349 memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz); |
325 _last_z_window--; |
350 _last_z_window--; |
326 } |
351 } |
327 |
352 |
328 Window *FindWindowById(WindowClass cls, WindowNumber number) |
353 Window *FindWindowById(WindowClass cls, WindowNumber number) |
873 _no_scroll = 0; |
898 _no_scroll = 0; |
874 } |
899 } |
875 |
900 |
876 void UnInitWindowSystem(void) |
901 void UnInitWindowSystem(void) |
877 { |
902 { |
878 Window* const *wz; |
903 Window **wz; |
879 // delete all malloced widgets |
904 /* Delete all malloced widgets, and reset z-array */ |
880 FOR_ALL_WINDOWS(wz) { |
905 FOR_ALL_WINDOWS(wz) { |
881 free((*wz)->widget); |
906 free((*wz)->widget); |
882 (*wz)->widget = NULL; |
907 (*wz)->widget = NULL; |
883 (*wz)->widget_count = 0; |
908 (*wz)->widget_count = 0; |
884 } |
909 *wz = NULL; |
|
910 } |
|
911 _last_z_window = _z_windows; |
885 } |
912 } |
886 |
913 |
887 void ResetWindowSystem(void) |
914 void ResetWindowSystem(void) |
888 { |
915 { |
889 UnInitWindowSystem(); |
916 UnInitWindowSystem(); |
1380 _cursor.delta.x = 0; |
1407 _cursor.delta.x = 0; |
1381 _cursor.delta.y = 0; |
1408 _cursor.delta.y = 0; |
1382 return false; |
1409 return false; |
1383 } |
1410 } |
1384 |
1411 |
1385 static void MaybeBringWindowToFront(const Window *w) |
1412 /** Check if a window can be made top-most window, and if so do |
1386 { |
1413 * it. If a window does not obscure any other windows, it will not |
|
1414 * be brought to the foreground. Also if the only obscuring windows |
|
1415 * are so-called system-windows, the window will not be moved. |
|
1416 * The function will return false when a child window of this window is a |
|
1417 * modal-popup; function returns a false and child window gets a white border |
|
1418 * @param w Window to bring on-top |
|
1419 * @return false if the window has an active modal child, true otherwise */ |
|
1420 static bool MaybeBringWindowToFront(const Window *w) |
|
1421 { |
|
1422 bool bring_to_front = false; |
1387 Window* const *wz; |
1423 Window* const *wz; |
1388 Window* const *uz; |
1424 Window* const *uz; |
1389 |
1425 |
1390 if (w->window_class == WC_MAIN_WINDOW || |
1426 if (w->window_class == WC_MAIN_WINDOW || |
1391 IsVitalWindow(w) || |
1427 IsVitalWindow(w) || |
1392 w->window_class == WC_TOOLTIPS || |
1428 w->window_class == WC_TOOLTIPS || |
1393 w->window_class == WC_DROPDOWN_MENU) { |
1429 w->window_class == WC_DROPDOWN_MENU) { |
1394 return; |
1430 return true; |
1395 } |
1431 } |
1396 |
1432 |
1397 wz = FindWindowZPosition(w); |
1433 wz = FindWindowZPosition(w); |
1398 for (uz = wz; ++uz != _last_z_window;) { |
1434 for (uz = wz; ++uz != _last_z_window;) { |
1399 const Window *u = *uz; |
1435 Window *u = *uz; |
|
1436 |
|
1437 /* A modal child will prevent the activation of the parent window */ |
|
1438 if (u->parent == w && (u->desc_flags & WDF_MODAL)) { |
|
1439 u->flags4 |= WF_WHITE_BORDER_MASK; |
|
1440 SetWindowDirty(u); |
|
1441 return false; |
|
1442 } |
1400 |
1443 |
1401 if (u->window_class == WC_MAIN_WINDOW || |
1444 if (u->window_class == WC_MAIN_WINDOW || |
1402 IsVitalWindow(u) || |
1445 IsVitalWindow(u) || |
1403 u->window_class == WC_TOOLTIPS || |
1446 u->window_class == WC_TOOLTIPS || |
1404 u->window_class == WC_DROPDOWN_MENU) { |
1447 u->window_class == WC_DROPDOWN_MENU) { |
1405 continue; |
1448 continue; |
1406 } |
1449 } |
1407 |
1450 |
|
1451 /* Window sizes don't interfere, leave z-order alone */ |
1408 if (w->left + w->width <= u->left || |
1452 if (w->left + w->width <= u->left || |
1409 u->left + u->width <= w->left || |
1453 u->left + u->width <= w->left || |
1410 w->top + w->height <= u->top || |
1454 w->top + w->height <= u->top || |
1411 u->top + u->height <= w->top) { |
1455 u->top + u->height <= w->top) { |
1412 continue; |
1456 continue; |
1413 } |
1457 } |
1414 |
1458 |
1415 BringWindowToFront(w); |
1459 bring_to_front = true; |
1416 return; |
1460 } |
1417 } |
1461 |
|
1462 if (bring_to_front) BringWindowToFront(w); |
|
1463 return true; |
1418 } |
1464 } |
1419 |
1465 |
1420 /** Send a message from one window to another. The receiving window is found by |
1466 /** Send a message from one window to another. The receiving window is found by |
1421 * @param w @see Window pointer pointing to the other window |
1467 * @param w @see Window pointer pointing to the other window |
1422 * @param msg Specifies the message to be sent |
1468 * @param msg Specifies the message to be sent |
1591 |
1637 |
1592 if (click == 0 && mousewheel == 0) return; |
1638 if (click == 0 && mousewheel == 0) return; |
1593 |
1639 |
1594 w = FindWindowFromPt(x, y); |
1640 w = FindWindowFromPt(x, y); |
1595 if (w == NULL) return; |
1641 if (w == NULL) return; |
1596 MaybeBringWindowToFront(w); |
1642 if (!MaybeBringWindowToFront(w)) return; |
1597 vp = IsPtInWindowViewport(w, x, y); |
1643 vp = IsPtInWindowViewport(w, x, y); |
1598 |
1644 |
1599 /* Don't allow any action in a viewport if either in menu of in generating world */ |
1645 /* Don't allow any action in a viewport if either in menu of in generating world */ |
1600 if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return; |
1646 if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return; |
1601 |
1647 |