mirror of https://github.com/bsnes-emu/bsnes.git
Update to v085r01 release.
byuu says: Changelog: - updated bsnes to use the newest versions of nall and phoenix - fixed ui-libsnes compilation (testing would be a good idea, especially the cheat codes. I just copy-pasted that from the regular UI.) - fixed multitap controllers 2-4 [quequotion]
This commit is contained in:
parent
ba081d309e
commit
cc518dcc3c
|
@ -32,7 +32,7 @@ namespace nall {
|
|||
string desc;
|
||||
type_t type;
|
||||
|
||||
string get() const {
|
||||
inline string get() const {
|
||||
switch(type) {
|
||||
case boolean_t: return { *(bool*)data };
|
||||
case signed_t: return { *(signed*)data };
|
||||
|
@ -43,7 +43,7 @@ namespace nall {
|
|||
return "???";
|
||||
}
|
||||
|
||||
void set(string s) {
|
||||
inline void set(string s) {
|
||||
switch(type) {
|
||||
case boolean_t: *(bool*)data = (s == "true"); break;
|
||||
case signed_t: *(signed*)data = integer(s); break;
|
||||
|
@ -56,7 +56,7 @@ namespace nall {
|
|||
linear_vector<item_t> list;
|
||||
|
||||
template<typename T>
|
||||
void attach(T &data, const char *name, const char *desc = "") {
|
||||
inline void append(T &data, const char *name, const char *desc = "") {
|
||||
unsigned n = list.size();
|
||||
list[n].data = (uintptr_t)&data;
|
||||
list[n].name = name;
|
||||
|
@ -70,7 +70,13 @@ namespace nall {
|
|||
else list[n].type = unknown_t;
|
||||
}
|
||||
|
||||
virtual bool load(const string &filename) {
|
||||
//deprecated
|
||||
template<typename T>
|
||||
inline void attach(T &data, const char *name, const char *desc = "") {
|
||||
append(data, name, desc);
|
||||
}
|
||||
|
||||
inline virtual bool load(const string &filename) {
|
||||
string data;
|
||||
if(data.readfile(filename) == true) {
|
||||
data.replace("\r", "");
|
||||
|
@ -100,7 +106,7 @@ namespace nall {
|
|||
}
|
||||
}
|
||||
|
||||
virtual bool save(const string &filename) const {
|
||||
inline virtual bool save(const string &filename) const {
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode::write)) {
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
|
|
|
@ -134,12 +134,12 @@ namespace nall {
|
|||
file_offset = req_offset;
|
||||
}
|
||||
|
||||
int offset() {
|
||||
int offset() const {
|
||||
if(!fp) return -1; //file not open
|
||||
return file_offset;
|
||||
}
|
||||
|
||||
int size() {
|
||||
int size() const {
|
||||
if(!fp) return -1; //file not open
|
||||
return file_size;
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ namespace nall {
|
|||
}
|
||||
}
|
||||
|
||||
bool open() {
|
||||
bool open() const {
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@ struct gzip {
|
|||
uint8_t *data;
|
||||
unsigned size;
|
||||
|
||||
bool decompress(const string &filename);
|
||||
bool decompress(const uint8_t *data, unsigned size);
|
||||
inline bool decompress(const string &filename);
|
||||
inline bool decompress(const uint8_t *data, unsigned size);
|
||||
|
||||
gzip();
|
||||
~gzip();
|
||||
inline gzip();
|
||||
inline ~gzip();
|
||||
};
|
||||
|
||||
bool gzip::decompress(const string &filename) {
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
#ifndef NALL_HID_HPP
|
||||
#define NALL_HID_HPP
|
||||
|
||||
#include <nall/xorg/xorg.hpp>
|
||||
#include <nall/input.hpp>
|
||||
|
||||
namespace nall {
|
||||
namespace HID {
|
||||
|
||||
struct Keyboard {
|
||||
XlibDisplay *display;
|
||||
|
||||
inline void poll() {
|
||||
XQueryKeymap(display, state);
|
||||
}
|
||||
|
||||
inline bool operator[](unsigned id) {
|
||||
return state[scancode[id] >> 3] & (1 << (scancode[id] & 7));
|
||||
}
|
||||
|
||||
inline Keyboard() {
|
||||
display = XOpenDisplay(0);
|
||||
memset(&scancode, 0, sizeof scancode);
|
||||
|
||||
#define map(key, sym) scancode[key] = XKeysymToKeycode(display, sym)
|
||||
|
||||
using nall::Keyboard;
|
||||
map(Keyboard::Insert, XK_Insert);
|
||||
map(Keyboard::Delete, XK_Delete);
|
||||
map(Keyboard::Home, XK_Home);
|
||||
map(Keyboard::End, XK_End);
|
||||
map(Keyboard::PageUp, XK_Prior);
|
||||
map(Keyboard::PageDown, XK_Next);
|
||||
|
||||
map(Keyboard::Up, XK_Up);
|
||||
map(Keyboard::Down, XK_Down);
|
||||
map(Keyboard::Left, XK_Left);
|
||||
map(Keyboard::Right, XK_Right);
|
||||
|
||||
#undef map
|
||||
}
|
||||
|
||||
inline ~Keyboard() {
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
private:
|
||||
char state[32];
|
||||
uint8_t scancode[256];
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -117,7 +117,7 @@ struct http {
|
|||
}
|
||||
}
|
||||
} else if(auto position = header.iposition("\r\nContent-Length: ")) {
|
||||
unsigned length = decimal((const char*)header + position() + 16);
|
||||
unsigned length = decimal((const char*)header + position() + 18);
|
||||
while(length) {
|
||||
char buffer[256];
|
||||
int packetlength = recv(serversocket, buffer, min(256, length), 0);
|
||||
|
|
|
@ -193,8 +193,8 @@ bool image::load(const string &filename) {
|
|||
}
|
||||
|
||||
void image::scale(unsigned outputWidth, unsigned outputHeight, interpolation op) {
|
||||
scaleX(outputWidth, op);
|
||||
scaleY(outputHeight, op);
|
||||
if(width != outputWidth) scaleX(outputWidth, op);
|
||||
if(height != outputHeight) scaleY(outputHeight, op);
|
||||
}
|
||||
|
||||
void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) {
|
||||
|
@ -284,6 +284,7 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
|
|||
uint8_t *outputData = new uint8_t[outputWidth * height * stride];
|
||||
unsigned outputPitch = outputWidth * stride;
|
||||
double step = (double)width / (double)outputWidth;
|
||||
const uint8_t *terminal = data + pitch * height;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
|
@ -291,15 +292,12 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
|
|||
uint8_t *sp = data + pitch * y;
|
||||
|
||||
double fraction = 0.0;
|
||||
uint64_t s[4] = { read(sp), read(sp), read(sp), read(sp) };
|
||||
uint64_t s[4] = { sp < terminal ? read(sp) : 0 }; //B,C (0,1) = center of kernel { 0, 0, 1, 2 }
|
||||
s[1] = s[0];
|
||||
s[2] = sp + stride < terminal ? read(sp += stride) : s[1];
|
||||
s[3] = sp + stride < terminal ? read(sp += stride) : s[2];
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
if(sp >= data + pitch * height) break;
|
||||
s[0] = s[1];
|
||||
s[1] = s[2];
|
||||
s[2] = s[3];
|
||||
s[3] = read(sp);
|
||||
|
||||
while(fraction <= 1.0) {
|
||||
if(dp >= outputData + outputPitch * height) break;
|
||||
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
|
||||
|
@ -307,7 +305,8 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
|
|||
fraction += step;
|
||||
}
|
||||
|
||||
sp += stride;
|
||||
s[0] = s[1]; s[1] = s[2]; s[2] = s[3];
|
||||
if(sp + stride < terminal) s[3] = read(sp += stride);
|
||||
fraction -= 1.0;
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +320,7 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
|
|||
void image::scaleY(unsigned outputHeight, interpolation op) {
|
||||
uint8_t *outputData = new uint8_t[width * outputHeight * stride];
|
||||
double step = (double)height / (double)outputHeight;
|
||||
const uint8_t *terminal = data + pitch * height;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
|
@ -328,15 +328,12 @@ void image::scaleY(unsigned outputHeight, interpolation op) {
|
|||
uint8_t *sp = data + stride * x;
|
||||
|
||||
double fraction = 0.0;
|
||||
uint64_t s[4] = { read(sp), read(sp), read(sp), read(sp) };
|
||||
uint64_t s[4] = { sp < terminal ? read(sp) : 0 };
|
||||
s[1] = s[0];
|
||||
s[2] = sp + pitch < terminal ? read(sp += pitch) : s[1];
|
||||
s[3] = sp + pitch < terminal ? read(sp += pitch) : s[2];
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
if(sp >= data + pitch * height) break;
|
||||
s[0] = s[1];
|
||||
s[1] = s[2];
|
||||
s[2] = s[3];
|
||||
s[3] = read(sp);
|
||||
|
||||
while(fraction <= 1.0) {
|
||||
if(dp >= outputData + pitch * outputHeight) break;
|
||||
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
|
||||
|
@ -344,7 +341,8 @@ void image::scaleY(unsigned outputHeight, interpolation op) {
|
|||
fraction += step;
|
||||
}
|
||||
|
||||
sp += pitch;
|
||||
s[0] = s[1]; s[1] = s[2]; s[2] = s[3];
|
||||
if(sp + pitch < terminal) s[3] = read(sp += pitch);
|
||||
fraction -= 1.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,23 +5,23 @@ namespace nall {
|
|||
|
||||
struct Interpolation {
|
||||
static inline double Nearest(double mu, double a, double b, double c, double d) {
|
||||
return (mu < 0.5 ? c : d);
|
||||
return (mu <= 0.5 ? b : c);
|
||||
}
|
||||
|
||||
static inline double Sublinear(double mu, double a, double b, double c, double d) {
|
||||
mu = ((mu - 0.5) * 2.0) + 0.5;
|
||||
if(mu < 0) mu = 0;
|
||||
if(mu > 1) mu = 1;
|
||||
return c * (1.0 - mu) + d * mu;
|
||||
return b * (1.0 - mu) + c * mu;
|
||||
}
|
||||
|
||||
static inline double Linear(double mu, double a, double b, double c, double d) {
|
||||
return c * (1.0 - mu) + d * mu;
|
||||
return b * (1.0 - mu) + c * mu;
|
||||
}
|
||||
|
||||
static inline double Cosine(double mu, double a, double b, double c, double d) {
|
||||
mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
|
||||
return c * (1.0 - mu) + d * mu;
|
||||
return b * (1.0 - mu) + c * mu;
|
||||
}
|
||||
|
||||
static inline double Cubic(double mu, double a, double b, double c, double d) {
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef NALL_MAP_HPP
|
||||
#define NALL_MAP_HPP
|
||||
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
struct map {
|
||||
struct pair {
|
||||
LHS name;
|
||||
RHS data;
|
||||
};
|
||||
|
||||
void reset() {
|
||||
list.reset();
|
||||
}
|
||||
|
||||
unsigned size() const {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
//O(n)
|
||||
void append(const LHS &name, const RHS &data) {
|
||||
signed offset = size();
|
||||
for(unsigned n = 0; n < size(); n++) {
|
||||
if(name < list[n].name) { offset = n; break; }
|
||||
}
|
||||
list.insert(offset, { name, data });
|
||||
}
|
||||
|
||||
//O(log n)
|
||||
RHS& operator[](const LHS &name) {
|
||||
signed first = 0, last = size() - 1;
|
||||
while(first <= last) {
|
||||
signed middle = (first + last) / 2;
|
||||
if(name < list[middle].name) last = middle - 1; //search lower half
|
||||
else if(name > list[middle].name) first = middle + 1; //search upper half
|
||||
else return list[middle].data; //match found
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
//O(log n) nothrow
|
||||
const RHS& operator()(const LHS &name, const RHS &data) {
|
||||
signed first = 0, last = size() - 1;
|
||||
while(first <= last) {
|
||||
signed middle = (first + last) / 2;
|
||||
if(name < list[middle].name) last = middle - 1; //search lower half
|
||||
else if(name > list[middle].name) first = middle + 1; //search upper half
|
||||
else return list[middle].data; //match found
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
pair* begin() { return list.begin(); }
|
||||
pair* end() { return list.end(); }
|
||||
const pair* begin() const { return list.begin(); }
|
||||
const pair* end() const { return list.end(); }
|
||||
|
||||
protected:
|
||||
vector<pair> list;
|
||||
};
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
struct bidirectional_map {
|
||||
map<LHS, RHS> lhs;
|
||||
map<RHS, LHS> rhs;
|
||||
|
||||
void reset() {
|
||||
lhs.reset();
|
||||
rhs.reset();
|
||||
}
|
||||
|
||||
unsigned size() const {
|
||||
return lhs.size();
|
||||
}
|
||||
|
||||
void append(const LHS &ldata, const RHS &rdata) {
|
||||
lhs.append(ldata, rdata);
|
||||
rhs.append(rdata, ldata);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef NALL_SORT_HPP
|
||||
#define NALL_SORT_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
//class: merge sort
|
||||
|
@ -29,7 +30,7 @@ namespace nall {
|
|||
for(unsigned j = i + 1; j < length; j++) {
|
||||
if(list[j] < list[min]) min = j;
|
||||
}
|
||||
if(min != i) swap(list[i], list[min]);
|
||||
if(min != i) std::swap(list[i], list[min]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef NALL_STREAM_HPP
|
||||
#define NALL_STREAM_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/filemap.hpp>
|
||||
#include <nall/gzip.hpp>
|
||||
#include <nall/http.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/zip.hpp>
|
||||
|
||||
#define NALL_STREAM_INTERNAL_HPP
|
||||
#include <nall/stream/stream.hpp>
|
||||
#include <nall/stream/memory.hpp>
|
||||
#include <nall/stream/mmap.hpp>
|
||||
#include <nall/stream/file.hpp>
|
||||
#include <nall/stream/http.hpp>
|
||||
#include <nall/stream/gzip.hpp>
|
||||
#include <nall/stream/zip.hpp>
|
||||
#include <nall/stream/auto.hpp>
|
||||
#undef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#ifdef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
#define autostream(...) (*makestream(__VA_ARGS__))
|
||||
|
||||
inline std::unique_ptr<stream> makestream(const string &path) {
|
||||
if(path.ibeginswith("http://")) return std::unique_ptr<stream>(new httpstream(path, 80));
|
||||
if(path.iendswith(".gz")) return std::unique_ptr<stream>(new gzipstream(filestream{path}));
|
||||
if(path.iendswith(".zip")) return std::unique_ptr<stream>(new zipstream(filestream{path}));
|
||||
return std::unique_ptr<stream>(new mmapstream(path));
|
||||
}
|
||||
|
||||
inline std::unique_ptr<stream> makestream(uint8_t *data, unsigned size) {
|
||||
return std::unique_ptr<stream>(new memorystream(data, size));
|
||||
}
|
||||
|
||||
inline std::unique_ptr<stream> makestream(const uint8_t *data, unsigned size) {
|
||||
return std::unique_ptr<stream>(new memorystream(data, size));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
#ifdef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct filestream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return pwritable; }
|
||||
inline bool randomaccess() const { return false; }
|
||||
|
||||
inline unsigned size() const { return pfile.size(); }
|
||||
inline unsigned offset() const { return pfile.offset(); }
|
||||
inline void seek(unsigned offset) const { pfile.seek(offset); }
|
||||
|
||||
inline uint8_t read() const { return pfile.read(); }
|
||||
inline void write(uint8_t data) const { pfile.write(data); }
|
||||
|
||||
inline filestream(const string &filename) {
|
||||
pfile.open(filename, file::mode::readwrite);
|
||||
pwritable = pfile.open();
|
||||
if(!pwritable) pfile.open(filename, file::mode::read);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable file pfile;
|
||||
bool pwritable;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
#ifdef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct gzipstream : memorystream {
|
||||
inline gzipstream(const stream &stream) {
|
||||
unsigned size = stream.size();
|
||||
uint8_t *data = new uint8_t[size];
|
||||
stream.read(data, size);
|
||||
|
||||
gzip archive;
|
||||
bool result = archive.decompress(data, size);
|
||||
delete[] data;
|
||||
if(result == false) return;
|
||||
|
||||
psize = archive.size;
|
||||
pdata = new uint8_t[psize];
|
||||
memcpy(pdata, archive.data, psize);
|
||||
}
|
||||
|
||||
inline ~gzipstream() {
|
||||
if(pdata) delete[] pdata;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
#ifdef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct httpstream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return true; }
|
||||
inline bool randomaccess() const { return true; }
|
||||
|
||||
inline unsigned size() const { return psize; }
|
||||
inline unsigned offset() const { return poffset; }
|
||||
inline void seek(unsigned offset) const { poffset = offset; }
|
||||
|
||||
inline uint8_t read() const { return pdata[poffset++]; }
|
||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||
|
||||
inline uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||
|
||||
inline httpstream(const string &url, unsigned port) : pdata(nullptr), psize(0), poffset(0) {
|
||||
string uri = url;
|
||||
uri.ltrim<1>("http://");
|
||||
lstring part = uri.split<1>("/");
|
||||
part[1] = { "/", part[1] };
|
||||
|
||||
http connection;
|
||||
if(connection.connect(part[0], port) == false) return;
|
||||
connection.download(part[1], pdata, psize);
|
||||
}
|
||||
|
||||
inline ~httpstream() {
|
||||
if(pdata) delete[] pdata;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable uint8_t *pdata;
|
||||
mutable unsigned psize, poffset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
#ifdef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct memorystream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return pwritable; }
|
||||
inline bool randomaccess() const { return true; }
|
||||
|
||||
inline unsigned size() const { return psize; }
|
||||
inline unsigned offset() const { return poffset; }
|
||||
inline void seek(unsigned offset) const { poffset = offset; }
|
||||
|
||||
inline uint8_t read() const { return pdata[poffset++]; }
|
||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||
|
||||
inline uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||
|
||||
inline memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {}
|
||||
|
||||
inline memorystream(uint8_t *data, unsigned size) {
|
||||
pdata = data, psize = size, poffset = 0;
|
||||
pwritable = true;
|
||||
}
|
||||
|
||||
inline memorystream(const uint8_t *data, unsigned size) {
|
||||
pdata = (uint8_t*)data, psize = size, poffset = 0;
|
||||
pwritable = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable uint8_t *pdata;
|
||||
mutable unsigned psize, poffset, pwritable;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
#ifdef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct mmapstream : stream {
|
||||
inline bool seekable() const { return true; }
|
||||
inline bool readable() const { return true; }
|
||||
inline bool writable() const { return pwritable; }
|
||||
inline bool randomaccess() const { return false; }
|
||||
|
||||
inline unsigned size() const { return pmmap.size(); }
|
||||
inline unsigned offset() const { return poffset; }
|
||||
inline void seek(unsigned offset) const { poffset = offset; }
|
||||
|
||||
inline uint8_t read() const { return pdata[poffset++]; }
|
||||
inline void write(uint8_t data) const { pdata[poffset++] = data; }
|
||||
|
||||
inline uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||
inline void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||
|
||||
inline mmapstream(const string &filename) {
|
||||
pmmap.open(filename, filemap::mode::readwrite);
|
||||
pwritable = pmmap.open();
|
||||
if(!pwritable) pmmap.open(filename, filemap::mode::read);
|
||||
pdata = pmmap.data(), poffset = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable filemap pmmap;
|
||||
mutable uint8_t *pdata;
|
||||
mutable unsigned pwritable, poffset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,90 @@
|
|||
#ifndef NALL_STREAM_STREAM_HPP
|
||||
#define NALL_STREAM_STREAM_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct stream {
|
||||
virtual bool seekable() const = 0;
|
||||
virtual bool readable() const = 0;
|
||||
virtual bool writable() const = 0;
|
||||
virtual bool randomaccess() const = 0;
|
||||
|
||||
virtual unsigned size() const = 0;
|
||||
virtual unsigned offset() const = 0;
|
||||
virtual void seek(unsigned offset) const = 0;
|
||||
|
||||
virtual uint8_t read() const = 0;
|
||||
virtual void write(uint8_t data) const = 0;
|
||||
|
||||
inline virtual uint8_t read(unsigned) const { return 0; }
|
||||
inline virtual void write(unsigned, uint8_t) const {}
|
||||
|
||||
inline bool end() const {
|
||||
return offset() >= size();
|
||||
}
|
||||
|
||||
inline void copy(uint8_t *&data, unsigned &length) const {
|
||||
seek(0);
|
||||
length = size();
|
||||
data = new uint8_t[length];
|
||||
for(unsigned n = 0; n < length; n++) data[n] = read();
|
||||
}
|
||||
|
||||
inline uintmax_t readl(unsigned length = 1) const {
|
||||
uintmax_t data = 0, shift = 0;
|
||||
while(length--) { data |= read() << shift; shift += 8; }
|
||||
return data;
|
||||
}
|
||||
|
||||
inline uintmax_t readm(unsigned length = 1) const {
|
||||
uintmax_t data = 0;
|
||||
while(length--) data = (data << 8) | read();
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void read(uint8_t *data, unsigned length) const {
|
||||
while(length--) *data++ = read();
|
||||
}
|
||||
|
||||
inline void writel(uintmax_t data, unsigned length = 1) const {
|
||||
while(length--) {
|
||||
write(data);
|
||||
data >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
inline void writem(uintmax_t data, unsigned length = 1) const {
|
||||
uintmax_t shift = 8 * length;
|
||||
while(length--) {
|
||||
shift -= 8;
|
||||
write(data >> shift);
|
||||
}
|
||||
}
|
||||
|
||||
inline void write(const uint8_t *data, unsigned length) const {
|
||||
while(length--) write(*data++);
|
||||
}
|
||||
|
||||
struct byte {
|
||||
inline operator uint8_t() const { return s.read(offset); }
|
||||
inline byte& operator=(uint8_t data) { s.write(offset, data); }
|
||||
inline byte(const stream &s, unsigned offset) : s(s), offset(offset) {}
|
||||
|
||||
private:
|
||||
const stream &s;
|
||||
const unsigned offset;
|
||||
};
|
||||
|
||||
inline byte operator[](unsigned offset) const {
|
||||
return byte(*this, offset);
|
||||
}
|
||||
|
||||
inline stream() {}
|
||||
inline virtual ~stream() {}
|
||||
stream(const stream&) = delete;
|
||||
stream& operator=(const stream&) = delete;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#ifdef NALL_STREAM_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct zipstream : memorystream {
|
||||
inline zipstream(const stream &stream, const string &filter = "*") {
|
||||
unsigned size = stream.size();
|
||||
uint8_t *data = new uint8_t[size];
|
||||
stream.read(data, size);
|
||||
|
||||
zip archive;
|
||||
if(archive.open(data, size) == false) return;
|
||||
delete[] data;
|
||||
|
||||
for(auto &file : archive.file) {
|
||||
if(file.name.wildcard(filter)) {
|
||||
archive.extract(file, pdata, psize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline ~zipstream() {
|
||||
if(pdata) delete[] pdata;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -35,7 +35,7 @@
|
|||
#include <nall/string/math-fixed-point.hpp>
|
||||
#include <nall/string/math-floating-point.hpp>
|
||||
#include <nall/string/platform.hpp>
|
||||
#include <nall/string/strl.hpp>
|
||||
#include <nall/string/strm.hpp>
|
||||
#include <nall/string/strpos.hpp>
|
||||
#include <nall/string/trim.hpp>
|
||||
#include <nall/string/replace.hpp>
|
||||
|
|
|
@ -151,9 +151,12 @@ namespace nall {
|
|||
inline string userpath();
|
||||
inline string currentpath();
|
||||
|
||||
//strl.hpp
|
||||
inline unsigned strlcpy(char *dest, const char *src, unsigned length);
|
||||
inline unsigned strlcat(char *dest, const char *src, unsigned length);
|
||||
//strm.hpp
|
||||
inline unsigned strmcpy(char *target, const char *source, unsigned length);
|
||||
inline unsigned strmcat(char *target, const char *source, unsigned length);
|
||||
inline bool strccpy(char *target, const char *source, unsigned length);
|
||||
inline bool strccat(char *target, const char *source, unsigned length);
|
||||
inline void strpcpy(char *&target, const char *source, unsigned &length);
|
||||
|
||||
//strpos.hpp
|
||||
inline optional<unsigned> strpos(const char *str, const char *key);
|
||||
|
@ -171,8 +174,6 @@ namespace nall {
|
|||
template<bool Insensitive> alwaysinline bool chrequal(char x, char y);
|
||||
template<bool Quoted, typename T> alwaysinline bool quoteskip(T *&p);
|
||||
template<bool Quoted, typename T> alwaysinline bool quotecopy(char *&t, T *&p);
|
||||
inline unsigned strlcpy(string &dest, const char *src, unsigned length);
|
||||
inline unsigned strlcat(string &dest, const char *src, unsigned length);
|
||||
inline string substr(const char *src, unsigned start = 0, unsigned length = ~0u);
|
||||
inline string sha256(const uint8_t *data, unsigned size);
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller
|
||||
|
||||
//return = strlen(src)
|
||||
unsigned strlcpy(char *dest, const char *src, unsigned length) {
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
unsigned n = length;
|
||||
|
||||
if(n) {
|
||||
while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached
|
||||
}
|
||||
|
||||
if(!n) {
|
||||
if(length) *d = 0;
|
||||
while(*s++); //traverse rest of s, so that s - src == strlen(src)
|
||||
}
|
||||
|
||||
return (s - src - 1); //return length of copied string, sans null terminator
|
||||
}
|
||||
|
||||
//return = strlen(src) + min(length, strlen(dest))
|
||||
unsigned strlcat(char *dest, const char *src, unsigned length) {
|
||||
char *d = dest;
|
||||
const char *s = src;
|
||||
unsigned n = length;
|
||||
|
||||
while(n-- && *d) d++; //find end of dest
|
||||
unsigned dlength = d - dest;
|
||||
n = length - dlength; //subtract length of dest from maximum string length
|
||||
|
||||
if(!n) return dlength + strlen(s);
|
||||
|
||||
while(*s) {
|
||||
if(n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = 0;
|
||||
|
||||
return dlength + (s - src); //return length of resulting string, sans null terminator
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
//
|
||||
//strmcpy, strmcat created by byuu
|
||||
//
|
||||
|
||||
//return = strlen(target)
|
||||
unsigned strmcpy(char *target, const char *source, unsigned length) {
|
||||
const char *origin = target;
|
||||
if(length) {
|
||||
while(*source && --length) *target++ = *source++;
|
||||
*target = 0;
|
||||
}
|
||||
return target - origin;
|
||||
}
|
||||
|
||||
//return = strlen(target)
|
||||
unsigned strmcat(char *target, const char *source, unsigned length) {
|
||||
const char *origin = target;
|
||||
while(*target && length) target++, length--;
|
||||
return (target - origin) + strmcpy(target, source, length);
|
||||
}
|
||||
|
||||
//return = true when all of source was copied
|
||||
bool strccpy(char *target, const char *source, unsigned length) {
|
||||
return !source[strmcpy(target, source, length)];
|
||||
}
|
||||
|
||||
//return = true when all of source was copied
|
||||
bool strccat(char *target, const char *source, unsigned length) {
|
||||
while(*target && length) target++, length--;
|
||||
return !source[strmcpy(target, source, length)];
|
||||
}
|
||||
|
||||
//return = reserved for future use
|
||||
void strpcpy(char *&target, const char *source, unsigned &length) {
|
||||
unsigned offset = strmcpy(target, source, length);
|
||||
target += offset, length -= offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -34,24 +34,15 @@ bool quotecopy(char *&t, T *&p) {
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned strlcpy(string &dest, const char *src, unsigned length) {
|
||||
dest.reserve(length);
|
||||
return strlcpy(dest(), src, length);
|
||||
}
|
||||
|
||||
unsigned strlcat(string &dest, const char *src, unsigned length) {
|
||||
dest.reserve(length);
|
||||
return strlcat(dest(), src, length);
|
||||
}
|
||||
|
||||
string substr(const char *src, unsigned start, unsigned length) {
|
||||
string dest;
|
||||
dest.reserve(length + 1);
|
||||
if(length == ~0u) {
|
||||
//copy entire string
|
||||
dest = src + start;
|
||||
strcpy(dest(), src + start);
|
||||
} else {
|
||||
//copy partial string
|
||||
strlcpy(dest, src + start, length + 1);
|
||||
strmcpy(dest(), src + start, length + 1);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
|
|
@ -9,12 +9,6 @@ namespace nall {
|
|||
template<typename T> struct enable_if<false, T> {};
|
||||
template<typename C, typename T = bool> struct mp_enable_if : enable_if<C::value, T> {};
|
||||
|
||||
template<typename T> inline void swap(T &x, T &y) {
|
||||
T temp(std::move(x));
|
||||
x = std::move(y);
|
||||
y = std::move(temp);
|
||||
}
|
||||
|
||||
template<typename T> struct base_from_member {
|
||||
T value;
|
||||
base_from_member(T value_) : value(value_) {}
|
||||
|
|
|
@ -55,15 +55,18 @@ namespace nall {
|
|||
new(pool + objectsize++) T(data);
|
||||
}
|
||||
|
||||
void prepend(const T& data) {
|
||||
void insert(unsigned position, const T& data) {
|
||||
append(data);
|
||||
for(unsigned n = objectsize - 1; n; n--) swap(pool[n], pool[n - 1]);
|
||||
for(signed n = size() - 1; n > position; n--) pool[n] = pool[n - 1];
|
||||
pool[position] = data;
|
||||
}
|
||||
|
||||
void prepend(const T& data) {
|
||||
insert(0, data);
|
||||
}
|
||||
|
||||
void remove(unsigned index, unsigned count = 1) {
|
||||
for(unsigned n = index; count + n < objectsize; n++) {
|
||||
pool[n] = pool[count + n];
|
||||
}
|
||||
for(unsigned n = index; count + n < objectsize; n++) pool[n] = pool[count + n];
|
||||
objectsize = (count + index >= objectsize) ? index : objectsize - count;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ static string iNES(const uint8_t *data, unsigned size) {
|
|||
"</cartridge>\n"
|
||||
);
|
||||
|
||||
print(output, "\n");
|
||||
//print(output, "\n");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,85 @@ Font::Font(const string &description):
|
|||
description(description) {
|
||||
}
|
||||
|
||||
//Desktop
|
||||
//=======
|
||||
|
||||
Size Desktop::size() {
|
||||
return pDesktop::size();
|
||||
}
|
||||
|
||||
Geometry Desktop::workspace() {
|
||||
return pDesktop::workspace();
|
||||
}
|
||||
|
||||
//Keyboard
|
||||
//========
|
||||
|
||||
bool Keyboard::pressed(Keyboard::Scancode scancode) {
|
||||
return pKeyboard::pressed(scancode);
|
||||
}
|
||||
|
||||
bool Keyboard::released(Keyboard::Scancode scancode) {
|
||||
return !pressed(scancode);
|
||||
}
|
||||
|
||||
array<bool> Keyboard::state() {
|
||||
return pKeyboard::state();
|
||||
}
|
||||
|
||||
//Mouse
|
||||
//=====
|
||||
|
||||
Position Mouse::position() {
|
||||
return pMouse::position();
|
||||
}
|
||||
|
||||
bool Mouse::pressed(Mouse::Button button) {
|
||||
return pMouse::pressed(button);
|
||||
}
|
||||
|
||||
bool Mouse::released(Mouse::Button button) {
|
||||
return !pressed(button);
|
||||
}
|
||||
|
||||
//DialogWindow
|
||||
//============
|
||||
|
||||
string DialogWindow::fileOpen_(Window &parent, const string &path, const lstring &filter_) {
|
||||
auto filter = filter_;
|
||||
if(filter.size() == 0) filter.append("All files (*)");
|
||||
return pDialogWindow::fileOpen(parent, path, filter);
|
||||
}
|
||||
|
||||
string DialogWindow::fileSave_(Window &parent, const string &path, const lstring &filter_) {
|
||||
auto filter = filter_;
|
||||
if(filter.size() == 0) filter.append("All files (*)");
|
||||
return pDialogWindow::fileSave(parent, path, filter);
|
||||
}
|
||||
|
||||
string DialogWindow::folderSelect(Window &parent, const string &path) {
|
||||
return pDialogWindow::folderSelect(parent, path);
|
||||
}
|
||||
|
||||
//MessageWindow
|
||||
//=============
|
||||
|
||||
MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::information(parent, text, buttons);
|
||||
}
|
||||
|
||||
MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::question(parent, text, buttons);
|
||||
}
|
||||
|
||||
MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::warning(parent, text, buttons);
|
||||
}
|
||||
|
||||
MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::critical(parent, text, buttons);
|
||||
}
|
||||
|
||||
//Object
|
||||
//======
|
||||
|
||||
|
@ -67,30 +146,6 @@ Object::~Object() {
|
|||
//OS
|
||||
//==
|
||||
|
||||
Geometry OS::availableGeometry() {
|
||||
return pOS::availableGeometry();
|
||||
}
|
||||
|
||||
Geometry OS::desktopGeometry() {
|
||||
return pOS::desktopGeometry();
|
||||
}
|
||||
|
||||
string OS::fileLoad_(Window &parent, const string &path, const lstring &filter_) {
|
||||
auto filter = filter_;
|
||||
if(filter.size() == 0) filter.append("All files (*)");
|
||||
return pOS::fileLoad(parent, path, filter);
|
||||
}
|
||||
|
||||
string OS::fileSave_(Window &parent, const string &path, const lstring &filter_) {
|
||||
auto filter = filter_;
|
||||
if(filter.size() == 0) filter.append("All files (*)");
|
||||
return pOS::fileSave(parent, path, filter);
|
||||
}
|
||||
|
||||
string OS::folderSelect(Window &parent, const string &path) {
|
||||
return pOS::folderSelect(parent, path);
|
||||
}
|
||||
|
||||
void OS::main() {
|
||||
return pOS::main();
|
||||
}
|
||||
|
@ -142,29 +197,10 @@ Timer::~Timer() {
|
|||
delete &state;
|
||||
}
|
||||
|
||||
//MessageWindow
|
||||
//=============
|
||||
|
||||
MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::information(parent, text, buttons);
|
||||
}
|
||||
|
||||
MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::question(parent, text, buttons);
|
||||
}
|
||||
|
||||
MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::warning(parent, text, buttons);
|
||||
}
|
||||
|
||||
MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
|
||||
return pMessageWindow::critical(parent, text, buttons);
|
||||
}
|
||||
|
||||
//Window
|
||||
//======
|
||||
|
||||
void Window::append(Layout &layout) {
|
||||
void Window::append_(Layout &layout) {
|
||||
if(state.layout.append(layout)) {
|
||||
((Sizable&)layout).state.window = this;
|
||||
((Sizable&)layout).state.layout = 0;
|
||||
|
@ -173,14 +209,14 @@ void Window::append(Layout &layout) {
|
|||
}
|
||||
}
|
||||
|
||||
void Window::append(Menu &menu) {
|
||||
void Window::append_(Menu &menu) {
|
||||
if(state.menu.append(menu)) {
|
||||
((Action&)menu).state.window = this;
|
||||
p.append(menu);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::append(Widget &widget) {
|
||||
void Window::append_(Widget &widget) {
|
||||
if(state.widget.append(widget)) {
|
||||
((Sizable&)widget).state.window = this;
|
||||
p.append(widget);
|
||||
|
@ -220,21 +256,21 @@ void Window::ignore() {
|
|||
state.ignore = true;
|
||||
}
|
||||
|
||||
void Window::remove(Layout &layout) {
|
||||
void Window::remove_(Layout &layout) {
|
||||
if(state.layout.remove(layout)) {
|
||||
p.remove(layout);
|
||||
((Sizable&)layout).state.window = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::remove(Menu &menu) {
|
||||
void Window::remove_(Menu &menu) {
|
||||
if(state.menu.remove(menu)) {
|
||||
p.remove(menu);
|
||||
((Action&)menu).state.window = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::remove(Widget &widget) {
|
||||
void Window::remove_(Widget &widget) {
|
||||
if(state.widget.remove(widget)) {
|
||||
p.remove(widget);
|
||||
((Sizable&)widget).state.window = 0;
|
||||
|
@ -376,17 +412,21 @@ Action::~Action() {
|
|||
//Menu
|
||||
//====
|
||||
|
||||
void Menu::append(Action &action) {
|
||||
if(state.action.append(action)) {
|
||||
action.state.menu = this;
|
||||
return p.append(action);
|
||||
void Menu::append(const reference_array<Action&> &list) {
|
||||
for(auto &action : list) {
|
||||
if(state.action.append(action)) {
|
||||
action.state.menu = this;
|
||||
p.append(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::remove(Action &action) {
|
||||
if(state.action.remove(action)) {
|
||||
action.state.menu = 0;
|
||||
return p.remove(action);
|
||||
void Menu::remove(const reference_array<Action&> &list) {
|
||||
for(auto &action : list) {
|
||||
if(state.action.remove(action)) {
|
||||
action.state.menu = 0;
|
||||
return p.remove(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,6 +465,11 @@ Separator::~Separator() {
|
|||
//Item
|
||||
//====
|
||||
|
||||
void Item::setImage(const image &image) {
|
||||
state.image = image;
|
||||
return p.setImage(image);
|
||||
}
|
||||
|
||||
void Item::setText(const string &text) {
|
||||
state.text = text;
|
||||
return p.setText(text);
|
||||
|
@ -658,6 +703,12 @@ Widget::~Widget() {
|
|||
//Button
|
||||
//======
|
||||
|
||||
void Button::setImage(const image &image, Orientation orientation) {
|
||||
state.image = image;
|
||||
state.orientation = orientation;
|
||||
return p.setImage(image, orientation);
|
||||
}
|
||||
|
||||
void Button::setText(const string &text) {
|
||||
state.text = text;
|
||||
return p.setText(text);
|
||||
|
@ -756,9 +807,11 @@ CheckBox::~CheckBox() {
|
|||
//ComboBox
|
||||
//========
|
||||
|
||||
void ComboBox::append(const string &text) {
|
||||
state.text.append(text);
|
||||
return p.append(text);
|
||||
void ComboBox::append_(const lstring &list) {
|
||||
for(auto &text : list) {
|
||||
state.text.append(text);
|
||||
p.append(text);
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::reset() {
|
||||
|
|
|
@ -70,53 +70,48 @@ struct Geometry {
|
|||
Geometry(const nall::string &text);
|
||||
};
|
||||
|
||||
enum class Orientation : unsigned { Horizontal, Vertical };
|
||||
|
||||
struct Font {
|
||||
nall::string description;
|
||||
Geometry geometry(const nall::string &text);
|
||||
Font(const nall::string &description = "");
|
||||
};
|
||||
|
||||
struct Object {
|
||||
Object(pObject &p);
|
||||
Object& operator=(const Object&) = delete;
|
||||
Object(const Object&) = delete;
|
||||
virtual ~Object();
|
||||
pObject &p;
|
||||
struct Desktop {
|
||||
static Size size();
|
||||
static Geometry workspace();
|
||||
Desktop() = delete;
|
||||
};
|
||||
|
||||
struct OS : Object {
|
||||
static Geometry availableGeometry();
|
||||
static Geometry desktopGeometry();
|
||||
template<typename... Args> static nall::string fileLoad(Window &parent, const nall::string &path, const Args&... args) { return fileLoad_(parent, path, { args... }); }
|
||||
struct Keyboard {
|
||||
#include "keyboard.hpp"
|
||||
static bool pressed(Scancode scancode);
|
||||
static bool released(Scancode scancode);
|
||||
static nall::array<bool> state();
|
||||
Keyboard() = delete;
|
||||
};
|
||||
|
||||
struct Mouse {
|
||||
enum class Button : unsigned { Left, Middle, Right };
|
||||
static Position position();
|
||||
static bool pressed(Button);
|
||||
static bool released(Button);
|
||||
Mouse() = delete;
|
||||
};
|
||||
|
||||
struct DialogWindow {
|
||||
template<typename... Args> static nall::string fileOpen(Window &parent, const nall::string &path, const Args&... args) { return fileOpen_(parent, path, { args... }); }
|
||||
template<typename... Args> static nall::string fileSave(Window &parent, const nall::string &path, const Args&... args) { return fileSave_(parent, path, { args... }); }
|
||||
static nall::string folderSelect(Window &parent, const nall::string &path);
|
||||
static void main();
|
||||
static bool pendingEvents();
|
||||
static void processEvents();
|
||||
static void quit();
|
||||
|
||||
OS();
|
||||
static void initialize();
|
||||
DialogWindow() = delete;
|
||||
|
||||
private:
|
||||
static nall::string fileLoad_(Window &parent, const nall::string &path, const nall::lstring& filter);
|
||||
static nall::string fileOpen_(Window &parent, const nall::string &path, const nall::lstring& filter);
|
||||
static nall::string fileSave_(Window &parent, const nall::string &path, const nall::lstring& filter);
|
||||
};
|
||||
|
||||
struct Timer : private nall::base_from_member<pTimer&>, Object {
|
||||
nall::function<void ()> onTimeout;
|
||||
|
||||
void setEnabled(bool enabled = true);
|
||||
void setInterval(unsigned milliseconds);
|
||||
|
||||
Timer();
|
||||
~Timer();
|
||||
struct State;
|
||||
State &state;
|
||||
pTimer &p;
|
||||
};
|
||||
|
||||
struct MessageWindow : Object {
|
||||
struct MessageWindow {
|
||||
enum class Buttons : unsigned {
|
||||
Ok,
|
||||
OkCancel,
|
||||
|
@ -134,17 +129,56 @@ struct MessageWindow : Object {
|
|||
static Response question(Window &parent, const nall::string &text, Buttons = Buttons::YesNo);
|
||||
static Response warning(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
|
||||
static Response critical(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
|
||||
MessageWindow() = delete;
|
||||
};
|
||||
|
||||
struct Object {
|
||||
Object(pObject &p);
|
||||
Object& operator=(const Object&) = delete;
|
||||
Object(const Object&) = delete;
|
||||
virtual ~Object();
|
||||
pObject &p;
|
||||
};
|
||||
|
||||
struct OS : Object {
|
||||
static void main();
|
||||
static bool pendingEvents();
|
||||
static void processEvents();
|
||||
static void quit();
|
||||
|
||||
OS();
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
struct Timer : private nall::base_from_member<pTimer&>, Object {
|
||||
nall::function<void ()> onTimeout;
|
||||
|
||||
void setEnabled(bool enabled = true);
|
||||
void setInterval(unsigned milliseconds);
|
||||
|
||||
Timer();
|
||||
~Timer();
|
||||
struct State;
|
||||
State &state;
|
||||
pTimer &p;
|
||||
};
|
||||
|
||||
struct Window : private nall::base_from_member<pWindow&>, Object {
|
||||
static Window None;
|
||||
nall::function<void ()> onClose;
|
||||
nall::function<void (Keyboard::Keycode)> onKeyPress;
|
||||
nall::function<void (Keyboard::Keycode)> onKeyRelease;
|
||||
nall::function<void ()> onMove;
|
||||
nall::function<void ()> onSize;
|
||||
|
||||
void append(Layout &layout);
|
||||
void append(Menu &menu);
|
||||
void append(Widget &widget);
|
||||
inline void append() {}
|
||||
inline void remove() {}
|
||||
template<typename T, typename... Args> void append(T &arg, Args&... args) { append_(arg); append(args...); }
|
||||
template<typename T, typename... Args> void remove(T &arg, Args&... args) { remove_(arg); remove(args...); }
|
||||
|
||||
void append_(Layout &layout);
|
||||
void append_(Menu &menu);
|
||||
void append_(Widget &widget);
|
||||
Color backgroundColor();
|
||||
Geometry frameGeometry();
|
||||
Geometry frameMargin();
|
||||
|
@ -152,9 +186,9 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
|
|||
bool fullScreen();
|
||||
Geometry geometry();
|
||||
void ignore();
|
||||
void remove(Layout &layout);
|
||||
void remove(Menu &menu);
|
||||
void remove(Widget &widget);
|
||||
void remove_(Layout &layout);
|
||||
void remove_(Menu &menu);
|
||||
void remove_(Widget &widget);
|
||||
void setBackgroundColor(const Color &color);
|
||||
void setFrameGeometry(const Geometry &geometry);
|
||||
void setFocused();
|
||||
|
@ -194,8 +228,11 @@ struct Action : Object {
|
|||
};
|
||||
|
||||
struct Menu : private nall::base_from_member<pMenu&>, Action {
|
||||
void append(Action &action);
|
||||
void remove(Action &action);
|
||||
template<typename... Args> void append(Args&... args) { append({ args... }); }
|
||||
template<typename... Args> void remove(Args&... args) { remove({ args... }); }
|
||||
|
||||
void append(const nall::reference_array<Action&> &list);
|
||||
void remove(const nall::reference_array<Action&> &list);
|
||||
void setText(const nall::string &text);
|
||||
|
||||
Menu();
|
||||
|
@ -214,6 +251,7 @@ struct Separator : private nall::base_from_member<pSeparator&>, Action {
|
|||
struct Item : private nall::base_from_member<pItem&>, Action {
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
void setImage(const nall::image &image);
|
||||
void setText(const nall::string &text);
|
||||
|
||||
Item();
|
||||
|
@ -308,6 +346,7 @@ struct Widget : private nall::base_from_member<pWidget&>, Sizable {
|
|||
struct Button : private nall::base_from_member<pButton&>, Widget {
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
void setImage(const nall::image &image, Orientation = Orientation::Horizontal);
|
||||
void setText(const nall::string &text);
|
||||
|
||||
Button();
|
||||
|
@ -348,7 +387,9 @@ struct CheckBox : private nall::base_from_member<pCheckBox&>, Widget {
|
|||
struct ComboBox : private nall::base_from_member<pComboBox&>, Widget {
|
||||
nall::function<void ()> onChange;
|
||||
|
||||
void append(const nall::string &text);
|
||||
template<typename... Args> void append(const Args&... args) { append_({ args... }); }
|
||||
|
||||
void append_(const nall::lstring &list);
|
||||
void reset();
|
||||
unsigned selection();
|
||||
void setSelection(unsigned row);
|
||||
|
@ -438,15 +479,19 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
|||
nall::function<void (unsigned)> onToggle;
|
||||
|
||||
template<typename... Args> void append(const Args&... args) { append_({ args... }); }
|
||||
template<typename... Args> void modify(unsigned row, const Args&... args) { modify_(row, { args... }); }
|
||||
template<typename... Args> void setHeaderText(const Args&... args) { setHeaderText_({ args... }); }
|
||||
|
||||
void append_(const nall::lstring &list);
|
||||
void autoSizeColumns();
|
||||
bool checked(unsigned row);
|
||||
template<typename... Args> void modify(unsigned row, const Args&... args) { modify_(row, { args... }); }
|
||||
void modify_(unsigned row, const nall::lstring &list);
|
||||
void reset();
|
||||
bool selected();
|
||||
unsigned selection();
|
||||
void setCheckable(bool checkable = true);
|
||||
void setChecked(unsigned row, bool checked = true);
|
||||
template<typename... Args> void setHeaderText(const Args&... args) { setHeaderText_({ args... }); }
|
||||
void setHeaderText_(const nall::lstring &list);
|
||||
void setHeaderVisible(bool visible = true);
|
||||
void setSelected(bool selected = true);
|
||||
void setSelection(unsigned row);
|
||||
|
@ -456,11 +501,6 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
|
|||
struct State;
|
||||
State &state;
|
||||
pListView &p;
|
||||
|
||||
private:
|
||||
void append_(const nall::lstring &list);
|
||||
void modify_(unsigned row, const nall::lstring &list);
|
||||
void setHeaderText_(const nall::lstring &list);
|
||||
};
|
||||
|
||||
struct ProgressBar : private nall::base_from_member<pProgressBar&>, Widget {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
//each code refers to a physical key
|
||||
//names are taken assuming: NumLock on, CapsLock off, Shift off
|
||||
//layout uses US-104 keyboard
|
||||
enum class Scancode : unsigned {
|
||||
None,
|
||||
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
PrintScreen, ScrollLock, Pause,
|
||||
Insert, Delete, Home, End, PageUp, PageDown,
|
||||
Up, Down, Left, Right,
|
||||
|
||||
Grave, Number1, Number2, Number3, Number4, Number5, Number6, Number7, Number8, Number9, Number0, Minus, Equal, Backspace,
|
||||
BracketLeft, BracketRight, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
|
||||
Tab, CapsLock, Return, ShiftLeft, ShiftRight, ControlLeft, ControlRight, SuperLeft, SuperRight, AltLeft, AltRight, Space, Menu,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
|
||||
NumLock, Divide, Multiply, Subtract, Add, Enter, Point,
|
||||
Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
|
||||
|
||||
Limit,
|
||||
};
|
||||
|
||||
//each enum refers to a translated scancode (eg Shift+1 = !)
|
||||
enum class Keycode : unsigned {
|
||||
None,
|
||||
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
PrintScreen, SysRq, ScrollLock, Pause, Break,
|
||||
Insert, Delete, Home, End, PageUp, PageDown,
|
||||
Up, Down, Left, Right,
|
||||
|
||||
Grave, Number1, Number2, Number3, Number4, Number5, Number6, Number7, Number8, Number9, Number0, Minus, Equal, Backspace,
|
||||
Tilde, Exclamation, At, Pound, Dollar, Percent, Power, Ampersand, Asterisk, ParenthesisLeft, ParenthesisRight, Underscore, Plus,
|
||||
BracketLeft, BracketRight, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
|
||||
BraceLeft, BraceRight, Pipe, Colon, Quote, CaretLeft, CaretRight, Question,
|
||||
Tab, CapsLock, Return, ShiftLeft, ShiftRight, ControlLeft, ControlRight, SuperLeft, SuperRight, AltLeft, AltRight, Space, Menu,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,
|
||||
|
||||
NumLock, Divide, Multiply, Subtract, Add, Enter, Point,
|
||||
Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
|
||||
KeypadInsert, KeypadDelete, KeypadHome, KeypadEnd, KeypadPageUp, KeypadPageDown, KeypadUp, KeypadDown, KeypadLeft, KeypadRight, KeypadCenter,
|
||||
|
||||
Limit,
|
||||
};
|
|
@ -60,7 +60,11 @@ struct Menu::State {
|
|||
};
|
||||
|
||||
struct Item::State {
|
||||
nall::image image;
|
||||
string text;
|
||||
|
||||
State() : image(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0) {
|
||||
}
|
||||
};
|
||||
|
||||
struct CheckItem::State {
|
||||
|
@ -113,9 +117,11 @@ struct Widget::State {
|
|||
};
|
||||
|
||||
struct Button::State {
|
||||
nall::image image;
|
||||
Orientation orientation;
|
||||
string text;
|
||||
|
||||
State() {
|
||||
State() : image(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0) {
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2,12 +2,17 @@ static void Item_activate(Item *self) {
|
|||
if(self->onActivate) self->onActivate();
|
||||
}
|
||||
|
||||
void pItem::setImage(const image &image) {
|
||||
GtkImage *gtkImage = CreateImage(image, /* menuIcon = */ true);
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
||||
}
|
||||
|
||||
void pItem::setText(const string &text) {
|
||||
gtk_menu_item_set_label(GTK_MENU_ITEM(widget), text);
|
||||
}
|
||||
|
||||
void pItem::constructor() {
|
||||
widget = gtk_menu_item_new_with_label(item.state.text);
|
||||
widget = gtk_image_menu_item_new_with_label(item.state.text);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "activate", G_CALLBACK(Item_activate), (gpointer)&item);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
Size pDesktop::size() {
|
||||
return {
|
||||
gdk_screen_get_width(gdk_screen_get_default()),
|
||||
gdk_screen_get_height(gdk_screen_get_default())
|
||||
};
|
||||
}
|
||||
|
||||
Geometry pDesktop::workspace() {
|
||||
XlibDisplay *display = XOpenDisplay(0);
|
||||
int screen = DefaultScreen(display);
|
||||
|
||||
static Atom atom = XlibNone;
|
||||
if(atom == XlibNone) atom = XInternAtom(display, "_NET_WORKAREA", True);
|
||||
|
||||
int format;
|
||||
unsigned char *data = 0;
|
||||
unsigned long items, after;
|
||||
Atom returnAtom;
|
||||
|
||||
int result = XGetWindowProperty(
|
||||
display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data
|
||||
);
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
||||
if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) {
|
||||
unsigned long *workarea = (unsigned long*)data;
|
||||
return { (signed)workarea[0], (signed)workarea[1], (unsigned)workarea[2], (unsigned)workarea[3] };
|
||||
}
|
||||
|
||||
return {
|
||||
0, 0,
|
||||
gdk_screen_get_width(gdk_screen_get_default()),
|
||||
gdk_screen_get_height(gdk_screen_get_default())
|
||||
};
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
static string FileDialog(bool save, Window &parent, const string &path, const lstring &filter) {
|
||||
string name;
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new(
|
||||
save == 0 ? "Load File" : "Save File",
|
||||
&parent != &Window::None ? GTK_WINDOW(parent.p.widget) : (GtkWindow*)0,
|
||||
save == 0 ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0
|
||||
);
|
||||
|
||||
if(path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
|
||||
for(auto &filterItem : filter) {
|
||||
GtkFileFilter *gtkFilter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(gtkFilter, filterItem);
|
||||
lstring part;
|
||||
part.split("(", filterItem);
|
||||
part[1].rtrim<1>(")");
|
||||
lstring list;
|
||||
list.split(",", part[1]);
|
||||
for(auto &pattern : list) gtk_file_filter_add_pattern(gtkFilter, pattern);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), gtkFilter);
|
||||
}
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
name = temp;
|
||||
g_free(temp);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return name;
|
||||
}
|
||||
|
||||
string pDialogWindow::fileOpen(Window &parent, const string &path, const lstring &filter) {
|
||||
return FileDialog(0, parent, path, filter);
|
||||
}
|
||||
|
||||
string pDialogWindow::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
return FileDialog(1, parent, path, filter);
|
||||
}
|
||||
|
||||
string pDialogWindow::folderSelect(Window &parent, const string &path) {
|
||||
string name;
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new(
|
||||
"Select Folder",
|
||||
&parent != &Window::None ? GTK_WINDOW(parent.p.widget) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0
|
||||
);
|
||||
|
||||
if(path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
name = temp;
|
||||
g_free(temp);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
if(name == "") return "";
|
||||
if(name.endswith("/") == false) name.append("/");
|
||||
return name;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
|
||||
|
||||
void pKeyboard::initialize() {
|
||||
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
||||
keymap.append(scancode, XKeysymToKeycode(pOS::display, keysym));
|
||||
};
|
||||
|
||||
append(Keyboard::Scancode::Escape, XK_Escape);
|
||||
append(Keyboard::Scancode::F1, XK_F1);
|
||||
append(Keyboard::Scancode::F2, XK_F2);
|
||||
append(Keyboard::Scancode::F3, XK_F3);
|
||||
append(Keyboard::Scancode::F4, XK_F4);
|
||||
append(Keyboard::Scancode::F5, XK_F5);
|
||||
append(Keyboard::Scancode::F6, XK_F6);
|
||||
append(Keyboard::Scancode::F7, XK_F7);
|
||||
append(Keyboard::Scancode::F8, XK_F8);
|
||||
append(Keyboard::Scancode::F9, XK_F9);
|
||||
append(Keyboard::Scancode::F10, XK_F10);
|
||||
append(Keyboard::Scancode::F11, XK_F11);
|
||||
append(Keyboard::Scancode::F12, XK_F12);
|
||||
|
||||
append(Keyboard::Scancode::PrintScreen, XK_Print);
|
||||
append(Keyboard::Scancode::ScrollLock, XK_Scroll_Lock);
|
||||
append(Keyboard::Scancode::Pause, XK_Pause);
|
||||
|
||||
append(Keyboard::Scancode::Insert, XK_Insert);
|
||||
append(Keyboard::Scancode::Delete, XK_Delete);
|
||||
append(Keyboard::Scancode::Home, XK_Home);
|
||||
append(Keyboard::Scancode::End, XK_End);
|
||||
append(Keyboard::Scancode::PageUp, XK_Prior);
|
||||
append(Keyboard::Scancode::PageDown, XK_Next);
|
||||
|
||||
append(Keyboard::Scancode::Up, XK_Up);
|
||||
append(Keyboard::Scancode::Down, XK_Down);
|
||||
append(Keyboard::Scancode::Left, XK_Left);
|
||||
append(Keyboard::Scancode::Right, XK_Right);
|
||||
|
||||
append(Keyboard::Scancode::Grave, XK_asciitilde);
|
||||
append(Keyboard::Scancode::Number1, XK_1);
|
||||
append(Keyboard::Scancode::Number2, XK_2);
|
||||
append(Keyboard::Scancode::Number3, XK_3);
|
||||
append(Keyboard::Scancode::Number4, XK_4);
|
||||
append(Keyboard::Scancode::Number5, XK_5);
|
||||
append(Keyboard::Scancode::Number6, XK_6);
|
||||
append(Keyboard::Scancode::Number7, XK_7);
|
||||
append(Keyboard::Scancode::Number8, XK_8);
|
||||
append(Keyboard::Scancode::Number9, XK_9);
|
||||
append(Keyboard::Scancode::Number0, XK_0);
|
||||
append(Keyboard::Scancode::Minus, XK_minus);
|
||||
append(Keyboard::Scancode::Equal, XK_equal);
|
||||
append(Keyboard::Scancode::Backspace, XK_BackSpace);
|
||||
|
||||
append(Keyboard::Scancode::BracketLeft, XK_bracketleft);
|
||||
append(Keyboard::Scancode::BracketRight, XK_bracketright);
|
||||
append(Keyboard::Scancode::Backslash, XK_backslash);
|
||||
append(Keyboard::Scancode::Semicolon, XK_semicolon);
|
||||
append(Keyboard::Scancode::Apostrophe, XK_apostrophe);
|
||||
append(Keyboard::Scancode::Comma, XK_comma);
|
||||
append(Keyboard::Scancode::Period, XK_period);
|
||||
append(Keyboard::Scancode::Slash, XK_slash);
|
||||
|
||||
append(Keyboard::Scancode::Tab, XK_Tab);
|
||||
append(Keyboard::Scancode::CapsLock, XK_Caps_Lock);
|
||||
append(Keyboard::Scancode::Return, XK_Return);
|
||||
append(Keyboard::Scancode::ShiftLeft, XK_Shift_L);
|
||||
append(Keyboard::Scancode::ShiftRight, XK_Shift_R);
|
||||
append(Keyboard::Scancode::ControlLeft, XK_Control_L);
|
||||
append(Keyboard::Scancode::ControlRight, XK_Control_R);
|
||||
append(Keyboard::Scancode::SuperLeft, XK_Super_L);
|
||||
append(Keyboard::Scancode::SuperRight, XK_Super_R);
|
||||
append(Keyboard::Scancode::AltLeft, XK_Alt_L);
|
||||
append(Keyboard::Scancode::AltRight, XK_Alt_R);
|
||||
append(Keyboard::Scancode::Space, XK_space);
|
||||
append(Keyboard::Scancode::Menu, XK_Menu);
|
||||
|
||||
append(Keyboard::Scancode::A, XK_A);
|
||||
append(Keyboard::Scancode::B, XK_B);
|
||||
append(Keyboard::Scancode::C, XK_C);
|
||||
append(Keyboard::Scancode::D, XK_D);
|
||||
append(Keyboard::Scancode::E, XK_E);
|
||||
append(Keyboard::Scancode::F, XK_F);
|
||||
append(Keyboard::Scancode::G, XK_G);
|
||||
append(Keyboard::Scancode::H, XK_H);
|
||||
append(Keyboard::Scancode::I, XK_I);
|
||||
append(Keyboard::Scancode::J, XK_J);
|
||||
append(Keyboard::Scancode::K, XK_K);
|
||||
append(Keyboard::Scancode::L, XK_L);
|
||||
append(Keyboard::Scancode::M, XK_M);
|
||||
append(Keyboard::Scancode::N, XK_N);
|
||||
append(Keyboard::Scancode::O, XK_O);
|
||||
append(Keyboard::Scancode::P, XK_P);
|
||||
append(Keyboard::Scancode::Q, XK_Q);
|
||||
append(Keyboard::Scancode::R, XK_R);
|
||||
append(Keyboard::Scancode::S, XK_S);
|
||||
append(Keyboard::Scancode::T, XK_T);
|
||||
append(Keyboard::Scancode::U, XK_U);
|
||||
append(Keyboard::Scancode::V, XK_V);
|
||||
append(Keyboard::Scancode::W, XK_W);
|
||||
append(Keyboard::Scancode::X, XK_X);
|
||||
append(Keyboard::Scancode::Y, XK_Y);
|
||||
append(Keyboard::Scancode::Z, XK_Z);
|
||||
|
||||
append(Keyboard::Scancode::NumLock, XK_Num_Lock);
|
||||
append(Keyboard::Scancode::Divide, XK_KP_Divide);
|
||||
append(Keyboard::Scancode::Multiply, XK_KP_Multiply);
|
||||
append(Keyboard::Scancode::Subtract, XK_KP_Subtract);
|
||||
append(Keyboard::Scancode::Add, XK_KP_Add);
|
||||
append(Keyboard::Scancode::Enter, XK_KP_Enter);
|
||||
append(Keyboard::Scancode::Point, XK_KP_Decimal);
|
||||
|
||||
append(Keyboard::Scancode::Keypad1, XK_KP_1);
|
||||
append(Keyboard::Scancode::Keypad2, XK_KP_2);
|
||||
append(Keyboard::Scancode::Keypad3, XK_KP_3);
|
||||
append(Keyboard::Scancode::Keypad4, XK_KP_4);
|
||||
append(Keyboard::Scancode::Keypad5, XK_KP_5);
|
||||
append(Keyboard::Scancode::Keypad6, XK_KP_6);
|
||||
append(Keyboard::Scancode::Keypad7, XK_KP_7);
|
||||
append(Keyboard::Scancode::Keypad8, XK_KP_8);
|
||||
append(Keyboard::Scancode::Keypad9, XK_KP_9);
|
||||
append(Keyboard::Scancode::Keypad0, XK_KP_0);
|
||||
}
|
||||
|
||||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||
char state[256];
|
||||
XQueryKeymap(pOS::display, state);
|
||||
unsigned id = keymap.lhs[scancode];
|
||||
return state[id >> 3] & (1 << (id & 7));
|
||||
}
|
||||
|
||||
array<bool> pKeyboard::state() {
|
||||
array<bool> output;
|
||||
output.reserve((unsigned)Keyboard::Scancode::Limit);
|
||||
for(auto &n : output) n = false;
|
||||
|
||||
char state[256];
|
||||
XQueryKeymap(pOS::display, state);
|
||||
for(auto &n : keymap.rhs) {
|
||||
if(state[n.name >> 3] & (1 << (n.name & 7))) {
|
||||
output[(unsigned)n.data] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
Position pMouse::position() {
|
||||
XlibWindow root, child;
|
||||
int rootx, rooty, winx, winy;
|
||||
unsigned int mask;
|
||||
XQueryPointer(pOS::display, DefaultRootWindow(pOS::display), &root, &child, &rootx, &rooty, &winx, &winy, &mask);
|
||||
return { rootx, rooty };
|
||||
}
|
||||
|
||||
bool pMouse::pressed(Mouse::Button button) {
|
||||
XlibWindow root, child;
|
||||
int rootx, rooty, winx, winy;
|
||||
unsigned int mask;
|
||||
XQueryPointer(pOS::display, DefaultRootWindow(pOS::display), &root, &child, &rootx, &rooty, &winx, &winy, &mask);
|
||||
switch(button) {
|
||||
case Mouse::Button::Left: return mask & Button1Mask;
|
||||
case Mouse::Button::Middle: return mask & Button2Mask;
|
||||
case Mouse::Button::Right: return mask & Button3Mask;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,9 +1,15 @@
|
|||
#include "platform.hpp"
|
||||
#include "utility.cpp"
|
||||
|
||||
#include "desktop.cpp"
|
||||
#include "keyboard.cpp"
|
||||
#include "mouse.cpp"
|
||||
#include "dialog-window.cpp"
|
||||
#include "message-window.cpp"
|
||||
|
||||
#include "settings.cpp"
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
#include "action/action.cpp"
|
||||
|
@ -31,112 +37,9 @@
|
|||
#include "widget/vertical-slider.cpp"
|
||||
#include "widget/viewport.cpp"
|
||||
|
||||
XlibDisplay* pOS::display = 0;
|
||||
Font pOS::defaultFont;
|
||||
|
||||
Geometry pOS::availableGeometry() {
|
||||
XlibDisplay *display = XOpenDisplay(0);
|
||||
int screen = DefaultScreen(display);
|
||||
|
||||
static Atom atom = XlibNone;
|
||||
if(atom == XlibNone) atom = XInternAtom(display, "_NET_WORKAREA", True);
|
||||
|
||||
int format;
|
||||
unsigned char *data = 0;
|
||||
unsigned long items, after;
|
||||
Atom returnAtom;
|
||||
|
||||
int result = XGetWindowProperty(
|
||||
display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data
|
||||
);
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
||||
if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) {
|
||||
unsigned long *workarea = (unsigned long*)data;
|
||||
return { (signed)workarea[0], (signed)workarea[1], (unsigned)workarea[2], (unsigned)workarea[3] };
|
||||
}
|
||||
|
||||
return desktopGeometry();
|
||||
}
|
||||
|
||||
Geometry pOS::desktopGeometry() {
|
||||
return {
|
||||
0, 0,
|
||||
gdk_screen_get_width(gdk_screen_get_default()),
|
||||
gdk_screen_get_height(gdk_screen_get_default())
|
||||
};
|
||||
}
|
||||
|
||||
static string pOS_fileDialog(bool save, Window &parent, const string &path, const lstring &filter) {
|
||||
string name;
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new(
|
||||
save == 0 ? "Load File" : "Save File",
|
||||
&parent != &Window::None ? GTK_WINDOW(parent.p.widget) : (GtkWindow*)0,
|
||||
save == 0 ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0
|
||||
);
|
||||
|
||||
if(path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
|
||||
for(auto &filterItem : filter) {
|
||||
GtkFileFilter *gtkFilter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(gtkFilter, filterItem);
|
||||
lstring part;
|
||||
part.split("(", filterItem);
|
||||
part[1].rtrim<1>(")");
|
||||
lstring list;
|
||||
list.split(",", part[1]);
|
||||
for(auto &pattern : list) gtk_file_filter_add_pattern(gtkFilter, pattern);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), gtkFilter);
|
||||
}
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
name = temp;
|
||||
g_free(temp);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return name;
|
||||
}
|
||||
|
||||
string pOS::fileLoad(Window &parent, const string &path, const lstring &filter) {
|
||||
return pOS_fileDialog(0, parent, path, filter);
|
||||
}
|
||||
|
||||
string pOS::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
return pOS_fileDialog(1, parent, path, filter);
|
||||
}
|
||||
|
||||
string pOS::folderSelect(Window &parent, const string &path) {
|
||||
string name;
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new(
|
||||
"Select Folder",
|
||||
&parent != &Window::None ? GTK_WINDOW(parent.p.widget) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0
|
||||
);
|
||||
|
||||
if(path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
name = temp;
|
||||
g_free(temp);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
if(name == "") return "";
|
||||
if(name.endswith("/") == false) name.append("/");
|
||||
return name;
|
||||
}
|
||||
|
||||
void pOS::main() {
|
||||
gtk_main();
|
||||
}
|
||||
|
@ -154,6 +57,8 @@ void pOS::quit() {
|
|||
}
|
||||
|
||||
void pOS::initialize() {
|
||||
display = XOpenDisplay(0);
|
||||
|
||||
settings = new Settings;
|
||||
settings->load();
|
||||
|
||||
|
@ -177,4 +82,6 @@ void pOS::initialize() {
|
|||
class "GtkTreeView" style "phoenix-gtk"
|
||||
# class "GtkComboBox" style "phoenix-gtk"
|
||||
)");
|
||||
|
||||
pKeyboard::initialize();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,38 @@ struct pFont {
|
|||
static void setFont(GtkWidget *widget, gpointer font);
|
||||
};
|
||||
|
||||
struct pDesktop {
|
||||
static Size size();
|
||||
static Geometry workspace();
|
||||
};
|
||||
|
||||
struct pKeyboard {
|
||||
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
||||
|
||||
static bool pressed(Keyboard::Scancode scancode);
|
||||
static array<bool> state();
|
||||
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
struct pMouse {
|
||||
static Position position();
|
||||
static bool pressed(Mouse::Button button);
|
||||
};
|
||||
|
||||
struct pDialogWindow {
|
||||
static string fileOpen(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
};
|
||||
|
||||
struct pMessageWindow {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pObject {
|
||||
Object &object;
|
||||
bool locked;
|
||||
|
@ -38,13 +70,9 @@ struct pObject {
|
|||
};
|
||||
|
||||
struct pOS : public pObject {
|
||||
static XlibDisplay *display;
|
||||
static Font defaultFont;
|
||||
|
||||
static Geometry availableGeometry();
|
||||
static Geometry desktopGeometry();
|
||||
static string fileLoad(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
static void main();
|
||||
static bool pendingEvents();
|
||||
static void processEvents();
|
||||
|
@ -63,13 +91,6 @@ struct pTimer : public pObject {
|
|||
void constructor();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pWindow : public pObject {
|
||||
Window &window;
|
||||
GtkWidget *widget;
|
||||
|
@ -150,6 +171,7 @@ struct pSeparator : public pAction {
|
|||
struct pItem : public pAction {
|
||||
Item &item;
|
||||
|
||||
void setImage(const image &image);
|
||||
void setText(const string &text);
|
||||
|
||||
pItem(Item &item) : pAction(item), item(item) {}
|
||||
|
@ -219,6 +241,7 @@ struct pButton : public pWidget {
|
|||
Button &button;
|
||||
|
||||
Geometry minimumGeometry();
|
||||
void setImage(const image &image, Orientation orientation);
|
||||
void setText(const string &text);
|
||||
|
||||
pButton(Button &button) : pWidget(button), button(button) {}
|
||||
|
|
|
@ -15,10 +15,10 @@ void Settings::save() {
|
|||
}
|
||||
|
||||
Settings::Settings() {
|
||||
attach(frameGeometryX = 4, "frameGeometryX");
|
||||
attach(frameGeometryY = 24, "frameGeometryY");
|
||||
attach(frameGeometryWidth = 8, "frameGeometryWidth");
|
||||
attach(frameGeometryHeight = 28, "frameGeometryHeight");
|
||||
attach(menuGeometryHeight = 20, "menuGeometryHeight");
|
||||
attach(statusGeometryHeight = 20, "statusGeometryHeight");
|
||||
append(frameGeometryX = 4, "frameGeometryX");
|
||||
append(frameGeometryY = 24, "frameGeometryY");
|
||||
append(frameGeometryWidth = 8, "frameGeometryWidth");
|
||||
append(frameGeometryHeight = 28, "frameGeometryHeight");
|
||||
append(menuGeometryHeight = 20, "menuGeometryHeight");
|
||||
append(statusGeometryHeight = 20, "statusGeometryHeight");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
static GtkImage* CreateImage(const nall::image &image, bool menuIcon = false) {
|
||||
nall::image gdkImage = image;
|
||||
gdkImage.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); //GTK+ uses ABGR format
|
||||
if(menuIcon) gdkImage.scale(16, 16, Interpolation::Linear);
|
||||
|
||||
GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, gdkImage.width, gdkImage.height);
|
||||
memcpy(gdk_pixbuf_get_pixels(pixbuf), gdkImage.data, gdkImage.width * gdkImage.height * 4);
|
||||
GtkImage *gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf);
|
||||
g_object_unref(pixbuf);
|
||||
|
||||
return gtkImage;
|
||||
}
|
||||
|
||||
static Keyboard::Keycode Keysym(unsigned keysym) {
|
||||
switch(keysym) {
|
||||
case GDK_Escape: return Keyboard::Keycode::Escape;
|
||||
case GDK_F1: return Keyboard::Keycode::F1;
|
||||
case GDK_F2: return Keyboard::Keycode::F2;
|
||||
case GDK_F3: return Keyboard::Keycode::F3;
|
||||
case GDK_F4: return Keyboard::Keycode::F4;
|
||||
case GDK_F5: return Keyboard::Keycode::F5;
|
||||
case GDK_F6: return Keyboard::Keycode::F6;
|
||||
case GDK_F7: return Keyboard::Keycode::F7;
|
||||
case GDK_F8: return Keyboard::Keycode::F8;
|
||||
case GDK_F9: return Keyboard::Keycode::F9;
|
||||
case GDK_F10: return Keyboard::Keycode::F10;
|
||||
case GDK_F11: return Keyboard::Keycode::F11;
|
||||
case GDK_F12: return Keyboard::Keycode::F12;
|
||||
|
||||
case GDK_Print: return Keyboard::Keycode::PrintScreen;
|
||||
//Keyboard::Keycode::SysRq
|
||||
case GDK_Scroll_Lock: return Keyboard::Keycode::ScrollLock;
|
||||
case GDK_Pause: return Keyboard::Keycode::Pause;
|
||||
//Keyboard::Keycode::Break
|
||||
|
||||
case GDK_Insert: return Keyboard::Keycode::Insert;
|
||||
case GDK_Delete: return Keyboard::Keycode::Delete;
|
||||
case GDK_Home: return Keyboard::Keycode::Home;
|
||||
case GDK_End: return Keyboard::Keycode::End;
|
||||
case GDK_Prior: return Keyboard::Keycode::PageUp;
|
||||
case GDK_Next: return Keyboard::Keycode::PageDown;
|
||||
|
||||
case GDK_Up: return Keyboard::Keycode::Up;
|
||||
case GDK_Down: return Keyboard::Keycode::Down;
|
||||
case GDK_Left: return Keyboard::Keycode::Left;
|
||||
case GDK_Right: return Keyboard::Keycode::Right;
|
||||
|
||||
case GDK_grave: return Keyboard::Keycode::Grave;
|
||||
case GDK_1: return Keyboard::Keycode::Number1;
|
||||
case GDK_2: return Keyboard::Keycode::Number2;
|
||||
case GDK_3: return Keyboard::Keycode::Number3;
|
||||
case GDK_4: return Keyboard::Keycode::Number4;
|
||||
case GDK_5: return Keyboard::Keycode::Number5;
|
||||
case GDK_6: return Keyboard::Keycode::Number6;
|
||||
case GDK_7: return Keyboard::Keycode::Number7;
|
||||
case GDK_8: return Keyboard::Keycode::Number8;
|
||||
case GDK_9: return Keyboard::Keycode::Number9;
|
||||
case GDK_0: return Keyboard::Keycode::Number0;
|
||||
case GDK_minus: return Keyboard::Keycode::Minus;
|
||||
case GDK_equal: return Keyboard::Keycode::Equal;
|
||||
case GDK_BackSpace: return Keyboard::Keycode::Backspace;
|
||||
|
||||
case GDK_asciitilde: return Keyboard::Keycode::Tilde;
|
||||
case GDK_exclam: return Keyboard::Keycode::Exclamation;
|
||||
case GDK_at: return Keyboard::Keycode::At;
|
||||
case GDK_numbersign: return Keyboard::Keycode::Pound;
|
||||
case GDK_dollar: return Keyboard::Keycode::Dollar;
|
||||
case GDK_percent: return Keyboard::Keycode::Percent;
|
||||
case GDK_asciicircum: return Keyboard::Keycode::Power;
|
||||
case GDK_ampersand: return Keyboard::Keycode::Ampersand;
|
||||
case GDK_asterisk: return Keyboard::Keycode::Asterisk;
|
||||
case GDK_parenleft: return Keyboard::Keycode::ParenthesisLeft;
|
||||
case GDK_parenright: return Keyboard::Keycode::ParenthesisRight;
|
||||
case GDK_underscore: return Keyboard::Keycode::Underscore;
|
||||
case GDK_plus: return Keyboard::Keycode::Plus;
|
||||
|
||||
case GDK_bracketleft: return Keyboard::Keycode::BracketLeft;
|
||||
case GDK_bracketright: return Keyboard::Keycode::BracketRight;
|
||||
case GDK_backslash: return Keyboard::Keycode::Backslash;
|
||||
case GDK_semicolon: return Keyboard::Keycode::Semicolon;
|
||||
case GDK_apostrophe: return Keyboard::Keycode::Apostrophe;
|
||||
case GDK_comma: return Keyboard::Keycode::Comma;
|
||||
case GDK_period: return Keyboard::Keycode::Period;
|
||||
case GDK_slash: return Keyboard::Keycode::Slash;
|
||||
|
||||
case GDK_braceleft: return Keyboard::Keycode::BraceLeft;
|
||||
case GDK_braceright: return Keyboard::Keycode::BraceRight;
|
||||
case GDK_bar: return Keyboard::Keycode::Pipe;
|
||||
case GDK_colon: return Keyboard::Keycode::Colon;
|
||||
case GDK_quotedbl: return Keyboard::Keycode::Quote;
|
||||
case GDK_less: return Keyboard::Keycode::CaretLeft;
|
||||
case GDK_greater: return Keyboard::Keycode::CaretRight;
|
||||
case GDK_question: return Keyboard::Keycode::Question;
|
||||
|
||||
case GDK_Tab: return Keyboard::Keycode::Tab;
|
||||
case GDK_Caps_Lock: return Keyboard::Keycode::CapsLock;
|
||||
case GDK_Return: return Keyboard::Keycode::Return;
|
||||
case GDK_Shift_L: return Keyboard::Keycode::ShiftLeft;
|
||||
case GDK_Shift_R: return Keyboard::Keycode::ShiftRight;
|
||||
case GDK_Control_L: return Keyboard::Keycode::ControlLeft;
|
||||
case GDK_Control_R: return Keyboard::Keycode::ControlRight;
|
||||
case GDK_Super_L: return Keyboard::Keycode::SuperLeft;
|
||||
case GDK_Super_R: return Keyboard::Keycode::SuperRight;
|
||||
case GDK_Alt_L: return Keyboard::Keycode::AltLeft;
|
||||
case GDK_Alt_R: return Keyboard::Keycode::AltRight;
|
||||
case GDK_space: return Keyboard::Keycode::Space;
|
||||
case GDK_Menu: return Keyboard::Keycode::Menu;
|
||||
|
||||
case GDK_A: return Keyboard::Keycode::A;
|
||||
case GDK_B: return Keyboard::Keycode::B;
|
||||
case GDK_C: return Keyboard::Keycode::C;
|
||||
case GDK_D: return Keyboard::Keycode::D;
|
||||
case GDK_E: return Keyboard::Keycode::E;
|
||||
case GDK_F: return Keyboard::Keycode::F;
|
||||
case GDK_G: return Keyboard::Keycode::G;
|
||||
case GDK_H: return Keyboard::Keycode::H;
|
||||
case GDK_I: return Keyboard::Keycode::I;
|
||||
case GDK_J: return Keyboard::Keycode::J;
|
||||
case GDK_K: return Keyboard::Keycode::K;
|
||||
case GDK_L: return Keyboard::Keycode::L;
|
||||
case GDK_M: return Keyboard::Keycode::M;
|
||||
case GDK_N: return Keyboard::Keycode::N;
|
||||
case GDK_O: return Keyboard::Keycode::O;
|
||||
case GDK_P: return Keyboard::Keycode::P;
|
||||
case GDK_Q: return Keyboard::Keycode::Q;
|
||||
case GDK_R: return Keyboard::Keycode::R;
|
||||
case GDK_S: return Keyboard::Keycode::S;
|
||||
case GDK_T: return Keyboard::Keycode::T;
|
||||
case GDK_U: return Keyboard::Keycode::U;
|
||||
case GDK_V: return Keyboard::Keycode::V;
|
||||
case GDK_W: return Keyboard::Keycode::W;
|
||||
case GDK_X: return Keyboard::Keycode::X;
|
||||
case GDK_Y: return Keyboard::Keycode::Y;
|
||||
case GDK_Z: return Keyboard::Keycode::Z;
|
||||
|
||||
case GDK_a: return Keyboard::Keycode::a;
|
||||
case GDK_b: return Keyboard::Keycode::b;
|
||||
case GDK_c: return Keyboard::Keycode::c;
|
||||
case GDK_d: return Keyboard::Keycode::d;
|
||||
case GDK_e: return Keyboard::Keycode::e;
|
||||
case GDK_f: return Keyboard::Keycode::f;
|
||||
case GDK_g: return Keyboard::Keycode::g;
|
||||
case GDK_h: return Keyboard::Keycode::h;
|
||||
case GDK_i: return Keyboard::Keycode::i;
|
||||
case GDK_j: return Keyboard::Keycode::j;
|
||||
case GDK_k: return Keyboard::Keycode::k;
|
||||
case GDK_l: return Keyboard::Keycode::l;
|
||||
case GDK_m: return Keyboard::Keycode::m;
|
||||
case GDK_n: return Keyboard::Keycode::n;
|
||||
case GDK_o: return Keyboard::Keycode::o;
|
||||
case GDK_p: return Keyboard::Keycode::p;
|
||||
case GDK_q: return Keyboard::Keycode::q;
|
||||
case GDK_r: return Keyboard::Keycode::r;
|
||||
case GDK_s: return Keyboard::Keycode::s;
|
||||
case GDK_t: return Keyboard::Keycode::t;
|
||||
case GDK_u: return Keyboard::Keycode::u;
|
||||
case GDK_v: return Keyboard::Keycode::v;
|
||||
case GDK_w: return Keyboard::Keycode::w;
|
||||
case GDK_x: return Keyboard::Keycode::x;
|
||||
case GDK_y: return Keyboard::Keycode::y;
|
||||
case GDK_z: return Keyboard::Keycode::z;
|
||||
|
||||
case GDK_Num_Lock: return Keyboard::Keycode::NumLock;
|
||||
case GDK_KP_Divide: return Keyboard::Keycode::Divide;
|
||||
case GDK_KP_Multiply: return Keyboard::Keycode::Multiply;
|
||||
case GDK_KP_Subtract: return Keyboard::Keycode::Subtract;
|
||||
case GDK_KP_Add: return Keyboard::Keycode::Add;
|
||||
case GDK_KP_Enter: return Keyboard::Keycode::Enter;
|
||||
case GDK_KP_Decimal: return Keyboard::Keycode::Point;
|
||||
|
||||
case GDK_KP_1: return Keyboard::Keycode::Keypad1;
|
||||
case GDK_KP_2: return Keyboard::Keycode::Keypad2;
|
||||
case GDK_KP_3: return Keyboard::Keycode::Keypad3;
|
||||
case GDK_KP_4: return Keyboard::Keycode::Keypad4;
|
||||
case GDK_KP_5: return Keyboard::Keycode::Keypad5;
|
||||
case GDK_KP_6: return Keyboard::Keycode::Keypad6;
|
||||
case GDK_KP_7: return Keyboard::Keycode::Keypad7;
|
||||
case GDK_KP_8: return Keyboard::Keycode::Keypad8;
|
||||
case GDK_KP_9: return Keyboard::Keycode::Keypad9;
|
||||
case GDK_KP_0: return Keyboard::Keycode::Keypad0;
|
||||
|
||||
case GDK_KP_Home: return Keyboard::Keycode::KeypadHome;
|
||||
case GDK_KP_End: return Keyboard::Keycode::KeypadEnd;
|
||||
case GDK_KP_Page_Up: return Keyboard::Keycode::KeypadPageUp;
|
||||
case GDK_KP_Page_Down: return Keyboard::Keycode::KeypadPageDown;
|
||||
case GDK_KP_Up: return Keyboard::Keycode::KeypadUp;
|
||||
case GDK_KP_Down: return Keyboard::Keycode::KeypadDown;
|
||||
case GDK_KP_Left: return Keyboard::Keycode::KeypadLeft;
|
||||
case GDK_KP_Right: return Keyboard::Keycode::KeypadRight;
|
||||
case GDK_KP_Begin: return Keyboard::Keycode::KeypadCenter;
|
||||
case GDK_KP_Insert: return Keyboard::Keycode::KeypadInsert;
|
||||
case GDK_KP_Delete: return Keyboard::Keycode::KeypadDelete;
|
||||
}
|
||||
return Keyboard::Keycode::None;
|
||||
}
|
|
@ -4,9 +4,29 @@ static void Button_activate(Button *self) {
|
|||
|
||||
Geometry pButton::minimumGeometry() {
|
||||
Geometry geometry = pFont::geometry(widget.state.font, button.state.text);
|
||||
|
||||
if(button.state.orientation == Orientation::Horizontal) {
|
||||
geometry.width += button.state.image.width;
|
||||
geometry.height = max(button.state.image.height, geometry.height);
|
||||
}
|
||||
|
||||
if(button.state.orientation == Orientation::Vertical) {
|
||||
geometry.width = max(button.state.image.width, geometry.width);
|
||||
geometry.height += button.state.image.height;
|
||||
}
|
||||
|
||||
return { 0, 0, geometry.width + 24, geometry.height + 12 };
|
||||
}
|
||||
|
||||
void pButton::setImage(const image &image, Orientation orientation) {
|
||||
GtkImage *gtkImage = CreateImage(image);
|
||||
gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage);
|
||||
switch(orientation) {
|
||||
case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break;
|
||||
case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pButton::setText(const string &text) {
|
||||
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
|
||||
setFont(widget.state.font);
|
||||
|
|
|
@ -79,6 +79,18 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win
|
|||
return false;
|
||||
}
|
||||
|
||||
static gboolean Window_keyPressEvent(GtkWidget *widget, GdkEventKey *event, Window *window) {
|
||||
Keyboard::Keycode key = Keysym(event->keyval);
|
||||
if(key != Keyboard::Keycode::None && window->onKeyPress) window->onKeyPress(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
static gboolean Window_keyReleaseEvent(GtkWidget *widget, GdkEventKey *event, Window *window) {
|
||||
Keyboard::Keycode key = Keysym(event->keyval);
|
||||
if(key != Keyboard::Keycode::None && window->onKeyRelease) window->onKeyRelease(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
void pWindow::append(Layout &layout) {
|
||||
Geometry geometry = this->geometry();
|
||||
geometry.x = geometry.y = 0;
|
||||
|
@ -123,7 +135,7 @@ bool pWindow::focused() {
|
|||
|
||||
Geometry pWindow::geometry() {
|
||||
if(window.state.fullScreen == true) {
|
||||
return { 0, menuHeight(), OS::desktopGeometry().width, OS::desktopGeometry().height - menuHeight() - statusHeight() };
|
||||
return { 0, menuHeight(), Desktop::size().width, Desktop::size().height - menuHeight() - statusHeight() };
|
||||
};
|
||||
return window.state.geometry;
|
||||
}
|
||||
|
@ -163,7 +175,7 @@ void pWindow::setFullScreen(bool fullScreen) {
|
|||
} else {
|
||||
gtk_window_fullscreen(GTK_WINDOW(widget));
|
||||
gtk_window_set_decorated(GTK_WINDOW(widget), false);
|
||||
gtk_widget_set_size_request(widget, OS::desktopGeometry().width, OS::desktopGeometry().height);
|
||||
gtk_widget_set_size_request(widget, Desktop::size().width, Desktop::size().height);
|
||||
gtk_window_set_resizable(GTK_WINDOW(widget), false);
|
||||
}
|
||||
gdk_display_sync(gtk_widget_get_display(widget));
|
||||
|
@ -275,6 +287,8 @@ void pWindow::constructor() {
|
|||
g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window);
|
||||
g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window);
|
||||
g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
|
||||
g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
|
||||
g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
|
||||
}
|
||||
|
||||
unsigned pWindow::menuHeight() {
|
||||
|
|
|
@ -17,13 +17,21 @@
|
|||
#elif defined(PHOENIX_QT)
|
||||
#include <QApplication>
|
||||
#include <QtGui>
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#define XK_MISCELLANY
|
||||
#define XK_LATIN1
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysymdef.h>
|
||||
#undef XK_MISCELLANY
|
||||
#undef XK_LATIN1
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#elif defined(PHOENIX_GTK)
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <cairo.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#elif defined(PHOENIX_REFERENCE)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <nall/config.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/image.hpp>
|
||||
#include <nall/map.hpp>
|
||||
#include <nall/reference_array.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
void pItem::setImage(const image &image) {
|
||||
nall::image qtBuffer = image;
|
||||
qtBuffer.transform(0, 32u, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||
|
||||
QImage qtImage(qtBuffer.data, qtBuffer.width, qtBuffer.height, QImage::Format_ARGB32);
|
||||
QIcon qtIcon(QPixmap::fromImage(qtImage));
|
||||
qtAction->setIcon(qtIcon);
|
||||
}
|
||||
|
||||
void pItem::setText(const string &text) {
|
||||
qtAction->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Size pDesktop::size() {
|
||||
QRect rect = QApplication::desktop()->screenGeometry();
|
||||
return { rect.width(), rect.height() };
|
||||
}
|
||||
|
||||
Geometry pDesktop::workspace() {
|
||||
QRect rect = QApplication::desktop()->availableGeometry();
|
||||
return { rect.x(), rect.y(), rect.width(), rect.height() };
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
string pDialogWindow::fileOpen(Window &parent, const string &path, const lstring &filter) {
|
||||
string filterList;
|
||||
for(auto &item : filter) {
|
||||
filterList.append(item);
|
||||
filterList.append(";;");
|
||||
}
|
||||
filterList.rtrim<1>(";;");
|
||||
|
||||
//convert filter list from phoenix to Qt format, example:
|
||||
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
|
||||
signed parenthesis = 0;
|
||||
for(auto &n : filterList) {
|
||||
if(n == '(') parenthesis++;
|
||||
if(n == ')') parenthesis--;
|
||||
if(n == ',' && parenthesis) n = ' ';
|
||||
}
|
||||
|
||||
QString filename = QFileDialog::getOpenFileName(
|
||||
&parent != &Window::None ? parent.p.qtWindow : 0, "Load File",
|
||||
QString::fromUtf8(path), QString::fromUtf8(filterList)
|
||||
);
|
||||
return filename.toUtf8().constData();
|
||||
}
|
||||
|
||||
string pDialogWindow::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
string filterList;
|
||||
for(auto &item : filter) {
|
||||
filterList.append(item);
|
||||
filterList.append(";;");
|
||||
}
|
||||
filterList.rtrim<1>(";;");
|
||||
|
||||
//convert filter list from phoenix to Qt format, example:
|
||||
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
|
||||
signed parenthesis = 0;
|
||||
for(auto &n : filterList) {
|
||||
if(n == '(') parenthesis++;
|
||||
if(n == ')') parenthesis--;
|
||||
if(n == ',' && parenthesis) n = ' ';
|
||||
}
|
||||
|
||||
QString filename = QFileDialog::getSaveFileName(
|
||||
&parent != &Window::None ? parent.p.qtWindow : 0, "Save File",
|
||||
QString::fromUtf8(path), QString::fromUtf8(filterList)
|
||||
);
|
||||
return filename.toUtf8().constData();
|
||||
}
|
||||
|
||||
string pDialogWindow::folderSelect(Window &parent, const string &path) {
|
||||
QString directory = QFileDialog::getExistingDirectory(
|
||||
&parent != &Window::None ? parent.p.qtWindow : 0, "Select Directory",
|
||||
QString::fromUtf8(path), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
string name = directory.toUtf8().constData();
|
||||
if(name != "" && name.endswith("/") == false) name.append("/");
|
||||
return name;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
|
||||
|
||||
void pKeyboard::initialize() {
|
||||
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
||||
keymap.append(scancode, XKeysymToKeycode(pOS::display, keysym));
|
||||
};
|
||||
|
||||
append(Keyboard::Scancode::Escape, XK_Escape);
|
||||
append(Keyboard::Scancode::F1, XK_F1);
|
||||
append(Keyboard::Scancode::F2, XK_F2);
|
||||
append(Keyboard::Scancode::F3, XK_F3);
|
||||
append(Keyboard::Scancode::F4, XK_F4);
|
||||
append(Keyboard::Scancode::F5, XK_F5);
|
||||
append(Keyboard::Scancode::F6, XK_F6);
|
||||
append(Keyboard::Scancode::F7, XK_F7);
|
||||
append(Keyboard::Scancode::F8, XK_F8);
|
||||
append(Keyboard::Scancode::F9, XK_F9);
|
||||
append(Keyboard::Scancode::F10, XK_F10);
|
||||
append(Keyboard::Scancode::F11, XK_F11);
|
||||
append(Keyboard::Scancode::F12, XK_F12);
|
||||
|
||||
append(Keyboard::Scancode::PrintScreen, XK_Print);
|
||||
append(Keyboard::Scancode::ScrollLock, XK_Scroll_Lock);
|
||||
append(Keyboard::Scancode::Pause, XK_Pause);
|
||||
|
||||
append(Keyboard::Scancode::Insert, XK_Insert);
|
||||
append(Keyboard::Scancode::Delete, XK_Delete);
|
||||
append(Keyboard::Scancode::Home, XK_Home);
|
||||
append(Keyboard::Scancode::End, XK_End);
|
||||
append(Keyboard::Scancode::PageUp, XK_Prior);
|
||||
append(Keyboard::Scancode::PageDown, XK_Next);
|
||||
|
||||
append(Keyboard::Scancode::Up, XK_Up);
|
||||
append(Keyboard::Scancode::Down, XK_Down);
|
||||
append(Keyboard::Scancode::Left, XK_Left);
|
||||
append(Keyboard::Scancode::Right, XK_Right);
|
||||
|
||||
append(Keyboard::Scancode::Grave, XK_asciitilde);
|
||||
append(Keyboard::Scancode::Number1, XK_1);
|
||||
append(Keyboard::Scancode::Number2, XK_2);
|
||||
append(Keyboard::Scancode::Number3, XK_3);
|
||||
append(Keyboard::Scancode::Number4, XK_4);
|
||||
append(Keyboard::Scancode::Number5, XK_5);
|
||||
append(Keyboard::Scancode::Number6, XK_6);
|
||||
append(Keyboard::Scancode::Number7, XK_7);
|
||||
append(Keyboard::Scancode::Number8, XK_8);
|
||||
append(Keyboard::Scancode::Number9, XK_9);
|
||||
append(Keyboard::Scancode::Number0, XK_0);
|
||||
append(Keyboard::Scancode::Minus, XK_minus);
|
||||
append(Keyboard::Scancode::Equal, XK_equal);
|
||||
append(Keyboard::Scancode::Backspace, XK_BackSpace);
|
||||
|
||||
append(Keyboard::Scancode::BracketLeft, XK_bracketleft);
|
||||
append(Keyboard::Scancode::BracketRight, XK_bracketright);
|
||||
append(Keyboard::Scancode::Backslash, XK_backslash);
|
||||
append(Keyboard::Scancode::Semicolon, XK_semicolon);
|
||||
append(Keyboard::Scancode::Apostrophe, XK_apostrophe);
|
||||
append(Keyboard::Scancode::Comma, XK_comma);
|
||||
append(Keyboard::Scancode::Period, XK_period);
|
||||
append(Keyboard::Scancode::Slash, XK_slash);
|
||||
|
||||
append(Keyboard::Scancode::Tab, XK_Tab);
|
||||
append(Keyboard::Scancode::CapsLock, XK_Caps_Lock);
|
||||
append(Keyboard::Scancode::Return, XK_Return);
|
||||
append(Keyboard::Scancode::ShiftLeft, XK_Shift_L);
|
||||
append(Keyboard::Scancode::ShiftRight, XK_Shift_R);
|
||||
append(Keyboard::Scancode::ControlLeft, XK_Control_L);
|
||||
append(Keyboard::Scancode::ControlRight, XK_Control_R);
|
||||
append(Keyboard::Scancode::SuperLeft, XK_Super_L);
|
||||
append(Keyboard::Scancode::SuperRight, XK_Super_R);
|
||||
append(Keyboard::Scancode::AltLeft, XK_Alt_L);
|
||||
append(Keyboard::Scancode::AltRight, XK_Alt_R);
|
||||
append(Keyboard::Scancode::Space, XK_space);
|
||||
append(Keyboard::Scancode::Menu, XK_Menu);
|
||||
|
||||
append(Keyboard::Scancode::A, XK_A);
|
||||
append(Keyboard::Scancode::B, XK_B);
|
||||
append(Keyboard::Scancode::C, XK_C);
|
||||
append(Keyboard::Scancode::D, XK_D);
|
||||
append(Keyboard::Scancode::E, XK_E);
|
||||
append(Keyboard::Scancode::F, XK_F);
|
||||
append(Keyboard::Scancode::G, XK_G);
|
||||
append(Keyboard::Scancode::H, XK_H);
|
||||
append(Keyboard::Scancode::I, XK_I);
|
||||
append(Keyboard::Scancode::J, XK_J);
|
||||
append(Keyboard::Scancode::K, XK_K);
|
||||
append(Keyboard::Scancode::L, XK_L);
|
||||
append(Keyboard::Scancode::M, XK_M);
|
||||
append(Keyboard::Scancode::N, XK_N);
|
||||
append(Keyboard::Scancode::O, XK_O);
|
||||
append(Keyboard::Scancode::P, XK_P);
|
||||
append(Keyboard::Scancode::Q, XK_Q);
|
||||
append(Keyboard::Scancode::R, XK_R);
|
||||
append(Keyboard::Scancode::S, XK_S);
|
||||
append(Keyboard::Scancode::T, XK_T);
|
||||
append(Keyboard::Scancode::U, XK_U);
|
||||
append(Keyboard::Scancode::V, XK_V);
|
||||
append(Keyboard::Scancode::W, XK_W);
|
||||
append(Keyboard::Scancode::X, XK_X);
|
||||
append(Keyboard::Scancode::Y, XK_Y);
|
||||
append(Keyboard::Scancode::Z, XK_Z);
|
||||
|
||||
append(Keyboard::Scancode::NumLock, XK_Num_Lock);
|
||||
append(Keyboard::Scancode::Divide, XK_KP_Divide);
|
||||
append(Keyboard::Scancode::Multiply, XK_KP_Multiply);
|
||||
append(Keyboard::Scancode::Subtract, XK_KP_Subtract);
|
||||
append(Keyboard::Scancode::Add, XK_KP_Add);
|
||||
append(Keyboard::Scancode::Enter, XK_KP_Enter);
|
||||
append(Keyboard::Scancode::Point, XK_KP_Decimal);
|
||||
|
||||
append(Keyboard::Scancode::Keypad1, XK_KP_1);
|
||||
append(Keyboard::Scancode::Keypad2, XK_KP_2);
|
||||
append(Keyboard::Scancode::Keypad3, XK_KP_3);
|
||||
append(Keyboard::Scancode::Keypad4, XK_KP_4);
|
||||
append(Keyboard::Scancode::Keypad5, XK_KP_5);
|
||||
append(Keyboard::Scancode::Keypad6, XK_KP_6);
|
||||
append(Keyboard::Scancode::Keypad7, XK_KP_7);
|
||||
append(Keyboard::Scancode::Keypad8, XK_KP_8);
|
||||
append(Keyboard::Scancode::Keypad9, XK_KP_9);
|
||||
append(Keyboard::Scancode::Keypad0, XK_KP_0);
|
||||
}
|
||||
|
||||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||
char state[256];
|
||||
XQueryKeymap(pOS::display, state);
|
||||
unsigned id = keymap.lhs[scancode];
|
||||
return state[id >> 3] & (1 << (id & 7));
|
||||
}
|
||||
|
||||
array<bool> pKeyboard::state() {
|
||||
array<bool> output;
|
||||
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||
for(auto &n : output) n = false;
|
||||
|
||||
char state[256];
|
||||
XQueryKeymap(pOS::display, state);
|
||||
for(auto &n : keymap.rhs) {
|
||||
if(state[n.name >> 3] & (1 << (n.name & 7))) {
|
||||
output[(unsigned)n.data] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
Position pMouse::position() {
|
||||
QPoint point = QCursor::pos();
|
||||
return { point.x(), point.y() };
|
||||
}
|
||||
|
||||
bool pMouse::pressed(Mouse::Button button) {
|
||||
Qt::MouseButtons buttons = QApplication::mouseButtons();
|
||||
switch(button) {
|
||||
case Mouse::Button::Left: return buttons & Qt::LeftButton;
|
||||
case Mouse::Button::Middle: return buttons & Qt::MidButton;
|
||||
case Mouse::Button::Right: return buttons & Qt::RightButton;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,10 +1,16 @@
|
|||
#include "platform.moc.hpp"
|
||||
#include "platform.moc"
|
||||
#include "utility.cpp"
|
||||
|
||||
#include "desktop.cpp"
|
||||
#include "keyboard.cpp"
|
||||
#include "mouse.cpp"
|
||||
#include "dialog-window.cpp"
|
||||
#include "message-window.cpp"
|
||||
|
||||
#include "settings.cpp"
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
#include "action/action.cpp"
|
||||
|
@ -32,73 +38,7 @@
|
|||
#include "widget/vertical-slider.cpp"
|
||||
#include "widget/viewport.cpp"
|
||||
|
||||
Geometry pOS::availableGeometry() {
|
||||
QRect rect = QApplication::desktop()->availableGeometry();
|
||||
return { rect.x(), rect.y(), rect.width(), rect.height() };
|
||||
}
|
||||
|
||||
Geometry pOS::desktopGeometry() {
|
||||
QRect rect = QApplication::desktop()->screenGeometry();
|
||||
return { 0, 0, rect.width(), rect.height() };
|
||||
}
|
||||
|
||||
string pOS::fileLoad(Window &parent, const string &path, const lstring &filter) {
|
||||
string filterList;
|
||||
for(auto &item : filter) {
|
||||
filterList.append(item);
|
||||
filterList.append(";;");
|
||||
}
|
||||
filterList.rtrim<1>(";;");
|
||||
|
||||
//convert filter list from phoenix to Qt format, example:
|
||||
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
|
||||
signed parenthesis = 0;
|
||||
for(auto &n : filterList) {
|
||||
if(n == '(') parenthesis++;
|
||||
if(n == ')') parenthesis--;
|
||||
if(n == ',' && parenthesis) n = ' ';
|
||||
}
|
||||
|
||||
QString filename = QFileDialog::getOpenFileName(
|
||||
&parent != &Window::None ? parent.p.qtWindow : 0, "Load File",
|
||||
QString::fromUtf8(path), QString::fromUtf8(filterList)
|
||||
);
|
||||
return filename.toUtf8().constData();
|
||||
}
|
||||
|
||||
string pOS::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
string filterList;
|
||||
for(auto &item : filter) {
|
||||
filterList.append(item);
|
||||
filterList.append(";;");
|
||||
}
|
||||
filterList.rtrim<1>(";;");
|
||||
|
||||
//convert filter list from phoenix to Qt format, example:
|
||||
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
|
||||
signed parenthesis = 0;
|
||||
for(auto &n : filterList) {
|
||||
if(n == '(') parenthesis++;
|
||||
if(n == ')') parenthesis--;
|
||||
if(n == ',' && parenthesis) n = ' ';
|
||||
}
|
||||
|
||||
QString filename = QFileDialog::getSaveFileName(
|
||||
&parent != &Window::None ? parent.p.qtWindow : 0, "Save File",
|
||||
QString::fromUtf8(path), QString::fromUtf8(filterList)
|
||||
);
|
||||
return filename.toUtf8().constData();
|
||||
}
|
||||
|
||||
string pOS::folderSelect(Window &parent, const string &path) {
|
||||
QString directory = QFileDialog::getExistingDirectory(
|
||||
&parent != &Window::None ? parent.p.qtWindow : 0, "Select Directory",
|
||||
QString::fromUtf8(path), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
string name = directory.toUtf8().constData();
|
||||
if(name != "" && name.endswith("/") == false) name.append("/");
|
||||
return name;
|
||||
}
|
||||
XlibDisplay* pOS::display = 0;
|
||||
|
||||
void pOS::main() {
|
||||
QApplication::exec();
|
||||
|
@ -127,6 +67,8 @@ void pOS::syncX() {
|
|||
}
|
||||
|
||||
void pOS::initialize() {
|
||||
display = XOpenDisplay(0);
|
||||
|
||||
settings = new Settings;
|
||||
settings->load();
|
||||
|
||||
|
@ -138,4 +80,6 @@ void pOS::initialize() {
|
|||
char **argvp = argv;
|
||||
|
||||
qtApplication = new QApplication(argc, argvp);
|
||||
|
||||
pKeyboard::initialize();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
||||
**
|
||||
** Created: Tue Dec 13 07:23:09 2011
|
||||
** Created: Sat Jan 14 09:18:07 2012
|
||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
|
|
|
@ -25,6 +25,38 @@ struct pFont {
|
|||
static Geometry geometry(const QFont &qtFont, const string &text);
|
||||
};
|
||||
|
||||
struct pDesktop {
|
||||
static Size size();
|
||||
static Geometry workspace();
|
||||
};
|
||||
|
||||
struct pKeyboard {
|
||||
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
||||
|
||||
static bool pressed(Keyboard::Scancode scancode);
|
||||
static array<bool> state();
|
||||
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
struct pMouse {
|
||||
static Position position();
|
||||
static bool pressed(Mouse::Button button);
|
||||
};
|
||||
|
||||
struct pDialogWindow {
|
||||
static string fileOpen(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
};
|
||||
|
||||
struct pMessageWindow {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pObject {
|
||||
Object &object;
|
||||
bool locked;
|
||||
|
@ -36,18 +68,15 @@ struct pObject {
|
|||
};
|
||||
|
||||
struct pOS : public pObject {
|
||||
static Geometry availableGeometry();
|
||||
static Geometry desktopGeometry();
|
||||
static string fileLoad(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
static XlibDisplay *display;
|
||||
|
||||
static void main();
|
||||
static bool pendingEvents();
|
||||
static void processEvents();
|
||||
static void quit();
|
||||
static void syncX();
|
||||
|
||||
static void initialize();
|
||||
static void syncX();
|
||||
};
|
||||
|
||||
struct pTimer : public QObject, public pObject {
|
||||
|
@ -68,13 +97,6 @@ public slots:
|
|||
void onTimeout();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pWindow : public QObject, public pObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -83,6 +105,8 @@ public:
|
|||
struct QtWindow : public QWidget {
|
||||
pWindow &self;
|
||||
void closeEvent(QCloseEvent*);
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
void keyReleaseEvent(QKeyEvent*);
|
||||
void moveEvent(QMoveEvent*);
|
||||
void resizeEvent(QResizeEvent*);
|
||||
QSize sizeHint() const;
|
||||
|
@ -165,6 +189,7 @@ public:
|
|||
Item &item;
|
||||
QAction *qtAction;
|
||||
|
||||
void setImage(const image &image);
|
||||
void setText(const string &text);
|
||||
|
||||
pItem(Item &item) : pAction(item), item(item) {}
|
||||
|
@ -256,9 +281,10 @@ struct pButton : public QObject, public pWidget {
|
|||
|
||||
public:
|
||||
Button &button;
|
||||
QPushButton *qtButton;
|
||||
QToolButton *qtButton;
|
||||
|
||||
Geometry minimumGeometry();
|
||||
void setImage(const image &image, Orientation orientation);
|
||||
void setText(const string &text);
|
||||
|
||||
pButton(Button &button) : pWidget(button), button(button) {}
|
||||
|
|
|
@ -15,10 +15,10 @@ void Settings::save() {
|
|||
}
|
||||
|
||||
Settings::Settings() {
|
||||
attach(frameGeometryX = 4, "frameGeometryX");
|
||||
attach(frameGeometryY = 24, "frameGeometryY");
|
||||
attach(frameGeometryWidth = 8, "frameGeometryWidth");
|
||||
attach(frameGeometryHeight = 28, "frameGeometryHeight");
|
||||
attach(menuGeometryHeight = 20, "menuGeometryHeight");
|
||||
attach(statusGeometryHeight = 20, "statusGeometryHeight");
|
||||
append(frameGeometryX = 4, "frameGeometryX");
|
||||
append(frameGeometryY = 24, "frameGeometryY");
|
||||
append(frameGeometryWidth = 8, "frameGeometryWidth");
|
||||
append(frameGeometryHeight = 28, "frameGeometryHeight");
|
||||
append(menuGeometryHeight = 20, "menuGeometryHeight");
|
||||
append(statusGeometryHeight = 20, "statusGeometryHeight");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
static Keyboard::Keycode Keysym(int keysym) {
|
||||
switch(keysym) {
|
||||
case XK_Escape: return Keyboard::Keycode::Escape;
|
||||
case XK_F1: return Keyboard::Keycode::F1;
|
||||
case XK_F2: return Keyboard::Keycode::F2;
|
||||
case XK_F3: return Keyboard::Keycode::F3;
|
||||
case XK_F4: return Keyboard::Keycode::F4;
|
||||
case XK_F5: return Keyboard::Keycode::F5;
|
||||
case XK_F6: return Keyboard::Keycode::F6;
|
||||
case XK_F7: return Keyboard::Keycode::F7;
|
||||
case XK_F8: return Keyboard::Keycode::F8;
|
||||
case XK_F9: return Keyboard::Keycode::F9;
|
||||
case XK_F10: return Keyboard::Keycode::F10;
|
||||
case XK_F11: return Keyboard::Keycode::F11;
|
||||
case XK_F12: return Keyboard::Keycode::F12;
|
||||
|
||||
case XK_Print: return Keyboard::Keycode::PrintScreen;
|
||||
//Keyboard::Keycode::SysRq
|
||||
case XK_Scroll_Lock: return Keyboard::Keycode::ScrollLock;
|
||||
case XK_Pause: return Keyboard::Keycode::Pause;
|
||||
//Keyboard::Keycode::Break
|
||||
|
||||
case XK_Insert: return Keyboard::Keycode::Insert;
|
||||
case XK_Delete: return Keyboard::Keycode::Delete;
|
||||
case XK_Home: return Keyboard::Keycode::Home;
|
||||
case XK_End: return Keyboard::Keycode::End;
|
||||
case XK_Prior: return Keyboard::Keycode::PageUp;
|
||||
case XK_Next: return Keyboard::Keycode::PageDown;
|
||||
|
||||
case XK_Up: return Keyboard::Keycode::Up;
|
||||
case XK_Down: return Keyboard::Keycode::Down;
|
||||
case XK_Left: return Keyboard::Keycode::Left;
|
||||
case XK_Right: return Keyboard::Keycode::Right;
|
||||
|
||||
case XK_grave: return Keyboard::Keycode::Grave;
|
||||
case XK_1: return Keyboard::Keycode::Number1;
|
||||
case XK_2: return Keyboard::Keycode::Number2;
|
||||
case XK_3: return Keyboard::Keycode::Number3;
|
||||
case XK_4: return Keyboard::Keycode::Number4;
|
||||
case XK_5: return Keyboard::Keycode::Number5;
|
||||
case XK_6: return Keyboard::Keycode::Number6;
|
||||
case XK_7: return Keyboard::Keycode::Number7;
|
||||
case XK_8: return Keyboard::Keycode::Number8;
|
||||
case XK_9: return Keyboard::Keycode::Number9;
|
||||
case XK_0: return Keyboard::Keycode::Number0;
|
||||
case XK_minus: return Keyboard::Keycode::Minus;
|
||||
case XK_equal: return Keyboard::Keycode::Equal;
|
||||
case XK_BackSpace: return Keyboard::Keycode::Backspace;
|
||||
|
||||
case XK_asciitilde: return Keyboard::Keycode::Tilde;
|
||||
case XK_exclam: return Keyboard::Keycode::Exclamation;
|
||||
case XK_at: return Keyboard::Keycode::At;
|
||||
case XK_numbersign: return Keyboard::Keycode::Pound;
|
||||
case XK_dollar: return Keyboard::Keycode::Dollar;
|
||||
case XK_percent: return Keyboard::Keycode::Percent;
|
||||
case XK_asciicircum: return Keyboard::Keycode::Power;
|
||||
case XK_ampersand: return Keyboard::Keycode::Ampersand;
|
||||
case XK_asterisk: return Keyboard::Keycode::Asterisk;
|
||||
case XK_parenleft: return Keyboard::Keycode::ParenthesisLeft;
|
||||
case XK_parenright: return Keyboard::Keycode::ParenthesisRight;
|
||||
case XK_underscore: return Keyboard::Keycode::Underscore;
|
||||
case XK_plus: return Keyboard::Keycode::Plus;
|
||||
|
||||
case XK_bracketleft: return Keyboard::Keycode::BracketLeft;
|
||||
case XK_bracketright: return Keyboard::Keycode::BracketRight;
|
||||
case XK_backslash: return Keyboard::Keycode::Backslash;
|
||||
case XK_semicolon: return Keyboard::Keycode::Semicolon;
|
||||
case XK_apostrophe: return Keyboard::Keycode::Apostrophe;
|
||||
case XK_comma: return Keyboard::Keycode::Comma;
|
||||
case XK_period: return Keyboard::Keycode::Period;
|
||||
case XK_slash: return Keyboard::Keycode::Slash;
|
||||
|
||||
case XK_braceleft: return Keyboard::Keycode::BraceLeft;
|
||||
case XK_braceright: return Keyboard::Keycode::BraceRight;
|
||||
case XK_bar: return Keyboard::Keycode::Pipe;
|
||||
case XK_colon: return Keyboard::Keycode::Colon;
|
||||
case XK_quotedbl: return Keyboard::Keycode::Quote;
|
||||
case XK_less: return Keyboard::Keycode::CaretLeft;
|
||||
case XK_greater: return Keyboard::Keycode::CaretRight;
|
||||
case XK_question: return Keyboard::Keycode::Question;
|
||||
|
||||
case XK_Tab: return Keyboard::Keycode::Tab;
|
||||
case XK_Caps_Lock: return Keyboard::Keycode::CapsLock;
|
||||
case XK_Return: return Keyboard::Keycode::Return;
|
||||
case XK_Shift_L: return Keyboard::Keycode::ShiftLeft;
|
||||
case XK_Shift_R: return Keyboard::Keycode::ShiftRight;
|
||||
case XK_Control_L: return Keyboard::Keycode::ControlLeft;
|
||||
case XK_Control_R: return Keyboard::Keycode::ControlRight;
|
||||
case XK_Super_L: return Keyboard::Keycode::SuperLeft;
|
||||
case XK_Super_R: return Keyboard::Keycode::SuperRight;
|
||||
case XK_Alt_L: return Keyboard::Keycode::AltLeft;
|
||||
case XK_Alt_R: return Keyboard::Keycode::AltRight;
|
||||
case XK_space: return Keyboard::Keycode::Space;
|
||||
case XK_Menu: return Keyboard::Keycode::Menu;
|
||||
|
||||
case XK_A: return Keyboard::Keycode::A;
|
||||
case XK_B: return Keyboard::Keycode::B;
|
||||
case XK_C: return Keyboard::Keycode::C;
|
||||
case XK_D: return Keyboard::Keycode::D;
|
||||
case XK_E: return Keyboard::Keycode::E;
|
||||
case XK_F: return Keyboard::Keycode::F;
|
||||
case XK_G: return Keyboard::Keycode::G;
|
||||
case XK_H: return Keyboard::Keycode::H;
|
||||
case XK_I: return Keyboard::Keycode::I;
|
||||
case XK_J: return Keyboard::Keycode::J;
|
||||
case XK_K: return Keyboard::Keycode::K;
|
||||
case XK_L: return Keyboard::Keycode::L;
|
||||
case XK_M: return Keyboard::Keycode::M;
|
||||
case XK_N: return Keyboard::Keycode::N;
|
||||
case XK_O: return Keyboard::Keycode::O;
|
||||
case XK_P: return Keyboard::Keycode::P;
|
||||
case XK_Q: return Keyboard::Keycode::Q;
|
||||
case XK_R: return Keyboard::Keycode::R;
|
||||
case XK_S: return Keyboard::Keycode::S;
|
||||
case XK_T: return Keyboard::Keycode::T;
|
||||
case XK_U: return Keyboard::Keycode::U;
|
||||
case XK_V: return Keyboard::Keycode::V;
|
||||
case XK_W: return Keyboard::Keycode::W;
|
||||
case XK_X: return Keyboard::Keycode::X;
|
||||
case XK_Y: return Keyboard::Keycode::Y;
|
||||
case XK_Z: return Keyboard::Keycode::Z;
|
||||
|
||||
case XK_a: return Keyboard::Keycode::a;
|
||||
case XK_b: return Keyboard::Keycode::b;
|
||||
case XK_c: return Keyboard::Keycode::c;
|
||||
case XK_d: return Keyboard::Keycode::d;
|
||||
case XK_e: return Keyboard::Keycode::e;
|
||||
case XK_f: return Keyboard::Keycode::f;
|
||||
case XK_g: return Keyboard::Keycode::g;
|
||||
case XK_h: return Keyboard::Keycode::h;
|
||||
case XK_i: return Keyboard::Keycode::i;
|
||||
case XK_j: return Keyboard::Keycode::j;
|
||||
case XK_k: return Keyboard::Keycode::k;
|
||||
case XK_l: return Keyboard::Keycode::l;
|
||||
case XK_m: return Keyboard::Keycode::m;
|
||||
case XK_n: return Keyboard::Keycode::n;
|
||||
case XK_o: return Keyboard::Keycode::o;
|
||||
case XK_p: return Keyboard::Keycode::p;
|
||||
case XK_q: return Keyboard::Keycode::q;
|
||||
case XK_r: return Keyboard::Keycode::r;
|
||||
case XK_s: return Keyboard::Keycode::s;
|
||||
case XK_t: return Keyboard::Keycode::t;
|
||||
case XK_u: return Keyboard::Keycode::u;
|
||||
case XK_v: return Keyboard::Keycode::v;
|
||||
case XK_w: return Keyboard::Keycode::w;
|
||||
case XK_x: return Keyboard::Keycode::x;
|
||||
case XK_y: return Keyboard::Keycode::y;
|
||||
case XK_z: return Keyboard::Keycode::z;
|
||||
|
||||
case XK_Num_Lock: return Keyboard::Keycode::NumLock;
|
||||
case XK_KP_Divide: return Keyboard::Keycode::Divide;
|
||||
case XK_KP_Multiply: return Keyboard::Keycode::Multiply;
|
||||
case XK_KP_Subtract: return Keyboard::Keycode::Subtract;
|
||||
case XK_KP_Add: return Keyboard::Keycode::Add;
|
||||
case XK_KP_Enter: return Keyboard::Keycode::Enter;
|
||||
case XK_KP_Decimal: return Keyboard::Keycode::Point;
|
||||
|
||||
case XK_KP_1: return Keyboard::Keycode::Keypad1;
|
||||
case XK_KP_2: return Keyboard::Keycode::Keypad2;
|
||||
case XK_KP_3: return Keyboard::Keycode::Keypad3;
|
||||
case XK_KP_4: return Keyboard::Keycode::Keypad4;
|
||||
case XK_KP_5: return Keyboard::Keycode::Keypad5;
|
||||
case XK_KP_6: return Keyboard::Keycode::Keypad6;
|
||||
case XK_KP_7: return Keyboard::Keycode::Keypad7;
|
||||
case XK_KP_8: return Keyboard::Keycode::Keypad8;
|
||||
case XK_KP_9: return Keyboard::Keycode::Keypad9;
|
||||
case XK_KP_0: return Keyboard::Keycode::Keypad0;
|
||||
|
||||
case XK_KP_Home: return Keyboard::Keycode::KeypadHome;
|
||||
case XK_KP_End: return Keyboard::Keycode::KeypadEnd;
|
||||
case XK_KP_Page_Up: return Keyboard::Keycode::KeypadPageUp;
|
||||
case XK_KP_Page_Down: return Keyboard::Keycode::KeypadPageDown;
|
||||
case XK_KP_Up: return Keyboard::Keycode::KeypadUp;
|
||||
case XK_KP_Down: return Keyboard::Keycode::KeypadDown;
|
||||
case XK_KP_Left: return Keyboard::Keycode::KeypadLeft;
|
||||
case XK_KP_Right: return Keyboard::Keycode::KeypadRight;
|
||||
case XK_KP_Begin: return Keyboard::Keycode::KeypadCenter;
|
||||
case XK_KP_Insert: return Keyboard::Keycode::KeypadInsert;
|
||||
case XK_KP_Delete: return Keyboard::Keycode::KeypadDelete;
|
||||
}
|
||||
return Keyboard::Keycode::None;
|
||||
}
|
|
@ -1,14 +1,40 @@
|
|||
Geometry pButton::minimumGeometry() {
|
||||
Geometry geometry = pFont::geometry(qtWidget->font(), button.state.text);
|
||||
|
||||
if(button.state.orientation == Orientation::Horizontal) {
|
||||
geometry.width += button.state.image.width;
|
||||
geometry.height = max(button.state.image.height, geometry.height);
|
||||
}
|
||||
|
||||
if(button.state.orientation == Orientation::Vertical) {
|
||||
geometry.width = max(button.state.image.width, geometry.width);
|
||||
geometry.height += button.state.image.height;
|
||||
}
|
||||
|
||||
return { 0, 0, geometry.width + 20, geometry.height + 12 };
|
||||
}
|
||||
|
||||
void pButton::setImage(const image &image, Orientation orientation) {
|
||||
nall::image qtBuffer = image;
|
||||
qtBuffer.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||
|
||||
QImage qtImage(qtBuffer.data, qtBuffer.width, qtBuffer.height, QImage::Format_ARGB32);
|
||||
QIcon qtIcon(QPixmap::fromImage(qtImage));
|
||||
qtButton->setIconSize(QSize(qtBuffer.width, qtBuffer.height));
|
||||
qtButton->setIcon(qtIcon);
|
||||
switch(orientation) {
|
||||
case Orientation::Horizontal: qtButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
|
||||
case Orientation::Vertical: qtButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pButton::setText(const string &text) {
|
||||
qtButton->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pButton::constructor() {
|
||||
qtWidget = qtButton = new QPushButton;
|
||||
qtWidget = qtButton = new QToolButton;
|
||||
qtButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||
connect(qtButton, SIGNAL(released()), SLOT(onActivate()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
|
|
|
@ -45,7 +45,7 @@ Geometry pWindow::geometry() {
|
|||
if(window.state.fullScreen) {
|
||||
unsigned menuHeight = window.state.menuVisible ? qtMenu->height() : 0;
|
||||
unsigned statusHeight = window.state.statusVisible ? qtStatus->height() : 0;
|
||||
return { 0, menuHeight, OS::desktopGeometry().width, OS::desktopGeometry().height - menuHeight - statusHeight };
|
||||
return { 0, menuHeight, Desktop::size().width, Desktop::size().height - menuHeight - statusHeight };
|
||||
}
|
||||
return window.state.geometry;
|
||||
}
|
||||
|
@ -84,9 +84,8 @@ void pWindow::setFullScreen(bool fullScreen) {
|
|||
qtWindow->showNormal();
|
||||
qtWindow->adjustSize();
|
||||
} else {
|
||||
Geometry geometry = OS::desktopGeometry(), margin = frameMargin();
|
||||
qtLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
|
||||
qtContainer->setFixedSize(geometry.width - margin.width, geometry.height - margin.height);
|
||||
qtContainer->setFixedSize(Desktop::size().width - frameMargin().width, Desktop::size().height - frameMargin().height);
|
||||
qtWindow->showFullScreen();
|
||||
}
|
||||
}
|
||||
|
@ -243,6 +242,16 @@ void pWindow::QtWindow::moveEvent(QMoveEvent *event) {
|
|||
}
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::keyPressEvent(QKeyEvent *event) {
|
||||
Keyboard::Keycode sym = Keysym(event->nativeVirtualKey());
|
||||
if(sym != Keyboard::Keycode::None && self.window.onKeyPress) self.window.onKeyPress(sym);
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::keyReleaseEvent(QKeyEvent *event) {
|
||||
Keyboard::Keycode sym = Keysym(event->nativeVirtualKey());
|
||||
if(sym != Keyboard::Keycode::None && self.window.onKeyRelease) self.window.onKeyRelease(sym);
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::resizeEvent(QResizeEvent*) {
|
||||
if(self.locked == false && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) {
|
||||
self.window.state.geometry.width = self.qtContainer->geometry().width();
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
void pItem::setImage(const image &image) {
|
||||
}
|
||||
|
||||
void pItem::setText(const string &text) {
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
Size pDesktop::size() {
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
Geometry pDesktop::workspace() {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
string pDialogWindow::fileOpen(Window &parent, const string &path, const lstring &filter) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string pDialogWindow::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string pDialogWindow::folderSelect(Window &parent, const string &path) {
|
||||
return "";
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
array<bool> pKeyboard::state() {
|
||||
array<bool> output;
|
||||
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||
for(auto &n : output) n = false;
|
||||
return output;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
Position pMouse::position() {
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
bool pMouse::pressed(Mouse::Button button) {
|
||||
return false;
|
||||
}
|
|
@ -1,8 +1,13 @@
|
|||
#include "platform.hpp"
|
||||
|
||||
#include "desktop.cpp"
|
||||
#include "keyboard.cpp"
|
||||
#include "mouse.cpp"
|
||||
#include "dialog-window.cpp"
|
||||
#include "message-window.cpp"
|
||||
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
#include "action/action.cpp"
|
||||
|
@ -30,26 +35,6 @@
|
|||
#include "widget/vertical-slider.cpp"
|
||||
#include "widget/viewport.cpp"
|
||||
|
||||
Geometry pOS::availableGeometry() {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
Geometry pOS::desktopGeometry() {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
string pOS::fileLoad(Window &parent, const string &path, const lstring &filter) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string pOS::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string pOS::folderSelect(Window &parent, const string &path) {
|
||||
return "";
|
||||
}
|
||||
|
||||
void pOS::main() {
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,34 @@ struct pFont {
|
|||
static Geometry geometry(const string &description, const string &text);
|
||||
};
|
||||
|
||||
struct pDesktop {
|
||||
static Size size();
|
||||
static Geometry workspace();
|
||||
};
|
||||
|
||||
struct pKeyboard {
|
||||
static bool pressed(Keyboard::Scancode scancode);
|
||||
static array<bool> state();
|
||||
};
|
||||
|
||||
struct pMouse {
|
||||
static Position position();
|
||||
static bool pressed(Mouse::Button button);
|
||||
};
|
||||
|
||||
struct pDialogWindow {
|
||||
static string fileOpen(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
};
|
||||
|
||||
struct pMessageWindow {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pObject {
|
||||
Object &object;
|
||||
bool locked;
|
||||
|
@ -20,11 +48,6 @@ struct pObject {
|
|||
};
|
||||
|
||||
struct pOS : public pObject {
|
||||
static Geometry availableGeometry();
|
||||
static Geometry desktopGeometry();
|
||||
static string fileLoad(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
static void main();
|
||||
static bool pendingEvents();
|
||||
static void processEvents();
|
||||
|
@ -43,13 +66,6 @@ struct pTimer : public pObject {
|
|||
void constructor();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pWindow : public pObject {
|
||||
Window &window;
|
||||
|
||||
|
@ -114,6 +130,7 @@ struct pSeparator : public pAction {
|
|||
struct pItem : public pAction {
|
||||
Item &item;
|
||||
|
||||
void setImage(const image &image);
|
||||
void setText(const string &text);
|
||||
|
||||
pItem(Item &item) : pAction(item), item(item) {}
|
||||
|
@ -176,6 +193,7 @@ struct pWidget : public pSizable {
|
|||
struct pButton : public pWidget {
|
||||
Button &button;
|
||||
|
||||
void setImage(const image &image, Orientation orientation);
|
||||
void setText(const string &text);
|
||||
|
||||
pButton(Button &button) : pWidget(button), button(button) {}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
void pButton::setImage(const image &image, Orientation orientation) {
|
||||
}
|
||||
|
||||
void pButton::setText(const string &text) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,29 @@
|
|||
void pItem::setImage(const image &image) {
|
||||
createBitmap();
|
||||
if(parentWindow) parentWindow->p.updateMenu();
|
||||
}
|
||||
|
||||
void pItem::setText(const string &text) {
|
||||
if(parentWindow) parentWindow->p.updateMenu();
|
||||
}
|
||||
|
||||
void pItem::constructor() {
|
||||
createBitmap();
|
||||
}
|
||||
|
||||
void pItem::destructor() {
|
||||
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
||||
if(parentMenu) parentMenu->remove(item);
|
||||
}
|
||||
|
||||
void pItem::createBitmap() {
|
||||
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
||||
|
||||
if(item.state.image.width && item.state.image.height) {
|
||||
nall::image nallImage = item.state.image;
|
||||
nallImage.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||
nallImage.alphaBlend(GetSysColor(COLOR_MENU)); //Windows does not alpha blend menu icons properly (leaves black outline)
|
||||
nallImage.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
|
||||
hbitmap = CreateBitmap(nallImage);
|
||||
}
|
||||
}
|
|
@ -39,7 +39,18 @@ void pMenu::update(Window &parentWindow, Menu *parentMenu) {
|
|||
if(action.state.visible) AppendMenu(hmenu, MF_SEPARATOR | enabled, item.p.id, L"");
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
Item &item = (Item&)action;
|
||||
if(action.state.visible) AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
||||
if(action.state.visible) {
|
||||
AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
||||
|
||||
if(item.state.image.width && item.state.image.height) {
|
||||
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
|
||||
//Windows XP and below displays MIIM_BITMAP + hbmpItem in its own column (separate from check/radio marks)
|
||||
//this causes too much spacing, so use a custom checkmark image instead
|
||||
mii.fMask = MIIM_CHECKMARKS;
|
||||
mii.hbmpUnchecked = item.p.hbitmap;
|
||||
SetMenuItemInfo(hmenu, item.p.id, FALSE, &mii);
|
||||
}
|
||||
}
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
CheckItem &item = (CheckItem&)action;
|
||||
if(action.state.visible) AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Size pDesktop::size() {
|
||||
return { GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) };
|
||||
}
|
||||
|
||||
Geometry pDesktop::workspace() {
|
||||
RECT rc;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
|
||||
return { rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top };
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
static string FileDialog(bool save, Window &parent, const string &path, const lstring &filter) {
|
||||
string dir = path;
|
||||
dir.replace("/", "\\");
|
||||
|
||||
string filterList;
|
||||
for(auto &filterItem : filter) {
|
||||
lstring part;
|
||||
part.split("(", filterItem);
|
||||
if(part.size() != 2) continue;
|
||||
part[1].rtrim<1>(")");
|
||||
part[1].replace(" ", "");
|
||||
part[1].transform(",", ";");
|
||||
filterList.append(string(filterItem, "\t", part[1], "\t"));
|
||||
}
|
||||
|
||||
utf16_t wfilter(filterList);
|
||||
utf16_t wdir(dir);
|
||||
wchar_t wfilename[PATH_MAX + 1] = L"";
|
||||
|
||||
wchar_t *p = wfilter;
|
||||
while(*p != L'\0') {
|
||||
if(*p == L'\t') *p = L'\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
OPENFILENAME ofn;
|
||||
memset(&ofn, 0, sizeof(OPENFILENAME));
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
ofn.hwndOwner = &parent != &Window::None ? parent.p.hwnd : 0;
|
||||
ofn.lpstrFilter = wfilter;
|
||||
ofn.lpstrInitialDir = wdir;
|
||||
ofn.lpstrFile = wfilename;
|
||||
ofn.nMaxFile = PATH_MAX;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
ofn.lpstrDefExt = L"";
|
||||
|
||||
bool result = (save == false ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn));
|
||||
if(result == false) return "";
|
||||
string name = (const char*)utf8_t(wfilename);
|
||||
name.transform("\\", "/");
|
||||
return name;
|
||||
}
|
||||
|
||||
string pDialogWindow::fileOpen(Window &parent, const string &path, const lstring &filter) {
|
||||
return FileDialog(false, parent, path, filter);
|
||||
}
|
||||
|
||||
string pDialogWindow::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
return FileDialog(true, parent, path, filter);
|
||||
}
|
||||
|
||||
string pDialogWindow::folderSelect(Window &parent, const string &path) {
|
||||
wchar_t wfilename[PATH_MAX + 1] = L"";
|
||||
BROWSEINFO bi;
|
||||
bi.hwndOwner = &parent != &Window::None ? parent.p.hwnd : 0;
|
||||
bi.pidlRoot = NULL;
|
||||
bi.pszDisplayName = wfilename;
|
||||
bi.lpszTitle = L"";
|
||||
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
|
||||
bi.lpfn = NULL;
|
||||
bi.lParam = 0;
|
||||
bi.iImage = 0;
|
||||
bool result = false;
|
||||
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
||||
if(pidl) {
|
||||
if(SHGetPathFromIDList(pidl, wfilename)) {
|
||||
result = true;
|
||||
IMalloc *imalloc = 0;
|
||||
if(SUCCEEDED(SHGetMalloc(&imalloc))) {
|
||||
imalloc->Free(pidl);
|
||||
imalloc->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(result == false) return "";
|
||||
string name = (const char*)utf8_t(wfilename);
|
||||
if(name == "") return "";
|
||||
name.transform("\\", "/");
|
||||
if(name.endswith("/") == false) name.append("/");
|
||||
return name;
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
|
||||
|
||||
void pKeyboard::initialize() {
|
||||
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
||||
keymap.append(scancode, keysym);
|
||||
};
|
||||
|
||||
append(Keyboard::Scancode::Escape, VK_ESCAPE);
|
||||
append(Keyboard::Scancode::F1, VK_F1);
|
||||
append(Keyboard::Scancode::F2, VK_F2);
|
||||
append(Keyboard::Scancode::F3, VK_F3);
|
||||
append(Keyboard::Scancode::F4, VK_F4);
|
||||
append(Keyboard::Scancode::F5, VK_F5);
|
||||
append(Keyboard::Scancode::F6, VK_F6);
|
||||
append(Keyboard::Scancode::F7, VK_F7);
|
||||
append(Keyboard::Scancode::F8, VK_F8);
|
||||
append(Keyboard::Scancode::F9, VK_F9);
|
||||
append(Keyboard::Scancode::F10, VK_F10);
|
||||
append(Keyboard::Scancode::F11, VK_F11);
|
||||
append(Keyboard::Scancode::F12, VK_F12);
|
||||
|
||||
append(Keyboard::Scancode::PrintScreen, VK_SNAPSHOT);
|
||||
append(Keyboard::Scancode::ScrollLock, VK_SCROLL);
|
||||
append(Keyboard::Scancode::Pause, VK_PAUSE);
|
||||
|
||||
append(Keyboard::Scancode::Insert, VK_INSERT);
|
||||
append(Keyboard::Scancode::Delete, VK_DELETE);
|
||||
append(Keyboard::Scancode::Home, VK_HOME);
|
||||
append(Keyboard::Scancode::End, VK_END);
|
||||
append(Keyboard::Scancode::PageUp, VK_PRIOR);
|
||||
append(Keyboard::Scancode::PageDown, VK_NEXT);
|
||||
|
||||
append(Keyboard::Scancode::Up, VK_UP);
|
||||
append(Keyboard::Scancode::Down, VK_DOWN);
|
||||
append(Keyboard::Scancode::Left, VK_LEFT);
|
||||
append(Keyboard::Scancode::Right, VK_RIGHT);
|
||||
|
||||
append(Keyboard::Scancode::Grave, VK_OEM_3);
|
||||
append(Keyboard::Scancode::Number1, '1');
|
||||
append(Keyboard::Scancode::Number2, '2');
|
||||
append(Keyboard::Scancode::Number3, '3');
|
||||
append(Keyboard::Scancode::Number4, '4');
|
||||
append(Keyboard::Scancode::Number5, '5');
|
||||
append(Keyboard::Scancode::Number6, '6');
|
||||
append(Keyboard::Scancode::Number7, '7');
|
||||
append(Keyboard::Scancode::Number8, '8');
|
||||
append(Keyboard::Scancode::Number9, '9');
|
||||
append(Keyboard::Scancode::Number0, '0');
|
||||
append(Keyboard::Scancode::Minus, VK_OEM_MINUS);
|
||||
append(Keyboard::Scancode::Equal, VK_OEM_PLUS);
|
||||
append(Keyboard::Scancode::Backspace, VK_BACK);
|
||||
|
||||
append(Keyboard::Scancode::BracketLeft, VK_OEM_4);
|
||||
append(Keyboard::Scancode::BracketRight, VK_OEM_6);
|
||||
append(Keyboard::Scancode::Backslash, VK_OEM_5);
|
||||
append(Keyboard::Scancode::Semicolon, VK_OEM_1);
|
||||
append(Keyboard::Scancode::Apostrophe, VK_OEM_7);
|
||||
append(Keyboard::Scancode::Comma, VK_OEM_COMMA);
|
||||
append(Keyboard::Scancode::Period, VK_OEM_PERIOD);
|
||||
append(Keyboard::Scancode::Slash, VK_OEM_2);
|
||||
|
||||
append(Keyboard::Scancode::Tab, VK_TAB);
|
||||
append(Keyboard::Scancode::CapsLock, VK_CAPITAL);
|
||||
append(Keyboard::Scancode::Return, VK_RETURN);
|
||||
append(Keyboard::Scancode::ShiftLeft, VK_LSHIFT);
|
||||
append(Keyboard::Scancode::ShiftRight, VK_RSHIFT);
|
||||
append(Keyboard::Scancode::ControlLeft, VK_LCONTROL);
|
||||
append(Keyboard::Scancode::ControlRight, VK_RCONTROL);
|
||||
append(Keyboard::Scancode::SuperLeft, VK_LWIN);
|
||||
append(Keyboard::Scancode::SuperRight, VK_RWIN);
|
||||
append(Keyboard::Scancode::AltLeft, VK_LMENU);
|
||||
append(Keyboard::Scancode::AltRight, VK_RMENU);
|
||||
append(Keyboard::Scancode::Space, VK_SPACE);
|
||||
append(Keyboard::Scancode::Menu, VK_APPS);
|
||||
|
||||
append(Keyboard::Scancode::A, 'A');
|
||||
append(Keyboard::Scancode::B, 'B');
|
||||
append(Keyboard::Scancode::C, 'C');
|
||||
append(Keyboard::Scancode::D, 'D');
|
||||
append(Keyboard::Scancode::E, 'E');
|
||||
append(Keyboard::Scancode::F, 'F');
|
||||
append(Keyboard::Scancode::G, 'G');
|
||||
append(Keyboard::Scancode::H, 'H');
|
||||
append(Keyboard::Scancode::I, 'I');
|
||||
append(Keyboard::Scancode::J, 'J');
|
||||
append(Keyboard::Scancode::K, 'K');
|
||||
append(Keyboard::Scancode::L, 'L');
|
||||
append(Keyboard::Scancode::M, 'M');
|
||||
append(Keyboard::Scancode::N, 'N');
|
||||
append(Keyboard::Scancode::O, 'O');
|
||||
append(Keyboard::Scancode::P, 'P');
|
||||
append(Keyboard::Scancode::Q, 'Q');
|
||||
append(Keyboard::Scancode::R, 'R');
|
||||
append(Keyboard::Scancode::S, 'S');
|
||||
append(Keyboard::Scancode::T, 'T');
|
||||
append(Keyboard::Scancode::U, 'U');
|
||||
append(Keyboard::Scancode::V, 'V');
|
||||
append(Keyboard::Scancode::W, 'W');
|
||||
append(Keyboard::Scancode::X, 'X');
|
||||
append(Keyboard::Scancode::Y, 'Y');
|
||||
append(Keyboard::Scancode::Z, 'Z');
|
||||
|
||||
append(Keyboard::Scancode::NumLock, VK_NUMLOCK);
|
||||
append(Keyboard::Scancode::Divide, VK_DIVIDE);
|
||||
append(Keyboard::Scancode::Multiply, VK_MULTIPLY);
|
||||
append(Keyboard::Scancode::Subtract, VK_SUBTRACT);
|
||||
append(Keyboard::Scancode::Add, VK_ADD);
|
||||
//append(Keyboard::Scancode::Enter, ...);
|
||||
append(Keyboard::Scancode::Point, VK_DECIMAL);
|
||||
|
||||
append(Keyboard::Scancode::Keypad1, VK_NUMPAD1);
|
||||
append(Keyboard::Scancode::Keypad2, VK_NUMPAD2);
|
||||
append(Keyboard::Scancode::Keypad3, VK_NUMPAD3);
|
||||
append(Keyboard::Scancode::Keypad4, VK_NUMPAD4);
|
||||
append(Keyboard::Scancode::Keypad5, VK_NUMPAD5);
|
||||
append(Keyboard::Scancode::Keypad6, VK_NUMPAD6);
|
||||
append(Keyboard::Scancode::Keypad7, VK_NUMPAD7);
|
||||
append(Keyboard::Scancode::Keypad8, VK_NUMPAD8);
|
||||
append(Keyboard::Scancode::Keypad9, VK_NUMPAD9);
|
||||
append(Keyboard::Scancode::Keypad0, VK_NUMPAD0);
|
||||
}
|
||||
|
||||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||
return GetAsyncKeyState(keymap.lhs[scancode]) & 0x8000;
|
||||
}
|
||||
|
||||
array<bool> pKeyboard::state() {
|
||||
array<bool> output;
|
||||
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||
for(auto &n : output) n = false;
|
||||
|
||||
for(auto &n : keymap.rhs) {
|
||||
if(GetAsyncKeyState(n.name) & 0x8000) {
|
||||
output[(unsigned)n.data] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
Position pMouse::position() {
|
||||
POINT point = { 0 };
|
||||
GetCursorPos(&point);
|
||||
return { point.x, point.y };
|
||||
}
|
||||
|
||||
bool pMouse::pressed(Mouse::Button button) {
|
||||
switch(button) {
|
||||
case Mouse::Button::Left: return GetAsyncKeyState(VK_LBUTTON) & 0x8000;
|
||||
case Mouse::Button::Middle: return GetAsyncKeyState(VK_MBUTTON) & 0x8000;
|
||||
case Mouse::Button::Right: return GetAsyncKeyState(VK_RBUTTON) & 0x8000;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,9 +1,15 @@
|
|||
#include "platform.hpp"
|
||||
#include "utility.cpp"
|
||||
|
||||
#include "desktop.cpp"
|
||||
#include "keyboard.cpp"
|
||||
#include "mouse.cpp"
|
||||
#include "dialog-window.cpp"
|
||||
#include "message-window.cpp"
|
||||
|
||||
#include "object.cpp"
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
#include "action/action.cpp"
|
||||
|
@ -35,98 +41,6 @@ static bool OS_keyboardProc(HWND, UINT, WPARAM, LPARAM);
|
|||
static void OS_processDialogMessage(MSG&);
|
||||
static LRESULT CALLBACK OS_windowProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
Geometry pOS::availableGeometry() {
|
||||
RECT rc;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
|
||||
return { rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top };
|
||||
}
|
||||
|
||||
Geometry pOS::desktopGeometry() {
|
||||
return { 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) };
|
||||
}
|
||||
|
||||
static string pOS_fileDialog(bool save, Window &parent, const string &path, const lstring &filter) {
|
||||
string dir = path;
|
||||
dir.replace("/", "\\");
|
||||
|
||||
string filterList;
|
||||
for(auto &filterItem : filter) {
|
||||
lstring part;
|
||||
part.split("(", filterItem);
|
||||
if(part.size() != 2) continue;
|
||||
part[1].rtrim<1>(")");
|
||||
part[1].replace(" ", "");
|
||||
part[1].transform(",", ";");
|
||||
filterList.append(string(filterItem, "\t", part[1], "\t"));
|
||||
}
|
||||
|
||||
utf16_t wfilter(filterList);
|
||||
utf16_t wdir(dir);
|
||||
wchar_t wfilename[PATH_MAX + 1] = L"";
|
||||
|
||||
wchar_t *p = wfilter;
|
||||
while(*p != L'\0') {
|
||||
if(*p == L'\t') *p = L'\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
OPENFILENAME ofn;
|
||||
memset(&ofn, 0, sizeof(OPENFILENAME));
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
ofn.hwndOwner = &parent != &Window::None ? parent.p.hwnd : 0;
|
||||
ofn.lpstrFilter = wfilter;
|
||||
ofn.lpstrInitialDir = wdir;
|
||||
ofn.lpstrFile = wfilename;
|
||||
ofn.nMaxFile = PATH_MAX;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
ofn.lpstrDefExt = L"";
|
||||
|
||||
bool result = (save == false ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn));
|
||||
if(result == false) return "";
|
||||
string name = (const char*)utf8_t(wfilename);
|
||||
name.transform("\\", "/");
|
||||
return name;
|
||||
}
|
||||
|
||||
string pOS::fileLoad(Window &parent, const string &path, const lstring &filter) {
|
||||
return pOS_fileDialog(false, parent, path, filter);
|
||||
}
|
||||
|
||||
string pOS::fileSave(Window &parent, const string &path, const lstring &filter) {
|
||||
return pOS_fileDialog(true, parent, path, filter);
|
||||
}
|
||||
|
||||
string pOS::folderSelect(Window &parent, const string &path) {
|
||||
wchar_t wfilename[PATH_MAX + 1] = L"";
|
||||
BROWSEINFO bi;
|
||||
bi.hwndOwner = &parent != &Window::None ? parent.p.hwnd : 0;
|
||||
bi.pidlRoot = NULL;
|
||||
bi.pszDisplayName = wfilename;
|
||||
bi.lpszTitle = L"";
|
||||
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
|
||||
bi.lpfn = NULL;
|
||||
bi.lParam = 0;
|
||||
bi.iImage = 0;
|
||||
bool result = false;
|
||||
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
||||
if(pidl) {
|
||||
if(SHGetPathFromIDList(pidl, wfilename)) {
|
||||
result = true;
|
||||
IMalloc *imalloc = 0;
|
||||
if(SUCCEEDED(SHGetMalloc(&imalloc))) {
|
||||
imalloc->Free(pidl);
|
||||
imalloc->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(result == false) return "";
|
||||
string name = (const char*)utf8_t(wfilename);
|
||||
if(name == "") return "";
|
||||
name.transform("\\", "/");
|
||||
if(name.endswith("/") == false) name.append("/");
|
||||
return name;
|
||||
}
|
||||
|
||||
void pOS::main() {
|
||||
MSG msg;
|
||||
while(GetMessage(&msg, 0, 0, 0)) {
|
||||
|
@ -149,7 +63,8 @@ void pOS::processEvents() {
|
|||
}
|
||||
|
||||
void OS_processDialogMessage(MSG &msg) {
|
||||
if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP) {
|
||||
if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP
|
||||
|| msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP) {
|
||||
if(OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam)) {
|
||||
DispatchMessage(&msg);
|
||||
return;
|
||||
|
@ -163,6 +78,7 @@ void OS_processDialogMessage(MSG &msg) {
|
|||
}
|
||||
|
||||
void pOS::quit() {
|
||||
osQuit = true;
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
|
@ -218,16 +134,31 @@ void pOS::initialize() {
|
|||
wc.lpszMenuName = 0;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
RegisterClass(&wc);
|
||||
|
||||
pKeyboard::initialize();
|
||||
}
|
||||
|
||||
static bool OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
if(msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN && msg != WM_KEYUP && msg != WM_SYSKEYUP) return false;
|
||||
|
||||
GUITHREADINFO info;
|
||||
memset(&info, 0, sizeof(GUITHREADINFO));
|
||||
info.cbSize = sizeof(GUITHREADINFO);
|
||||
GetGUIThreadInfo(GetCurrentThreadId(), &info);
|
||||
Object *object = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
|
||||
if(object == nullptr) return false;
|
||||
|
||||
if(dynamic_cast<Window*>(object)) {
|
||||
Window &window = (Window&)*object;
|
||||
Keyboard::Keycode keysym = Keysym(wparam, lparam);
|
||||
if(keysym != Keyboard::Keycode::None) {
|
||||
if((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && window.onKeyPress) window.onKeyPress(keysym);
|
||||
if((msg == WM_KEYUP || msg == WM_SYSKEYUP) && window.onKeyRelease) window.onKeyRelease(keysym);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(msg == WM_KEYDOWN) {
|
||||
GUITHREADINFO info;
|
||||
memset(&info, 0, sizeof(GUITHREADINFO));
|
||||
info.cbSize = sizeof(GUITHREADINFO);
|
||||
GetGUIThreadInfo(GetCurrentThreadId(), &info);
|
||||
Object *object = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
|
||||
if(object == nullptr) return false;
|
||||
if(dynamic_cast<ListView*>(object)) {
|
||||
ListView &listView = (ListView&)*object;
|
||||
if(wparam == VK_RETURN) {
|
||||
|
@ -287,7 +218,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
if(!object || !dynamic_cast<Window*>(object)) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
Window &window = (Window&)*object;
|
||||
|
||||
switch(msg) {
|
||||
if(!osQuit) switch(msg) {
|
||||
case WM_CLOSE: {
|
||||
window.state.ignore = false;
|
||||
if(window.onClose) window.onClose();
|
||||
|
|
|
@ -4,6 +4,8 @@ struct pMenu;
|
|||
struct pLayout;
|
||||
struct pWidget;
|
||||
|
||||
static bool osQuit = false;
|
||||
|
||||
struct pFont {
|
||||
static Geometry geometry(const string &description, const string &text);
|
||||
|
||||
|
@ -12,6 +14,38 @@ struct pFont {
|
|||
static Geometry geometry(HFONT hfont, const string &text);
|
||||
};
|
||||
|
||||
struct pDesktop {
|
||||
static Size size();
|
||||
static Geometry workspace();
|
||||
};
|
||||
|
||||
struct pKeyboard {
|
||||
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
||||
|
||||
static bool pressed(Keyboard::Scancode scancode);
|
||||
static array<bool> state();
|
||||
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
struct pMouse {
|
||||
static Position position();
|
||||
static bool pressed(Mouse::Button button);
|
||||
};
|
||||
|
||||
struct pDialogWindow {
|
||||
static string fileOpen(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
};
|
||||
|
||||
struct pMessageWindow {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pObject {
|
||||
Object &object;
|
||||
uintptr_t id;
|
||||
|
@ -27,11 +61,6 @@ struct pObject {
|
|||
};
|
||||
|
||||
struct pOS : public pObject {
|
||||
static Geometry availableGeometry();
|
||||
static Geometry desktopGeometry();
|
||||
static string fileLoad(Window &parent, const string &path, const lstring &filter);
|
||||
static string fileSave(Window &parent, const string &path, const lstring &filter);
|
||||
static string folderSelect(Window &parent, const string &path);
|
||||
static void main();
|
||||
static bool pendingEvents();
|
||||
static void processEvents();
|
||||
|
@ -51,13 +80,6 @@ struct pTimer : public pObject {
|
|||
void constructor();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
};
|
||||
|
||||
struct pWindow : public pObject {
|
||||
Window &window;
|
||||
HWND hwnd;
|
||||
|
@ -133,12 +155,15 @@ struct pSeparator : public pAction {
|
|||
|
||||
struct pItem : public pAction {
|
||||
Item &item;
|
||||
HBITMAP hbitmap;
|
||||
|
||||
void setImage(const image &image);
|
||||
void setText(const string &text);
|
||||
|
||||
pItem(Item &item) : pAction(item), item(item) {}
|
||||
pItem(Item &item) : pAction(item), item(item), hbitmap(0) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void createBitmap();
|
||||
};
|
||||
|
||||
struct pCheckItem : public pAction {
|
||||
|
@ -202,11 +227,14 @@ struct pWidget : public pSizable {
|
|||
|
||||
struct pButton : public pWidget {
|
||||
Button &button;
|
||||
HBITMAP hbitmap;
|
||||
HIMAGELIST himagelist;
|
||||
|
||||
Geometry minimumGeometry();
|
||||
void setImage(const image &image, Orientation orientation);
|
||||
void setText(const string &text);
|
||||
|
||||
pButton(Button &button) : pWidget(button), button(button) {}
|
||||
pButton(Button &button) : pWidget(button), button(button), hbitmap(0), himagelist(0) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
static const unsigned Windows2000 = 0x0500;
|
||||
static const unsigned WindowsXP = 0x0501;
|
||||
static const unsigned WindowsVista = 0x0600;
|
||||
static const unsigned Windows7 = 0x0601;
|
||||
|
||||
static unsigned OsVersion() {
|
||||
OSVERSIONINFO versionInfo = { 0 };
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&versionInfo);
|
||||
return (versionInfo.dwMajorVersion << 8) + (versionInfo.dwMajorVersion << 0);
|
||||
}
|
||||
|
||||
static HBITMAP CreateBitmap(const image &image) {
|
||||
HDC hdc = GetDC(0);
|
||||
BITMAPINFO bitmapInfo;
|
||||
memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
|
||||
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.bmiHeader.biWidth = image.width;
|
||||
bitmapInfo.bmiHeader.biHeight = -image.height; //bitmaps are stored upside down unless we negate height
|
||||
bitmapInfo.bmiHeader.biPlanes = 1;
|
||||
bitmapInfo.bmiHeader.biBitCount = 32;
|
||||
bitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
bitmapInfo.bmiHeader.biSizeImage = image.width * image.height * 4;
|
||||
void *bits = nullptr;
|
||||
HBITMAP hbitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
|
||||
if(bits) memcpy(bits, image.data, image.width * image.height * 4);
|
||||
ReleaseDC(0, hdc);
|
||||
return hbitmap;
|
||||
}
|
||||
|
||||
static Keyboard::Keycode Keysym(unsigned keysym, unsigned keyflags) {
|
||||
#define pressed(keysym) (GetAsyncKeyState(keysym) & 0x8000)
|
||||
#define enabled(keysym) (GetKeyState(keysym))
|
||||
#define shifted() (pressed(VK_LSHIFT) || pressed(VK_RSHIFT))
|
||||
#define extended() (keyflags & (1 << 24))
|
||||
|
||||
switch(keysym) {
|
||||
case VK_ESCAPE: return Keyboard::Keycode::Escape;
|
||||
case VK_F1: return Keyboard::Keycode::F1;
|
||||
case VK_F2: return Keyboard::Keycode::F2;
|
||||
case VK_F3: return Keyboard::Keycode::F3;
|
||||
case VK_F4: return Keyboard::Keycode::F4;
|
||||
case VK_F5: return Keyboard::Keycode::F5;
|
||||
case VK_F6: return Keyboard::Keycode::F6;
|
||||
case VK_F7: return Keyboard::Keycode::F7;
|
||||
case VK_F8: return Keyboard::Keycode::F8;
|
||||
case VK_F9: return Keyboard::Keycode::F9;
|
||||
//Keyboard::Keycode::F10 (should be captured under VK_MENU from WM_SYSKEY(UP,DOWN); but this is not working...)
|
||||
case VK_F11: return Keyboard::Keycode::F11;
|
||||
case VK_F12: return Keyboard::Keycode::F12;
|
||||
|
||||
//Keyboard::Keycode::PrintScreen
|
||||
//Keyboard::Keycode::SysRq
|
||||
case VK_SCROLL: return Keyboard::Keycode::ScrollLock;
|
||||
case VK_PAUSE: return Keyboard::Keycode::Pause;
|
||||
//Keyboard::Keycode::Break
|
||||
|
||||
case VK_INSERT: return extended() ? Keyboard::Keycode::Insert : Keyboard::Keycode::KeypadInsert;
|
||||
case VK_DELETE: return extended() ? Keyboard::Keycode::Delete : Keyboard::Keycode::KeypadDelete;
|
||||
case VK_HOME: return extended() ? Keyboard::Keycode::Home : Keyboard::Keycode::KeypadHome;
|
||||
case VK_END: return extended() ? Keyboard::Keycode::End : Keyboard::Keycode::KeypadEnd;
|
||||
case VK_PRIOR: return extended() ? Keyboard::Keycode::PageUp : Keyboard::Keycode::KeypadPageUp;
|
||||
case VK_NEXT: return extended() ? Keyboard::Keycode::PageDown : Keyboard::Keycode::KeypadPageDown;
|
||||
|
||||
case VK_UP: return extended() ? Keyboard::Keycode::Up : Keyboard::Keycode::KeypadUp;
|
||||
case VK_DOWN: return extended() ? Keyboard::Keycode::Down : Keyboard::Keycode::KeypadDown;
|
||||
case VK_LEFT: return extended() ? Keyboard::Keycode::Left : Keyboard::Keycode::KeypadLeft;
|
||||
case VK_RIGHT: return extended() ? Keyboard::Keycode::Right : Keyboard::Keycode::KeypadRight;
|
||||
|
||||
case VK_OEM_3: return !shifted() ? Keyboard::Keycode::Grave : Keyboard::Keycode::Tilde;
|
||||
case '1': return !shifted() ? Keyboard::Keycode::Number1 : Keyboard::Keycode::Exclamation;
|
||||
case '2': return !shifted() ? Keyboard::Keycode::Number2 : Keyboard::Keycode::At;
|
||||
case '3': return !shifted() ? Keyboard::Keycode::Number3 : Keyboard::Keycode::Pound;
|
||||
case '4': return !shifted() ? Keyboard::Keycode::Number4 : Keyboard::Keycode::Dollar;
|
||||
case '5': return !shifted() ? Keyboard::Keycode::Number5 : Keyboard::Keycode::Percent;
|
||||
case '6': return !shifted() ? Keyboard::Keycode::Number6 : Keyboard::Keycode::Power;
|
||||
case '7': return !shifted() ? Keyboard::Keycode::Number7 : Keyboard::Keycode::Ampersand;
|
||||
case '8': return !shifted() ? Keyboard::Keycode::Number8 : Keyboard::Keycode::Asterisk;
|
||||
case '9': return !shifted() ? Keyboard::Keycode::Number9 : Keyboard::Keycode::ParenthesisLeft;
|
||||
case '0': return !shifted() ? Keyboard::Keycode::Number0 : Keyboard::Keycode::ParenthesisRight;
|
||||
case VK_OEM_MINUS: return !shifted() ? Keyboard::Keycode::Minus : Keyboard::Keycode::Underscore;
|
||||
case VK_OEM_PLUS: return !shifted() ? Keyboard::Keycode::Equal : Keyboard::Keycode::Plus;
|
||||
case VK_BACK: return Keyboard::Keycode::Backspace;
|
||||
|
||||
case VK_OEM_4: return !shifted() ? Keyboard::Keycode::BracketLeft : Keyboard::Keycode::BraceLeft;
|
||||
case VK_OEM_6: return !shifted() ? Keyboard::Keycode::BracketRight : Keyboard::Keycode::BraceRight;
|
||||
case VK_OEM_5: return !shifted() ? Keyboard::Keycode::Backslash : Keyboard::Keycode::Pipe;
|
||||
case VK_OEM_1: return !shifted() ? Keyboard::Keycode::Semicolon : Keyboard::Keycode::Colon;
|
||||
case VK_OEM_7: return !shifted() ? Keyboard::Keycode::Apostrophe : Keyboard::Keycode::Quote;
|
||||
case VK_OEM_COMMA: return !shifted() ? Keyboard::Keycode::Comma : Keyboard::Keycode::CaretLeft;
|
||||
case VK_OEM_PERIOD: return !shifted() ? Keyboard::Keycode::Period : Keyboard::Keycode::CaretRight;
|
||||
case VK_OEM_2: return !shifted() ? Keyboard::Keycode::Slash : Keyboard::Keycode::Question;
|
||||
|
||||
case VK_TAB: return Keyboard::Keycode::Tab;
|
||||
case VK_CAPITAL: return Keyboard::Keycode::CapsLock;
|
||||
case VK_RETURN: return !extended() ? Keyboard::Keycode::Return : Keyboard::Keycode::Enter;
|
||||
case VK_SHIFT: return !pressed(VK_RSHIFT) ? Keyboard::Keycode::ShiftLeft : Keyboard::Keycode::ShiftRight;
|
||||
case VK_CONTROL: return !pressed(VK_RCONTROL) ? Keyboard::Keycode::ControlLeft : Keyboard::Keycode::ControlRight;
|
||||
case VK_LWIN: return Keyboard::Keycode::SuperLeft;
|
||||
case VK_RWIN: return Keyboard::Keycode::SuperRight;
|
||||
case VK_MENU:
|
||||
if(keyflags & (1 << 24)) return Keyboard::Keycode::AltRight;
|
||||
return Keyboard::Keycode::AltLeft;
|
||||
case VK_SPACE: return Keyboard::Keycode::Space;
|
||||
case VK_APPS: return Keyboard::Keycode::Menu;
|
||||
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M':
|
||||
case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
||||
if(enabled(VK_CAPITAL)) {
|
||||
if(shifted()) {
|
||||
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::a + keysym - 'A');
|
||||
} else {
|
||||
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::A + keysym - 'A');
|
||||
}
|
||||
} else {
|
||||
if(shifted()) {
|
||||
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::A + keysym - 'A');
|
||||
} else {
|
||||
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::a + keysym - 'A');
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_NUMLOCK: return Keyboard::Keycode::NumLock;
|
||||
case VK_DIVIDE: return Keyboard::Keycode::Divide;
|
||||
case VK_MULTIPLY: return Keyboard::Keycode::Multiply;
|
||||
case VK_SUBTRACT: return Keyboard::Keycode::Subtract;
|
||||
case VK_ADD: return Keyboard::Keycode::Add;
|
||||
case VK_DECIMAL: return Keyboard::Keycode::Point;
|
||||
case VK_NUMPAD1: return Keyboard::Keycode::Keypad1;
|
||||
case VK_NUMPAD2: return Keyboard::Keycode::Keypad2;
|
||||
case VK_NUMPAD3: return Keyboard::Keycode::Keypad3;
|
||||
case VK_NUMPAD4: return Keyboard::Keycode::Keypad4;
|
||||
case VK_NUMPAD5: return Keyboard::Keycode::Keypad5;
|
||||
case VK_NUMPAD6: return Keyboard::Keycode::Keypad6;
|
||||
case VK_NUMPAD7: return Keyboard::Keycode::Keypad7;
|
||||
case VK_NUMPAD8: return Keyboard::Keycode::Keypad8;
|
||||
case VK_NUMPAD9: return Keyboard::Keycode::Keypad9;
|
||||
case VK_NUMPAD0: return Keyboard::Keycode::Keypad0;
|
||||
|
||||
case VK_CLEAR: return Keyboard::Keycode::KeypadCenter;
|
||||
}
|
||||
|
||||
return Keyboard::Keycode::None;
|
||||
|
||||
#undef pressed
|
||||
#undef enabled
|
||||
#undef shifted
|
||||
#undef extended
|
||||
}
|
|
@ -1,8 +1,51 @@
|
|||
Geometry pButton::minimumGeometry() {
|
||||
Geometry geometry = pFont::geometry(hfont, button.state.text);
|
||||
|
||||
if(button.state.orientation == Orientation::Horizontal) {
|
||||
geometry.width += button.state.image.width;
|
||||
geometry.height = max(button.state.image.height, geometry.height);
|
||||
}
|
||||
|
||||
if(button.state.orientation == Orientation::Vertical) {
|
||||
geometry.width = max(button.state.image.width, geometry.width);
|
||||
geometry.height += button.state.image.height;
|
||||
}
|
||||
|
||||
return { 0, 0, geometry.width + 20, geometry.height + 10 };
|
||||
}
|
||||
|
||||
void pButton::setImage(const image &image, Orientation orientation) {
|
||||
nall::image nallImage = image;
|
||||
nallImage.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||
|
||||
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
||||
if(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; }
|
||||
|
||||
if(OsVersion() >= WindowsVista) {
|
||||
hbitmap = CreateBitmap(nallImage);
|
||||
SendMessage(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbitmap);
|
||||
switch(orientation) {
|
||||
case Orientation::Horizontal: SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) & ~BS_TOP); break;
|
||||
case Orientation::Vertical: SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | BS_TOP); break;
|
||||
}
|
||||
} else {
|
||||
//Windows XP and earlier cannot display bitmaps and text at the same time with BM_SETIMAGE
|
||||
//Use BCM_SETIMAGELIST instead. It does not support alpha blending, so blend with button color
|
||||
//The XP theme and above use a gradient fade background, so it won't be a perfect match there
|
||||
nallImage.alphaBlend(GetSysColor(COLOR_BTNFACE));
|
||||
hbitmap = CreateBitmap(nallImage);
|
||||
himagelist = ImageList_Create(nallImage.width, nallImage.height, ILC_COLOR32, 1, 0);
|
||||
ImageList_Add(himagelist, hbitmap, NULL);
|
||||
BUTTON_IMAGELIST list;
|
||||
list.himl = himagelist;
|
||||
switch(orientation) {
|
||||
case Orientation::Horizontal: SetRect(&list.margin, 5, 0, 0, 0); list.uAlign = BUTTON_IMAGELIST_ALIGN_LEFT; break;
|
||||
case Orientation::Vertical: SetRect(&list.margin, 0, 5, 0, 0); list.uAlign = BUTTON_IMAGELIST_ALIGN_TOP; break;
|
||||
}
|
||||
Button_SetImageList(hwnd, &list);
|
||||
}
|
||||
}
|
||||
|
||||
void pButton::setText(const string &text) {
|
||||
SetWindowText(hwnd, utf16_t(text));
|
||||
}
|
||||
|
@ -11,11 +54,14 @@ void pButton::constructor() {
|
|||
hwnd = CreateWindow(L"BUTTON", L"", WS_CHILD | WS_TABSTOP, 0, 0, 0, 0, parentWindow->p.hwnd, (HMENU)id, GetModuleHandle(0), 0);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&button);
|
||||
setDefaultFont();
|
||||
setImage(button.state.image, button.state.orientation);
|
||||
setText(button.state.text);
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void pButton::destructor() {
|
||||
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
||||
if(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; }
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
|
|
|
@ -116,9 +116,9 @@ uint32 PPU::Screen::get_pixel(bool swap) {
|
|||
}
|
||||
|
||||
if(swap == true) {
|
||||
nall::swap(priority_main, priority_sub);
|
||||
nall::swap(color_main, color_sub);
|
||||
nall::swap(source_main, source_sub);
|
||||
std::swap(priority_main, priority_sub);
|
||||
std::swap(color_main, color_sub);
|
||||
std::swap(source_main, source_sub);
|
||||
}
|
||||
|
||||
uint16 output;
|
||||
|
|
|
@ -7,7 +7,7 @@ serializer System::serialize() {
|
|||
char description[512], profile[16];
|
||||
memset(&description, 0, sizeof description);
|
||||
memset(&profile, 0, sizeof profile);
|
||||
strlcpy(profile, Info::Profile, sizeof profile);
|
||||
strmcpy(profile, Info::Profile, sizeof profile);
|
||||
|
||||
s.integer(signature);
|
||||
s.integer(version);
|
||||
|
|
|
@ -79,7 +79,7 @@ struct Interface : public SNES::Interface {
|
|||
static Interface interface;
|
||||
|
||||
const char* snes_library_id(void) {
|
||||
return "bsnes v083";
|
||||
return "bsnes v085";
|
||||
}
|
||||
|
||||
unsigned snes_library_revision_major(void) {
|
||||
|
@ -115,7 +115,8 @@ void snes_set_cartridge_basename(const char *basename) {
|
|||
}
|
||||
|
||||
void snes_init(void) {
|
||||
interface.initialize(&interface);
|
||||
SNES::interface = &interface;
|
||||
SNES::system.init();
|
||||
SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::Joypad);
|
||||
SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Joypad);
|
||||
}
|
||||
|
@ -163,7 +164,10 @@ static linear_vector<CheatList> cheatList;
|
|||
|
||||
void snes_cheat_reset(void) {
|
||||
cheatList.reset();
|
||||
interface.setCheats();
|
||||
GameBoy::cheat.reset();
|
||||
GameBoy::cheat.synchronize();
|
||||
SNES::cheat.reset();
|
||||
SNES::cheat.synchronize();
|
||||
}
|
||||
|
||||
void snes_cheat_set(unsigned index, bool enable, const char *code) {
|
||||
|
@ -173,7 +177,35 @@ void snes_cheat_set(unsigned index, bool enable, const char *code) {
|
|||
for(unsigned n = 0; n < cheatList.size(); n++) {
|
||||
if(cheatList[n].enable) list.append(cheatList[n].code);
|
||||
}
|
||||
interface.setCheats(list);
|
||||
|
||||
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {
|
||||
GameBoy::cheat.reset();
|
||||
for(auto &code : list) {
|
||||
lstring codelist;
|
||||
codelist.split("+", code);
|
||||
for(auto &part : codelist) {
|
||||
unsigned addr, data, comp;
|
||||
if(GameBoy::Cheat::decode(part, addr, data, comp)) {
|
||||
GameBoy::cheat.append({ addr, data, comp });
|
||||
}
|
||||
}
|
||||
}
|
||||
GameBoy::cheat.synchronize();
|
||||
return;
|
||||
}
|
||||
|
||||
SNES::cheat.reset();
|
||||
for(auto &code : list) {
|
||||
lstring codelist;
|
||||
codelist.split("+", code);
|
||||
for(auto &part : codelist) {
|
||||
unsigned addr, data;
|
||||
if(SNES::Cheat::decode(part, addr, data)) {
|
||||
SNES::cheat.append({ addr, data });
|
||||
}
|
||||
}
|
||||
}
|
||||
SNES::cheat.synchronize();
|
||||
}
|
||||
|
||||
bool snes_load_cartridge_normal(
|
||||
|
@ -244,7 +276,7 @@ bool snes_load_cartridge_super_game_boy(
|
|||
uint8_t *data = new uint8_t[dmg_size];
|
||||
memcpy(data, dmg_data, dmg_size);
|
||||
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : GameBoyCartridge(data, dmg_size).markup;
|
||||
GameBoy::cartridge.load(xmldmg, data, dmg_size);
|
||||
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, xmldmg, data, dmg_size);
|
||||
delete[] data;
|
||||
}
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, xmlrom);
|
||||
|
|
|
@ -27,7 +27,7 @@ FileBrowser::FileBrowser() {
|
|||
};
|
||||
|
||||
pathBrowse.onActivate = [&] {
|
||||
string path = OS::folderSelect(*this, mode->path);
|
||||
string path = DialogWindow::folderSelect(*this, mode->path);
|
||||
if(path != "") setPath(path);
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ int16_t AbstractInput::poll() {
|
|||
//
|
||||
|
||||
bool AnalogInput::bind(int16_t scancode, int16_t value) {
|
||||
using nall::Mouse;
|
||||
string encode = Scancode::encode(scancode);
|
||||
Type type = Type::Button;
|
||||
|
||||
|
@ -66,6 +67,8 @@ int16_t AnalogInput::poll() {
|
|||
//
|
||||
|
||||
bool DigitalInput::bind(int16_t scancode, int16_t value) {
|
||||
using nall::Keyboard;
|
||||
using nall::Mouse;
|
||||
string encode = Scancode::encode(scancode);
|
||||
Type type = Type::Button;
|
||||
|
||||
|
|
|
@ -317,9 +317,9 @@ int16_t InterfaceSNES::inputPoll(bool port, SNES::Input::Device device, unsigned
|
|||
if(device == SNES::Input::Device::Joypad) return inputManager->snes.port1.gamepad.poll(id);
|
||||
if(device == SNES::Input::Device::Multitap) {
|
||||
if(index == 0) return inputManager->snes.port1.multitap1.poll(id);
|
||||
if(index == 1) return inputManager->snes.port1.multitap1.poll(id);
|
||||
if(index == 2) return inputManager->snes.port1.multitap1.poll(id);
|
||||
if(index == 3) return inputManager->snes.port1.multitap1.poll(id);
|
||||
if(index == 1) return inputManager->snes.port1.multitap2.poll(id);
|
||||
if(index == 2) return inputManager->snes.port1.multitap3.poll(id);
|
||||
if(index == 3) return inputManager->snes.port1.multitap4.poll(id);
|
||||
}
|
||||
if(device == SNES::Input::Device::Mouse) return inputManager->snes.port1.mouse.poll(id);
|
||||
}
|
||||
|
@ -328,9 +328,9 @@ int16_t InterfaceSNES::inputPoll(bool port, SNES::Input::Device device, unsigned
|
|||
if(device == SNES::Input::Device::Joypad) return inputManager->snes.port2.gamepad.poll(id);
|
||||
if(device == SNES::Input::Device::Multitap) {
|
||||
if(index == 0) return inputManager->snes.port2.multitap1.poll(id);
|
||||
if(index == 1) return inputManager->snes.port2.multitap1.poll(id);
|
||||
if(index == 2) return inputManager->snes.port2.multitap1.poll(id);
|
||||
if(index == 3) return inputManager->snes.port2.multitap1.poll(id);
|
||||
if(index == 1) return inputManager->snes.port2.multitap2.poll(id);
|
||||
if(index == 2) return inputManager->snes.port2.multitap3.poll(id);
|
||||
if(index == 3) return inputManager->snes.port2.multitap4.poll(id);
|
||||
}
|
||||
if(device == SNES::Input::Device::Mouse) return inputManager->snes.port2.mouse.poll(id);
|
||||
if(device == SNES::Input::Device::SuperScope) return inputManager->snes.port2.superScope.poll(id);
|
||||
|
|
|
@ -27,7 +27,7 @@ void Application::run() {
|
|||
}
|
||||
|
||||
Application::Application(int argc, char **argv) {
|
||||
title = "bsnes v085";
|
||||
title = "bsnes v085.01";
|
||||
|
||||
application = this;
|
||||
quit = false;
|
||||
|
|
|
@ -133,6 +133,7 @@ void InputSettings::clearInput() {
|
|||
}
|
||||
|
||||
void InputSettings::inputEvent(int16_t scancode, int16_t value, bool allowMouseInput) {
|
||||
using nall::Mouse;
|
||||
if(activeInput == 0) return;
|
||||
if(allowMouseInput == false && (Mouse::isAnyButton(scancode) || Mouse::isAnyAxis(scancode))) return;
|
||||
if(activeInput->bind(scancode, value) == false) return;
|
||||
|
|
|
@ -141,7 +141,7 @@ void StateManager::slotErase() {
|
|||
string StateManager::slotLoadDescription(unsigned n) {
|
||||
if(slot[n].capacity() == 0) return "(empty)";
|
||||
char text[DescriptionLength];
|
||||
strlcpy(text, (const char*)slot[n].data() + HeaderLength, DescriptionLength);
|
||||
strmcpy(text, (const char*)slot[n].data() + HeaderLength, DescriptionLength);
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ void StateManager::slotSaveDescription() {
|
|||
if(stateList.selected() == false) return;
|
||||
string text = descEdit.text();
|
||||
if(slot[stateList.selection()].capacity() > 0) {
|
||||
strlcpy((char*)slot[stateList.selection()].data() + HeaderLength, (const char*)text, DescriptionLength);
|
||||
strmcpy((char*)slot[stateList.selection()].data() + HeaderLength, (const char*)text, DescriptionLength);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue