123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961 |
- #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
|