/* generate_mouse_event: [bgman thread] * Helper to generate a mouse event. */ static void generate_mouse_event(unsigned int type, int x, int y, int z, int w, float pressure, int dx, int dy, int dz, int dw, unsigned int button, ALLEGRO_DISPLAY *display) { ALLEGRO_EVENT event; if (!_al_event_source_needs_to_generate_event(&the_mouse.parent.es)) return; event.mouse.type = type; event.mouse.timestamp = al_get_time(); event.mouse.display = display; event.mouse.x = x; event.mouse.y = y; event.mouse.z = z; event.mouse.w = w; event.mouse.dx = dx; event.mouse.dy = dy; event.mouse.dz = dz; event.mouse.dw = dw; event.mouse.button = button; event.mouse.pressure = pressure; _al_event_source_emit_event(&the_mouse.parent.es, &event); }
/* handle_key_release: [fdwatch thread] * Helper: stuff to do when a key is released. */ static void handle_key_release(int mycode) { ALLEGRO_EVENT event; /* This can happen, e.g. when we are switching back into a VT with * ALT+Fn, we only get the release event of the function key. */ if (!_AL_KEYBOARD_STATE_KEY_DOWN(the_keyboard.state, mycode)) return; /* Maintain the key_down array. */ _AL_KEYBOARD_STATE_CLEAR_KEY_DOWN(the_keyboard.state, mycode); /* Generate key release events if necessary. */ if (!_al_event_source_needs_to_generate_event(&the_keyboard.parent.es)) return; event.keyboard.type = ALLEGRO_EVENT_KEY_UP; event.keyboard.timestamp = al_get_time(); event.keyboard.display = NULL; event.keyboard.keycode = mycode; event.keyboard.unichar = 0; event.keyboard.modifiers = 0; _al_event_source_emit_event(&the_keyboard.parent.es, &event); }
static void android_keyboard_handle_event(ALLEGRO_DISPLAY *display, int scancode, int unichar, ALLEGRO_EVENT_TYPE event_type) { ALLEGRO_EVENT event; ASSERT(display != NULL); ASSERT(scancode > 0); if (event_type == ALLEGRO_EVENT_KEY_UP) { _AL_KEYBOARD_STATE_CLEAR_KEY_DOWN(the_state, scancode); } else { _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_state, scancode); } _al_event_source_lock(&the_keyboard.es); if (_al_event_source_needs_to_generate_event(&the_keyboard.es)) { event.keyboard.type = event_type; event.keyboard.timestamp = al_get_time(); event.keyboard.display = display; event.keyboard.keycode = scancode; event.keyboard.unichar = unichar; event.keyboard.modifiers = 0; event.keyboard.repeat = event_type == ALLEGRO_EVENT_KEY_CHAR; _al_event_source_emit_event(&the_keyboard.es, &event); } _al_event_source_unlock(&the_keyboard.es); }
/* handle_key_press: [fdwatch thread] * Helper: stuff to do when a key is pressed. */ static void handle_key_press(int mycode, unsigned int ascii) { ALLEGRO_EVENT_TYPE event_type; ALLEGRO_EVENT event; event_type = (_AL_KEYBOARD_STATE_KEY_DOWN(the_keyboard.state, mycode) ? ALLEGRO_EVENT_KEY_CHAR : ALLEGRO_EVENT_KEY_DOWN); /* Maintain the key_down array. */ _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_keyboard.state, mycode); /* Generate key press/repeat events if necessary. */ if (!_al_event_source_needs_to_generate_event(&the_keyboard.parent.es)) return; event.keyboard.type = event_type; event.keyboard.timestamp = al_get_time(); event.keyboard.display = NULL; event.keyboard.keycode = mycode; event.keyboard.unichar = ascii; event.keyboard.modifiers = the_keyboard.modifiers; _al_event_source_emit_event(&the_keyboard.parent.es, &event); /* The first press should generate a KEY_CHAR also */ if (event_type == ALLEGRO_EVENT_KEY_DOWN) { event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR; event.keyboard.timestamp = al_get_time(); _al_event_source_emit_event(&the_keyboard.parent.es, &event); } }
/* Handle X11 switch event. [X11 thread] */ void _al_xwin_display_switch_handler_inner(ALLEGRO_DISPLAY *display, bool focus_in) { ALLEGRO_EVENT_SOURCE *es = &display->es; _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; if (focus_in) event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_IN; else event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_OUT; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); }
/* ljoy_generate_button_event: [fdwatch thread] * * Helper to generate an event after a button is pressed or released. * The joystick must be locked BEFORE entering this function. */ static void ljoy_generate_button_event(ALLEGRO_JOYSTICK_LINUX *joy, int button, ALLEGRO_EVENT_TYPE event_type) { ALLEGRO_EVENT event; if (!_al_event_source_needs_to_generate_event(&joy->parent.es)) return; event.joystick.type = event_type; event.joystick.timestamp = al_current_time(); event.joystick.stick = 0; event.joystick.axis = 0; event.joystick.pos = 0.0; event.joystick.button = button; _al_event_source_emit_event(&joy->parent.es, &event); }
/* ljoy_generate_axis_event: [fdwatch thread] * * Helper to generate an event after an axis is moved. * The joystick must be locked BEFORE entering this function. */ static void ljoy_generate_axis_event(ALLEGRO_JOYSTICK_LINUX *joy, int stick, int axis, float pos) { ALLEGRO_EVENT event; if (!_al_event_source_needs_to_generate_event(&joy->parent.es)) return; event.joystick.type = ALLEGRO_EVENT_JOYSTICK_AXIS; event.joystick.timestamp = al_current_time(); event.joystick.stick = stick; event.joystick.axis = axis; event.joystick.pos = pos; event.joystick.button = 0; _al_event_source_emit_event(&joy->parent.es, &event); }
void _al_xwin_display_expose(ALLEGRO_DISPLAY *display, XExposeEvent *xevent) { ALLEGRO_EVENT_SOURCE *es = &display->es; _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; event.display.timestamp = al_get_time(); event.display.x = xevent->x; event.display.y = xevent->y; event.display.width = xevent->width; event.display.height = xevent->height; _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); }
/* ljoy_generate_button_event: [fdwatch thread] * * Helper to generate an event after a button is pressed or released. * The joystick must be locked BEFORE entering this function. */ static void ljoy_generate_button_event(ALLEGRO_JOYSTICK_LINUX *joy, int button, ALLEGRO_EVENT_TYPE event_type) { ALLEGRO_EVENT event; ALLEGRO_EVENT_SOURCE *es = al_get_joystick_event_source(); if (!_al_event_source_needs_to_generate_event(es)) return; event.joystick.type = event_type; event.joystick.timestamp = al_get_time(); event.joystick.id = (ALLEGRO_JOYSTICK *)joy; event.joystick.stick = 0; event.joystick.axis = 0; event.joystick.pos = 0.0; event.joystick.button = button; _al_event_source_emit_event(es, &event); }
/* generate_axis_event: [joystick thread] * Helper to generate an event after an axis is moved. * The joystick must be locked BEFORE entering this function. */ static void generate_axis_event(ALLEGRO_JOYSTICK_DIRECTX *joy, int stick, int axis, float pos) { ALLEGRO_EVENT event; ALLEGRO_EVENT_SOURCE *es = al_get_joystick_event_source(); if (!_al_event_source_needs_to_generate_event(es)) return; event.joystick.type = ALLEGRO_EVENT_JOYSTICK_AXIS; event.joystick.timestamp = al_get_time(); event.joystick.id = (ALLEGRO_JOYSTICK *)joy; event.joystick.stick = stick; event.joystick.axis = axis; event.joystick.pos = pos; event.joystick.button = 0; _al_event_source_emit_event(es, &event); }
/* _al_win_kbd_handle_key_release: * Does stuff when a key is released. */ void _al_win_kbd_handle_key_release(int scode, int vcode, bool extended, ALLEGRO_DISPLAY_WIN *win_disp) { ALLEGRO_EVENT event; int my_code; if (!installed) return; my_code = 0; if (extended) my_code = extkey_to_keycode(vcode); if (my_code == 0) { if (vcode == VK_SHIFT) vcode = MapVirtualKey(scode, MAPVK_VSC_TO_VK_EX); my_code = hw_to_mycode[vcode]; } update_modifiers(my_code, false); _AL_KEYBOARD_STATE_CLEAR_KEY_DOWN(the_state, my_code); /* Windows only sends a WM_KEYUP message for the Shift keys when both have been released. If one of the Shift keys is still reported as down, we need to release it as well. */ if (my_code == ALLEGRO_KEY_LSHIFT && _AL_KEYBOARD_STATE_KEY_DOWN(the_state, ALLEGRO_KEY_RSHIFT)) _al_win_kbd_handle_key_release(scode, VK_RSHIFT, extended, win_disp); else if (my_code == ALLEGRO_KEY_RSHIFT && _AL_KEYBOARD_STATE_KEY_DOWN(the_state, ALLEGRO_KEY_LSHIFT)) _al_win_kbd_handle_key_release(scode, VK_LSHIFT, extended, win_disp); if (!_al_event_source_needs_to_generate_event(&the_keyboard.es)) return; event.keyboard.type = ALLEGRO_EVENT_KEY_UP; event.keyboard.timestamp = al_get_time(); event.keyboard.display = (void*)win_disp; event.keyboard.keycode = my_code; event.keyboard.unichar = 0; event.keyboard.modifiers = 0; _al_event_source_lock(&the_keyboard.es); _al_event_source_emit_event(&the_keyboard.es, &event); _al_event_source_unlock(&the_keyboard.es); }
/* Generate a resize event if the size has changed. We cannot asynchronously * change the display size here yet, since the user will only know about a * changed size after receiving the resize event. Here we merely add the * event to the queue. */ static void win_generate_resize_event(ALLEGRO_DISPLAY_WIN *win_display) { ALLEGRO_DISPLAY *display = (ALLEGRO_DISPLAY *)win_display; ALLEGRO_EVENT_SOURCE *es = &display->es; WINDOWINFO wi; int x, y, w, h; wi.cbSize = sizeof(WINDOWINFO); GetWindowInfo(win_display->window, &wi); x = wi.rcClient.left; y = wi.rcClient.top; w = wi.rcClient.right - wi.rcClient.left; h = wi.rcClient.bottom - wi.rcClient.top; /* Don't generate events when restoring after minimise. */ if (w == 0 && h == 0 && x == -32000 && y == -32000) return; if (display->w != w || display->h != h) { _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_RESIZE; event.display.timestamp = al_get_time(); event.display.x = x; event.display.y = y; event.display.width = w; event.display.height = h; event.display.source = display; _al_event_source_emit_event(es, &event); /* Generate an expose event. */ /* This seems a bit redundant after a resize. */ if (win_display->display.flags & ALLEGRO_GENERATE_EXPOSE_EVENTS) { event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; _al_event_source_emit_event(es, &event); } } _al_event_source_unlock(es); } }
/* Handle X11 switch event. [X11 thread] */ void _al_xwin_display_switch_handler(ALLEGRO_DISPLAY *display, XFocusChangeEvent *xevent) { /* Anything but NotifyNormal seem to indicate the switch is not "real". * TODO: Find out details? */ if (xevent->mode != NotifyNormal) return; ALLEGRO_EVENT_SOURCE *es = &display->es; _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; if (xevent->type == FocusOut) event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_OUT; else event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_IN; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); }
/* handle_key_release: [bgman thread] * Hook for the X event dispatcher to handle key releases. * The caller must lock the X-display. */ static void handle_key_release(int mycode, ALLEGRO_DISPLAY *display) { if (last_press_code == mycode) last_press_code = -1; _al_event_source_lock(&the_keyboard.parent.es); { /* Update the key_down array. */ _AL_KEYBOARD_STATE_CLEAR_KEY_DOWN(the_keyboard.state, mycode); /* Generate the release event if necessary. */ if (_al_event_source_needs_to_generate_event(&the_keyboard.parent.es)) { ALLEGRO_EVENT event; event.keyboard.type = ALLEGRO_EVENT_KEY_UP; event.keyboard.timestamp = al_get_time(); event.keyboard.display = display; event.keyboard.keycode = mycode; event.keyboard.unichar = 0; event.keyboard.modifiers = 0; _al_event_source_emit_event(&the_keyboard.parent.es, &event); } } _al_event_source_unlock(&the_keyboard.parent.es); }
static LRESULT CALLBACK window_callback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ALLEGRO_DISPLAY *d = NULL; ALLEGRO_DISPLAY_WIN *win_display = NULL; WINDOWINFO wi; int w; int h; int x; int y; unsigned int i; ALLEGRO_EVENT_SOURCE *es = NULL; ALLEGRO_SYSTEM *system = al_get_system_driver(); wi.cbSize = sizeof(WINDOWINFO); if (message == _al_win_msg_call_proc) { ((void (*)(void*))wParam) ((void*)lParam); return 0; } if (!system) { return DefWindowProc(hWnd,message,wParam,lParam); } if (message == _al_win_msg_suicide && wParam) { win_display = (ALLEGRO_DISPLAY_WIN*)wParam; win_display->end_thread = true; DestroyWindow(hWnd); return 0; } for (i = 0; i < system->displays._size; i++) { ALLEGRO_DISPLAY **dptr = _al_vector_ref(&system->displays, i); d = *dptr; win_display = (void*)d; if (win_display->window == hWnd) { es = &d->es; break; } } if (i == system->displays._size) return DefWindowProc(hWnd,message,wParam,lParam); if (message == _al_win_msg_suicide) { win_display->end_thread = true; DestroyWindow(hWnd); return 0; } switch (message) { case WM_INPUT: { UINT dwSize; LPBYTE lpb; RAWINPUT* raw; /* We can't uninstall WM_INPUT mesages. */ if (!al_is_mouse_installed()) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); lpb = malloc(sizeof(BYTE)*dwSize); if (lpb == NULL) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); raw = (RAWINPUT*)lpb; if (raw->header.dwType != RIM_TYPEMOUSE) { free(lpb); break; } { RAWMOUSE *rm = &raw->data.mouse; int x = raw->data.mouse.lLastX; int y = raw->data.mouse.lLastY; bool abs = rm->usFlags & (MOUSE_MOVE_ABSOLUTE || MOUSE_VIRTUAL_DESKTOP); if (abs || x || y) _al_win_mouse_handle_move(x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) _al_win_mouse_handle_button(1, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_UP) _al_win_mouse_handle_button(1, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) _al_win_mouse_handle_button(2, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_UP) _al_win_mouse_handle_button(2, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) _al_win_mouse_handle_button(3, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_UP) _al_win_mouse_handle_button(3, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) _al_win_mouse_handle_button(4, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_UP) _al_win_mouse_handle_button(4, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) _al_win_mouse_handle_button(5, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_UP) _al_win_mouse_handle_button(5, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_WHEEL) { SHORT z = (SHORT)rm->usButtonData; _al_win_mouse_handle_wheel(z / WHEEL_DELTA, false, win_display); } } free(lpb); break; } case WM_LBUTTONDOWN: case WM_LBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_LBUTTONDOWN); _al_win_mouse_handle_button(1, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_MBUTTONDOWN: case WM_MBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_MBUTTONDOWN); _al_win_mouse_handle_button(3, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_RBUTTONDOWN: case WM_RBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_RBUTTONDOWN); _al_win_mouse_handle_button(2, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_XBUTTONDOWN: case WM_XBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); int button = HIWORD(wParam); bool down = (message == WM_XBUTTONDOWN); if (button == XBUTTON1) _al_win_mouse_handle_button(4, down, mx, my, true, win_display); else if (button == XBUTTON2) _al_win_mouse_handle_button(5, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); return TRUE; } case WM_MOUSEWHEEL: { int d = GET_WHEEL_DELTA_WPARAM(wParam); _al_win_mouse_handle_wheel(d / WHEEL_DELTA, false, win_display); return TRUE; } case WM_MOUSEMOVE: { TRACKMOUSEEVENT tme; int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); if (win_display->mouse_cursor_shown && we_hid_the_mouse) { we_hid_the_mouse = false; win_display->display.vt->hide_mouse_cursor((void*)win_display); } _al_win_mouse_handle_move(mx, my, true, win_display); if (mx >= 0 && my >= 0 && mx < d->w && my < d->h) { tme.cbSize = sizeof(tme); tme.dwFlags = TME_QUERY; if (TrackMouseEvent(&tme) && !tme.hwndTrack) { tme.dwFlags = TME_LEAVE; tme.hwndTrack = hWnd; tme.dwHoverTime = 0; TrackMouseEvent(&tme); _al_win_mouse_handle_enter(win_display); } } break; } case WM_MOUSELEAVE: { _al_win_mouse_handle_leave(win_display); break; } case WM_CAPTURECHANGED: if (al_is_mouse_installed()) { int i; ALLEGRO_MOUSE_STATE state; if (!lParam || (HWND)lParam == hWnd) break; al_get_mouse_state(&state); for (i = 1; i <= 5; i++) { if (al_mouse_button_down(&state, i)) _al_win_mouse_handle_button(i, 0, 0, 0, true, win_display); } break; } case WM_NCMOUSEMOVE: { if (!win_display->mouse_cursor_shown) { we_hid_the_mouse = true; win_display->display.vt->show_mouse_cursor((void*)win_display); } break; } case WM_SYSKEYDOWN: { int vcode = wParam; bool repeated = (lParam >> 30) & 0x1; _al_win_kbd_handle_key_press(0, vcode, repeated, win_display); break; } case WM_KEYDOWN: { int vcode = wParam; int scode = (lParam >> 16) & 0xff; bool repeated = (lParam >> 30) & 0x1; /* We can't use TranslateMessage() because we don't know if it will produce a WM_CHAR or not. */ _al_win_kbd_handle_key_press(scode, vcode, repeated, win_display); break; } case WM_SYSKEYUP: case WM_KEYUP: { int vcode = wParam; _al_win_kbd_handle_key_release(vcode, win_display); break; } case WM_SYSCOMMAND: { if (_al_win_disable_screensaver && ((wParam & 0xfff0) == SC_MONITORPOWER || (wParam & 0xfff0) == SC_SCREENSAVE)) { return 0; } else if ((wParam & 0xfff0) == SC_KEYMENU) { /* Prevent Windows from intercepting the ALT key. (Disables opening menus via the ALT key.) */ return 0; } break; } case WM_PAINT: { if ((win_display->display.flags & ALLEGRO_GENERATE_EXPOSE_EVENTS) && _al_event_source_needs_to_generate_event(es)) { RECT r; HRGN hrgn; GetWindowRect(win_display->window, &r); hrgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); if (GetUpdateRgn(win_display->window, hrgn, false) != ERROR) { PAINTSTRUCT ps; DWORD size; LPRGNDATA rgndata; int n; int i; RECT *rects; BeginPaint(win_display->window, &ps); size = GetRegionData(hrgn, 0, NULL); rgndata = _AL_MALLOC(size); GetRegionData(hrgn, size, rgndata); n = rgndata->rdh.nCount; rects = (RECT *)rgndata->Buffer; //GetWindowInfo(win_display->window, &wi); _al_event_source_lock(es); for (i = 0; i < n; i++) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; event.display.timestamp = al_current_time(); event.display.x = rects[i].left; event.display.y = rects[i].top; event.display.width = rects[i].right - rects[i].left; event.display.height = rects[i].bottom - rects[i].top; _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); _AL_FREE(rgndata); EndPaint(win_display->window, &ps); DeleteObject(hrgn); } return 0; } break; } case WM_SETCURSOR: switch (LOWORD(lParam)) { case HTLEFT: case HTRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break; case HTBOTTOM: case HTTOP: SetCursor(LoadCursor(NULL, IDC_SIZENS)); break; case HTBOTTOMLEFT: case HTTOPRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZENESW)); break; case HTBOTTOMRIGHT: case HTTOPLEFT: SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); break; default: if (win_display->mouse_cursor_shown) { SetCursor(win_display->mouse_selected_hcursor); } else { SetCursor(NULL); } break; } return 1; case WM_ACTIVATE: if (LOWORD(wParam) != WA_INACTIVE) { /* This SetWindowPos is for faux-fullscreen windows that lost focus * so they can get placed back on top */ // FIXME: this doesn't seem to work //SetWindowPos(win_display->window, HWND_TOP, 0, 0, 0, 0, // SWP_NOMOVE | SWP_NOSIZE); if (d->vt->switch_in) d->vt->switch_in(d); _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_IN; event.display.timestamp = al_current_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); _al_win_grab_input(win_display); return 0; } else { if (d->flags & ALLEGRO_FULLSCREEN) { d->vt->switch_out(d); } _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_OUT; event.display.timestamp = al_current_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; } break; case WM_MENUCHAR : return (MNC_CLOSE << 16) | (wParam & 0xffff); case WM_CLOSE: _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_CLOSE; event.display.timestamp = al_current_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; case WM_SIZE: if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED) { /* * Delay the resize event so we don't get bogged down with them */ if (!resize_postponed) { resize_postponed = true; postpone_resize(win_display->window); } } return 0; case WM_USER+0: /* Generate a resize event if the size has changed. We cannot asynchronously * change the display size here yet, since the user will only know about a * changed size after receiving the resize event. Here we merely add the * event to the queue. */ GetWindowInfo(win_display->window, &wi); x = wi.rcClient.left; y = wi.rcClient.top; w = wi.rcClient.right - wi.rcClient.left; h = wi.rcClient.bottom - wi.rcClient.top; if (d->w != w || d->h != h) { _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_RESIZE; event.display.timestamp = al_current_time(); event.display.x = x; event.display.y = y; event.display.width = w; event.display.height = h; _al_event_source_emit_event(es, &event); } /* Generate an expose event. */ if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; event.display.timestamp = al_current_time(); event.display.x = x; event.display.y = y; event.display.width = w; event.display.height = h; _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); } resize_postponed = false; win_display->can_acknowledge = true; return 0; } return DefWindowProc(hWnd,message,wParam,lParam); }
static void handle_key_press(int mycode, int unichar, int filtered, unsigned int modifiers, ALLEGRO_DISPLAY *display) { bool is_repeat; is_repeat = (last_press_code == mycode); if (mycode > 0) last_press_code = mycode; _al_event_source_lock(&the_keyboard.parent.es); { /* Update the key_down array. */ _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_keyboard.state, mycode); /* Generate the events if necessary. */ if (_al_event_source_needs_to_generate_event(&the_keyboard.parent.es)) { ALLEGRO_EVENT event; event.keyboard.type = ALLEGRO_EVENT_KEY_DOWN; event.keyboard.timestamp = al_get_time(); event.keyboard.display = display; event.keyboard.keycode = last_press_code; event.keyboard.unichar = 0; event.keyboard.modifiers = 0; event.keyboard.repeat = false; /* Don't send KEY_DOWN for non-physical key events. */ if (mycode > 0 && !is_repeat) { _al_event_source_emit_event(&the_keyboard.parent.es, &event); } /* Don't send KEY_CHAR for events filtered by an input method, * nor modifier keys. */ if (!filtered && mycode < ALLEGRO_KEY_MODIFIERS) { event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR; event.keyboard.unichar = unichar; event.keyboard.modifiers = modifiers; event.keyboard.repeat = is_repeat; _al_event_source_emit_event(&the_keyboard.parent.es, &event); } } } _al_event_source_unlock(&the_keyboard.parent.es); // FIXME? #ifndef ALLEGRO_RASPBERRYPI /* Toggle mouse grab key. The system driver should not be locked here. */ if (last_press_code && !is_repeat) { ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); if (system->toggle_mouse_grab_keycode == mycode && (modifiers & system->toggle_mouse_grab_modifiers) == system->toggle_mouse_grab_modifiers) { if (system->mouse_grab_display == display) al_ungrab_mouse(); else al_grab_mouse(display); } } #endif /* Exit by Ctrl-Alt-End. */ if ((_al_three_finger_flag) && ((mycode == ALLEGRO_KEY_DELETE) || (mycode == ALLEGRO_KEY_END)) && (modifiers & ALLEGRO_KEYMOD_CTRL) && (modifiers & (ALLEGRO_KEYMOD_ALT | ALLEGRO_KEYMOD_ALTGR))) { ALLEGRO_WARN("Three finger combo detected. SIGTERMing " "pid %d\n", main_pid); kill(main_pid, SIGTERM); } }
static LRESULT CALLBACK window_callback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ALLEGRO_DISPLAY *d = NULL; ALLEGRO_DISPLAY_WIN *win_display = NULL; unsigned int i; ALLEGRO_EVENT_SOURCE *es = NULL; ALLEGRO_SYSTEM *system = al_get_system_driver(); if (message == _al_win_msg_call_proc) { ((void (*)(void*))wParam) ((void*)lParam); return 0; } if (!system) { return DefWindowProc(hWnd,message,wParam,lParam); } if (message == _al_win_msg_suicide && wParam) { win_display = (ALLEGRO_DISPLAY_WIN*)wParam; break_window_message_pump(win_display, hWnd); DestroyWindow(hWnd); return 0; } for (i = 0; i < system->displays._size; i++) { ALLEGRO_DISPLAY **dptr = _al_vector_ref(&system->displays, i); d = *dptr; win_display = (void*)d; if (win_display->window == hWnd) { es = &d->es; break; } } if (i == system->displays._size) return DefWindowProc(hWnd,message,wParam,lParam); if (message == _al_win_msg_suicide) { break_window_message_pump(win_display, hWnd); DestroyWindow(hWnd); return 0; } switch (message) { case WM_INPUT: { /* RAW Input is currently unused. */ UINT dwSize; LPBYTE lpb; RAWINPUT* raw; /* We can't uninstall WM_INPUT mesages. */ if (!al_is_mouse_installed()) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); lpb = al_malloc(sizeof(BYTE)*dwSize); if (lpb == NULL) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); raw = (RAWINPUT*)lpb; if (raw->header.dwType != RIM_TYPEMOUSE) { al_free(lpb); break; } { RAWMOUSE *rm = &raw->data.mouse; int x = raw->data.mouse.lLastX; int y = raw->data.mouse.lLastY; bool abs = (rm->usFlags & (MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP)) != 0; if (abs || x || y) _al_win_mouse_handle_move(x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) _al_win_mouse_handle_button(1, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_UP) _al_win_mouse_handle_button(1, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) _al_win_mouse_handle_button(2, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_UP) _al_win_mouse_handle_button(2, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) _al_win_mouse_handle_button(3, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_UP) _al_win_mouse_handle_button(3, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) _al_win_mouse_handle_button(4, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_UP) _al_win_mouse_handle_button(4, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) _al_win_mouse_handle_button(5, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_UP) _al_win_mouse_handle_button(5, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_WHEEL) { SHORT z = (SHORT)rm->usButtonData; _al_win_mouse_handle_wheel(z / WHEEL_DELTA, false, win_display); } } al_free(lpb); break; } case WM_LBUTTONDOWN: case WM_LBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_LBUTTONDOWN); _al_win_mouse_handle_button(1, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_MBUTTONDOWN: case WM_MBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_MBUTTONDOWN); _al_win_mouse_handle_button(3, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_RBUTTONDOWN: case WM_RBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_RBUTTONDOWN); _al_win_mouse_handle_button(2, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_XBUTTONDOWN: case WM_XBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); int button = HIWORD(wParam); bool down = (message == WM_XBUTTONDOWN); if (button == XBUTTON1) _al_win_mouse_handle_button(4, down, mx, my, true, win_display); else if (button == XBUTTON2) _al_win_mouse_handle_button(5, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); return TRUE; } case WM_MOUSEWHEEL: { int d = GET_WHEEL_DELTA_WPARAM(wParam); _al_win_mouse_handle_wheel(d / WHEEL_DELTA, false, win_display); return TRUE; } case WM_MOUSEHWHEEL: { int d = GET_WHEEL_DELTA_WPARAM(wParam); _al_win_mouse_handle_hwheel(d / WHEEL_DELTA, false, win_display); return TRUE; } case WM_MOUSEMOVE: { TRACKMOUSEEVENT tme; int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); if (win_display->mouse_cursor_shown && we_hid_the_mouse) { we_hid_the_mouse = false; win_display->display.vt->hide_mouse_cursor((void*)win_display); } _al_win_mouse_handle_move(mx, my, true, win_display); if (mx >= 0 && my >= 0 && mx < d->w && my < d->h) { tme.cbSize = sizeof(tme); tme.dwFlags = TME_QUERY; if (TrackMouseEvent(&tme) && !tme.hwndTrack) { tme.dwFlags = TME_LEAVE; tme.hwndTrack = hWnd; tme.dwHoverTime = 0; TrackMouseEvent(&tme); _al_win_mouse_handle_enter(win_display); } } /* WM_SETCURSOR messages are not received while the mouse is * captured. We call SetCursor here so that changing the mouse * cursor has an effect while the user is holding down the mouse * button. */ if (GetCapture() == hWnd && win_display->mouse_cursor_shown) { SetCursor(win_display->mouse_selected_hcursor); } break; } case WM_MOUSELEAVE: { _al_win_mouse_handle_leave(win_display); break; } case WM_CAPTURECHANGED: { if (al_is_mouse_installed()) { int i; ALLEGRO_MOUSE_STATE state; if (!lParam || (HWND)lParam == hWnd) break; al_get_mouse_state(&state); for (i = 1; i <= 5; i++) { if (al_mouse_button_down(&state, i)) _al_win_mouse_handle_button(i, 0, 0, 0, true, win_display); } } break; } case WM_NCMOUSEMOVE: { if (!win_display->mouse_cursor_shown) { we_hid_the_mouse = true; win_display->display.vt->show_mouse_cursor((void*)win_display); } break; } case WM_SYSKEYDOWN: { int vcode = wParam; bool extended = (lParam >> 24) & 0x1; bool repeated = (lParam >> 30) & 0x1; _al_win_kbd_handle_key_press(0, vcode, extended, repeated, win_display); break; } case WM_KEYDOWN: { int vcode = wParam; int scode = (lParam >> 16) & 0xff; bool extended = (lParam >> 24) & 0x1; bool repeated = (lParam >> 30) & 0x1; /* We can't use TranslateMessage() because we don't know if it will produce a WM_CHAR or not. */ _al_win_kbd_handle_key_press(scode, vcode, extended, repeated, win_display); break; } case WM_SYSKEYUP: case WM_KEYUP: { int vcode = wParam; int scode = (lParam >> 16) & 0xff; bool extended = (lParam >> 24) & 0x1; _al_win_kbd_handle_key_release(scode, vcode, extended, win_display); break; } case WM_SYSCOMMAND: { if (_al_win_disable_screensaver && ((wParam & 0xfff0) == SC_MONITORPOWER || (wParam & 0xfff0) == SC_SCREENSAVE)) { return 0; } else if ((wParam & 0xfff0) == SC_KEYMENU) { /* Prevent Windows from intercepting the ALT key. (Disables opening menus via the ALT key.) */ return 0; } break; } case WM_PAINT: { if (win_display->display.flags & ALLEGRO_GENERATE_EXPOSE_EVENTS) { RECT r; HRGN hrgn; GetWindowRect(win_display->window, &r); hrgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); if (GetUpdateRgn(win_display->window, hrgn, false) != ERROR) { PAINTSTRUCT ps; DWORD size; LPRGNDATA rgndata; int n; int i; RECT *rects; BeginPaint(win_display->window, &ps); size = GetRegionData(hrgn, 0, NULL); rgndata = al_malloc(size); GetRegionData(hrgn, size, rgndata); n = rgndata->rdh.nCount; rects = (RECT *)rgndata->Buffer; _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; event.display.timestamp = al_get_time(); for (i = 0; i < n; i++) { event.display.x = rects[i].left; event.display.y = rects[i].top; event.display.width = rects[i].right - rects[i].left; event.display.height = rects[i].bottom - rects[i].top; _al_event_source_emit_event(es, &event); } } _al_event_source_unlock(es); al_free(rgndata); EndPaint(win_display->window, &ps); DeleteObject(hrgn); } return 0; } break; } case WM_SETCURSOR: switch (LOWORD(lParam)) { case HTLEFT: case HTRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break; case HTBOTTOM: case HTTOP: SetCursor(LoadCursor(NULL, IDC_SIZENS)); break; case HTBOTTOMLEFT: case HTTOPRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZENESW)); break; case HTBOTTOMRIGHT: case HTTOPLEFT: SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); break; default: if (win_display->mouse_cursor_shown) { SetCursor(win_display->mouse_selected_hcursor); } else { SetCursor(NULL); } break; } return 1; case WM_ACTIVATE: if (HIWORD(wParam) && LOWORD(wParam) != WA_INACTIVE) break; if (HIWORD(wParam)) d->flags |= ALLEGRO_MINIMIZED; else d->flags &= ~ALLEGRO_MINIMIZED; if (LOWORD(wParam) != WA_INACTIVE) { // Make fullscreen windows TOPMOST again if (d->flags & ALLEGRO_FULLSCREEN_WINDOW) { SetWindowPos(win_display->window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } if (d->vt->switch_in) d->vt->switch_in(d); _al_win_fix_modifiers(); _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; memset(&event, 0, sizeof(event)); event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_IN; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); _al_win_grab_input(win_display); return 0; } else { // Remove TOPMOST flag from fullscreen windows so we can alt-tab. Also must raise the new activated window if (d->flags & ALLEGRO_FULLSCREEN_WINDOW) { SetWindowPos(win_display->window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); SetWindowPos(GetForegroundWindow(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } // Show the taskbar in case we hid it SetWindowPos(FindWindow("Shell_traywnd", ""), 0, 0, 0, 0, 0, SWP_SHOWWINDOW); if (d->flags & ALLEGRO_FULLSCREEN) { d->vt->switch_out(d); } _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; memset(&event, 0, sizeof(event)); event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_OUT; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; } break; case WM_MENUCHAR : return (MNC_CLOSE << 16) | (wParam & 0xffff); case WM_CLOSE: _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; memset(&event, 0, sizeof(event)); event.display.type = ALLEGRO_EVENT_DISPLAY_CLOSE; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; case WM_SIZE: if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED) { /* * Delay the resize event so we don't get bogged down with them */ if (!resize_postponed) { resize_postponed = true; _beginthread(postpone_thread_proc, 0, (void *)d); } } return 0; case WM_ENTERSIZEMOVE: /* DefWindowProc for WM_ENTERSIZEMOVE enters a modal loop, which also * ends up blocking the loop in d3d_display_thread_proc (which is * where we are called from, if using D3D). Rather than batching up * intermediate resize events which the user cannot acknowledge in the * meantime anyway, make it so only a single resize event is generated * at WM_EXITSIZEMOVE. */ if (d->flags & ALLEGRO_DIRECT3D) { resize_postponed = true; } break; case WM_EXITSIZEMOVE: if (resize_postponed) { win_generate_resize_event(win_display); win_display->ignore_resize = false; resize_postponed = false; win_display->can_acknowledge = true; } break; } return DefWindowProc(hWnd,message,wParam,lParam); }
static void generate_touch_input_event(int type, double timestamp, int id, float x, float y, float dx, float dy, bool primary, ALLEGRO_DISPLAY_WIN *win_disp) { ALLEGRO_EVENT event; bool want_touch_event = _al_event_source_needs_to_generate_event(&touch_input.es); bool want_mouse_emulation_event = _al_event_source_needs_to_generate_event(&touch_input.mouse_emulation_es) && primary && al_is_mouse_installed(); if (touch_input.mouse_emulation_mode == ALLEGRO_MOUSE_EMULATION_NONE) want_mouse_emulation_event = false; else if (touch_input.mouse_emulation_mode == ALLEGRO_MOUSE_EMULATION_INCLUSIVE) want_touch_event = want_mouse_emulation_event ? (want_touch_event && !primary) : want_touch_event; else if (touch_input.mouse_emulation_mode == ALLEGRO_MOUSE_EMULATION_EXCLUSIVE) want_touch_event = want_mouse_emulation_event ? false : want_touch_event; if (!want_touch_event && !want_mouse_emulation_event) return; if (want_touch_event) { event.touch.type = type; event.touch.display = (ALLEGRO_DISPLAY*)win_disp; event.touch.timestamp = timestamp; event.touch.id = id; event.touch.x = x; event.touch.y = y; event.touch.dx = dx; event.touch.dy = dy; event.touch.primary = primary; _al_event_source_lock(&touch_input.es); _al_event_source_emit_event(&touch_input.es, &event); _al_event_source_unlock(&touch_input.es); } if (want_mouse_emulation_event) { ALLEGRO_MOUSE_STATE state; switch (type) { case ALLEGRO_EVENT_TOUCH_BEGIN: type = ALLEGRO_EVENT_MOUSE_BUTTON_DOWN; break; case ALLEGRO_EVENT_TOUCH_CANCEL: case ALLEGRO_EVENT_TOUCH_END: type = ALLEGRO_EVENT_MOUSE_BUTTON_UP; break; case ALLEGRO_EVENT_TOUCH_MOVE: type = ALLEGRO_EVENT_MOUSE_AXES; break; } al_get_mouse_state(&state); event.mouse.type = type; event.mouse.timestamp = timestamp; event.mouse.display = (ALLEGRO_DISPLAY*)win_disp; event.mouse.x = (int)x; event.mouse.y = (int)y; event.mouse.z = state.z; event.mouse.w = state.w; event.mouse.dx = (int)dx; event.mouse.dy = (int)dy; event.mouse.dz = 0; event.mouse.dw = 0; event.mouse.button = 1; event.mouse.pressure = state.pressure; al_set_mouse_xy(event.mouse.display, event.mouse.x, event.mouse.y); _al_event_source_lock(&touch_input.mouse_emulation_es); _al_event_source_emit_event(&touch_input.mouse_emulation_es, &event); _al_event_source_unlock(&touch_input.mouse_emulation_es); } }
void _al_xglx_display_configure(ALLEGRO_DISPLAY *d, int x, int y, int width, int height, bool setglxy) { ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d; ALLEGRO_EVENT_SOURCE *es = &glx->display.es; _al_event_source_lock(es); /* Generate a resize event if the size has changed non-programmtically. * We cannot asynchronously change the display size here yet, since the user * will only know about a changed size after receiving the resize event. * Here we merely add the event to the queue. */ if (!glx->programmatic_resize && (d->w != width || d->h != height)) { if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_RESIZE; event.display.timestamp = al_get_time(); event.display.x = x; event.display.y = y; event.display.width = width; event.display.height = height; _al_event_source_emit_event(es, &event); } } /* We receive two configure events when toggling the window frame. * We ignore the first one as it has bogus coordinates. * The only way to tell them apart seems to be the send_event field. * Unfortunately, we also end up ignoring the only event we receive in * response to a XMoveWindow request so we have to compensate for that. */ if (setglxy) { glx->x = x; glx->y = y; } ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX*)al_get_system_driver(); ALLEGRO_MONITOR_INFO mi; int center_x = (glx->x + (glx->x + width)) / 2; int center_y = (glx->y + (glx->y + height)) / 2; _al_xglx_get_monitor_info(system, glx->adapter, &mi); ALLEGRO_DEBUG("xconfigure event! %ix%i\n", x, y); /* check if we're no longer inside the stored adapter */ if ((center_x < mi.x1 && center_x > mi.x2) || (center_y < mi.y1 && center_y > mi.x2)) { int new_adapter = _al_xglx_get_adapter(system, glx, true); if (new_adapter != glx->adapter) { ALLEGRO_DEBUG("xdpy: adapter change!\n"); _al_xglx_unuse_adapter(system, glx->adapter); if (d->flags & ALLEGRO_FULLSCREEN) _al_xglx_restore_video_mode(system, glx->adapter); glx->adapter = new_adapter; _al_xglx_use_adapter(system, glx->adapter); } } _al_event_source_unlock(es); }
/* _al_win_kbd_handle_key_press: * Does stuff when a key is pressed. */ void _al_win_kbd_handle_key_press(int scode, int vcode, bool extended, bool repeated, ALLEGRO_DISPLAY_WIN *win_disp) { ALLEGRO_DISPLAY *display = (ALLEGRO_DISPLAY *)win_disp; ALLEGRO_EVENT event; int my_code; bool actual_repeat; int char_count; int event_count; int i; BYTE ks[256]; WCHAR buf[8] = { 0 }; if (!installed) return; /* Check for an extended key first. */ my_code = 0; if (extended) my_code = extkey_to_keycode(vcode); /* Map a non-extended key. This also works as a fallback in case the key was extended, but no extended mapping was found. */ if (my_code == 0) { if (vcode == VK_SHIFT) /* Left or right Shift key? */ vcode = MapVirtualKey(scode, MAPVK_VSC_TO_VK_EX); my_code = hw_to_mycode[vcode]; } update_modifiers(my_code, true); actual_repeat = repeated && _AL_KEYBOARD_STATE_KEY_DOWN(the_state, my_code); _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_state, my_code); if (!_al_event_source_needs_to_generate_event(&the_keyboard.es)) return; event.keyboard.type = ALLEGRO_EVENT_KEY_DOWN; event.keyboard.timestamp = al_get_time(); event.keyboard.display = display; event.keyboard.keycode = my_code; event.keyboard.unichar = 0; event.keyboard.modifiers = 0; event.keyboard.repeat = false; _al_event_source_lock(&the_keyboard.es); if (my_code > 0 && !actual_repeat) { _al_event_source_emit_event(&the_keyboard.es, &event); } /* Send char events, but not for modifier keys or dead keys. */ if (my_code < ALLEGRO_KEY_MODIFIERS) { char_count = ToUnicode(vcode, scode, GetKeyboardState(ks) ? ks : NULL, buf, 8, 0); /* Send ASCII code 127 for both Del keys. */ if (char_count == 0 && vcode == VK_DELETE) { char_count = 1; buf[0] = 127; } if (char_count != -1) { /* -1 means it was a dead key. */ event_count = char_count ? char_count : 1; event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR; update_toggle_modifiers(); event.keyboard.modifiers = modifiers; event.keyboard.repeat = actual_repeat; for (i = 0; i < event_count; i++) { event.keyboard.unichar = buf[i]; _al_event_source_emit_event(&the_keyboard.es, &event); } } } _al_event_source_unlock(&the_keyboard.es); /* Toggle mouse grab key. */ if (my_code && !repeated) { ALLEGRO_SYSTEM_WIN *system = (void *)al_get_system_driver(); if (my_code == system->toggle_mouse_grab_keycode && (modifiers & system->toggle_mouse_grab_modifiers) == system->toggle_mouse_grab_modifiers) { if (system->mouse_grab_display == display) { al_ungrab_mouse(); } else { al_grab_mouse(display); } } } }
void _al_xglx_display_configure(ALLEGRO_DISPLAY *d, int x, int y, int width, int height, bool setglxy) { ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d; ALLEGRO_EVENT_SOURCE *es = &glx->display.es; _al_event_source_lock(es); /* Generate a resize event if the size has changed non-programmatically. * We cannot asynchronously change the display size here yet, since the user * will only know about a changed size after receiving the resize event. * Here we merely add the event to the queue. */ if (!glx->programmatic_resize && (d->w != width || d->h != height)) { if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_RESIZE; event.display.timestamp = al_get_time(); event.display.x = x; event.display.y = y; event.display.width = width; event.display.height = height; _al_event_source_emit_event(es, &event); } } if (setglxy) { glx->x = x; glx->y = y; } ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX*)al_get_system_driver(); ALLEGRO_MONITOR_INFO mi; int center_x = (glx->x + (glx->x + width)) / 2; int center_y = (glx->y + (glx->y + height)) / 2; _al_xglx_get_monitor_info(system, glx->adapter, &mi); ALLEGRO_DEBUG("xconfigure event! %ix%i\n", x, y); /* check if we're no longer inside the stored adapter */ if ((center_x < mi.x1 && center_x > mi.x2) || (center_y < mi.y1 && center_y > mi.x2)) { int new_adapter = _al_xglx_get_adapter(system, glx, true); if (new_adapter != glx->adapter) { ALLEGRO_DEBUG("xdpy: adapter change!\n"); _al_xglx_unuse_adapter(system, glx->adapter); if (d->flags & ALLEGRO_FULLSCREEN) _al_xglx_restore_video_mode(system, glx->adapter); glx->adapter = new_adapter; _al_xglx_use_adapter(system, glx->adapter); } } _al_xwin_check_maximized(d); _al_event_source_unlock(es); }