mirror of
https://github.com/QB64Official/qb64.git
synced 2024-07-05 17:00:26 +00:00
Re-implements clipboard support for Linux
Fixes a threading issue which caused QB64 to intermittently crash when using hardware commands (Same threading fix yet to be applied to Linux) Fixes problem in last update which prevented _OPENHOST/_OPENCLIENT from working (they always returned invalid handle '0') Fixes 3D perspective issue when 3D rendering into images not the primary display (previuosly the dimensions of the screen/window not the target image were used to determine the aspect ratio)
This commit is contained in:
parent
dcacfd49e3
commit
67e08be312
|
@ -21,8 +21,52 @@
|
|||
#ifdef QB64_X11
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
Display *X11_display=NULL;
|
||||
Window X11_window;
|
||||
int32 x11_locked=0;
|
||||
int32 x11_lock_request=0;
|
||||
|
||||
void x11_lock(){
|
||||
x11_lock_request=1; while (x11_locked==0) Sleep(1);
|
||||
}
|
||||
void x11_unlock(){
|
||||
x11_locked=0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
Logging for QB64 developers (when an alert() just isn't enough)
|
||||
1) Temporarily set allow_logging=1
|
||||
2) Call log with a string or number:
|
||||
log_event("this is a char* string");
|
||||
log_event(12345);
|
||||
3) 'log.txt' is created in the same folder as your executable
|
||||
* 'log.txt' is truncated every time your program runs on the first call to log_event(...)
|
||||
*/
|
||||
int32 allow_logging=1;
|
||||
std::ofstream log_file;
|
||||
int32 log_file_opened=0;
|
||||
void open_log_file(){
|
||||
if (log_file_opened==0){
|
||||
log_file.open("log.txt", std::ios_base::out|std::ios_base::trunc);
|
||||
log_file_opened=1;
|
||||
}
|
||||
}
|
||||
void log_event(char *x){
|
||||
open_log_file();
|
||||
log_file << x;
|
||||
}
|
||||
void log_event(int32 x){
|
||||
open_log_file();
|
||||
char str[1000];
|
||||
memset(&str[0],0,1000);
|
||||
sprintf(str, "%d", x);
|
||||
log_file << &str[0];
|
||||
}
|
||||
|
||||
|
||||
#include "libqb/printer.h"
|
||||
|
||||
|
@ -122,7 +166,7 @@ extern "C" int qb64_custom_event(int event,int v1,int v2,int v3,int v4,int v5,in
|
|||
#ifdef QB64_LINUX
|
||||
#ifdef QB64_GUI //Cannot have X11 events without a GUI
|
||||
#ifndef QB64_MACOSX
|
||||
extern "C" void qb64_os_event_linux(XEvent *event, int *qb64_os_event_info);
|
||||
extern "C" void qb64_os_event_linux(XEvent *event, Display *display, int *qb64_os_event_info);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -244,6 +288,41 @@ int64 last_hardware_display_frame_order=0;
|
|||
|
||||
|
||||
|
||||
//Mutex support (Windows only atm)
|
||||
|
||||
struct MUTEX{
|
||||
#ifdef QB64_WINDOWS
|
||||
HANDLE handle;
|
||||
#else
|
||||
ptrszint todo;
|
||||
#endif
|
||||
};
|
||||
|
||||
MUTEX* new_mutex(){
|
||||
MUTEX *m=(MUTEX*)calloc(1,sizeof(MUTEX));
|
||||
#ifdef QB64_WINDOWS
|
||||
m->handle=CreateMutex(
|
||||
NULL, // default security attributes
|
||||
FALSE, // initially not owned
|
||||
NULL); // unnamed mutex
|
||||
#endif
|
||||
}
|
||||
|
||||
void free_mutex(MUTEX *mutex){
|
||||
//todo
|
||||
}
|
||||
|
||||
void lock_mutex(MUTEX *m){
|
||||
if (m==NULL) return;
|
||||
WaitForSingleObject(
|
||||
m->handle, // handle to mutex
|
||||
INFINITE); // no time-out interval
|
||||
}
|
||||
|
||||
void unlock_mutex(MUTEX *m){
|
||||
if (m==NULL) return;
|
||||
ReleaseMutex(m->handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -257,47 +336,62 @@ struct list{
|
|||
ptrszint structures;
|
||||
ptrszint structures_last;
|
||||
ptrszint *structure_freed;//quickly re-reference available structures after they have been removed
|
||||
ptrszint *structure_freed_cleanup;//the previous *structure_freed memory block
|
||||
ptrszint structures_freed;
|
||||
ptrszint structures_freed_last;
|
||||
ptrszint structure_base[64];//every time the 'structure' block is full a new and larger block is allocated
|
||||
//because the list doubles each time, 64 entries will never be exceeded
|
||||
ptrszint structure_bases;
|
||||
ptrszint *index;//pointers to the structures referred to by each index value
|
||||
ptrszint *index_cleanup;
|
||||
ptrszint indexes;
|
||||
ptrszint indexes_last;
|
||||
uint8 lock_freed_list;
|
||||
uint8 lock_index_list;
|
||||
MUTEX *lock_add;
|
||||
MUTEX *lock_remove;
|
||||
};
|
||||
|
||||
//fwd refs
|
||||
void *list_get(list *L, ptrszint i);
|
||||
|
||||
|
||||
|
||||
list *list_new(ptrszint structure_size){
|
||||
list *L;
|
||||
L=(list*)calloc(1,sizeof(list));
|
||||
L->structure=(uint8*)malloc(1);
|
||||
L->structure=(uint8*)malloc(sizeof(uint8*));
|
||||
L->structure_base[1]=(ptrszint)L->structure;
|
||||
L->structure_bases=1;
|
||||
L->structure_freed=(ptrszint*)malloc(1);
|
||||
L->structure_freed=(ptrszint*)malloc(sizeof(ptrszint*));
|
||||
L->index=(ptrszint*)malloc(sizeof(ptrszint*));
|
||||
L->user_structure_size=structure_size;
|
||||
L->internal_structure_size=structure_size+sizeof(ptrszint);
|
||||
return L;
|
||||
}
|
||||
|
||||
list *list_new_threadsafe(ptrszint structure_size){
|
||||
list *L=list_new(structure_size);
|
||||
L->lock_add=new_mutex();
|
||||
L->lock_remove=new_mutex();
|
||||
return L;
|
||||
}
|
||||
|
||||
ptrszint list_add(list *L){
|
||||
lock_mutex(L->lock_add);
|
||||
ptrszint i;
|
||||
if (L->structures_freed){//retrieve index from freed list if possible
|
||||
if (L->lock_freed_list){
|
||||
still_locked:
|
||||
Sleep(0);
|
||||
if (L->lock_freed_list) goto still_locked;
|
||||
}
|
||||
if(L->structures_freed){//retrieve index from freed list if possible
|
||||
lock_mutex(L->lock_remove);
|
||||
i=L->structure_freed[L->structures_freed--];
|
||||
uint8* structure;
|
||||
structure=(uint8*)L->index[i];
|
||||
memset(structure,0,L->user_structure_size);
|
||||
*(ptrszint*)(structure+L->user_structure_size)=i;
|
||||
unlock_mutex(L->lock_remove);
|
||||
}else{
|
||||
//create new buffer?
|
||||
if ((L->structures+1)>L->structures_last){
|
||||
ptrszint new_structures_last;
|
||||
new_structures_last=(L->structures_last*2)+1;
|
||||
//note: L->structure is only modified by list_add
|
||||
L->structure=(uint8*)calloc(1,L->internal_structure_size*(new_structures_last+1));
|
||||
if (L->structure==NULL){ alert("list_add: failed to allocate new buffer, structure size:"); alert(L->internal_structure_size);}
|
||||
L->structures_last=new_structures_last;
|
||||
|
@ -308,36 +402,49 @@ ptrszint list_add(list *L){
|
|||
*(ptrszint*)(L->structure+(L->internal_structure_size*(++L->structures))+L->user_structure_size)=i;
|
||||
//allocate new index
|
||||
if (L->indexes>L->indexes_last){
|
||||
L->lock_index_list=1;
|
||||
L->indexes_last=(L->indexes_last*2)+1; L->index=(ptrszint*)realloc(L->index,sizeof(ptrszint)*(L->indexes_last+1));
|
||||
L->lock_index_list=0;
|
||||
}
|
||||
if (L->index_cleanup!=NULL) free(L->index_cleanup);
|
||||
L->index_cleanup=L->index;
|
||||
int32 new_indexes_last=(L->indexes_last*2)+1;
|
||||
ptrszint* temp=(ptrszint*)malloc(sizeof(ptrszint)*(new_indexes_last+1));
|
||||
memcpy(temp,L->index,sizeof(ptrszint)*(L->indexes_last+1));
|
||||
L->index=temp;
|
||||
L->index[i]=(ptrszint)( L->structure + (L->internal_structure_size*L->structures) );
|
||||
L->indexes_last=new_indexes_last;
|
||||
}else{
|
||||
L->index[i]=(ptrszint)( L->structure + (L->internal_structure_size*L->structures) );
|
||||
}
|
||||
}
|
||||
unlock_mutex(L->lock_add);
|
||||
return i;
|
||||
}//list_add
|
||||
|
||||
ptrszint list_remove(list *L,ptrszint i){//returns -1 on success, 0 on failure
|
||||
if ((i<1)||(i>L->indexes)) return 0;
|
||||
uint8* structure;
|
||||
if (L->lock_index_list){
|
||||
still_locked:
|
||||
Sleep(0);
|
||||
if (L->lock_index_list) goto still_locked;
|
||||
lock_mutex(L->lock_remove);
|
||||
if ((i<1)||(i>L->indexes)){
|
||||
unlock_mutex(L->lock_remove);
|
||||
return 0;
|
||||
}
|
||||
uint8* structure;
|
||||
structure=(uint8*)(L->index[i]);
|
||||
if (!*(ptrszint*)(structure+L->user_structure_size)) return 0;
|
||||
*(ptrszint*)(structure+L->user_structure_size)=0;
|
||||
if (!*(ptrszint*)(structure+L->user_structure_size)){
|
||||
unlock_mutex(L->lock_remove);
|
||||
return 0;
|
||||
}
|
||||
//expand buffer?
|
||||
if ((L->structures_freed+1)>L->structures_freed_last){
|
||||
L->lock_freed_list=1;
|
||||
ptrszint new_structures_freed_last;
|
||||
new_structures_freed_last=(L->structures_freed_last*2)+1;
|
||||
L->structure_freed=(ptrszint*)realloc(L->structure_freed,sizeof(ptrszint)*(new_structures_freed_last+1));
|
||||
ptrszint *temp=(ptrszint*)malloc(sizeof(ptrszint)*(new_structures_freed_last+1));
|
||||
memcpy(temp, L->structure_freed, sizeof(ptrszint)*(L->structures_freed+1));
|
||||
if (L->structure_freed_cleanup!=NULL) free(L->structure_freed_cleanup);
|
||||
L->structure_freed_cleanup=L->structure_freed;
|
||||
L->structure_freed=temp;
|
||||
L->structures_freed_last=new_structures_freed_last;
|
||||
L->lock_freed_list=0;
|
||||
}
|
||||
L->structure_freed[++L->structures_freed]=i;
|
||||
L->structure_freed[L->structures_freed+1]=i;
|
||||
*(ptrszint*)(structure+L->user_structure_size)=0;
|
||||
L->structures_freed++;
|
||||
unlock_mutex(L->lock_remove);
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
@ -352,20 +459,18 @@ void list_destroy(list *L){
|
|||
}
|
||||
|
||||
void *list_get(list *L, ptrszint i){//Returns a pointer to an index's structure
|
||||
if ((i<1)||(i>L->indexes)) return NULL;
|
||||
uint8* structure;
|
||||
if (L->lock_index_list){
|
||||
still_locked:
|
||||
Sleep(0);
|
||||
if (L->lock_index_list) goto still_locked;
|
||||
if ((i<1)||(i>L->indexes)){
|
||||
return NULL;
|
||||
}
|
||||
uint8* structure;
|
||||
structure=(uint8*)(L->index[i]);
|
||||
if (!*(ptrszint*)(structure+L->user_structure_size)) return NULL;
|
||||
return (void*)structure;
|
||||
}
|
||||
|
||||
ptrszint list_get_index(list *L,void *structure){//Retrieves the index value of a structure
|
||||
return *(ptrszint*) ( ((uint8*)structure) + L->user_structure_size );
|
||||
ptrszint i=*(ptrszint*) ( ((uint8*)structure) + L->user_structure_size );
|
||||
return i;
|
||||
}
|
||||
|
||||
//Special Handle system
|
||||
|
@ -551,7 +656,7 @@ int32 HARDWARE_IMG_HANDLE_OFFSET=-16777216;//added to all hardware image handles
|
|||
|
||||
//note: only to be used by user functions, not internal functions
|
||||
hardware_img_struct *get_hardware_img(int32 handle){
|
||||
static hardware_img_struct *img;
|
||||
hardware_img_struct *img;
|
||||
if (handle<HARDWARE_IMG_HANDLE_OFFSET||handle>=SOFTWARE_IMG_HANDLE_MIN) return NULL;
|
||||
img=(hardware_img_struct*)list_get(hardware_img_handles,handle-HARDWARE_IMG_HANDLE_OFFSET);
|
||||
if (img==NULL) return NULL;
|
||||
|
@ -3576,6 +3681,8 @@ void alert(int32 x){
|
|||
MessageBox(0,&str[0], "Alert", MB_OK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void alert(char *x){
|
||||
MessageBox(0,x, "Alert", MB_OK );
|
||||
}
|
||||
|
@ -3584,8 +3691,6 @@ void alert(char *x){
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
//vc->project->properties->configuration properties->general->configuration type->application(.exe)
|
||||
//vc->project->properties->configuration properties->general->configuration type->static library(.lib)
|
||||
|
||||
|
@ -4763,7 +4868,6 @@ int32 imgload(char *filename,int32 bpp){
|
|||
|
||||
|
||||
void flush_old_hardware_commands(){
|
||||
|
||||
static int32 old_command;
|
||||
static int32 command_to_remove;
|
||||
static hardware_graphics_command_struct* last_rendered_hgc;
|
||||
|
@ -4821,6 +4925,7 @@ void flush_old_hardware_commands(){
|
|||
|
||||
cant_remove:;
|
||||
|
||||
|
||||
}//next_hardware_command_to_remove&&last_hardware_command_rendered
|
||||
}//flush_old_hardware_commands
|
||||
|
||||
|
@ -19806,7 +19911,7 @@ void sub_mkdir(qbs *str){
|
|||
|
||||
static hardware_img_struct *himg;
|
||||
if (himg=get_hardware_img(i)){
|
||||
|
||||
flush_old_hardware_commands();
|
||||
//add command to free image
|
||||
//create new command handle & structure
|
||||
int32 hgch=list_add(hardware_graphics_command_handles);
|
||||
|
@ -19838,7 +19943,7 @@ void sub_mkdir(qbs *str){
|
|||
if (img[i].flags&IMG_SCREEN){error(5); return;}//The SCREEN's pages cannot be freed!
|
||||
if (write_page_index==i) sub__dest(-display_page_index);
|
||||
if (read_page_index==i) sub__source(-display_page_index);
|
||||
if (img[i].flags&IMG_FREEMEM) free(img[i].offset);//free pixel data
|
||||
if (img[i].flags&IMG_FREEMEM) free(img[i].offset);//free pixel data (potential crash here)
|
||||
if (img[i].flags&IMG_FREEPAL) free(img[i].pal);//free palette
|
||||
freeimg(i);
|
||||
}
|
||||
|
@ -22555,7 +22660,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
static int32 init=0;
|
||||
if (!init){
|
||||
init=1;
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
sockVersion = MAKEWORD(1, 1);
|
||||
WSAStartup(sockVersion, &wsaData);
|
||||
#endif
|
||||
|
@ -22563,13 +22668,13 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
}
|
||||
|
||||
void tcp_done(){
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct tcp_connection{
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
SOCKET socket;
|
||||
#endif
|
||||
int32 port;//connection to host & clients only
|
||||
|
@ -22581,7 +22686,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
tcp_init();
|
||||
if ((port<0)||(port>65535)) return NULL;
|
||||
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
//Ref. from 'winsock.h': typedef u_int SOCKET;
|
||||
static SOCKET listeningSocket;
|
||||
listeningSocket = socket(AF_INET, // Go over TCP/IP
|
||||
|
@ -22628,7 +22733,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
|
||||
if ((port<0)||(port>65535)) return NULL;
|
||||
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
static LPHOSTENT hostEntry;
|
||||
hostEntry=gethostbyname((char*)host);
|
||||
if (!hostEntry) return NULL;
|
||||
|
@ -22672,7 +22777,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
|
||||
void *tcp_connection_open(void *host_tcp){
|
||||
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
static tcp_connection *host; host=(tcp_connection*)host_tcp;
|
||||
static sockaddr sa;
|
||||
static int sa_size;
|
||||
|
@ -22699,7 +22804,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
|
||||
void tcp_close(void* connection){
|
||||
static tcp_connection *tcp=(tcp_connection*)connection;
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
shutdown(tcp->socket,SD_BOTH);
|
||||
closesocket(tcp->socket);
|
||||
#endif
|
||||
|
@ -22709,7 +22814,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
|
||||
void tcp_out(void *connection,void *offset,ptrszint bytes){
|
||||
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
static tcp_connection *tcp; tcp=(tcp_connection*)connection;
|
||||
static int nret;
|
||||
nret = send(tcp->socket,
|
||||
|
@ -22750,7 +22855,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
|
||||
void stream_update(stream_struct *stream){
|
||||
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
//assume tcp
|
||||
|
||||
static connection_struct *connection;
|
||||
|
@ -23074,7 +23179,7 @@ int32 func__printwidth(qbs* text, int32 screenhandle, int32 passed){
|
|||
|
||||
int32 tcp_connected (void *connection){
|
||||
static tcp_connection *tcp=(tcp_connection*)connection;
|
||||
#if defined(QB64_WINDOWS) && defined(QB64_SOCKETS)
|
||||
#if defined(QB64_WINDOWS) && defined(DEPENDENCY_SOCKETS)
|
||||
char buf;
|
||||
int length=recv(tcp->socket, &buf, 0, 0);
|
||||
int nError=WSAGetLastError();
|
||||
|
@ -23412,6 +23517,156 @@ int32 func__exit(){
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef QB64_LINUX
|
||||
#ifndef QB64_MACOSX
|
||||
|
||||
//X11 clipboard interface for Linux
|
||||
//SDL_SysWMinfo syswminfo;
|
||||
Atom targets,utf8string,compoundtext,clipboard;
|
||||
|
||||
int x11filter(XEvent *x11event){
|
||||
static int i;
|
||||
static char *cp;
|
||||
static XSelectionRequestEvent *x11request;
|
||||
static XSelectionEvent x11selectionevent;
|
||||
static Atom mytargets[]={XA_STRING,utf8string,compoundtext};
|
||||
if (x11event->type==SelectionRequest){
|
||||
x11request=&x11event->xselectionrequest;
|
||||
x11selectionevent.type=SelectionNotify;
|
||||
x11selectionevent.serial=x11event->xany.send_event;
|
||||
x11selectionevent.send_event=True;
|
||||
x11selectionevent.display=X11_display;
|
||||
x11selectionevent.requestor=x11request->requestor;
|
||||
x11selectionevent.selection=x11request->selection;
|
||||
x11selectionevent.target=None;
|
||||
x11selectionevent.property=x11request->property;
|
||||
x11selectionevent.time=x11request->time;
|
||||
if (x11request->target==targets){
|
||||
XChangeProperty(X11_display,x11request->requestor,x11request->property,XA_ATOM,32,PropModeReplace,(unsigned char*)mytargets,3);
|
||||
}else{
|
||||
if (x11request->target==compoundtext||x11request->target==utf8string||x11request->target==XA_STRING){
|
||||
cp=XFetchBytes(X11_display,&i);
|
||||
XChangeProperty(X11_display,x11request->requestor,x11request->property,x11request->target,8,PropModeReplace,(unsigned char*)cp,i);
|
||||
XFree(cp);
|
||||
}else{
|
||||
x11selectionevent.property=None;
|
||||
}
|
||||
}
|
||||
XSendEvent(x11request->display,x11request->requestor,0,NoEventMask,(XEvent*)&x11selectionevent);
|
||||
XSync(X11_display,False);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void setupx11clipboard(){
|
||||
static int32 setup=0;
|
||||
if (!setup){
|
||||
setup=1;
|
||||
//SDL_GetWMInfo(&syswminfo);
|
||||
//SDL_EventState(SDL_SYSWMEVENT,SDL_ENABLE);
|
||||
//SDL_SetEventFilter(x11filter);
|
||||
x11_lock();
|
||||
targets=XInternAtom(X11_display,"TARGETS",True);
|
||||
utf8string=XInternAtom(X11_display,"UTF8_STRING",True);
|
||||
compoundtext=XInternAtom(X11_display,"COMPOUND_TEXT",True);
|
||||
clipboard=XInternAtom(X11_display,"CLIPBOARD",True);
|
||||
x11_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void x11clipboardcopy(const char *text){
|
||||
setupx11clipboard();
|
||||
x11_lock();
|
||||
XStoreBytes(X11_display,text,strlen(text)+1);
|
||||
XSetSelectionOwner(X11_display,clipboard,X11_window,CurrentTime);
|
||||
x11_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
char *x11clipboardpaste(){
|
||||
static int32 i;
|
||||
static char *cp;
|
||||
static unsigned char *cp2;
|
||||
static Window x11selectionowner;
|
||||
static XEvent x11event;
|
||||
static unsigned long data_items,bytes_remaining,ignore;
|
||||
static int format;
|
||||
static Atom type;
|
||||
cp=NULL; cp2=NULL;
|
||||
setupx11clipboard();
|
||||
//syswminfo.info.x11.lock_func();
|
||||
x11_lock();
|
||||
x11selectionowner=XGetSelectionOwner(X11_display,clipboard);
|
||||
if (x11selectionowner!=None){
|
||||
//The XGetSelectionOwner() function returns the window ID associated with the window
|
||||
if (x11selectionowner==X11_window){//we are the provider, so just return buffered content
|
||||
x11_unlock();
|
||||
int bytes;
|
||||
cp=XFetchBytes(X11_display,&bytes);
|
||||
return cp;
|
||||
}
|
||||
XConvertSelection(X11_display,clipboard,utf8string,clipboard,X11_window,CurrentTime);
|
||||
XFlush(X11_display);
|
||||
bool gotReply = false;
|
||||
int timeoutMs = 10000;//10sec
|
||||
do {
|
||||
XEvent event;
|
||||
gotReply = XCheckTypedWindowEvent(X11_display, X11_window, SelectionNotify, &event);
|
||||
if (gotReply) {
|
||||
if (event.xselection.property == clipboard) {
|
||||
XGetWindowProperty(X11_display,X11_window,clipboard,0,0,False,AnyPropertyType,&type,&format,&data_items,&bytes_remaining,&cp2);
|
||||
if (cp2){XFree(cp2); cp2=NULL;}
|
||||
if (bytes_remaining){
|
||||
if (XGetWindowProperty(X11_display,X11_window,clipboard,0,bytes_remaining,False,AnyPropertyType,&type,&format,&data_items, &ignore,&cp2)==Success){
|
||||
cp=strdup((char*)cp2);
|
||||
XFree(cp2);
|
||||
XDeleteProperty(X11_display,X11_window,clipboard);
|
||||
x11_unlock();
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
x11_unlock();
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
x11_unlock();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
Sleep(1);
|
||||
timeoutMs -= 1;
|
||||
} while (timeoutMs > 0);
|
||||
}//x11selectionowner!=None
|
||||
x11_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
qbs *internal_clipboard=NULL;//used only if clipboard services unavailable
|
||||
int32 linux_clipboard_init=0;
|
||||
|
||||
|
@ -23459,6 +23714,11 @@ int32 func__exit(){
|
|||
|
||||
#ifdef QB64_LINUX
|
||||
#ifndef QB64_MACOSX
|
||||
static qbs *textz=NULL; if (!textz) textz=qbs_new(0,0);
|
||||
qbs_set(textz,qbs_add(text,qbs_new_txt_len("\0",1)));
|
||||
x11clipboardcopy((char*)textz->chr);
|
||||
return;
|
||||
|
||||
//Need to find a way to get the clipboard working on Linux! (Hack freeGLUT, switch to GLFW, small 'helper' program?)
|
||||
/* while (!display_surface) Sleep(1);
|
||||
lock_mainloop=1; while (lock_mainloop!=2) Sleep(1);//lock
|
||||
|
@ -23635,6 +23895,109 @@ int32 func__exit(){
|
|||
|
||||
#ifdef QB64_LINUX
|
||||
#ifndef QB64_MACOSX
|
||||
|
||||
qbs *text;
|
||||
char *cp=x11clipboardpaste();
|
||||
cp=x11clipboardpaste();
|
||||
if (!cp){
|
||||
text=qbs_new(0,1);
|
||||
}else{
|
||||
text=qbs_new(strlen(cp),1);
|
||||
memcpy(text->chr,cp,text->len);
|
||||
free(cp);
|
||||
}
|
||||
return text;
|
||||
|
||||
|
||||
//char *XFetchBytes(display, nbytes_return)
|
||||
//Display *display;
|
||||
|
||||
|
||||
/*
|
||||
Atom a1, a2, type;
|
||||
int format, result;
|
||||
unsigned long len, bytes_left, dummy;
|
||||
unsigned char *data;
|
||||
Window Sown;
|
||||
Display *dpy=X11_display;
|
||||
|
||||
x11_lock_request=1; while (x11_locked==0) Sleep(1);
|
||||
|
||||
Sown = XGetSelectionOwner (dpy, XA_PRIMARY);
|
||||
//printf ("Selection owner%i\n", (int)Sown);
|
||||
if (Sown != None) {
|
||||
|
||||
XConvertSelection (dpy, XA_PRIMARY, XA_STRING, None,
|
||||
Sown, CurrentTime);
|
||||
XFlush (dpy);
|
||||
|
||||
//
|
||||
// Do not get any data, see how much data is there
|
||||
//
|
||||
|
||||
XGetWindowProperty (dpy, Sown,
|
||||
XA_STRING, // Tricky..
|
||||
0, 0, // offset - len
|
||||
0, // Delete 0==FALSE
|
||||
AnyPropertyType, //flag
|
||||
&type, // return type
|
||||
&format, // return format
|
||||
&len, &bytes_left, //that
|
||||
&data);
|
||||
//printf ("type:%i len:%i format:%i byte_left:%i\n",
|
||||
//(int)type, len, format, bytes_left);
|
||||
// DATA is There
|
||||
|
||||
|
||||
|
||||
if (bytes_left > 0)
|
||||
{
|
||||
result = XGetWindowProperty (dpy, Sown,
|
||||
XA_STRING, 0,bytes_left,0,
|
||||
AnyPropertyType, &type,&format,
|
||||
&len, &dummy, &data);
|
||||
if (result == Success){
|
||||
//printf ("DATA IS HERE!!```%s'''\n",
|
||||
//data);
|
||||
//XFree (data);
|
||||
x11_locked=0;
|
||||
return qbs_new_txt((const char*)data);
|
||||
}
|
||||
else
|
||||
{ //printf ("FAIL\n");
|
||||
//XFree (data);
|
||||
}
|
||||
}//bytes_left
|
||||
}//Sown != None
|
||||
|
||||
x11_locked=0;
|
||||
return qbs_new(0,1);
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
int bytes;
|
||||
char *data=XFetchBytes(X11_display, &bytes);
|
||||
if (bytes==0) return qbs_new(0,1);
|
||||
return qbs_new_txt_len(data, bytes);
|
||||
*/
|
||||
|
||||
//Linux clipboard not functional, see comment in sub__clipboard
|
||||
/* static char *cp;
|
||||
static qbs *text;
|
||||
|
@ -28485,6 +28848,13 @@ void sub__maptriangle(int32 cull_options,float sx1,float sy1,float sx2,float sy2
|
|||
#else
|
||||
void GLUT_IDLEFUNC(){
|
||||
#ifdef QB64_GLUT
|
||||
|
||||
if (x11_lock_request){
|
||||
x11_locked=1;
|
||||
x11_lock_request=0;
|
||||
while (x11_locked) Sleep(1);
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
int32 msdelay=1000.0/max_fps;
|
||||
if (msdelay<1) msdelay=1;
|
||||
|
@ -28557,6 +28927,12 @@ void sub__maptriangle(int32 cull_options,float sx1,float sy1,float sx2,float sy2
|
|||
|
||||
int main( int argc, char* argv[] ){
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef QB64_LINUX
|
||||
#ifndef QB64_MACOSX
|
||||
XInitThreads();
|
||||
|
@ -28614,9 +28990,11 @@ render_state.cull_mode=CULL_MODE__UNKNOWN;
|
|||
stream_handles=list_new(sizeof(stream_struct));
|
||||
connection_handles=list_new(sizeof(connection_struct));
|
||||
|
||||
hardware_img_handles=list_new(sizeof(hardware_img_struct));
|
||||
hardware_img_handles=list_new_threadsafe(sizeof(hardware_img_struct));
|
||||
hardware_graphics_command_handles=list_new(sizeof(hardware_graphics_command_struct));
|
||||
|
||||
|
||||
|
||||
if (!cloud_app){
|
||||
snd_init();
|
||||
}
|
||||
|
@ -29261,7 +29639,10 @@ QB64_GAMEPAD_INIT();
|
|||
#endif
|
||||
|
||||
#ifdef QB64_WINDOWS
|
||||
_beginthread(QBMAIN_WINDOWS,0,NULL);
|
||||
{
|
||||
uintptr_t thread_handle = _beginthread(QBMAIN_WINDOWS,0,NULL);
|
||||
SetThreadPriority((HANDLE)thread_handle, THREAD_PRIORITY_NORMAL);
|
||||
}
|
||||
#else
|
||||
{
|
||||
static pthread_t thread_handle;
|
||||
|
@ -29270,7 +29651,10 @@ QB64_GAMEPAD_INIT();
|
|||
#endif
|
||||
|
||||
#ifdef QB64_WINDOWS
|
||||
_beginthread(TIMERTHREAD_WINDOWS,0,NULL);
|
||||
{
|
||||
uintptr_t thread_handle = _beginthread(TIMERTHREAD_WINDOWS,0,NULL);
|
||||
SetThreadPriority((HANDLE)thread_handle, THREAD_PRIORITY_NORMAL);
|
||||
}
|
||||
#else
|
||||
{
|
||||
static pthread_t thread_handle;
|
||||
|
@ -29283,7 +29667,7 @@ QB64_GAMEPAD_INIT();
|
|||
|
||||
|
||||
|
||||
//_beginthread(GLUT_MAINLOOP_THREAD,0,NULL);
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -29322,7 +29706,10 @@ QB64_GAMEPAD_INIT();
|
|||
#endif
|
||||
|
||||
#ifdef QB64_WINDOWS
|
||||
_beginthread(MAIN_LOOP_WINDOWS,0,NULL);
|
||||
{
|
||||
uintptr_t thread_handle = _beginthread(MAIN_LOOP_WINDOWS,0,NULL);
|
||||
SetThreadPriority((HANDLE)thread_handle, THREAD_PRIORITY_NORMAL);
|
||||
}
|
||||
#else
|
||||
{
|
||||
static pthread_t thread_handle;
|
||||
|
@ -31044,6 +31431,11 @@ QB64_GAMEPAD_POLL();
|
|||
check_last=0;
|
||||
}
|
||||
|
||||
if (displayorder_screen==0 && check_last==1){
|
||||
//a valid frame of the correct dimensions exists and we are not required to display software content
|
||||
goto no_new_frame;
|
||||
}
|
||||
|
||||
//Check/Prepare palette-buffer
|
||||
if (!check_last){
|
||||
//set pal_last (no prev pal was avilable to compare to)
|
||||
|
@ -31412,12 +31804,19 @@ QB64_GAMEPAD_POLL();
|
|||
if (!screen_last_valid) goto update_display32b; //force update because of mode change?
|
||||
i=display_page->width*display_page->height*4;
|
||||
if (i!=(display_frame[i2].w*display_frame[i2].h*4)) goto update_display32b;
|
||||
|
||||
if (displayorder_screen==0){
|
||||
//a valid frame of the correct dimensions exists and we are not required to display software content
|
||||
goto no_new_frame;
|
||||
}
|
||||
|
||||
if (memcmp(display_frame[i2].bgra,display_page->offset,i)) goto update_display32b;
|
||||
if (qb64_ime_reading==1) goto screen_refreshed;
|
||||
goto no_new_frame;//no need to update display
|
||||
}
|
||||
update_display32b:;
|
||||
}else{
|
||||
|
||||
//BGRA_to_RGBA
|
||||
i=display_page->width*display_page->height*4;
|
||||
if (i!=pixeldatasize){
|
||||
|
@ -31427,6 +31826,12 @@ QB64_GAMEPAD_POLL();
|
|||
goto update_display32;
|
||||
}
|
||||
if (force_display_update) goto update_display32; //force update
|
||||
|
||||
if (displayorder_screen==0){
|
||||
//a valid frame of the correct dimensions exists and we are not required to display software content
|
||||
goto no_new_frame;
|
||||
}
|
||||
|
||||
if (memcmp(pixeldata,display_page->offset,i)) goto update_display32;
|
||||
if (!screen_last_valid) goto update_display32; //force update because of mode change?
|
||||
if (qb64_ime_reading==1) goto screen_refreshed;
|
||||
|
@ -31505,6 +31910,11 @@ QB64_GAMEPAD_POLL();
|
|||
|
||||
if (force_display_update) goto update_display; //force update
|
||||
|
||||
if (displayorder_screen==0){
|
||||
//a valid frame of the correct dimensions exists and we are not required to display software content
|
||||
goto no_new_frame;
|
||||
}
|
||||
|
||||
if (memcmp(pixeldata,display_page->offset,i)) goto update_display;
|
||||
//palette changed?
|
||||
if (memcmp(paldata,display_page->pal,i2*4)) goto update_display;
|
||||
|
@ -32623,9 +33033,142 @@ QB64_GAMEPAD_POLL();
|
|||
#ifdef QB64_LINUX
|
||||
#ifdef QB64_GUI //Cannot have X11 events without a GUI
|
||||
#ifndef QB64_MACOSX
|
||||
extern "C" void qb64_os_event_linux(XEvent *event, int *qb64_os_event_info){
|
||||
|
||||
|
||||
|
||||
extern "C" void qb64_os_event_linux(XEvent *event, Display *display, int *qb64_os_event_info){
|
||||
if (*qb64_os_event_info==OS_EVENT_PRE_PROCESSING){
|
||||
|
||||
if (X11_display==NULL){
|
||||
X11_display=display;
|
||||
X11_window=event->xexpose.window;
|
||||
}
|
||||
|
||||
x11filter(event);//handles clipboard request events from other applications
|
||||
|
||||
/*
|
||||
Atom a1, a2, type;
|
||||
int format, result;
|
||||
unsigned long len, bytes_left, dummy;
|
||||
unsigned char *data;
|
||||
Window Sown;
|
||||
Display *dpy=X11_display;
|
||||
|
||||
Sown = XGetSelectionOwner (dpy, XA_PRIMARY);
|
||||
//printf ("Selection owner%i\n", (int)Sown);
|
||||
if (Sown != None) {
|
||||
|
||||
|
||||
XConvertSelection (dpy, XA_PRIMARY, XA_STRING, None,
|
||||
Sown, CurrentTime);
|
||||
*/
|
||||
|
||||
|
||||
////XFlush (dpy);
|
||||
|
||||
//
|
||||
// Do not get any data, see how much data is there
|
||||
//
|
||||
|
||||
/*
|
||||
XGetWindowProperty (dpy, Sown,
|
||||
XA_STRING, // Tricky..
|
||||
0, 0, // offset - len
|
||||
0, // Delete 0==FALSE
|
||||
AnyPropertyType, //flag
|
||||
&type, // return type
|
||||
&format, // return format
|
||||
&len, &bytes_left, //that
|
||||
&data);
|
||||
//printf ("type:%i len:%i format:%i byte_left:%i\n",
|
||||
//(int)type, len, format, bytes_left);
|
||||
// DATA is There
|
||||
|
||||
|
||||
|
||||
if (bytes_left > 0)
|
||||
{
|
||||
result = XGetWindowProperty (dpy, Sown,
|
||||
XA_STRING, 0,bytes_left,0,
|
||||
AnyPropertyType, &type,&format,
|
||||
&len, &dummy, &data);
|
||||
if (result == Success){
|
||||
//printf ("DATA IS HERE!!```%s'''\n",
|
||||
//data);
|
||||
|
||||
XFree (data);
|
||||
//return qbs_new_txt((const char*)data);
|
||||
}else{
|
||||
XFree (data);
|
||||
}
|
||||
}
|
||||
//return qbs_new(0,1);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//if (event->type==KeyPress){
|
||||
//}
|
||||
|
||||
/*
|
||||
|
||||
XGenericEventCookie *cookie = &event->xcookie;
|
||||
XIRawEvent *re;
|
||||
|
||||
Window dpy=event->xexpose.window;
|
||||
|
||||
//out
|
||||
Window root_ret, child_ret;
|
||||
int root_x, root_y;
|
||||
int win_x, win_y;
|
||||
unsigned int mask;
|
||||
|
||||
if (cookie->type != GenericEvent ||
|
||||
cookie->extension != xi_opcode ||
|
||||
!XGetEventData(dpy, cookie))
|
||||
{
|
||||
}
|
||||
else{
|
||||
switch (cookie->evtype) {
|
||||
case XI_RawMotion:
|
||||
re = (XIRawEvent *) cookie->data;
|
||||
XQueryPointer(dpy, DefaultRootWindow(dpy),
|
||||
&root_ret, &child_ret, &root_x, &root_y, &win_x, &win_y, &mask);
|
||||
//cout<<re->raw_values[0];
|
||||
//printf ("raw %g,%g root %d,%d\n",
|
||||
// re->raw_values[0], re->raw_values[1],
|
||||
// root_x, root_y);
|
||||
break;
|
||||
}
|
||||
XFreeEventData(dpy, cookie);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -97,14 +97,14 @@
|
|||
|
||||
|
||||
|
||||
void free_hardware_img(int32 handle){
|
||||
void free_hardware_img(int32 handle, int32 caller_id){
|
||||
|
||||
//alert("free_hardware_img: entered");
|
||||
|
||||
static hardware_img_struct* hardware_img;
|
||||
hardware_img_struct* hardware_img;
|
||||
hardware_img=(hardware_img_struct*)list_get(hardware_img_handles,handle);
|
||||
|
||||
if (hardware_img==NULL) alert("free_hardware_img: image does not exist");
|
||||
if (hardware_img==NULL){
|
||||
alert("free_hardware_img: image does not exist");
|
||||
}
|
||||
|
||||
if (hardware_img->dest_context_handle){
|
||||
GLuint context=(GLuint)hardware_img->dest_context_handle;
|
||||
|
@ -117,10 +117,18 @@
|
|||
GLuint texture=(GLuint)hardware_img->texture_handle;
|
||||
glDeleteTextures(1, &texture);
|
||||
|
||||
//test reasset of hardware+img
|
||||
//hardware_img=(hardware_img_struct*)list_get(hardware_img_handles,handle);
|
||||
//if (hardware_img==NULL) alert("free_hardware_img: image does not exist");
|
||||
|
||||
//if image has not been used, it may still have buffered pixel content
|
||||
if (hardware_img->software_pixel_buffer!=NULL) free(hardware_img->software_pixel_buffer);
|
||||
|
||||
if (hardware_img->software_pixel_buffer!=NULL){
|
||||
free(hardware_img->software_pixel_buffer);
|
||||
}
|
||||
|
||||
list_remove(hardware_img_handles,handle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -363,7 +371,7 @@ if (new_mode_shrunk==SMOOTH_MODE__DONT_SMOOTH){
|
|||
if (render_state.source->PO2_fix==PO2_FIX__MIPMAPPED){
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}else{
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//Use _MAPTRIANGLE's _SMOOTHSHRUNK to apply linear filtering here
|
||||
}
|
||||
}
|
||||
if (new_mode_shrunk==SMOOTH_MODE__SMOOTH){
|
||||
|
@ -580,17 +588,16 @@ if (new_mode==VIEW_MODE__3D){
|
|||
glScalef (1.0, -1.0, 1.0);
|
||||
//note: the max FOV is 90-degrees (this maximum applies to the longest screen dimension)
|
||||
float fov;
|
||||
if (environment_2d__screen_scaled_width>environment_2d__screen_scaled_height){
|
||||
fov=90.0f*((float)environment__window_width/(float)environment_2d__screen_scaled_width);
|
||||
if (dst_w>dst_h){
|
||||
fov=90.0f;
|
||||
//convert fov from horizontal to vertical
|
||||
fov=fov*((float)dst_h/(float)dst_w);
|
||||
}else{
|
||||
fov=90.0f*((float)environment__window_height/(float)environment_2d__screen_scaled_height);
|
||||
fov=90.0f;
|
||||
}
|
||||
gluPerspective(fov, (GLfloat)dst_w / (GLfloat)dst_h, 0.1, 10000.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
//alert("3D rendering onto FBO not supported yet");
|
||||
}
|
||||
}
|
||||
|
@ -1619,7 +1626,7 @@ if (src_hardware_img->source_state.PO2_fix){
|
|||
if (level==displayorder_screen){
|
||||
|
||||
if (software_screen_hardware_frame!=0&&i!=last_i){
|
||||
free_hardware_img(software_screen_hardware_frame);
|
||||
free_hardware_img(software_screen_hardware_frame, 847001);
|
||||
}
|
||||
if (i!=last_i||software_screen_hardware_frame==0){
|
||||
software_screen_hardware_frame=new_hardware_img(display_frame[i].w, display_frame[i].h,display_frame[i].bgra,NULL);
|
||||
|
@ -1651,20 +1658,29 @@ if (src_hardware_img->source_state.PO2_fix){
|
|||
static int32 command;
|
||||
command=0;
|
||||
|
||||
static int32 caller_flag;
|
||||
caller_flag=0;
|
||||
|
||||
if (first_hardware_layer_rendered==0){
|
||||
|
||||
if (first_hardware_command){
|
||||
|
||||
if (last_hardware_command_rendered){
|
||||
|
||||
if (rerender_prev_hardware_frame){
|
||||
command=last_hardware_command_rendered;
|
||||
caller_flag=100;
|
||||
}else{
|
||||
hardware_graphics_command_struct* last_hgc=(hardware_graphics_command_struct*)list_get(hardware_graphics_command_handles,last_hardware_command_rendered);
|
||||
if (last_hgc==NULL) alert("Rendering: Last HGC is NULL!");
|
||||
command=last_hgc->next_command;
|
||||
caller_flag=200;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
command=first_hardware_command;
|
||||
caller_flag=300;
|
||||
}
|
||||
|
||||
//process/skip pending hardware puts before this frame's order value
|
||||
|
@ -1673,7 +1689,7 @@ if (src_hardware_img->source_state.PO2_fix){
|
|||
if (hgc->order<order){
|
||||
|
||||
if (hgc->command==HARDWARE_GRAPHICS_COMMAND__FREEIMAGE){
|
||||
free_hardware_img(hgc->src_img);
|
||||
free_hardware_img(hgc->src_img, 847002+caller_flag);
|
||||
}
|
||||
|
||||
if (hgc->command==HARDWARE_GRAPHICS_COMMAND__PUTIMAGE){
|
||||
|
@ -1742,7 +1758,7 @@ if (src_hardware_img->source_state.PO2_fix){
|
|||
if (first_command_prev_order==0) first_command_prev_order=command;
|
||||
|
||||
if (hgc->command==HARDWARE_GRAPHICS_COMMAND__FREEIMAGE&&rerender_prev_hardware_frame==0&&first_hardware_layer_rendered==0){
|
||||
free_hardware_img(hgc->src_img);
|
||||
free_hardware_img(hgc->src_img, 847003);
|
||||
}
|
||||
|
||||
if (hgc->command==HARDWARE_GRAPHICS_COMMAND__PUTIMAGE){
|
||||
|
|
|
@ -248,7 +248,7 @@ void hardware_img_buffer_to_texture(int32 handle){
|
|||
}
|
||||
}
|
||||
free(hardware_img->software_pixel_buffer);
|
||||
hardware_img->software_pixel_buffer=NULL;
|
||||
hardware_img->software_pixel_buffer=NULL;//2015 critical bug fix
|
||||
set_render_source(INVALID_HARDWARE_HANDLE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
int qb64_custom_event(int event,int v1,int v2,int v3,int v4,int v5,int v6,int v7,int v8,void *p1,void *p2);
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
void qb64_os_event_linux(XEvent *event, int *qb64_os_event_info);
|
||||
void qb64_os_event_linux(XEvent *event, Display *display, int *qb64_os_event_info);
|
||||
#else
|
||||
LRESULT qb64_os_event_windows(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, int *qb64_os_event_info);
|
||||
#endif
|
||||
|
@ -1309,7 +1309,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
int qb64_os_event_info=0;
|
||||
|
||||
qb64_os_event_info=1;
|
||||
qb64_os_event_linux(&event, &qb64_os_event_info);
|
||||
qb64_os_event_linux(&event, fgDisplay.Display, &qb64_os_event_info);
|
||||
if (qb64_os_event_info==3) return;
|
||||
|
||||
switch( event.type )
|
||||
|
@ -1765,7 +1765,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
}
|
||||
|
||||
qb64_os_event_info=2;
|
||||
qb64_os_event_linux(&event, &qb64_os_event_info);
|
||||
qb64_os_event_linux(&event, fgDisplay.Display, &qb64_os_event_info);
|
||||
if (qb64_os_event_info==3) return;//(although we would return anyway)
|
||||
|
||||
}
|
||||
|
|
|
@ -1690,42 +1690,40 @@ return NULL;
|
|||
}
|
||||
#endif
|
||||
void TIMERTHREAD(){
|
||||
static int32 i,z=0;
|
||||
static int32 i;
|
||||
static double time_now=100000;
|
||||
while(1){
|
||||
quick_lock:
|
||||
if (ontimerthread_lock==1) ontimerthread_lock=2;//mutex, verify lock
|
||||
if (!ontimerthread_lock){//mutex
|
||||
time_now=((double)GetTicks())*0.001;
|
||||
for (i=0;i<ontimer_nextfree;i++){
|
||||
if (ontimer[i].allocated){
|
||||
if (ontimer[i].id){
|
||||
if (ontimer[i].active){
|
||||
if (!ontimer[i].state){
|
||||
if (time_now-ontimer[i].last_time>ontimer[i].seconds){
|
||||
if (!ontimer[i].last_time){
|
||||
time_now=((double)GetTicks())*0.001;
|
||||
for (i=0;i<ontimer_nextfree;i++){
|
||||
if (ontimer[i].allocated){
|
||||
if (ontimer[i].id){
|
||||
if (ontimer[i].active){
|
||||
if (!ontimer[i].state){
|
||||
if (time_now-ontimer[i].last_time>ontimer[i].seconds){
|
||||
if (!ontimer[i].last_time){
|
||||
ontimer[i].last_time=time_now;
|
||||
}else{
|
||||
}else{
|
||||
//keep measured time for accurate number of calls overall
|
||||
ontimer[i].last_time+=ontimer[i].seconds;
|
||||
//if difference between actual time and measured time is beyond 'seconds' set measured to actual
|
||||
if (fabs(time_now-ontimer[i].last_time)>=ontimer[i].seconds) ontimer[i].last_time=time_now;
|
||||
ontimer[i].state=1;
|
||||
qbevent=1;
|
||||
}
|
||||
}//time check
|
||||
}//state==0
|
||||
}//active
|
||||
}//id
|
||||
}//allocated
|
||||
if (ontimerthread_lock==1) goto quick_lock;
|
||||
}//i
|
||||
z++; if (z==4){Sleep(1); z=0;} else Sleep(0);
|
||||
}else{//mutex
|
||||
Sleep(0);
|
||||
}
|
||||
}
|
||||
}//time check
|
||||
}//state==0
|
||||
}//active
|
||||
}//id
|
||||
}//allocated
|
||||
if (ontimerthread_lock==1) goto quick_lock;
|
||||
}//i
|
||||
}//not locked
|
||||
Sleep(1);
|
||||
if (stop_program){exit_ok|=2; return;}//close thread #2
|
||||
}
|
||||
}//while(1)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue