bool FruityPerfInput::on_button_press_event (GdkEventButton * ev, perfroll & roll) { bool result = false; perform & p = roll.perf(); roll.grab_focus(); int & dropseq = roll.m_drop_sequence; /* reference needed */ sequence * seq = p.get_sequence(dropseq); if (p.is_active(dropseq)) { seq->unselect_triggers(); roll.draw_all(); } else { return false; } roll.m_drop_x = int(ev->x); roll.m_drop_y = int(ev->y); m_current_x = int(ev->x); m_current_y = int(ev->y); roll.convert_xy /* side-effects */ ( roll.m_drop_x, roll.m_drop_y, roll.m_drop_tick, dropseq ); if (SEQ64_CLICK_LEFT(ev->button)) { result = on_left_button_pressed(ev, roll); } else if (SEQ64_CLICK_RIGHT(ev->button)) { result = on_right_button_pressed(ev, roll); } else if (SEQ64_CLICK_MIDDLE(ev->button)) /* left-ctrl???, middle */ { /* * Implements some Stazed fixes now. */ if (p.is_active(dropseq)) { midipulse droptick = roll.m_drop_tick; droptick -= droptick % roll.m_snap; /* stazed fix: grid snap */ bool state = seq->get_trigger_state(droptick); if (state) /* trigger click, split it */ { roll.split_trigger(dropseq, droptick); result = true; } else /* track click, paste trig */ { p.push_trigger_undo(dropseq); seq->paste_trigger(droptick); } } } update_mouse_pointer(roll); return result; }
/* gfx_gdi_move_mouse: */ static void gfx_gdi_move_mouse(int x, int y) { if (!mouse_on) return; x -= mouse_xfocus; y -= mouse_yfocus; if ((mouse_xpos == x) && (mouse_ypos == y)) return; update_mouse_pointer(x, y, TRUE); }
/* gfx_gdi_show_mouse: */ static int gfx_gdi_show_mouse(struct BITMAP *bmp, int x, int y) { /* handle only the screen */ if (bmp != gdi_screen) return -1; mouse_on = TRUE; x -= mouse_xfocus; y -= mouse_yfocus; update_mouse_pointer(x, y, FALSE); return 0; }
bool FruitySeqEventInput::on_motion_notify_event ( GdkEventMotion * ev, seqevent & seqev ) { bool result = false; midipulse tick = 0; seqev.m_current_x = (int) ev->x + seqev.m_scroll_offset_x; if (seqev.m_moving_init) { seqev.m_moving_init = false; seqev.m_moving = true; } update_mouse_pointer(seqev); /* context sensitive mouse pointer... */ /* * Ctrl-left click drag on selected note(s) starts a copy/unselect/paste. */ if (m_is_drag_pasting_start) { seqev.m_seq.copy_selected(); seqev.m_seq.unselect(); seqev.start_paste(); m_is_drag_pasting_start = false; m_is_drag_pasting = true; } if (seqev.m_selecting || seqev.m_moving || seqev.m_paste) { if (seqev.m_moving || seqev.m_paste) seqev.snap_x(seqev.m_current_x); seqev.draw_selection_on_window(); } if (seqev.m_painting) { seqev.m_current_x = int(ev->x) + seqev.m_scroll_offset_x; seqev.snap_x(seqev.m_current_x); seqev.convert_x(seqev.m_current_x, tick); seqev.drop_event(tick); // Why no push_undo()? result = true; } return result; }
bool FruityPerfInput::on_button_release_event (GdkEventButton * ev, perfroll & roll) { bool result = false; m_current_x = int(ev->x); m_current_y = int(ev->y); perform & p = roll.perf(); roll.m_moving = false; roll.m_growing = false; set_adding_pressed(false); if (p.is_active(roll.m_drop_sequence)) roll.draw_all(); update_mouse_pointer(roll); return result; }
bool FruitySeqEventInput::on_button_release_event ( GdkEventButton * ev, seqevent & seqev ) { bool result = false; midipulse tick_s; midipulse tick_f; seqev.grab_focus(); seqev.m_current_x = int(ev->x) + seqev.m_scroll_offset_x;; if (seqev.m_moving || m_is_drag_pasting) seqev.snap_x(seqev.m_current_x); int delta_x = seqev.m_current_x - seqev.m_drop_x; midipulse delta_tick; if (SEQ64_CLICK_LEFT(ev->button)) { int current_x = seqev.m_current_x; midipulse t_s, t_f; seqev.snap_x(current_x); seqev.convert_x(current_x, t_s); t_f = t_s + (seqev.m_zoom); /* shift back a few ticks */ if (t_s < 0) t_s = 0; /* * Use the ctrl-left click button up for select/drag copy/paste; * use the left click button up for ending a move of selected notes. */ if (m_is_drag_pasting) { m_is_drag_pasting = false; m_is_drag_pasting_start = false; seqev.m_paste = false; /* convert deltas into screen coordinates */ seqev.m_seq.paste_selected(t_s, 0); result = true; } /* ctrl-left click but without movement - select a note */ if (m_is_drag_pasting_start) { m_is_drag_pasting_start = false; /* * If a ctrl-left click without movement and if the note under * cursor is selected, and ctrl is held and button-down, * just select one. */ if /* deselect the event? */ ( is_ctrl_key(ev) && ! m_justselected_one && seqev.m_seq.select_events ( t_s, t_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ) ) { (void) seqev.m_seq.select_events ( t_s, t_f, seqev.m_status, seqev.m_cc, sequence::e_deselect ); } } m_justselected_one = false; /* clear flag on left button up */ if (seqev.m_moving) { delta_x -= seqev.m_move_snap_offset_x; /* adjust for snap */ seqev.convert_x(delta_x, delta_tick); /* deltas to screen coords */ seqev.m_seq.move_selected_notes(delta_tick, 0); result = true; } } /* * Yet another stazed fix. :-) */ bool right = SEQ64_CLICK_RIGHT(ev->button); if (! right) right = is_ctrl_key(ev) && SEQ64_CLICK_LEFT(ev->button); if (right) { if (seqev.m_selecting) { int x, w; seqev.x_to_w(seqev.m_drop_x, seqev.m_current_x, x, w); seqev.convert_x(x, tick_s); seqev.convert_x(x + w, tick_f); (void) seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_toggle_selection ); #ifdef USE_STAZED_SELECTION_EXTENSIONS /* * Stazed fix */ if (event::is_strict_note_msg(seqev.m_status)) seqev.m_seq.select_linked(tick_s, tick_f, seqev.m_status); #endif /* * To update the select or unselect of notes by this action. * Not sure this makes sense, though. How does selection dirty * anything? */ seqev.m_seq.set_dirty(); } } seqev.m_selecting = false; /* turn it all off */ seqev.m_moving = false; seqev.m_growing = false; seqev.m_moving_init = false; seqev.m_painting = false; seqev.m_seq.unpaint_all(); seqev.update_pixmap(); /* if they clicked, something changed */ seqev.draw_pixmap_on_window(); update_mouse_pointer(seqev); return result; // true; }
bool FruitySeqEventInput::on_button_press_event ( GdkEventButton * ev, seqevent & seqev ) { bool result = false; midipulse tick_s, tick_w; seqev.grab_focus(); // NEW: I think this would be helpful seqev.convert_x(c_eventevent_x, tick_w); seqev.m_drop_x = seqev.m_current_x = int(ev->x) + seqev.m_scroll_offset_x; seqev.m_old.x = seqev.m_old.y = seqev.m_old.width = seqev.m_old.height = 0; if (seqev.m_paste) { seqev.snap_x(seqev.m_current_x); seqev.convert_x(seqev.m_current_x, tick_s); seqev.m_paste = false; seqev.m_seq.paste_selected(tick_s, 0); /* does undo/mod */ seqev.m_seq.set_dirty(); /* a stazed fix */ result = true; } else { int x, w; midipulse tick_f; if (SEQ64_CLICK_LEFT(ev->button)) /* Note 1 */ { seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y into tick/note */ tick_f = tick_s + seqev.m_zoom; /* shift back some ticks */ tick_s -= tick_w; if (tick_s < 0) tick_s = 0; int eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (! is_ctrl_key(ev) && eventcount == 0) { seqev.m_painting = true; seqev.snap_x(seqev.m_drop_x); seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y-->tick/note */ eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (eventcount == 0) { seqev.m_seq.push_undo(); /* add to add_event? */ seqev.drop_event(tick_s); /* m_seq.add_event() */ result = true; } } else /* selecting */ { eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ); if (eventcount == 0) { eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (eventcount > 0) /* if clicking event */ { if (! is_ctrl_key(ev)) seqev.m_seq.unselect(); } else /* clickempty space, unselect all if no Ctrl-Sh */ { if (! is_ctrl_shift_key(ev)) seqev.m_seq.unselect(); } /* on direct click select only one event */ eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_select_one ); /* * Stazed fix: */ #ifdef USE_STAZED_SELECTION_EXTENSIONS if (event::is_strict_note_msg(seqev.m_status)) { seqev.m_seq.select_linked(tick_s, tick_f, seqev.m_status); seqev.m_seq.set_dirty(); } #endif if (eventcount) m_justselected_one = true; /* stop deselect on release */ /* if nothing selected, start the selection box */ if (is_ctrl_key(ev) && eventcount == 0) seqev.m_selecting = true; } eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ); if (eventcount > 0) /* if event under cursor selected */ { if (! is_ctrl_key(ev)) /* grab/move note */ { seqev.m_moving_init = true; int note; seqev.m_seq.get_selected_box(tick_s, note, tick_f, note); tick_f += tick_w; seqev.convert_t(tick_s, x); /* convert to X,Y values */ seqev.convert_t(tick_f, w); w -= x; /* w is coordinates now */ /* set the m_selected rectangle for x,y,w,h */ seqev.m_selected.x = x; seqev.m_selected.width = w; seqev.m_selected.y = (c_eventarea_y-c_eventevent_y) / 2; seqev.m_selected.height = c_eventevent_y; /* save offset that we get from the snap above */ int adjusted_selected_x = seqev.m_selected.x; seqev.snap_x(adjusted_selected_x); seqev.m_move_snap_offset_x = seqev.m_selected.x - adjusted_selected_x; /* align selection for drawing */ seqev.snap_x(seqev.m_selected.x); seqev.snap_x(seqev.m_current_x); seqev.snap_x(seqev.m_drop_x); } else if /* Ctrl-Left-click when stuff already selected */ ( is_ctrl_key(ev) && seqev.m_seq.select_events(tick_s, tick_f, seqev. m_status, seqev.m_cc, sequence::e_is_selected) ) { m_is_drag_pasting_start = true; } } } } if (SEQ64_CLICK_RIGHT(ev->button)) { seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y in to tick/note */ tick_f = tick_s + seqev.m_zoom; /* shift back some ticks */ tick_s -= (tick_w); if (tick_s < 0) tick_s = 0; /* * Stazed fix: don't allow individual deletion of Note On/Off * events. Should we do the same for AfterTouch events? No, they * are not linked to Note On or Note Off events. */ if (event::is_strict_note_msg(seqev.m_status)) return true; int eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (eventcount > 0) /* erase event under cursor if there is one */ { /* remove only note under cursor, leave selection intact */ (void) seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_remove_one ); seqev.redraw(); seqev.m_seq.set_dirty(); /* take note! */ result = true; } else /* selecting */ { if (! is_ctrl_key(ev)) seqev.m_seq.unselect(); /* nothing selected */ seqev.m_selecting = true; /* start select-box */ } } } seqev.update_pixmap(); /* if they clicked, something changed */ seqev.draw_pixmap_on_window(); update_mouse_pointer(seqev); return result; // true; }
bool FruityPerfInput::on_motion_notify_event (GdkEventMotion * ev, perfroll & roll) { bool result = false; perform & p = roll.perf(); int dropseq = roll.m_drop_sequence; sequence * seq = p.get_sequence(dropseq); int x = int(ev->x); midipulse tick = 0; m_current_x = int(ev->x); m_current_y = int(ev->y); if (is_adding_pressed()) { roll.convert_x(x, tick); /* side-effect */ if (p.is_active(dropseq)) { midipulse seqlength = seq->get_length(); tick -= (tick % seqlength); midipulse length = seqlength; seq->grow_trigger(roll.m_drop_tick, tick, length); roll.draw_all(); result = true; } } else if (roll.m_moving || roll.m_growing) { if (p.is_active(dropseq)) { /* * This code is necessary to insure that there is no push unless * we have a motion notification. */ if (roll.m_have_button_press) { p.push_trigger_undo(dropseq); roll.m_have_button_press = false; } roll.convert_x(x, tick); /* side-effect */ tick -= roll.m_drop_tick_trigger_offset; tick -= tick % roll.m_snap; if (roll.m_moving) { seq->move_selected_triggers_to(tick, true); result = true; } if (roll.m_growing) { result = true; if (roll.m_grow_direction) { seq->move_selected_triggers_to ( tick, false, triggers::GROW_START ); } else { seq->move_selected_triggers_to ( tick - 1, false, triggers::GROW_END ); } } roll.draw_all(); } } update_mouse_pointer(roll); return result; }
/* render_proc: * Timer proc that updates the window. */ static void render_proc(void) { int top_line, bottom_line; HDC hdc = NULL; HWND allegro_wnd = win_get_window(); /* to prevent reentrant calls */ if (render_semaphore) return; render_semaphore = TRUE; /* to prevent the drawing threads and the rendering proc * from concurrently accessing the dirty lines array. */ _enter_gfx_critical(); if (!gdi_screen) { _exit_gfx_critical(); render_semaphore = FALSE; return; } /* pseudo dirty rectangles mechanism: * at most only one GDI call is performed for each frame, * a true dirty rectangles mechanism makes the demo game * unplayable in 640x480 on my system. */ /* find the first dirty line */ top_line = 0; while (!gdi_dirty_lines[top_line]) top_line++; if (top_line < gfx_gdi.h) { /* find the last dirty line */ bottom_line = gfx_gdi.h-1; while (!gdi_dirty_lines[bottom_line]) bottom_line--; hdc = GetDC(allegro_wnd); if (_color_depth == 8) set_palette_to_hdc(hdc, palette); blit_to_hdc(gdi_screen, hdc, 0, top_line, 0, top_line, gfx_gdi.w, bottom_line - top_line + 1); /* update mouse pointer if needed */ if (mouse_on) { if ((mouse_ypos+wgdi_mouse_sprite->h > top_line) && (mouse_ypos <= bottom_line)) { blit(gdi_screen, mouse_backbuffer, mouse_xpos, mouse_ypos, 0, 0, mouse_backbuffer->w, mouse_backbuffer->h); update_mouse_pointer(mouse_xpos, mouse_ypos, TRUE); } } /* clean up the dirty lines */ while (top_line <= bottom_line) gdi_dirty_lines[top_line++] = 0; ReleaseDC(allegro_wnd, hdc); } _exit_gfx_critical(); /* simulate vertical retrace */ PulseEvent(vsync_event); render_semaphore = FALSE; }