diff --git a/Makefile b/Makefile index 9e6f7f7cc..f47b3b665 100644 --- a/Makefile +++ b/Makefile @@ -401,13 +401,8 @@ endif QBLIB := $(PATH_INTERNAL_C)/$(QBLIB_NAME).o -ifneq ($(OS),osx) $(QBLIB): $(PATH_INTERNAL_C)/libqb.cpp $(CXX) $(CXXFLAGS) $< -c -o $@ -else -$(QBLIB): $(PATH_INTERNAL_C)/libqb.mm - $(CXX) $(CXXFLAGS) $< -c -o $@ -endif ifeq ($(OS),win) CLEAN_LIST += $(ICON_OBJ) @@ -421,6 +416,11 @@ EXE_OBJS := $(QBLIB) $(EXE_OBJS) %.o: %.cpp $(CXX) $(CXXFLAGS) $< -c -o $@ +ifeq ($(OS),osx) +%.o: %.mm + $(CXX) $(CXXFLAGS) $< -c -o $@ +endif + $(PATH_INTERNAL_TEMP)/data.o: $(PATH_INTERNAL_TEMP)/data.bin $(OBJCOPY) -Ibinary $(OBJCOPY_FLAGS) $< $@ diff --git a/internal/c/libqb.cpp b/internal/c/libqb.cpp index 09a62a662..64d027868 100644 --- a/internal/c/libqb.cpp +++ b/internal/c/libqb.cpp @@ -13,13 +13,7 @@ #ifdef QB64_MACOSX # include -# include "Cocoa/Cocoa.h" -# include -# include -# include - # include //required for _NSGetExecutablePath - #endif #include "mutex.h" @@ -29,6 +23,8 @@ #include "image.h" #include "gui.h" #include "http.h" +#include "keyhandler.h" +#include "glut-thread.h" int32 disableEvents = 0; @@ -243,26 +239,10 @@ extern "C" void QB64_Window_Handle(void *handle) { //... } -static bool is_glut_up(); -static void start_glut_thread(); - -#define NEEDS_GLUT(error_result) do { \ - if (!is_glut_up()) { \ - error(5); \ - return error_result; \ - } \ - } while (0) - -#define OPTIONAL_GLUT(result) do { \ - if (!is_glut_up()) \ - return result; \ - } while (0) - // forward references void set_view(int32 new_mode); void set_render_source(int32 new_handle); void set_render_dest(int32 new_handle); -void reinit_glut_callbacks(); int32 framebufferobjects_supported = 0; @@ -283,7 +263,6 @@ int32 environment_2d__letterbox = 0; // 1=vertical black stripes required, 2 int32 window_focused = 0; // Not used on Windows uint8 *window_title = NULL; -int32 temp_window_title_set = 0; double max_fps = 60; // 60 is the default int32 auto_fps = 0; // set to 1 to make QB64 auto-adjust fps based on load @@ -515,14 +494,6 @@ int32 dont_call_sub_gl = 0; void GLUT_DISPLAY_REQUEST(); -void timerCB(int millisec) // not currently being used -{ -#ifdef QB64_GLUT - glutPostRedisplay(); - glutTimerFunc(millisec, timerCB, millisec); -#endif -} - struct display_frame_struct { int32 state; int64 order; @@ -1243,294 +1214,6 @@ int64 GetTicks() { return orwl_gettime(); } int64 GetTicks() { return ((((int64)clock()) * ((int64)1000)) / ((int64)CLOCKS_PER_SEC)); } #endif -#define QBK 200000 -#define VK 100000 -#define UC 1073741824 -/* QBK codes: - 200000-200010: Numpad keys with Num-Lock off - NO_NUMLOCK_KP0=INSERT - NO_NUMLOCK_KP1=END - NO_NUMLOCK_KP2=DOWN - NO_NUMLOCK_KP3=PGDOWN - NO_NUMLOCK_KP4... - NO_NUMLOCK_KP5 - NO_NUMLOCK_KP6 - NO_NUMLOCK_KP7 - NO_NUMLOCK_KP8 - NO_NUMLOCK_KP9 - NO_NUMLOCK_KP_PERIOD=DEL - 200011: SCROLL_LOCK_ON - 200012: INSERT_MODE_ON -*/ -#define QBK_SCROLL_LOCK_MODE 11 -#define QBK_INSERT_MODE 12 -#define QBK_CHR0 13 -typedef enum { - QBVK_UNKNOWN = 0, - QBVK_FIRST = 0, - QBVK_BACKSPACE = 8, - QBVK_TAB = 9, - QBVK_CLEAR = 12, - QBVK_RETURN = 13, - QBVK_PAUSE = 19, - QBVK_ESCAPE = 27, - QBVK_SPACE = 32, - QBVK_EXCLAIM = 33, - QBVK_QUOTEDBL = 34, - QBVK_HASH = 35, - QBVK_DOLLAR = 36, - QBVK_AMPERSAND = 38, - QBVK_QUOTE = 39, - QBVK_LEFTPAREN = 40, - QBVK_RIGHTPAREN = 41, - QBVK_ASTERISK = 42, - QBVK_PLUS = 43, - QBVK_COMMA = 44, - QBVK_MINUS = 45, - QBVK_PERIOD = 46, - QBVK_SLASH = 47, - QBVK_0 = 48, - QBVK_1 = 49, - QBVK_2 = 50, - QBVK_3 = 51, - QBVK_4 = 52, - QBVK_5 = 53, - QBVK_6 = 54, - QBVK_7 = 55, - QBVK_8 = 56, - QBVK_9 = 57, - QBVK_COLON = 58, - QBVK_SEMICOLON = 59, - QBVK_LESS = 60, - QBVK_EQUALS = 61, - QBVK_GREATER = 62, - QBVK_QUESTION = 63, - QBVK_AT = 64, - // Skip uppercase letters - QBVK_LEFTBRACKET = 91, - QBVK_BACKSLASH = 92, - QBVK_RIGHTBRACKET = 93, - QBVK_CARET = 94, - QBVK_UNDERSCORE = 95, - QBVK_BACKQUOTE = 96, - QBVK_a = 97, - QBVK_b = 98, - QBVK_c = 99, - QBVK_d = 100, - QBVK_e = 101, - QBVK_f = 102, - QBVK_g = 103, - QBVK_h = 104, - QBVK_i = 105, - QBVK_j = 106, - QBVK_k = 107, - QBVK_l = 108, - QBVK_m = 109, - QBVK_n = 110, - QBVK_o = 111, - QBVK_p = 112, - QBVK_q = 113, - QBVK_r = 114, - QBVK_s = 115, - QBVK_t = 116, - QBVK_u = 117, - QBVK_v = 118, - QBVK_w = 119, - QBVK_x = 120, - QBVK_y = 121, - QBVK_z = 122, - QBVK_DELETE = 127, - // End of ASCII mapped QBVKs - // International QBVKs - QBVK_WORLD_0 = 160, /* 0xA0 */ - QBVK_WORLD_1 = 161, - QBVK_WORLD_2 = 162, - QBVK_WORLD_3 = 163, - QBVK_WORLD_4 = 164, - QBVK_WORLD_5 = 165, - QBVK_WORLD_6 = 166, - QBVK_WORLD_7 = 167, - QBVK_WORLD_8 = 168, - QBVK_WORLD_9 = 169, - QBVK_WORLD_10 = 170, - QBVK_WORLD_11 = 171, - QBVK_WORLD_12 = 172, - QBVK_WORLD_13 = 173, - QBVK_WORLD_14 = 174, - QBVK_WORLD_15 = 175, - QBVK_WORLD_16 = 176, - QBVK_WORLD_17 = 177, - QBVK_WORLD_18 = 178, - QBVK_WORLD_19 = 179, - QBVK_WORLD_20 = 180, - QBVK_WORLD_21 = 181, - QBVK_WORLD_22 = 182, - QBVK_WORLD_23 = 183, - QBVK_WORLD_24 = 184, - QBVK_WORLD_25 = 185, - QBVK_WORLD_26 = 186, - QBVK_WORLD_27 = 187, - QBVK_WORLD_28 = 188, - QBVK_WORLD_29 = 189, - QBVK_WORLD_30 = 190, - QBVK_WORLD_31 = 191, - QBVK_WORLD_32 = 192, - QBVK_WORLD_33 = 193, - QBVK_WORLD_34 = 194, - QBVK_WORLD_35 = 195, - QBVK_WORLD_36 = 196, - QBVK_WORLD_37 = 197, - QBVK_WORLD_38 = 198, - QBVK_WORLD_39 = 199, - QBVK_WORLD_40 = 200, - QBVK_WORLD_41 = 201, - QBVK_WORLD_42 = 202, - QBVK_WORLD_43 = 203, - QBVK_WORLD_44 = 204, - QBVK_WORLD_45 = 205, - QBVK_WORLD_46 = 206, - QBVK_WORLD_47 = 207, - QBVK_WORLD_48 = 208, - QBVK_WORLD_49 = 209, - QBVK_WORLD_50 = 210, - QBVK_WORLD_51 = 211, - QBVK_WORLD_52 = 212, - QBVK_WORLD_53 = 213, - QBVK_WORLD_54 = 214, - QBVK_WORLD_55 = 215, - QBVK_WORLD_56 = 216, - QBVK_WORLD_57 = 217, - QBVK_WORLD_58 = 218, - QBVK_WORLD_59 = 219, - QBVK_WORLD_60 = 220, - QBVK_WORLD_61 = 221, - QBVK_WORLD_62 = 222, - QBVK_WORLD_63 = 223, - QBVK_WORLD_64 = 224, - QBVK_WORLD_65 = 225, - QBVK_WORLD_66 = 226, - QBVK_WORLD_67 = 227, - QBVK_WORLD_68 = 228, - QBVK_WORLD_69 = 229, - QBVK_WORLD_70 = 230, - QBVK_WORLD_71 = 231, - QBVK_WORLD_72 = 232, - QBVK_WORLD_73 = 233, - QBVK_WORLD_74 = 234, - QBVK_WORLD_75 = 235, - QBVK_WORLD_76 = 236, - QBVK_WORLD_77 = 237, - QBVK_WORLD_78 = 238, - QBVK_WORLD_79 = 239, - QBVK_WORLD_80 = 240, - QBVK_WORLD_81 = 241, - QBVK_WORLD_82 = 242, - QBVK_WORLD_83 = 243, - QBVK_WORLD_84 = 244, - QBVK_WORLD_85 = 245, - QBVK_WORLD_86 = 246, - QBVK_WORLD_87 = 247, - QBVK_WORLD_88 = 248, - QBVK_WORLD_89 = 249, - QBVK_WORLD_90 = 250, - QBVK_WORLD_91 = 251, - QBVK_WORLD_92 = 252, - QBVK_WORLD_93 = 253, - QBVK_WORLD_94 = 254, - QBVK_WORLD_95 = 255, /* 0xFF */ - // Numeric keypad - QBVK_KP0 = 256, - QBVK_KP1 = 257, - QBVK_KP2 = 258, - QBVK_KP3 = 259, - QBVK_KP4 = 260, - QBVK_KP5 = 261, - QBVK_KP6 = 262, - QBVK_KP7 = 263, - QBVK_KP8 = 264, - QBVK_KP9 = 265, - QBVK_KP_PERIOD = 266, - QBVK_KP_DIVIDE = 267, - QBVK_KP_MULTIPLY = 268, - QBVK_KP_MINUS = 269, - QBVK_KP_PLUS = 270, - QBVK_KP_ENTER = 271, - QBVK_KP_EQUALS = 272, - // Arrows + Home/End pad - QBVK_UP = 273, - QBVK_DOWN = 274, - QBVK_RIGHT = 275, - QBVK_LEFT = 276, - QBVK_INSERT = 277, - QBVK_HOME = 278, - QBVK_END = 279, - QBVK_PAGEUP = 280, - QBVK_PAGEDOWN = 281, - // Function keys - QBVK_F1 = 282, - QBVK_F2 = 283, - QBVK_F3 = 284, - QBVK_F4 = 285, - QBVK_F5 = 286, - QBVK_F6 = 287, - QBVK_F7 = 288, - QBVK_F8 = 289, - QBVK_F9 = 290, - QBVK_F10 = 291, - QBVK_F11 = 292, - QBVK_F12 = 293, - QBVK_F13 = 294, - QBVK_F14 = 295, - QBVK_F15 = 296, - // Key state modifier keys - QBVK_NUMLOCK = 300, - QBVK_CAPSLOCK = 301, - QBVK_SCROLLOCK = 302, - // If more modifiers are added, the window defocus code in qb64_os_event_linux must be altered - QBVK_RSHIFT = 303, - QBVK_LSHIFT = 304, - QBVK_RCTRL = 305, - QBVK_LCTRL = 306, - QBVK_RALT = 307, - QBVK_LALT = 308, - QBVK_RMETA = 309, - QBVK_LMETA = 310, - QBVK_LSUPER = 311, /* Left "Windows" key */ - QBVK_RSUPER = 312, /* Right "Windows" key */ - QBVK_MODE = 313, /* "Alt Gr" key */ - QBVK_COMPOSE = 314, /* Multi-key compose key */ - // Miscellaneous function keys - QBVK_HELP = 315, - QBVK_PRINT = 316, - QBVK_SYSREQ = 317, - QBVK_BREAK = 318, - QBVK_MENU = 319, - QBVK_POWER = 320, /* Power Macintosh power key */ - QBVK_EURO = 321, /* Some european keyboards */ - QBVK_UNDO = 322, /* Atari keyboard has Undo */ - QBVK_LAST -} QBVKs; -// Enumeration of valid key mods (possibly OR'd together) -typedef enum { - KMOD_NONE = 0x0000, - KMOD_LSHIFT = 0x0001, - KMOD_RSHIFT = 0x0002, - KMOD_LCTRL = 0x0040, - KMOD_RCTRL = 0x0080, - KMOD_LALT = 0x0100, - KMOD_RALT = 0x0200, - KMOD_LMETA = 0x0400, - KMOD_RMETA = 0x0800, - KMOD_NUM = 0x1000, - KMOD_CAPS = 0x2000, - KMOD_MODE = 0x4000, - KMOD_RESERVED = 0x8000 -} KMODs; -#define KMOD_CTRL (KMOD_LCTRL | KMOD_RCTRL) -#define KMOD_SHIFT (KMOD_LSHIFT | KMOD_RSHIFT) -#define KMOD_ALT (KMOD_LALT | KMOD_RALT) -#define KMOD_META (KMOD_LMETA | KMOD_RMETA) - /* Restricted Functionality: (Security focused approach, does not include restricting sound etc) Block while compiling: (ONLY things that cannot be caught at runtime) @@ -23784,7 +23467,7 @@ void sub__mousehide() { #ifdef QB64_GUI # ifdef QB64_GLUT OPTIONAL_GLUT(); - glutSetCursor(GLUT_CURSOR_NONE); + libqb_glut_set_cursor(GLUT_CURSOR_NONE); # endif #endif } @@ -23856,7 +23539,7 @@ void sub__mouseshow(qbs *style, int32 passed) { } cursor_valid: - glutSetCursor(mouse_cursor_style); + libqb_glut_set_cursor(mouse_cursor_style); #endif } @@ -23938,7 +23621,7 @@ void sub__mousemove(float x, float y) { x2 += environment_2d__screen_x1; y2 += environment_2d__screen_y1; - glutWarpPointer(x2, y2); + libqb_glut_warp_pointer(x2, y2); return; error: @@ -27518,7 +27201,7 @@ int32 func_screenwidth() { #else # ifdef QB64_GLUT OPTIONAL_GLUT(0); - return glutGet(GLUT_SCREEN_WIDTH); + return libqb_glut_get(GLUT_SCREEN_WIDTH); # else return 0; # endif @@ -27531,7 +27214,7 @@ int32 func_screenheight() { #else # ifdef QB64_GLUT OPTIONAL_GLUT(0); - return glutGet(GLUT_SCREEN_HEIGHT); + return libqb_glut_get(GLUT_SCREEN_HEIGHT); # else return 0; # endif @@ -27541,13 +27224,13 @@ int32 func_screenheight() { void sub_screenicon() { #ifdef QB64_GLUT NEEDS_GLUT(); - glutIconifyWindow(); + libqb_glut_iconify_window(); #endif } int32 func_windowexists() { #ifdef QB64_GLUT - return is_glut_up(); + return libqb_is_glut_up(); #else return -1; #endif @@ -32951,10 +32634,10 @@ qbs *func__os() { int32 func__screenx() { #if defined(QB64_GUI) && defined(QB64_WINDOWS) && defined(QB64_GLUT) NEEDS_GLUT(0); - return glutGet(GLUT_WINDOW_X) - glutGet(GLUT_WINDOW_BORDER_WIDTH); + return libqb_glut_get(GLUT_WINDOW_X) - libqb_glut_get(GLUT_WINDOW_BORDER_WIDTH); #elif defined(QB64_GUI) && defined(QB64_MACOSX) && defined(QB64_GLUT) NEEDS_GLUT(0); - return glutGet(GLUT_WINDOW_X); + return libqb_glut_get(GLUT_WINDOW_X); #endif return 0; // if not windows then return 0 } @@ -32962,10 +32645,10 @@ int32 func__screenx() { int32 func__screeny() { #if defined(QB64_GUI) && defined(QB64_WINDOWS) && defined(QB64_GLUT) NEEDS_GLUT(0); - return glutGet(GLUT_WINDOW_Y) - glutGet(GLUT_WINDOW_BORDER_WIDTH) - glutGet(GLUT_WINDOW_HEADER_HEIGHT); + return libqb_glut_get(GLUT_WINDOW_Y) - libqb_glut_get(GLUT_WINDOW_BORDER_WIDTH) - libqb_glut_get(GLUT_WINDOW_HEADER_HEIGHT); #elif defined(QB64_GUI) && defined(QB64_MACOSX) && defined(QB64_GLUT) NEEDS_GLUT(0); - return glutGet(GLUT_WINDOW_Y); + return libqb_glut_get(GLUT_WINDOW_Y); #endif return 0; // if not windows then return 0 } @@ -32984,18 +32667,18 @@ void sub__screenmove(int32 x, int32 y, int32 passed) { NEEDS_GLUT(); if (passed == 2) { - glutPositionWindow(x, y); + libqb_glut_position_window(x, y); } else { int32 SW = -1, SH, WW, WH; while (SW == -1) { - SW = glutGet(GLUT_SCREEN_WIDTH); + SW = libqb_glut_get(GLUT_SCREEN_WIDTH); } - SH = glutGet(GLUT_SCREEN_HEIGHT); - WW = glutGet(GLUT_WINDOW_WIDTH); - WH = glutGet(GLUT_WINDOW_HEIGHT); + SH = libqb_glut_get(GLUT_SCREEN_HEIGHT); + WW = libqb_glut_get(GLUT_WINDOW_WIDTH); + WH = libqb_glut_get(GLUT_WINDOW_HEIGHT); x = (SW - WW) / 2; y = (SH - WH) / 2; - glutPositionWindow(x, y); + libqb_glut_position_window(x, y); } #endif @@ -34286,8 +33969,8 @@ void sub__screenshow() { #ifdef QB64_GLUT screen_hide = 0; // $SCREENHIDE programs will not have the window running - start_glut_thread(); - glutShowWindow(); + libqb_start_glut_thread(); + libqb_glut_show_window(); #endif } @@ -34296,8 +33979,10 @@ void sub__screenhide() { return; #ifdef QB64_GLUT - // start_glut_thread(); - glutHideWindow(); + // This is probably unnecessary, no conditions allow for screen_hide==0 + // without GLUT running, but it doesn't hurt anything. + libqb_start_glut_thread(); + libqb_glut_hide_window(); #endif screen_hide = 1; @@ -34957,6 +34642,8 @@ void GLUT_SPECIALUP_FUNC(int key, int x, int y) { GLUT_key_special(key, 0); } #ifdef QB64_WINDOWS void GLUT_TIMER_EVENT(int ignore) { + libqb_process_glut_queue(); + # ifdef QB64_GLUT glutPostRedisplay(); int32 msdelay = 1000.0 / max_fps; @@ -34969,6 +34656,7 @@ void GLUT_TIMER_EVENT(int ignore) { } #else void GLUT_IDLEFUNC() { + libqb_process_glut_queue(); # ifdef QB64_MACOSX # ifdef DEPENDENCY_DEVICEINPUT @@ -36210,13 +35898,6 @@ void GLUT_DISPLAY_REQUEST() { } in_GLUT_DISPLAY_REQUEST = 1; -# ifdef QB64_MACOSX - if (temp_window_title_set == 1) { - glutSetWindowTitle((char *)window_title); - temp_window_title_set = 0; - } -# endif - // general use variables static int32 i, i2, i3; static int32 x, y, x2, y2; @@ -37026,15 +36707,9 @@ void sub__title(qbs *title) { if (old_buf) free(old_buf); -#ifdef QB64_GLUT -# ifdef QB64_MACOSX - temp_window_title_set = 1; -# else OPTIONAL_GLUT(); - glutSetWindowTitle((char *)window_title); -# endif -#endif + libqb_glut_set_window_title((char *)window_title); } // title void sub__echo(qbs *message) { @@ -37367,165 +37042,6 @@ qbs *func__dir(qbs *context_in) { #endif } -static void glutWarning(const char *fmt, va_list lst) { - // Do something -} - -// Performs all of the FreeGLUT initialization except for calling glutMainLoop() -static void initialize_glut(int argc, char **argv) { -#ifdef QB64_GLUT -# ifdef CORE_FREEGLUT - // This keeps FreeGlut from dumping warnings to console - glutInitWarningFunc(glutWarning); - glutInitErrorFunc(glutWarning); -# endif - - glutInit(&argc, argv); - -# ifdef QB64_MACOSX - [NSEvent addLocalMonitorForEventsMatchingMask:NSFlagsChangedMask - handler:^NSEvent *(NSEvent *event) { - // notes on bitfields: - // if ([event modifierFlags] == 131330) keydown_vk(VK+QBVK_LSHIFT);// 100000000100000010 - // if ([event modifierFlags] == 131332) keydown_vk(VK+QBVK_RSHIFT);// 100000000100000100 - // if ([event modifierFlags] == 262401) keydown_vk(VK+QBVK_LCTRL); //1000000000100000001 - // if ([event modifierFlags] == 270592) keydown_vk(VK+QBVK_RCTRL); //1000010000100000000 - // if ([event modifierFlags] == 524576) keydown_vk(VK+QBVK_LALT); //10000000000100100000 - // if ([event modifierFlags] == 524608) keydown_vk(VK+QBVK_RALT); //10000000000101000000 - // caps lock // 10000000100000000 - - int x = [event modifierFlags]; - - if (x & (1 << 0)) { - if (!keyheld(VK + QBVK_LCTRL)) - keydown_vk(VK + QBVK_LCTRL); - } else { - if (keyheld(VK + QBVK_LCTRL)) - keyup_vk(VK + QBVK_LCTRL); - } - if (x & (1 << 13)) { - if (!keyheld(VK + QBVK_RCTRL)) - keydown_vk(VK + QBVK_RCTRL); - } else { - if (keyheld(VK + QBVK_RCTRL)) - keyup_vk(VK + QBVK_RCTRL); - } - - if (x & (1 << 1)) { - if (!keyheld(VK + QBVK_LSHIFT)) - keydown_vk(VK + QBVK_LSHIFT); - } else { - if (keyheld(VK + QBVK_LSHIFT)) - keyup_vk(VK + QBVK_LSHIFT); - } - if (x & (1 << 2)) { - if (!keyheld(VK + QBVK_RSHIFT)) - keydown_vk(VK + QBVK_RSHIFT); - } else { - if (keyheld(VK + QBVK_RSHIFT)) - keyup_vk(VK + QBVK_RSHIFT); - } - - if (x & (1 << 5)) { - if (!keyheld(VK + QBVK_LALT)) - keydown_vk(VK + QBVK_LALT); - } else { - if (keyheld(VK + QBVK_LALT)) - keyup_vk(VK + QBVK_LALT); - } - if (x & (1 << 6)) { - if (!keyheld(VK + QBVK_RALT)) - keydown_vk(VK + QBVK_RALT); - } else { - if (keyheld(VK + QBVK_RALT)) - keyup_vk(VK + QBVK_RALT); - } - - if (x & (1 << 16)) { - if (!keyheld(VK + QBVK_CAPSLOCK)) - keydown_vk(VK + QBVK_CAPSLOCK); - } else { - if (keyheld(VK + QBVK_CAPSLOCK)) - keyup_vk(VK + QBVK_CAPSLOCK); - } - - return event; - }]; -# endif - -# ifdef QB64_WINDOWS - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); -# else - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); -# endif - - glutInitWindowSize(640, 400); // cannot be changed unless display_x(etc) are modified - - if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) // must be called on Linux or GLUT crashes - { - exit(1); - } - - if (!window_title) { - glutCreateWindow("Untitled"); - } else { - glutCreateWindow((char *)window_title); - } - - GLenum err = glewInit(); - if (GLEW_OK != err) { - gui_alert((char *)glewGetErrorString(err)); - } - if (glewIsSupported("GL_EXT_framebuffer_object")) - framebufferobjects_supported = 1; - - glutDisplayFunc(GLUT_DISPLAY_REQUEST); - -# ifdef QB64_WINDOWS - glutTimerFunc(8, GLUT_TIMER_EVENT, 0); -# else - glutIdleFunc(GLUT_IDLEFUNC); -# endif - - glutKeyboardFunc(GLUT_KEYBOARD_FUNC); - glutKeyboardUpFunc(GLUT_KEYBOARDUP_FUNC); - glutSpecialFunc(GLUT_SPECIAL_FUNC); - glutSpecialUpFunc(GLUT_SPECIALUP_FUNC); - glutMouseFunc(GLUT_MOUSE_FUNC); - glutMotionFunc(GLUT_MOTION_FUNC); - glutPassiveMotionFunc(GLUT_PASSIVEMOTION_FUNC); - glutReshapeFunc(GLUT_RESHAPE_FUNC); - -# ifdef CORE_FREEGLUT - glutMouseWheelFunc(GLUT_MOUSEWHEEL_FUNC); -# endif -#endif // QB64_GLUT -} - -static bool glut_is_started; -static struct completion glut_thread_starter; -static struct completion *glut_thread_initialized; - -static void start_glut_thread() { - if (glut_is_started) - return; - - struct completion init; - completion_init(&init); - - glut_thread_initialized = &init; - - completion_finish(&glut_thread_starter); - - completion_wait(&init); - completion_clear(&init); -} - -// Checks whether the GLUT thread is running -static bool is_glut_up() { - return glut_is_started; -} - extern void set_dynamic_info(); int main(int argc, char *argv[]) { @@ -37967,14 +37483,7 @@ int main(int argc, char *argv[]) { libqb_http_init(); -#ifdef QB64_GUI - if (!screen_hide) { - initialize_glut(argc, argv); // Initialize GLUT if the screen isn't hidden - glut_is_started = true; - } else { - completion_init(&glut_thread_starter); - } -#endif + libqb_glut_presetup(argc, argv); struct libqb_thread *qbmain = libqb_thread_new(); libqb_thread_start(qbmain, QBMAIN, NULL); @@ -37984,32 +37493,9 @@ int main(int argc, char *argv[]) { lock_display_required = 1; -#ifdef QB64_GUI + libqb_start_main_thread(argc, argv); - struct libqb_thread *main_loop = libqb_thread_new(); - libqb_thread_start(main_loop, MAIN_LOOP, NULL); - - // This happens for $SCREENHIDE programs. This thread waits on the - // `glut_thread_starter` completion, which will get completed if a - // _ScreenShow is used. - if (!glut_is_started) { - completion_wait(&glut_thread_starter); - - initialize_glut(argc, argv); - glut_is_started = true; - - if (glut_thread_initialized) - completion_finish(glut_thread_initialized); - } - - glutMainLoop(); - -#else - // normally MAIN_LOOP() is launched in a separate thread to reserve the primary thread for GLUT - // that is not required, so run MAIN_LOOP() in our primary thread - MAIN_LOOP(NULL); - return 0; -#endif + return 0; // Should never get here } //###################### Main Loop #################### @@ -38200,7 +37686,7 @@ end_program: snd_un_init(); - exit(exit_code); + libqb_exit(exit_code); } // used to preserve the previous frame's content for comparison/reuse purposes @@ -40238,31 +39724,6 @@ extern "C" int qb64_custom_event(int event, int v1, int v2, int v3, int v4, int return -1; // Unknown command (use for debugging purposes only) } // qb64_custom_event -void reinit_glut_callbacks() { - -#ifdef QB64_GLUT - - glutDisplayFunc(GLUT_DISPLAY_REQUEST); -# ifdef QB64_WINDOWS - glutTimerFunc(8, GLUT_TIMER_EVENT, 0); -# else - glutIdleFunc(GLUT_IDLEFUNC); -# endif - glutKeyboardFunc(GLUT_KEYBOARD_FUNC); - glutKeyboardUpFunc(GLUT_KEYBOARDUP_FUNC); - glutSpecialFunc(GLUT_SPECIAL_FUNC); - glutSpecialUpFunc(GLUT_SPECIALUP_FUNC); - glutMouseFunc(GLUT_MOUSE_FUNC); - glutMotionFunc(GLUT_MOTION_FUNC); - glutPassiveMotionFunc(GLUT_PASSIVEMOTION_FUNC); - glutReshapeFunc(GLUT_RESHAPE_FUNC); -# ifdef CORE_FREEGLUT - glutMouseWheelFunc(GLUT_MOUSEWHEEL_FUNC); -# endif - -#endif -} - int32 func__capslock() { #ifdef QB64_WINDOWS return -GetKeyState(VK_CAPITAL); diff --git a/internal/c/libqb.mm b/internal/c/libqb.mm deleted file mode 100644 index 59eae3f8c..000000000 --- a/internal/c/libqb.mm +++ /dev/null @@ -1,2 +0,0 @@ -#include "libqb.cpp" - diff --git a/internal/c/libqb/build.mk b/internal/c/libqb/build.mk index 3350de34c..9ffba313b 100644 --- a/internal/c/libqb/build.mk +++ b/internal/c/libqb/build.mk @@ -8,4 +8,14 @@ libqb-objs-y$(DEP_HTTP) += $(PATH_LIBQB)/src/http-stub.o libqb-objs-y += $(PATH_LIBQB)/src/threading-$(PLATFORM).o +libqb-objs-y$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/glut-main-thread.o +libqb-objs-y$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/glut-message.o +libqb-objs-y$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/glut-msg-queue.o + +libqb-objs-$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/console-only-main-thread.o + +ifeq ($(OS),osx) +libqb-objs-y$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/mac-key-monitor.o +endif + CLEAN_LIST += $(libqb-objs-y) $(libqb-objs-yy) $(libqb-objs-) diff --git a/internal/c/libqb/include/glut-thread.h b/internal/c/libqb/include/glut-thread.h new file mode 100644 index 000000000..0578e9efd --- /dev/null +++ b/internal/c/libqb/include/glut-thread.h @@ -0,0 +1,50 @@ +#ifndef INCLUDE_LIBQB_GLUT_THREAD_H +#define INCLUDE_LIBQB_GLUT_THREAD_H + +// Called to potentially setup GLUT before starting the program. +void libqb_glut_presetup(int argc, char **argv); + +// Starts the "main thread", including handling all the GLUT setup. +void libqb_start_main_thread(int argc, char **argv); + +// Used to support _ScreenShow, which can start the GLUT thread after the +// program is started +void libqb_start_glut_thread(); + +// Indicates whether GLUT is currently running (and thus whether we're able to +// do any GLUT-related stuff +bool libqb_is_glut_up(); + +// Called at consistent intervals from a GLUT callback +void libqb_process_glut_queue(); + +// Called to properly exit the program. Necessary because GLUT requires a +// special care to not seg-fault when exiting the program. +void libqb_exit(int); + +// These functions perform the same actions as their coresponding glut* functions. +// They tell the GLUT thread to perform the command, returning the result if applicable +void libqb_glut_set_cursor(int style); +void libqb_glut_warp_pointer(int x, int y); +int libqb_glut_get(int id); +void libqb_glut_iconify_window(); +void libqb_glut_position_window(int x, int y); +void libqb_glut_show_window(); +void libqb_glut_hide_window(); +void libqb_glut_set_window_title(const char *title); +void libqb_glut_exit_program(int exitcode); + +// Convinence macros, exists a function depending on the state of GLUT +#define NEEDS_GLUT(error_result) do { \ + if (!libqb_is_glut_up()) { \ + error(5); \ + return error_result; \ + } \ + } while (0) + +#define OPTIONAL_GLUT(result) do { \ + if (!libqb_is_glut_up()) \ + return result; \ + } while (0) + +#endif diff --git a/internal/c/libqb/include/keyhandler.h b/internal/c/libqb/include/keyhandler.h new file mode 100644 index 000000000..4909c5ae8 --- /dev/null +++ b/internal/c/libqb/include/keyhandler.h @@ -0,0 +1,299 @@ +#ifndef INCLUDE_LIBQB_KEYHANDLER_h +#define INCLUDE_LIBQB_KEYHANDLER_h + +#include + +int32_t keyheld(uint32_t x); + +void keydown_vk(uint32_t key); +void keyup_vk(uint32_t key); + +#define QBK 200000 +#define VK 100000 +#define UC 1073741824 +/* QBK codes: + 200000-200010: Numpad keys with Num-Lock off + NO_NUMLOCK_KP0=INSERT + NO_NUMLOCK_KP1=END + NO_NUMLOCK_KP2=DOWN + NO_NUMLOCK_KP3=PGDOWN + NO_NUMLOCK_KP4... + NO_NUMLOCK_KP5 + NO_NUMLOCK_KP6 + NO_NUMLOCK_KP7 + NO_NUMLOCK_KP8 + NO_NUMLOCK_KP9 + NO_NUMLOCK_KP_PERIOD=DEL + 200011: SCROLL_LOCK_ON + 200012: INSERT_MODE_ON +*/ +#define QBK_SCROLL_LOCK_MODE 11 +#define QBK_INSERT_MODE 12 +#define QBK_CHR0 13 +typedef enum { + QBVK_UNKNOWN = 0, + QBVK_FIRST = 0, + QBVK_BACKSPACE = 8, + QBVK_TAB = 9, + QBVK_CLEAR = 12, + QBVK_RETURN = 13, + QBVK_PAUSE = 19, + QBVK_ESCAPE = 27, + QBVK_SPACE = 32, + QBVK_EXCLAIM = 33, + QBVK_QUOTEDBL = 34, + QBVK_HASH = 35, + QBVK_DOLLAR = 36, + QBVK_AMPERSAND = 38, + QBVK_QUOTE = 39, + QBVK_LEFTPAREN = 40, + QBVK_RIGHTPAREN = 41, + QBVK_ASTERISK = 42, + QBVK_PLUS = 43, + QBVK_COMMA = 44, + QBVK_MINUS = 45, + QBVK_PERIOD = 46, + QBVK_SLASH = 47, + QBVK_0 = 48, + QBVK_1 = 49, + QBVK_2 = 50, + QBVK_3 = 51, + QBVK_4 = 52, + QBVK_5 = 53, + QBVK_6 = 54, + QBVK_7 = 55, + QBVK_8 = 56, + QBVK_9 = 57, + QBVK_COLON = 58, + QBVK_SEMICOLON = 59, + QBVK_LESS = 60, + QBVK_EQUALS = 61, + QBVK_GREATER = 62, + QBVK_QUESTION = 63, + QBVK_AT = 64, + // Skip uppercase letters + QBVK_LEFTBRACKET = 91, + QBVK_BACKSLASH = 92, + QBVK_RIGHTBRACKET = 93, + QBVK_CARET = 94, + QBVK_UNDERSCORE = 95, + QBVK_BACKQUOTE = 96, + QBVK_a = 97, + QBVK_b = 98, + QBVK_c = 99, + QBVK_d = 100, + QBVK_e = 101, + QBVK_f = 102, + QBVK_g = 103, + QBVK_h = 104, + QBVK_i = 105, + QBVK_j = 106, + QBVK_k = 107, + QBVK_l = 108, + QBVK_m = 109, + QBVK_n = 110, + QBVK_o = 111, + QBVK_p = 112, + QBVK_q = 113, + QBVK_r = 114, + QBVK_s = 115, + QBVK_t = 116, + QBVK_u = 117, + QBVK_v = 118, + QBVK_w = 119, + QBVK_x = 120, + QBVK_y = 121, + QBVK_z = 122, + QBVK_DELETE = 127, + // End of ASCII mapped QBVKs + // International QBVKs + QBVK_WORLD_0 = 160, /* 0xA0 */ + QBVK_WORLD_1 = 161, + QBVK_WORLD_2 = 162, + QBVK_WORLD_3 = 163, + QBVK_WORLD_4 = 164, + QBVK_WORLD_5 = 165, + QBVK_WORLD_6 = 166, + QBVK_WORLD_7 = 167, + QBVK_WORLD_8 = 168, + QBVK_WORLD_9 = 169, + QBVK_WORLD_10 = 170, + QBVK_WORLD_11 = 171, + QBVK_WORLD_12 = 172, + QBVK_WORLD_13 = 173, + QBVK_WORLD_14 = 174, + QBVK_WORLD_15 = 175, + QBVK_WORLD_16 = 176, + QBVK_WORLD_17 = 177, + QBVK_WORLD_18 = 178, + QBVK_WORLD_19 = 179, + QBVK_WORLD_20 = 180, + QBVK_WORLD_21 = 181, + QBVK_WORLD_22 = 182, + QBVK_WORLD_23 = 183, + QBVK_WORLD_24 = 184, + QBVK_WORLD_25 = 185, + QBVK_WORLD_26 = 186, + QBVK_WORLD_27 = 187, + QBVK_WORLD_28 = 188, + QBVK_WORLD_29 = 189, + QBVK_WORLD_30 = 190, + QBVK_WORLD_31 = 191, + QBVK_WORLD_32 = 192, + QBVK_WORLD_33 = 193, + QBVK_WORLD_34 = 194, + QBVK_WORLD_35 = 195, + QBVK_WORLD_36 = 196, + QBVK_WORLD_37 = 197, + QBVK_WORLD_38 = 198, + QBVK_WORLD_39 = 199, + QBVK_WORLD_40 = 200, + QBVK_WORLD_41 = 201, + QBVK_WORLD_42 = 202, + QBVK_WORLD_43 = 203, + QBVK_WORLD_44 = 204, + QBVK_WORLD_45 = 205, + QBVK_WORLD_46 = 206, + QBVK_WORLD_47 = 207, + QBVK_WORLD_48 = 208, + QBVK_WORLD_49 = 209, + QBVK_WORLD_50 = 210, + QBVK_WORLD_51 = 211, + QBVK_WORLD_52 = 212, + QBVK_WORLD_53 = 213, + QBVK_WORLD_54 = 214, + QBVK_WORLD_55 = 215, + QBVK_WORLD_56 = 216, + QBVK_WORLD_57 = 217, + QBVK_WORLD_58 = 218, + QBVK_WORLD_59 = 219, + QBVK_WORLD_60 = 220, + QBVK_WORLD_61 = 221, + QBVK_WORLD_62 = 222, + QBVK_WORLD_63 = 223, + QBVK_WORLD_64 = 224, + QBVK_WORLD_65 = 225, + QBVK_WORLD_66 = 226, + QBVK_WORLD_67 = 227, + QBVK_WORLD_68 = 228, + QBVK_WORLD_69 = 229, + QBVK_WORLD_70 = 230, + QBVK_WORLD_71 = 231, + QBVK_WORLD_72 = 232, + QBVK_WORLD_73 = 233, + QBVK_WORLD_74 = 234, + QBVK_WORLD_75 = 235, + QBVK_WORLD_76 = 236, + QBVK_WORLD_77 = 237, + QBVK_WORLD_78 = 238, + QBVK_WORLD_79 = 239, + QBVK_WORLD_80 = 240, + QBVK_WORLD_81 = 241, + QBVK_WORLD_82 = 242, + QBVK_WORLD_83 = 243, + QBVK_WORLD_84 = 244, + QBVK_WORLD_85 = 245, + QBVK_WORLD_86 = 246, + QBVK_WORLD_87 = 247, + QBVK_WORLD_88 = 248, + QBVK_WORLD_89 = 249, + QBVK_WORLD_90 = 250, + QBVK_WORLD_91 = 251, + QBVK_WORLD_92 = 252, + QBVK_WORLD_93 = 253, + QBVK_WORLD_94 = 254, + QBVK_WORLD_95 = 255, /* 0xFF */ + // Numeric keypad + QBVK_KP0 = 256, + QBVK_KP1 = 257, + QBVK_KP2 = 258, + QBVK_KP3 = 259, + QBVK_KP4 = 260, + QBVK_KP5 = 261, + QBVK_KP6 = 262, + QBVK_KP7 = 263, + QBVK_KP8 = 264, + QBVK_KP9 = 265, + QBVK_KP_PERIOD = 266, + QBVK_KP_DIVIDE = 267, + QBVK_KP_MULTIPLY = 268, + QBVK_KP_MINUS = 269, + QBVK_KP_PLUS = 270, + QBVK_KP_ENTER = 271, + QBVK_KP_EQUALS = 272, + // Arrows + Home/End pad + QBVK_UP = 273, + QBVK_DOWN = 274, + QBVK_RIGHT = 275, + QBVK_LEFT = 276, + QBVK_INSERT = 277, + QBVK_HOME = 278, + QBVK_END = 279, + QBVK_PAGEUP = 280, + QBVK_PAGEDOWN = 281, + // Function keys + QBVK_F1 = 282, + QBVK_F2 = 283, + QBVK_F3 = 284, + QBVK_F4 = 285, + QBVK_F5 = 286, + QBVK_F6 = 287, + QBVK_F7 = 288, + QBVK_F8 = 289, + QBVK_F9 = 290, + QBVK_F10 = 291, + QBVK_F11 = 292, + QBVK_F12 = 293, + QBVK_F13 = 294, + QBVK_F14 = 295, + QBVK_F15 = 296, + // Key state modifier keys + QBVK_NUMLOCK = 300, + QBVK_CAPSLOCK = 301, + QBVK_SCROLLOCK = 302, + // If more modifiers are added, the window defocus code in qb64_os_event_linux must be altered + QBVK_RSHIFT = 303, + QBVK_LSHIFT = 304, + QBVK_RCTRL = 305, + QBVK_LCTRL = 306, + QBVK_RALT = 307, + QBVK_LALT = 308, + QBVK_RMETA = 309, + QBVK_LMETA = 310, + QBVK_LSUPER = 311, /* Left "Windows" key */ + QBVK_RSUPER = 312, /* Right "Windows" key */ + QBVK_MODE = 313, /* "Alt Gr" key */ + QBVK_COMPOSE = 314, /* Multi-key compose key */ + // Miscellaneous function keys + QBVK_HELP = 315, + QBVK_PRINT = 316, + QBVK_SYSREQ = 317, + QBVK_BREAK = 318, + QBVK_MENU = 319, + QBVK_POWER = 320, /* Power Macintosh power key */ + QBVK_EURO = 321, /* Some european keyboards */ + QBVK_UNDO = 322, /* Atari keyboard has Undo */ + QBVK_LAST +} QBVKs; +// Enumeration of valid key mods (possibly OR'd together) +typedef enum { + KMOD_NONE = 0x0000, + KMOD_LSHIFT = 0x0001, + KMOD_RSHIFT = 0x0002, + KMOD_LCTRL = 0x0040, + KMOD_RCTRL = 0x0080, + KMOD_LALT = 0x0100, + KMOD_RALT = 0x0200, + KMOD_LMETA = 0x0400, + KMOD_RMETA = 0x0800, + KMOD_NUM = 0x1000, + KMOD_CAPS = 0x2000, + KMOD_MODE = 0x4000, + KMOD_RESERVED = 0x8000 +} KMODs; +#define KMOD_CTRL (KMOD_LCTRL | KMOD_RCTRL) +#define KMOD_SHIFT (KMOD_LSHIFT | KMOD_RSHIFT) +#define KMOD_ALT (KMOD_LALT | KMOD_RALT) +#define KMOD_META (KMOD_LMETA | KMOD_RMETA) + +#endif diff --git a/internal/c/libqb/src/console-only-main-thread.cpp b/internal/c/libqb/src/console-only-main-thread.cpp new file mode 100644 index 000000000..fa737f556 --- /dev/null +++ b/internal/c/libqb/src/console-only-main-thread.cpp @@ -0,0 +1,72 @@ + +#include "libqb-common.h" + +#include +#include +#include +#include + +#include "glut-thread.h" + +// This file is for Console-Only programs. They never invoke GLUT so the setup +// here is much simpler. + +// FIXME: PUt this definition somewhere else +void MAIN_LOOP(void *); + + +void libqb_glut_presetup(int argc, char **argv) { + +} + +void libqb_start_main_thread(int argc, char **argv) { + // Because GLUT is not used, we can just run MAIN_LOOP without creating a + // new thread for it. + MAIN_LOOP(NULL); +} + +void libqb_start_glut_thread() { +} + +bool libqb_is_glut_up() { + return false; +} + +void libqb_process_glut_queue() { +} + +void libqb_glut_set_cursor(int style) { + +} + +void libqb_glut_warp_pointer(int x, int y) +{ +} + +int libqb_glut_get(int id) { + return 0; +} + +void libqb_glut_iconify_window() { +} + +void libqb_glut_position_window(int x, int y) { +} + +void libqb_glut_show_window() { +} + +void libqb_glut_hide_window() { +} + +void libqb_glut_set_window_title(const char *title) { +} + +void libqb_glut_exit_program(int exitcode) { + libqb_exit(exitcode); +} + +// Since there's no GLUT thread to deal with we can just exit() like normal +void libqb_exit(int code) { + exit(code); +} diff --git a/internal/c/libqb/src/glut-main-thread.cpp b/internal/c/libqb/src/glut-main-thread.cpp new file mode 100644 index 000000000..bd776cc93 --- /dev/null +++ b/internal/c/libqb/src/glut-main-thread.cpp @@ -0,0 +1,188 @@ + +#include "libqb-common.h" + +#include +#include +#include +#include +#include +#include +#include +#include "GL/glew.h" + +// note: MacOSX uses Apple's GLUT not FreeGLUT +#ifdef QB64_MACOSX +# include +#else +# define CORE_FREEGLUT +# include "freeglut.h" +#endif + +#include "mutex.h" +#include "thread.h" +#include "completion.h" +#include "gui.h" +#include "mac-key-monitor.h" +#include "glut-thread.h" + +// FIXME: These extern variable and function definitions should probably go +// somewhere more global so that they can be referenced by libqb.cpp +extern uint8_t *window_title; +extern int32_t framebufferobjects_supported; +extern int32_t screen_hide; + +void MAIN_LOOP(void *); +void GLUT_KEYBOARD_FUNC(unsigned char key, int x, int y); +void GLUT_DISPLAY_REQUEST(); +void GLUT_KEYBOARDUP_FUNC(unsigned char key, int x, int y); +void GLUT_SPECIAL_FUNC(int key, int x, int y); +void GLUT_SPECIALUP_FUNC(int key, int x, int y); +void GLUT_MOUSE_FUNC(int glut_button, int state, int x, int y); +void GLUT_MOTION_FUNC(int x, int y); +void GLUT_PASSIVEMOTION_FUNC(int x, int y); +void GLUT_RESHAPE_FUNC(int width, int height); + +#ifdef QB64_WINDOWS +void GLUT_TIMER_EVENT(int ignore); +#else +void GLUT_IDLEFUNC(); +#endif + +#ifdef CORE_FREEGLUT +void GLUT_MOUSEWHEEL_FUNC(int wheel, int direction, int x, int y); +#endif + +static void glutWarning(const char *fmt, va_list lst) { + // This keeps FreeGlut from dumping warnings to console +} + +// Performs all of the FreeGLUT initialization except for calling glutMainLoop() +static void initialize_glut(int argc, char **argv) { +# ifdef CORE_FREEGLUT + glutInitWarningFunc(glutWarning); + glutInitErrorFunc(glutWarning); +# endif + + glutInit(&argc, argv); + + mac_register_key_handler(); + +# ifdef QB64_WINDOWS + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); +# else + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); +# endif + + glutInitWindowSize(640, 400); // cannot be changed unless display_x(etc) are modified + + if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) // must be called on Linux or GLUT crashes + { + exit(1); + } + + if (!window_title) { + glutCreateWindow("Untitled"); + } else { + glutCreateWindow((char *)window_title); + } + + GLenum err = glewInit(); + if (GLEW_OK != err) { + gui_alert((char *)glewGetErrorString(err)); + } + + if (glewIsSupported("GL_EXT_framebuffer_object")) + framebufferobjects_supported = 1; + + glutDisplayFunc(GLUT_DISPLAY_REQUEST); + +# ifdef QB64_WINDOWS + glutTimerFunc(8, GLUT_TIMER_EVENT, 0); +# else + glutIdleFunc(GLUT_IDLEFUNC); +# endif + + glutKeyboardFunc(GLUT_KEYBOARD_FUNC); + glutKeyboardUpFunc(GLUT_KEYBOARDUP_FUNC); + glutSpecialFunc(GLUT_SPECIAL_FUNC); + glutSpecialUpFunc(GLUT_SPECIALUP_FUNC); + glutMouseFunc(GLUT_MOUSE_FUNC); + glutMotionFunc(GLUT_MOTION_FUNC); + glutPassiveMotionFunc(GLUT_PASSIVEMOTION_FUNC); + glutReshapeFunc(GLUT_RESHAPE_FUNC); + +# ifdef CORE_FREEGLUT + glutMouseWheelFunc(GLUT_MOUSEWHEEL_FUNC); +# endif +} + +static bool glut_is_started; +static struct completion glut_thread_starter; +static struct completion *glut_thread_initialized; + +void libqb_start_glut_thread() { + if (glut_is_started) + return; + + struct completion init; + completion_init(&init); + + glut_thread_initialized = &init; + + completion_finish(&glut_thread_starter); + + completion_wait(&init); + completion_clear(&init); +} + +// Checks whether the GLUT thread is running +bool libqb_is_glut_up() { + return glut_is_started; +} + +void libqb_glut_presetup(int argc, char **argv) { + if (!screen_hide) { + initialize_glut(argc, argv); // Initialize GLUT if the screen isn't hidden + glut_is_started = true; + } else { + completion_init(&glut_thread_starter); + } +} + +void libqb_start_main_thread(int argc, char **argv) { + + // Start the 'MAIN_LOOP' in a separate thread, as GLUT has to run on the + // initial thread. + struct libqb_thread *main_loop = libqb_thread_new(); + libqb_thread_start(main_loop, MAIN_LOOP, NULL); + + // This happens for $SCREENHIDE programs. This thread waits on the + // `glut_thread_starter` completion, which will get completed if a + // _ScreenShow is used. + if (!glut_is_started) { + completion_wait(&glut_thread_starter); + + initialize_glut(argc, argv); + glut_is_started = true; + + if (glut_thread_initialized) + completion_finish(glut_thread_initialized); + } + + glutMainLoop(); +} + +// Due to GLUT making use of cleanup via atexit, we have to call exit() from +// the same thread handling the GLUT logic so that the atexit handler also runs +// from that thread (not doing that can result in a segfault due to using GLUT +// from two threads at the same time). +// +// This is acomplished by simply queuing a GLUT message that calls exit() for us. +void libqb_exit(int exitcode) +{ + // If GLUT isn't running then we're free to do the exit() call from here + if (!libqb_is_glut_up()) + exit(exitcode); + + libqb_glut_exit_program(exitcode); +} diff --git a/internal/c/libqb/src/glut-message.cpp b/internal/c/libqb/src/glut-message.cpp new file mode 100644 index 000000000..1bfc115c2 --- /dev/null +++ b/internal/c/libqb/src/glut-message.cpp @@ -0,0 +1,54 @@ + +#include "libqb-common.h" + +#include +#include +#include +#include + +// note: MacOSX uses Apple's GLUT not FreeGLUT +#ifdef QB64_MACOSX +# include +#else +# define CORE_FREEGLUT +# include "freeglut.h" +#endif + +#include "glut-message.h" + +void glut_message_set_cursor::execute() { + glutSetCursor(style); +} + +void glut_message_warp_pointer::execute() { + glutWarpPointer(x, y); +} + +void glut_message_get::execute() { + response_value = glutGet(id); +} + +void glut_message_iconify_window::execute() { + glutIconifyWindow(); +} + +void glut_message_position_window::execute() { + glutPositionWindow(x, y); +} + +void glut_message_show_window::execute() { + glutShowWindow(); +} + +void glut_message_hide_window::execute() { + glutHideWindow(); +} + +void glut_message_set_window_title::execute() { + glutSetWindowTitle(newTitle); +} + +void glut_message_exit_program::execute() { + exit(exitCode); +} + diff --git a/internal/c/libqb/src/glut-message.h b/internal/c/libqb/src/glut-message.h new file mode 100644 index 000000000..c3c556740 --- /dev/null +++ b/internal/c/libqb/src/glut-message.h @@ -0,0 +1,133 @@ +#ifndef INCLUDE_LIBQB_GLUT_MESSAGE_H +#define INCLUDE_LIBQB_GLUT_MESSAGE_H + +#include +#include +#include +#include "completion.h" + +class glut_message { + private: + completion *finished = NULL; + + void initCompletion() { + finished = new completion(); + completion_init(finished); + } + + protected: + glut_message(bool withCompletion) { + if (withCompletion) + initCompletion(); + } + + public: + // Calling this indicates to the creator of the message that it has been + // completed, and any response data is availiable to be read. + // + // If `finsihed` is NULL that means nobody is waiting for the response. In + // that situation we're free to simply delete the object. + void finish() { + if (finished) + completion_finish(finished); + else + delete this; + } + + void wait_for_response() { + completion_wait(finished); + } + + virtual ~glut_message() { + if (finished) { + completion_wait(finished); // Should be a NOP, but better to check anyway + completion_clear(finished); + + delete finished; + } + } + + virtual void execute() = 0; +}; + +class glut_message_set_cursor : public glut_message { + public: + int style; + void execute(); + + glut_message_set_cursor(int _style) : glut_message(false), style(_style) { } +}; + +class glut_message_warp_pointer : public glut_message { + public: + int x, y; + void execute(); + + glut_message_warp_pointer(int _x, int _y) : glut_message(false), x(_x), y(_y) { } +}; + +class glut_message_get : public glut_message { + public: + int id; + int response_value; + void execute(); + + glut_message_get(int _id) : glut_message(true), id(_id), response_value(0) { } +}; + +class glut_message_iconify_window : public glut_message { + public: + void execute(); + + glut_message_iconify_window() : glut_message(false) { } +}; + +class glut_message_position_window : public glut_message { + public: + int x, y; + void execute(); + + glut_message_position_window(int _x, int _y) : glut_message(false), x(_x), y(_y) { } +}; + +class glut_message_show_window : public glut_message { + public: + void execute(); + + glut_message_show_window() : glut_message(false) { } +}; + +class glut_message_hide_window : public glut_message { + public: + void execute(); + + glut_message_hide_window() : glut_message(false) { } +}; + +class glut_message_set_window_title : public glut_message { + public: + char *newTitle; + void execute(); + + glut_message_set_window_title(const char *title) : glut_message(false) { + newTitle = strdup(title); + } + + virtual ~glut_message_set_window_title() { + free(newTitle); + } +}; + +class glut_message_exit_program : public glut_message { + public: + int exitCode; + void execute(); + + glut_message_exit_program(int _exitCode) : glut_message(true), exitCode(_exitCode) { } +}; + +// Queues a glut_message to be processed. Returns false if the message was not +// queued. +bool libqb_queue_glut_message(glut_message *msg); + +#endif diff --git a/internal/c/libqb/src/glut-msg-queue.cpp b/internal/c/libqb/src/glut-msg-queue.cpp new file mode 100644 index 000000000..8e5fe4291 --- /dev/null +++ b/internal/c/libqb/src/glut-msg-queue.cpp @@ -0,0 +1,137 @@ + +#include "libqb-common.h" + +#include +#include + +// note: MacOSX uses Apple's GLUT not FreeGLUT +#ifdef QB64_MACOSX +# include +#else +# define CORE_FREEGLUT +# include "freeglut.h" +#endif + +#include "mutex.h" +#include "glut-message.h" +#include "glut-thread.h" + +static libqb_mutex *glut_msg_queue_lock = libqb_mutex_new(); +static std::queue glut_msg_queue; + +// These values from GLUT are read on every process of the msg queue. Calls to +// libqb_glut_get() can then read from these values directly rather than wait +// for the GLUT thread to process the command. +static int glut_window_x, glut_window_y; + +#ifdef CORE_FREEGLUT +static int glut_window_border_width, glut_window_header_height; +#endif + +bool libqb_queue_glut_message(glut_message *msg) { + if (!libqb_is_glut_up()) { + msg->finish(); + return false; + } + + libqb_mutex_guard guard(glut_msg_queue_lock); + + glut_msg_queue.push(msg); + + return true; +} + +void libqb_process_glut_queue() { + libqb_mutex_guard guard(glut_msg_queue_lock); + + glut_window_x = glutGet(GLUT_WINDOW_X); + glut_window_y = glutGet(GLUT_WINDOW_Y); + +#ifdef CORE_FREEGLUT + glut_window_border_width = glutGet(GLUT_WINDOW_BORDER_WIDTH); + glut_window_header_height = glutGet(GLUT_WINDOW_HEADER_HEIGHT); +#endif + + while (!glut_msg_queue.empty()) { + glut_message *msg = glut_msg_queue.front(); + glut_msg_queue.pop(); + + msg->execute(); + + msg->finish(); + } +} + +void libqb_glut_set_cursor(int style) { + libqb_queue_glut_message(new glut_message_set_cursor(style)); +} + +void libqb_glut_warp_pointer(int x, int y) { + libqb_queue_glut_message(new glut_message_warp_pointer(x, y)); +} + +static bool is_static_glut_value(int id) { + return id == GLUT_WINDOW_Y + || id == GLUT_WINDOW_X +#ifdef CORE_FREEGLUT + || id == GLUT_WINDOW_BORDER_WIDTH + || id == GLUT_WINDOW_HEADER_HEIGHT +#endif + ; +} + +static int __get_static_glut_value(int id) { + switch (id) { + case GLUT_WINDOW_Y: return glut_window_y; + case GLUT_WINDOW_X: return glut_window_x; +#ifdef CORE_FREEGLUT + case GLUT_WINDOW_BORDER_WIDTH: return glut_window_border_width; + case GLUT_WINDOW_HEADER_HEIGHT: return glut_window_header_height; +#endif + default: return -1; + } +} + +int libqb_glut_get(int id) { + if (is_static_glut_value(id)) { + libqb_mutex_guard guard(glut_msg_queue_lock); + return __get_static_glut_value(id); + } + + glut_message_get msg(id); + + libqb_queue_glut_message(&msg); + msg.wait_for_response(); + + return msg.response_value; +} + +void libqb_glut_iconify_window() { + libqb_queue_glut_message(new glut_message_iconify_window()); +} + +void libqb_glut_position_window(int x, int y) { + libqb_queue_glut_message(new glut_message_position_window(x, y)); +} + +void libqb_glut_show_window() { + libqb_queue_glut_message(new glut_message_show_window()); +} + +void libqb_glut_hide_window() { + libqb_queue_glut_message(new glut_message_hide_window()); +} + +void libqb_glut_set_window_title(const char *title) { + libqb_queue_glut_message(new glut_message_set_window_title(title)); +} + +void libqb_glut_exit_program(int exitcode) { + glut_message_exit_program msg(exitcode); + + libqb_queue_glut_message(&msg); + msg.wait_for_response(); + + // Should never return + exit(exitcode); +} diff --git a/internal/c/libqb/src/mac-key-monitor.h b/internal/c/libqb/src/mac-key-monitor.h new file mode 100644 index 000000000..b6f20581b --- /dev/null +++ b/internal/c/libqb/src/mac-key-monitor.h @@ -0,0 +1,10 @@ +#ifndef INCLUDE_INTERNAL_MAC_KEY_MONITOR_H +#define INCLUDE_INTERNAL_MAC_KEY_MONITOR_H + +#ifdef QB64_MACOSX +void mac_register_key_handler(); +#else +static inline void mac_register_key_handler() { }; +#endif + +#endif diff --git a/internal/c/libqb/src/mac-key-monitor.mm b/internal/c/libqb/src/mac-key-monitor.mm new file mode 100644 index 000000000..0e6987ebb --- /dev/null +++ b/internal/c/libqb/src/mac-key-monitor.mm @@ -0,0 +1,85 @@ + +#include "libqb-common.h" + +#include +#include +#include +#include + +#include "Cocoa/Cocoa.h" +#include + +#include "keyhandler.h" +#include "mac-key-monitor.h" + +void mac_register_key_handler() +{ + [NSEvent addLocalMonitorForEventsMatchingMask:NSFlagsChangedMask + handler:^NSEvent *(NSEvent *event) { + // notes on bitfields: + // if ([event modifierFlags] == 131330) keydown_vk(VK+QBVK_LSHIFT);// 100000000100000010 + // if ([event modifierFlags] == 131332) keydown_vk(VK+QBVK_RSHIFT);// 100000000100000100 + // if ([event modifierFlags] == 262401) keydown_vk(VK+QBVK_LCTRL); //1000000000100000001 + // if ([event modifierFlags] == 270592) keydown_vk(VK+QBVK_RCTRL); //1000010000100000000 + // if ([event modifierFlags] == 524576) keydown_vk(VK+QBVK_LALT); //10000000000100100000 + // if ([event modifierFlags] == 524608) keydown_vk(VK+QBVK_RALT); //10000000000101000000 + // caps lock // 10000000100000000 + + int x = [event modifierFlags]; + + if (x & (1 << 0)) { + if (!keyheld(VK + QBVK_LCTRL)) + keydown_vk(VK + QBVK_LCTRL); + } else { + if (keyheld(VK + QBVK_LCTRL)) + keyup_vk(VK + QBVK_LCTRL); + } + if (x & (1 << 13)) { + if (!keyheld(VK + QBVK_RCTRL)) + keydown_vk(VK + QBVK_RCTRL); + } else { + if (keyheld(VK + QBVK_RCTRL)) + keyup_vk(VK + QBVK_RCTRL); + } + + if (x & (1 << 1)) { + if (!keyheld(VK + QBVK_LSHIFT)) + keydown_vk(VK + QBVK_LSHIFT); + } else { + if (keyheld(VK + QBVK_LSHIFT)) + keyup_vk(VK + QBVK_LSHIFT); + } + if (x & (1 << 2)) { + if (!keyheld(VK + QBVK_RSHIFT)) + keydown_vk(VK + QBVK_RSHIFT); + } else { + if (keyheld(VK + QBVK_RSHIFT)) + keyup_vk(VK + QBVK_RSHIFT); + } + + if (x & (1 << 5)) { + if (!keyheld(VK + QBVK_LALT)) + keydown_vk(VK + QBVK_LALT); + } else { + if (keyheld(VK + QBVK_LALT)) + keyup_vk(VK + QBVK_LALT); + } + if (x & (1 << 6)) { + if (!keyheld(VK + QBVK_RALT)) + keydown_vk(VK + QBVK_RALT); + } else { + if (keyheld(VK + QBVK_RALT)) + keyup_vk(VK + QBVK_RALT); + } + + if (x & (1 << 16)) { + if (!keyheld(VK + QBVK_CAPSLOCK)) + keydown_vk(VK + QBVK_CAPSLOCK); + } else { + if (keyheld(VK + QBVK_CAPSLOCK)) + keyup_vk(VK + QBVK_CAPSLOCK); + } + + return event; + }]; +} diff --git a/internal/c/parts/core/build.mk b/internal/c/parts/core/build.mk index 6a7cc2b05..6a8e9b765 100644 --- a/internal/c/parts/core/build.mk +++ b/internal/c/parts/core/build.mk @@ -12,5 +12,7 @@ $(FREEGLUT_LIB): $(FREEGLUT_OBJS) QB_CORE_LIB := $(FREEGLUT_LIB) +CXXFLAGS += -I$(PATH_INTERNAL_C)/parts/core/src/ -I$(PATH_INTERNAL_C)/parts/core/glew/include/ + CLEAN_LIST += $(FREEGLUT_LIB) $(FREEGLUT_OBJS) diff --git a/tests/compile_tests.sh b/tests/compile_tests.sh index 6746289dd..ed05cf59e 100755 --- a/tests/compile_tests.sh +++ b/tests/compile_tests.sh @@ -32,6 +32,12 @@ show_incorrect_result() # This is either win, lnx, or osx OS=$CI_OS +# On Linux, we make use of xvfb-run to provide each test with a framebuffer +# based X server, which allows graphics to work. +if [ "$OS" == "lnx" ]; then + LNX_PREFIX=xvfb-run +fi + # Each .bas file represents a separate test. while IFS= read -r test do @@ -107,7 +113,7 @@ do pushd . > /dev/null cd "./tests/compile_tests/$category" - testResult=$("../../../$EXE" "../../../$RESULTS_DIR" "$category-$testName" 2>&1) + testResult=$($LNX_PREFIX "../../../$EXE" "../../../$RESULTS_DIR" "$category-$testName" 2>&1) ERR=$? popd > /dev/null diff --git a/tests/compile_tests/glut/README.md b/tests/compile_tests/glut/README.md new file mode 100644 index 000000000..a8fa9e9f5 --- /dev/null +++ b/tests/compile_tests/glut/README.md @@ -0,0 +1,6 @@ +Glut +==== + +These tests cover the initialization of GLUT, and verify that even when these +statements which make use of GLUT are the first thing in the program they still +execute correctly. diff --git a/tests/compile_tests/glut/desktopheight.bas b/tests/compile_tests/glut/desktopheight.bas new file mode 100644 index 000000000..05c2419cc --- /dev/null +++ b/tests/compile_tests/glut/desktopheight.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print _DesktopHeight > 0 +System diff --git a/tests/compile_tests/glut/desktopheight.output b/tests/compile_tests/glut/desktopheight.output new file mode 100644 index 000000000..30610d132 --- /dev/null +++ b/tests/compile_tests/glut/desktopheight.output @@ -0,0 +1 @@ +-1 diff --git a/tests/compile_tests/glut/desktopwidth.bas b/tests/compile_tests/glut/desktopwidth.bas new file mode 100644 index 000000000..4c92785a0 --- /dev/null +++ b/tests/compile_tests/glut/desktopwidth.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print _DesktopWidth > 0 +System diff --git a/tests/compile_tests/glut/desktopwidth.output b/tests/compile_tests/glut/desktopwidth.output new file mode 100644 index 000000000..30610d132 --- /dev/null +++ b/tests/compile_tests/glut/desktopwidth.output @@ -0,0 +1 @@ +-1 diff --git a/tests/compile_tests/glut/icon.bas b/tests/compile_tests/glut/icon.bas new file mode 100644 index 000000000..1d78af21c --- /dev/null +++ b/tests/compile_tests/glut/icon.bas @@ -0,0 +1,6 @@ +$CONSOLE +_Dest _Console + +_Icon +Print "Got Past Icon!" +System diff --git a/tests/compile_tests/glut/icon.output b/tests/compile_tests/glut/icon.output new file mode 100644 index 000000000..d1596b35b --- /dev/null +++ b/tests/compile_tests/glut/icon.output @@ -0,0 +1 @@ +Got Past Icon! diff --git a/tests/compile_tests/glut/mousehide.bas b/tests/compile_tests/glut/mousehide.bas new file mode 100644 index 000000000..e18e388a4 --- /dev/null +++ b/tests/compile_tests/glut/mousehide.bas @@ -0,0 +1,6 @@ +$CONSOLE +_Dest _Console + +_MouseHide +Print "Got Past MouseHide!" +System diff --git a/tests/compile_tests/glut/mousehide.output b/tests/compile_tests/glut/mousehide.output new file mode 100644 index 000000000..deecf500d --- /dev/null +++ b/tests/compile_tests/glut/mousehide.output @@ -0,0 +1 @@ +Got Past MouseHide! diff --git a/tests/compile_tests/glut/mouseshow.bas b/tests/compile_tests/glut/mouseshow.bas new file mode 100644 index 000000000..f97d5f667 --- /dev/null +++ b/tests/compile_tests/glut/mouseshow.bas @@ -0,0 +1,6 @@ +$CONSOLE +_Dest _Console + +_MouseShow +Print "Got Past MouseShow!" +System diff --git a/tests/compile_tests/glut/mouseshow.output b/tests/compile_tests/glut/mouseshow.output new file mode 100644 index 000000000..8dda79e92 --- /dev/null +++ b/tests/compile_tests/glut/mouseshow.output @@ -0,0 +1 @@ +Got Past MouseShow! diff --git a/tests/compile_tests/glut/qb64pe.ico b/tests/compile_tests/glut/qb64pe.ico new file mode 100644 index 000000000..541e29c47 Binary files /dev/null and b/tests/compile_tests/glut/qb64pe.ico differ diff --git a/tests/compile_tests/glut/screenexists.bas b/tests/compile_tests/glut/screenexists.bas new file mode 100644 index 000000000..1f6a7ff74 --- /dev/null +++ b/tests/compile_tests/glut/screenexists.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print _ScreenExists +System diff --git a/tests/compile_tests/glut/screenexists.output b/tests/compile_tests/glut/screenexists.output new file mode 100644 index 000000000..33c4d9955 --- /dev/null +++ b/tests/compile_tests/glut/screenexists.output @@ -0,0 +1 @@ + 1 diff --git a/tests/compile_tests/glut/screenhide.bas b/tests/compile_tests/glut/screenhide.bas new file mode 100644 index 000000000..e7b63e601 --- /dev/null +++ b/tests/compile_tests/glut/screenhide.bas @@ -0,0 +1,6 @@ +$CONSOLE +_Dest _Console + +_ScreenHide +Print "Got Past ScreenHide!" +System diff --git a/tests/compile_tests/glut/screenhide.output b/tests/compile_tests/glut/screenhide.output new file mode 100644 index 000000000..900901875 --- /dev/null +++ b/tests/compile_tests/glut/screenhide.output @@ -0,0 +1 @@ +Got Past ScreenHide! diff --git a/tests/compile_tests/glut/screenhide_commands.bas b/tests/compile_tests/glut/screenhide_commands.bas new file mode 100644 index 000000000..6bb92b3c9 --- /dev/null +++ b/tests/compile_tests/glut/screenhide_commands.bas @@ -0,0 +1,58 @@ +$SCREENHIDE +$CONSOLE +_Dest _Console +ON ERROR GOTO errorhand + +$IF WIN THEN +Print _DesktopHeight > 0 +$ELSE +Print _DesktopHeight = 0 +$END IF + +$IF WIN THEN +Print _DesktopWidth > 0 +$ELSE +Print _DesktopWidth = 0 +$END IF + +_Icon +Print "Got past icon!" + +_MouseHide +Print "Got past MouseHide!" + +_MouseShow +Print "Got past MouseHide!" + +Print _ScreenExists + +_ScreenHide +Print "Got past ScreenHide" + +Print _ScreenIcon <> 0 + +$IF LINUX THEN +' Since these functions don't work on linux they also don't trigger errors +' We're just printing the error manually so the test passes on Linux +Print "Error:"; 5 +Print "Error:"; 5 +$ELSE +Print _ScreenX >= 0 +Print _ScreenY >= 0 +$END IF + +_Title "foobar" +Print "Title: "; _Title$ + +Print _WindowHandle <> 0 +Print _WindowHasFocus <= 0 ' This can be a bit random + +_ScreenShow +Print "Got past ScreenShow!" +System + +System + +errorhand: +PRINT "Error:"; ERR +RESUME NEXT diff --git a/tests/compile_tests/glut/screenhide_commands.output b/tests/compile_tests/glut/screenhide_commands.output new file mode 100644 index 000000000..900b089e8 --- /dev/null +++ b/tests/compile_tests/glut/screenhide_commands.output @@ -0,0 +1,14 @@ +-1 +-1 +Got past icon! +Got past MouseHide! +Got past MouseHide! + 0 +Got past ScreenHide + 0 +Error: 5 +Error: 5 +Title: foobar + 0 +-1 +Got past ScreenShow! diff --git a/tests/compile_tests/glut/screenhide_sub.bas b/tests/compile_tests/glut/screenhide_sub.bas new file mode 100644 index 000000000..7a37532fd --- /dev/null +++ b/tests/compile_tests/glut/screenhide_sub.bas @@ -0,0 +1,30 @@ +$CONSOLE +_Dest _Console + +_ScreenHide +Print _DesktopHeight > 0 +Print _DesktopWidth > 0 +_Icon +Print "Got Past Icon!" +_MouseHide +Print "Got Past MouseHide!" +_MouseShow +Print "Got Past MouseShow!" +Print _ScreenExists +Print _ScreenIcon <> 0 +Print _ScreenX >= 0 +Print _ScreenY >= 0 +_Title "foobar" +Print "Title: "; _Title$ + +$IF WIN THEN +Print _WindowHandle <> 0 +$ELSE +Print _WindowHandle = 0 +$END IF + +Print _WindowHasFocus <= 0 ' This can be a bit random + +_ScreenShow +Print "Got past ScreenShow!" +System diff --git a/tests/compile_tests/glut/screenhide_sub.output b/tests/compile_tests/glut/screenhide_sub.output new file mode 100644 index 000000000..617884d16 --- /dev/null +++ b/tests/compile_tests/glut/screenhide_sub.output @@ -0,0 +1,13 @@ +-1 +-1 +Got Past Icon! +Got Past MouseHide! +Got Past MouseShow! + 1 + 0 +-1 +-1 +Title: foobar +-1 +-1 +Got past ScreenShow! diff --git a/tests/compile_tests/glut/screenicon.bas b/tests/compile_tests/glut/screenicon.bas new file mode 100644 index 000000000..91af25c26 --- /dev/null +++ b/tests/compile_tests/glut/screenicon.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print _ScreenIcon <> 0 +System diff --git a/tests/compile_tests/glut/screenicon.output b/tests/compile_tests/glut/screenicon.output new file mode 100644 index 000000000..cff180f6c --- /dev/null +++ b/tests/compile_tests/glut/screenicon.output @@ -0,0 +1 @@ + 0 diff --git a/tests/compile_tests/glut/screenshow.bas b/tests/compile_tests/glut/screenshow.bas new file mode 100644 index 000000000..8f38b48cc --- /dev/null +++ b/tests/compile_tests/glut/screenshow.bas @@ -0,0 +1,6 @@ +$CONSOLE +_Dest _Console + +_ScreenShow +Print "Got past ScreenShow!" +System diff --git a/tests/compile_tests/glut/screenshow.output b/tests/compile_tests/glut/screenshow.output new file mode 100644 index 000000000..a06faccc5 --- /dev/null +++ b/tests/compile_tests/glut/screenshow.output @@ -0,0 +1 @@ +Got past ScreenShow! diff --git a/tests/compile_tests/glut/screenx.bas b/tests/compile_tests/glut/screenx.bas new file mode 100644 index 000000000..86f2eba6b --- /dev/null +++ b/tests/compile_tests/glut/screenx.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print _ScreenX >= 0 +System diff --git a/tests/compile_tests/glut/screenx.output b/tests/compile_tests/glut/screenx.output new file mode 100644 index 000000000..30610d132 --- /dev/null +++ b/tests/compile_tests/glut/screenx.output @@ -0,0 +1 @@ +-1 diff --git a/tests/compile_tests/glut/screeny.bas b/tests/compile_tests/glut/screeny.bas new file mode 100644 index 000000000..0b4cc8186 --- /dev/null +++ b/tests/compile_tests/glut/screeny.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print _ScreenY >= 0 +System diff --git a/tests/compile_tests/glut/screeny.output b/tests/compile_tests/glut/screeny.output new file mode 100644 index 000000000..30610d132 --- /dev/null +++ b/tests/compile_tests/glut/screeny.output @@ -0,0 +1 @@ +-1 diff --git a/tests/compile_tests/glut/title.bas b/tests/compile_tests/glut/title.bas new file mode 100644 index 000000000..b17ef2ea9 --- /dev/null +++ b/tests/compile_tests/glut/title.bas @@ -0,0 +1,6 @@ +$CONSOLE +_Dest _Console + +_Title "foobar" +Print "Got past Title!" +System diff --git a/tests/compile_tests/glut/title.output b/tests/compile_tests/glut/title.output new file mode 100644 index 000000000..58c08ff4d --- /dev/null +++ b/tests/compile_tests/glut/title.output @@ -0,0 +1 @@ +Got past Title! diff --git a/tests/compile_tests/glut/title_func.bas b/tests/compile_tests/glut/title_func.bas new file mode 100644 index 000000000..867ab3bca --- /dev/null +++ b/tests/compile_tests/glut/title_func.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print "Title: "; _Title$ +System diff --git a/tests/compile_tests/glut/title_func.output b/tests/compile_tests/glut/title_func.output new file mode 100644 index 000000000..04eb51c01 --- /dev/null +++ b/tests/compile_tests/glut/title_func.output @@ -0,0 +1 @@ +Title: diff --git a/tests/compile_tests/glut/windowhandle.bas b/tests/compile_tests/glut/windowhandle.bas new file mode 100644 index 000000000..d94f9dfca --- /dev/null +++ b/tests/compile_tests/glut/windowhandle.bas @@ -0,0 +1,11 @@ +$CONSOLE +_Dest _Console + +' _WindowHandle only returns an actual handle on Windows +$IF WIN THEN +Print _WindowHandle <> 0 +$ELSE +Print _WindowHandle = 0 +$END IF + +System diff --git a/tests/compile_tests/glut/windowhandle.output b/tests/compile_tests/glut/windowhandle.output new file mode 100644 index 000000000..30610d132 --- /dev/null +++ b/tests/compile_tests/glut/windowhandle.output @@ -0,0 +1 @@ +-1 diff --git a/tests/compile_tests/glut/windowhasfocus.bas b/tests/compile_tests/glut/windowhasfocus.bas new file mode 100644 index 000000000..1c3f2de03 --- /dev/null +++ b/tests/compile_tests/glut/windowhasfocus.bas @@ -0,0 +1,5 @@ +$CONSOLE +_Dest _Console + +Print _WindowHasFocus <= 0 ' This can be a bit random +System diff --git a/tests/compile_tests/glut/windowhasfocus.output b/tests/compile_tests/glut/windowhasfocus.output new file mode 100644 index 000000000..30610d132 --- /dev/null +++ b/tests/compile_tests/glut/windowhasfocus.output @@ -0,0 +1 @@ +-1