1
|
#include "CtrlCore.h"
|
2
|
|
3
|
#ifdef GUI_X11
|
4
|
|
5
|
#include <locale.h>
|
6
|
|
7
|
NAMESPACE_UPP
|
8
|
|
9
|
#define LLOG(x)
|
10
|
|
11
|
XIM Ctrl::xim;
|
12
|
|
13
|
Atom XAtomRaw(const char *name)
|
14
|
{
|
15
|
return XInternAtom(Xdisplay, name, XFalse);
|
16
|
}
|
17
|
|
18
|
Atom XAtom(const char *name)
|
19
|
{
|
20
|
GuiLock __;
|
21
|
Atom x;
|
22
|
INTERLOCKED {
|
23
|
static VectorMap<String, int> atoms;
|
24
|
int q = atoms.Get(name, Null);
|
25
|
if(IsNull(q)) {
|
26
|
q = XAtomRaw(name);
|
27
|
atoms.Add(name, q);
|
28
|
}
|
29
|
x = q;
|
30
|
}
|
31
|
return x;
|
32
|
}
|
33
|
|
34
|
String XAtomName(Atom atom)
|
35
|
{
|
36
|
GuiLock __;
|
37
|
LLOG("GetAtomName");
|
38
|
return XGetAtomName(Xdisplay, atom);
|
39
|
}
|
40
|
|
41
|
String GetProperty(Window w, Atom property, Atom rtype)
|
42
|
{
|
43
|
GuiLock __;
|
44
|
LLOG("GetProperty");
|
45
|
String result;
|
46
|
int format;
|
47
|
unsigned long nitems, after = 1;
|
48
|
long offset = 0;
|
49
|
Atom type = None;
|
50
|
unsigned char *data;
|
51
|
long rsize = minmax((long)(XMaxRequestSize(Xdisplay) - 100), (long)256, (long)65536);
|
52
|
while(after > 0) {
|
53
|
if(XGetWindowProperty(Xdisplay, w, property, offset, rsize, XFalse,
|
54
|
rtype, &type, &format, &nitems, &after, &data) != Success)
|
55
|
break;
|
56
|
if(type == None)
|
57
|
break;
|
58
|
if(data) {
|
59
|
int len = format == 32 ? sizeof(unsigned long) * nitems : nitems * (format >> 3);
|
60
|
result.Cat(data, len);
|
61
|
XFree((char *)data);
|
62
|
offset += nitems / (32 / format);
|
63
|
}
|
64
|
else
|
65
|
break;
|
66
|
}
|
67
|
result.Shrink();
|
68
|
XFlush(Xdisplay);
|
69
|
return result;
|
70
|
}
|
71
|
|
72
|
bool WaitForEvent(Window w, int type, XEvent& event){
|
73
|
GuiLock __;
|
74
|
for(int i = 0; i < 80; i++) {
|
75
|
if(XCheckTypedWindowEvent(Xdisplay, w, type, &event))
|
76
|
return true;
|
77
|
XFlush(Xdisplay);
|
78
|
Sleep(50);
|
79
|
}
|
80
|
LOG("WaitForEvent failed");
|
81
|
return false;
|
82
|
}
|
83
|
|
84
|
|
85
|
String ReadPropertyData(Window w, Atom property, Atom rtype)
|
86
|
{
|
87
|
GuiLock __;
|
88
|
static Atom XA_INCR = XAtom("INCR");
|
89
|
Atom type;
|
90
|
int format;
|
91
|
unsigned long nitems, after;
|
92
|
unsigned char *ptr;
|
93
|
String r;
|
94
|
if(XGetWindowProperty(Xdisplay, w, property, 0, 0, XFalse, AnyPropertyType,
|
95
|
&type, &format, &nitems, &after, &ptr) == Success && type != None) {
|
96
|
XFree(ptr);
|
97
|
if(type == XA_INCR) {
|
98
|
XDeleteProperty(Xdisplay, w, property);
|
99
|
XEvent event;
|
100
|
for(;;) {
|
101
|
XFlush(Xdisplay);
|
102
|
if(!WaitForEvent(w, PropertyNotify, event))
|
103
|
break;
|
104
|
if(event.xproperty.atom == property && event.xproperty.state == PropertyNewValue) {
|
105
|
String x = GetProperty(w, property);
|
106
|
if(!x.GetLength())
|
107
|
break;
|
108
|
r.Cat(x);
|
109
|
XDeleteProperty(Xdisplay, w, property);
|
110
|
}
|
111
|
}
|
112
|
}
|
113
|
else {
|
114
|
r = GetProperty(w, property);
|
115
|
XDeleteProperty(Xdisplay, w, property);
|
116
|
}
|
117
|
}
|
118
|
return r;
|
119
|
}
|
120
|
|
121
|
Vector<int> GetPropertyInts(Window w, Atom property, Atom rtype)
|
122
|
{
|
123
|
GuiLock __;
|
124
|
Vector<int> result;
|
125
|
String p = GetProperty(w, property, rtype);
|
126
|
const long int *ptr = (const long int *)~p;
|
127
|
const long int *lim = ptr + p.GetLength() / sizeof(long int);
|
128
|
result.Reserve(p.GetLength() / sizeof(long int));
|
129
|
while(ptr < lim)
|
130
|
result.Add(*ptr++);
|
131
|
return result;
|
132
|
}
|
133
|
|
134
|
Index<Atom>& _NET_Supported()
|
135
|
{
|
136
|
static Index<Atom> q;
|
137
|
return q;
|
138
|
}
|
139
|
|
140
|
bool X11ErrorTrap;
|
141
|
|
142
|
bool Ctrl::TrapX11Errors()
|
143
|
{
|
144
|
GuiLock __;
|
145
|
bool b = X11ErrorTrap;
|
146
|
X11ErrorTrap = true;
|
147
|
return b;
|
148
|
}
|
149
|
|
150
|
void Ctrl::UntrapX11Errors(bool b)
|
151
|
{
|
152
|
GuiLock __;
|
153
|
X11ErrorTrap = b;
|
154
|
}
|
155
|
|
156
|
void sPanicMessageBox(const char *title, const char *text)
|
157
|
{
|
158
|
IGNORE_RESULT(
|
159
|
write(2, text, strlen(text))
|
160
|
);
|
161
|
IGNORE_RESULT(
|
162
|
write(2, "\n", 1)
|
163
|
);
|
164
|
if(Ctrl::grabWindow) {
|
165
|
LLOG("RELEASE GRAB");
|
166
|
XUngrabPointer(Xdisplay, CurrentTime);
|
167
|
XFlush(Xdisplay);
|
168
|
}
|
169
|
XDisplay *display = XOpenDisplay(NULL);
|
170
|
if(!display)
|
171
|
return;
|
172
|
int screen = DefaultScreen(display);
|
173
|
int x = (DisplayWidth(display, screen) - 600) / 2;
|
174
|
int y = (DisplayHeight(display, screen) - 120) / 2;
|
175
|
Window win = XCreateSimpleWindow(display, RootWindow(display, screen),
|
176
|
x, y, 600, 120, 4,
|
177
|
BlackPixel(display, screen),
|
178
|
WhitePixel(display, screen));
|
179
|
XSizeHints size_hints;
|
180
|
size_hints.flags = PPosition|PSize|PMinSize;
|
181
|
size_hints.x = x;
|
182
|
size_hints.y = x;
|
183
|
size_hints.width = 600;
|
184
|
size_hints.height = 120;
|
185
|
size_hints.min_width = 600;
|
186
|
size_hints.min_height = 120;
|
187
|
char *h[1];
|
188
|
char hh[1];
|
189
|
*hh = 0;
|
190
|
h[0] = hh;
|
191
|
XSetStandardProperties(display, win, title, title, None, h, 0, &size_hints);
|
192
|
XSelectInput(display, win, ExposureMask|KeyPressMask|ButtonPressMask|StructureNotifyMask);
|
193
|
XGCValues values;
|
194
|
GC gc = XCreateGC(display, win, 0, &values);
|
195
|
unsigned long wina[1];
|
196
|
wina[0] = XInternAtom(display, "_NET_WM_STATE_ABOVE", XFalse);
|
197
|
XChangeProperty(display, win,
|
198
|
XInternAtom(display, "_NET_WM_STATE", XFalse),
|
199
|
XInternAtom(display, "ATOM", XFalse), 32,
|
200
|
PropModeReplace, (const unsigned char *)&wina, 1);
|
201
|
XMapWindow(display, win);
|
202
|
|
203
|
XRaiseWindow(display, win);
|
204
|
XFontStruct *font_info = XQueryFont(display, XGContextFromGC(gc));
|
205
|
for(;;) {
|
206
|
XEvent e;
|
207
|
XNextEvent(display, &e);
|
208
|
switch(e.type) {
|
209
|
case ButtonPress:
|
210
|
XFreeFont(display, font_info);
|
211
|
XFreeGC(display, gc);
|
212
|
XCloseDisplay(display);
|
213
|
#ifdef _DEBUG
|
214
|
__BREAK__;
|
215
|
#endif
|
216
|
return;
|
217
|
case Expose:
|
218
|
int y = 20;
|
219
|
const char *b = text;
|
220
|
for(;;) {
|
221
|
const char *e = strchr(b, '\n');
|
222
|
if(!e) break;
|
223
|
XDrawString(display, win, gc, 20, y, b, e - b);
|
224
|
y += font_info->max_bounds.ascent + font_info->max_bounds.descent;
|
225
|
b = e + 1;
|
226
|
}
|
227
|
XDrawString(display, win, gc, 20, y, b, strlen(b));
|
228
|
break;
|
229
|
}
|
230
|
}
|
231
|
}
|
232
|
|
233
|
#ifdef _DEBUG
|
234
|
#define INI_PREFIX "DEBUG_"
|
235
|
#else
|
236
|
#define INI_PREFIX
|
237
|
#endif
|
238
|
|
239
|
int X11ErrorHandler(XDisplay *, XErrorEvent *error)
|
240
|
{
|
241
|
if(X11ErrorTrap || IsPanicMode()) return 0;
|
242
|
|
243
|
if(GetIniKey(INI_PREFIX "X11_ERRORS") != "1")
|
244
|
return 0;
|
245
|
|
246
|
static const char *request[] = {
|
247
|
"",
|
248
|
"X_CreateWindow",
|
249
|
"X_ChangeWindowAttributes",
|
250
|
"X_GetWindowAttributes",
|
251
|
"X_DestroyWindow",
|
252
|
"X_DestroySubwindows",
|
253
|
"X_ChangeSaveSet",
|
254
|
"X_ReparentWindow",
|
255
|
"X_MapWindow",
|
256
|
"X_MapSubwindows",
|
257
|
"X_UnmapWindow",
|
258
|
"X_UnmapSubwindows",
|
259
|
"X_ConfigureWindow",
|
260
|
"X_CirculateWindow",
|
261
|
"X_GetGeometry",
|
262
|
"X_QueryTree",
|
263
|
"X_InternAtom",
|
264
|
"X_GetAtomName",
|
265
|
"X_ChangeProperty",
|
266
|
"X_DeleteProperty",
|
267
|
"X_GetProperty",
|
268
|
"X_ListProperties",
|
269
|
"X_SetSelectionOwner",
|
270
|
"X_GetSelectionOwner",
|
271
|
"X_ConvertSelection",
|
272
|
"X_SendEvent",
|
273
|
"X_GrabPointer",
|
274
|
"X_UngrabPointer",
|
275
|
"X_GrabButton",
|
276
|
"X_UngrabButton",
|
277
|
"X_ChangeActivePointerGrab",
|
278
|
"X_GrabKeyboard",
|
279
|
"X_UngrabKeyboard",
|
280
|
"X_GrabKey",
|
281
|
"X_UngrabKey",
|
282
|
"X_AllowEvents",
|
283
|
"X_GrabServer",
|
284
|
"X_UngrabServer",
|
285
|
"X_QueryPointer",
|
286
|
"X_GetMotionEvents",
|
287
|
"X_TranslateCoords",
|
288
|
"X_WarpPointer",
|
289
|
"X_SetInputFocus",
|
290
|
"X_GetInputFocus",
|
291
|
"X_QueryKeymap",
|
292
|
"X_OpenFont",
|
293
|
"X_CloseFont",
|
294
|
"X_QueryFont",
|
295
|
"X_QueryTextExtents",
|
296
|
"X_ListFonts",
|
297
|
"X_ListFontsWithInfo",
|
298
|
"X_SetFontPath",
|
299
|
"X_GetFontPath",
|
300
|
"X_CreatePixmap",
|
301
|
"X_FreePixmap",
|
302
|
"X_CreateGC",
|
303
|
"X_ChangeGC",
|
304
|
"X_CopyGC",
|
305
|
"X_SetDashes",
|
306
|
"X_SetClipRectangles",
|
307
|
"X_FreeGC",
|
308
|
"X_ClearArea",
|
309
|
"X_CopyArea",
|
310
|
"X_CopyPlane",
|
311
|
"X_PolyPoint",
|
312
|
"X_PolyLine",
|
313
|
"X_PolySegment",
|
314
|
"X_PolyRectangle",
|
315
|
"X_PolyArc",
|
316
|
"X_FillPoly",
|
317
|
"X_PolyFillRectangle",
|
318
|
"X_PolyFillArc",
|
319
|
"X_PutImage",
|
320
|
"X_GetImage",
|
321
|
"X_PolyText8",
|
322
|
"X_PolyText16",
|
323
|
"X_ImageText8",
|
324
|
"X_ImageText16",
|
325
|
"X_CreateColormap",
|
326
|
"X_FreeColormap",
|
327
|
"X_CopyColormapAndFree",
|
328
|
"X_InstallColormap",
|
329
|
"X_UninstallColormap",
|
330
|
"X_ListInstalledColormaps",
|
331
|
"X_AllocColor",
|
332
|
"X_AllocNamedColor",
|
333
|
"X_AllocColorCells",
|
334
|
"X_AllocColorPlanes",
|
335
|
"X_FreeColors",
|
336
|
"X_StoreColors",
|
337
|
"X_StoreNamedColor",
|
338
|
"X_QueryColors",
|
339
|
"X_LookupColor",
|
340
|
"X_CreateCursor",
|
341
|
"X_CreateGlyphCursor",
|
342
|
"X_FreeCursor",
|
343
|
"X_RecolorCursor",
|
344
|
"X_QueryBestSize",
|
345
|
"X_QueryExtension",
|
346
|
"X_ListExtensions",
|
347
|
"X_ChangeKeyboardMapping",
|
348
|
"X_GetKeyboardMapping",
|
349
|
"X_ChangeKeyboardControl",
|
350
|
"X_GetKeyboardControl",
|
351
|
"X_Bell",
|
352
|
"X_ChangePointerControl",
|
353
|
"X_GetPointerControl",
|
354
|
"X_SetScreenSaver",
|
355
|
"X_GetScreenSaver",
|
356
|
"X_ChangeHosts",
|
357
|
"X_ListHosts",
|
358
|
"X_SetAccessControl",
|
359
|
"X_SetCloseDownMode",
|
360
|
"X_KillClient",
|
361
|
"X_RotateProperties",
|
362
|
"X_ForceScreenSaver",
|
363
|
"X_SetPointerMapping",
|
364
|
"X_GetPointerMapping",
|
365
|
"X_SetModifierMapping",
|
366
|
"X_GetModifierMapping",
|
367
|
"X_NoOperation",
|
368
|
};
|
369
|
|
370
|
char h[512];
|
371
|
XGetErrorText(Xdisplay, error->error_code, h, 512);
|
372
|
String e;
|
373
|
e << "X Error: " << h;
|
374
|
if(error->request_code < __countof(request))
|
375
|
e << "\nrequest: " << request[error->request_code];
|
376
|
e << "\nresource id: " << (int)error->resourceid << " = " << Format("%0X", (int)error->resourceid);
|
377
|
|
378
|
RLOG(e);
|
379
|
puts(e);
|
380
|
|
381
|
Panic(e);
|
382
|
|
383
|
return 0;
|
384
|
}
|
385
|
|
386
|
void SetX11ErrorHandler()
|
387
|
{
|
388
|
XSetErrorHandler(X11ErrorHandler);
|
389
|
}
|
390
|
|
391
|
INITBLOCK {
|
392
|
InstallPanicMessageBox(sPanicMessageBox);
|
393
|
}
|
394
|
|
395
|
void Ctrl::InstallPanicBox()
|
396
|
{
|
397
|
InstallPanicMessageBox(sPanicMessageBox);
|
398
|
}
|
399
|
|
400
|
void Ctrl::InitX11(const char *display)
|
401
|
{
|
402
|
GuiLock __;
|
403
|
|
404
|
XInitThreads();
|
405
|
|
406
|
InstallPanicMessageBox(sPanicMessageBox);
|
407
|
|
408
|
InitX11Draw(display);
|
409
|
InitTimer();
|
410
|
byte dummy[5];
|
411
|
Xbuttons = XGetPointerMapping(Xdisplay, dummy, 5);
|
412
|
|
413
|
Xeventtime = CurrentTime;
|
414
|
SetX11ErrorHandler();
|
415
|
if(GetIniKey(INI_PREFIX "X11_SYNCHRONIZE") == "1")
|
416
|
XSynchronize(Xdisplay, 1);
|
417
|
Vector<int> nets = GetPropertyInts(Xroot, XAtom("_NET_SUPPORTED"));
|
418
|
for(int i = 0; i < nets.GetCount(); i++)
|
419
|
_NET_Supported().Add(nets[i]);
|
420
|
|
421
|
SetStdFont(Arial(12));
|
422
|
|
423
|
ReSkin();
|
424
|
|
425
|
GUI_GlobalStyle_Write(GUISTYLE_XP);
|
426
|
GUI_DragFullWindow_Write(1);
|
427
|
GUI_PopUpEffect_Write(IsCompositedGui() ? GUIEFFECT_NONE : GUIEFFECT_SLIDE);
|
428
|
GUI_DropShadows_Write(1);
|
429
|
GUI_AltAccessKeys_Write(1);
|
430
|
GUI_AKD_Conservative_Write(0);
|
431
|
|
432
|
setlocale(LC_ALL, "en_US.utf8");
|
433
|
if(XSupportsLocale()) {
|
434
|
XSetLocaleModifiers("");
|
435
|
xim = XOpenIM(Xdisplay, NULL, NULL, NULL);
|
436
|
}
|
437
|
else {
|
438
|
xim = NULL;
|
439
|
LOG("IM unsupported!");
|
440
|
}
|
441
|
|
442
|
Csizeinit();
|
443
|
}
|
444
|
|
445
|
void Ctrl::ExitX11()
|
446
|
{
|
447
|
GuiLock __;
|
448
|
|
449
|
|
450
|
TopWindow::ShutdownWindows();
|
451
|
CloseTopCtrls();
|
452
|
for(int i = 0; i < hotkey.GetCount(); i++)
|
453
|
UnregisterSystemHotKey(i);
|
454
|
if(xim)
|
455
|
XCloseIM(xim);
|
456
|
}
|
457
|
|
458
|
Vector<Rect> FindScreensResolutions()
|
459
|
{
|
460
|
Vector<Rect> screensResolutions;
|
461
|
int event, error;
|
462
|
|
463
|
if(XineramaQueryExtension(Xdisplay, &event, &error)) {
|
464
|
if(XineramaIsActive(Xdisplay)) {
|
465
|
int screensNumber = 0;
|
466
|
XineramaScreenInfo* info = XineramaQueryScreens(Xdisplay, &screensNumber);
|
467
|
for(int i = 0; i < screensNumber; i++)
|
468
|
screensResolutions.Add(Rect(info[i].x_org, info[i].y_org, info[i].x_org + info[i].width, info[i].y_org + info[i].height));
|
469
|
XFree(info);
|
470
|
}
|
471
|
}
|
472
|
return screensResolutions;
|
473
|
}
|
474
|
|
475
|
Vector<Rect> FindScreensStruts()
|
476
|
{
|
477
|
Vector<Rect> struts;
|
478
|
|
479
|
Vector<int> clients = GetPropertyInts(Xroot, XAtom("_NET_CLIENT_LIST"));
|
480
|
for (int i = 0; i < clients.GetCount(); i++) {
|
481
|
Vector<int> strut = GetPropertyInts(clients[i], XAtom("_NET_WM_STRUT"));
|
482
|
if(strut.GetCount() == 4)
|
483
|
struts.Add(Rect(strut[0], strut[2], strut[1], strut[3]));
|
484
|
}
|
485
|
return struts;
|
486
|
}
|
487
|
|
488
|
Rect Ctrl::GetDefaultWindowRect()
|
489
|
{
|
490
|
GuiLock __;
|
491
|
static int width = 0;
|
492
|
static int height = 0;
|
493
|
static int left = 0;
|
494
|
static int top = 0;
|
495
|
if (width == 0 && height == 0) {
|
496
|
Vector<Rect> screens = FindScreensResolutions();
|
497
|
if(screens.GetCount()) {
|
498
|
width = screens[0].Width();
|
499
|
height = screens[0].Height();
|
500
|
left = screens[0].left;
|
501
|
top = screens[0].top;
|
502
|
}
|
503
|
else {
|
504
|
width = Xwidth;
|
505
|
height = Xheight;
|
506
|
}
|
507
|
}
|
508
|
|
509
|
static int pos = min(width / 10, 50);
|
510
|
pos += 10;
|
511
|
int cx = width * 2 / 3;
|
512
|
int cy = height * 2 / 3;
|
513
|
if(pos + cx + 50 > width || pos + cy + 50 > height)
|
514
|
pos = 0;
|
515
|
return RectC(left + pos + 20, top + pos + 20, cx, cy);
|
516
|
}
|
517
|
|
518
|
void Ctrl::GetWorkArea(Array<Rect>& out)
|
519
|
{
|
520
|
Vector<Rect> workAreas = FindScreensResolutions();
|
521
|
Vector<Rect> struts = FindScreensStruts();
|
522
|
for (int i = 0; i < workAreas.GetCount(); i++) {
|
523
|
if (i < struts.GetCount()) {
|
524
|
workAreas[i].left += struts[i].left;
|
525
|
workAreas[i].right -= struts[i].right;
|
526
|
workAreas[i].top += struts[i].top;
|
527
|
workAreas[i].bottom -= struts[i].bottom;
|
528
|
}
|
529
|
out.Add(workAreas[i]);
|
530
|
}
|
531
|
if (out.IsEmpty())
|
532
|
out.Add(GetPrimaryWorkArea());
|
533
|
}
|
534
|
|
535
|
Rect Ctrl::GetWorkArea() const
|
536
|
{
|
537
|
GuiLock __;
|
538
|
static Array<Rect> rc;
|
539
|
if (rc.IsEmpty())
|
540
|
GetWorkArea(rc);
|
541
|
Point pt = GetMousePos();
|
542
|
for (int i = 0; i < rc.GetCount(); i++)
|
543
|
if(rc[i].Contains(pt))
|
544
|
return rc[i];
|
545
|
return GetPrimaryWorkArea();
|
546
|
}
|
547
|
|
548
|
Rect Ctrl::GetWorkArea(Point pt)
|
549
|
{
|
550
|
static Array<Rect> rc;
|
551
|
if (rc.IsEmpty())
|
552
|
GetWorkArea(rc);
|
553
|
for(int i = 0; i < rc.GetCount(); i++)
|
554
|
if(rc[i].Contains(pt))
|
555
|
return rc[i];
|
556
|
return GetPrimaryWorkArea();
|
557
|
}
|
558
|
|
559
|
Rect Ctrl::GetVirtualWorkArea()
|
560
|
{
|
561
|
GuiLock __;
|
562
|
static Rect r;
|
563
|
if(r.right == 0) {
|
564
|
Vector<int> x = GetPropertyInts(Xroot, XAtom("_NET_WORKAREA"));
|
565
|
if(x.GetCount())
|
566
|
r = RectC(x[0], x[1], x[2], x[3]);
|
567
|
else
|
568
|
r = RectC(0, 0, Xwidth, Xheight);
|
569
|
}
|
570
|
return r;
|
571
|
}
|
572
|
|
573
|
Rect Ctrl::GetVirtualScreenArea()
|
574
|
{
|
575
|
return RectC(0, 0, Xwidth, Xheight);
|
576
|
}
|
577
|
|
578
|
Rect Ctrl::GetPrimaryWorkArea()
|
579
|
{
|
580
|
GuiLock __;
|
581
|
static Rect r;
|
582
|
if(r.right == 0) {
|
583
|
Array<Rect> rc;
|
584
|
GetWorkArea(rc);
|
585
|
rc.GetCount() ? r = rc[0] : r = GetVirtualScreenArea();
|
586
|
}
|
587
|
return r;
|
588
|
}
|
589
|
|
590
|
Rect Ctrl::GetPrimaryScreenArea()
|
591
|
{
|
592
|
GuiLock __;
|
593
|
static Rect r;
|
594
|
if(r.right == 0) {
|
595
|
Vector<Rect> screens = FindScreensResolutions();
|
596
|
screens.GetCount() ? r = screens[0] : r = GetVirtualScreenArea();
|
597
|
}
|
598
|
return r;
|
599
|
}
|
600
|
|
601
|
int Ctrl::GetKbdDelay()
|
602
|
{
|
603
|
return 250;
|
604
|
}
|
605
|
|
606
|
int Ctrl::GetKbdSpeed()
|
607
|
{
|
608
|
return 25;
|
609
|
}
|
610
|
|
611
|
|
612
|
#ifdef _DEBUG
|
613
|
extern bool __X11_Grabbing;
|
614
|
void _DBG_Ungrab(void) {
|
615
|
if(__X11_Grabbing)
|
616
|
{
|
617
|
XUngrabPointer(Xdisplay, CurrentTime);
|
618
|
XUngrabKeyboard(Xdisplay, CurrentTime);
|
619
|
XFlush(Xdisplay);
|
620
|
__X11_Grabbing = false;
|
621
|
}
|
622
|
}
|
623
|
#endif
|
624
|
|
625
|
END_UPP_NAMESPACE
|
626
|
|
627
|
#endif
|