*/ LRESULT CALLBACK REBOL_Window_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM xy) /* ** A Window_Proc() message handler. Simply translate Windows ** messages into a generic form that REBOL processes. ** ***********************************************************************/ { REBGOB *gob; REBCNT flags = 1 << EVF_NO_REQ; // (because no device request field) REBCNT i; REBCNT mw_num_lines; // mouse wheel lines setting // In order to trace resizing, we need these state variables. It is // assumed that we are not re-entrant during this operation. In Win32 // resizing is a modal loop and prevents it being a problem. static LPARAM last_xy = 0; static REBINT mode = 0; gob = (REBGOB *)GetWindowLong(hwnd, GWL_USERDATA); // Not a REBOL window (or early creation): if (!gob || !IS_WINDOW(gob)) { switch(msg) { case WM_PAINT: Paint_Window(hwnd); break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: // Default processing that we do not care about: return DefWindowProc(hwnd, msg, wParam, xy); } return 0; } // Handle message: switch(msg) { case WM_PAINT: Paint_Window(hwnd); break; case WM_MOUSEMOVE: Add_Event_XY(gob, EVT_MOVE, xy, flags); //if (!(WIN_FLAGS(wp) & WINDOW_TRACK_LEAVE)) // Track_Mouse_Leave(wp); break; case WM_SIZE: //Reb_Print("SIZE %d\n", mode); if (wParam == SIZE_MINIMIZED) { //Invalidate the size but not win buffer gob->old_size.x = 0; gob->old_size.y = 0; Add_Event_XY(gob, EVT_MINIMIZE, xy, flags); } else { gob->size.x = LOWORD(xy); gob->size.y = HIWORD(xy); last_xy = xy; if (mode) { //Resize and redraw the window buffer (when resize dragging) Resize_Window(gob, TRUE); mode = EVT_RESIZE; break; } else { //Resize only the window buffer (when win gob size changed by REBOL code or using min/max buttons) if (!Resize_Window(gob, FALSE)){ //size has been changed programatically - return only 'resize event Add_Event_XY(gob, EVT_RESIZE, xy, flags); break; } } //Otherwise send combo of 'resize + maximize/restore events if (wParam == SIZE_MAXIMIZED) i = EVT_MAXIMIZE; else if (wParam == SIZE_RESTORED) i = EVT_RESTORE; else i = 0; Add_Event_XY(gob, EVT_RESIZE, xy, flags); if (i) Add_Event_XY(gob, i, xy, flags); } break; case WM_MOVE: // Minimize and maximize call this w/o mode set. gob->offset.x = LOWORD(xy); gob->offset.y = HIWORD(xy); last_xy = xy; if (mode) mode = EVT_OFFSET; else Add_Event_XY(gob, EVT_OFFSET, xy, flags); break; case WM_ENTERSIZEMOVE: mode = -1; // possible to ENTER and EXIT w/o SIZE change break; case WM_EXITSIZEMOVE: if (mode > 0) Add_Event_XY(gob, mode, last_xy, flags); mode = 0; break; case WM_MOUSELEAVE: // Get cursor position, not the one given in message: //GetCursorPos(&x_y); //ScreenToClient(hwnd, &x_y); //xy = (x_y.y << 16) + (x_y.x & 0xffff); Add_Event_XY(gob, EVT_MOVE, xy, flags); // WIN_FLAGS(wp) &= ~WINDOW_TRACK_LEAVE; break; case WM_MOUSEWHEEL: SystemParametersInfo(SPI_GETWHEELSCROLLLINES,0, &mw_num_lines, 0); if (LOWORD(wParam) == MK_CONTROL || mw_num_lines > WHEEL_DELTA) { Add_Event_XY(gob, EVT_SCROLL_PAGE, GET_WHEEL_DELTA_WPARAM(wParam), flags); } else { Add_Event_XY(gob, EVT_SCROLL_LINE, GET_WHEEL_DELTA_WPARAM(wParam) * mw_num_lines, flags); } break; case WM_TIMER: //Add_Event_XY(gob, EVT_TIME, xy, flags); break; case WM_SETCURSOR: if (LOWORD(xy) == 1) { SetCursor(Cursor); return TRUE; } else goto default_case; case WM_LBUTTONDBLCLK: SET_FLAG(flags, EVF_DOUBLE); case WM_LBUTTONDOWN: //if (!WIN_CAPTURED(wp)) { flags = Check_Modifiers(flags); Add_Event_XY(gob, EVT_DOWN, xy, flags); SetCapture(hwnd); //WIN_CAPTURED(wp) = EVT_BTN1_UP; break; case WM_LBUTTONUP: //if (WIN_CAPTURED(wp) == EVT_BTN1_UP) { flags = Check_Modifiers(flags); Add_Event_XY(gob, EVT_UP, xy, flags); ReleaseCapture(); //WIN_CAPTURED(wp) = 0; break; case WM_RBUTTONDBLCLK: SET_FLAG(flags, EVF_DOUBLE); case WM_RBUTTONDOWN: //if (!WIN_CAPTURED(wp)) { flags = Check_Modifiers(flags); Add_Event_XY(gob, EVT_ALT_DOWN, xy, flags); SetCapture(hwnd); //WIN_CAPTURED(wp) = EVT_BTN2_UP; break; case WM_RBUTTONUP: //if (WIN_CAPTURED(wp) == EVT_BTN2_UP) { flags = Check_Modifiers(flags); Add_Event_XY(gob, EVT_ALT_UP, xy, flags); ReleaseCapture(); //WIN_CAPTURED(wp) = 0; break; case WM_MBUTTONDBLCLK: SET_FLAG(flags, EVF_DOUBLE); case WM_MBUTTONDOWN: //if (!WIN_CAPTURED(wp)) { flags = Check_Modifiers(flags); Add_Event_XY(gob, EVT_AUX_DOWN, xy, flags); SetCapture(hwnd); break; case WM_MBUTTONUP: //if (WIN_CAPTURED(wp) == EVT_BTN2_UP) { flags = Check_Modifiers(flags); Add_Event_XY(gob, EVT_AUX_UP, xy, flags); ReleaseCapture(); break; case WM_KEYDOWN: // Note: key repeat may cause multiple downs before an up. case WM_KEYUP: flags = Check_Modifiers(flags); for (i = 0; Key_To_Event[i] && wParam > Key_To_Event[i]; i += 2); if (wParam == Key_To_Event[i]) Add_Event_Key(gob, (msg==WM_KEYDOWN) ? EVT_KEY : EVT_KEY_UP, Key_To_Event[i+1] << 16, flags); break; case WM_CHAR: flags = Check_Modifiers(flags); i = wParam & 0xff; //if (i == 127) i = 8; // Windows weirdness of converting ctrl-backspace to delete Add_Event_Key(gob, EVT_KEY, i, flags); break; case WM_DROPFILES: Add_File_Events(gob, flags, (HDROP)wParam); break; case WM_CLOSE: Add_Event_XY(gob, EVT_CLOSE, xy, flags); Close_Window(gob); // Needs to be removed - should be done by REBOL event handling // DestroyWindow(hwnd);// This is done in Close_Window() break; case WM_DESTROY: PostQuitMessage(0); break; default: default_case: return DefWindowProc(hwnd, msg, wParam, xy); } return 0; }
void mouseintr(uint tick) { uint ch; ch = inb(0x64); if((ch & 0x01) == 0) { //cprintf("no data\n"); state = 1; return; } acquire(&mouse_lock); ch = inb(0x60); if(state == 1) { if((ch & 0x08) == 0 || (ch & 0x04) != 0) { release(&mouse_lock); return; } left_down = (ch & 0x01) ? 1 : 0; right_down = (ch & 0x02) ? 1 : 0; x_sign = (ch & 0x10) ? 1 : 0; y_sign = (ch & 0x20) ? 1 : 0; x_overflow = (ch & 0x40) ? 1 : 0; y_overflow = (ch & 0x80) ? 1 : 0; state = 2; release(&mouse_lock); //cprintf("state1\n"); //cprintf("overflow: %d\n", y_overflow); return; } else if(state == 2) { int dis; if(x_sign == 0) dis = ch; else dis = ch - 256; if(dis > 50 || dis < -50) { //cprintf("error"); state = 1; release(&mouse_lock); return; } //cprintf("xdis: %d, sign: %d\n", dis, x_sign); x_position += dis; if(x_position < 0) x_position = 0; if(x_position > SCREEN_WIDTH - SIZE_X_MOUSE) x_position = SCREEN_WIDTH - SIZE_X_MOUSE; state = 3; release(&mouse_lock); //cprintf("state2\n"); return; } else if(state == 3) { int dis; if(y_sign == 0) dis = ch; else dis = ch - 256; if(dis > 50 || dis < -50) { //cprintf("error"); state = 1; release(&mouse_lock); return; } //cprintf("ydis: %d, sign: %d, overflow: %d\n", dis, y_sign, y_overflow); y_position -= dis; if(y_position < 0) y_position = 0; if(y_position > SCREEN_HEIGHT - SIZE_Y_MOUSE) y_position = SCREEN_HEIGHT - SIZE_Y_MOUSE; state = 1; release(&mouse_lock); //cprintf("state3\n"); } else { state = 1; release(&mouse_lock); return; } event = 0; if(left_already_down == 0 && right_already_down == 0) { if(left_down == 1) { left_already_down = 1; x_drag_start = x_position; y_drag_start = y_position; } else if(right_down == 1) { right_already_down = 1; } } else if(left_already_down == 1) { if(left_down == 0) { //cprintf("dragging: %d\n", is_dragging); if(is_dragging == 1) { event = DRAG_RELEASE; is_dragging = 0; } else { int dtick = tick - left_click_tick; //cprintf("tick: %d\n", dtick); if(dtick > 15) { event = LEFT_CLICK; left_click_tick = tick; } else { event = DOUBLE_CLICK; left_click_tick = -20; } } left_already_down = 0; } else { event = DRAGGING; is_dragging = 1; } } else if(right_already_down == 1) { if(right_down == 0) { event = RIGHT_CLICK; right_already_down = 0; } } if(event == 0) { draw_mouse(x_position, y_position); return; } struct Window* win; int click_icon = -1; if(y_position > ICON_Y && y_position < ICON_Y + 75 + 18) { if(event != LEFT_CLICK) { draw_mouse(x_position, y_position); return; } if(x_position > ICON_X1 && x_position < ICON_X1 + 75) { click_icon = ICON_FINDER; } else if(x_position > ICON_X2 && x_position < ICON_X2 + 75) { click_icon = ICON_PHOTO; } else if(x_position > ICON_X3 && x_position < ICON_X3 + 75) { click_icon = ICON_TEXT; } else if(x_position > ICON_X4 && x_position < ICON_X4 + 75) { click_icon = ICON_GAME; } else if(x_position > ICON_X5 && x_position < ICON_X5 + 75) { click_icon = ICON_DRAW; } else if(x_position > ICON_X6 && x_position < ICON_X6 + 75) { click_icon = ICON_SETTING; } else { draw_mouse(x_position, y_position); return; } win = get_window_by_icon(click_icon); if(click_icon == ICON_FINDER || win == 0) { win = Add_Window(click_icon); if(win != 0) draw_window(win); } else if(win != 0 && WindowLine->next != win) { draw_window(win); Focus(win); } display_to_screen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); draw_mouse(x_position, y_position); return; } win = Click_Get_Window(x_position, y_position); if(win != 0 && WindowLine->next != win) { //cprintf("window: %d\n", win->Cur_icon); if(event == LEFT_CLICK) { draw_window(win); display_to_screen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); Focus(win); } } else if(win != 0) { int Pos_x, Pos_y; Pos_x = x_position - win->Pos_x; Pos_y = y_position - win->Pos_y; if(Pos_x > 2 && Pos_x < 18 && Pos_y > 2 && Pos_y < 18) { Close_Window(); draw_again(get_current_bg()); } else if(Pos_y < 20) { if(event == DRAGGING) { if(dragging_top_window == 0) { dragging_top_window = 1; x_drag_window = win->Pos_x; y_drag_window = win->Pos_y; dragging_count = 0; } dragging_count = (dragging_count + 1) % 5; if(dragging_count != 0) return; if(x_drag_window + (x_position - x_drag_start) < 0 || x_drag_window + (x_position - x_drag_start) + WindowWidth > SCREEN_WIDTH || y_drag_window + (y_position - y_drag_start) < 0 || y_drag_window + (y_position - y_drag_start) + WindowHeight > SCREEN_HEIGHT) return; draw_bottom(get_current_bg()); win->Pos_x = x_drag_window + (x_position - x_drag_start); win->Pos_y = y_drag_window + (y_position - y_drag_start); draw_window(win); display_to_screen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); } else if(event == DRAG_RELEASE) { if(dragging_top_window == 1) dragging_top_window = 0; } } else if(Pos_y > 20 && Pos_y < WindowHeight - 20) { switch(win->Cur_icon) { case ICON_DRAW: draw(win, Pos_x, Pos_y, event); break; case ICON_SETTING: setting(Pos_x, Pos_y, event); break; case ICON_FINDER: Folder(win, Pos_x, Pos_y, event); break; case ICON_GAME: pointInGameWindow(Pos_x, Pos_y, event); break; case 8://LIST_FINDER Folder(win, Pos_x, Pos_y, event); break; case 9://LAYOUT_FINDER Folder(win, Pos_x, Pos_y, event); break; } } } draw_mouse(x_position, y_position); }