History

Pushed v1.16 code

- The mouse system has been rewritten so that we don't need to do mouse capturing while interacting with GUI widgets, which could be buggy sometimes. - The different Disk Op. item paths (mod./instr./smp./pat./trk.) now behave exactly like real FT2. I.e. if they haven't been initialized before, they will be set to the current working directory. - Scrollbar thumbs are now limited to minimum 9 pixels in length/height, to prevent them from being difficult to click on.

Olav Sørensen committed 6 years ago

Commit 2247f4c1 parent 108c33316 files · +458 −256Browse files

Showing the changes to src (16 of 16 files). Show all

Unified · Split

16 files
  1. src/ft2_diskop.c +131 −27
  2. src/ft2_diskop.h +1 −1
  3. src/ft2_events.c +16 −7
  4. src/ft2_header.h +1 −1
  5. src/ft2_inst_ed.c +1 −1
  6. src/ft2_module_loader.c +14 −18
  7. src/ft2_mouse.c +129 −111
  8. src/ft2_mouse.h +5 −3
  9. src/ft2_sample_ed.c +2 −2
  10. src/ft2_sample_ed_features.c +0 −5
  11. src/ft2_scrollbars.c +91 −33
  12. src/ft2_scrollbars.h +1 −1
  13. src/ft2_sysreqs.c +0 −10
  14. src/ft2_textboxes.c +2 −1
  15. src/ft2_video.c +59 −30
  16. src/ft2_video.h +5 −5
src/ft2_diskop.c+131−27
@@ -75,7 +75,7 @@ static char FReq_SysReqText[196], *FReq_FileName, *FReq_NameTemp; · 74 unmodified lines
7575 static char *modTmpFName, *insTmpFName, *smpTmpFName, *patTmpFName, *trkTmpFName;
7676 static char *modTmpFNameUTF8; // for window title
7777 static uint8_t FReq_Item;
78−static bool FReq_ShowAllFiles;
78+static bool FReq_ShowAllFiles, modPathSet, insPathSet, smpPathSet, patPathSet, trkPathSet;
7979 static int32_t FReq_EntrySelected = -1, FReq_FileCount, FReq_DirPos, lastMouseY;
8080 static UNICHAR *FReq_CurPathU, *FReq_ModCurPathU, *FReq_InsCurPathU, *FReq_SmpCurPathU, *FReq_PatCurPathU, *FReq_TrkCurPathU;
8181 static DirRec *FReq_Buffer;
@@ -176,20 +176,70 @@ static void setupInitialPaths(void) · 94 unmodified lines
176176 UNICHAR pathU[PATH_MAX + 2];
177177 #endif
178178
179+ UNICHAR_GETCWD(FReq_ModCurPathU, PATH_MAX);
180+
179181 // the UNICHAR paths are already zeroed out
180182
181183 #ifdef _WIN32
182− if (config.modulesPath[0] != '\0') MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.modulesPath, -1, FReq_ModCurPathU, 80);
183− if (config.instrPath[0] != '\0') MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.instrPath, -1, FReq_InsCurPathU, 80);
184− if (config.samplesPath[0] != '\0') MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.samplesPath, -1, FReq_SmpCurPathU, 80);
185− if (config.patternsPath[0] != '\0') MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.patternsPath, -1, FReq_PatCurPathU, 80);
186− if (config.tracksPath[0] != '\0') MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.tracksPath, -1, FReq_TrkCurPathU, 80);
184+ if (config.modulesPath[0] != '\0')
185+ {
186+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.modulesPath, -1, FReq_ModCurPathU, 80);
187+ modPathSet = true;
188+ }
189+
190+ if (config.instrPath[0] != '\0')
191+ {
192+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.instrPath, -1, FReq_InsCurPathU, 80);
193+ insPathSet = true;
194+ }
195+
196+ if (config.samplesPath[0] != '\0')
197+ {
198+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.samplesPath, -1, FReq_SmpCurPathU, 80);
199+ smpPathSet = true;
200+ }
201+
202+ if (config.patternsPath[0] != '\0')
203+ {
204+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.patternsPath, -1, FReq_PatCurPathU, 80);
205+ patPathSet = true;
206+ }
207+
208+ if (config.tracksPath[0] != '\0')
209+ {
210+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.tracksPath, -1, FReq_TrkCurPathU, 80);
211+ trkPathSet = true;
212+ }
187213 #else
188− if (config.modulesPath[0] != '\0') strncpy(FReq_ModCurPathU, config.modulesPath, 80);
189− if (config.instrPath[0] != '\0') strncpy(FReq_InsCurPathU, config.instrPath, 80);
190− if (config.samplesPath[0] != '\0') strncpy(FReq_SmpCurPathU, config.samplesPath, 80);
191− if (config.patternsPath[0] != '\0') strncpy(FReq_PatCurPathU, config.patternsPath, 80);
192− if (config.tracksPath[0] != '\0') strncpy(FReq_TrkCurPathU, config.tracksPath, 80);
214+ if (config.modulesPath[0] != '\0')
215+ {
216+ strncpy(FReq_ModCurPathU, config.modulesPath, 80);
217+ modPathSet = true;
218+ }
219+
220+ if (config.instrPath[0] != '\0')
221+ {
222+ strncpy(FReq_InsCurPathU, config.instrPath, 80);
223+ insPathSet = true;
224+ }
225+
226+ if (config.samplesPath[0] != '\0')
227+ {
228+ strncpy(FReq_SmpCurPathU, config.samplesPath, 80);
229+ smpPathSet = true;
230+ }
231+
232+ if (config.patternsPath[0] != '\0')
233+ {
234+ strncpy(FReq_PatCurPathU, config.patternsPath, 80);
235+ patPathSet = true;
236+ }
237+
238+ if (config.tracksPath[0] != '\0')
239+ {
240+ strncpy(FReq_TrkCurPathU, config.tracksPath, 80);
241+ trkPathSet = true;
242+ }
193243 #endif
194244
195245 // set initial path to user directory
@@ -200,16 +250,12 @@ static void setupInitialPaths(void) · 4 unmodified lines
200250 UNICHAR_CHDIR(getenv("HOME"));
201251 #endif
202252
203− // if present in config, set custom "modules" path
204− if (UNICHAR_CHDIR(FReq_ModCurPathU) != 0)
253+ // if we couldn't set present in config, set custom "modules" path
254+ if (modPathSet && UNICHAR_CHDIR(FReq_ModCurPathU) != 0)
255+ {
205256 UNICHAR_GETCWD(FReq_ModCurPathU, PATH_MAX);
206−
207− if (UNICHAR_CHDIR(FReq_InsCurPathU) != 0) UNICHAR_STRCPY(FReq_InsCurPathU, FReq_ModCurPathU);
208− if (UNICHAR_CHDIR(FReq_SmpCurPathU) != 0) UNICHAR_STRCPY(FReq_SmpCurPathU, FReq_ModCurPathU);
209− if (UNICHAR_CHDIR(FReq_PatCurPathU) != 0) UNICHAR_STRCPY(FReq_PatCurPathU, FReq_ModCurPathU);
210− if (UNICHAR_CHDIR(FReq_TrkCurPathU) != 0) UNICHAR_STRCPY(FReq_TrkCurPathU, FReq_ModCurPathU);
211−
212− UNICHAR_CHDIR(FReq_ModCurPathU); // set back after testing
257+ modPathSet = true;
258+ }
213259 }
214260
215261 static void freeDirRecBuffer(void)
@@ -1969,7 +2015,7 @@ static int32_t SDLCALL diskOp_ReadDirectoryThread(void *ptr) · 1753 unmodified lines
19692015 return true;
19702016 }
19712017
1972−void startDiskOpFillThread(void)
2018+void diskOp_StartDirReadThread(void)
19732019 {
19742020 editor.diskOpReadDone = false;
19752021
@@ -2076,11 +2122,69 @@ static void setDiskOpItem(uint8_t item) · 100 unmodified lines
20762122 FReq_Item = item;
20772123 switch (FReq_Item)
20782124 {
2079− default: case DISKOP_ITEM_MODULE: FReq_FileName = modTmpFName; FReq_CurPathU = FReq_ModCurPathU; break;
2080− case DISKOP_ITEM_INSTR: FReq_FileName = insTmpFName; FReq_CurPathU = FReq_InsCurPathU; break;
2081− case DISKOP_ITEM_SAMPLE: FReq_FileName = smpTmpFName; FReq_CurPathU = FReq_SmpCurPathU; break;
2082− case DISKOP_ITEM_PATTERN: FReq_FileName = patTmpFName; FReq_CurPathU = FReq_PatCurPathU; break;
2083− case DISKOP_ITEM_TRACK: FReq_FileName = trkTmpFName; FReq_CurPathU = FReq_TrkCurPathU; break;
2125+ default:
2126+ case DISKOP_ITEM_MODULE:
2127+ {
2128+ FReq_FileName = modTmpFName;
2129+ FReq_CurPathU = FReq_ModCurPathU;
2130+ }
2131+ break;
2132+
2133+ case DISKOP_ITEM_INSTR:
2134+ {
2135+ FReq_FileName = insTmpFName;
2136+
2137+ if (!insPathSet)
2138+ {
2139+ UNICHAR_STRCPY(FReq_InsCurPathU, FReq_CurPathU);
2140+ insPathSet = true;
2141+ }
2142+
2143+ FReq_CurPathU = FReq_InsCurPathU;
2144+ }
2145+ break;
2146+
2147+ case DISKOP_ITEM_SAMPLE:
2148+ {
2149+ FReq_FileName = smpTmpFName;
2150+
2151+ if (!smpPathSet)
2152+ {
2153+ UNICHAR_STRCPY(FReq_SmpCurPathU, FReq_CurPathU);
2154+ smpPathSet = true;
2155+ }
2156+
2157+ FReq_CurPathU = FReq_SmpCurPathU;
2158+ }
2159+ break;
2160+
2161+ case DISKOP_ITEM_PATTERN:
2162+ {
2163+ FReq_FileName = patTmpFName;
2164+
2165+ if (!patPathSet)
2166+ {
2167+ UNICHAR_STRCPY(FReq_SmpCurPathU, FReq_CurPathU);
2168+ patPathSet = true;
2169+ }
2170+
2171+ FReq_CurPathU = FReq_PatCurPathU;
2172+ }
2173+ break;
2174+
2175+ case DISKOP_ITEM_TRACK:
2176+ {
2177+ FReq_FileName = trkTmpFName;
2178+
2179+ if (!trkPathSet)
2180+ {
2181+ UNICHAR_STRCPY(FReq_TrkCurPathU, FReq_CurPathU);
2182+ trkPathSet = true;
2183+ }
2184+
2185+ FReq_CurPathU = FReq_TrkCurPathU;
2186+ }
2187+ break;
20842188 }
20852189
20862190 pathLen = (int32_t)UNICHAR_STRLEN(FReq_CurPathU);
@@ -2189,7 +2293,7 @@ void showDiskOpScreen(void) · 102 unmodified lines
21892293 if (editor.diskOpReadOnOpen)
21902294 {
21912295 editor.diskOpReadOnOpen = false;
2192− startDiskOpFillThread();
2296+ diskOp_StartDirReadThread();
21932297 }
21942298 }
21952299
src/ft2_diskop.h+1−1
@@ -40,7 +40,7 @@ void pbDiskOpRoot(void); · 39 unmodified lines
4040 int32_t getExtOffset(char *s, int32_t stringLen); // get byte offset of file extension (last '.')
4141 bool testDiskOpMouseDown(bool mouseHeldDown);
4242 void testDiskOpMouseRelease(void);
43−void startDiskOpFillThread(void);
43+void diskOp_StartDirReadThread(void);
4444 void diskOp_DrawDirectory(void);
4545 void showDiskOpScreen(void);
4646 void hideDiskOpScreen(void);
src/ft2_events.c+16−7
@@ -152,7 +152,7 @@ void handleEvents(void) · 151 unmodified lines
152152 if (editor.diskOpReadDir)
153153 {
154154 editor.diskOpReadDir = false;
155− startDiskOpFillThread();
155+ diskOp_StartDirReadThread();
156156 }
157157
158158 if (editor.diskOpReadDone)
@@ -407,14 +407,23 @@ static void handleInput(void) · 248 unmodified lines
407407
408408 while (SDL_PollEvent(&event))
409409 {
410− if (video.vsync60HzPresent)
410+ if (event.type == SDL_WINDOWEVENT)
411411 {
412− /* if we minimize the window and vsync is present, vsync is temporarily turned off.
413− ** recalc waitVBL() vars so that it can sleep properly in said mode. */
414− if (event.type == SDL_WINDOWEVENT &&
415− (event.window.event == SDL_WINDOWEVENT_MINIMIZED || event.window.event == SDL_WINDOWEVENT_FOCUS_LOST))
412+ if (event.window.event == SDL_WINDOWEVENT_HIDDEN)
413+ video.windowHidden = true;
414+ else if (event.window.event == SDL_WINDOWEVENT_SHOWN)
415+ video.windowHidden = false;
416+
417+ if (video.vsync60HzPresent)
416418 {
417− setupWaitVBL();
419+ /* if we minimize the window and vsync is present, vsync is temporarily turned off.
420+ ** recalc waitVBL() vars so that it can sleep properly in said mode.
421+ */
422+ if (event.window.event == SDL_WINDOWEVENT_MINIMIZED ||
423+ event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
424+ {
425+ setupWaitVBL();
426+ }
418427 }
419428 }
420429
src/ft2_header.h+1−1
@@ -12,7 +12,7 @@ · 11 unmodified lines
1212 #endif
1313 #include "ft2_replayer.h"
1414
15−#define PROG_VER_STR "1.15"
15+#define PROG_VER_STR "1.16"
1616
1717 // do NOT change these! It will only mess things up...
1818
src/ft2_inst_ed.c+1−1
@@ -3146,7 +3146,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) · 3145 unmodified lines
31463146 ins->vibDepth = ih.vibDepth;
31473147 ins->vibRate = ih.vibRate;
31483148 ins->fadeOut = ih.fadeOut;
3149− ins->midiOn = (ih.midiOn > 0) ? true : false;
3149+ ins->midiOn = (ih.midiOn == 1) ? true : false;
31503150 ins->midiChannel = ih.midiChannel;
31513151 ins->midiProgram = ih.midiProgram;
31523152 ins->midiBend = ih.midiBend;
src/ft2_module_loader.c+14−18
@@ -622,16 +622,6 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 621 unmodified lines
622622 s = &instrTmp[1+a]->samp[0];
623623
624624 s->len = 2 * SWAP16(h_MOD31.instr[a].len);
625−
626− s->pek = NULL;
627− s->origPek = (int8_t *)malloc(s->len + LOOP_FIX_LEN);
628− if (s->origPek == NULL)
629− {
630− showMsg(0, "System message", "Not enough memory!");
631− goto modLoadError;
632− }
633−
634− s->pek = s->origPek + SMP_DAT_OFFSET;
635625
636626 if (modFormat != FORMAT_HMNT) // most of "His Master's Noisetracker" songs have junk sample names, so let's not load them
637627 memcpy(s->name, songTmp.instrName[1+a], 22);
@@ -655,11 +645,11 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 17 unmodified lines
655645 s->repL = 2;
656646
657647 // in The Ultimate SoundTracker, sample loop start is in bytes, not words
658− if (mightBeSTK)
648+ if (modFormat == FORMAT_STK)
659649 s->repS >>= 1;
660650
661651 // fix for poorly converted STK (< v2.5) -> PT/NT modules (FIXME: Worth keeping or not?)
662− if (!mightBeSTK && s->repL > 2 && s->repS+s->repL > s->len)
652+ if (modFormat != FORMAT_STK && s->repL > 2 && s->repS+s->repL > s->len)
663653 {
664654 if ((s->repS>>1)+s->repL <= s->len)
665655 s->repS >>= 1;
@@ -692,6 +682,16 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 26 unmodified lines
692682 s->repS = 0;
693683 }
694684
685+ s->pek = NULL;
686+ s->origPek = (int8_t *)malloc(s->len + LOOP_FIX_LEN);
687+ if (s->origPek == NULL)
688+ {
689+ showMsg(0, "System message", "Not enough memory!");
690+ goto modLoadError;
691+ }
692+
693+ s->pek = s->origPek + SMP_DAT_OFFSET;
694+
695695 int32_t bytesRead = (int32_t)fread(s->pek, 1, s->len, f);
696696 if (bytesRead < s->len)
697697 {
@@ -737,7 +737,7 @@ static uint8_t stmTempoToBPM(uint8_t tempo) // ported from original ST2.3 replay · 39 unmodified lines
737737 static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread)
738738 {
739739 uint8_t typ, tempo;
740− int16_t i, j, k, ai, ap, tmp;
740+ int16_t i, j, k, ap, tmp;
741741 uint16_t a;
742742 tonTyp *ton;
743743 sampleTyp *s;
@@ -899,7 +899,6 @@ static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread) · 155 unmodified lines
899899 }
900900 }
901901
902− ai = 31;
903902 for (i = 0; i < 31; i++)
904903 {
905904 // trim off spaces at end of name
@@ -1010,7 +1009,6 @@ static int8_t countS3MChannels(uint16_t antPtn) · 104 unmodified lines
10101009 static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread)
10111010 {
10121011 int8_t *tmpSmp;
1013− bool illegalUxx;
10141012 uint8_t ha[2048];
10151013 uint8_t alastnfo[32], alastefx[32], alastvibnfo[32], s3mLastGInstr[32];
10161014 uint8_t typ;
@@ -1129,8 +1127,6 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 112 unmodified lines
11291127
11301128 // *** PATTERNS ***
11311129
1132− illegalUxx = false;
1133−
11341130 k = 0;
11351131 for (i = 0; i < ap; i++)
11361132 {
@@ -2012,7 +2008,7 @@ static bool loadInstrHeader(FILE *f, uint16_t i) · 875 unmodified lines
20122008 ins->vibDepth = ih.vibDepth;
20132009 ins->vibRate = ih.vibRate;
20142010 ins->fadeOut = ih.fadeOut;
2015− ins->midiOn = (ih.midiOn > 0) ? true : false;
2011+ ins->midiOn = (ih.midiOn == 1) ? true : false;
20162012 ins->midiChannel = ih.midiChannel;
20172013 ins->midiProgram = ih.midiProgram;
20182014 ins->midiBend = ih.midiBend;
src/ft2_mouse.c+129−111
@@ -59,16 +59,18 @@ bool createMouseCursors(void) // creates scaled SDL surfaces for current mouse p · 58 unmodified lines
5959 const uint8_t *cursorsSrc = bmp.mouseCursors;
6060 switch (config.mouseType)
6161 {
62− case MOUSE_IDLE_SHAPE_NICE: cursorsSrc += 0 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
63− case MOUSE_IDLE_SHAPE_UGLY: cursorsSrc += 1 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
64− case MOUSE_IDLE_SHAPE_AWFUL: cursorsSrc += 2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
62+ case MOUSE_IDLE_SHAPE_NICE: cursorsSrc += 0 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
63+ case MOUSE_IDLE_SHAPE_UGLY: cursorsSrc += 1 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
64+ case MOUSE_IDLE_SHAPE_AWFUL: cursorsSrc += 2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
6565 case MOUSE_IDLE_SHAPE_USABLE: cursorsSrc += 3 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
6666 default: break;
6767 }
6868
6969 for (uint32_t i = 0; i < NUM_CURSORS; i++)
7070 {
71− SDL_Surface *surface = SDL_CreateRGBSurface(0, MOUSE_CURSOR_W*video.yScale, MOUSE_CURSOR_H*video.yScale, 32, 0, 0, 0, 0);
71+ int32_t scaleFactor = video.yScale;
72+
73+ SDL_Surface *surface = SDL_CreateRGBSurface(0, MOUSE_CURSOR_W*scaleFactor, MOUSE_CURSOR_H*scaleFactor, 32, 0, 0, 0, 0);
7274 if (surface == NULL)
7375 {
7476 freeMouseCursors();
@@ -104,10 +106,10 @@ bool createMouseCursors(void) // creates scaled SDL surfaces for current mouse p · 29 unmodified lines
104106 // blit upscaled cursor to surface
105107 for (uint32_t y = 0; y < MOUSE_CURSOR_H; y++)
106108 {
107− uint32_t *outX = &dstPixels32[(y * video.yScale) * surface->w];
108− for (uint32_t yScale = 0; yScale < video.yScale; yScale++)
109+ uint32_t *outX = &dstPixels32[(y * scaleFactor) * surface->w];
110+ for (int32_t yScale = 0; yScale < scaleFactor; yScale++)
109111 {
110− for (uint32_t x = 0; x < MOUSE_CURSOR_W; x++)
112+ for (int32_t x = 0; x < MOUSE_CURSOR_W; x++)
111113 {
112114 uint8_t srcPix = srcPixels8[(y * MOUSE_CURSOR_W) + x];
113115 if (srcPix != PAL_TRANSPR)
@@ -118,7 +120,7 @@ bool createMouseCursors(void) // creates scaled SDL surfaces for current mouse p · 4 unmodified lines
118120 else if (srcPix == PAL_BCKGRND)
119121 pixel = border;
120122
121− for (uint32_t xScale = 0; xScale < video.yScale; xScale++)
123+ for (int32_t xScale = 0; xScale < scaleFactor; xScale++)
122124 outX[xScale] = pixel;
123125 }
124126
@@ -163,13 +165,13 @@ void setMousePosToCenter(void) · 38 unmodified lines
163165 {
164166 if (video.fullscreen)
165167 {
166− mouse.setPosX = video.displayW / 2;
167− mouse.setPosY = video.displayH / 2;
168+ mouse.setPosX = video.displayW >> 1;
169+ mouse.setPosY = video.displayH >> 1;
168170 }
169171 else
170172 {
171− mouse.setPosX = video.renderW / 2;
172− mouse.setPosY = video.renderH / 2;
173+ mouse.setPosX = video.renderW >> 1;
174+ mouse.setPosY = video.renderH >> 1;
173175 }
174176
175177 mouse.setPosFlag = true;
@@ -242,11 +244,11 @@ void setMouseShape(int16_t shape) · 66 unmodified lines
242244 gfxPtr = &bmp.mouseCursors[mouseModeGfxOffs];
243245 switch (shape)
244246 {
245− case MOUSE_IDLE_SHAPE_NICE: gfxPtr += 0 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
246− case MOUSE_IDLE_SHAPE_UGLY: gfxPtr += 1 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
247− case MOUSE_IDLE_SHAPE_AWFUL: gfxPtr += 2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
248− case MOUSE_IDLE_SHAPE_USABLE: gfxPtr += 3 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
249− case MOUSE_IDLE_TEXT_EDIT: gfxPtr += 12 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
247+ case MOUSE_IDLE_SHAPE_NICE: gfxPtr += 0 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
248+ case MOUSE_IDLE_SHAPE_UGLY: gfxPtr += 1 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
249+ case MOUSE_IDLE_SHAPE_AWFUL: gfxPtr += 2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
250+ case MOUSE_IDLE_SHAPE_USABLE: gfxPtr += 3 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
251+ case MOUSE_IDLE_TEXT_EDIT: gfxPtr += 12 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;
250252 default: return;
251253 }
252254 }
@@ -284,7 +286,7 @@ static void clearTextEditMouse(void) · 31 unmodified lines
284286
285287 static void changeCursorIfOverTextBoxes(void)
286288 {
287− int16_t i, mx, my;
289+ int32_t i, mx, my;
288290 textBox_t *t;
289291
290292 mouse.mouseOverTextBox = false;
@@ -542,11 +544,6 @@ static bool testPatternDataMouseDown(void) · 251 unmodified lines
542544
543545 void mouseButtonUpHandler(uint8_t mouseButton)
544546 {
545−#ifndef __APPLE__
546− if (!video.fullscreen) // release mouse button trap
547− SDL_SetWindowGrab(video.window, SDL_FALSE);
548−#endif
549−
550547 if (mouseButton == SDL_BUTTON_LEFT)
551548 {
552549 mouse.leftButtonPressed = false;
@@ -569,7 +566,6 @@ void mouseButtonUpHandler(uint8_t mouseButton) · 16 unmodified lines
569566 mouse.rightButtonPressed = false;
570567 mouse.rightButtonReleased = true;
571568
572−
573569 if (editor.editSampleFlag)
574570 {
575571 // right mouse button released after hand-editing sample data
@@ -582,9 +578,9 @@ void mouseButtonUpHandler(uint8_t mouseButton) · 6 unmodified lines
582578 writeSample(true);
583579
584580 setSongModifiedFlag();
581+
585582 editor.editSampleFlag = false;
586583 }
587−
588584 }
589585
590586 mouse.firstTimePressingButton = false;
@@ -611,9 +607,9 @@ void mouseButtonUpHandler(uint8_t mouseButton) · 20 unmodified lines
611607 testRadioButtonMouseRelease();
612608
613609 // revert "delete/rename" mouse modes (disk op.)
614− if (mouse.lastUsedObjectID != PB_DISKOP_DELETE && mouse.lastUsedObjectID != PB_DISKOP_RENAME)
610+ if (mouse.mode != MOUSE_MODE_NORMAL)
615611 {
616− if (mouse.mode != MOUSE_MODE_NORMAL)
612+ if (mouse.lastUsedObjectID != PB_DISKOP_DELETE && mouse.lastUsedObjectID != PB_DISKOP_RENAME)
617613 setMouseMode(MOUSE_MODE_NORMAL);
618614 }
619615
@@ -623,11 +619,6 @@ void mouseButtonUpHandler(uint8_t mouseButton) · 3 unmodified lines
623619
624620 void mouseButtonDownHandler(uint8_t mouseButton)
625621 {
626−#ifndef __APPLE__
627− if (!video.fullscreen) // trap mouse pointer while holding down left and/or right button
628− SDL_SetWindowGrab(video.window, SDL_TRUE);
629−#endif
630−
631622 // if already holding left button and clicking right, don't do mouse down handling
632623 if (mouseButton == SDL_BUTTON_RIGHT && mouse.leftButtonPressed)
633624 {
@@ -691,34 +682,35 @@ void mouseButtonDownHandler(uint8_t mouseButton) · 57 unmodified lines
691682 if (mouse.lastUsedObjectType != OBJECT_PUSHBUTTON && mouse.lastUsedObjectID != OBJECT_ID_NONE)
692683 return;
693684
694− // kludge #3
685+ // kludge #3 :(
695686 if (!mouse.rightButtonPressed)
696687 mouse.lastUsedObjectID = OBJECT_ID_NONE;
697688
698689 // check if we pressed a GUI object
699690
700691 /* test objects like this - clickable things *never* overlap, so no need to test all
701− ** other objects if we clicked on one already */
692+ ** other objects if we clicked on one already
693+ */
702694
703695 testInstrSwitcherMouseDown(); // kludge: allow right click to both change ins. and edit text
704696
705− if (testTextBoxMouseDown()) return;
706− if (testPushButtonMouseDown()) return;
707− if (testCheckBoxMouseDown()) return;
708− if (testScrollBarMouseDown()) return;
697+ if (testTextBoxMouseDown()) return;
698+ if (testPushButtonMouseDown()) return;
699+ if (testCheckBoxMouseDown()) return;
700+ if (testScrollBarMouseDown()) return;
709701 if (testRadioButtonMouseDown()) return;
710702
711− // from this point, we don't need to test more widgets if a system request box is shown
703+ // at this point, we don't need to test more widgets if a system request is shown
712704 if (editor.ui.sysReqShown)
713705 return;
714706
715707 if (testInstrVolEnvMouseDown(false)) return;
716708 if (testInstrPanEnvMouseDown(false)) return;
717− if (testDiskOpMouseDown(false)) return;
718− if (testPianoKeysMouseDown(false)) return;
719− if (testSamplerDataMouseDown()) return;
720− if (testPatternDataMouseDown()) return;
721− if (testScopesMouseDown()) return;
709+ if (testDiskOpMouseDown(false)) return;
710+ if (testPianoKeysMouseDown(false)) return;
711+ if (testSamplerDataMouseDown()) return;
712+ if (testPatternDataMouseDown()) return;
713+ if (testScopesMouseDown()) return;
722714 if (testAudioDeviceListsMouseDown()) return;
723715
724716 #ifdef HAS_MIDI
@@ -737,11 +729,11 @@ void handleLastGUIObjectDown(void) · 12 unmodified lines
737729 {
738730 switch (mouse.lastUsedObjectType)
739731 {
740− case OBJECT_PUSHBUTTON: handlePushButtonsWhileMouseDown(); break;
732+ case OBJECT_PUSHBUTTON: handlePushButtonsWhileMouseDown(); break;
741733 case OBJECT_RADIOBUTTON: handleRadioButtonsWhileMouseDown(); break;
742− case OBJECT_CHECKBOX: handleCheckBoxesWhileMouseDown(); break;
743− case OBJECT_SCROLLBAR: handleScrollBarsWhileMouseDown(); break;
744− case OBJECT_TEXTBOX: handleTextBoxWhileMouseDown(); break;
734+ case OBJECT_CHECKBOX: handleCheckBoxesWhileMouseDown(); break;
735+ case OBJECT_SCROLLBAR: handleScrollBarsWhileMouseDown(); break;
736+ case OBJECT_TEXTBOX: handleTextBoxWhileMouseDown(); break;
745737 default: break;
746738 }
747739 }
@@ -750,16 +742,28 @@ void handleLastGUIObjectDown(void) · 2 unmodified lines
750742 // test non-standard GUI elements
751743 switch (mouse.lastUsedObjectType)
752744 {
753− case OBJECT_INSTRSWITCH: testInstrSwitcherMouseDown(); break;
754− case OBJECT_PATTERNMARK: handlePatternDataMouseDown(true); break;
755− case OBJECT_DISKOPLIST: testDiskOpMouseDown(true); break;
756− case OBJECT_SMPDATA: handleSampleDataMouseDown(true); break;
757− case OBJECT_PIANO: testPianoKeysMouseDown(true); break;
758− case OBJECT_INSVOLENV: testInstrVolEnvMouseDown(true); break;
759− case OBJECT_INSPANENV: testInstrPanEnvMouseDown(true); break;
745+ case OBJECT_INSTRSWITCH: testInstrSwitcherMouseDown(); break;
746+ case OBJECT_PATTERNMARK: handlePatternDataMouseDown(true); break;
747+ case OBJECT_DISKOPLIST: testDiskOpMouseDown(true); break;
748+ case OBJECT_SMPDATA: handleSampleDataMouseDown(true); break;
749+ case OBJECT_PIANO: testPianoKeysMouseDown(true); break;
750+ case OBJECT_INSVOLENV: testInstrVolEnvMouseDown(true); break;
751+ case OBJECT_INSPANENV: testInstrPanEnvMouseDown(true); break;
760752 default: break;
761753 }
762754 }
755+
756+ /* Hack to send "mouse button up" events if we released the mouse button(s)
757+ ** outside of the window...
758+ */
759+ if (mouse.x < 0 || mouse.x >= SCREEN_W || mouse.y < 0 || mouse.y >= SCREEN_H)
760+ {
761+ if (mouse.leftButtonPressed && !(mouse.buttonState & SDL_BUTTON_LMASK))
762+ sendMouseButtonUpEvent(SDL_BUTTON_LEFT);
763+
764+ if (mouse.rightButtonPressed && !(mouse.buttonState & SDL_BUTTON_RMASK))
765+ sendMouseButtonUpEvent(SDL_BUTTON_RIGHT);
766+ }
763767 }
764768 }
765769
@@ -769,88 +773,102 @@ void updateMouseScaling(void) · 3 unmodified lines
769773 if (video.renderH > 0.0) video.dMouseYMul = (double)SCREEN_H / video.renderH;
770774 }
771775
776+void sendMouseButtonUpEvent(uint8_t button)
777+{
778+ SDL_Event event;
779+
780+ memset(&event, 0, sizeof (event));
781+
782+ event.type = SDL_MOUSEBUTTONUP;
783+ event.button.button = button;
784+
785+ SDL_PushEvent(&event);
786+}
787+
772788 void readMouseXY(void)
773789 {
774− int16_t x, y;
775− int32_t mx, my;
790+ int32_t mx, my, windowX, windowY;
776791
777792 if (mouse.setPosFlag)
778793 {
779− mouse.setPosFlag = false;
780−
781− if (SDL_GetWindowFlags(video.window) & SDL_WINDOW_SHOWN)
794+ if (!video.windowHidden)
782795 SDL_WarpMouseInWindow(video.window, mouse.setPosX, mouse.setPosY);
783796
797+ mouse.setPosFlag = false;
784798 return;
785799 }
786800
787− SDL_PumpEvents(); // gathers all pending input from devices into the event queue (less mouse lag)
788− SDL_GetMouseState(&mx, &my);
801+ mouse.buttonState = SDL_GetGlobalMouseState(&mx, &my);
789802
790− /* in centered fullscreen mode, trap the mouse inside the framed image
791− ** and subtract the coords to match the OS mouse position (fixes touch from touchscreens) */
792− if (video.fullscreen && !(config.windowFlags & FILTERING))
803+ if (video.fullscreen)
793804 {
794− if (mx < video.renderX)
795− {
796− mx = video.renderX;
797− SDL_WarpMouseInWindow(video.window, mx, my);
798− }
799− else if (mx >= video.renderX+video.renderW)
800− {
801− mx = (video.renderX + video.renderW) - 1;
802− SDL_WarpMouseInWindow(video.window, mx, my);
803− }
805+ /* If fullscreen without filtering mode, translate coords and warp mouse
806+ ** inside the render space.
807+ ** Fullscreen + filtering mode takes up 100% of the screen area used, so no
808+ ** need to translate coords in that mode.
809+ */
804810
805− if (my < video.renderY)
811+ if (!(config.windowFlags & FILTERING))
806812 {
807− my = video.renderY;
808− SDL_WarpMouseInWindow(video.window, mx, my);
809− }
810− else if (my >= video.renderY+video.renderH)
811− {
812− my = (video.renderY + video.renderH) - 1;
813− SDL_WarpMouseInWindow(video.window, mx, my);
814− }
813+ if (!(config.specialFlags2 & HARDWARE_MOUSE))
814+ {
815+ bool warpMouse = false;
816+
817+ if (mx < video.renderX)
818+ {
819+ mx = video.renderX;
820+ warpMouse = true;
821+ }
822+ else if (mx >= video.renderX+video.renderW)
823+ {
824+ mx = (video.renderX + video.renderW) - 1;
825+ warpMouse = true;
826+ }
827+
828+ if (my < video.renderY)
829+ {
830+ my = video.renderY;
831+ warpMouse = true;
832+ }
833+ else if (my >= video.renderY+video.renderH)
834+ {
835+ my = (video.renderY + video.renderH) - 1;
836+ warpMouse = true;
837+ }
815838
816− mx -= video.renderX;
817− my -= video.renderY;
839+ if (warpMouse)
840+ SDL_WarpMouseInWindow(video.window, mx, my);
841+ }
842+
843+ // convert fullscreen coords to window (centered image) coords
844+ mx -= video.renderX;
845+ my -= video.renderY;
846+ }
818847 }
848+ else
849+ {
850+ // convert desktop coords to window coords
819851
820− if (mx < 0) mx = 0;
821− if (my < 0) mx = 0;
852+ // (a call to this function is really fast in windowed mode)
853+ SDL_GetWindowPosition(video.window, &windowX, &windowY);
822854
823− // multiply coords by video upscaling factors (don't round)
824− mx = (int32_t)(mx * video.dMouseXMul);
825− my = (int32_t)(my * video.dMouseYMul);
855+ mx -= windowX;
856+ my -= windowY;
857+ }
826858
827− if (mx >= SCREEN_W) mx = SCREEN_W - 1;
828− if (my >= SCREEN_H) my = SCREEN_H - 1;
859+ // multiply coords by video upscaling factors (don't round)
860+ mouse.x = (int32_t)(mx * video.dMouseXMul);
861+ mouse.y = (int32_t)(my * video.dMouseYMul);
829862
830863 if (config.specialFlags2 & HARDWARE_MOUSE)
831864 {
832− // hardware mouse (OS)
833− mouse.x = (int16_t)mx;
834− mouse.y = (int16_t)my;
865+ // hardware mouse mode (OS)
835866 hideSprite(SPRITE_MOUSE_POINTER);
836867 }
837868 else
838869 {
839− // software mouse (FT2 mouse)
840− x = (int16_t)mx;
841− y = (int16_t)my;
842−
843− mouse.x = x;
844− mouse.y = y;
845−
846− // for text editing cursor (do this after clamp)
847− x += mouse.xBias;
848− y += mouse.yBias;
849−
850− if (x < 0) x = 0;
851− if (y < 0) y = 0;
852−
853− setSpritePos(SPRITE_MOUSE_POINTER, x, y);
870+ // software mouse mode (FT2 mouse)
871+ setSpritePos(SPRITE_MOUSE_POINTER, mouse.x + mouse.xBias, mouse.y + mouse.yBias);
854872 }
855873
856874 changeCursorIfOverTextBoxes();
src/ft2_mouse.h+5−3
@@ -19,9 +19,10 @@ struct mouse_t · 18 unmodified lines
1919 bool leftButtonPressed, rightButtonPressed, leftButtonReleased, rightButtonReleased;
2020 bool firstTimePressingButton, mouseOverTextBox;
2121 int8_t buttonCounter, mode;
22− int16_t lastUsedObjectID, lastUsedObjectType, lastEditBox, x, y, lastX, lastY, xBias, yBias;
23− int16_t lastScrollX, lastScrollXTmp, lastScrollY, saveMouseX, saveMouseY;
24− int32_t setPosX, setPosY;
22+ int16_t lastUsedObjectID, lastUsedObjectType, lastEditBox;
23+ int32_t x, y, lastX, lastY, xBias, yBias, setPosX, setPosY;
24+ int32_t lastScrollX, lastScrollXTmp, lastScrollY, saveMouseX, saveMouseY;
25+ uint32_t buttonState;
2526 } mouse;
2627
2728 // do not change these!
@@ -30,6 +31,7 @@ struct mouse_t · 2 unmodified lines
3031 #define MOUSE_GLASS_ANI_FRAMES 22
3132 #define MOUSE_CLOCK_ANI_FRAMES 5
3233
34+void sendMouseButtonUpEvent(uint8_t button);
3335 void freeMouseCursors(void);
3436 bool createMouseCursors(void);
3537 void setMousePosToCenter(void);
src/ft2_sample_ed.c+2−2
@@ -1440,7 +1440,7 @@ void rangeAll(void) · 1439 unmodified lines
14401440 smpEd_Rx2 = smpEd_ScrPos + smpEd_ViewSize;
14411441 }
14421442
1443−static void zoomSampleDataIn(int32_t step, int16_t x)
1443+static void zoomSampleDataIn(int32_t step, int32_t x)
14441444 {
14451445 int32_t tmp32, minViewSize;
14461446 int64_t newScrPos64;
@@ -1482,7 +1482,7 @@ static void zoomSampleDataIn(int32_t step, int16_t x) · 35 unmodified lines
14821482 updateScrPos();
14831483 }
14841484
1485−static void zoomSampleDataOut(int32_t step, int16_t x)
1485+static void zoomSampleDataOut(int32_t step, int32_t x)
14861486 {
14871487 int32_t tmp32;
14881488 int64_t newViewSize64;
src/ft2_sample_ed_features.c+0−5
@@ -43,11 +43,6 @@ static void windowOpen(void) · 42 unmodified lines
4343 editor.ui.sysReqShown = true;
4444 editor.ui.sysReqEnterPressed = false;
4545
46−#ifndef __APPLE__
47− if (!video.fullscreen) // release mouse button trap
48− SDL_SetWindowGrab(video.window, SDL_FALSE);
49−#endif
50−
5146 unstuckLastUsedGUIElement();
5247 SDL_EventState(SDL_DROPFILE, SDL_DISABLE);
5348 }
src/ft2_scrollbars.c+91−33
@@ -20,6 +20,12 @@ · 19 unmodified lines
2020 #include "ft2_video.h"
2121 #include "ft2_palette.h"
2222
23+/* Prevent the scrollbar thumbs from being so small that
24+** it's difficult to use them. In units of pixels.
25+** Shouldn't be higher than 9!
26+*/
27+#define MIN_THUMB_LENGTH 9
28+
2329 scrollBar_t scrollBars[NUM_SCROLLBARS] =
2430 {
2531 // ------ RESERVED SCROLLBARS ------
@@ -168,7 +174,9 @@ void hideScrollBar(uint16_t scrollBarID) · 142 unmodified lines
168174
169175 static void setScrollBarThumbCoords(uint16_t scrollBarID)
170176 {
171− int16_t tmp16, thumbX, thumbY, thumbW, thumbH, scrollEnd;
177+ int16_t thumbX, thumbY, thumbW, thumbH, scrollEnd, realThumbLength;
178+ int32_t tmp32, length, end;
179+ double dTmp;
172180 scrollBar_t *scrollBar;
173181
174182 assert(scrollBarID < NUM_SCROLLBARS);
@@ -196,11 +204,18 @@ static void setScrollBarThumbCoords(uint16_t scrollBarID) · 21 unmodified lines
196204
197205 if (scrollBar->thumbType == SCROLLBAR_THUMB_NOFLAT)
198206 {
199− thumbW = 15;
207+ realThumbLength = 15;
208+
209+ thumbW = realThumbLength;
210+ if (thumbW < MIN_THUMB_LENGTH)
211+ thumbW = MIN_THUMB_LENGTH;
212+
200213 if (scrollBar->end > 0)
201214 {
202− tmp16 = (int16_t)round(((scrollBar->w - thumbW) / (double)scrollBar->end) * scrollBar->pos);
203− thumbX = scrollBar->x + tmp16;
215+ length = scrollBar->w - realThumbLength;
216+ dTmp = (length / (double)scrollBar->end) * scrollBar->pos;
217+ tmp32 = (int32_t)(dTmp + 0.5);
218+ thumbX = (int16_t)(scrollBar->x + tmp32);
204219 }
205220 else
206221 {
@@ -211,18 +226,27 @@ static void setScrollBarThumbCoords(uint16_t scrollBarID) · 4 unmodified lines
211226 {
212227 if (scrollBar->end > 0)
213228 {
214− tmp16 = (int16_t)round((scrollBar->w / (double)scrollBar->end) * scrollBar->page);
215− thumbW = CLAMP(tmp16, 1, scrollBar->w);
229+ dTmp = (scrollBar->w / (double)scrollBar->end) * scrollBar->page;
230+ tmp32 = (int32_t)(dTmp + 0.5);
231+ realThumbLength = (int16_t)CLAMP(tmp32, 1, scrollBar->w);
216232 }
217233 else
218234 {
219− thumbW = 1;
235+ realThumbLength = 1;
220236 }
221237
238+ thumbW = realThumbLength;
239+ if (thumbW < MIN_THUMB_LENGTH)
240+ thumbW = MIN_THUMB_LENGTH;
241+
222242 if (scrollBar->end > scrollBar->page)
223243 {
224− tmp16 = (int16_t)round(((scrollBar->w - thumbW) / (double)(scrollBar->end - scrollBar->page)) * scrollBar->pos);
225− thumbX = scrollBar->x + tmp16;
244+ length = scrollBar->w - thumbW;
245+ end = scrollBar->end - scrollBar->page;
246+
247+ dTmp = (length / (double)end) * scrollBar->pos;
248+ tmp32 = (int32_t)(dTmp + 0.5);
249+ thumbX = (int16_t)(scrollBar->x + tmp32);
226250 }
227251 else
228252 {
@@ -231,7 +255,7 @@ static void setScrollBarThumbCoords(uint16_t scrollBarID) · 2 unmodified lines
231255 }
232256
233257 // prevent scrollbar thumb coords from being outside of the scrollbar area
234− thumbX = CLAMP(thumbX, scrollBar->x, scrollEnd - 1);
258+ thumbX = CLAMP(thumbX, scrollBar->x, scrollEnd-1);
235259 if (thumbX+thumbW > scrollEnd)
236260 thumbW = scrollEnd - thumbX;
237261 }
@@ -245,18 +269,27 @@ static void setScrollBarThumbCoords(uint16_t scrollBarID) · 7 unmodified lines
245269
246270 if (scrollBar->end > 0)
247271 {
248− tmp16 = (int16_t)round((scrollBar->h / (double)scrollBar->end) * scrollBar->page);
249− thumbH = CLAMP(tmp16, 1, scrollBar->h);
272+ dTmp = (scrollBar->h / (double)scrollBar->end) * scrollBar->page;
273+ tmp32 = (int32_t)(dTmp + 0.5);
274+ realThumbLength = (int16_t)CLAMP(tmp32, MIN_THUMB_LENGTH, scrollBar->h);
250275 }
251276 else
252277 {
253− thumbH = 1;
278+ realThumbLength = 1;
254279 }
255280
281+ thumbH = realThumbLength;
282+ if (thumbW < MIN_THUMB_LENGTH)
283+ thumbW = MIN_THUMB_LENGTH;
284+
256285 if (scrollBar->end > scrollBar->page)
257286 {
258− tmp16 = (int16_t)round(((scrollBar->h - thumbH) / (double)(scrollBar->end - scrollBar->page)) * scrollBar->pos);
259− thumbY = scrollBar->y + tmp16;
287+ length = scrollBar->h - thumbH;
288+ end = scrollBar->end - scrollBar->page;
289+
290+ dTmp = (length / (double)end) * scrollBar->pos;
291+ tmp32 = (int32_t)(dTmp + 0.5);
292+ thumbY = (int16_t)(scrollBar->y + tmp32);
260293 }
261294 else
262295 {
@@ -270,6 +303,7 @@ static void setScrollBarThumbCoords(uint16_t scrollBarID) · 7 unmodified lines
270303 }
271304
272305 // set values now
306+ scrollBar->realThumbLength = realThumbLength;
273307 scrollBar->thumbX = thumbX;
274308 scrollBar->thumbY = thumbY;
275309 scrollBar->thumbW = thumbW;
@@ -463,7 +497,7 @@ void setScrollBarPageLength(uint16_t scrollBarID, uint32_t pageLength) · 187 unmodified lines
463497 bool testScrollBarMouseDown(void)
464498 {
465499 uint16_t start, end;
466− int32_t scrollPos;
500+ int32_t scrollPos, length;
467501 double dTmp;
468502 scrollBar_t *scrollBar;
469503
@@ -506,18 +540,26 @@ bool testScrollBarMouseDown(void) · 36 unmodified lines
506540 }
507541 else
508542 {
509− mouse.saveMouseX = (int16_t)round(scrollBar->thumbW / 2.0);
543+ mouse.saveMouseX = scrollBar->thumbW >> 1;
510544
511545 scrollPos = mouse.lastScrollX - scrollBar->x - mouse.saveMouseX;
512546 if (scrollBar->thumbType == SCROLLBAR_THUMB_NOFLAT)
513− scrollPos = (int32_t)round(scrollPos * (scrollBar->w / (double)(scrollBar->w - 15)));
547+ {
548+ dTmp = scrollPos * (scrollBar->w / (double)(scrollBar->w - scrollBar->thumbW));
549+ scrollPos = (int32_t)(dTmp + 0.5);
550+ }
514551
552+ assert(scrollBar->w > 0);
515553 scrollPos = CLAMP(scrollPos, 0, scrollBar->w);
516554
517− assert(scrollBar->w > 0);
555+ length = scrollBar->w + (scrollBar->realThumbLength - scrollBar->thumbW);
556+ if (length < 1)
557+ length = 1;
518558
519− dTmp = round(((double)scrollPos * scrollBar->end) / scrollBar->w);
520− setScrollBarPos(mouse.lastUsedObjectID, (int32_t)dTmp, true);
559+ dTmp = ((double)scrollPos * scrollBar->end) / length;
560+ scrollPos = (int32_t)(dTmp + 0.5);
561+
562+ setScrollBarPos(mouse.lastUsedObjectID, scrollPos, true);
521563 }
522564 }
523565 else
@@ -529,15 +571,21 @@ bool testScrollBarMouseDown(void) · 5 unmodified lines
529571 }
530572 else
531573 {
532− mouse.saveMouseY = (int16_t)(scrollBar->thumbH / 2.0); // truncate here
574+ mouse.saveMouseY = scrollBar->thumbH >> 1;
533575
534576 scrollPos = mouse.lastScrollY - scrollBar->y - mouse.saveMouseY;
535− scrollPos = CLAMP(scrollPos, 0, scrollBar->h);
536577
537578 assert(scrollBar->h > 0);
579+ scrollPos = CLAMP(scrollPos, 0, scrollBar->h);
580+
581+ length = scrollBar->h + (scrollBar->realThumbLength - scrollBar->thumbW);
582+ if (length < 1)
583+ length = 1;
584+
585+ dTmp = ((double)scrollPos * scrollBar->end) / length;
586+ scrollPos = (int32_t)(dTmp + 0.5);
538587
539− dTmp = round(((double)scrollPos * scrollBar->end) / scrollBar->h);
540− setScrollBarPos(mouse.lastUsedObjectID, (int32_t)dTmp, true);
588+ setScrollBarPos(mouse.lastUsedObjectID, scrollPos, true);
541589 }
542590 }
543591
@@ -575,7 +623,7 @@ void testScrollBarMouseRelease(void) · 31 unmodified lines
575623
576624 void handleScrollBarsWhileMouseDown(void)
577625 {
578− int16_t scrollX, scrollY;
626+ int32_t scrollX, scrollY, length;
579627 double dTmp;
580628 scrollBar_t *scrollBar;
581629
@@ -594,15 +642,21 @@ void handleScrollBarsWhileMouseDown(void) · 12 unmodified lines
594642 if (scrollBar->thumbType == SCROLLBAR_THUMB_NOFLAT)
595643 {
596644 assert(scrollBar->w >= 16);
597− scrollX = (int16_t)round(scrollX * (scrollBar->w / (double)(scrollBar->w - 15)));
645+ dTmp = scrollX * (scrollBar->w / (double)(scrollBar->w - scrollBar->thumbW));
646+ scrollX = (int32_t)(dTmp + 0.5);
598647 }
599648
649+ assert(scrollBar->w > 0);
600650 scrollX = CLAMP(scrollX, 0, scrollBar->w);
601651
602− assert(scrollBar->w > 0);
652+ length = scrollBar->w + (scrollBar->realThumbLength - scrollBar->thumbW);
653+ if (length < 1)
654+ length = 1;
603655
604− dTmp = round(((double)scrollX * scrollBar->end) / scrollBar->w);
605− setScrollBarPos(mouse.lastUsedObjectID, (int32_t)dTmp, true);
656+ dTmp = ((double)scrollX * scrollBar->end) / length;
657+ scrollX = (int32_t)(dTmp + 0.5);
658+
659+ setScrollBarPos(mouse.lastUsedObjectID, scrollX, true);
606660
607661 if (mouse.lastUsedObjectID != OBJECT_ID_NONE) // this can change in the callback in setScrollBarPos()
608662 drawScrollBar(mouse.lastUsedObjectID);
@@ -617,10 +671,14 @@ void handleScrollBarsWhileMouseDown(void) · 8 unmodified lines
617671 scrollY = mouse.lastScrollY - mouse.saveMouseY - scrollBar->y;
618672 scrollY = CLAMP(scrollY, 0, scrollBar->h);
619673
620− assert(scrollBar->h > 0);
674+ length = scrollBar->h + (scrollBar->realThumbLength - scrollBar->thumbH);
675+ if (length < 1)
676+ length = 1;
677+
678+ dTmp = ((double)scrollY * scrollBar->end) / length;
679+ scrollY = (int32_t)(dTmp + 0.5);
621680
622− dTmp = round(((double)scrollY * scrollBar->end) / scrollBar->h);
623− setScrollBarPos(mouse.lastUsedObjectID, (int32_t)dTmp, true);
681+ setScrollBarPos(mouse.lastUsedObjectID, scrollY, true);
624682
625683 if (mouse.lastUsedObjectID != OBJECT_ID_NONE) // this can change in the callback in setScrollBarPos()
626684 drawScrollBar(mouse.lastUsedObjectID);
src/ft2_scrollbars.h+1−1
@@ -76,7 +76,7 @@ typedef struct scrollBar_t // DO NOT TOUCH! · 75 unmodified lines
7676 uint8_t state;
7777 uint32_t pos, page, end;
7878 uint32_t oldPos, oldPage, oldEnd;
79− uint16_t thumbX, thumbY, thumbW, thumbH;
79+ uint16_t thumbX, thumbY, thumbW, thumbH, realThumbLength;
8080 } scrollBar_t;
8181
8282 void drawScrollBar(uint16_t scrollBarID);
src/ft2_sysreqs.c+0−10
@@ -161,11 +161,6 @@ int16_t okBox(int16_t typ, const char *headline, const char *text) · 160 unmodified lines
161161 pushButton_t *p;
162162 checkBox_t *c;
163163
164−#ifndef __APPLE__
165− if (!video.fullscreen) // release mouse button trap
166− SDL_SetWindowGrab(video.window, SDL_FALSE);
167−#endif
168−
169164 if (editor.editTextFlag)
170165 exitTextEditing();
171166
@@ -411,11 +406,6 @@ int16_t inputBox(int16_t typ, const char *headline, char *edText, uint16_t maxSt · 239 unmodified lines
411406 return 0;
412407 }
413408
414−#ifndef __APPLE__
415− if (!video.fullscreen) // release mouse button trap
416− SDL_SetWindowGrab(video.window, SDL_FALSE);
417−#endif
418−
419409 SDL_EventState(SDL_DROPFILE, SDL_DISABLE);
420410
421411 editor.ui.sysReqShown = true;
src/ft2_textboxes.c+2−1
@@ -63,7 +63,8 @@ textBox_t textBoxes[NUM_TEXTBOXES] = · 62 unmodified lines
6363 };
6464
6565 static int16_t markX1, markX2;
66−static uint16_t oldCursorPos, oldMouseX;
66+static uint16_t oldCursorPos;
67+static int32_t oldMouseX;
6768
6869 static void moveTextCursorLeft(int16_t i, bool updateTextBox);
6970 static void moveTextCursorRight(int16_t i, bool updateTextBox);
src/ft2_video.c+59−30
@@ -376,7 +376,7 @@ bool setupSprites(void) · 375 unmodified lines
376376 return true;
377377 }
378378
379−void changeSpriteData(uint8_t sprite, const uint8_t *data)
379+void changeSpriteData(int32_t sprite, const uint8_t *data)
380380 {
381381 sprites[sprite].data = data;
382382 memset(sprites[sprite].refreshBuffer, 0, sprites[sprite].w * sprites[sprite].h * sizeof (int32_t));
@@ -384,7 +384,7 @@ void changeSpriteData(uint8_t sprite, const uint8_t *data) · 1 unmodified line
384384
385385 void freeSprites(void)
386386 {
387− for (uint32_t i = 0; i < SPRITE_NUM; i++)
387+ for (int32_t i = 0; i < SPRITE_NUM; i++)
388388 {
389389 if (sprites[i].refreshBuffer != NULL)
390390 {
@@ -404,18 +404,18 @@ void setRightLoopPinState(bool clicked) · 13 unmodified lines
404404 changeSpriteData(SPRITE_RIGHT_LOOP_PIN, clicked ? &bmp.loopPins[3*(154*16)] : &bmp.loopPins[2*(154*16)]);
405405 }
406406
407−int32_t getSpritePosX(uint8_t sprite)
407+int32_t getSpritePosX(int32_t sprite)
408408 {
409409 return sprites[sprite].x;
410410 }
411411
412−void setSpritePos(uint8_t sprite, int16_t x, int16_t y)
412+void setSpritePos(int32_t sprite, int32_t x, int32_t y)
413413 {
414− sprites[sprite].newX = x;
415− sprites[sprite].newY = y;
414+ sprites[sprite].newX = (int16_t)x;
415+ sprites[sprite].newY = (int16_t)y;
416416 }
417417
418−void hideSprite(uint8_t sprite)
418+void hideSprite(int32_t sprite)
419419 {
420420 sprites[sprite].newX = SCREEN_W;
421421 }
@@ -423,7 +423,7 @@ void hideSprite(uint8_t sprite) · 1 unmodified line
423423 void eraseSprites(void)
424424 {
425425 int8_t i;
426− register int32_t x, y, sw, sh, srcPitch, dstPitch;
426+ int32_t sx, sy, x, y, sw, sh, srcPitch, dstPitch;
427427 const uint32_t *src32;
428428 uint32_t *dst32;
429429 sprite_t *s;
@@ -431,28 +431,36 @@ void eraseSprites(void) · 1 unmodified line
431431 for (i = SPRITE_NUM-1; i >= 0; i--) // erasing must be done in reverse order
432432 {
433433 s = &sprites[i];
434− if (s->x >= SCREEN_W) // sprite is hidden, don't erase
434+ if (s->x >= SCREEN_W || s->y >= SCREEN_H) // sprite is hidden, don't draw nor fill clear buffer
435435 continue;
436436
437− assert(s->y >= 0 && s->refreshBuffer != NULL);
437+ assert(s->refreshBuffer != NULL);
438438
439439 sw = s->w;
440440 sh = s->h;
441− x = s->x;
442− y = s->y;
441+ sx = s->x;
442+ sy = s->y;
443+
444+ // if x is negative, adjust variables
445+ if (sx < 0)
446+ {
447+ sw += sx; // subtraction
448+ sx = 0;
449+ }
443450
444− // if x is negative, adjust variables (can only happen on loop pins in smp. ed.)
445− if (x < 0)
451+ // if y is negative, adjust variables
452+ if (sy < 0)
446453 {
447− sw += x; // subtraction
448− x = 0;
454+ sh += sy; // subtraction
455+ sy = 0;
449456 }
450457
451458 src32 = s->refreshBuffer;
452− dst32 = &video.frameBuffer[(y * SCREEN_W) + x];
459+ dst32 = &video.frameBuffer[(sy * SCREEN_W) + sx];
453460
454− if (y+sh >= SCREEN_H) sh = SCREEN_H - y;
455− if (x+sw >= SCREEN_W) sw = SCREEN_W - x;
461+ // handle x/y clipping
462+ if (sx+sw >= SCREEN_W) sw = SCREEN_W - sx;
463+ if (sy+sh >= SCREEN_H) sh = SCREEN_H - sy;
456464
457465 srcPitch = s->w - sw;
458466 dstPitch = SCREEN_W - sw;
@@ -471,7 +479,7 @@ void eraseSprites(void) · 12 unmodified lines
471479 void renderSprites(void)
472480 {
473481 const uint8_t *src8;
474− register int32_t x, y, sw, sh, srcPitch, dstPitch;
482+ int32_t sx, sy, x, y, sw, sh, srcPitch, dstPitch;
475483 uint32_t i, *clr32, *dst32, windowFlags;
476484 sprite_t *s;
477485
@@ -495,20 +503,42 @@ void renderSprites(void) · 17 unmodified lines
495503 s->x = s->newX;
496504 s->y = s->newY;
497505
498− if (s->x >= SCREEN_W) // sprite is hidden, don't draw nor fill clear buffer
506+ if (s->x >= SCREEN_W || s->y >= SCREEN_H) // sprite is hidden, don't draw nor fill clear buffer
499507 continue;
500508
501− assert(s->x >= 0 && s->y >= 0 && s->data != NULL && s->refreshBuffer != NULL);
509+ assert(s->data != NULL && s->refreshBuffer != NULL);
502510
503511 sw = s->w;
504512 sh = s->h;
513+ sx = s->x;
514+ sy = s->y;
505515 src8 = s->data;
506− dst32 = &video.frameBuffer[(s->y * SCREEN_W) + s->x];
516+
517+ // if x is negative, adjust variables
518+ if (sx < 0)
519+ {
520+ sw += sx; // subtraction
521+ src8 -= sx; // addition
522+ sx = 0;
523+ }
524+
525+ // if y is negative, adjust variables
526+ if (sy < 0)
527+ {
528+ sh += sy; // subtraction
529+ src8 += (-sy * s->w); // addition
530+ sy = 0;
531+ }
532+
533+ if (sw <= 0 || sh <= 0) // sprite is hidden, don't draw nor fill clear buffer
534+ continue;
535+
536+ dst32 = &video.frameBuffer[(sy * SCREEN_W) + sx];
507537 clr32 = s->refreshBuffer;
508538
509− // handle xy clipping
510− if (s->y+sh >= SCREEN_H) sh = SCREEN_H - s->y;
511− if (s->x+sw >= SCREEN_W) sw = SCREEN_W - s->x;
539+ // handle x/y clipping
540+ if (sx+sw >= SCREEN_W) sw = SCREEN_W - sx;
541+ if (sy+sh >= SCREEN_H) sh = SCREEN_H - sy;
512542
513543 srcPitch = s->w - sw;
514544 dstPitch = SCREEN_W - sw;
@@ -570,8 +600,7 @@ void renderLoopPins(void) · 55 unmodified lines
570600 {
571601 uint8_t pal;
572602 const uint8_t *src8;
573− int32_t sx;
574− register int32_t x, y, sw, sh, srcPitch, dstPitch;
603+ int32_t sx, x, y, sw, sh, srcPitch, dstPitch;
575604 uint32_t *clr32, *dst32;
576605 sprite_t *s;
577606
@@ -604,7 +633,7 @@ void renderLoopPins(void) · 26 unmodified lines
604633 dst32 = &video.frameBuffer[(s->y * SCREEN_W) + sx];
605634
606635 // handle x clipping
607− if (s->x+sw >= SCREEN_W) sw = SCREEN_W - s->x;
636+ if (sx+sw >= SCREEN_W) sw = SCREEN_W - sx;
608637
609638 srcPitch = s->w - sw;
610639 dstPitch = SCREEN_W - sw;
@@ -663,7 +692,7 @@ void renderLoopPins(void) · 52 unmodified lines
663692 dst32 = &video.frameBuffer[(s->y * SCREEN_W) + sx];
664693
665694 // handle x clipping
666− if (s->x+sw >= SCREEN_W) sw = SCREEN_W - s->x;
695+ if (sx+sw >= SCREEN_W) sw = SCREEN_W - sx;
667696
668697 srcPitch = s->w - sw;
669698 dstPitch = SCREEN_W - sw;
src/ft2_video.h+5−5
@@ -27,7 +27,7 @@ struct video_t · 26 unmodified lines
2727 SDL_Window *window;
2828 double dMonitorRefreshRate, dMouseXMul, dMouseYMul;
2929 uint8_t upscaleFactor;
30− bool vsync60HzPresent;
30+ bool vsync60HzPresent, windowHidden;
3131 int32_t renderX, renderY, renderW, renderH, displayW, displayH;
3232 uint32_t *frameBufferUnaligned;
3333 SDL_Renderer *renderer;
@@ -56,15 +56,15 @@ bool setupRenderer(void); · 22 unmodified lines
5656 void closeVideo(void);
5757 void setLeftLoopPinState(bool clicked);
5858 void setRightLoopPinState(bool clicked);
59−int32_t getSpritePosX(uint8_t sprite);
59+int32_t getSpritePosX(int32_t sprite);
6060 void eraseSprites(void);
6161 void renderLoopPins(void);
6262 void renderSprites(void);
6363 bool setupSprites(void);
6464 void freeSprites(void);
65−void setSpritePos(uint8_t sprite, int16_t x, int16_t y);
66−void changeSpriteData(uint8_t sprite, const uint8_t *data);
67−void hideSprite(uint8_t sprite);
65+void setSpritePos(int32_t sprite, int32_t x, int32_t y);
66+void changeSpriteData(int32_t sprite, const uint8_t *data);
67+void hideSprite(int32_t sprite);
6868 void handleRedrawing(void);
6969 void enterFullscreen(void);
7070 void leaveFullScreen(void);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t