Index: viewport.c =================================================================== --- viewport.c (revision 6470) +++ viewport.c (working copy) @@ -2227,7 +2227,6 @@ _thd.make_square_red = false; if (mode == VHM_DRAG) { // mode 4 is for dragdropping trains in the depot window - mode = 0; _special_mouse_mode = WSM_DRAGDROP; } else { _special_mouse_mode = WSM_NONE; Index: aircraft_gui.c =================================================================== --- aircraft_gui.c (revision 6470) +++ aircraft_gui.c (working copy) @@ -812,16 +812,16 @@ case WE_CLICK: switch (e->click.widget) { - case 5: /* click aircraft */ + case 5: // click aircraft AircraftDepotClickAircraft(w, e->click.pt.x, e->click.pt.y); break; - case 7: /* show build aircraft window */ + case 7: // show build aircraft window ResetObjectToPlace(); ShowBuildAircraftWindow(w->window_number); break; - case 8: /* clone button */ + case 8: // clone button InvalidateWidget(w, 8); TOGGLEBIT(w->click_state, 8); @@ -842,8 +842,13 @@ break; case WE_ABORT_PLACE_OBJ: + // abort clone object mode CLRBIT(w->click_state, 8); InvalidateWidget(w, 8); + + // cancel dragging + WP(w, traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); break; // check if a vehicle in a depot was clicked.. @@ -894,6 +899,7 @@ _backup_orders_tile = 0; } break; + default: WP(w,traindepot_d).sel = INVALID_VEHICLE; SetWindowDirty(w); Index: roadveh_gui.c =================================================================== --- roadveh_gui.c (revision 6470) +++ roadveh_gui.c (working copy) @@ -770,19 +770,19 @@ ShowBuildRoadVehWindow(w->window_number); break; - case 8: /* clone button */ + case 8: // clone button InvalidateWidget(w, 8); - TOGGLEBIT(w->click_state, 8); + TOGGLEBIT(w->click_state, 8); - if (HASBIT(w->click_state, 8)) { - _place_clicked_vehicle = NULL; - SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w); - } else { - ResetObjectToPlace(); - } - break; + if (HASBIT(w->click_state, 8)) { + _place_clicked_vehicle = NULL; + SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w); + } else { + ResetObjectToPlace(); + } + break; - case 9: ScrollMainWindowToTile(w->window_number); break; + case 9: ScrollMainWindowToTile(w->window_number); break; } } break; @@ -791,8 +791,13 @@ break; case WE_ABORT_PLACE_OBJ: + // abort clone object mode CLRBIT(w->click_state, 8); InvalidateWidget(w, 8); + + // cancel dragging + WP(w,traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); break; // check if a vehicle in a depot was clicked.. @@ -851,12 +856,11 @@ break; case WE_RESIZE: - /* Update the scroll + matrix */ + // Update the scroll + matrix w->vscroll.cap += e->sizing.diff.y / 14; w->hscroll.cap += e->sizing.diff.x / 56; w->widget[5].data = (w->vscroll.cap << 8) + w->hscroll.cap; break; - } } Index: train_gui.c =================================================================== --- train_gui.c (revision 6470) +++ train_gui.c (working copy) @@ -357,7 +357,7 @@ { DrawPixelInfo tmp_dpi, *old_dpi; int dx = -(skip * 8) / _traininfo_vehicle_width; - /* Position of highlight box */ + // position of highlight box int highlight_l = 0; int highlight_r = 0; @@ -376,9 +376,13 @@ PalSpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v); DrawSprite(GetTrainImage(v, DIR_W) | pal, 16 + WagonLengthToPixels(dx), 7 + (is_custom_sprite(RailVehInfo(v->engine_type)->image_index) ? _traininfo_vehicle_pitch : 0)); if (v->index == selection) { - /* Set the highlight position */ + // set the highlight position highlight_l = WagonLengthToPixels(dx) + 1; - highlight_r = WagonLengthToPixels(dx + width) + 1; + + if (!_ctrl_pressed) { + // set highlight_r immediately if ctrl key is not pressed + highlight_r = WagonLengthToPixels(dx + width) + 1; + } } } } @@ -388,8 +392,11 @@ } while (dx < count && v != NULL); if (highlight_l != highlight_r) { - /* Draw the highlight. Now done after drawing all the engines, as - * the next engine after the highlight could overlap it. */ + // if ctrl key was pressed, we need to set highlight_r + if (highlight_r == 0) highlight_r = WagonLengthToPixels(dx) + 1; + + /* draw the highlight; done after drawing all the vehicles, as + the next vehicle after the highlight could overlap it */ DrawFrameRect(highlight_l, 0, highlight_r, 13, 15, FR_BORDERONLY); } @@ -659,12 +666,13 @@ ShowBuildTrainWindow(w->window_number); break; - case 10: ScrollMainWindowToTile(w->window_number); break; + case 10: ScrollMainWindowToTile(w->window_number); break; case 6: TrainDepotClickTrain(w, e->click.pt.x, e->click.pt.y); break; - case 9: /* clone button */ + + case 9: // clone button InvalidateWidget(w, 9); TOGGLEBIT(w->click_state, 9); @@ -675,7 +683,6 @@ ResetObjectToPlace(); } break; - } } break; @@ -684,8 +691,13 @@ break; case WE_ABORT_PLACE_OBJ: + // abort clone object mode CLRBIT(w->click_state, 9); InvalidateWidget(w, 9); + + // cancel dragging + WP(w, traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); break; // check if a vehicle in a depot was clicked.. @@ -697,9 +709,20 @@ _place_clicked_vehicle = NULL; HandleCloneVehClick(v, w); } + + if (_ctrl_pressed != WP(w,traindepot_d).ctrl_key_status) { + // XXX: WE_KEYPRESS is not triggered by toggling of ctrl key, so test for it here + VehicleID selection = WP(w,traindepot_d).sel; + + WP(w,traindepot_d).ctrl_key_status = _ctrl_pressed; + + if (selection != INVALID_VEHICLE) { + // redraw highlight around selected vehicle(s) for drag/drop + SetWindowDirty(w); + } + } } break; - case WE_DESTROY: DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); break; @@ -710,7 +733,7 @@ Vehicle *v; int sell_cmd; - /* sell vehicle */ + // sell vehicle if (w->disabled_state & (1 << e->click.widget)) return; @@ -760,9 +783,10 @@ SetWindowDirty(w); break; } - } break; + } break; + case WE_RESIZE: { - /* Update the scroll + matrix */ + // Update the scroll + matrix w->vscroll.cap += e->sizing.diff.y / 14; w->hscroll.cap += e->sizing.diff.x; w->widget[6].data = (w->vscroll.cap << 8) + 1; Index: window.c =================================================================== --- window.c (revision 6470) +++ window.c (working copy) @@ -426,7 +426,7 @@ /* XXX - This very strange construction makes sure that the chatbar is always * on top of other windows. Why? It is created as last_window (so, on top). - * Any other window will go below toolbar/statusbar/news window, which implicitely + * Any other window will go below toolbar/statusbar/news window, which implicitly * also means it is below the chatbar. Very likely needs heavy improvement * to de-braindeadize */ if (w != _windows && cls != WC_SEND_NETWORK_MSG) { @@ -795,8 +795,6 @@ w = GetCallbackWnd(); - ResetObjectToPlace(); - if (w != NULL) { // send an event in client coordinates. e.event = WE_DRAGDROP; @@ -805,6 +803,9 @@ e.dragdrop.widget = GetWidgetFromPos(w, e.dragdrop.pt.x, e.dragdrop.pt.y); w->wndproc(w, &e); } + + ResetObjectToPlace(); + return false; } @@ -1271,12 +1272,12 @@ { Window *w; WindowEvent we; - /* Stores if a window with a textfield for typing is open - * If this is the case, keypress events are only passed to windows with text fields and - * to thein this main toolbar. */ + /* stores if a window with a text-field for typing is open + * If this is the case, keypress events are only passed to windows with text-fields and + * to the main toolbar. */ bool query_open = false; - // Setup event + // setup event we.keypress.event = WE_KEYPRESS; we.keypress.ascii = key & 0xFF; we.keypress.keycode = key >> 16; @@ -1291,7 +1292,7 @@ query_open = true; } - // Call the event, start with the uppermost window. + // call the event; start with the uppermost window for (w = _last_window; w != _windows;) { --w; // if a query window is open, only call the event for certain window types Index: ship_gui.c =================================================================== --- ship_gui.c (revision 6470) +++ ship_gui.c (working copy) @@ -761,29 +761,33 @@ ShowBuildShipWindow(w->window_number); break; - case 8: /* clone button */ + case 8: // clone button InvalidateWidget(w, 8); - TOGGLEBIT(w->click_state, 8); + TOGGLEBIT(w->click_state, 8); - if (HASBIT(w->click_state, 8)) { - _place_clicked_vehicle = NULL; - SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w); - } else { - ResetObjectToPlace(); - } - break; + if (HASBIT(w->click_state, 8)) { + _place_clicked_vehicle = NULL; + SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w); + } else { + ResetObjectToPlace(); + } + break; - case 9: ScrollMainWindowToTile(w->window_number); break; - } - break; + case 9: ScrollMainWindowToTile(w->window_number); break; + } break; case WE_PLACE_OBJ: { ClonePlaceObj(w); } break; case WE_ABORT_PLACE_OBJ: { + // abort clone object mode CLRBIT(w->click_state, 8); InvalidateWidget(w, 8); + + // cancel dragging + WP(w, traindepot_d).sel = INVALID_VEHICLE; + SetWindowDirty(w); } break; // check if a vehicle in a depot was clicked.. @@ -834,6 +838,7 @@ _backup_orders_tile = 0; } break; + default: WP(w,traindepot_d).sel = INVALID_VEHICLE; SetWindowDirty(w); Index: window.h =================================================================== --- window.h (revision 6470) +++ window.h (working copy) @@ -379,6 +379,8 @@ typedef struct { VehicleID sel; + // used to track whether the ctrl key was toggled, so that drap/drop highlight can be redrawn + bool ctrl_key_status; } traindepot_d; assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(traindepot_d));