x11windowdisplayi.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. Constructor TX11WindowDisplay.Create(ADisplay : PDisplay; AScreen : Integer; Const AFlags : TX11Flags);
  2. Begin
  3. Inherited;
  4. FFocus := True;
  5. FX11InvisibleCursor := None;
  6. FCursorVisible := True;
  7. End;
  8. Destructor TX11WindowDisplay.Destroy;
  9. Begin
  10. Close;
  11. Inherited Destroy;
  12. End;
  13. Procedure TX11WindowDisplay.Open(ATitle : AnsiString; AWidth, AHeight : Integer; Const AFormat : TPTCFormat);
  14. Var
  15. tmpFormat : TPTCFormat;
  16. xgcv : TXGCValues;
  17. textprop : TXTextProperty;
  18. e : TXEvent;
  19. found : Boolean;
  20. attr : TXSetWindowAttributes;
  21. size_hints : PXSizeHints;
  22. tmpArea : TPTCArea;
  23. tmppchar : PChar;
  24. tmpArrayOfCLong : Array[1..1] Of clong;
  25. tmpPixmap : TPixmap;
  26. BlackColor : TXColor;
  27. BlankCursorData : Array[1..8] Of Byte = (0, 0, 0, 0, 0, 0, 0, 0);
  28. Begin
  29. FHeight := AHeight;
  30. FWidth := AWidth;
  31. FDestX := 0;
  32. FDestY := 0;
  33. FFullScreen := PTC_X11_FULLSCREEN In FFlags;
  34. FFocus := True;
  35. FPreviousMousePositionSaved := False;
  36. FillChar(BlackColor, SizeOf(BlackColor), 0);
  37. BlackColor.red := 0;
  38. BlackColor.green := 0;
  39. BlackColor.blue := 0;
  40. { Create the mode switcher object }
  41. If (FModeSwitcher = Nil) And FFullScreen Then
  42. FModeSwitcher := CreateModeSwitcher;
  43. { Create the invisible cursor }
  44. tmpPixmap := XCreateBitmapFromData(FDisplay, RootWindow(FDisplay, FScreen), @BlankCursorData, 8, 8);
  45. Try
  46. FX11InvisibleCursor := XCreatePixmapCursor(FDisplay, tmpPixmap, tmpPixmap, @BlackColor, @BlackColor, 0, 0);
  47. Finally
  48. If tmpPixmap <> None Then
  49. XFreePixmap(FDisplay, tmpPixmap);
  50. End;
  51. { Check if we have that colour depth available.. Easy as there is no
  52. format conversion yet }
  53. tmpFormat := Nil;
  54. Try
  55. tmpFormat := GetX11Format(AFormat);
  56. FFormat.Assign(tmpFormat);
  57. Finally
  58. tmpFormat.Free;
  59. End;
  60. tmpFormat := Nil;
  61. { Create a window }
  62. FWindow := XCreateSimpleWindow(FDisplay, RootWindow(FDisplay, FScreen), 0, 0,
  63. AWidth, AHeight, 0, BlackPixel(FDisplay, FScreen),
  64. BlackPixel(FDisplay, FScreen));
  65. { Register the delete atom }
  66. FAtomClose := XInternAtom(FDisplay, 'WM_DELETE_WINDOW', False);
  67. X11Check(XSetWMProtocols(FDisplay, FWindow, @FAtomClose, 1), 'XSetWMProtocols');
  68. { Get graphics context }
  69. xgcv.graphics_exposures := False;
  70. FGC := XCreateGC(FDisplay, FWindow, GCGraphicsExposures, @xgcv);
  71. If FGC = Nil Then
  72. Raise TPTCError.Create('can''t create graphics context');
  73. { Set window title }
  74. tmppchar := PChar(ATitle);
  75. X11Check(XStringListToTextProperty(@tmppchar, 1, @textprop), 'XStringListToTextProperty');
  76. Try
  77. XSetWMName(FDisplay, FWindow, @textprop);
  78. XFlush(FDisplay);
  79. Finally
  80. XFree(textprop.value);
  81. End;
  82. { Set normal hints }
  83. size_hints := XAllocSizeHints;
  84. Try
  85. size_hints^.flags := PMinSize Or PBaseSize;
  86. size_hints^.min_width := AWidth;
  87. size_hints^.min_height := AHeight;
  88. size_hints^.base_width := AWidth;
  89. size_hints^.base_height := AHeight;
  90. If FFullScreen Then
  91. Begin
  92. size_hints^.flags := size_hints^.flags Or PWinGravity;
  93. size_hints^.win_gravity := StaticGravity;
  94. End
  95. Else
  96. Begin
  97. { not fullscreen - add maxsize limit=minsize, i.e. make window not resizable }
  98. size_hints^.flags := size_hints^.flags Or PMaxSize;
  99. size_hints^.max_width := AWidth;
  100. size_hints^.max_height := AHeight;
  101. End;
  102. XSetWMNormalHints(FDisplay, FWindow, size_hints);
  103. XFlush(FDisplay);
  104. Finally
  105. XFree(size_hints);
  106. End;
  107. { Set the _NET_WM_STATE property }
  108. If FFullScreen Then
  109. Begin
  110. tmpArrayOfCLong[1] := XInternAtom(FDisplay, '_NET_WM_STATE_FULLSCREEN', False);
  111. XChangeProperty(FDisplay, FWindow,
  112. XInternAtom(FDisplay, '_NET_WM_STATE', False),
  113. XA_ATOM,
  114. 32, PropModeReplace, @tmpArrayOfCLong, 1);
  115. End;
  116. { Map the window and wait for success }
  117. XSelectInput(FDisplay, FWindow, StructureNotifyMask);
  118. XMapRaised(FDisplay, FWindow);
  119. Repeat
  120. XNextEvent(FDisplay, @e);
  121. If e._type = MapNotify Then
  122. Break;
  123. Until False;
  124. { Get keyboard input and sync }
  125. XSelectInput(FDisplay, FWindow, KeyPressMask Or KeyReleaseMask Or
  126. StructureNotifyMask Or FocusChangeMask Or
  127. ButtonPressMask Or ButtonReleaseMask Or
  128. PointerMotionMask);
  129. XSync(FDisplay, False);
  130. { Create XImage using factory method }
  131. FPrimary := CreateImage(FDisplay, FScreen, FWidth, FHeight, FFormat);
  132. found := False;
  133. Repeat
  134. { Stupid loop. The key }
  135. { events were causing }
  136. { problems.. }
  137. found := XCheckMaskEvent(FDisplay, KeyPressMask Or KeyReleaseMask, @e);
  138. Until Not found;
  139. attr.backing_store := Always;
  140. XChangeWindowAttributes(FDisplay, FWindow, CWBackingStore, @attr);
  141. { Set clipping area }
  142. tmpArea := TPTCArea.Create(0, 0, FWidth, FHeight);
  143. Try
  144. FClip.Assign(tmpArea);
  145. Finally
  146. tmpArea.Free;
  147. End;
  148. { Installs the right colour map for 8 bit modes }
  149. CreateColormap;
  150. If FFullScreen Then
  151. EnterFullScreen;
  152. End;
  153. Procedure TX11WindowDisplay.Open(AWindow : TWindow; Const AFormat : TPTCFormat);
  154. Begin
  155. End;
  156. Procedure TX11WindowDisplay.Open(AWindow : TWindow; Const AFormat : TPTCFormat; AX, AY, AWidth, AHeight : Integer);
  157. Begin
  158. End;
  159. Procedure TX11WindowDisplay.Close;
  160. Begin
  161. FreeAndNil(FModeSwitcher);
  162. {pthreads?!}
  163. If FCMap <> 0 Then
  164. Begin
  165. XFreeColormap(FDisplay, FCMap);
  166. FCMap := 0;
  167. End;
  168. { Destroy XImage and buffer }
  169. FreeAndNil(FPrimary);
  170. FreeMemAndNil(FColours);
  171. { Hide and destroy window }
  172. If (FWindow <> 0) And (Not (PTC_X11_LEAVE_WINDOW In FFlags)) Then
  173. Begin
  174. XUnmapWindow(FDisplay, FWindow);
  175. XSync(FDisplay, False);
  176. XDestroyWindow(FDisplay, FWindow);
  177. End;
  178. { Free the invisible cursor }
  179. If FX11InvisibleCursor <> None Then
  180. Begin
  181. XFreeCursor(FDisplay, FX11InvisibleCursor);
  182. FX11InvisibleCursor := None;
  183. End;
  184. End;
  185. Procedure TX11WindowDisplay.internal_ShowCursor(AVisible : Boolean);
  186. Var
  187. attr : TXSetWindowAttributes;
  188. Begin
  189. If AVisible Then
  190. attr.cursor := None { Use the normal cursor }
  191. Else
  192. attr.cursor := FX11InvisibleCursor; { Set the invisible cursor }
  193. XChangeWindowAttributes(FDisplay, FWindow, CWCursor, @attr);
  194. End;
  195. Procedure TX11WindowDisplay.SetCursor(AVisible : Boolean);
  196. Begin
  197. FCursorVisible := AVisible;
  198. If FFocus Then
  199. internal_ShowCursor(FCursorVisible);
  200. End;
  201. Procedure TX11WindowDisplay.EnterFullScreen;
  202. Begin
  203. { Try to switch mode }
  204. If Assigned(FModeSwitcher) Then
  205. FModeSwitcher.SetBestMode(FWidth, FHeight);
  206. XSync(FDisplay, False);
  207. { Center the image }
  208. FDestX := FModeSwitcher.Width Div 2 - FWidth Div 2;
  209. FDestY := FModeSwitcher.Height Div 2 - FHeight Div 2;
  210. End;
  211. Procedure TX11WindowDisplay.LeaveFullScreen;
  212. Begin
  213. { Restore previous mode }
  214. If Assigned(FModeSwitcher) Then
  215. FModeSwitcher.RestorePreviousMode;
  216. XSync(FDisplay, False);
  217. End;
  218. Procedure TX11WindowDisplay.HandleChangeFocus(ANewFocus : Boolean);
  219. Begin
  220. { No change? }
  221. If ANewFocus = FFocus Then
  222. Exit;
  223. FFocus := ANewFocus;
  224. If FFocus Then
  225. Begin
  226. { focus in }
  227. If FFullScreen Then
  228. EnterFullScreen;
  229. internal_ShowCursor(FCursorVisible);
  230. End
  231. Else
  232. Begin
  233. { focus out }
  234. If FFullScreen Then
  235. LeaveFullScreen;
  236. internal_ShowCursor(True);
  237. End;
  238. XSync(FDisplay, False);
  239. End;
  240. Procedure TX11WindowDisplay.HandleEvents;
  241. Var
  242. e : TXEvent;
  243. NewFocus : Boolean;
  244. NewFocusSpecified : Boolean;
  245. Function UsefulEventsPending : Boolean;
  246. Var
  247. tmpEvent : TXEvent;
  248. Begin
  249. If XCheckTypedEvent(FDisplay, ClientMessage, @tmpEvent) Then
  250. Begin
  251. Result := True;
  252. XPutBackEvent(FDisplay, @tmpEvent);
  253. Exit;
  254. End;
  255. If XCheckMaskEvent(FDisplay, FocusChangeMask Or
  256. KeyPressMask Or KeyReleaseMask Or
  257. ButtonPressMask Or ButtonReleaseMask Or
  258. PointerMotionMask Or ExposureMask, @tmpEvent) Then
  259. Begin
  260. Result := True;
  261. XPutBackEvent(FDisplay, @tmpEvent);
  262. Exit;
  263. End;
  264. Result := False;
  265. End;
  266. Procedure HandleKeyEvent;
  267. Var
  268. sym : TKeySym;
  269. sym_modded : TKeySym; { modifiers like shift are taken into account here }
  270. press : Boolean;
  271. alt, shift, ctrl : Boolean;
  272. uni : Integer;
  273. key : TPTCKeyEvent;
  274. buf : Array[1..16] Of Char;
  275. Begin
  276. sym := XLookupKeySym(@e.xkey, 0);
  277. XLookupString(@e.xkey, @buf, SizeOf(buf), @sym_modded, Nil);
  278. uni := X11ConvertKeySymToUnicode(sym_modded);
  279. alt := (e.xkey.state And Mod1Mask) <> 0;
  280. shift := (e.xkey.state And ShiftMask) <> 0;
  281. ctrl := (e.xkey.state And ControlMask) <> 0;
  282. If e._type = KeyPress Then
  283. press := True
  284. Else
  285. press := False;
  286. key := Nil;
  287. Case sym Shr 8 Of
  288. 0 : key := TPTCKeyEvent.Create(FNormalKeys[sym And $FF], uni, alt, shift, ctrl, press);
  289. $FF : key := TPTCKeyEvent.Create(FFunctionKeys[sym And $FF], uni, alt, shift, ctrl, press);
  290. Else
  291. key := TPTCKeyEvent.Create;
  292. End;
  293. FEventQueue.AddEvent(key);
  294. End;
  295. Procedure HandleMouseEvent;
  296. Var
  297. x, y : cint;
  298. state : cuint;
  299. PTCMouseButtonState : TPTCMouseButtonState;
  300. button : TPTCMouseButton;
  301. before, after : Boolean;
  302. cstate : TPTCMouseButtonState;
  303. Begin
  304. Case e._type Of
  305. MotionNotify : Begin
  306. x := e.xmotion.x;
  307. y := e.xmotion.y;
  308. state := e.xmotion.state;
  309. End;
  310. ButtonPress, ButtonRelease : Begin
  311. x := e.xbutton.x;
  312. y := e.xbutton.y;
  313. state := e.xbutton.state;
  314. If e._type = ButtonPress Then
  315. Begin
  316. Case e.xbutton.button Of
  317. Button1 : state := state Or Button1Mask;
  318. Button2 : state := state Or Button2Mask;
  319. Button3 : state := state Or Button3Mask;
  320. Button4 : state := state Or Button4Mask;
  321. Button5 : state := state Or Button5Mask;
  322. End;
  323. End
  324. Else
  325. Begin
  326. Case e.xbutton.button Of
  327. Button1 : state := state And (Not Button1Mask);
  328. Button2 : state := state And (Not Button2Mask);
  329. Button3 : state := state And (Not Button3Mask);
  330. Button4 : state := state And (Not Button4Mask);
  331. Button5 : state := state And (Not Button5Mask);
  332. End;
  333. End;
  334. End;
  335. Else
  336. Raise TPTCError.Create('Internal Error');
  337. End;
  338. If (state And Button1Mask) = 0 Then
  339. PTCMouseButtonState := []
  340. Else
  341. PTCMouseButtonState := [PTCMouseButton1];
  342. If (state And Button2Mask) <> 0 Then
  343. PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton2];
  344. If (state And Button3Mask) <> 0 Then
  345. PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton3];
  346. If (state And Button4Mask) <> 0 Then
  347. PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton4];
  348. If (state And Button5Mask) <> 0 Then
  349. PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton5];
  350. If (x >= 0) And (x < FWidth) And (y >= 0) And (y < FHeight) Then
  351. Begin
  352. If Not FPreviousMousePositionSaved Then
  353. Begin
  354. FPreviousMouseX := x; { first DeltaX will be 0 }
  355. FPreviousMouseY := y; { first DeltaY will be 0 }
  356. FPreviousMouseButtonState := [];
  357. End;
  358. { movement? }
  359. If (x <> FPreviousMouseX) Or (y <> FPreviousMouseY) Then
  360. FEventQueue.AddEvent(TPTCMouseEvent.Create(x, y, x - FPreviousMouseX, y - FPreviousMouseY, FPreviousMouseButtonState));
  361. { button presses/releases? }
  362. cstate := FPreviousMouseButtonState;
  363. For button := Low(button) To High(button) Do
  364. Begin
  365. before := button In FPreviousMouseButtonState;
  366. after := button In PTCMouseButtonState;
  367. If after And (Not before) Then
  368. Begin
  369. { button was pressed }
  370. cstate := cstate + [button];
  371. FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(x, y, 0, 0, cstate, True, button));
  372. End
  373. Else
  374. If before And (Not after) Then
  375. Begin
  376. { button was released }
  377. cstate := cstate - [button];
  378. FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(x, y, 0, 0, cstate, False, button));
  379. End;
  380. End;
  381. FPreviousMouseX := x;
  382. FPreviousMouseY := y;
  383. FPreviousMouseButtonState := PTCMouseButtonState;
  384. FPreviousMousePositionSaved := True;
  385. End;
  386. End;
  387. Begin
  388. NewFocusSpecified := False;
  389. While UsefulEventsPending Do
  390. Begin
  391. XNextEvent(FDisplay, @e);
  392. Case e._type Of
  393. FocusIn : Begin
  394. NewFocus := True;
  395. NewFocusSpecified := True;
  396. End;
  397. FocusOut : Begin
  398. NewFocus := False;
  399. NewFocusSpecified := True;
  400. End;
  401. ClientMessage : Begin
  402. If (e.xclient.format = 32) And (TAtom(e.xclient.data.l[0]) = FAtomClose) Then
  403. Halt(0);
  404. End;
  405. Expose : Begin
  406. {...}
  407. End;
  408. KeyPress, KeyRelease : HandleKeyEvent;
  409. ButtonPress, ButtonRelease, MotionNotify : HandleMouseEvent;
  410. End;
  411. End;
  412. If NewFocusSpecified Then
  413. HandleChangeFocus(NewFocus);
  414. End;
  415. Procedure TX11WindowDisplay.Update;
  416. Begin
  417. FPrimary.Put(FWindow, FGC, FDestX, FDestY);
  418. HandleEvents;
  419. End;
  420. Procedure TX11WindowDisplay.Update(Const AArea : TPTCArea);
  421. Var
  422. updatearea : TPTCArea;
  423. tmparea : TPTCArea;
  424. Begin
  425. tmparea := TPTCArea.Create(0, 0, FWidth, FHeight);
  426. Try
  427. updatearea := TPTCClipper.Clip(tmparea, AArea);
  428. Try
  429. FPrimary.Put(FWindow, FGC, updatearea.Left, updatearea.Top,
  430. FDestX + updatearea.Left, FDestY + updatearea.Top,
  431. updatearea.Width, updatearea.Height);
  432. Finally
  433. updatearea.Free;
  434. End;
  435. Finally
  436. tmparea.Free;
  437. End;
  438. HandleEvents;
  439. End;
  440. Function TX11WindowDisplay.NextEvent(Var AEvent : TPTCEvent; AWait : Boolean; Const AEventMask : TPTCEventMask) : Boolean;
  441. Var
  442. tmpEvent : TXEvent;
  443. Begin
  444. FreeAndNil(AEvent);
  445. Repeat
  446. { process all events from the X queue and put them on our FEventQueue }
  447. HandleEvents;
  448. { try to find an event that matches the EventMask }
  449. AEvent := FEventQueue.NextEvent(AEventMask);
  450. If AWait And (AEvent = Nil) Then
  451. Begin
  452. { if the X event queue is empty, block until an event is received }
  453. XPeekEvent(FDisplay, @tmpEvent);
  454. End;
  455. Until (Not AWait) Or (AEvent <> Nil);
  456. Result := AEvent <> Nil;
  457. End;
  458. Function TX11WindowDisplay.PeekEvent(AWait : Boolean; Const AEventMask : TPTCEventMask) : TPTCEvent;
  459. Var
  460. tmpEvent : TXEvent;
  461. Begin
  462. Repeat
  463. { process all events from the X queue and put them on our FEventQueue }
  464. HandleEvents;
  465. { try to find an event that matches the EventMask }
  466. Result := FEventQueue.PeekEvent(AEventMask);
  467. If AWait And (Result = Nil) Then
  468. Begin
  469. { if the X event queue is empty, block until an event is received }
  470. XPeekEvent(FDisplay, @tmpEvent);
  471. End;
  472. Until (Not AWait) Or (Result <> Nil);
  473. End;
  474. Function TX11WindowDisplay.Lock : Pointer;
  475. Begin
  476. Result := FPrimary.Lock;
  477. End;
  478. Procedure TX11WindowDisplay.unlock;
  479. Begin
  480. End;
  481. Procedure TX11WindowDisplay.GetModes(Var AModes : TPTCModeDynArray);
  482. Var
  483. current_desktop_format, tmpfmt : TPTCFormat;
  484. Begin
  485. If FModeSwitcher = Nil Then
  486. FModeSwitcher := CreateModeSwitcher;
  487. current_desktop_format := Nil;
  488. tmpfmt := TPTCFormat.Create(8);
  489. Try
  490. current_desktop_format := GetX11Format(tmpfmt);
  491. FModeSwitcher.GetModes(AModes, current_desktop_format);
  492. Finally
  493. tmpfmt.Free;
  494. current_desktop_format.Free;
  495. End;
  496. End;
  497. Procedure TX11WindowDisplay.Palette(Const APalette : TPTCPalette);
  498. Var
  499. pal : PUint32;
  500. i : Integer;
  501. Begin
  502. pal := APalette.Data;
  503. If Not FFormat.Indexed Then
  504. Exit;
  505. For i := 0 To 255 Do
  506. Begin
  507. FColours[i].pixel := i;
  508. FColours[i].red := ((pal[i] Shr 16) And $FF) Shl 8;
  509. FColours[i].green := ((pal[i] Shr 8) And $FF) Shl 8;
  510. FColours[i].blue := (pal[i] And $FF) Shl 8;
  511. Byte(FColours[i].flags) := DoRed Or DoGreen Or DoBlue;
  512. End;
  513. XStoreColors(FDisplay, FCMap, FColours, 256);
  514. End;
  515. Function TX11WindowDisplay.GetPitch : Integer;
  516. Begin
  517. Result := FPrimary.pitch;
  518. End;
  519. Function TX11WindowDisplay.CreateImage(ADisplay : PDisplay; AScreen, AWidth, AHeight : Integer;
  520. AFormat : TPTCFormat) : TX11Image;
  521. Begin
  522. {$IFDEF ENABLE_X11_EXTENSION_XSHM}
  523. If (PTC_X11_TRY_XSHM In FFlags) And XShmQueryExtension(ADisplay) Then
  524. Begin
  525. Try
  526. LOG('trying to create a XShm image');
  527. Result := TX11ShmImage.Create(ADisplay, AScreen, AWidth, AHeight, AFormat);
  528. Exit;
  529. Except
  530. LOG('XShm failed');
  531. End;
  532. End;
  533. {$ENDIF ENABLE_X11_EXTENSION_XSHM}
  534. LOG('trying to create a normal image');
  535. Result := TX11NormalImage.Create(ADisplay, AScreen, AWidth, AHeight, AFormat);
  536. End;
  537. Function TX11WindowDisplay.CreateModeSwitcher : TX11Modes;
  538. Begin
  539. {$IFDEF ENABLE_X11_EXTENSION_XRANDR}
  540. If PTC_X11_TRY_XRANDR In FFlags Then
  541. Try
  542. LOG('trying to initialize the Xrandr mode switcher');
  543. Result := TX11ModesXrandr.Create(FDisplay, FScreen);
  544. Exit;
  545. Except
  546. LOG('Xrandr failed');
  547. End;
  548. {$ENDIF ENABLE_X11_EXTENSION_XRANDR}
  549. {$IFDEF ENABLE_X11_EXTENSION_XF86VIDMODE}
  550. If PTC_X11_TRY_XF86VIDMODE In FFlags Then
  551. Try
  552. LOG('trying to initialize the XF86VidMode mode switcher');
  553. Result := TX11ModesXF86VidMode.Create(FDisplay, FScreen);
  554. Exit;
  555. Except
  556. LOG('XF86VidMode failed');
  557. End;
  558. {$ENDIF ENABLE_X11_EXTENSION_XF86VIDMODE}
  559. LOG('creating the standard NoModeSwitching mode switcher');
  560. Result := TX11ModesNoModeSwitching.Create(FDisplay, FScreen);
  561. End;
  562. Function TX11WindowDisplay.GetX11Window : TWindow;
  563. Begin
  564. Result := FWindow;
  565. End;
  566. Function TX11WindowDisplay.GetX11GC : TGC;
  567. Begin
  568. Result := FGC;
  569. End;
  570. Function TX11WindowDisplay.IsFullScreen : Boolean;
  571. Begin
  572. Result := FFullScreen;
  573. End;
  574. Procedure TX11WindowDisplay.CreateColormap; { Register colour maps }
  575. Var
  576. i : Integer;
  577. r, g, b : Single;
  578. Begin
  579. If FFormat.Bits = 8 Then
  580. Begin
  581. FColours := GetMem(256 * SizeOf(TXColor));
  582. If FColours = Nil Then
  583. Raise TPTCError.Create('Cannot allocate colour map cells');
  584. FCMap := XCreateColormap(FDisplay, RootWindow(FDisplay, FScreen),
  585. DefaultVisual(FDisplay, FScreen), AllocAll);
  586. If FCMap = 0 Then
  587. Raise TPTCError.Create('Cannot create colour map');
  588. XInstallColormap(FDisplay, FCMap);
  589. XSetWindowColormap(FDisplay, FWindow, FCMap);
  590. End
  591. Else
  592. FCMap := 0;
  593. { Set 332 palette, for now }
  594. If (FFormat.Bits = 8) And FFormat.Direct Then
  595. Begin
  596. {Taken from PTC 0.72, i hope it's fine}
  597. For i := 0 To 255 Do
  598. Begin
  599. r := ((i And $E0) Shr 5) * 255 / 7;
  600. g := ((i And $1C) Shr 2) * 255 / 7;
  601. b := (i And $03) * 255 / 3;
  602. FColours[i].pixel := i;
  603. FColours[i].red := Round(r) Shl 8;
  604. FColours[i].green := Round(g) Shl 8;
  605. FColours[i].blue := Round(b) Shl 8;
  606. Byte(FColours[i].flags) := DoRed Or DoGreen Or DoBlue;
  607. End;
  608. XStoreColors(FDisplay, FCMap, FColours, 256);
  609. End;
  610. End;