Merge branch 'remove-sdl'

This commit is contained in:
Josh Holtrop 2017-10-18 12:26:08 -04:00
commit a509c4bded
17 changed files with 1073 additions and 259 deletions

View File

@ -170,6 +170,8 @@ bool BufferView::cursor_move(CursorMovement which, bool allow_eol)
{
case CursorMovement::LEFT:
case CursorMovement::RIGHT:
case CursorMovement::SCREEN_ROW_UP:
case CursorMovement::SCREEN_ROW_DOWN:
determine_new_cursor_screen_row();
break;
case CursorMovement::UP:

View File

@ -201,8 +201,8 @@ void BufferPane::draw_buffer_character(uint32_t character, int screen_row, int s
m_window->gl()->draw_rect(win_x(x + 2), win_y(y),
m_window->font()->get_advance() * 2 - 4, 1,
0, 0.7, 1.0, 1.0);
m_window->gl()->draw_character(win_x(x), win_y(y), '^', *m_window->font(), 1.0, 1.0, 1.0, 1.0);
m_window->gl()->draw_character(win_x(col_x(screen_column + 1)), win_y(y), character | 0x40u, *m_window->font(), 1.0, 1.0, 1.0, 1.0);
m_window->gl()->draw_character(win_x(x), win_y(y), '^', *m_window->font(), 0.0, 0.7, 1.0, 1.0);
m_window->gl()->draw_character(win_x(col_x(screen_column + 1)), win_y(y), character | 0x40u, *m_window->font(), 0.0, 0.7, 1.0, 1.0);
}
else
{

View File

@ -4,44 +4,16 @@
#include "BufferPane.h"
#include <iostream>
#include "jes_icon-32x32.h"
#include <unistd.h>
#include <unordered_map>
#define INITIAL_WIDTH 800
#define INITIAL_HEIGHT 800
#define FONT_SIZE 16
struct
{
SDL_TimerID timer_id;
SDL_Keycode keysym;
bool pressed;
bool event_pending;
} Key_Statuses[SDL_NUM_SCANCODES];
/**
* Initialize SDL.
*
* @retval true SDL was loaded successfully.
* @retval false Loading SDL failed.
*/
static bool Initialize_SDL()
{
static bool initialized = false;
if (initialized)
{
return true;
}
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
{
return false;
}
atexit(SDL_Quit);
initialized = true;
return true;
}
/* Process multiple queued events for up to this long before stopping to
* redraw the screen. */
#define MAX_EVENT_PROCESS_TIME 50000
/**
* Initialize OpenGL.
@ -80,6 +52,7 @@ static bool Initialize_OpenGL()
return true;
}
#if 0
void Window::set_window_icon()
{
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom((void *)jes_icon_32x32, 32, 32, 24, 32 * 3, 0xFF0000u, 0xFF00u, 0xFFu, 0u);
@ -88,6 +61,7 @@ void Window::set_window_icon()
SDL_FreeSurface(surface);
}
#endif
/**
* Create a Window.
@ -97,28 +71,23 @@ void Window::set_window_icon()
*/
bool Window::create(std::shared_ptr<Buffer> buffer)
{
if (!Initialize_SDL())
if (!Jtk_Init())
{
std::cerr << "Error initializing SDL" << std::endl;
std::cerr << "Error initializing GUI" << std::endl;
return false;
}
m_window = SDL_CreateWindow(
APPNAME,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
INITIAL_WIDTH,
INITIAL_HEIGHT,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
m_window = Jtk_CreateWindow();
if (m_window == NULL)
{
std::cerr << "Error creating SDL window" << std::endl;
std::cerr << "Error creating window" << std::endl;
return false;
}
Jtk_SetWindowTitle(m_window, "jes");
#if 0
set_window_icon();
(void)SDL_GL_CreateContext(m_window);
#endif
if (!Initialize_OpenGL())
{
@ -157,7 +126,9 @@ bool Window::create(std::shared_ptr<Buffer> buffer)
m_command_buffer_pane->set_command_mode();
m_command_buffer_screen_rows = 1;
resize();
resize(INITIAL_WIDTH, INITIAL_HEIGHT);
m_redraw_requested = true;
return true;
}
@ -169,76 +140,60 @@ bool Window::create(std::shared_ptr<Buffer> buffer)
*/
void Window::run_event_loop()
{
SDL_Event event;
Jtk_Event event;
while ((!m_exit_requested) && SDL_WaitEvent(&event))
while (!m_exit_requested)
{
handle_event(event);
if (m_redraw_requested)
{
m_redraw_requested = false;
redraw();
}
}
}
Uint32 Key_Repeat(Uint32 interval, void * param)
{
if (Key_Statuses[(uintptr_t)param].pressed)
Jtk_WaitEvent(&event);
uint64_t event_time = Jtk_UsTime();
handle_event(event);
while (Jtk_CheckEvent(&event) &&
((Jtk_UsTime() - event_time) < MAX_EVENT_PROCESS_TIME))
{
if (!Key_Statuses[(uintptr_t)param].event_pending)
{
SDL_Event event;
event.user.code = 0;
event.user.data1 = (void *)(uintptr_t)Key_Statuses[(uintptr_t)param].keysym;
event.user.data2 = param;
event.type = SDL_USEREVENT;
SDL_PushEvent(&event);
Key_Statuses[(uintptr_t)param].event_pending = true;
handle_event(event);
}
return 25u;
}
else
{
return 0u;
}
}
/**
* Handle a SDL event.
* Handle a Jtk event.
*/
void Window::handle_event(SDL_Event & event)
void Window::handle_event(Jtk_Event & event)
{
switch (event.type)
{
#if 0
case SDL_QUIT:
m_exit_requested = true;
break;
#endif
case SDL_KEYDOWN:
m_keymod = event.key.keysym.mod;
if (event.key.repeat == 0)
case JTK_EVENT_KEY_PRESS:
#if 0
if (!event.key.repeat)
{
Key_Statuses[event.key.keysym.scancode].pressed = true;
Key_Statuses[event.key.keysym.scancode].keysym = event.key.keysym.sym;
Key_Statuses[event.key.keysym.scancode].timer_id = SDL_AddTimer(300, Key_Repeat, (void *)event.key.keysym.scancode);
handle_keysym(event.key.keysym.sym);
Jtk_BeginKeyRepeat(&event.key, 300u, 25u);
}
#endif
handle_keypress(event.key.key);
m_redraw_requested = true;
break;
case SDL_KEYUP:
m_keymod = event.key.keysym.mod;
Key_Statuses[event.key.keysym.scancode].pressed = false;
if (Key_Statuses[event.key.keysym.scancode].timer_id != 0)
{
SDL_RemoveTimer(Key_Statuses[event.key.keysym.scancode].timer_id);
Key_Statuses[event.key.keysym.scancode].timer_id = 0;
}
case JTK_EVENT_WINDOW_EXPOSE:
m_redraw_requested = true;
break;
case JTK_EVENT_WINDOW_RESIZE:
resize(event.resize.width, event.resize.height);
m_redraw_requested = true;
break;
#if 0
case SDL_WINDOWEVENT:
switch (event.window.event)
{
@ -251,18 +206,14 @@ void Window::handle_event(SDL_Event & event)
break;
}
break;
#endif
case SDL_USEREVENT:
Key_Statuses[(uintptr_t)event.user.data2].event_pending = false;
handle_keysym((uint32_t)(uintptr_t)event.user.data1);
break;
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0)
case JTK_EVENT_BUTTON_PRESS:
if (event.button.button == 4)
{
m_focused_buffer_pane->scroll_window_up(ScrollMode::WHEEL);
}
else
else if (event.button.button == 5)
{
m_focused_buffer_pane->scroll_window_down(ScrollMode::WHEEL);
}
@ -270,43 +221,39 @@ void Window::handle_event(SDL_Event & event)
}
}
void Window::handle_keysym(uint32_t keysym)
void Window::handle_keypress(uint32_t keyval)
{
handle_keyval(get_keyval(keysym));
}
void Window::handle_keyval(uint32_t keyval)
{
switch (keyval)
uint32_t keycode = keyval & JTK_KEY_KEYCODE_MASK;
switch (keyval & (JTK_KEY_KEYCODE_MASK | JTK_KEY_MODS_CTRL))
{
case SDLK_HOME:
case JTK_KEY_HOME:
m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::SOL);
break;
case SDLK_END:
case JTK_KEY_END:
m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::EOL);
break;
case SDLK_RIGHT:
case JTK_KEY_RIGHT:
m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::RIGHT);
break;
case SDLK_LEFT:
case JTK_KEY_LEFT:
m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::LEFT);
break;
case SDLK_DOWN:
case JTK_KEY_DOWN:
m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::DOWN);
break;
case SDLK_UP:
case JTK_KEY_UP:
m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::UP);
break;
case SDLK_PAGEUP:
case JTK_KEY_PAGE_UP:
m_focused_buffer_pane->scroll_window_up(ScrollMode::WHOLE_SCREEN);
break;
case SDLK_PAGEDOWN:
case JTK_KEY_PAGE_DOWN:
m_focused_buffer_pane->scroll_window_down(ScrollMode::WHOLE_SCREEN);
break;
default:
if (m_focused_buffer_pane->insert_mode())
{
if (keyval == '\033')
if (keycode == '\033')
{
if (m_focused_buffer_pane == m_command_buffer_pane)
{
@ -319,9 +266,9 @@ void Window::handle_keyval(uint32_t keyval)
m_focused_buffer_pane->exit_insert_mode();
}
}
else if (keyval < 0xFFu)
else if (keycode < 0xFFu)
{
if ((keyval == '\n') && (m_focused_buffer_pane == m_command_buffer_pane))
if ((keycode == '\n') && (m_focused_buffer_pane == m_command_buffer_pane))
{
EncodedString command = m_command_buffer->get_string();
m_command_buffer_pane->clear();
@ -331,13 +278,13 @@ void Window::handle_keyval(uint32_t keyval)
}
else
{
m_focused_buffer_pane->insert_code_point(keyval);
m_focused_buffer_pane->insert_code_point(keycode);
}
}
}
else
{
switch (keyval)
switch (keyval & (JTK_KEY_KEYCODE_MASK | JTK_KEY_MODS_CTRL))
{
case '0':
m_focused_buffer_pane->cursor_move(BufferPane::CursorMovement::SOL);
@ -400,22 +347,22 @@ void Window::handle_keyval(uint32_t keyval)
case 'x':
m_focused_buffer_pane->kill_character_at_cursor();
break;
case Keymod::CTRL + 'b':
case JTK_KEY_MODS_CTRL + 'b':
m_focused_buffer_pane->scroll_window_up(ScrollMode::WHOLE_SCREEN);
break;
case Keymod::CTRL + 'd':
case JTK_KEY_MODS_CTRL + 'd':
m_focused_buffer_pane->scroll_window_down(ScrollMode::HALF_SCREEN);
break;
case Keymod::CTRL + 'e':
case JTK_KEY_MODS_CTRL + 'e':
m_focused_buffer_pane->scroll_window_down(ScrollMode::ONE_LINE);
break;
case Keymod::CTRL + 'f':
case JTK_KEY_MODS_CTRL + 'f':
m_focused_buffer_pane->scroll_window_down(ScrollMode::WHOLE_SCREEN);
break;
case Keymod::CTRL + 'u':
case JTK_KEY_MODS_CTRL + 'u':
m_focused_buffer_pane->scroll_window_up(ScrollMode::HALF_SCREEN);
break;
case Keymod::CTRL + 'y':
case JTK_KEY_MODS_CTRL + 'y':
m_focused_buffer_pane->scroll_window_up(ScrollMode::ONE_LINE);
break;
}
@ -424,9 +371,10 @@ void Window::handle_keyval(uint32_t keyval)
}
}
void Window::resize()
void Window::resize(size_t width, size_t height)
{
SDL_GetWindowSize(m_window, &m_width, &m_height);
m_width = width;
m_height = height;
glViewport(0, 0, m_width, m_height);
m_gl->resize(m_width, m_height);
int command_buffer_height = m_command_buffer_screen_rows * m_font->get_line_height();
@ -443,7 +391,7 @@ void Window::redraw()
m_command_buffer_screen_rows = 1;
if (m_command_buffer_screen_rows != last_command_buffer_screen_rows)
{
resize();
resize(m_width, m_height);
}
last_command_buffer_screen_rows = m_command_buffer_screen_rows;
@ -453,112 +401,7 @@ void Window::redraw()
m_gl->draw_rect(0, m_command_buffer_screen_rows * m_font->get_line_height(), m_width, 1, 0.5, 0.5, 0.5, 1.0);
m_command_buffer_pane->draw();
SDL_GL_SwapWindow(m_window);
}
uint32_t Window::get_keyval(SDL_Keycode keysym)
{
uint32_t keyval = keysym;
if ((m_keymod & (KMOD_SHIFT | KMOD_CAPS)) != 0u)
{
uint32_t shifted = get_shifted(keyval);
if (shifted != 0u)
{
keyval = shifted;
}
else
{
keyval |= Keymod::SHIFT;
}
}
switch (keyval)
{
case SDLK_RETURN: keyval = '\n'; break;
case SDLK_KP_DIVIDE: keyval = '/'; break;
case SDLK_KP_MULTIPLY: keyval = '*'; break;
case SDLK_KP_MINUS: keyval = '-'; break;
case SDLK_KP_PLUS: keyval = '+'; break;
case SDLK_KP_ENTER: keyval = '\n'; break;
case SDLK_KP_1: keyval = '1'; break;
case SDLK_KP_2: keyval = '2'; break;
case SDLK_KP_3: keyval = '3'; break;
case SDLK_KP_4: keyval = '4'; break;
case SDLK_KP_5: keyval = '5'; break;
case SDLK_KP_6: keyval = '6'; break;
case SDLK_KP_7: keyval = '7'; break;
case SDLK_KP_8: keyval = '8'; break;
case SDLK_KP_9: keyval = '9'; break;
case SDLK_KP_0: keyval = '0'; break;
case SDLK_KP_PERIOD: keyval = '.'; break;
case SDLK_KP_EQUALS: keyval = '='; break;
case SDLK_KP_COMMA: keyval = ','; break;
case SDLK_KP_LEFTPAREN: keyval = '('; break;
case SDLK_KP_RIGHTPAREN: keyval = ')'; break;
case SDLK_KP_LEFTBRACE: keyval = '{'; break;
case SDLK_KP_RIGHTBRACE: keyval = '}'; break;
case SDLK_KP_TAB: keyval = '\t'; break;
case SDLK_KP_BACKSPACE: keyval = '\b'; break;
case SDLK_KP_PERCENT: keyval = '%'; break;
case SDLK_KP_LESS: keyval = '<'; break;
case SDLK_KP_GREATER: keyval = '>'; break;
case SDLK_KP_AMPERSAND: keyval = '&'; break;
case SDLK_KP_VERTICALBAR: keyval = '|'; break;
case SDLK_KP_COLON: keyval = ':'; break;
case SDLK_KP_HASH: keyval = '#'; break;
case SDLK_KP_SPACE: keyval = ' '; break;
case SDLK_KP_AT: keyval = '@'; break;
case SDLK_KP_EXCLAM: keyval = '!'; break;
}
if ((m_keymod & KMOD_CTRL) != 0u)
{
keyval |= Keymod::CTRL;
}
if ((m_keymod & KMOD_ALT) != 0u)
{
keyval |= Keymod::ALT;
}
if ((m_keymod & KMOD_GUI) != 0u)
{
keyval |= Keymod::GUI;
}
return keyval;
}
uint32_t Window::get_shifted(uint32_t keysym)
{
if ((keysym >= 'a') && (keysym <= 'z'))
{
return keysym - ('a' - 'A');
}
switch (keysym)
{
case SDLK_QUOTE: return '"';
case SDLK_COMMA: return '<';
case SDLK_MINUS: return '_';
case SDLK_PERIOD: return '>';
case SDLK_SLASH: return '?';
case SDLK_0: return ')';
case SDLK_1: return '!';
case SDLK_2: return '@';
case SDLK_3: return '#';
case SDLK_4: return '$';
case SDLK_5: return '%';
case SDLK_6: return '^';
case SDLK_7: return '&';
case SDLK_8: return '*';
case SDLK_9: return '(';
case SDLK_SEMICOLON: return ':';
case SDLK_EQUALS: return '+';
case SDLK_LEFTBRACKET: return '{';
case SDLK_BACKSLASH: return '|';
case SDLK_RIGHTBRACKET: return '}';
case SDLK_BACKQUOTE: return '~';
case SDLK_SPACE: return ' ';
case SDLK_BACKSPACE: return '\b';
}
return 0u;
Jtk_SwapBuffers(m_window);
}
void Window::change_focus(std::shared_ptr<BufferPane> buffer_pane)

View File

@ -3,30 +3,18 @@
#include <memory>
#include <utility>
#include <SDL.h>
#include "Font.h"
#include "Buffer.h"
#include "GL.h"
#include "EncodedString.h"
#include "CommandParser.h"
#include "Jtk.h"
class BufferPane;
class Window
{
public:
class Keymod
{
public:
enum : uint32_t
{
CTRL = 0x10000,
ALT = 0x20000,
SHIFT = 0x40000,
GUI = 0x80000,
};
};
enum class ScrollMode : uint8_t
{
ONE_LINE,
@ -53,21 +41,24 @@ public:
protected:
void resize();
void resize(size_t width, size_t height);
void redraw();
void handle_event(SDL_Event & event);
void handle_keysym(uint32_t keysym);
void handle_keyval(uint32_t keyval);
void handle_event(Jtk_Event & event);
void handle_keypress(uint32_t keyval);
#if 0
uint32_t get_keyval(SDL_Keycode keysym);
uint32_t get_shifted(uint32_t keysym);
#endif
void change_focus(std::shared_ptr<BufferPane> buffer_pane);
#if 0
void set_window_icon();
#endif
void handle_command(const EncodedString & command);
void command_write_file(const CommandParser & cp);
void command_quit(const CommandParser & cp);
SDL_Window * m_window;
void * m_window;
bool m_exit_requested;
bool m_redraw_requested;
int m_width;
@ -83,8 +74,6 @@ protected:
std::shared_ptr<BufferPane> m_focused_buffer_pane;
std::shared_ptr<Buffer> m_command_buffer;
std::shared_ptr<BufferPane> m_command_buffer_pane;
Uint16 m_keymod;
};
#endif

59
src/gui/jtk/Jtk.cc Normal file
View File

@ -0,0 +1,59 @@
#include "Jtk.h"
#ifdef JTK_X
#include <GL/glx.h>
#include <stdio.h>
Display * g_display;
XVisualInfo * g_vi;
XSetWindowAttributes g_swa;
GLXContext g_context;
/**
* Initialize the Jtk subsystem.
*
* @return true on success, false on failure
*/
bool Jtk_Init()
{
static int glx_attribute_list[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
None,
};
g_display = XOpenDisplay(NULL);
if (g_display == NULL)
{
fprintf(stderr, "XOpenDisplay() failure\n");
return false;
}
g_vi = glXChooseVisual(g_display, DefaultScreen(g_display),
glx_attribute_list);
if (g_vi == NULL)
{
fprintf(stderr, "glXChooseVisual() failure\n");
return false;
}
g_context = glXCreateContext(g_display, g_vi, NULL, True);
if (g_context == NULL)
{
fprintf(stderr, "glXCreateContext() failure\n");
return false;
}
Colormap colormap = XCreateColormap(g_display,
RootWindow(g_display, g_vi->screen), g_vi->visual, AllocNone);
g_swa.colormap = colormap;
g_swa.border_pixel = 0;
g_swa.event_mask = StructureNotifyMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask;
return true;
}
#endif

12
src/gui/jtk/Jtk.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef JTK_H
#define JTK_H
#include "Jtk_event.h"
#include "Jtk_keys.h"
#include "Jtk_time.h"
#include "Jtk_timer.h"
#include "Jtk_window.h"
bool Jtk_Init();
#endif

460
src/gui/jtk/Jtk_event.cc Normal file
View File

@ -0,0 +1,460 @@
#include "Jtk.h"
#ifdef JTK_X
#include <GL/glx.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include "Jtk_internal.h"
#include <unordered_map>
/** Do not wait longer than 100ms */
#define MAX_WAIT_TIME 100000u
static std::unordered_map<unsigned int, size_t> g_repeating_keys;
static std::unordered_map<size_t, unsigned int> g_key_repeat_timers;
#if 0
static void StopKeyRepeat(unsigned int x_keycode)
{
auto it = g_repeating_keys.find(x_keycode);
if (it != g_repeating_keys.end())
{
size_t timer_id = it->second;
Jtk_RemoveTimer(timer_id);
g_repeating_keys.erase(x_keycode);
g_key_repeat_timers.erase(timer_id);
}
}
#endif
#if 0
static unsigned int GetXState()
{
Window win;
int i;
unsigned int state;
XQueryPointer(g_display, RootWindow(g_display, DefaultScreen(g_display)), &win, &win, &i, &i, &i, &i, &state);
return state;
}
#endif
static uint32_t XStateToJtkKeyMods(unsigned int x_state)
{
uint32_t mods = 0u;
/* OR in the modifier states */
if (x_state & ShiftMask)
{
mods |= JTK_KEY_MODS_SHIFT;
}
if (x_state & LockMask)
{
mods |= JTK_KEY_MODS_LOCK;
}
if (x_state & ControlMask)
{
mods |= JTK_KEY_MODS_CTRL;
}
return mods;
}
static uint32_t XKeyToJtkKey(unsigned int x_keycode, unsigned int x_state)
{
XKeyEvent x_key_event;
x_key_event.type = KeyPress;
x_key_event.display = g_display;
/* Turn off the ControlMask bit for looking up keys. We'll handle control
* keys ourselves. */
x_key_event.state = x_state & ~ControlMask;
x_key_event.keycode = x_keycode;
char buffer;
KeySym keysym;
uint32_t key = JTK_KEY_UNKNOWN;
if (XLookupString(&x_key_event, &buffer, 1, &keysym, nullptr) > 0)
{
if (buffer == '\r')
{
key = '\n';
}
else
{
key = buffer;
}
}
else
{
switch (keysym)
{
case XK_F1: key = JTK_KEY_F1; break;
case XK_F2: key = JTK_KEY_F2; break;
case XK_F3: key = JTK_KEY_F3; break;
case XK_F4: key = JTK_KEY_F4; break;
case XK_F5: key = JTK_KEY_F5; break;
case XK_F6: key = JTK_KEY_F6; break;
case XK_F7: key = JTK_KEY_F7; break;
case XK_F8: key = JTK_KEY_F8; break;
case XK_F9: key = JTK_KEY_F9; break;
case XK_F10: key = JTK_KEY_F10; break;
case XK_F11: key = JTK_KEY_F11; break;
case XK_F12: key = JTK_KEY_F12; break;
case XK_F13: key = JTK_KEY_F13; break;
case XK_F14: key = JTK_KEY_F14; break;
case XK_F15: key = JTK_KEY_F15; break;
case XK_F16: key = JTK_KEY_F16; break;
case XK_F17: key = JTK_KEY_F17; break;
case XK_F18: key = JTK_KEY_F18; break;
case XK_F19: key = JTK_KEY_F19; break;
case XK_F20: key = JTK_KEY_F20; break;
case XK_F21: key = JTK_KEY_F21; break;
case XK_F22: key = JTK_KEY_F22; break;
case XK_F23: key = JTK_KEY_F23; break;
case XK_F24: key = JTK_KEY_F24; break;
case XK_F25: key = JTK_KEY_F25; break;
case XK_F26: key = JTK_KEY_F26; break;
case XK_F27: key = JTK_KEY_F27; break;
case XK_F28: key = JTK_KEY_F28; break;
case XK_F29: key = JTK_KEY_F29; break;
case XK_F30: key = JTK_KEY_F30; break;
case XK_F31: key = JTK_KEY_F31; break;
case XK_Shift_L: key = JTK_KEY_SHIFT_L; break;
case XK_Shift_R: key = JTK_KEY_SHIFT_R; break;
case XK_Control_L: key = JTK_KEY_CTRL_L; break;
case XK_Control_R: key = JTK_KEY_CTRL_R; break;
case XK_Caps_Lock: key = JTK_KEY_CAPS_LOCK; break;
case XK_Shift_Lock: key = JTK_KEY_SHIFT_LOCK;break;
case XK_Meta_L: key = JTK_KEY_META_L; break;
case XK_Meta_R: key = JTK_KEY_META_R; break;
case XK_Alt_L: key = JTK_KEY_ALT_L; break;
case XK_Alt_R: key = JTK_KEY_ALT_R; break;
case XK_Super_L: key = JTK_KEY_SUPER_L; break;
case XK_Super_R: key = JTK_KEY_SUPER_R; break;
case XK_Home: key = JTK_KEY_HOME; break;
case XK_Left: key = JTK_KEY_LEFT; break;
case XK_Up: key = JTK_KEY_UP; break;
case XK_Right: key = JTK_KEY_RIGHT; break;
case XK_Down: key = JTK_KEY_DOWN; break;
case XK_Page_Up: key = JTK_KEY_PAGE_UP; break;
case XK_Page_Down: key = JTK_KEY_PAGE_DOWN; break;
case XK_End: key = JTK_KEY_END; break;
case XK_Begin: key = JTK_KEY_BEGIN; break;
case XK_Select: key = JTK_KEY_SELECT; break;
case XK_Print: key = JTK_KEY_PRINT; break;
case XK_Execute: key = JTK_KEY_EXECUTE; break;
case XK_Insert: key = JTK_KEY_INSERT; break;
case XK_Undo: key = JTK_KEY_UNDO; break;
case XK_Redo: key = JTK_KEY_REDO; break;
case XK_Menu: key = JTK_KEY_MENU; break;
case XK_Find: key = JTK_KEY_FIND; break;
case XK_Cancel: key = JTK_KEY_CANCEL; break;
case XK_Help: key = JTK_KEY_HELP; break;
case XK_Break: key = JTK_KEY_BREAK; break;
case XK_Num_Lock: key = JTK_KEY_NUM_LOCK; break;
case XK_KP_Space: key = JTK_KEY_KP_SPACE; break;
case XK_KP_Tab: key = JTK_KEY_KP_TAB; break;
case XK_KP_Enter: key = JTK_KEY_KP_ENTER; break;
case XK_KP_F1: key = JTK_KEY_KP_F1; break;
case XK_KP_F2: key = JTK_KEY_KP_F2; break;
case XK_KP_F3: key = JTK_KEY_KP_F3; break;
case XK_KP_F4: key = JTK_KEY_KP_F4; break;
case XK_KP_Home: key = JTK_KEY_KP_HOME; break;
case XK_KP_Left: key = JTK_KEY_KP_LEFT; break;
case XK_KP_Up: key = JTK_KEY_KP_UP; break;
case XK_KP_Right: key = JTK_KEY_KP_RIGHT; break;
case XK_KP_Down: key = JTK_KEY_KP_DOWN; break;
case XK_KP_Page_Up: key = JTK_KEY_KP_PAGE_UP; break;
case XK_KP_Page_Down: key = JTK_KEY_KP_PAGE_DOWN; break;
case XK_KP_End: key = JTK_KEY_KP_END; break;
case XK_KP_Begin: key = JTK_KEY_KP_BEGIN; break;
case XK_KP_Insert: key = JTK_KEY_KP_INSERT; break;
case XK_KP_Delete: key = JTK_KEY_KP_DELETE; break;
case XK_KP_Equal: key = JTK_KEY_KP_EQUAL; break;
case XK_KP_Multiply: key = JTK_KEY_KP_MULTIPLY; break;
case XK_KP_Add: key = JTK_KEY_KP_ADD; break;
case XK_KP_Separator: key = JTK_KEY_KP_SEPARATOR; break;
case XK_KP_Subtract: key = JTK_KEY_KP_SUBTRACT; break;
case XK_KP_Decimal: key = JTK_KEY_KP_DECIMAL; break;
case XK_KP_Divide: key = JTK_KEY_KP_DIVIDE; break;
case XK_KP_0: key = JTK_KEY_KP_0; break;
case XK_KP_1: key = JTK_KEY_KP_1; break;
case XK_KP_2: key = JTK_KEY_KP_2; break;
case XK_KP_3: key = JTK_KEY_KP_3; break;
case XK_KP_4: key = JTK_KEY_KP_4; break;
case XK_KP_5: key = JTK_KEY_KP_5; break;
case XK_KP_6: key = JTK_KEY_KP_6; break;
case XK_KP_7: key = JTK_KEY_KP_7; break;
case XK_KP_8: key = JTK_KEY_KP_8; break;
case XK_KP_9: key = JTK_KEY_KP_9; break;
}
}
/* OR in the modifier states */
key |= XStateToJtkKeyMods(x_state);
return key;
}
#if 0
static Bool KeyRepeatCheckIfEvent(Display * display, XEvent * chkev,
XPointer arg)
{
XEvent * release_event = (XEvent *)arg;
if (chkev->type == KeyPress &&
chkev->xkey.keycode == release_event->xkey.keycode &&
chkev->xkey.time - release_event->xkey.time < 2)
return True;
return False;
}
/**
* Check to see if this is a repeated key.
*/
static bool IsRepeatKey(Display * display, XEvent * event)
{
XEvent dummyev;
if (XPending(display))
{
if (XCheckIfEvent(display, &dummyev, KeyRepeatCheckIfEvent,
(XPointer)event) == True)
{
return true;
}
}
return false;
}
#endif
static Bool MatchKeyPress(Display * display, XEvent * event, XPointer arg)
{
XEvent * match_event = (XEvent *)arg;
return (event->type == match_event->type) &&
(event->xkey.window == match_event->xkey.window) &&
(event->xkey.state == match_event->xkey.state) &&
(event->xkey.keycode == match_event->xkey.keycode);
}
/**
* Process an X key press event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*/
static bool ProcessXKeyPressEvent(XEvent * x_event, Jtk_Event * event)
{
unsigned int x_keycode = x_event->xkey.keycode;
event->type = JTK_EVENT_KEY_PRESS;
event->key.repeat = false;
event->key.key = XKeyToJtkKey(x_keycode, x_event->xkey.state);
event->key.x_keycode = x_keycode;
/* Remove any following keypress events for the same keycode from the X
* queue. */
XEvent remove_event;
while (XCheckIfEvent(g_display, &remove_event, MatchKeyPress, (XPointer)x_event) == True)
{
}
return true;
}
/**
* Process an X key release event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*/
static bool ProcessXKeyReleaseEvent(XEvent * x_event, Jtk_Event * event)
{
#if 0
if (IsRepeatKey(g_display, x_event))
{
return false;
}
StopKeyRepeat(x_event->xkey.keycode);
#endif
return false;
}
static Bool MatchButtonPress(Display * display, XEvent * event, XPointer arg)
{
XEvent * match_event = (XEvent *)arg;
return (event->type == match_event->type) &&
(event->xbutton.window == match_event->xbutton.window) &&
(event->xbutton.state == match_event->xbutton.state) &&
(event->xbutton.button == match_event->xbutton.button);
}
/**
* Process an X button press event.
*/
static bool ProcessXButtonPressEvent(XEvent * x_event, Jtk_Event * event)
{
event->type = JTK_EVENT_BUTTON_PRESS;
event->button.mods = XStateToJtkKeyMods(x_event->xbutton.state);
event->button.button = x_event->xbutton.button;
/* If this is a mouse wheel scroll event, remove any following scroll
* events. */
if ((event->button.button == 4) || (event->button.button == 5))
{
XEvent remove_event;
while (XCheckIfEvent(g_display, &remove_event, MatchButtonPress, (XPointer)x_event) == True)
{
}
}
return true;
}
/**
* Process an X configure event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*/
static bool ProcessConfigureEvent(XEvent * x_event, Jtk_Event * event)
{
event->type = JTK_EVENT_WINDOW_RESIZE;
event->resize.width = x_event->xconfigure.width;
event->resize.height = x_event->xconfigure.height;
return true;
}
/**
* Process an X event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*
* @retval true
* The event should be passed to the user and event has been filled in.
* @retval false
* The event should not be passed to the user.
*/
static bool ProcessXEvent(XEvent * x_event, Jtk_Event * event)
{
switch (x_event->type)
{
case KeyPress:
return ProcessXKeyPressEvent(x_event, event);
case KeyRelease:
return ProcessXKeyReleaseEvent(x_event, event);
case ButtonPress:
return ProcessXButtonPressEvent(x_event, event);
case ButtonRelease:
break;
case Expose:
event->type = JTK_EVENT_WINDOW_EXPOSE;
return true;
case GraphicsExpose:
event->type = JTK_EVENT_WINDOW_EXPOSE;
return true;
case MapNotify:
event->type = JTK_EVENT_WINDOW_EXPOSE;
return true;
case ConfigureNotify:
return ProcessConfigureEvent(x_event, event);
case MappingNotify:
XRefreshKeyboardMapping(&x_event->xmapping);
return false;
}
return false;
}
bool Jtk_CheckEvent(Jtk_Event * event)
{
/* First check for an X event. */
while (XPending(g_display) > 0)
{
XEvent x_event;
XNextEvent(g_display, &x_event);
if (ProcessXEvent(&x_event, event))
return true;
}
/* Next check if any timer has expired. */
size_t timer_id = Jtk_GetExpiredTimer();
if (timer_id != (size_t)-1)
{
#if 0
auto it = g_key_repeat_timers.find(timer_id);
if (it != g_key_repeat_timers.end())
{
event->type = JTK_EVENT_KEY_PRESS;
event->key.repeat = true;
event->key.key = XKeyToJtkKey(it->second);
event->key.x_keycode = it->second;
}
else
{
#endif
event->type = JTK_EVENT_TIMER;
event->timer.timer_id = timer_id;
event->timer.user1 = Jtk_GetTimerUserData(timer_id, 0u);
event->timer.user2 = Jtk_GetTimerUserData(timer_id, 1u);
#if 0
}
#endif
Jtk_ServiceTimer(timer_id);
return true;
}
return false;
}
void Jtk_WaitEvent(Jtk_Event * event)
{
for (;;)
{
if (Jtk_CheckEvent(event))
return;
/* Wait for something to happen. */
uint64_t time_to_wait = Jtk_TimeToNextTimerExpiration();
if (time_to_wait > MAX_WAIT_TIME)
{
time_to_wait = MAX_WAIT_TIME;
}
int x_fd = ConnectionNumber(g_display);
fd_set fds;
FD_ZERO(&fds);
FD_SET(x_fd, &fds);
struct timeval tv;
tv.tv_sec = time_to_wait / 1000000u;
tv.tv_usec = time_to_wait % 1000000u;
select(x_fd + 1, &fds, nullptr, nullptr, &tv);
}
}
#if 0
void Jtk_BeginKeyRepeat(Jtk_KeyEvent * key_event, uint32_t delay, uint32_t interval)
{
StopKeyRepeat(key_event->x_keycode);
size_t timer_id = Jtk_AddTimer(delay, interval, nullptr, nullptr);
g_repeating_keys[key_event->x_keycode] = timer_id;
g_key_repeat_timers[timer_id] = key_event->x_keycode;
}
#endif
#endif

62
src/gui/jtk/Jtk_event.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef JTK_EVENT_H
#define JTK_EVENT_H
#include <stdint.h>
#include <stdlib.h>
#define JTK_EVENT_CLOSE_WINDOW 1u
#define JTK_EVENT_WINDOW_EXPOSE 2u
#define JTK_EVENT_KEY_PRESS 3u
#define JTK_EVENT_KEY_RELEASE 4u
#define JTK_EVENT_BUTTON_PRESS 5u
#define JTK_EVENT_BUTTON_RELEASE 6u
#define JTK_EVENT_TIMER 7u
#define JTK_EVENT_WINDOW_RESIZE 8u
typedef struct
{
bool repeat;
uint32_t key;
#ifdef JTK_X
unsigned int x_keycode;
#endif
} Jtk_KeyEvent;
typedef struct
{
uint32_t mods;
uint8_t button;
} Jtk_ButtonEvent;
typedef struct
{
size_t timer_id;
void * user1;
void * user2;
} Jtk_TimerEvent;
typedef struct
{
size_t width;
size_t height;
} Jtk_WindowResizeEvent;
typedef struct
{
uint8_t type;
union
{
Jtk_KeyEvent key;
Jtk_ButtonEvent button;
Jtk_TimerEvent timer;
Jtk_WindowResizeEvent resize;
};
} Jtk_Event;
bool Jtk_CheckEvent(Jtk_Event * event);
void Jtk_WaitEvent(Jtk_Event * event);
#if 0
void Jtk_BeginKeyRepeat(Jtk_KeyEvent * key_event, uint32_t delay, uint32_t interval);
#endif
#endif

View File

@ -0,0 +1,9 @@
#ifndef JTK_INTERNAL_H
#define JTK_INTERNAL_H
extern Display * g_display;
extern XVisualInfo * g_vi;
extern XSetWindowAttributes g_swa;
extern GLXContext g_context;
#endif

120
src/gui/jtk/Jtk_keys.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef JTK_KEYS_H
#define JTK_KEYS_H
#define JTK_KEY_MODS_MASK 0xFF000000u
#define JTK_KEY_MODS_SHIFT 0x01000000u
#define JTK_KEY_MODS_LOCK 0x02000000u
#define JTK_KEY_MODS_CTRL 0x04000000u
#define JTK_KEY_KEYCODE_MASK 0x00FFFFFFu
#define JTK_KEY_F1 0x00FF0001u
#define JTK_KEY_F2 0x00FF0002u
#define JTK_KEY_F3 0x00FF0003u
#define JTK_KEY_F4 0x00FF0004u
#define JTK_KEY_F5 0x00FF0005u
#define JTK_KEY_F6 0x00FF0006u
#define JTK_KEY_F7 0x00FF0007u
#define JTK_KEY_F8 0x00FF0008u
#define JTK_KEY_F9 0x00FF0009u
#define JTK_KEY_F10 0x00FF000Au
#define JTK_KEY_F11 0x00FF000Bu
#define JTK_KEY_F12 0x00FF000Cu
#define JTK_KEY_F13 0x00FF000Du
#define JTK_KEY_F14 0x00FF000Eu
#define JTK_KEY_F15 0x00FF000Fu
#define JTK_KEY_F16 0x00FF0010u
#define JTK_KEY_F17 0x00FF0011u
#define JTK_KEY_F18 0x00FF0012u
#define JTK_KEY_F19 0x00FF0013u
#define JTK_KEY_F20 0x00FF0014u
#define JTK_KEY_F21 0x00FF0015u
#define JTK_KEY_F22 0x00FF0016u
#define JTK_KEY_F23 0x00FF0017u
#define JTK_KEY_F24 0x00FF0018u
#define JTK_KEY_F25 0x00FF0019u
#define JTK_KEY_F26 0x00FF001Au
#define JTK_KEY_F27 0x00FF001Bu
#define JTK_KEY_F28 0x00FF001Cu
#define JTK_KEY_F29 0x00FF001Du
#define JTK_KEY_F30 0x00FF001Eu
#define JTK_KEY_F31 0x00FF001Fu
#define JTK_KEY_SHIFT_L 0x00FF0030u
#define JTK_KEY_SHIFT_R 0x00FF0031u
#define JTK_KEY_CTRL_L 0x00FF0032u
#define JTK_KEY_CTRL_R 0x00FF0033u
#define JTK_KEY_CAPS_LOCK 0x00FF0034u
#define JTK_KEY_SHIFT_LOCK 0x00FF0035u
#define JTK_KEY_META_L 0x00FF0036u
#define JTK_KEY_META_R 0x00FF0037u
#define JTK_KEY_ALT_L 0x00FF0038u
#define JTK_KEY_ALT_R 0x00FF0039u
#define JTK_KEY_SUPER_L 0x00FF003Au
#define JTK_KEY_SUPER_R 0x00FF003Bu
#define JTK_KEY_HOME 0x00FF003Cu
#define JTK_KEY_LEFT 0x00FF003Du
#define JTK_KEY_UP 0x00FF003Eu
#define JTK_KEY_RIGHT 0x00FF003Fu
#define JTK_KEY_DOWN 0x00FF0040u
#define JTK_KEY_PAGE_UP 0x00FF0042u
#define JTK_KEY_PAGE_DOWN 0x00FF0044u
#define JTK_KEY_END 0x00FF0045u
#define JTK_KEY_BEGIN 0x00FF0046u
#define JTK_KEY_SELECT 0x00FF0047u
#define JTK_KEY_PRINT 0x00FF0048u
#define JTK_KEY_EXECUTE 0x00FF0049u
#define JTK_KEY_INSERT 0x00FF004Au
#define JTK_KEY_UNDO 0x00FF004Bu
#define JTK_KEY_REDO 0x00FF004Cu
#define JTK_KEY_MENU 0x00FF004Du
#define JTK_KEY_FIND 0x00FF004Eu
#define JTK_KEY_CANCEL 0x00FF004Fu
#define JTK_KEY_HELP 0x00FF0050u
#define JTK_KEY_BREAK 0x00FF0051u
#define JTK_KEY_NUM_LOCK 0x00FF0054u
#define JTK_KEY_KP_SPACE 0x00FF0055u
#define JTK_KEY_KP_TAB 0x00FF0056u
#define JTK_KEY_KP_ENTER 0x00FF0057u
#define JTK_KEY_KP_F1 0x00FF0058u
#define JTK_KEY_KP_F2 0x00FF0059u
#define JTK_KEY_KP_F3 0x00FF005Au
#define JTK_KEY_KP_F4 0x00FF005Bu
#define JTK_KEY_KP_HOME 0x00FF005Cu
#define JTK_KEY_KP_LEFT 0x00FF005Du
#define JTK_KEY_KP_UP 0x00FF005Eu
#define JTK_KEY_KP_RIGHT 0x00FF005Fu
#define JTK_KEY_KP_DOWN 0x00FF0060u
#define JTK_KEY_KP_PAGE_UP 0x00FF0062u
#define JTK_KEY_KP_PAGE_DOWN 0x00FF0064u
#define JTK_KEY_KP_END 0x00FF0065u
#define JTK_KEY_KP_BEGIN 0x00FF0066u
#define JTK_KEY_KP_INSERT 0x00FF0067u
#define JTK_KEY_KP_DELETE 0x00FF0068u
#define JTK_KEY_KP_EQUAL 0x00FF0069u
#define JTK_KEY_KP_MULTIPLY 0x00FF006Au
#define JTK_KEY_KP_ADD 0x00FF006Bu
#define JTK_KEY_KP_SEPARATOR 0x00FF006Cu
#define JTK_KEY_KP_SUBTRACT 0x00FF006Du
#define JTK_KEY_KP_DECIMAL 0x00FF006Eu
#define JTK_KEY_KP_DIVIDE 0x00FF006Fu
#define JTK_KEY_KP_0 0x00FF0070u
#define JTK_KEY_KP_1 0x00FF0071u
#define JTK_KEY_KP_2 0x00FF0072u
#define JTK_KEY_KP_3 0x00FF0073u
#define JTK_KEY_KP_4 0x00FF0074u
#define JTK_KEY_KP_5 0x00FF0075u
#define JTK_KEY_KP_6 0x00FF0076u
#define JTK_KEY_KP_7 0x00FF0077u
#define JTK_KEY_KP_8 0x00FF0078u
#define JTK_KEY_KP_9 0x00FF0079u
#define JTK_KEY_UNKNOWN 0x00FFFFFFu
#endif

9
src/gui/jtk/Jtk_time.cc Normal file
View File

@ -0,0 +1,9 @@
#include "Jtk.h"
#include <sys/time.h>
uint64_t Jtk_UsTime()
{
struct timeval tv;
gettimeofday(&tv, nullptr);
return (uint64_t)tv.tv_sec * 1000000u + (uint64_t)tv.tv_usec;
}

9
src/gui/jtk/Jtk_time.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef JTK_TIME_H
#define JTK_TIME_H
#include "Jtk_timer.h"
bool Jtk_Init();
uint64_t Jtk_UsTime();
#endif

157
src/gui/jtk/Jtk_timer.cc Normal file
View File

@ -0,0 +1,157 @@
#include "Jtk.h"
#include <vector>
#include <memory>
#include <list>
typedef struct
{
uint64_t next; /**< Time the timer next expires (us). */
uint64_t interval; /**< Timer interval (us). */
size_t id; /**< Timer ID. */
void * user[2]; /**< User data pointers. */
} Timer;
/** Vector used to allocate timer IDs. */
static std::vector<std::shared_ptr<Timer>> g_timers;
/** Linked list used to traverse all active timers. */
static std::list<std::shared_ptr<Timer>> g_active_timers;
static size_t AllocateTimerID()
{
for (size_t i = 0; i < g_timers.size(); i++)
{
if (!g_timers[i])
{
return i;
}
}
g_timers.push_back(nullptr);
return g_timers.size() - 1u;
}
/**
* Add a timer.
*
* @param delay
* Delay time in milliseconds.
* @param interval
* Interval time in milliseconds. A value of 0 indicates that the timer
* is not periodic.
* @param user1
* User data pointer 1. This value is not used by Jtk but can be retrieved by
* the user when a timer expires.
* @param user2
* User data pointer 2. This value is not used by Jtk but can be retrieved by
* the user when a timer expires.
*
* @return
* Timer ID.
*/
size_t Jtk_AddTimer(uint32_t delay, uint32_t interval, void * user1, void * user2)
{
uint64_t current_system_time = Jtk_UsTime();
size_t timer_id = AllocateTimerID();
auto timer = std::make_shared<Timer>();
timer->next = current_system_time + (delay * 1000u);
timer->interval = interval * 1000u;
timer->id = timer_id;
timer->user[0] = user1;
timer->user[1] = user2;
g_timers[timer_id] = timer;
g_active_timers.push_back(timer);
return timer_id;
}
/**
* Remove a timer.
*
* @param timer_id
* The ID of the timer to remove.
*/
void Jtk_RemoveTimer(size_t timer_id)
{
if (timer_id < g_timers.size())
{
auto timer = g_timers[timer_id];
g_active_timers.remove(timer);
g_timers[timer_id] = nullptr;
}
}
/**
* Determine the amount of time until the next timer expires (in us).
*
* @return
* Time (in us) until the next timer expires. This will be 0 if an active
* timer has already expired, and will be (uint64_t)-1 if there are no
* active timers.
*/
uint64_t Jtk_TimeToNextTimerExpiration()
{
uint64_t time = (uint64_t)-1;
uint64_t current_system_time = Jtk_UsTime();
for (auto & timer : g_active_timers)
{
if (timer->next <= current_system_time)
{
return 0;
}
uint64_t time_until_this_timer = timer->next - current_system_time;
if (time_until_this_timer < time)
{
time = time_until_this_timer;
}
}
return time;
}
/**
* Service a timer.
*
* This will increment the timer's next activation time by its interval, or
* for a timer with an interval of 0, will remove the timer.
*
* @param timer_id
* The ID of the timer to service.
*/
void Jtk_ServiceTimer(size_t timer_id)
{
auto timer = g_timers[timer_id];
if (timer->interval == 0u)
{
Jtk_RemoveTimer(timer_id);
}
else
{
timer->next += timer->interval;
}
}
/**
* Return the ID of an expired timer.
*
* @return
* The ID of an expired timer, or (size_t)-1 if no timer is expired.
*/
size_t Jtk_GetExpiredTimer()
{
uint64_t current_system_time = Jtk_UsTime();
for (auto & timer : g_active_timers)
{
if (timer->next <= current_system_time)
{
return timer->id;
}
}
return (size_t)-1;
}
void * Jtk_GetTimerUserData(size_t timer_id, uint8_t index)
{
if (timer_id < g_timers.size())
{
return g_timers[timer_id]->user[index];
}
return nullptr;
}

14
src/gui/jtk/Jtk_timer.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef JTK_TIMER_H
#define JTK_TIMER_H
#include <stdint.h>
#include <stdlib.h>
size_t Jtk_AddTimer(uint32_t delay, uint32_t interval, void * user1, void * user2);
void Jtk_RemoveTimer(size_t timer_id);
uint64_t Jtk_TimeToNextTimerExpiration();
void Jtk_ServiceTimer(size_t timer_id);
size_t Jtk_GetExpiredTimer();
void * Jtk_GetTimerUserData(size_t timer_id, uint8_t index);
#endif

55
src/gui/jtk/Jtk_window.cc Normal file
View File

@ -0,0 +1,55 @@
#include "Jtk.h"
#ifdef JTK_X
#include <GL/glx.h>
#include "Jtk_internal.h"
#include <stdio.h>
#include <X11/Xatom.h>
static Bool WaitForNotify(Display * display, XEvent * event, XPointer arg)
{
return (event->type == MapNotify) && (event->xmap.window == (Window)arg);
}
void * Jtk_CreateWindow()
{
XEvent event;
Window window = XCreateWindow(g_display,
RootWindow(g_display, g_vi->screen),
0, 0, 800, 800, 0, g_vi->depth, InputOutput, g_vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &g_swa);
XMapWindow(g_display, window);
XIfEvent(g_display, &event, WaitForNotify, (XPointer)window);
if (glXMakeCurrent(g_display, window, g_context) == False)
{
fprintf(stderr, "glXMakeCurrent() failure\n");
XDestroyWindow(g_display, window);
return nullptr;
}
return (void *)window;
}
void Jtk_SwapBuffers(void * window)
{
glXSwapBuffers(g_display, (Window)window);
}
void Jtk_CloseWindow(void * window)
{
XDestroyWindow(g_display, (Window)window);
}
void Jtk_SetWindowTitle(void * window, const char * title)
{
XTextProperty title_property;
if (XStringListToTextProperty((char **)&title, 1, &title_property) != 0)
{
XSetTextProperty(g_display, (Window)window, &title_property, XA_WM_NAME);
XFree(title_property.value);
}
}
#endif

9
src/gui/jtk/Jtk_window.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef JTK_WINDOW_H
#define JTK_WINDOW_H
void * Jtk_CreateWindow();
void Jtk_SwapBuffers(void * window);
void Jtk_CloseWindow(void * window);
void Jtk_SetWindowTitle(void * window, const char * title);
#endif

15
wscript
View File

@ -11,8 +11,11 @@ def options(opt):
def configure(conf):
conf.load("compiler_c compiler_cxx")
conf.check(header_name = "getopt.h", global_define = False)
conf.check_cfg(package = "sdl2", args = "--cflags --libs")
conf.check_cfg(package = "freetype2", uselib_store = "FreeType2", args = "--cflags --libs")
if platform.system() == "Linux":
conf.check(header_name = "X11/Xlib.h", global_define = False)
elif platform.system() == "Windows":
conf.check(header_name = "windows.h", global_define = False)
def build(bld):
defines = ['APPNAME="%s"' % APPNAME]
@ -22,9 +25,11 @@ def build(bld):
libs = []
if platform.system() == "Linux":
defines += ["PLATFORM_LINUX"]
libs += ["dl", "GL"]
elif re.search(r'MINGW', platform.system()):
defines += ["JTK_X"]
libs += ["dl", "GL", "X11"]
elif platform.system() == "Windows":
defines += ["PLATFORM_WINDOWS"]
defines += ["JTK_WINDOWS"]
libs += ["opengl32"]
defines += ['GLCXX_GL_INCLUDE="gl3w.h"']
sources = bld.path.ant_glob(["src/**/*.cc", "src/**/*.c", "libs/glcxx/src/glcxx/*"])
@ -35,7 +40,7 @@ def build(bld):
defines = defines,
cxxflags = ["-Wall", "-std=gnu++14", "-O2", "-Wno-switch"],
lib = libs,
uselib = ["SDL2", "FreeType2"])
uselib = ["FreeType2"])
test_libs = libs + []
if platform.system() == "Linux":
@ -56,4 +61,4 @@ def build(bld):
lib = test_libs,
cxxflags = ["-Wall", "-std=gnu++14", "--coverage", "-Wno-switch", "-include", "iostream"],
linkflags = ["--coverage"],
uselib = ["SDL2", "FreeType2"])
uselib = ["FreeType2"])