Atrinik Client 2.5
events/event.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00031 #include <global.h>
00032 
00033 int old_mouse_y = 0;
00034 
00038 static uint8 keys_pressed[SDLK_LAST];
00039 
00044 uint8 key_is_pressed(SDLKey key)
00045 {
00046     return keys_pressed[key];
00047 }
00048 
00049 /* src:  (if != DRAG_GET_STATUS) set actual dragging source.
00050  * item: (if != NULL) set actual dragging item.
00051  * ret:  the actual dragging source. */
00052 int draggingInvItem(int src)
00053 {
00054     static int drag_src = DRAG_NONE;
00055 
00056     if (src != DRAG_GET_STATUS)
00057         drag_src = src;
00058 
00059     return drag_src;
00060 }
00061 
00068 void resize_window(int width, int height)
00069 {
00070     setting_set_int(OPT_CAT_CLIENT, OPT_RESOLUTION_X, width);
00071     setting_set_int(OPT_CAT_CLIENT, OPT_RESOLUTION_Y, height);
00072 
00073     if (!setting_get_int(OPT_CAT_CLIENT, OPT_OFFSCREEN_WIDGETS) && width > 100 && height > 100)
00074     {
00075         widgets_ensure_onscreen();
00076     }
00077 }
00078 
00082 int Event_PollInputDevice()
00083 {
00084     SDL_Event event;
00085     int x, y, done = 0;
00086     static Uint32 Ticks = 0;
00087     int tx, ty;
00088 
00089     /* Execute mouse actions, even if mouse button is being held. */
00090     if ((SDL_GetTicks() - Ticks > 125) || !Ticks)
00091     {
00092         if (GameStatus >= GAME_STATUS_PLAY)
00093         {
00094             if (text_input_string_flag && cpl.input_mode == INPUT_MODE_NUMBER)
00095             {
00096                 Ticks = SDL_GetTicks();
00097                 mouse_InputNumber();
00098             }
00099             /* Mouse gesture: hold right+left buttons or middle button
00100              * to fire. */
00101             else if (!cpl.action_timer && cpl.menustatus == MENU_NO && widget_mouse_event.owner == cur_widget[MAP_ID])
00102             {
00103                 int state = SDL_GetMouseState(&x, &y);
00104 
00105                 if ((state == (SDL_BUTTON(SDL_BUTTON_RIGHT) | SDL_BUTTON(SDL_BUTTON_LEFT)) || state == SDL_BUTTON(SDL_BUTTON_MIDDLE)) && mouse_to_tile_coords(x, y, &tx, &ty))
00106                 {
00107                     Ticks = SDL_GetTicks();
00108                     cpl.fire_on = 1;
00109                     move_keys(dir_from_tile_coords(tx, ty));
00110                     cpl.fire_on = 0;
00111                 }
00112             }
00113         }
00114     }
00115 
00116     while (SDL_PollEvent(&event))
00117     {
00118         if (event.type == SDL_KEYUP)
00119         {
00120             keys_pressed[event.key.keysym.sym] = 0;
00121         }
00122         else if (event.type == SDL_KEYDOWN)
00123         {
00124             keys_pressed[event.key.keysym.sym] = 1;
00125         }
00126 
00127         x = event.motion.x;
00128         y = event.motion.y;
00129 
00130         if ((event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEMOTION || event.type == SDL_KEYUP || event.type == SDL_KEYDOWN) && popup_handle_event(&event))
00131         {
00132             continue;
00133         }
00134 
00135         switch (event.type)
00136         {
00137             /* Screen has been resized, update screen size. */
00138             case SDL_VIDEORESIZE:
00139                 ScreenSurface = SDL_SetVideoMode(event.resize.w, event.resize.h, video_get_bpp(), get_video_flags());
00140 
00141                 if (!ScreenSurface)
00142                 {
00143                     LOG(llevError, "Unable to grab surface after resize event: %s\n", SDL_GetError());
00144                 }
00145 
00146                 /* Set resolution to custom. */
00147                 setting_set_int(OPT_CAT_CLIENT, OPT_RESOLUTION, 0);
00148                 resize_window(event.resize.w, event.resize.h);
00149                 break;
00150 
00151             case SDL_MOUSEBUTTONUP:
00152                 if (lists_handle_mouse(x, y, &event))
00153                 {
00154                     break;
00155                 }
00156 
00157                 if (GameStatus < GAME_STATUS_PLAY)
00158                 {
00159                     break;
00160                 }
00161 
00162                 /* Widget has higher priority than anything below, except menus
00163                  * so break if we had a widget event */
00164                 if (widget_event_mouseup(x,y, &event))
00165                 {
00166                     /* NOTE: Place here special handlings that have to be done, even if a widget owns it */
00167 
00168                     /* Sanity handling */
00169                     draggingInvItem(DRAG_NONE);
00170                     break;
00171                 }
00172 
00173                 if (text_input_string_flag && cpl.input_mode == INPUT_MODE_NUMBER)
00174                     break;
00175 
00176                 /* Only drop to ground has to be handled, the rest do the widget handlers */
00177                 if (draggingInvItem(DRAG_GET_STATUS) > DRAG_IWIN_BELOW)
00178                 {
00179                     /* KEYFUNC_APPLY and KEYFUNC_DROP works only if cpl.inventory_win = IWIN_INV. The tag must
00180                      * be placed in cpl.win_inv_tag. So we do this and after DnD we restore the old values. */
00181                     int old_inv_win = cpl.inventory_win;
00182                     int old_inv_tag = cpl.win_inv_tag;
00183                     cpl.inventory_win = IWIN_INV;
00184 
00185                     /* Drop to ground */
00186                     if (mouse_to_tile_coords(x, y, NULL, NULL))
00187                     {
00188                         if (draggingInvItem(DRAG_GET_STATUS) != DRAG_QUICKSLOT_SPELL)
00189                         {
00190                             keybind_process_command("?DROP");
00191                         }
00192                     }
00193 
00194                     cpl.inventory_win = old_inv_win;
00195                     cpl.win_inv_tag = old_inv_tag;
00196                 }
00197 
00198                 draggingInvItem(DRAG_NONE);
00199                 break;
00200 
00201             case SDL_MOUSEMOTION:
00202             {
00203                 if (lists_handle_mouse(x, y, &event))
00204                 {
00205                     break;
00206                 }
00207 
00208                 if (GameStatus < GAME_STATUS_PLAY)
00209                 {
00210                     break;
00211                 }
00212 
00213                 x_custom_cursor = x;
00214                 y_custom_cursor = y;
00215 
00216                 /* We have to break now when menu is active - menu is higher priority than any widget! */
00217                 if (cpl.menustatus != MENU_NO)
00218                 {
00219                     break;
00220                 }
00221 
00222                 if (widget_event_mousemv(x, y, &event))
00223                 {
00224                     /* NOTE: place here special handlings that have to be done, even if a widget owns it */
00225 
00226                     break;
00227                 }
00228 
00229                 break;
00230             }
00231 
00232             case SDL_MOUSEBUTTONDOWN:
00233             {
00234                 if (lists_handle_mouse(x, y, &event))
00235                 {
00236                     break;
00237                 }
00238 
00239                 if (GameStatus == GAME_STATUS_WAITLOOP)
00240                 {
00241                     break;
00242                 }
00243 
00244                 if (GameStatus < GAME_STATUS_PLAY)
00245                     break;
00246 
00247                 /* If this is book GUI, handle the click */
00248                 if (cpl.menustatus == MENU_BOOK)
00249                 {
00250                     book_handle_event(&event);
00251                 }
00252 
00253                 if (cpl.menustatus == MENU_REGION_MAP)
00254                 {
00255                     region_map_handle_event(&event);
00256                 }
00257 
00258                 /* Beyond here only when no menu is active. */
00259                 if (cpl.menustatus != MENU_NO)
00260                 {
00261                     break;
00262                 }
00263 
00264                 /* Widget System */
00265                 if (widget_event_mousedn(x, y, &event))
00266                 {
00267                     /* NOTE: Place here special handlings that have to be done, even if a widget owns it */
00268 
00269                     break;
00270                 }
00271 
00272                 break;
00273             }
00274 
00275             case SDL_KEYUP:
00276             case SDL_KEYDOWN:
00277                 done = event_poll_key(&event);
00278                 break;
00279 
00280             case SDL_QUIT:
00281                 done = 1;
00282                 break;
00283 
00284             default:
00285                 break;
00286         }
00287 
00288         old_mouse_y = y;
00289     }
00290 
00291     /* OK, now we have processed all real events.
00292      * Now run through the list of keybinds and control repeat time value.
00293      * If the key is still marked as pressed in our keyboard mirror table,
00294      * and the time this is pressed <= keybind press value + repeat value,
00295      * we assume a repeat flag is true.
00296      * Sadly, SDL doesn't have a tick count inside the event messages, which
00297      * means the tick value when the event really was triggered. So, the
00298      * client can't simulate the buffered "rhythm" of the key pressings when
00299      * the client lags. */
00300     key_repeat();
00301 
00302     return done;
00303 }