2
/* Ekiga -- A VoIP and Video-Conferencing application
3
* Copyright (C) 2000-2007 Damien Sandras
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20
* Ekiga is licensed under the GPL license and as a special exception,
21
* you have permission to link or otherwise combine this program with the
22
* programs OPAL, OpenH323 and PWLIB, and distribute the combination,
23
* without applying the requirements of the GNU GPL to the OPAL, OpenH323
24
* and PWLIB programs, as long as you do follow the requirements of the
25
* GNU GPL for all the rest of the software thus combined.
30
* XWindow.cpp - description
31
* ----------------------------
32
* begin : Fri Oct 26 2007
33
* copyright : (C) 2007 by Matthias Schneider <ma30002000@yahoo.de>
34
* description : High-level class offering direct X server drawing
41
#include <ptlib/object.h>
52
#ifdef WORDS_BIGENDIAN
53
#define BO_NATIVE MSBFirst
54
#define BO_NONNATIVE LSBFirst
56
#define BO_NATIVE LSBFirst
57
#define BO_NONNATIVE MSBFirst
60
struct xFormatsentry {
69
{"RGB24", 24, 3, MSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF}, //-RGB
70
{"RGB24", 24, 3, LSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000}, //-BGR
71
{"BGR24", 24, 3, MSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000}, //-BGR
72
{"BGR24", 24, 3, LSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF}, //-RGB
73
{"RGB32", 32, 4, BO_NATIVE, 0x000000FF, 0x0000FF00, 0x00FF0000}, //XBGR
74
{"RGB32", 32, 4, BO_NONNATIVE, 0xFF000000, 0x00FF0000, 0x0000FF00}, //RGBX
75
{"BGR32", 32, 4, BO_NATIVE, 0x00FF0000, 0x0000FF00, 0x000000FF}, //XRGB
76
{"BGR32", 32, 4, BO_NONNATIVE, 0x0000FF00, 0x00FF0000, 0xFF000000}, //BGRX
77
{"ARGB", 1, 0, MSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF}, //ARGB *
78
{"BGR32", 1, 4, LSBFirst, 0x0000FF00, 0x00FF0000, 0xFF000000}, //ARGB
79
{"ABGR", 1, 0, MSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000}, //ABGR *
80
{"RGB32", 1, 4, LSBFirst, 0xFF000000, 0x00FF0000, 0x0000FF00}, //ABGR
81
{"RGB32", 1, 4, MSBFirst, 0xFF000000, 0x00FF0000, 0x0000FF00}, //RGBA
82
{"RGBA", 1, 0, LSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000}, //RGBA *
83
{"BGR32", 1, 4, MSBFirst, 0x0000FF00, 0x00FF0000, 0xFF000000}, //BGRA
84
{"BGRA", 1, 0, LSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF}, //BGRA *
85
{NULL, 0, 0, 0, 0, 0, 0}
89
bool XWindow::_shmError = false;
91
static void catchXShmError(Display * , XErrorEvent * )
93
XWindow::_shmError = true;
99
// initialize class variables
111
_paintColorKey = false;
114
_isInitialized = false;
116
_state.fullscreen = false;
117
_state.ontop = false;
118
_state.decoration = true;
123
_imageDataOrig = NULL;
125
snprintf (_colorFormat, sizeof(_colorFormat), "NONE");
127
_colorConverter = NULL;
131
_XShmInfo.shmaddr = NULL;
133
_scalingAlgorithm = NULL;
139
XLockDisplay (_display);
143
if (_isInitialized && _XShmInfo.shmaddr) {
144
XShmDetach (_display, &_XShmInfo);
145
shmdt (_XShmInfo.shmaddr);
151
_XImage->data = _imageDataOrig;
156
XDestroyImage(_XImage);
160
_imageDataOrig = NULL;
162
// shared data structures
163
if (!_embedded && _gc)
164
XFreeGC (_display, _gc);
168
PTRACE(4, "X11\tUnmapping and destroying Window with ID " << _XWindow);
169
XUnmapWindow (_display, _XWindow);
170
XDestroyWindow (_display, _XWindow);
174
XUnlockDisplay (_display);
177
delete (_colorConverter);
185
XWindow::Init (Display* dp,
196
_rootWindow = rootWindow;
197
_imageWidth = imageWidth;
198
_imageHeight = imageHeight;
200
PTRACE(4, "X11\tInitiasing new X11 window with " << windowWidth << "x" << windowHeight << " at " << x << "," << y);
201
XLockDisplay (_display);
203
if (PTrace::CanTrace (4))
206
if (!CreateAtomsAndWindow(gc, x, y, windowWidth, windowHeight)) {
207
XUnlockDisplay(_display);
211
CreateXImage(windowWidth, windowHeight);
213
_isInitialized = true;
214
XUnlockDisplay (_display);
216
// check if that format is supported
217
struct xFormatsentry* xFormat = xFormats;
218
while (xFormat->name) {
219
if (xFormat->depth == _XImage->bits_per_pixel &&
220
xFormat->byte_order == _XImage->byte_order &&
221
xFormat->red_mask == _XImage->red_mask &&
222
xFormat->green_mask == _XImage->green_mask &&
223
xFormat->blue_mask == _XImage->blue_mask)
227
PTRACE(4, "X11\tXImage created with format: " << _XImage->bits_per_pixel <<" BPP, "
228
<< "Byte order: " << (_XImage->byte_order ? "MSBFirst" : "LSBFirst")
229
<< " Native: " << (BO_NATIVE ? "MSBFirst" : "LSBFirst"));
230
PTRACE(4, std::hex << "X11\tMask: Red: 0x" << _XImage->red_mask
231
<< " Green: 0x" << _XImage->green_mask
232
<< " Blue: 0x" << _XImage->blue_mask << std::dec);
233
if (!xFormat->name) {
234
PTRACE(1, "X11\tX server image format not supported, please contact the developers");
238
snprintf (_colorFormat, sizeof(_colorFormat), "%s", xFormat->name);
240
_planes = xFormat->planes;
242
#ifdef WORDS_BIGENDIAN
243
if (strcmp (xFormat->name, "BGRA") == 0) {
244
snprintf (_colorFormat, sizeof(_colorFormat), "RGB32");
248
if (strcmp (xFormat->name, "RGBA") == 0) {
249
snprintf (_colorFormat, sizeof(_colorFormat), "BGR32");
254
if (strcmp (xFormat->name, "ABGR") == 0) {
255
snprintf (_colorFormat, sizeof(_colorFormat), "BGR32");
259
if (strcmp (xFormat->name, "ARGB") == 0) {
260
snprintf (_colorFormat, sizeof(_colorFormat), "RGB32");
265
PTRACE(4, "X11\tUsing color format: " << _colorFormat);
266
PTRACE(4, "X11\tPlanes: " << _planes);
268
PVideoFrameInfo srcFrameInfo, dstFrameInfo;
269
srcFrameInfo.SetFrameSize(_imageWidth,_imageHeight);
270
dstFrameInfo.SetFrameSize(_imageWidth,_imageHeight);
271
dstFrameInfo.SetColourFormat(_colorFormat);
272
_colorConverter = PColourConverter::Create(srcFrameInfo, dstFrameInfo);
273
if (!_colorConverter)
276
_frameBuffer = (uint8_t*) malloc (_imageWidth * _imageHeight * _planes);
278
// detect the window manager type
279
_wmType = GetWMType ();
280
CalculateSize (windowWidth, windowHeight, true);
287
XWindow::PutFrame (uint8_t* frame,
294
if (width != _imageWidth || height != _imageHeight) {
295
PTRACE (1, "X11\tDynamic switching of resolution not supported\n");
299
XLockDisplay (_display);
302
if ((_state.curWidth != _XImage->width) || (_state.curHeight!=_XImage->height))
303
CreateXImage(_state.curWidth, _state.curHeight);
305
_colorConverter->Convert((BYTE*)frame, (BYTE*)_frameBuffer);
307
pixops_scale ((guchar*) _XImage->data,
309
_state.curWidth, _state.curHeight,
310
_state.curWidth * _planes, //dest_rowstride
311
_planes, //dest_channels,
312
FALSE, //dest_has_alpha,
314
(const guchar*) _frameBuffer,
317
width * _planes, //src_rowstride
318
_planes, //src_channels,
319
FALSE, //src_has_alpha,
321
(double) _state.curWidth / width,
322
(double) _state.curHeight / height,
323
(PixopsInterpType) _scalingAlgorithm);
325
_XImage->data += _outOffset;
329
XShmPutImage(_display, _XWindow, _gc, _XImage,
331
_state.curX, _state.curY,
332
_state.curWidth, _state.curHeight, false);
336
XPutImage(_display, _XWindow, _gc, _XImage,
338
_state.curX, _state.curY,
339
_state.curWidth,_state.curHeight);
341
_XImage->data -= _outOffset;
343
XUnlockDisplay (_display);
347
XWindow::ProcessEvents()
352
XLockDisplay (_display);
353
while (XCheckWindowEvent (_display, _XWindow, StructureNotifyMask
354
| SubstructureRedirectMask
357
| ButtonPressMask, &event) == True) {
359
switch (event.type) {
361
// If "closeWindow" is clicked do nothing right now
362
// (window is closed from the GUI)
365
case ConfigureNotify:
367
// the window size has changed
368
XConfigureEvent *xce = &(event.xconfigure);
370
// if a slave window exists it has to be resized as well
372
_slave->SetWindow (xce->width - (int) (xce->width / ( _state.fullscreen ? PIP_RATIO_FS : PIP_RATIO_WIN)),
373
xce->height - (int) (_slave->GetYUVHeight () * xce->width / ( _state.fullscreen ? PIP_RATIO_FS : PIP_RATIO_WIN) / _slave->GetYUVWidth ()),
374
(int) (xce->width / ( _state.fullscreen ? PIP_RATIO_FS : PIP_RATIO_WIN)),
375
(int) (_slave->GetYUVHeight () * xce->width / ( _state.fullscreen ? PIP_RATIO_FS : PIP_RATIO_WIN) / _slave->GetYUVWidth ()));
377
CalculateSize (xce->width, xce->height, true);
379
if( _paintColorKey ) {
381
XSetForeground( _display, _gc, _colorKey );
382
XFillRectangle( _display, _XWindow, _gc, _state.curX, _state.curY, _state.curWidth, _state.curHeight);
388
if (_paintColorKey) {
389
XSetForeground( _display, _gc, _colorKey );
390
XFillRectangle( _display, _XWindow, _gc, _state.curX, _state.curY, _state.curWidth, _state.curHeight);
398
XKeyEvent *xke = &(event.xkey);
399
switch (xke->keycode) {
402
_master->ToggleFullscreen ();
404
ToggleFullscreen (); // "f"
408
_master->ToggleDecoration ();
410
ToggleDecoration (); // "d"
414
_master->ToggleOntop ();
416
ToggleOntop (); // "o"
420
if (_master->IsFullScreen ())
421
_master->ToggleFullscreen();
435
// a mouse button is clicked
438
if (!_master->HasDecoration())
439
_master->ToggleDecoration();
441
_master->ToggleFullscreen();
443
if (!_state.decoration)
450
PTRACE(4, "X11\tWindow is being destroyed");
454
PTRACE(1, "X11\tUnknown X Event " << event.type << " received");
457
XUnlockDisplay (_display);
466
XLockDisplay(_display);
467
XSync (_display, False);
468
XUnlockDisplay(_display);
473
XWindow::ToggleFullscreen ()
479
XWindowAttributes xwattributes;
486
if (_state.fullscreen) {
488
// not needed with EWMH fs
489
if (!(_wmType & wm_FULLSCREEN)) {
493
newWidth = _state.oldWidth;
494
newHeight = _state.oldHeight;
495
SetDecoration (true);
498
// removes fullscreen state if wm supports EWMH
499
SetEWMHFullscreen (_NET_WM_STATE_REMOVE);
503
// sets fullscreen state if wm supports EWMH
504
SetEWMHFullscreen (_NET_WM_STATE_ADD);
506
// not needed with EWMH fs - save window coordinates/size
507
// and discover fullscreen window size
508
if (!(_wmType & wm_FULLSCREEN)) {
510
XLockDisplay (_display);
514
newWidth = DisplayWidth (_display, DefaultScreen (_display));
515
newHeight = DisplayHeight (_display, DefaultScreen (_display));
517
SetDecoration (false);
520
XTranslateCoordinates (_display, _XWindow, RootWindow (_display, DefaultScreen (_display)),
521
0, 0, &_state.oldx, &_state.oldy, &childWindow);
523
XGetWindowAttributes (_display, _XWindow, &xwattributes);
524
XUnlockDisplay (_display);
526
_state.oldWidth = xwattributes.width;
527
_state.oldHeight = xwattributes.height;
531
// not needed with EWMH fs - create a screen-filling window on top
532
// and turn of decorations
533
if (!(_wmType & wm_FULLSCREEN)) {
535
SetSizeHints (newX, newY, _XImage->width, _XImage->height, newWidth, newHeight);
537
XLockDisplay (_display);
538
SetLayer (!_state.fullscreen ? 0 : 1);
539
XMoveResizeWindow (_display, _XWindow, newX, newY, newWidth, newHeight);
540
XUnlockDisplay (_display);
543
// some WMs lose ontop after fullscreeen
544
if (_state.fullscreen & _state.ontop)
547
XLockDisplay (_display);
548
XMapRaised (_display, _XWindow);
549
XRaiseWindow (_display, _XWindow);
550
XSync (_display, False);
551
XUnlockDisplay (_display);
553
_state.fullscreen = !_state.fullscreen;
558
XWindow::ToggleOntop ()
562
SetLayer (_state.ontop ? 0 : 1);
563
_state.ontop = !_state.ontop;
568
XWindow::ToggleDecoration ()
572
SetDecoration (!_state.decoration);
577
XWindow::SetWindow (int x,
579
unsigned int windowWidth,
580
unsigned int windowHeight)
582
PTRACE(4, "X11\tSetWindow " << x << "," << y << " " << windowWidth << "x" << windowHeight);
583
XLockDisplay (_display);
584
XMoveResizeWindow (_display, _XWindow, x, y, windowWidth, windowHeight);
585
XUnlockDisplay (_display);
586
CalculateSize (windowWidth, windowHeight, true);
591
XWindow::GetWindow (int *x,
593
unsigned int *windowWidth,
594
unsigned int *windowHeight)
603
bool decoration = false;
605
decoration = _state.decoration;
606
SetDecoration (false);
608
XLockDisplay (_display);
609
XSync (_display, False);
610
XGetGeometry (_display, _XWindow, &root, &oldx, &oldy, windowWidth, windowHeight, &ud, &ud);
611
XTranslateCoordinates (_display, _XWindow, root, oldx, oldy, x, y, &_dw);
612
XUnlockDisplay (_display);
614
SetDecoration (decoration);
620
XWindow::CreateAtomsAndWindow(GC gc,
626
XSetWindowAttributes xswattributes;
629
WM_DELETE_WINDOW = XInternAtom (_display, "WM_DELETE_WINDOW", False);
630
XA_WIN_PROTOCOLS = XInternAtom (_display, "_WIN_PROTOCOLS", False);
631
XA_NET_SUPPORTED = XInternAtom (_display, "_NET_SUPPORTED", False);
632
XA_NET_WM_STATE = XInternAtom (_display, "_NET_WM_STATE", False);
633
XA_NET_WM_STATE_FULLSCREEN = XInternAtom (_display, "_NET_WM_STATE_FULLSCREEN", False);
634
XA_NET_WM_STATE_ABOVE = XInternAtom (_display, "_NET_WM_STATE_ABOVE", False);
635
XA_NET_WM_STATE_STAYS_ON_TOP = XInternAtom (_display, "_NET_WM_STATE_STAYS_ON_TOP", False);
636
XA_NET_WM_STATE_BELOW = XInternAtom (_display, "_NET_WM_STATE_BELOW", False);
638
XSync (_display, False);
643
// define window properties and create the window
644
xswattributes.colormap = XCreateColormap (_display, _rootWindow, _XVInfo.visual, AllocNone);
645
xswattributes.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask;
647
xswattributes.background_pixel = WhitePixel (_display, DefaultScreen (_display));
649
xswattributes.border_pixel = WhitePixel (_display, DefaultScreen (_display));
651
_XWindow = XCreateWindow (_display, _rootWindow, x, y, windowWidth, windowHeight,
652
0, _XVInfo.depth, InputOutput, _XVInfo.visual,
653
CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &xswattributes);
655
PTRACE(4, "X11\tCreated Window with ID " << _XWindow);
657
SetSizeHints (DEFAULT_X,DEFAULT_Y, _imageWidth, _imageHeight, windowWidth, windowHeight);
660
XMapWindow (_display, _XWindow);
662
XSetWMProtocols (_display, _XWindow, &WM_DELETE_WINDOW, 1);
664
// Checking if we are going embedded or not
670
_gc = XCreateGC (_display, _XWindow, 0, 0);
678
XWindow::SetLayer (int layer)
682
Window mRootWin = RootWindow (_display, DefaultScreen (_display));
684
memset (&xev, 0, sizeof(xev));
686
if (_wmType & wm_LAYER) {
688
if (!_state.origLayer)
689
_state.origLayer = GetGnomeLayer ();
691
xev.type = ClientMessage;
692
xev.xclient.display = _display;
693
xev.xclient.window = _XWindow;
694
xev.xclient.message_type = XA_WIN_LAYER;
695
xev.xclient.format = 32;
696
xev.xclient.data.l [0] = layer ? WIN_LAYER_ABOVE_DOCK : _state.origLayer;
697
xev.xclient.data.l [1] = CurrentTime;
698
PTRACE(4, "X11\tLayered style stay on top (layer " << xev.xclient.data.l[0] << ")");
700
XLockDisplay (_display);
701
XSendEvent (_display, mRootWin, FALSE, SubstructureNotifyMask, &xev);
702
XUnlockDisplay (_display);
705
else if (_wmType & wm_NETWM) {
707
xev.type = ClientMessage;
708
xev.xclient.message_type = XA_NET_WM_STATE;
709
xev.xclient.display = _display;
710
xev.xclient.window = _XWindow;
711
xev.xclient.format = 32;
712
xev.xclient.data.l [0] = layer;
714
if (_wmType & wm_STAYS_ON_TOP)
715
xev.xclient.data.l [1] = XA_NET_WM_STATE_STAYS_ON_TOP;
717
if (_wmType & wm_ABOVE)
718
xev.xclient.data.l [1] = XA_NET_WM_STATE_ABOVE;
720
if (_wmType & wm_FULLSCREEN)
721
xev.xclient.data.l [1] = XA_NET_WM_STATE_FULLSCREEN;
723
if (_wmType & wm_BELOW)
724
xev.xclient.data.l [1] = XA_NET_WM_STATE_BELOW;
726
XLockDisplay (_display);
727
XSendEvent (_display, mRootWin, FALSE, SubstructureRedirectMask, &xev);
728
state = XGetAtomName (_display, xev.xclient.data.l [1]);
729
PTRACE(4, "X11\tNET style stay on top (layer " << layer << "). Using state " << state );
731
XUnlockDisplay (_display);
737
XWindow::SetEWMHFullscreen (int action)
739
if (_wmType & wm_FULLSCREEN) {
741
// create an event event to toggle fullscreen mode
744
xev.xclient.type = ClientMessage;
745
xev.xclient.serial = 0;
746
xev.xclient.send_event = True;
747
xev.xclient.message_type = XInternAtom (_display, "_NET_WM_STATE", False);
748
xev.xclient.window = _XWindow;
749
xev.xclient.format = 32;
751
xev.xclient.data.l[0] = action;
752
xev.xclient.data.l[1] = XInternAtom (_display, "_NET_WM_STATE_FULLSCREEN", False);
753
xev.xclient.data.l[2] = 0;
754
xev.xclient.data.l[3] = 0;
755
xev.xclient.data.l[4] = 0;
757
// send the event to the window
758
XLockDisplay (_display);
759
if (!XSendEvent (_display, _rootWindow, FALSE, SubstructureRedirectMask | SubstructureNotifyMask, &xev)) {
760
PTRACE(1, "X11\tSetEWMHFullscreen failed");
762
XUnlockDisplay (_display);
768
XWindow::SetDecoration (bool d)
773
MotifWmHints setHints;
774
MotifWmHints *getHints = NULL;
776
unsigned char *args = NULL;
779
unsigned long mn = 0;
780
unsigned long mb = 0;
782
static unsigned int oldDecor = MWM_DECOR_ALL;
783
static unsigned int oldFuncs = MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE;
785
XLockDisplay (_display);
787
motifHints = XInternAtom (_display, "_MOTIF_WM_HINTS", 0);
789
if (motifHints != None) {
791
memset (&setHints, 0, sizeof (setHints));
795
XGetWindowProperty (_display, _XWindow, motifHints, 0, 20, False, motifHints, &mType, &mFormat, &mn, &mb, &args);
796
getHints = (MotifWmHints*) args;
800
if (getHints->flags & MWM_HINTS_DECORATIONS)
801
oldDecor = getHints->decorations;
803
if (getHints->flags & MWM_HINTS_FUNCTIONS)
804
oldFuncs = getHints->functions;
810
setHints.decorations = 0;
814
setHints.functions = oldFuncs;
815
setHints.decorations = oldDecor;
818
setHints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
820
XChangeProperty (_display, _XWindow, motifHints, motifHints, 32, PropModeReplace, (unsigned char *) &setHints, 5);
822
_state.decoration=!_state.decoration;
825
XUnlockDisplay (_display);
830
XWindow::GetWMType ()
836
int metacityHack = 0;
837
unsigned long nitems = 0;
839
// check if WM supports layers
840
if (GetWindowProperty (XA_WIN_PROTOCOLS, &args, &nitems)) {
842
PTRACE(4, "X11\tDetected WM supports layers");
843
for (i = 0; i < nitems; i++) {
845
if (args [i] == XA_WIN_LAYER) {
853
XLockDisplay (_display);
855
XUnlockDisplay (_display);
857
// metacity WM reports that it supports layers,
858
// but it is not really true :-)
859
if (wmType && metacityHack == 1) {
861
PTRACE(4, "X11\tUsing workaround for Metacity bug");
866
if (GetWindowProperty (XA_NET_SUPPORTED, &args, &nitems)) {
868
PTRACE(4, "X11\tDetected wm supports NetWM.");
870
for (i = 0; i < nitems; i++)
871
wmType |= GetSupportedState (args[i]);
873
XLockDisplay (_display);
875
XUnlockDisplay (_display);
880
PTRACE(4, "X11\tUnknown wm type...");
888
XWindow::GetGnomeLayer ()
893
unsigned long count = 0;
894
unsigned long bytesafter = 0;
895
unsigned char *prop = NULL;
897
long layer = WIN_LAYER_NORMAL;
899
XLockDisplay (_display);
900
if (XGetWindowProperty (_display, _XWindow,XA_WIN_LAYER, 0, 16384, false, XA_CARDINAL, &type, &format, &count, &bytesafter, &prop)
901
== Success && prop) {
903
if (type == XA_CARDINAL && format == 32 && count == 1)
904
layer = ((long *) prop) [0];
908
XUnlockDisplay(_display);
915
XWindow::GetSupportedState (Atom atom)
917
if (atom == XA_NET_WM_STATE_FULLSCREEN)
918
return wm_FULLSCREEN;
920
if (atom == XA_NET_WM_STATE_ABOVE)
923
if (atom == XA_NET_WM_STATE_STAYS_ON_TOP)
924
return wm_STAYS_ON_TOP;
926
if (atom==XA_NET_WM_STATE_BELOW)
934
XWindow::GetWindowProperty (Atom type,
936
unsigned long *nitems)
939
unsigned long bytesafter = 0;
942
XLockDisplay(_display);
943
ret = (Success == XGetWindowProperty (_display, _rootWindow, type, 0, 16384, false,
944
AnyPropertyType, &type, &format, nitems, &bytesafter, (unsigned char **) args) && *nitems > 0);
945
XUnlockDisplay(_display);
952
XWindow::CalculateSize (int windowWidth,
954
bool doAspectCorrection)
956
if ( doAspectCorrection && ((windowWidth * _imageHeight / _imageWidth) > windowHeight)) {
958
_state.curX = (int) ((windowWidth - (windowHeight * _imageWidth / _imageHeight)) / 2);
960
_state.curWidth = (int) (windowHeight * _imageWidth / _imageHeight);
961
_state.curHeight = windowHeight;
964
else if ( doAspectCorrection && ((windowHeight * _imageWidth / _imageHeight) > windowWidth)) {
967
_state.curY = (int) ((windowHeight - (windowWidth * _imageHeight / _imageWidth)) / 2);
968
_state.curWidth = windowWidth;
969
_state.curHeight = (int) (windowWidth * _imageHeight / _imageWidth);
975
_state.curWidth = windowWidth;
976
_state.curHeight = windowHeight;
982
XWindow::SetSizeHints (int x,
991
xshints.flags = PPosition | PSize | PAspect | PMinSize | PMaxSize;
993
xshints.min_aspect.x = imageWidth;
994
xshints.min_aspect.y = imageHeight;
995
xshints.max_aspect.x = imageWidth;
996
xshints.max_aspect.y = imageHeight;
1000
xshints.width = windowWidth;
1001
xshints.height = windowHeight;
1002
xshints.min_width = windowWidth;
1003
xshints.min_height = windowHeight;
1004
xshints.max_width = windowWidth;
1005
xshints.max_height = windowHeight;
1007
XSetStandardProperties (_display, _XWindow, "Video", "Video", None, NULL, 0, &xshints);
1011
bool XWindow::checkDepth ()
1014
XWindowAttributes xwattributes;
1015
XGetWindowAttributes (_display, _rootWindow, &xwattributes);
1016
if (xwattributes.depth == 32) {
1018
if (!XMatchVisualInfo (_display, DefaultScreen (_display), _depth, TrueColor, &_XVInfo)) {
1019
PTRACE(4, "X11\tCould not find visual with colordepth of " << _depth << " bits per pixel");
1021
if (!XMatchVisualInfo (_display, DefaultScreen (_display), _depth, TrueColor, &_XVInfo)) {
1022
PTRACE(1, "X11\tCould neither find visual with colordepth of 32 bits per pixel nor with 24 bits per pixel");
1029
if (!XMatchVisualInfo (_display, DefaultScreen (_display), _depth, TrueColor, &_XVInfo)) {
1030
PTRACE(4, "X11\tCould not find visual with colordepth of " << _depth << " bits per pixel");
1032
if (!XMatchVisualInfo (_display, DefaultScreen (_display), _depth, TrueColor, &_XVInfo)) {
1033
PTRACE(1, "X11\tCould neither find visual with colordepth of 24 bits per pixel nor with 32 bits per pixel");
1043
void XWindow::ShmAttach(int imageWidth, int imageHeight)
1046
_XImage = XShmCreateImage(_display, _XVInfo.visual, _depth, ZPixmap, NULL, &_XShmInfo, imageWidth, imageHeight);
1047
if (_XImage == NULL) {
1048
PTRACE(1, "X11\tXShmCreateImage failed");
1054
_XShmInfo.shmid = shmget(IPC_PRIVATE, _XImage->bytes_per_line * _XImage->height, IPC_CREAT | 0777);
1055
if (_XShmInfo.shmid < 0) {
1056
XDestroyImage(_XImage);
1058
PTRACE(1, "X11\tshmget failed"); //strerror(errno)
1064
_XShmInfo.shmaddr = (char *) shmat(_XShmInfo.shmid, 0, 0);
1065
if (_XShmInfo.shmaddr == ((char *) -1)) {
1066
XDestroyImage(_XImage);
1068
PTRACE(1, "X11\tshmat failed"); //strerror(errno)
1074
_XImage->data = _XShmInfo.shmaddr;
1075
_XShmInfo.readOnly = False;
1077
// Attaching the shared memory to the display
1078
XErrorHandler oldHandler = XSetErrorHandler((XErrorHandler) catchXShmError);
1079
Status status = XShmAttach (_display, &_XShmInfo);
1080
XSync(_display, False);
1081
XSetErrorHandler((XErrorHandler) oldHandler);
1083
if ( (status != True) || (_shmError) ) {
1084
XDestroyImage(_XImage);
1086
if (_XShmInfo.shmaddr != ((char *) -1)) {
1087
shmdt(_XShmInfo.shmaddr);
1089
PTRACE(1, "X11\t XShmAttach failed");
1090
if ( (status == True) && (_shmError) ) {
1091
PTRACE(1, "X11\t X server supports SHM but apparently we are remotely connected...");
1098
shmctl(_XShmInfo.shmid, IPC_RMID, 0);
1104
void XWindow::CreateXImage(int width, int height)
1108
if (_isInitialized && _XShmInfo.shmaddr) {
1109
XShmDetach (_display, &_XShmInfo);
1110
shmdt (_XShmInfo.shmaddr);
1116
_XImage->data = _imageDataOrig;
1121
XDestroyImage(_XImage);
1123
_imageDataOrig = NULL;
1126
if (XShmQueryExtension (_display)) {
1128
PTRACE(1, "X11\tXQueryShmExtension success");
1132
PTRACE(1, "X11\tXQueryShmExtension failed");
1136
ShmAttach(width, height);
1139
PTRACE(4, "X11\tUsing shm extension");
1144
_XImage = XCreateImage(_display, _XVInfo.visual, _depth, ZPixmap, 0, NULL, width, height, 8, 0);
1145
_imageDataOrig = (char*)malloc(width * height * 4 + 32);
1146
_XImage->data = _imageDataOrig + 16 - ((long)_imageDataOrig & 15);
1147
memset(_XImage->data, 0, width * 4 * height);
1153
XWindow::DumpVisuals()
1155
XVisualInfo visualTemplate;
1156
XVisualInfo *visuals;
1160
visualTemplate.screen = DefaultScreen(_display);
1161
visuals = XGetVisualInfo(_display, VisualScreenMask , &visualTemplate, &nbVisuals);
1162
if (visuals != NULL) {
1163
for (i = 0; i < nbVisuals; i++) {
1164
PTRACE(4, "X11\tVisual #" << i << " ID: " << visuals[i].visualid
1165
<< " Class: " << visuals[i].c_class
1166
<< " BPRGB: " << visuals[i].bits_per_rgb
1167
<< " Depth: " << visuals[i].depth << std::hex
1168
<< " Red: 0x" << visuals[i].red_mask
1169
<< " Green: 0x" << visuals[i].green_mask
1170
<< " Blue 0x" << visuals[i].blue_mask << std::dec);