mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-19 21:39:57 +00:00
Updates for a future Mac build
This commit is contained in:
parent
941b611ba0
commit
0b7fdbf8e1
14 changed files with 698 additions and 94 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,8 +1,10 @@
|
|||
*.o
|
||||
*.pro.*
|
||||
*.cmake
|
||||
*.bak
|
||||
*.xxd
|
||||
*.exe
|
||||
*.app
|
||||
*.bmp
|
||||
|
||||
Makefile*
|
||||
|
|
@ -16,3 +18,7 @@ Makefile*
|
|||
|
||||
object_script.*
|
||||
rpgscript.bat
|
||||
|
||||
.qmake.stash
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
|
|
@ -6,8 +6,8 @@ Project(mkxp)
|
|||
option(SHARED_FLUID "Dynamically link fluidsynth at build time" OFF)
|
||||
option(WORKDIR_CURRENT "Keep current directory on startup" OFF)
|
||||
option(FORCE32 "Force 32bit compile on 64bit OS" OFF)
|
||||
set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, MRUBY, NULL)")
|
||||
set(EXTERNAL_LIB_PATH "" CACHE PATH "External precompiled lib prefix")
|
||||
set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, NULL)")
|
||||
set(EXTERNAL_LIB_PATH "/usr/local/opt/ruby21" CACHE PATH "External precompiled lib prefix")
|
||||
|
||||
## Misc setup ##
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ set(MAIN_HEADERS
|
|||
src/alstream.h
|
||||
src/audiostream.h
|
||||
src/rgssad.h
|
||||
src/windowvx.h
|
||||
src/window.h
|
||||
src/tilemapvx.h
|
||||
src/tileatlasvx.h
|
||||
src/sharedmidistate.h
|
||||
|
|
@ -197,7 +197,7 @@ set(MAIN_SOURCE
|
|||
src/rgssad.cpp
|
||||
src/bundledfont.cpp
|
||||
src/vorbissource.cpp
|
||||
src/windowvx.cpp
|
||||
src/window.cpp
|
||||
src/tilemapvx.cpp
|
||||
src/tileatlasvx.cpp
|
||||
src/autotilesvx.cpp
|
||||
|
|
@ -318,8 +318,8 @@ if (BINDING STREQUAL "MRI")
|
|||
binding-mri/audio-binding.cpp
|
||||
binding-mri/module_rpg.cpp
|
||||
binding-mri/filesystem-binding.cpp
|
||||
binding-mri/windowvx-binding.cpp
|
||||
binding-mri/tilemapvx-binding.cpp
|
||||
binding-mri/window-binding.cpp
|
||||
binding-mri/tilemap-binding.cpp
|
||||
)
|
||||
elseif(BINDING STREQUAL "MRUBY")
|
||||
message(FATAL_ERROR "Mruby support in CMake needs to be finished")
|
||||
|
|
|
|||
|
|
@ -5,12 +5,26 @@
|
|||
|
||||
#include <SDL.h>
|
||||
|
||||
#if defined __linux
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
//OS-Specific code
|
||||
#if defined _WIN32
|
||||
#define OS_W32
|
||||
#elif defined __APPLE__ || __linux__
|
||||
#define LINUX
|
||||
#ifdef __APPLE__
|
||||
#define OS_OSX
|
||||
#else
|
||||
#define OS_LINUX
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef OS_LINUX
|
||||
#include <sys/inotify.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#error "Operating system not detected."
|
||||
#endif
|
||||
|
||||
#define BUFFER_SIZE 256
|
||||
|
|
@ -20,20 +34,20 @@ static SDL_mutex *mutex = NULL;
|
|||
static volatile char message_buffer[BUFFER_SIZE];
|
||||
static volatile bool active = false;
|
||||
|
||||
#if defined __linux
|
||||
#define PIPE_PATH "/tmp/oneshot-pipe"
|
||||
static volatile int message_len = 0;
|
||||
static volatile int out_pipe = -1;
|
||||
void cleanup_pipe()
|
||||
{
|
||||
unlink(PIPE_PATH);
|
||||
}
|
||||
#ifdef LINUX
|
||||
#define PIPE_PATH "/tmp/oneshot-pipe"
|
||||
static volatile int message_len = 0;
|
||||
static volatile int out_pipe = -1;
|
||||
void cleanup_pipe()
|
||||
{
|
||||
unlink(PIPE_PATH);
|
||||
}
|
||||
#endif
|
||||
|
||||
int server_thread(void *data)
|
||||
{
|
||||
(void)data;
|
||||
#if defined _WIN32
|
||||
#if defined OS_W32
|
||||
HANDLE pipe = CreateNamedPipeW(L"\\\\.\\pipe\\oneshot-journal-to-game",
|
||||
PIPE_ACCESS_OUTBOUND,
|
||||
PIPE_TYPE_BYTE | PIPE_WAIT,
|
||||
|
|
@ -53,7 +67,7 @@ int server_thread(void *data)
|
|||
DisconnectNamedPipe(pipe);
|
||||
}
|
||||
CloseHandle(pipe);
|
||||
#elif defined __linux
|
||||
#else
|
||||
out_pipe = open(PIPE_PATH, O_WRONLY);
|
||||
active = true;
|
||||
SDL_LockMutex(mutex);
|
||||
|
|
@ -69,7 +83,7 @@ RB_METHOD(journalSet)
|
|||
RB_UNUSED_PARAM;
|
||||
const char *name;
|
||||
rb_get_args(argc, argv, "z", &name RB_ARG_END);
|
||||
#if defined _WIN32
|
||||
#if defined OS_W32
|
||||
SDL_LockMutex(mutex);
|
||||
strcpy((char*)message_buffer, name);
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
|
@ -90,7 +104,7 @@ RB_METHOD(journalSet)
|
|||
if (thread == NULL) {
|
||||
thread = SDL_CreateThread(server_thread, "journal", NULL);
|
||||
}
|
||||
#elif defined __linux
|
||||
#else
|
||||
// Clean up connection thread
|
||||
if (thread != NULL && out_pipe != -1) {
|
||||
SDL_WaitThread(thread, NULL);
|
||||
|
|
@ -115,8 +129,6 @@ RB_METHOD(journalSet)
|
|||
// We don't have a pipe open, so spawn the connection thread
|
||||
thread = SDL_CreateThread(server_thread, "journal", NULL);
|
||||
}
|
||||
#else
|
||||
#error "not yet implemented"
|
||||
#endif
|
||||
return Qnil;
|
||||
}
|
||||
|
|
@ -130,7 +142,7 @@ RB_METHOD(journalActive)
|
|||
void journalBindingInit()
|
||||
{
|
||||
mutex = SDL_CreateMutex();
|
||||
#if defined __linux
|
||||
#ifdef LINUX
|
||||
mkfifo(PIPE_PATH, 0666);
|
||||
atexit(cleanup_pipe);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
|
||||
#if defined _WIN32
|
||||
#include <shlwapi.h>
|
||||
#elif defined __APPLE__ || __linux__
|
||||
#define LINUX
|
||||
#ifdef __APPLE__
|
||||
#define OS_OSX
|
||||
#else
|
||||
#define OS_LINUX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
|
|
@ -43,7 +50,7 @@ RB_METHOD(nikoStart)
|
|||
si.cb = sizeof(si);
|
||||
PROCESS_INFORMATION pi;
|
||||
CreateProcessW(path, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
||||
#elif defined __linux
|
||||
#elif defined LINUX
|
||||
// Calculate where to stick the window
|
||||
int x, y; // Top-left area of client (hopefully)
|
||||
SDL_GetWindowPosition(shState->rtData().window, &x, &y);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,53 @@ unix:!macx {
|
|||
|
||||
# OS X
|
||||
macx {
|
||||
# Directly copied from Linux, assuming this works but unsure
|
||||
|
||||
SOURCES += \
|
||||
mac/main.c \
|
||||
mac/niko.c \
|
||||
mac/journal.c \
|
||||
mac/image/niko1.c \
|
||||
mac/image/niko2.c \
|
||||
mac/image/niko3.c \
|
||||
mac/image/default.c \
|
||||
mac/image/c1.c \
|
||||
mac/image/c2.c \
|
||||
mac/image/c3.c \
|
||||
mac/image/c4.c \
|
||||
mac/image/c5.c \
|
||||
mac/image/c6.c \
|
||||
mac/image/c7.c \
|
||||
mac/image/s1.c \
|
||||
mac/image/s2.c \
|
||||
mac/image/s3.c \
|
||||
mac/image/s4.c \
|
||||
mac/image/t1.c \
|
||||
mac/image/t2.c \
|
||||
mac/image/t3.c \
|
||||
mac/image/t4.c \
|
||||
mac/image/t5.c \
|
||||
mac/image/t6.c \
|
||||
mac/image/t7.c \
|
||||
mac/image/t8.c \
|
||||
mac/image/t9.c \
|
||||
mac/image/t10.c \
|
||||
mac/image/t11.c \
|
||||
mac/image/t12.c \
|
||||
mac/image/t13.c \
|
||||
mac/image/t14.c \
|
||||
mac/image/t15.c \
|
||||
mac/image/t16.c \
|
||||
mac/image/final.c \
|
||||
mac/image/save.c
|
||||
|
||||
HEADERS += \
|
||||
mac/display.h \
|
||||
mac/image.h
|
||||
|
||||
QMAKE_CFLAGS += -pthread
|
||||
|
||||
LIBS += -pthread -lxcb -lxcb-util -lxcb-image -lxcb-shape -lxcb-icccm -lxcb-ewmh
|
||||
}
|
||||
|
||||
# Windows
|
||||
|
|
|
|||
17
journal/mac/display.h
Normal file
17
journal/mac/display.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef DISPLAY_H
|
||||
#define DISPLAY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
|
||||
struct Display {
|
||||
xcb_connection_t *c;
|
||||
xcb_screen_t *screen;
|
||||
};
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define STRING(x) sizeof(x) - 1, (x)
|
||||
#define ARRAY(x) sizeof(x), (x)
|
||||
|
||||
#endif // DISPLAY_H
|
||||
113
journal/mac/image.h
Normal file
113
journal/mac/image.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
#ifndef EMBED_H
|
||||
#define EMBED_H
|
||||
|
||||
#include <xcb/xcb_image.h>
|
||||
#include <xcb/shape.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
|
||||
static inline xcb_pixmap_t create_mask(xcb_connection_t *c,
|
||||
xcb_window_t win,
|
||||
unsigned char *bits,
|
||||
uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
return xcb_create_pixmap_from_bitmap_data(c, win, bits, width, height, 1, 0, 0, NULL);
|
||||
}
|
||||
|
||||
static inline xcb_pixmap_t create_image(xcb_connection_t *c,
|
||||
xcb_window_t win,
|
||||
unsigned char *bytes,
|
||||
uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
xcb_image_t *image = xcb_image_create_native(
|
||||
c, width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 24, NULL, width * height * 4, bytes);
|
||||
xcb_pixmap_t pixmap = xcb_generate_id(c);
|
||||
xcb_create_pixmap(c, 24, pixmap, win, width, height);
|
||||
xcb_gcontext_t gc = xcb_generate_id(c);
|
||||
xcb_create_gc(c, gc, pixmap, 0, NULL);
|
||||
xcb_image_put(c, pixmap, gc, image, 0, 0, 0);
|
||||
xcb_image_destroy(image);
|
||||
xcb_free_gc(c, gc);
|
||||
return pixmap;
|
||||
|
||||
}
|
||||
|
||||
static inline void set_shape(xcb_connection_t *c, xcb_window_t win, xcb_pixmap_t mask)
|
||||
{
|
||||
xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, mask);
|
||||
}
|
||||
|
||||
#define NIKO_WIDTH 48
|
||||
#define NIKO_HEIGHT 64
|
||||
extern unsigned char niko1_mask[];
|
||||
extern unsigned char niko1_rgb[];
|
||||
extern unsigned char niko2_mask[];
|
||||
extern unsigned char niko2_rgb[];
|
||||
extern unsigned char niko3_mask[];
|
||||
extern unsigned char niko3_rgb[];
|
||||
|
||||
#define JOURNAL_WIDTH 800
|
||||
#define JOURNAL_HEIGHT 600
|
||||
extern unsigned char default_mask[];
|
||||
extern unsigned char default_rgb[];
|
||||
extern unsigned char c1_mask[];
|
||||
extern unsigned char c1_rgb[];
|
||||
extern unsigned char c2_mask[];
|
||||
extern unsigned char c2_rgb[];
|
||||
extern unsigned char c3_mask[];
|
||||
extern unsigned char c3_rgb[];
|
||||
extern unsigned char c4_mask[];
|
||||
extern unsigned char c4_rgb[];
|
||||
extern unsigned char c5_mask[];
|
||||
extern unsigned char c5_rgb[];
|
||||
extern unsigned char c6_mask[];
|
||||
extern unsigned char c6_rgb[];
|
||||
extern unsigned char c7_mask[];
|
||||
extern unsigned char c7_rgb[];
|
||||
extern unsigned char s1_mask[];
|
||||
extern unsigned char s1_rgb[];
|
||||
extern unsigned char s2_mask[];
|
||||
extern unsigned char s2_rgb[];
|
||||
extern unsigned char s3_mask[];
|
||||
extern unsigned char s3_rgb[];
|
||||
extern unsigned char s4_mask[];
|
||||
extern unsigned char s4_rgb[];
|
||||
extern unsigned char t1_mask[];
|
||||
extern unsigned char t1_rgb[];
|
||||
extern unsigned char t2_mask[];
|
||||
extern unsigned char t2_rgb[];
|
||||
extern unsigned char t3_mask[];
|
||||
extern unsigned char t3_rgb[];
|
||||
extern unsigned char t4_mask[];
|
||||
extern unsigned char t4_rgb[];
|
||||
extern unsigned char t5_mask[];
|
||||
extern unsigned char t5_rgb[];
|
||||
extern unsigned char t6_mask[];
|
||||
extern unsigned char t6_rgb[];
|
||||
extern unsigned char t7_mask[];
|
||||
extern unsigned char t7_rgb[];
|
||||
extern unsigned char t8_mask[];
|
||||
extern unsigned char t8_rgb[];
|
||||
extern unsigned char t9_mask[];
|
||||
extern unsigned char t9_rgb[];
|
||||
extern unsigned char t10_mask[];
|
||||
extern unsigned char t10_rgb[];
|
||||
extern unsigned char t11_mask[];
|
||||
extern unsigned char t11_rgb[];
|
||||
extern unsigned char t12_mask[];
|
||||
extern unsigned char t12_rgb[];
|
||||
extern unsigned char t13_mask[];
|
||||
extern unsigned char t13_rgb[];
|
||||
extern unsigned char t14_mask[];
|
||||
extern unsigned char t14_rgb[];
|
||||
extern unsigned char t15_mask[];
|
||||
extern unsigned char t15_rgb[];
|
||||
extern unsigned char t16_mask[];
|
||||
extern unsigned char t16_rgb[];
|
||||
extern unsigned char final_mask[];
|
||||
extern unsigned char final_rgb[];
|
||||
extern unsigned char save_mask[];
|
||||
extern unsigned char save_rgb[];
|
||||
|
||||
#endif // EMBED_H
|
||||
1
journal/mac/image/.gitignore
vendored
Normal file
1
journal/mac/image/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.c
|
||||
12
journal/mac/image/pixmapper.sh
Executable file
12
journal/mac/image/pixmapper.sh
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "usage: pixmapper.sh <image>"
|
||||
exit 1
|
||||
fi
|
||||
basename="$(basename "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
name="${basename%.*}"
|
||||
cfile="$name.c"
|
||||
convert "$1" -alpha on -transparent '#00ff00' -alpha extract -negate xbm:- | sed "/^#define/d;s/-_bits/${name}_mask/g;s/^static char/unsigned char/" > "$cfile"
|
||||
echo "unsigned char ${name}_rgb[] = {" >> "$cfile"
|
||||
convert "$1" -alpha on -transparent '#00ff00' -depth 8 bgra:- | xxd -i >> "$cfile"
|
||||
echo "};" >> "$cfile"
|
||||
235
journal/mac/journal.c
Normal file
235
journal/mac/journal.c
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
#include <xcb/xcb_ewmh.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "image.h"
|
||||
|
||||
#define PIPE_DIR "/tmp"
|
||||
#define PIPE_NAME "oneshot-pipe"
|
||||
#define PIPE_PATH PIPE_DIR "/" PIPE_NAME
|
||||
#define MESSAGE_BUF_SIZE 256
|
||||
|
||||
#define PAGES \
|
||||
PAGE(default) \
|
||||
PAGE(c1) \
|
||||
PAGE(c2) \
|
||||
PAGE(c3) \
|
||||
PAGE(c4) \
|
||||
PAGE(c5) \
|
||||
PAGE(c6) \
|
||||
PAGE(c7) \
|
||||
PAGE(s1) \
|
||||
PAGE(s2) \
|
||||
PAGE(s3) \
|
||||
PAGE(s4) \
|
||||
PAGE(t1) \
|
||||
PAGE(t2) \
|
||||
PAGE(t3) \
|
||||
PAGE(t4) \
|
||||
PAGE(t5) \
|
||||
PAGE(t6) \
|
||||
PAGE(t7) \
|
||||
PAGE(t8) \
|
||||
PAGE(t9) \
|
||||
PAGE(t10) \
|
||||
PAGE(t11) \
|
||||
PAGE(t12) \
|
||||
PAGE(t13) \
|
||||
PAGE(t14) \
|
||||
PAGE(t15) \
|
||||
PAGE(t16) \
|
||||
PAGE(final) \
|
||||
PAGE(save)
|
||||
|
||||
struct ThreadData {
|
||||
struct Display *dpy;
|
||||
xcb_window_t window;
|
||||
xcb_gcontext_t gc;
|
||||
xcb_pixmap_t *masks;
|
||||
xcb_pixmap_t *images;
|
||||
volatile int page;
|
||||
};
|
||||
|
||||
void set_page(struct ThreadData *threaddata, const char *name)
|
||||
{
|
||||
int page = 0;
|
||||
#define PAGE(x) if (strncmp(name, #x, MESSAGE_BUF_SIZE) == 0) { goto end; } else { ++page; }
|
||||
PAGES
|
||||
#undef PAGE
|
||||
|
||||
end:
|
||||
threaddata->page = page;
|
||||
xcb_shape_mask(threaddata->dpy->c, ShapeSet, ShapeBounding,
|
||||
threaddata->window, 0, 0, threaddata->masks[page]);
|
||||
xcb_copy_area(threaddata->dpy->c,
|
||||
threaddata->images[page],
|
||||
threaddata->window,
|
||||
threaddata->gc,
|
||||
0, 0, 0, 0, JOURNAL_WIDTH, JOURNAL_HEIGHT);
|
||||
xcb_flush(threaddata->dpy->c);
|
||||
}
|
||||
|
||||
static void *ipc_thread(void *data)
|
||||
{
|
||||
struct ThreadData *threaddata = (struct ThreadData*)data;
|
||||
|
||||
for (;;) {
|
||||
// Try to open pipe
|
||||
int pipe = open(PIPE_PATH, O_RDONLY);
|
||||
if (pipe == -1) {
|
||||
// Use the default image for now
|
||||
set_page(threaddata, "default");
|
||||
// Wait until the pipe appears to try again
|
||||
int inotify = inotify_init();
|
||||
inotify_add_watch(inotify, PIPE_DIR, IN_CREATE);
|
||||
char inotify_buf[sizeof(struct inotify_event) + NAME_MAX + 1];
|
||||
for (;;) {
|
||||
ssize_t result = read(inotify, inotify_buf, sizeof(inotify_buf));
|
||||
if (result > 0) {
|
||||
struct inotify_event *e = (struct inotify_event*)inotify_buf;
|
||||
if (strcmp(e->name, PIPE_NAME) == 0)
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(inotify);
|
||||
} else {
|
||||
// Message loop
|
||||
char message[MESSAGE_BUF_SIZE];
|
||||
for (;;) {
|
||||
ssize_t len = read(pipe, message, sizeof(message));
|
||||
if (len > 0) {
|
||||
set_page(threaddata, message);
|
||||
} else if (len == 0) {
|
||||
exit(0); // empty string
|
||||
} else {
|
||||
// End of the line
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(pipe);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int do_journal(struct Display *dpy)
|
||||
{
|
||||
// Connect EWMH
|
||||
xcb_ewmh_connection_t ewmh;
|
||||
xcb_ewmh_init_atoms_replies(&ewmh, xcb_ewmh_init_atoms(dpy->c, &ewmh), NULL);
|
||||
|
||||
// Request some atoms
|
||||
xcb_intern_atom_cookie_t WM_DELETE_WINDOW_cookie = xcb_intern_atom(dpy->c, false, STRING("WM_DELETE_WINDOW"));
|
||||
xcb_intern_atom_cookie_t _NET_WM_PING_cookie = xcb_intern_atom(dpy->c, false, STRING("_NET_WM_PING"));
|
||||
xcb_intern_atom_cookie_t WM_PROTOCOLS_cookie = xcb_intern_atom(dpy->c, false, STRING("WM_PROTOCOLS"));
|
||||
xcb_atom_t WM_DELETE_WINDOW = xcb_intern_atom_reply(dpy->c, WM_DELETE_WINDOW_cookie, NULL)->atom;
|
||||
xcb_atom_t _NET_WM_PING = xcb_intern_atom_reply(dpy->c, _NET_WM_PING_cookie, NULL)->atom;
|
||||
xcb_atom_t WM_PROTOCOLS = xcb_intern_atom_reply(dpy->c, WM_PROTOCOLS_cookie, NULL)->atom;
|
||||
|
||||
// Create window
|
||||
uint32_t values[] = {
|
||||
XCB_EVENT_MASK_EXPOSURE, // event mask
|
||||
};
|
||||
xcb_window_t window = xcb_generate_id(dpy->c);
|
||||
xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root,
|
||||
0, 0, JOURNAL_WIDTH, JOURNAL_HEIGHT,
|
||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual,
|
||||
XCB_CW_EVENT_MASK, &values);
|
||||
|
||||
xcb_atom_t protocols[] = {
|
||||
WM_DELETE_WINDOW,
|
||||
_NET_WM_PING,
|
||||
};
|
||||
xcb_icccm_set_wm_protocols(dpy->c, window, WM_PROTOCOLS, ARRAY(protocols));
|
||||
|
||||
xcb_icccm_set_wm_name(dpy->c, window, XCB_ATOM_STRING, 8, STRING(""));
|
||||
xcb_icccm_set_wm_class(dpy->c, window, ARRAY("_______\0OneshotJournal"));
|
||||
xcb_ewmh_set_wm_window_type(&ewmh, window, 1, &ewmh._NET_WM_WINDOW_TYPE_NORMAL);
|
||||
|
||||
xcb_size_hints_t size_hints;
|
||||
xcb_icccm_size_hints_set_min_size(&size_hints, JOURNAL_WIDTH, JOURNAL_HEIGHT);
|
||||
xcb_icccm_size_hints_set_max_size(&size_hints, JOURNAL_WIDTH, JOURNAL_HEIGHT);
|
||||
xcb_icccm_set_wm_size_hints(dpy->c, window, XCB_ATOM_WM_NORMAL_HINTS, &size_hints);
|
||||
|
||||
// Create pixmaps
|
||||
xcb_pixmap_t masks[] = {
|
||||
#define PAGE(x) create_mask(dpy->c, window, x##_mask, JOURNAL_WIDTH, JOURNAL_HEIGHT),
|
||||
PAGES
|
||||
#undef PAGE
|
||||
};
|
||||
xcb_pixmap_t images[] = {
|
||||
#define PAGE(x) create_image(dpy->c, window, x##_rgb, JOURNAL_WIDTH, JOURNAL_HEIGHT),
|
||||
PAGES
|
||||
#undef PAGE
|
||||
};
|
||||
|
||||
// Create graphics context
|
||||
xcb_gcontext_t gc = xcb_generate_id(dpy->c);
|
||||
xcb_create_gc(dpy->c, gc, window, 0, NULL);
|
||||
|
||||
// Start IPC thread
|
||||
struct ThreadData threaddata = {
|
||||
dpy,
|
||||
window,
|
||||
gc,
|
||||
masks,
|
||||
images,
|
||||
0,
|
||||
};
|
||||
pthread_t thread;
|
||||
if (pthread_create(&thread, NULL, ipc_thread, &threaddata) != 0)
|
||||
return 1;
|
||||
|
||||
// Map!
|
||||
xcb_map_window(dpy->c, window);
|
||||
xcb_flush(dpy->c);
|
||||
|
||||
// Handle events
|
||||
xcb_generic_event_t *e;
|
||||
while ((e = xcb_wait_for_event(dpy->c))) {
|
||||
switch (e->response_type & ~0x80) {
|
||||
case XCB_EXPOSE: {
|
||||
xcb_expose_event_t *ee = (xcb_expose_event_t*)e;
|
||||
xcb_copy_area(dpy->c, images[threaddata.page],
|
||||
window, gc,
|
||||
ee->x, ee->y, ee->x, ee->y,
|
||||
ee->width, ee->height);
|
||||
xcb_flush(dpy->c);
|
||||
} break;
|
||||
case XCB_CLIENT_MESSAGE: {
|
||||
xcb_client_message_event_t *ce = (xcb_client_message_event_t*)e;
|
||||
if (ce->type == WM_PROTOCOLS && ce->format == 32) {
|
||||
xcb_atom_t atom = ce->data.data32[0];
|
||||
if (atom == WM_DELETE_WINDOW) {
|
||||
goto end;
|
||||
} else if (atom == _NET_WM_PING) {
|
||||
ce->window = dpy->screen->root;
|
||||
xcb_send_event(dpy->c, false, dpy->screen->root,
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
|
||||
(const char*)e);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
free(e);
|
||||
}
|
||||
|
||||
end:
|
||||
xcb_free_gc(dpy->c, gc);
|
||||
for (size_t i = 0; i < ARRAY_SIZE(masks); ++i) {
|
||||
xcb_free_pixmap(dpy->c, masks[i]);
|
||||
xcb_free_pixmap(dpy->c, images[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
26
journal/mac/main.c
Normal file
26
journal/mac/main.c
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include "display.h"
|
||||
|
||||
extern int do_niko(struct Display *dpy, int x, int y);
|
||||
extern int do_journal(struct Display *dpy);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Connect
|
||||
struct Display dpy;
|
||||
dpy.c = xcb_connect(NULL, NULL);
|
||||
dpy.screen = xcb_setup_roots_iterator(xcb_get_setup(dpy.c)).data;
|
||||
|
||||
int result;
|
||||
if (argc == 3) {
|
||||
// argc == 3, assume niko
|
||||
int x = atoi(argv[1]);
|
||||
int y = atoi(argv[2]);
|
||||
result = do_niko(&dpy, x, y);
|
||||
} else {
|
||||
// argc == 3, assume journal
|
||||
result = do_journal(&dpy);
|
||||
}
|
||||
|
||||
xcb_disconnect(dpy.c);
|
||||
return result;
|
||||
}
|
||||
114
journal/mac/niko.c
Normal file
114
journal/mac/niko.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#include <sys/time.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "image.h"
|
||||
|
||||
static uint64_t getticks()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
static void draw_niko(xcb_connection_t *c,
|
||||
xcb_window_t win,
|
||||
xcb_gcontext_t gc,
|
||||
xcb_pixmap_t masks[3],
|
||||
xcb_pixmap_t images[3],
|
||||
int x, int y, int w, int h,
|
||||
int offset)
|
||||
{
|
||||
int frame;
|
||||
if (offset % 32 >= 16) {
|
||||
frame = 1;
|
||||
} else {
|
||||
if ((offset / 32) % 2)
|
||||
frame = 0;
|
||||
else
|
||||
frame = 2;
|
||||
}
|
||||
xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, masks[frame]);
|
||||
xcb_copy_area(c, images[frame], win, gc, x, y, x, y, w, h);
|
||||
|
||||
}
|
||||
|
||||
int do_niko(struct Display *dpy, int x, int y)
|
||||
{
|
||||
// Create window
|
||||
uint32_t values[] = {
|
||||
true, // override_redirect
|
||||
XCB_EVENT_MASK_EXPOSURE, // event mask
|
||||
};
|
||||
xcb_window_t window = xcb_generate_id(dpy->c);
|
||||
xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root,
|
||||
x, y, NIKO_WIDTH, NIKO_HEIGHT,
|
||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual,
|
||||
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, &values);
|
||||
|
||||
// Stick window on top
|
||||
xcb_stack_mode_t stack = XCB_STACK_MODE_ABOVE;
|
||||
xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_STACK_MODE, &stack);
|
||||
|
||||
// Create pixmaps
|
||||
xcb_pixmap_t niko_masks[] = {
|
||||
create_mask(dpy->c, window, niko1_mask, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_mask(dpy->c, window, niko2_mask, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_mask(dpy->c, window, niko3_mask, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
};
|
||||
xcb_pixmap_t niko_images[] = {
|
||||
create_image(dpy->c, window, niko1_rgb, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_image(dpy->c, window, niko2_rgb, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_image(dpy->c, window, niko3_rgb, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
};
|
||||
|
||||
// Create graphics context
|
||||
xcb_gcontext_t gc = xcb_generate_id(dpy->c);
|
||||
xcb_create_gc(dpy->c, gc, window, 0, NULL);
|
||||
|
||||
// Map!
|
||||
xcb_map_window(dpy->c, window);
|
||||
xcb_flush(dpy->c);
|
||||
|
||||
// Niko movement info
|
||||
int niko_offset = 0;
|
||||
|
||||
uint64_t ticks = getticks();
|
||||
for (;;) {
|
||||
// Handle events
|
||||
for (;;) {
|
||||
xcb_generic_event_t *e = xcb_poll_for_event(dpy->c);
|
||||
if (e) {
|
||||
switch (e->response_type) {
|
||||
case XCB_EXPOSE: {
|
||||
xcb_expose_event_t *ee = (xcb_expose_event_t*)e;
|
||||
draw_niko(dpy->c, window, gc, niko_masks, niko_images,
|
||||
ee->x, ee->y, ee->width, ee->height, niko_offset);
|
||||
xcb_flush(dpy->c);
|
||||
} break;
|
||||
}
|
||||
free(e);
|
||||
} else if (getticks() - ticks >= 1000 / 60) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Move niko
|
||||
niko_offset += 2;
|
||||
int new_y = y + niko_offset;
|
||||
if (new_y > dpy->screen->height_in_pixels)
|
||||
break;
|
||||
xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_Y, &new_y);
|
||||
draw_niko(dpy->c, window, gc, niko_masks, niko_images, 0, 0, NIKO_WIDTH, NIKO_HEIGHT, niko_offset);
|
||||
xcb_flush(dpy->c);
|
||||
ticks = getticks();
|
||||
}
|
||||
|
||||
// Free up stuff
|
||||
xcb_free_gc(dpy->c, gc);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
xcb_free_pixmap(dpy->c, niko_masks[i]);
|
||||
xcb_free_pixmap(dpy->c, niko_images[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
18
mkxp.pro
18
mkxp.pro
|
|
@ -24,15 +24,6 @@ contains(BINDING, MRI) {
|
|||
CONFIG += BINDING_MRI
|
||||
}
|
||||
|
||||
contains(BINDING, MRUBY) {
|
||||
contains(_HAVE_BINDING, YES) {
|
||||
error("Only one binding may be selected")
|
||||
}
|
||||
_HAVE_BINDING = YES
|
||||
|
||||
CONFIG += BINDING_MRUBY
|
||||
}
|
||||
|
||||
contains(BINDING, NULL) {
|
||||
contains(_HAVE_BINDING, YES) {
|
||||
error("Only one binding may be selected")
|
||||
|
|
@ -45,12 +36,13 @@ contains(BINDING, NULL) {
|
|||
unix {
|
||||
CONFIG += c++11
|
||||
PKGCONFIG += sigc++-2.0 pixman-1 vorbisfile \
|
||||
sdl2 SDL2_image SDL2_ttf SDL_sound physfs
|
||||
LIBS += -ldl
|
||||
sdl2 SDL2_image SDL2_ttf SDL_sound physfs
|
||||
LIBS += -ldl
|
||||
macx: {
|
||||
CONFIG -= app_bundle
|
||||
#CONFIG -= app_bundle
|
||||
INCLUDEPATH += $$QMAKE_MAC_SDK_PATH/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers
|
||||
LIBS += -framework OpenAL
|
||||
QMAKE_LFLAGS += -L/usr/local/opt/ruby21/lib -L/usr/local/opt/openal-soft/lib
|
||||
}
|
||||
!macx: {
|
||||
PKGCONFIG += openal zlib
|
||||
|
|
@ -252,7 +244,7 @@ BINDING_NULL {
|
|||
|
||||
BINDING_MRI {
|
||||
isEmpty(MRIVERSION) {
|
||||
MRIVERSION = 2.2
|
||||
MRIVERSION = 2.1
|
||||
}
|
||||
|
||||
PKGCONFIG += ruby-$$MRIVERSION
|
||||
|
|
|
|||
128
src/oneshot.cpp
128
src/oneshot.cpp
|
|
@ -18,50 +18,54 @@
|
|||
#include <security.h>
|
||||
#include <shlobj.h>
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
#elif defined __APPLE__
|
||||
#define OS_OSX
|
||||
#include <pwd.h>
|
||||
#elif defined __linux__
|
||||
#define OS_LINUX
|
||||
#elif defined __APPLE__ || __linux__
|
||||
#ifdef __APPLE__
|
||||
#define OS_OSX
|
||||
#else
|
||||
#define OS_LINUX
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
class GtkWidget;
|
||||
#ifdef OS_LINUX
|
||||
class GtkWidget;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_MESSAGE_WARNING,
|
||||
GTK_MESSAGE_QUESTION,
|
||||
GTK_MESSAGE_ERROR
|
||||
} GtkMessageType;
|
||||
typedef enum
|
||||
{
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_MESSAGE_WARNING,
|
||||
GTK_MESSAGE_QUESTION,
|
||||
GTK_MESSAGE_ERROR
|
||||
} GtkMessageType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GTK_BUTTONS_NONE,
|
||||
GTK_BUTTONS_OK,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
GTK_BUTTONS_CANCEL,
|
||||
GTK_BUTTONS_YES_NO,
|
||||
GTK_BUTTONS_OK_CANCEL
|
||||
} GtkButtonsType;
|
||||
typedef enum
|
||||
{
|
||||
GTK_BUTTONS_NONE,
|
||||
GTK_BUTTONS_OK,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
GTK_BUTTONS_CANCEL,
|
||||
GTK_BUTTONS_YES_NO,
|
||||
GTK_BUTTONS_OK_CANCEL
|
||||
} GtkButtonsType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GTK_RESPONSE_NONE = -1,
|
||||
GTK_RESPONSE_REJECT = -2,
|
||||
GTK_RESPONSE_ACCEPT = -3,
|
||||
GTK_RESPONSE_DELETE_EVENT = -4,
|
||||
GTK_RESPONSE_OK = -5,
|
||||
GTK_RESPONSE_CANCEL = -6,
|
||||
GTK_RESPONSE_CLOSE = -7,
|
||||
GTK_RESPONSE_YES = -8,
|
||||
GTK_RESPONSE_NO = -9,
|
||||
GTK_RESPONSE_APPLY = -10,
|
||||
GTK_RESPONSE_HELP = -11
|
||||
} GtkResponseType;
|
||||
typedef enum
|
||||
{
|
||||
GTK_RESPONSE_NONE = -1,
|
||||
GTK_RESPONSE_REJECT = -2,
|
||||
GTK_RESPONSE_ACCEPT = -3,
|
||||
GTK_RESPONSE_DELETE_EVENT = -4,
|
||||
GTK_RESPONSE_OK = -5,
|
||||
GTK_RESPONSE_CANCEL = -6,
|
||||
GTK_RESPONSE_CLOSE = -7,
|
||||
GTK_RESPONSE_YES = -8,
|
||||
GTK_RESPONSE_NO = -9,
|
||||
GTK_RESPONSE_APPLY = -10,
|
||||
GTK_RESPONSE_HELP = -11
|
||||
} GtkResponseType;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* xdg_user_dir_lookup_with_fallback:
|
||||
|
|
@ -422,28 +426,46 @@ Oneshot::Oneshot(RGSSThreadData &threadData) :
|
|||
else
|
||||
p->lang = "en";
|
||||
|
||||
//Get user's name
|
||||
struct passwd *pwd = getpwuid(getuid());
|
||||
if (pwd)
|
||||
{
|
||||
if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',')
|
||||
{
|
||||
//Get the user's full name
|
||||
int comma = 0;
|
||||
for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {}
|
||||
p->userName = std::string(pwd->pw_gecos, comma);
|
||||
}
|
||||
else
|
||||
p->userName = pwd->pw_name;
|
||||
}
|
||||
#ifdef OS_OSX
|
||||
|
||||
//Get user's name
|
||||
struct passwd *pwd = getpwuid(geteuid());
|
||||
if (pwd)
|
||||
{
|
||||
if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',')
|
||||
{
|
||||
//Get the user's full name
|
||||
int comma = 0;
|
||||
for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {}
|
||||
p->userName = std::string(pwd->pw_gecos, comma);
|
||||
}
|
||||
else
|
||||
p->userName = pwd->pw_name;
|
||||
}
|
||||
|
||||
#elif defined OS_LINUX
|
||||
|
||||
//Get user's name
|
||||
struct passwd *pwd = getpwuid(getuid());
|
||||
if (pwd)
|
||||
{
|
||||
if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',')
|
||||
{
|
||||
//Get the user's full name
|
||||
int comma = 0;
|
||||
for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {}
|
||||
p->userName = std::string(pwd->pw_gecos, comma);
|
||||
}
|
||||
else
|
||||
p->userName = pwd->pw_name;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OS_LINUX
|
||||
//Get documents path
|
||||
char *path = xdg_user_dir_lookup_with_fallback("DOCUMENTS", getenv("HOME"));
|
||||
p->docsPath = path;
|
||||
free(path);
|
||||
#elif OS_OSX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**********
|
||||
|
|
|
|||
Loading…
Reference in a new issue