Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
961
Src/Wasabi/bfc/platform/linux/linux.cpp
Normal file
961
Src/Wasabi/bfc/platform/linux/linux.cpp
Normal file
|
@ -0,0 +1,961 @@
|
|||
#include <precomp.h>
|
||||
|
||||
#include <api/api.h>
|
||||
#include <api/linux/api_linux.h>
|
||||
|
||||
#include <bfc/ptrlist.h>
|
||||
#include <bfc/string/string.h>
|
||||
#include <bfc/critsec.h>
|
||||
#include <bfc/thread.h>
|
||||
#include <api/application/ipcs.h>
|
||||
|
||||
#ifdef WASABI_COMPILE_WND
|
||||
Display *Linux::display = NULL;
|
||||
|
||||
int linux_atoms_loaded = 0;
|
||||
|
||||
Atom winamp_msg;
|
||||
Atom dnd_enter, dnd_position, dnd_status, dnd_leave, dnd_drop, dnd_finished;
|
||||
Atom dnd_selection, dnd_wa3drop, dnd_private, dnd_typelist;
|
||||
Atom dnd_urilist, dnd_textplain, dnd_mozurl;
|
||||
#endif
|
||||
|
||||
#ifndef _NOSTUDIO
|
||||
|
||||
#ifdef WASABI_COMPILE_WND
|
||||
void LoadAtoms() {
|
||||
if ( !linux_atoms_loaded ) {
|
||||
linux_atoms_loaded = 1;
|
||||
winamp_msg = XInternAtom( Linux::getDisplay(), "Winamp3", False );
|
||||
dnd_wa3drop = XInternAtom( Linux::getDisplay(), "Winamp3_drop", False );
|
||||
dnd_enter = XInternAtom( Linux::getDisplay(), "XdndEnter", True );
|
||||
dnd_position = XInternAtom( Linux::getDisplay(), "XdndPosition", True );
|
||||
dnd_status = XInternAtom( Linux::getDisplay(), "XdndStatus", True );
|
||||
dnd_leave = XInternAtom( Linux::getDisplay(), "XdndLeave", True );
|
||||
dnd_drop = XInternAtom( Linux::getDisplay(), "XdndDrop", True );
|
||||
dnd_finished = XInternAtom( Linux::getDisplay(), "XdndFinished", True );
|
||||
dnd_selection = XInternAtom( Linux::getDisplay(), "XdndSelection", True );
|
||||
dnd_private = XInternAtom( Linux::getDisplay(), "XdndActionPrivate", True );
|
||||
dnd_typelist = XInternAtom( Linux::getDisplay(), "XdndTypeList", True );
|
||||
dnd_urilist = XInternAtom( Linux::getDisplay(), "text/uri-list", True );
|
||||
dnd_textplain = XInternAtom( Linux::getDisplay(), "text/plain", True );
|
||||
dnd_mozurl = XInternAtom( Linux::getDisplay(), "text/x-moz-url", True );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
void OutputDebugString( const char *s ) {
|
||||
#ifdef _DEBUG
|
||||
fprintf( stderr, "%s", s );
|
||||
#endif
|
||||
char *file = getenv( "WASABI_LOG_FILE" );
|
||||
if ( file ) {
|
||||
if ( !STRCMP( file, "-" ) ) {
|
||||
fprintf( stdout, "%s", s );
|
||||
} else {
|
||||
FILE *f = fopen( file, "a" );
|
||||
if ( f ) {
|
||||
fprintf( f, "%s", s );
|
||||
fclose( f );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DWORD GetTickCount() {
|
||||
static int starttime = -1;
|
||||
|
||||
if ( starttime == -1 )
|
||||
starttime = time( NULL );
|
||||
|
||||
struct timeb tb;
|
||||
ftime( &tb );
|
||||
tb.time -= starttime;
|
||||
return tb.time * 1000 + tb.millitm;
|
||||
}
|
||||
void Sleep( int ms ) {
|
||||
if ( ms != 0 ) {
|
||||
struct timespec ts = { 0, 0 };
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms % 1000) * 1000000;
|
||||
nanosleep( &ts, NULL);
|
||||
// usleep(ms * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _NOSTUDIO
|
||||
|
||||
#ifdef WASABI_COMPILE_WND
|
||||
|
||||
Display *Linux::getDisplay() {
|
||||
if ( ! display )
|
||||
display = WASABI_API_LINUX->linux_getDisplay();
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
XContext Linux::getContext() {
|
||||
static XContext context = 0;
|
||||
|
||||
if ( context == 0 )
|
||||
context = WASABI_API_LINUX->linux_getContext();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
int Linux::getScreenNum() { return DefaultScreen( getDisplay() ); }
|
||||
|
||||
Window Linux::RootWin() {
|
||||
return RootWindow( getDisplay(), getScreenNum() );
|
||||
}
|
||||
Visual *Linux::DefaultVis() {
|
||||
return DefaultVisual( getDisplay(), getScreenNum() );
|
||||
}
|
||||
|
||||
void Linux::setCursor( HWND h, int cursor ) {
|
||||
Cursor c = XCreateFontCursor( Linux::getDisplay(), cursor );
|
||||
|
||||
if ( cursor == None )
|
||||
XUndefineCursor( Linux::getDisplay(), h );
|
||||
else
|
||||
XDefineCursor( Linux::getDisplay(), h, c );
|
||||
|
||||
XFreeCursor( Linux::getDisplay(), c );
|
||||
}
|
||||
|
||||
int Linux::convertEvent( MSG *m, XEvent *e ) {
|
||||
m->hwnd = e->xany.window;
|
||||
|
||||
if ( m->hwnd ) {
|
||||
api_window *rw =(api_window *)GetWindowLong( m->hwnd, GWL_USERDATA );
|
||||
if ( !rw ) {
|
||||
// This is to fix messages for dead windows...
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( e->type ) {
|
||||
case ButtonPress:
|
||||
switch( e->xbutton.button ) {
|
||||
case 1:
|
||||
m->message = WM_LBUTTONDOWN;
|
||||
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
case 3:
|
||||
m->message = WM_RBUTTONDOWN;
|
||||
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m->message = WM_MOUSEWHEEL;
|
||||
m->wParam = 120 << 16 | 0; // 1 tick, no modifiers
|
||||
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m->message = WM_MOUSEWHEEL;
|
||||
m->wParam = (-120) << 16 | 0; // 1 tick, no modifiers
|
||||
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
switch( e->xbutton.button ) {
|
||||
case 1:
|
||||
m->message = WM_LBUTTONUP;
|
||||
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
case 3:
|
||||
m->message = WM_RBUTTONUP;
|
||||
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MotionNotify:
|
||||
{
|
||||
m->message = WM_MOUSEMOVE;
|
||||
do {
|
||||
// Spin...
|
||||
} while( XCheckTypedWindowEvent( Linux::getDisplay(), m->hwnd, MotionNotify, e ) );
|
||||
|
||||
RECT r;
|
||||
POINT offset = {0, 0};
|
||||
HWND hwnd = m->hwnd;
|
||||
|
||||
GetWindowRect( hwnd, &r );
|
||||
|
||||
m->lParam = ((e->xmotion.x_root - r.left) & 0xffff) |
|
||||
((e->xmotion.y_root - r.top) << 16);
|
||||
|
||||
if ( ! (e->xmotion.state & ( Button1Mask | Button2Mask | Button3Mask )) )
|
||||
PostMessage( m->hwnd, WM_SETCURSOR, m->hwnd, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyPress:
|
||||
m->message = WM_KEYDOWN;
|
||||
m->wParam = e->xkey.keycode;
|
||||
break;
|
||||
|
||||
case KeyRelease:
|
||||
m->message = WM_KEYUP;
|
||||
m->wParam = e->xkey.keycode;
|
||||
break;
|
||||
|
||||
case Expose:
|
||||
{
|
||||
RECT r;
|
||||
m->message = WM_PAINT;
|
||||
do {
|
||||
r.left = e->xexpose.x;
|
||||
r.top = e->xexpose.y;
|
||||
r.right = r.left + e->xexpose.width;
|
||||
r.bottom = r.top + e->xexpose.height;
|
||||
InvalidateRect( m->hwnd, &r, FALSE );
|
||||
} while( XCheckTypedWindowEvent( Linux::getDisplay(), m->hwnd, Expose, e ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case ClientMessage: {
|
||||
static int coord = -1;
|
||||
static Atom supported = None;
|
||||
XClientMessageEvent cme;
|
||||
|
||||
LoadAtoms();
|
||||
|
||||
int message = e->xclient.message_type;
|
||||
if ( message == dnd_enter ) {
|
||||
if ( e->xclient.data.l[1] & 1 ) {
|
||||
Atom actual;
|
||||
int format;
|
||||
long unsigned int nitems, bytes;
|
||||
unsigned char *data = NULL;
|
||||
|
||||
XGetWindowProperty( Linux::getDisplay(), e->xclient.data.l[0],
|
||||
dnd_typelist, 0, 65536, True, XA_ATOM,
|
||||
&actual, &format, &nitems, &bytes, &data );
|
||||
|
||||
Atom *atomdata = (Atom *)data;
|
||||
|
||||
supported = None;
|
||||
for( int i = 0; i < nitems; i++ ) {
|
||||
if ( atomdata[i] == dnd_urilist ) {
|
||||
supported = dnd_urilist;
|
||||
}
|
||||
}
|
||||
if ( supported == None ) {
|
||||
for( int i = 0; i < nitems; i++ ) {
|
||||
if ( atomdata[i] == dnd_textplain ) {
|
||||
OutputDebugString( "text/plain found\n" );
|
||||
supported = dnd_textplain;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( supported == None ) {
|
||||
for( int i = 0; i < nitems; i++ ) {
|
||||
if ( atomdata[i] == dnd_mozurl ) {
|
||||
supported = dnd_mozurl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XFree( data );
|
||||
} else {
|
||||
if ( e->xclient.data.l[2] == dnd_urilist ||
|
||||
e->xclient.data.l[3] == dnd_urilist ||
|
||||
e->xclient.data.l[4] == dnd_urilist ) {
|
||||
supported = dnd_urilist;
|
||||
} else if ( e->xclient.data.l[2] == dnd_mozurl ||
|
||||
e->xclient.data.l[3] == dnd_mozurl ||
|
||||
e->xclient.data.l[4] == dnd_mozurl ) {
|
||||
supported = dnd_mozurl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// DnD Enter
|
||||
return 0;
|
||||
|
||||
} else if ( message == dnd_position ) {
|
||||
// DnD Position Notify
|
||||
|
||||
cme.type = ClientMessage;
|
||||
cme.message_type = dnd_status;
|
||||
cme.format = 32;
|
||||
cme.window = e->xclient.data.l[0];
|
||||
cme.data.l[0] = e->xclient.window;
|
||||
cme.data.l[1] = 1; // Can Accept
|
||||
cme.data.l[2] = cme.data.l[3] = 0; // Empty rectangle - give us moves
|
||||
cme.data.l[4] = dnd_private; // We're doing our own thing
|
||||
|
||||
if ( coord == -1 && supported != None ) {
|
||||
XConvertSelection( Linux::getDisplay(), dnd_selection, supported,
|
||||
dnd_wa3drop, cme.window, CurrentTime );
|
||||
}
|
||||
|
||||
coord = e->xclient.data.l[2];
|
||||
|
||||
XSendEvent( Linux::getDisplay(), e->xclient.data.l[0], False,
|
||||
NoEventMask, (XEvent *)&cme );
|
||||
|
||||
return 0;
|
||||
|
||||
} else if ( message == dnd_leave ) {
|
||||
// DnD Leave
|
||||
coord = -1;
|
||||
supported = None;
|
||||
|
||||
return 0;
|
||||
|
||||
} else if ( message == dnd_drop ) {
|
||||
// DnD Drop
|
||||
|
||||
Window win = e->xclient.data.l[0];
|
||||
|
||||
cme.type = ClientMessage;
|
||||
cme.message_type = dnd_finished;
|
||||
cme.format = 32;
|
||||
cme.window = e->xclient.data.l[0];
|
||||
cme.data.l[0] = e->xclient.window;
|
||||
cme.data.l[1] = cme.data.l[2] = cme.data.l[3] = cme.data.l[4] = 0;
|
||||
|
||||
XSendEvent( Linux::getDisplay(), e->xclient.data.l[0], False,
|
||||
NoEventMask, (XEvent *)&cme );
|
||||
|
||||
if ( supported != None ) {
|
||||
Atom actual;
|
||||
int format;
|
||||
long unsigned int nitems, bytes;
|
||||
unsigned char *data = NULL;
|
||||
|
||||
XGetWindowProperty( Linux::getDisplay(), cme.window, dnd_wa3drop,
|
||||
0, 65536, True, supported, &actual,
|
||||
&format, &nitems, &bytes,
|
||||
&data );
|
||||
|
||||
OutputDebugString( StringPrintf( "Drop data (%d):\n%s\n", nitems, data ) );
|
||||
|
||||
m->message = WM_DROPFILES;
|
||||
m->wParam = coord;
|
||||
m->lParam = (LPARAM)data;
|
||||
|
||||
coord = -1;
|
||||
supported = None;
|
||||
|
||||
} else {
|
||||
coord = -1;
|
||||
supported = None;
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} else if ( message == winamp_msg ) {
|
||||
// Internal Message ...
|
||||
|
||||
m->message = e->xclient.data.l[0];
|
||||
m->wParam = e->xclient.data.l[1];
|
||||
m->lParam = e->xclient.data.l[2];
|
||||
break;
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LeaveNotify:
|
||||
case EnterNotify:
|
||||
m->message = WM_MOUSEMOVE;
|
||||
m->lParam = (e->xcrossing.x & 0xffff) | (e->xcrossing.y << 16);
|
||||
|
||||
if ( ! (e->xcrossing.state & ( Button1Mask | Button2Mask | Button3Mask )) )
|
||||
PostMessage( m->hwnd, WM_SETCURSOR, m->hwnd, 0 );
|
||||
break;
|
||||
|
||||
case FocusIn:
|
||||
m->message = WM_SETFOCUS;
|
||||
break;
|
||||
|
||||
case FocusOut:
|
||||
m->message = WM_KILLFOCUS;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HWND activeWindow;
|
||||
|
||||
HWND GetActiveWindow() {
|
||||
return activeWindow;
|
||||
}
|
||||
|
||||
int IntersectRect( RECT *out, const RECT *i1, const RECT *i2 ) {
|
||||
return Std::rectIntersect(i1, i2, out);
|
||||
}
|
||||
|
||||
void TranslateMessage( MSG *m ) {
|
||||
if ( m->message != WM_CHAR && m->message != WM_KEYDOWN &&
|
||||
m->message != WM_KEYUP )
|
||||
return;
|
||||
|
||||
int index = !!( Std::keyDown( VK_SHIFT ));
|
||||
|
||||
m->wParam = XKeycodeToKeysym( Linux::getDisplay(), m->wParam, index );
|
||||
}
|
||||
|
||||
void PostMessage( HWND win, UINT msg, WPARAM wParam, LPARAM lParam ) {
|
||||
XEvent e;
|
||||
|
||||
LoadAtoms();
|
||||
|
||||
e.type = ClientMessage;
|
||||
e.xclient.window = win;
|
||||
e.xclient.message_type = winamp_msg;
|
||||
e.xclient.format = 32;
|
||||
e.xclient.data.l[0] = msg;
|
||||
e.xclient.data.l[1] = wParam;
|
||||
e.xclient.data.l[2] = lParam;
|
||||
|
||||
XSendEvent( Linux::getDisplay(), win, FALSE, NoEventMask, &e );
|
||||
}
|
||||
|
||||
void PostQuitMessage( int i ) {
|
||||
PostMessage( None, WM_QUIT, i, 0 );
|
||||
}
|
||||
|
||||
#endif // wnd
|
||||
|
||||
#if defined(WASABI_API_TIMER) | defined(WASABI_API_WND)
|
||||
|
||||
struct TimerElem {
|
||||
HWND win;
|
||||
int id;
|
||||
int nexttime;
|
||||
int delta;
|
||||
TIMERPROC tproc;
|
||||
|
||||
TimerElem( HWND _win, int _id, int ms, TIMERPROC _tproc ) {
|
||||
win = _win;
|
||||
id = _id;
|
||||
delta = ms;
|
||||
tproc = _tproc;
|
||||
nexttime = Std::getTickCount() + delta;
|
||||
}
|
||||
};
|
||||
|
||||
int timer_id = 0;
|
||||
CriticalSection timer_cs;
|
||||
PtrList<TimerElem> timer_elems;
|
||||
|
||||
int SetTimer( HWND win, int id, int ms, TIMERPROC tproc ) {
|
||||
KillTimer(win, id);
|
||||
|
||||
if ( win == (HWND)0 ) {
|
||||
id = timer_id++;
|
||||
}
|
||||
|
||||
TimerElem *te = new TimerElem( win, id, ms, tproc );
|
||||
timer_cs.enter();
|
||||
timer_elems.addItem( te, PTRLIST_POS_LAST );
|
||||
timer_cs.leave();
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void KillTimer( HWND win, int id ) {
|
||||
timer_cs.enter();
|
||||
for( int i = 0; i < timer_elems.getNumItems(); i++ )
|
||||
if ( timer_elems[i]->win == win && timer_elems[i]->id == id ) {
|
||||
delete timer_elems[i];
|
||||
timer_elems.delByPos( i );
|
||||
i--;
|
||||
}
|
||||
timer_cs.leave();
|
||||
}
|
||||
|
||||
CriticalSection send_cs;
|
||||
MSG *send_msg;
|
||||
int sending = 0;
|
||||
int send_ret;
|
||||
pthread_t message_thread = (pthread_t)-1;
|
||||
|
||||
int _GetMessage( MSG *m, HWND, UINT, UINT, int block=1) {
|
||||
MEMSET( m, 0, sizeof( MSG ) );
|
||||
|
||||
message_thread = pthread_self();
|
||||
|
||||
#ifdef WASABI_COMPILE_WND
|
||||
XEvent e;
|
||||
#endif // wnd
|
||||
int curtime;
|
||||
int done = 0;
|
||||
int first = 1;
|
||||
static wa_msgbuf ipcm;
|
||||
static int qid = -1;
|
||||
int size;
|
||||
|
||||
if ( qid == -1 ) { qid = WASABI_API_LINUX->linux_getIPCId(); }
|
||||
|
||||
if ( sending ) {
|
||||
*m = *send_msg;
|
||||
done = 1;
|
||||
}
|
||||
|
||||
while( !done && (block || first)) {
|
||||
if ( qid != -1 ) {
|
||||
if ( (size = msgrcv( qid, &ipcm, IPC_MSGMAX , 0, IPC_NOWAIT )) != -1 ) {
|
||||
m->hwnd = None;
|
||||
m->message = WM_WA_IPC;
|
||||
m->wParam = (WPARAM)&ipcm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
curtime = GetTickCount();
|
||||
|
||||
timer_cs.enter();
|
||||
for( int i = 0; i < timer_elems.getNumItems(); i++ ) {
|
||||
if ( timer_elems[i]->nexttime < curtime ) {
|
||||
if (block)
|
||||
while( timer_elems[i]->nexttime < curtime )
|
||||
timer_elems[i]->nexttime += timer_elems[i]->delta;
|
||||
|
||||
m->hwnd = timer_elems[i]->win;
|
||||
m->message = WM_TIMER;
|
||||
m->wParam = (WPARAM)timer_elems[i]->id;
|
||||
m->lParam = (LPARAM)timer_elems[i]->tproc;
|
||||
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
timer_cs.leave();
|
||||
|
||||
if ( !done && ! first )
|
||||
Sleep( 1 );
|
||||
else
|
||||
first = 0;
|
||||
|
||||
#ifdef WASABI_API_WND
|
||||
if ( !done && XPending( Linux::getDisplay() ) ) {
|
||||
int n = XEventsQueued( Linux::getDisplay(), QueuedAlready );
|
||||
|
||||
for ( int i = 0; !done && i < n; i++ ) {
|
||||
XNextEvent( Linux::getDisplay(), &e );
|
||||
if ( Linux::convertEvent( m, &e ) )
|
||||
done = 1;
|
||||
}
|
||||
if ( done )
|
||||
break;
|
||||
}
|
||||
#endif // wnd
|
||||
}
|
||||
|
||||
#ifdef WASABI_API_WND
|
||||
activeWindow = m->hwnd;
|
||||
#endif // wnd
|
||||
|
||||
return m->message != WM_QUIT;
|
||||
}
|
||||
|
||||
int GetMessage( MSG *m, HWND w, UINT f, UINT l) {
|
||||
return _GetMessage(m, w, f, l, 1);
|
||||
}
|
||||
|
||||
// on linux, we don't really simply peek when PM_NOREMOVE is used,
|
||||
// we just don't block, which is the only thing we want to accomplish here
|
||||
int PeekMessage( MSG *m, HWND w, UINT f, UINT l, UINT remove) {
|
||||
if (remove == PM_NOREMOVE) return _GetMessage(m, w, f, l, 0);
|
||||
else _GetMessage(m, w, f, l, 1);
|
||||
}
|
||||
|
||||
|
||||
int DispatchMessage( MSG *m ) {
|
||||
if ( m->message == WM_TIMER && m->hwnd == None ) {
|
||||
TIMERPROC tproc = (TIMERPROC)m->lParam;
|
||||
tproc( m->hwnd, m->message, m->wParam, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
|
||||
#ifdef WASABI_COMPILE_WND
|
||||
api_window *rootwnd = (api_window *)GetWindowLong( m->hwnd, GWL_USERDATA );
|
||||
|
||||
if ( rootwnd ) {
|
||||
ret = rootwnd->wndProc( m->hwnd, m->message, m->wParam, m->lParam );
|
||||
rootwnd->performBatchProcesses();
|
||||
}
|
||||
#endif // wnd
|
||||
|
||||
if ( sending ) {
|
||||
send_ret = ret;
|
||||
sending = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SendMessage( HWND win, UINT msg, WPARAM wParam, LPARAM lParam ) {
|
||||
MSG m;
|
||||
m.hwnd = win;
|
||||
m.message = msg;
|
||||
m.wParam = wParam;
|
||||
m.lParam = lParam;
|
||||
|
||||
int ret;
|
||||
|
||||
if ( pthread_equal( message_thread, pthread_self() ) ) {
|
||||
return DispatchMessage( &m );
|
||||
|
||||
} else {
|
||||
send_cs.enter();
|
||||
sending = 1;
|
||||
send_msg = &m;
|
||||
while( sending ) { Sleep( 1 ); }
|
||||
ret = send_ret;
|
||||
send_cs.leave();
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // timer | wnd
|
||||
|
||||
int MulDiv( int m1, int m2, int d ) {
|
||||
__asm__ volatile (
|
||||
"mov %0, %%eax\n"
|
||||
"mov %1, %%ebx\n"
|
||||
"mov %2, %%ecx\n"
|
||||
"mul %%ebx\n"
|
||||
"div %%ecx\n"
|
||||
: : "m" (m1), "m" (m2), "m" (d)
|
||||
: "%eax", "%ebx", "%ecx", "%edx" );
|
||||
}
|
||||
|
||||
void ExitProcess( int ret ) {
|
||||
exit( ret );
|
||||
}
|
||||
|
||||
#ifdef WASABI_COMPILE_WND
|
||||
|
||||
void Linux::initContextData( HWND h ) {
|
||||
int *data;
|
||||
XPointer xp;
|
||||
|
||||
ASSERT( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ));
|
||||
|
||||
data = (int *)MALLOC( GWL_ENUM_SIZE * sizeof( int ) );
|
||||
|
||||
data[GWL_HWND] = h;
|
||||
|
||||
XSaveContext( Linux::getDisplay(), h, Linux::getContext(), (char *)data );
|
||||
}
|
||||
|
||||
void Linux::nukeContextData( HWND h ) {
|
||||
int *data;
|
||||
XPointer xp;
|
||||
|
||||
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
|
||||
return;
|
||||
|
||||
data = (int *)xp;
|
||||
|
||||
ASSERT( data[GWL_HWND] == h );
|
||||
|
||||
if ( data[GWL_INVALIDREGION] ) {
|
||||
XDestroyRegion( (HRGN)data[GWL_INVALIDREGION] );
|
||||
}
|
||||
|
||||
XDeleteContext( Linux::getDisplay(), h, Linux::getContext() );
|
||||
|
||||
FREE( data );
|
||||
}
|
||||
|
||||
void SetWindowLong( HWND h, contextdata type, LONG value ) {
|
||||
XPointer data;
|
||||
|
||||
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &data ) )
|
||||
return;
|
||||
|
||||
ASSERT( ((int *)data)[GWL_HWND] == h );
|
||||
|
||||
((int*)data)[type] = value;
|
||||
}
|
||||
|
||||
LONG GetWindowLong( HWND h, contextdata type ) {
|
||||
XPointer data;
|
||||
|
||||
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &data ) )
|
||||
return 0;
|
||||
|
||||
ASSERT( ((int *)data)[GWL_HWND] == h );
|
||||
|
||||
return ((int*)data)[type];
|
||||
}
|
||||
|
||||
void MoveWindowRect( HWND h, int x, int y ) {
|
||||
XPointer xp;
|
||||
int *data;
|
||||
|
||||
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
|
||||
return;
|
||||
|
||||
data = (int *)xp;
|
||||
|
||||
ASSERT( data[GWL_HWND] == h );
|
||||
|
||||
data[GWL_RECT_RIGHT] -= data[GWL_RECT_LEFT] - x;
|
||||
data[GWL_RECT_BOTTOM] -= data[GWL_RECT_TOP] - y;
|
||||
data[GWL_RECT_LEFT] = x;
|
||||
data[GWL_RECT_TOP] = y;
|
||||
}
|
||||
|
||||
void SetWindowRect( HWND h, RECT *r ) {
|
||||
int *data;
|
||||
XPointer xp;
|
||||
|
||||
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
|
||||
return;
|
||||
|
||||
data = (int *)xp;
|
||||
|
||||
ASSERT( data[GWL_HWND] == h );
|
||||
|
||||
data[GWL_RECT_LEFT] = r->left;
|
||||
data[GWL_RECT_TOP] = r->top;
|
||||
data[GWL_RECT_RIGHT] = r->right;
|
||||
data[GWL_RECT_BOTTOM] = r->bottom;
|
||||
}
|
||||
|
||||
int GetWindowRect( HWND h, RECT *r ) {
|
||||
int *data;
|
||||
XPointer xp;
|
||||
|
||||
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
|
||||
return 0;
|
||||
|
||||
data = (int *)xp;
|
||||
|
||||
ASSERT( data[GWL_HWND] == h );
|
||||
|
||||
r->left = data[GWL_RECT_LEFT];
|
||||
r->top = data[GWL_RECT_TOP];
|
||||
r->right = data[GWL_RECT_RIGHT];
|
||||
r->bottom = data[GWL_RECT_BOTTOM];
|
||||
|
||||
POINT offset = { 0, 0};
|
||||
while( (h = data[GWL_PARENT]) != Linux::RootWin() ) {
|
||||
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
|
||||
return 0;
|
||||
|
||||
data = (int *)xp;
|
||||
|
||||
ASSERT( data[GWL_HWND] == h );
|
||||
|
||||
offset.x += data[GWL_RECT_LEFT];
|
||||
offset.y += data[GWL_RECT_TOP];
|
||||
}
|
||||
r->left += offset.x;
|
||||
r->top += offset.y;
|
||||
r->right += offset.x;
|
||||
r->bottom += offset.y;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetUpdateRect( HWND h, RECT *ret, BOOL ) {
|
||||
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
|
||||
if ( ! invalid || XEmptyRegion( invalid ) )
|
||||
return 0;
|
||||
|
||||
XRectangle xr;
|
||||
XClipBox( invalid, &xr );
|
||||
ret->left = xr.x;
|
||||
ret->top = xr.y;
|
||||
ret->right = xr.x + xr.width;
|
||||
ret->bottom = xr.y + xr.height;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GetUpdateRgn( HWND h, HRGN r, BOOL ) {
|
||||
XSubtractRegion( r, r, r );
|
||||
|
||||
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
|
||||
if ( ! invalid ) return;
|
||||
|
||||
|
||||
XUnionRegion( r, invalid, r );
|
||||
|
||||
XRectangle xr;
|
||||
|
||||
RECT rct;
|
||||
GetWindowRect( h, &rct );
|
||||
xr.x = 0;
|
||||
xr.y = 0;
|
||||
xr.width = rct.right - rct.left;
|
||||
xr.height = rct.bottom - rct.top;
|
||||
|
||||
HRGN tmp = XCreateRegion();
|
||||
|
||||
XUnionRectWithRegion( &xr, tmp, tmp );
|
||||
XIntersectRegion( r, tmp, r );
|
||||
XDestroyRegion( tmp );
|
||||
}
|
||||
|
||||
void InvalidateRect( HWND h, const RECT *r, BOOL ) {
|
||||
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
|
||||
if ( ! invalid ) {
|
||||
invalid = XCreateRegion();
|
||||
SetWindowLong( h, GWL_INVALIDREGION, (LONG)invalid );
|
||||
}
|
||||
|
||||
XRectangle xr;
|
||||
if ( r == NULL ) {
|
||||
RECT rct;
|
||||
GetWindowRect( h, &rct );
|
||||
xr.x = 0;
|
||||
xr.y = 0;
|
||||
xr.width = rct.right - rct.left;
|
||||
xr.height = rct.bottom - rct.top;
|
||||
} else {
|
||||
xr.x = r->left;
|
||||
xr.y = r->top;
|
||||
xr.width = r->right - r->left;
|
||||
xr.height = r->bottom - r->top;
|
||||
}
|
||||
|
||||
XUnionRectWithRegion( &xr, invalid, invalid );
|
||||
|
||||
PostMessage( h, WM_PAINT, 0, 0 );
|
||||
}
|
||||
|
||||
void InvalidateRgn( HWND h, HRGN r, BOOL ) {
|
||||
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
|
||||
|
||||
if ( ! invalid ) {
|
||||
invalid = XCreateRegion();
|
||||
SetWindowLong( h, GWL_INVALIDREGION, (LONG)invalid );
|
||||
}
|
||||
|
||||
ASSERT( r != invalid );
|
||||
XUnionRegion( invalid, r, invalid );
|
||||
|
||||
PostMessage( h, WM_PAINT, 0, 0 );
|
||||
}
|
||||
|
||||
void ValidateRect( HWND h, const RECT *r ) {
|
||||
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
|
||||
if ( ! invalid ) return;
|
||||
|
||||
XRectangle xr;
|
||||
if ( r == NULL ) {
|
||||
XDestroyRegion( invalid );
|
||||
SetWindowLong( h, GWL_INVALIDREGION, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
xr.x = r->left;
|
||||
xr.y = r->top;
|
||||
xr.width = r->right - r->left;
|
||||
xr.height = r->bottom - r->top;
|
||||
|
||||
HRGN tmp = XCreateRegion();
|
||||
XUnionRectWithRegion( &xr, tmp, tmp );
|
||||
XSubtractRegion( invalid, tmp, invalid );
|
||||
XDestroyRegion( tmp );
|
||||
}
|
||||
|
||||
void ValidateRgn( HWND h, HRGN r ) {
|
||||
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
|
||||
if ( ! invalid ) return;
|
||||
|
||||
ASSERT( r != invalid );
|
||||
XSubtractRegion( invalid, r, invalid );
|
||||
}
|
||||
#endif // wnd
|
||||
|
||||
int SubtractRect( RECT *out, RECT *in1, RECT *in2 ) {
|
||||
int ret;
|
||||
if ( in1->left >= in2->left && in1->right <= in2->right ) {
|
||||
out->left = in1->left; out->right = in1->right;
|
||||
|
||||
if ( in1->top >= in2->top && in2->bottom >= in2->top && in2->bottom <= in2->bottom ) {
|
||||
out->top = in1->bottom; out->bottom = in2->bottom;
|
||||
|
||||
ret = 1;
|
||||
} else if ( in1->top <= in2->top && in1->bottom >= in2->top && in1->bottom <= in2->bottom ) {
|
||||
out->top = in1->top; out->bottom = in2->top;
|
||||
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
} else if ( in1->top >= in2->top && in1->bottom <= in2->bottom ) {
|
||||
out->top = in1->top; out->bottom = in1->bottom;
|
||||
|
||||
if ( in1->left >= in2->left && in2->right >= in2->left && in2->right <= in2->right ) {
|
||||
out->left = in1->right; out->right = in2->right;
|
||||
|
||||
ret = 1;
|
||||
} else if ( in1->left <= in2->left && in1->right >= in2->left && in1->right <= in2->right ) {
|
||||
out->left = in1->left; out->right = in2->left;
|
||||
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EqualRect( RECT *a, RECT *b ) {
|
||||
return ( a->top == b->top && a->bottom == b->bottom &&
|
||||
a->left == b->left && a->right == b->right );
|
||||
}
|
||||
|
||||
#ifdef WASABI_COMPILE_WND
|
||||
|
||||
HWND WindowFromPoint( POINT p ) {
|
||||
int x, y;
|
||||
Window child;
|
||||
|
||||
XTranslateCoordinates( Linux::getDisplay(), Linux::RootWin(), Linux::RootWin(), p.x, p.y, &x, &y, &child );
|
||||
return child;
|
||||
}
|
||||
#endif // wnd
|
||||
|
||||
void CopyFile( const char *f1, const char *f2, BOOL b ) {
|
||||
COPYFILE( f1, f2 );
|
||||
}
|
||||
|
||||
DWORD GetModuleFileName(void *pid, const char *filename, int bufsize) {
|
||||
char procbuffer[512];
|
||||
sprintf(procbuffer, "/proc/%d/exe", (int)pid);
|
||||
return readlink(procbuffer, (char *)filename, bufsize);
|
||||
}
|
||||
|
||||
const char *CharPrev(const char *lpszStart, const char *lpszCurrent) {
|
||||
if (lpszCurrent-1 >= lpszStart) return lpszCurrent-1;
|
||||
return lpszStart;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue