1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 #include "SDL_mouse.h" 25 #include "../../events/SDL_events_c.h" 26 #include "../SDL_cursor_c.h" 27 #include "SDL_ph_mouse_c.h" 28 29 struct WMcursor 30 { 31 PhCursorDef_t *ph_cursor ; 32 }; 33 34 void ph_FreeWMCursor(_THIS, WMcursor *cursor) 35 { 36 if (window != NULL) 37 { 38 SDL_Lock_EventThread(); 39 40 if (PtSetResource(window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_INHERIT, 0) < 0) 41 { 42 /* TODO: output error msg */ 43 } 44 45 SDL_Unlock_EventThread(); 46 } 47 48 SDL_free(cursor); 49 } 50 51 WMcursor *ph_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) 52 { 53 WMcursor* cursor; 54 int clen, i; 55 unsigned char bit, databit, maskbit; 56 57 /* Allocate and initialize the cursor memory */ 58 if ((cursor = (WMcursor*)SDL_malloc(sizeof(WMcursor))) == NULL) 59 { 60 SDL_OutOfMemory(); 61 return(NULL); 62 } 63 SDL_memset(cursor,0,sizeof(WMcursor)); 64 65 cursor->ph_cursor = (PhCursorDef_t *) SDL_malloc(sizeof(PhCursorDef_t) + 32*4*2); 66 67 if (cursor->ph_cursor == NULL) 68 { 69 SDL_SetError("ph_CreateWMCursor(): cursor malloc failed !\n"); 70 return NULL; 71 } 72 73 SDL_memset(cursor->ph_cursor,0,(sizeof(PhCursorDef_t) + 32*4*2)); 74 75 cursor->ph_cursor->hdr.type =Ph_RDATA_CURSOR; 76 cursor->ph_cursor->size1.x = (short)w; 77 cursor->ph_cursor->size1.y = (short)h; 78 cursor->ph_cursor->offset1.x = (short)hot_x; 79 cursor->ph_cursor->offset1.y = (short)hot_y; 80 cursor->ph_cursor->bytesperline1 = (char)w/8; 81 cursor->ph_cursor->color1 = Pg_WHITE; 82 cursor->ph_cursor->size2.x = (short)w; 83 cursor->ph_cursor->size2.y = (short)h; 84 cursor->ph_cursor->offset2.x = (short)hot_x; 85 cursor->ph_cursor->offset2.y = (short)hot_y; 86 cursor->ph_cursor->bytesperline2 = (char)w/8; 87 cursor->ph_cursor->color2 = Pg_BLACK; 88 89 clen = (w/8)*h; 90 91 /* Copy the mask and the data to different bitmap planes */ 92 for (i=0; i<clen; ++i) 93 { 94 for (bit = 0; bit < 8; bit++) 95 { 96 databit = data[i] & (1 << bit); 97 maskbit = mask[i] & (1 << bit); 98 99 cursor->ph_cursor->images[i] |= (databit == 0) ? maskbit : 0; 100 /* If the databit != 0, treat it as a black pixel and 101 * ignore the maskbit (can't do an inverted color) */ 102 cursor->ph_cursor->images[i+clen] |= databit; 103 } 104 } 105 106 /* #bytes following the hdr struct */ 107 cursor->ph_cursor->hdr.len =sizeof(PhCursorDef_t) + clen*2 - sizeof(PhRegionDataHdr_t); 108 109 return (cursor); 110 } 111 112 PhCursorDef_t ph_GetWMPhCursor(WMcursor *cursor) 113 { 114 return (*cursor->ph_cursor); 115 } 116 117 int ph_ShowWMCursor(_THIS, WMcursor* cursor) 118 { 119 PtArg_t args[3]; 120 int nargs = 0; 121 122 /* Don't do anything if the display is gone */ 123 if (window == NULL) 124 { 125 return (0); 126 } 127 128 /* looks like photon can't draw mouse cursor in direct mode */ 129 if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) 130 { 131 /* disable the fake mouse in the fullscreen OpenGL mode */ 132 if ((this->screen->flags & SDL_OPENGL) == SDL_OPENGL) 133 { 134 cursor=NULL; 135 } 136 else 137 { 138 return (0); 139 } 140 } 141 142 /* Set the photon cursor, or blank if cursor is NULL */ 143 if (cursor!=NULL) 144 { 145 PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_BITMAP, 0); 146 /* Could set next to any PgColor_t value */ 147 PtSetArg(&args[1], Pt_ARG_CURSOR_COLOR, Ph_CURSOR_DEFAULT_COLOR , 0); 148 PtSetArg(&args[2], Pt_ARG_BITMAP_CURSOR, cursor->ph_cursor, (cursor->ph_cursor->hdr.len + sizeof(PhRegionDataHdr_t))); 149 nargs = 3; 150 } 151 else /* Ph_CURSOR_NONE */ 152 { 153 PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0); 154 nargs = 1; 155 } 156 157 SDL_Lock_EventThread(); 158 159 if (PtSetResources(window, nargs, args) < 0 ) 160 { 161 return (0); 162 } 163 164 SDL_Unlock_EventThread(); 165 166 return (1); 167 } 168 169 170 void ph_WarpWMCursor(_THIS, Uint16 x, Uint16 y) 171 { 172 short abs_x, abs_y; 173 174 SDL_Lock_EventThread(); 175 PtGetAbsPosition( window, &abs_x, &abs_y ); 176 PhMoveCursorAbs( PhInputGroup(NULL), x + abs_x, y + abs_y ); 177 SDL_Unlock_EventThread(); 178 } 179 180 181 void ph_CheckMouseMode(_THIS) 182 { 183 /* If the mouse is hidden and input is grabbed, we use relative mode */ 184 if ( !(SDL_cursorstate & CURSOR_VISIBLE) && (this->input_grab != SDL_GRAB_OFF)) 185 { 186 mouse_relative = 1; 187 } 188 else 189 { 190 mouse_relative = 0; 191 } 192 } 193 194 195 void ph_UpdateMouse(_THIS) 196 { 197 PhCursorInfo_t phcursor; 198 short abs_x; 199 short abs_y; 200 201 /* Lock the event thread, in multi-threading environments */ 202 SDL_Lock_EventThread(); 203 204 /* synchronizing photon mouse cursor position and SDL mouse position, if cursor appears over window. */ 205 PtGetAbsPosition(window, &abs_x, &abs_y); 206 PhQueryCursor(PhInputGroup(NULL), &phcursor); 207 if (((phcursor.pos.x >= abs_x) && (phcursor.pos.x <= abs_x + this->screen->w)) && 208 ((phcursor.pos.y >= abs_y) && (phcursor.pos.y <= abs_y + this->screen->h))) 209 { 210 SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); 211 SDL_PrivateMouseMotion(0, 0, phcursor.pos.x-abs_x, phcursor.pos.y-abs_y); 212 } 213 else 214 { 215 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); 216 } 217 218 /* Unlock the event thread, in multi-threading environments */ 219 SDL_Unlock_EventThread(); 220 } 221