3 Simple GUI abstraction- Unix implementation
5 Part of the swftools package.
7 Copyright (c) 2005 Matthias Kramm <kramm@quiss.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
31 #include <X11/Xutil.h>
32 #include <X11/Xresource.h>
34 #include <X11/Xthreads.h>
35 #include <X11/Xatom.h>
36 #include <X11/extensions/XShm.h>
37 #include "gfxwindow.h"
41 #define USE_PIXMAP 1 // use pixmap instead of ximage for off-screen rendering
43 #define initMutex(mutex) {pthread_mutex_init(mutex, 0);}
44 #define destroyMutex(mutex) {pthread_mutex_destroy((mutex));}
45 #define lockMutex(mutex) pthread_mutex_lock(mutex)
46 #define unlockMutex(mutex) pthread_mutex_unlock(mutex)
56 pthread_mutex_t mutex
;
60 queue_t
* queue_init(int size
, int nmemb
)
62 queue_t
* queue
= malloc(sizeof(queue_t
));
63 queue
->data
= (char*)malloc(size
* nmemb
);
69 initMutex(&queue
->mutex
);
73 void queue_destroy(queue_t
*queue
)
75 free(queue
->data
);queue
->data
= 0;
76 destroyMutex(&queue
->mutex
);
77 memset(queue
, 0, sizeof(queue_t
));
80 int queue_put(queue_t
*queue
, void*data
)
82 int tmp
= queue
->writepos
+1;
85 lockMutex(&queue
->mutex
);
86 if(tmp
==queue
->readpos
) {
87 unlockMutex(&queue
->mutex
);
90 memcpy(&queue
->data
[queue
->writepos
*queue
->size
], data
, queue
->size
);
91 queue
->writepos
= tmp
;
93 unlockMutex(&queue
->mutex
);
97 int queue_get(queue_t
*queue
, void*data
)
99 lockMutex(&queue
->mutex
);
100 if(queue
->writepos
== queue
->readpos
) {
101 unlockMutex(&queue
->mutex
);
104 memcpy(data
, &queue
->data
[queue
->readpos
*queue
->size
], queue
->size
);
106 queue
->readpos
%= queue
->nmemb
;
108 unlockMutex(&queue
->mutex
);
112 void queue_flush(queue_t
*queue
)
114 lockMutex(&queue
->mutex
);
118 unlockMutex(&queue
->mutex
);
121 int queue_num(queue_t
*queue
)
123 return queue
->number
;
126 static int initializexwindows();
148 pthread_t eventhandler
;
149 pthread_mutex_t xmutex
;
151 struct _QXWindow
*windowring
;
160 static int initialized
= 0;
165 pthread_cancel(X
.eventhandler
);
168 pthread_mutex_destroy(&X
.xmutex
);
171 typedef struct _QXWindow
{
172 struct _QXWindow
*next
;
173 struct _QXWindow
*prev
;
181 XSetWindowAttributes xswa
;
182 XWindowAttributes xwa
;
185 Pixmap offscreen_pixmap
;
187 XImage
* offscreen_ximage
;
200 pthread_mutex_t wmutex
;
205 static int lastbit(U32 bits
)
216 static int firstbit(U32 bits
)
227 static U32
shiftl(U32 bits
,int shift
)
229 if(shift
>0) return bits
<<shift
;
230 else return bits
>>-shift
;
233 static U32
getColorFromRGB(U8 r
,U8 g
,U8 b
)
236 ret
|=shiftl(r
,(firstbit(X
.v
->red_mask
)-7))&X
.v
->red_mask
;
237 ret
|=shiftl(g
,(firstbit(X
.v
->green_mask
)-7))&X
.v
->green_mask
;
238 ret
|=shiftl(b
,(firstbit(X
.v
->blue_mask
)-7))&X
.v
->blue_mask
;
242 static void whatever()
249 static void*eventloop(void*);
251 static int initializexwindows()
258 pthread_mutex_init(&X
.xmutex
, 0);
261 /* open display, and show some information */
262 X
.d
=XOpenDisplay(0);//getenv("DISPLAY"));
264 /* printf("Xprotocol V%d.%d Vendor:%s Name:%s Defaults:%s",X.d->proto_major_version,
265 X.d->proto_minor_version,
266 X.d->vendor,X.d->display_name,X.d->defaults);
268 printf("Formats:\n");
269 for(t=0;t<X.d->nformats;t++) {
270 ScreenFormat*sf=&X.d->pixmap_formats[t];
271 printf("%d:depth:%d, bpp:%d, scanline:%d\n",sf->depth,sf->bits_per_pixel,sf->scanline_pad);
273 printf("Screens:\n");
274 for(t=0;t<X.d->nscreens;t++) {
275 Screen*s=&X.d->screens[t];
276 printf("%d*%d, bpp:%d\n",s->width,s->height,s->root_depth);
280 X
.s
=DefaultScreen(X
.d
);
281 if(debug
) printf("Display:\n");
282 int xbig
=DisplayWidth(X
.d
, X
.s
);
283 int ybig
=DisplayHeight(X
.d
, X
.s
);
286 int bppbig
=X
.bpp
=DisplayPlanes(X
.d
, X
.s
);
287 if(X
.bpp
==24) X
.bypp
=4; //Can this be 3, also?
288 if(X
.bpp
==16) X
.bypp
=2;
289 if(X
.bpp
==8) X
.bypp
=1;
290 if(debug
) printf("%d*%d:%d/%d/%d\n",xbig
,ybig
,bppbig
, X
.bpp
, X
.bypp
);
291 if(debug
) printf("%d screens, vendor:%s, Ver:%d.%d(%d), at %s\n",
294 ProtocolVersion(X
.d
),
295 ProtocolRevision(X
.d
),
300 X
.v
=XDefaultVisualOfScreen(DefaultScreenOfDisplay(X
.d
));
302 X
.isnative24
= (bppbig
==24 && X
.v
->red_mask
==0xff0000 &&
303 X
.v
->green_mask
==0x00ff00 &&
304 X
.v
->blue_mask
==0x0000ff);
305 X
.isnative16
= (bppbig
==16 && X
.v
->red_mask
==0xf800 &&
306 X
.v
->green_mask
==0x07e0 &&
307 X
.v
->blue_mask
==0x1f);
308 X
.isnative8
= (bppbig
==8);
309 if(debug
) printf("8bpp:%d 16bpp:%d 24(32)bpp:%d\n",X
.isnative8
,X
.isnative16
,X
.isnative24
);
311 X
.root
=DefaultRootWindow(X
.d
);
312 if(!X
.root
) {return 0;}
314 X
.atom_wm
= XInternAtom( X
.d
, "WM_PROTOCOLS", False
);
315 X
.atom_wmdelete
= XInternAtom( X
.d
, "WM_DELETE_WINDOW", False
);
317 X
.cmap
=DefaultColormap(X
.d
,X
.s
);
318 X
.white
=WhitePixel(X
.d
,X
.s
);
319 X
.black
=BlackPixel(X
.d
,X
.s
);
321 /* start event handler thread */
323 pthread_create(&X
.eventhandler
,0,eventloop
,0);
331 //needed to set the border attribute
332 #define MWM_HINTS_FUNCTIONS (1L << 0)
333 #define MWM_HINTS_DECORATIONS (1L << 1)
334 #define MWM_HINTS_INPUT_MODE (1L << 2)
335 #define MWM_HINTS_STATUS (1L << 3)
337 #define MWM_FUNC_ALL (1L << 0)
338 #define MWM_FUNC_RESIZE (1L << 1)
339 #define MWM_FUNC_MOVE (1L << 2)
340 #define MWM_FUNC_MINIMIZE (1L << 3)
341 #define MWM_FUNC_MAXIMIZE (1L << 4)
342 #define MWM_FUNC_CLOSE (1L << 5)
344 #define MWM_DECOR_ALL (1L << 0)
345 #define MWM_DECOR_BORDER (1L << 1)
346 #define MWM_DECOR_RESIZEH (1L << 2)
347 #define MWM_DECOR_TITLE (1L << 3)
348 #define MWM_DECOR_MENU (1L << 4)
349 #define MWM_DECOR_MINIMIZE (1L << 5)
350 #define MWM_DECOR_MAXIMIZE (1L << 6)
352 #define MWM_INPUT_MODELESS 0
353 #define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
354 #define MWM_INPUT_SYSTEM_MODAL 2
355 #define MWM_INPUT_FULL_APPLICATION_MODAL 3
356 #define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
358 typedef struct _mwmhints
{
360 unsigned int functions
;
361 unsigned int decorations
;
366 static QXWindow
* openwindow(int posx
,int posy
,int w
,int h
,char*winName
)
372 pthread_mutex_lock(&X
.xmutex
);
375 fprintf(stderr
, "Error: XWindows not yet initialized!\n");
376 pthread_mutex_unlock(&X
.xmutex
);
380 QXWindow
*qx
= malloc(sizeof(QXWindow
));
386 qx
->next
=X
.windowring
;
387 qx
->prev
=X
.windowring
->prev
;
389 X
.windowring
->prev
=qx
;
393 char*iconName
=winName
;
400 qx
->mywin
=XCreateSimpleWindow(X
.d
,X
.root
,posx
,posy
,qx
->lenx
,qx
->leny
,0,X
.white
,X
.black
);
403 printf("Error: Couldn't create SimpleWindow\n");
404 pthread_mutex_unlock(&X
.xmutex
);
407 qx
->xwmh
=XAllocWMHints();
408 qx
->xsh
=XAllocSizeHints();
409 qx
->xch
=XAllocClassHint();
411 qx
->xsh
->flags
=(PPosition
|PSize
|PMinSize
|PMaxSize
);
412 qx
->xsh
->height
=qx
->xsh
->min_height
=qx
->xsh
->max_height
=h
;
413 qx
->xsh
->width
=qx
->xsh
->min_width
=qx
->xsh
->max_width
=w
;
417 if(!XStringListToTextProperty(&winName
, 1, &wname
)) {
418 printf("Error: XStringToTextProperty failed\n");
419 pthread_mutex_unlock(&X
.xmutex
);
422 if(!XStringListToTextProperty(&iconName
, 1, &iname
)) {
423 printf("Error: XStringToTextProperty failed\n");
424 pthread_mutex_unlock(&X
.xmutex
);
428 XSetWMProperties(X
.d
,qx
->mywin
,&wname
,&iname
,0,0,qx
->xsh
,qx
->xwmh
,qx
->xch
);
430 qx
->xgcv
.foreground
=X
.white
;
431 qx
->xgcv
.background
=X
.black
;
432 //qx->gc=XDefaultGC(X.d,qx->mywin);
433 qx
->gc
=XCreateGC(X
.d
,qx
->mywin
,GCForeground
|GCBackground
,&qx
->xgcv
);
435 XGetWindowAttributes(X
.d
,qx
->mywin
,&qx
->xwa
);
437 // enable events for close window
438 XChangeProperty(X
.d
, qx
->mywin
, X
.atom_wm
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *)(&X
.atom_wmdelete
), 1 );
441 // (This code comes from the project xine (xine.sourceforge.net)
442 // I wonder if this works with all windowmanagers, though)
445 Atom atomprop
= XInternAtom(X
.d
, "_MOTIF_WM_HINTS", True
);
449 mwmhints
.flags
= MWM_HINTS_DECORATIONS
;
450 if(noborder
==1) mwmhints
.decorations
= 2;
451 if(noborder
>1) mwmhints
.decorations
= 0;
452 XChangeProperty(X
.d
, qx
->mywin
, atomprop
, atomprop
, 32,
453 PropModeReplace
, (unsigned char *) &mwmhints
, 5);
454 XSetTransientForHint (X
.d
, qx
->mywin
, X
.root
);
458 qx
->bpp
=qx
->xwa
.depth
;
459 if(qx
->bpp
==24) qx
->bypp
=4; //Can this be 3, also?
460 if(qx
->bpp
==16) qx
->bypp
=2;
461 if(qx
->bpp
==8) qx
->bypp
=1;
464 XShmSegmentInfo segInfo
;
465 int bpl
= qx
->lenx
*qx
->bypp
;
466 segInfo
.readOnly
= 0;
467 segInfo
.shmid
= shmget(IPC_PRIVATE
,qx
->leny
*bpl
,IPC_CREAT
|0777);
469 if (segInfo
.shmid
<0) {
471 fprintf(stderr
,"Size = %d x %d\n", qx
->lenx
, qx
->leny
);
473 segInfo
.shmaddr
= (char*)shmat (segInfo
.shmid
, 0, 0);
474 if ((long)segInfo
.shmaddr
== -1) {
477 XShmAttach(X
.d
, &segInfo
);
478 if (shmctl(segInfo
.shmid
, IPC_RMID
, &buf
) < 0)
481 qx
->currentscr
= (U8
*)segInfo
.shmaddr
;
484 qx
->offscreen_pixmap
= XShmCreatePixmap(X
.d
,qx
->mywin
,segInfo
.shmaddr
,&segInfo
,qx
->lenx
,qx
->leny
,DefaultDepth(X
.d
, DefaultScreen(X
.d
)));
486 qx
->offscreen_ximage
= XShmCreateImage(X
.d
,X
.v
,24,ZPixmap
,(char*)segInfo
.shmaddr
, &segInfo
, qx
->lenx
,qx
->leny
);
487 XInitImage(qx
->offscreen_ximage
);
492 qx
->currentscr
= malloc(qx
->lenx
*qx
->leny
*4);
494 qx
->offscreen_pixmap
= XCreatePixmapFromBitmapData(X
.d
,qx
->mywin
,qx
->currentscr
,qx
->lenx
,qx
->leny
,0,0,DefaultDepth(X
.d
,X
.s
));
496 qx
->offscreen_ximage
= XCreateImage(X
.d
,X
.v
,24,ZPixmap
,0,(char*)qx
->currentscr
,qx
->lenx
,qx
->leny
,8,qx
->lenx
*4);
497 XInitImage(qx
->offscreen_ximage
);
503 /* get the image data for the area this window will be/is placed on */
508 XTranslateCoordinates(X.d,qx->mywin,X.root,0,0,&x,&y,&tmpwin);
509 qx->background = XGetImage(X.d, DefaultRootWindow(X.d), x, y, qx->lenx, qx->leny, AllPlanes, ZPixmap);
510 printf("%d %d\n",x,y);
513 XMapRaised(X
.d
,qx
->mywin
);
516 qx
->xswa
.event_mask
=(qx
->xwa
.your_event_mask
|=
526 XChangeWindowAttributes(X
.d
,qx
->mywin
,CWEventMask
,&qx
->xswa
);
528 qx
->queue
= queue_init(sizeof(gfxevent_t
), 256);
530 pthread_mutex_unlock(&X
.xmutex
);
532 pthread_mutex_init(&qx
->wmutex
, 0);
536 static void closeWindow(QXWindow
*qx
)
539 pthread_mutex_lock(&X
.xmutex
);
540 XDestroyWindow(X
.d
,qx
->mywin
);
541 pthread_mutex_unlock(&X
.xmutex
);
546 static void processEvent(gfxevent_t
*event
)
555 FD_SET(ConnectionNumber(X
.d
),&fdset
);
557 de
.tv_usec
= 5000; // 1/200 s
559 pthread_mutex_lock(&X
.xmutex
);
561 FD_SET(ConnectionNumber(X
.d
),&fdset
);
562 de
.tv_sec
= de
.tv_usec
= 0;
563 if(!select(ConnectionNumber(X
.d
)+1, &fdset
, 0, 0, &de
)) {
564 pthread_mutex_unlock(&X
.xmutex
);
569 pthread_mutex_unlock(&X
.xmutex
);
571 /* 1: find out which windows the message is for */
575 case ClientMessage
: w
= xe
.xclient
.window
;break;
576 case Expose
: w
= xe
.xexpose
.window
;break;
577 case NoExpose
: w
= xe
.xexpose
.window
;break;
578 case ButtonPress
: w
= xe
.xbutton
.window
;break;
579 case ButtonRelease
: w
= xe
.xbutton
.window
;break;
580 case KeyPress
: w
= xe
.xkey
.window
; break;
581 case KeyRelease
: w
= xe
.xkey
.window
; break;
582 case MotionNotify
: w
= xe
.xmotion
.window
;break;
583 case EnterNotify
: w
= xe
.xmotion
.window
;break;
584 case LeaveNotify
: w
= xe
.xmotion
.window
;break;
586 /* this usually happens for unknown events which
587 we don't care about */
591 QXWindow
*qx
=X
.windowring
;
599 while(qx
!=X
.windowring
);
602 /* Not one of our windows. This may be a bug */
605 event
->internal
= win
;
607 /* 2: Go for the event construction */
612 event
->type
= GFXEVENT_MOUSEPRESS
;
613 event
->button
= xe
.xbutton
.button
;
616 event
->type
= GFXEVENT_MOUSERELEASE
;
617 event
->button
= xe
.xbutton
.button
;
620 event
->type
= GFXEVENT_KEYPRESS
;
621 event
->key
= xe
.xkey
.keycode
;
624 event
->type
= GFXEVENT_KEYRELEASE
;
625 event
->key
= xe
.xkey
.keycode
;
628 event
->type
= GFXEVENT_MOUSEMOVE
;
629 pthread_mutex_lock(&qx
->wmutex
);
630 event
->x
= xe
.xmotion
.x_root
- win
->x
;
631 event
->y
= xe
.xmotion
.y_root
- win
->y
;
632 if(!queue_put(win
->queue
, event
)) {
633 printf("Queue overflow for window %08x!\n", win
);
635 pthread_mutex_unlock(&qx
->wmutex
);
638 event
->type
= GFXEVENT_MOUSEENTER
;
639 pthread_mutex_lock(&qx
->wmutex
);
640 event
->x
= xe
.xmotion
.x_root
- win
->x
;
641 event
->y
= xe
.xmotion
.y_root
- win
->y
;
642 pthread_mutex_unlock(&qx
->wmutex
);
645 event
->type
= GFXEVENT_MOUSELEAVE
;
646 pthread_mutex_lock(&qx
->wmutex
);
647 event
->x
= xe
.xmotion
.x
- win
->x
;
648 event
->y
= xe
.xmotion
.y
- win
->y
;
649 pthread_mutex_unlock(&qx
->wmutex
);
652 if ((xe
.xclient
.message_type
== X
.atom_wm
) &&
653 ((unsigned)xe
.xclient
.data
.l
[0] == X
.atom_wmdelete
) ) {
654 pthread_mutex_lock(&qx
->wmutex
);
656 event
->type
= GFXEVENT_DESTROY
;
657 pthread_mutex_unlock(&qx
->wmutex
);
663 static void*eventloop(void*r
)
665 //while(!XEventsQueued(X.d,QueuedAfterReading))
669 event
.type
= GFXEVENT_NOTHING
;
670 event
.key
= event
.x
= event
.y
= event
.button
= -1;
671 processEvent(&event
);
672 if(event
.type
!= GFXEVENT_NOTHING
&& event
.type
!= GFXEVENT_MOUSEMOVE
) {
673 QXWindow
*win
= (QXWindow
*)event
.internal
;
674 pthread_mutex_lock(&win
->wmutex
);
675 if(!queue_put(win
->queue
,&event
)) {
676 fprintf(stderr
, "Queue overflow for window %08x!\n", win
);
678 pthread_mutex_unlock(&win
->wmutex
);
684 typedef struct _internal
{
689 int tmplenx
, tmpleny
;
693 static void gfxwindow_on(gfxwindow_t
*win
)
695 internal_t
*i
= (internal_t
*)win
->internal
;
697 i
->qx
=openwindow(64, 64, win
->width
, win
->height
, i
->name
);
701 if(i
->qx
->bypp
!= 4) {
702 fprintf(stderr
, "Warning: Not a native 32 bit screen, using second buffer\n");
703 i
->currentscr2
= malloc(win
->width
*win
->height
*4);
704 win
->currentscr
= (unsigned char*)i
->currentscr2
;
706 win
->currentscr
= i
->qx
->currentscr
;
711 static void gfxwindow_off(gfxwindow_t
*win
)
713 internal_t
*i
= (internal_t
*)win
->internal
;
715 free(i
->currentscr2
);
719 static void gfxwindow_flippage(gfxwindow_t
*win
)
721 internal_t
*i
= (internal_t
*)win
->internal
;
722 pthread_mutex_lock(&X
.xmutex
);
725 if(i
->qx
->bypp
==2 && X
.isnative16
) {
727 int l
= win
->width
*win
->height
;
728 unsigned char*dest
= i
->qx
->currentscr
;
729 unsigned char*src
= (unsigned char*)i
->currentscr2
;
731 dest
[1] = (src
[2]&0xf8)|(src
[1]>>5);
732 dest
[0] = ((src
[1]<<5)&0xe0)|(src
[0]>>3);
737 memcpy(i
->qx
->currentscr
, i
->currentscr2
, i
->lenx
*i
->leny
*i
->qx
->bypp
);
741 XSetFunction(X
.d
,i
->qx
->gc
,GXcopy
);
744 if(i
->qx
->offscreen_pixmap
) {
745 XFreePixmap(X
.d
,i
->qx
->offscreen_pixmap
);i
->qx
->offscreen_pixmap
= 0;
747 i
->qx
->offscreen_pixmap
= XCreatePixmapFromBitmapData(X
.d
,i
->qx
->mywin
,i
->qx
->currentscr
,i
->qx
->lenx
,i
->qx
->leny
,X
.white
,X
.black
,DefaultDepth(X
.d
,X
.s
));
749 XCopyArea(X
.d
,i
->qx
->offscreen_pixmap
,i
->qx
->mywin
,i
->qx
->gc
, 0, 0, i
->qx
->lenx
,i
->qx
->leny
, 0, 0);
752 XPutImage(X
.d
,i
->qx
->mywin
,i
->qx
->gc
,i
->qx
->offscreen_ximage
,0,0,0,0,i
->qx
->lenx
,i
->qx
->leny
);
754 pthread_mutex_unlock(&X
.xmutex
);
757 void gfxwindow_setcolor(gfxwindow_t
*win
, U32 c
)
759 internal_t
*i
= (internal_t
*)win
->internal
;
760 pthread_mutex_lock(&X
.xmutex
);
761 i
->qx
->xgcv
.foreground
=getColorFromRGB((U8
)(c
>>16),(U8
)(c
>>8),(U8
)c
);
762 i
->gc
=XCreateGC(X
.d
,i
->qx
->mywin
,GCForeground
|GCBackground
,&i
->qx
->xgcv
);
763 pthread_mutex_unlock(&X
.xmutex
);
765 void gfxwindow_putpixel(gfxwindow_t
*win
, int x
, int y
, unsigned char c
)
767 internal_t
*i
= (internal_t
*)win
->internal
;
768 if(((U32
)x
)<(U32
)win
->width
&& ((U32
)y
)<(U32
)win
->height
)
769 *(U32
*)&win
->currentscr
[y
*win
->width
*i
->qx
->bypp
+x
*i
->qx
->bypp
]=c
;
771 static gfxevent_t
gfxwindow_getEvent(gfxwindow_t
*win
)
773 internal_t
*i
= (internal_t
*)win
->internal
;
775 pthread_mutex_lock(&i
->qx
->wmutex
);
776 if(!i
->qx
->queue
|| !queue_get(i
->qx
->queue
,&event
)) {
777 event
.type
= GFXEVENT_NOTHING
;
778 } else if(event
.type
== GFXEVENT_DESTROY
) {
779 queue_destroy(i
->qx
->queue
);i
->qx
->queue
=0;
781 pthread_mutex_unlock(&i
->qx
->wmutex
);
785 static void gfxwindow_move(gfxwindow_t
*win
, int x
,int y
)
787 internal_t
*i
= (internal_t
*)win
->internal
;
788 pthread_mutex_lock(&i
->qx
->wmutex
);
789 pthread_mutex_lock(&X
.xmutex
);
793 XMoveResizeWindow(X
.d
, i
->qx
->mywin
, i
->qx
->x
, i
->qx
->y
, i
->tmplenx
, i
->tmpleny
);
795 queue_t
* queue2
= queue_init(sizeof(gfxevent_t
), 256);
797 /* HACK: now that we have moved the window, all mouse move events
798 are outdated- remove them*/
799 while(queue_get(i
->qx
->queue
, &event
)) {
800 if(event
.type
!=GFXEVENT_MOUSEMOVE
)
801 queue_put(queue2
, &event
);
803 queue_destroy(i
->qx
->queue
);
804 i
->qx
->queue
= queue2
;
806 pthread_mutex_unlock(&X
.xmutex
);
807 pthread_mutex_unlock(&i
->qx
->wmutex
);
810 static void gfxwindow_resize(gfxwindow_t
*win
, int x
,int y
)
812 internal_t
*i
= (internal_t
*)win
->internal
;
813 if(x
>win
->width
|| y
>win
->height
) {
814 fprintf(stderr
, "resize: can only make windows smaller\n");
819 pthread_mutex_lock(&i
->qx
->wmutex
);
822 pthread_mutex_lock(&X
.xmutex
);
823 XMoveResizeWindow(X
.d
, i
->qx
->mywin
, i
->qx
->x
, i
->qx
->y
, i
->tmplenx
, i
->tmpleny
);
824 pthread_mutex_unlock(&X
.xmutex
);
825 pthread_mutex_unlock(&i
->qx
->wmutex
);
827 static void gfxwindow_destroy(gfxwindow_t
*win
)
829 internal_t
*i
= (internal_t
*)win
->internal
;
831 pthread_mutex_destroy(&i
->qx
->wmutex
);
834 gfxwindow_t
* gfxwindow_new(int width
, int height
)
836 gfxwindow_t
*w
= (gfxwindow_t
*)malloc(sizeof(gfxwindow_t
));
837 if(!initializexwindows()) {
838 fprintf(stderr
, "Warning: Couldn't initialize X-Windows\n");
840 internal_t
*i
= malloc(sizeof(internal_t
));
842 w
->move
= gfxwindow_move
;
843 w
->resize
= gfxwindow_resize
;
844 w
->flippage
= gfxwindow_flippage
;
845 w
->getEvent
= gfxwindow_getEvent
;
848 w
->destroy
= gfxwindow_destroy
;
850 i
->lenx
= i
->tmplenx
= width
;
851 i
->leny
= i
->tmpleny
= height
;