window.inc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. {$IFDEF XStringListToTextProperty_notyetimplemented_in_xutil_pp}
  2. Function XStringListToTextProperty(list : PPChar; count : Integer;
  3. text_prop_return : PXTextProperty) : TStatus; CDecl; External;
  4. {$ENDIF}
  5. Constructor TX11WindowDisplay.Create;
  6. Begin
  7. m_has_shm := False;
  8. m_primary := Nil;
  9. m_window := 0;
  10. m_colours := Nil;
  11. m_keypressed := False;
  12. Inherited Create;
  13. // XSHM_LoadLibrary;
  14. {$IFDEF HAVE_X11_EXTENSIONS_XSHM}
  15. m_has_shm := True;
  16. {$ENDIF HAVE_X11_EXTENSIONS_XSHM}
  17. End;
  18. Destructor TX11WindowDisplay.Destroy;
  19. Begin
  20. close;
  21. // XSHM_UnloadLibrary;
  22. Inherited Destroy;
  23. End;
  24. Procedure TX11WindowDisplay.open(title : String; _width, _height : Integer; Const _format : TPTCFormat; disp : PDisplay; screen : Integer);
  25. Var
  26. tmpFormat : TPTCFormat;
  27. xgcv : TXGCValues;
  28. textprop : TXTextProperty;
  29. e : TXEvent;
  30. found : Boolean;
  31. attr : TXSetWindowAttributes;
  32. size_hints : PXSizeHints;
  33. tmpArea : TPTCArea;
  34. tmppchar : PChar;
  35. Begin
  36. m_disp := disp;
  37. m_screen := DefaultScreen(disp);
  38. m_height := _height;
  39. m_width := _width;
  40. m_destx := 0;
  41. m_desty := 0;
  42. { Check if we have that colour depth available.. Easy as there is no
  43. format conversion yet }
  44. tmpFormat := Nil;
  45. Try
  46. tmpFormat := getFormat(_format);
  47. m_format.ASSign(tmpFormat);
  48. Finally
  49. tmpFormat.Free;
  50. End;
  51. tmpFormat := Nil;
  52. { Create a window }
  53. m_window := XCreateSimpleWindow(m_disp, DefaultRootWindow(m_disp), 0, 0,
  54. _width, _height, 0, BlackPixel(m_disp, DefaultScreen(m_disp)),
  55. BlackPixel(m_disp, DefaultScreen(m_disp)));
  56. { Register the delete atom }
  57. m_atom_close := XInternAtom(m_disp, 'WM_DELETE_WINDOW', False);
  58. X11Check(XSetWMProtocols(m_disp, m_window, @m_atom_close, 1), 'XSetWMProtocols');
  59. { Get graphics context }
  60. xgcv.graphics_exposures := False;
  61. m_gc := XCreateGC(m_disp, m_window, GCGraphicsExposures, @xgcv);
  62. If m_gc = Nil Then
  63. Raise TPTCError.Create('can''t create graphics context');
  64. { Set window title }
  65. tmppchar := PChar(title);
  66. X11Check(XStringListToTextProperty(@tmppchar, 1, @textprop), 'XStringListToTextProperty');
  67. Try
  68. XSetWMName(m_disp, m_window, @textprop);
  69. XFlush(m_disp);
  70. Finally
  71. XFree(textprop.value);
  72. End;
  73. { Set normal hints }
  74. size_hints := XAllocSizeHints;
  75. Try
  76. size_hints^.flags := PBaseSize;
  77. size_hints^.base_width := _width;
  78. size_hints^.base_height := _height;
  79. XSetWMNormalHints(m_disp, m_window, size_hints);
  80. XFlush(m_disp);
  81. Finally
  82. XFree(size_hints);
  83. End;
  84. { Map the window and wait for success }
  85. XSelectInput(m_disp, m_window, StructureNotifyMask);
  86. XMapRaised(m_disp, m_window);
  87. Repeat
  88. XNextEvent(disp, @e);
  89. If e._type = MapNotify Then
  90. Break;
  91. Until False;
  92. { Get keyboard input and sync }
  93. XSelectInput(m_disp, m_window, KeyPressMask Or KeyReleaseMask Or
  94. StructureNotifyMask Or
  95. ButtonPressMask Or ButtonReleaseMask Or
  96. PointerMotionMask);
  97. XSync(m_disp, False);
  98. { Create XImage using factory method }
  99. m_primary := createImage(m_disp, m_screen, m_width, m_height, m_format);
  100. found := False;
  101. Repeat
  102. { Stupid loop. The key }
  103. { events were causing }
  104. { problems.. }
  105. found := XCheckMaskEvent(m_disp, KeyPressMask Or KeyReleaseMask, @e);
  106. Until Not found;
  107. attr.backing_store := Always;
  108. XChangeWindowAttributes(m_disp, m_window, CWBackingStore, @attr);
  109. { Set clipping area }
  110. tmpArea := TPTCArea.Create(0, 0, m_width, m_height);
  111. Try
  112. m_clip.ASSign(tmpArea);
  113. Finally
  114. tmpArea.Free;
  115. End;
  116. { Installs the right colour map for 8 bit modes }
  117. createColormap;
  118. {ifdef PTHREADS...}
  119. End;
  120. Procedure TX11WindowDisplay.open(disp : PDisplay; screen : Integer; w : TWindow; Const _format : TPTCFormat);
  121. Begin
  122. End;
  123. Procedure TX11WindowDisplay.open(disp : PDisplay; screen : Integer; _window : TWindow; Const _format : TPTCFormat; x, y, w, h : Integer);
  124. Begin
  125. End;
  126. Procedure TX11WindowDisplay.close;
  127. Begin
  128. {pthreads?!}
  129. If m_cmap <> 0 Then
  130. Begin
  131. XFreeColormap(m_disp, m_cmap);
  132. m_cmap := 0;
  133. End;
  134. { Destroy XImage and buffer }
  135. FreeAndNil(m_primary);
  136. FreeMemAndNil(m_colours);
  137. { Hide and destroy window }
  138. If (m_window <> 0) And ((m_flags And PTC_X11_LEAVE_WINDOW) = 0) Then
  139. Begin
  140. XUnmapWindow(m_disp, m_window);
  141. XSync(m_disp, False);
  142. XDestroyWindow(m_disp, m_window);
  143. End;
  144. End;
  145. Procedure TX11WindowDisplay.update;
  146. Var
  147. e : TXEvent;
  148. Begin
  149. m_primary.put(m_window, m_gc, m_destx, m_desty);
  150. {ifndef pthreads}
  151. If XCheckTypedEvent(m_disp, ClientMessage, @e) Then
  152. Begin
  153. If (e.xclient.format = 32) And (TAtom(e.xclient.data.l[0]) = m_atom_close) Then
  154. Halt(0);
  155. End;
  156. {endif}
  157. End;
  158. Procedure TX11WindowDisplay.update(Const _area : TPTCArea);
  159. Var
  160. e : TXEvent;
  161. updatearea : TPTCArea;
  162. tmparea : TPTCArea;
  163. Begin
  164. tmparea := TPTCArea.Create(0, 0, m_width, m_height);
  165. Try
  166. updatearea := TPTCClipper.clip(tmparea, _area);
  167. Try
  168. m_primary.put(m_window, m_gc, updatearea.left, updatearea.top,
  169. m_destx + updatearea.left, m_desty + updatearea.top,
  170. updatearea.width, updatearea.height);
  171. Finally
  172. updatearea.Free;
  173. End;
  174. Finally
  175. tmparea.Free;
  176. End;
  177. {ifndef pthreads}
  178. If XCheckTypedEvent(m_disp, ClientMessage, @e) Then
  179. Begin
  180. If (e.xclient.format = 32) And (TAtom(e.xclient.data.l[0]) = m_atom_close) Then
  181. Halt(0);
  182. End;
  183. {endif}
  184. End;
  185. Procedure TX11WindowDisplay.internal_ReadKey(k : TPTCKey);
  186. Var
  187. e : TXEvent;
  188. sym : TKeySym;
  189. press : Boolean;
  190. alt, shift, ctrl : Boolean;
  191. uni : Integer;
  192. tmpkey : TPTCKey;
  193. Begin
  194. XMaskEvent(m_disp, KeyPressMask Or KeyReleaseMask, @e); { Blocks and waits }
  195. If (e._type <> KeyPress) And (e._type <> KeyRelease) Then
  196. Raise TPTCError.Create('XMaskEvent returned event <> KeyPress/KeyRelease');
  197. { XLookupString(@e.xkey, Nil, 0, @sym, Nil);}
  198. sym := XLookupKeySym(@e.xkey, 0);
  199. uni := X11ConvertKeySymToUnicode(sym);
  200. alt := (e.xkey.state And Mod1Mask) <> 0;
  201. shift := (e.xkey.state And ShiftMask) <> 0;
  202. ctrl := (e.xkey.state And ControlMask) <> 0;
  203. If e._type = KeyPress Then
  204. press := True
  205. Else
  206. press := False;
  207. tmpkey := Nil;
  208. Try
  209. Case sym Shr 8 Of
  210. 0 : tmpkey := TPTCKey.Create(m_normalkeys[sym And $FF], uni, alt, shift, ctrl, press);
  211. $FF : tmpkey := TPTCKey.Create(m_functionkeys[sym And $FF], uni, alt, shift, ctrl, press);
  212. Else
  213. tmpkey := TPTCKey.Create;
  214. End;
  215. k.ASSign(tmpkey);
  216. Finally
  217. tmpkey.Free;
  218. End;
  219. End;
  220. Function TX11WindowDisplay.internal_PeekKey(k : TPTCKey) : Boolean;
  221. Var
  222. e : TXEvent;
  223. Begin
  224. If XCheckMaskEvent(m_disp, KeyPressMask Or KeyReleaseMask, @e) Then
  225. Begin
  226. XPutBackEvent(m_disp, @e); { Simulate "normal" kbhit behaviour }
  227. XPutBackEvent(m_disp, @e); { i.e. leave the buffer intact }
  228. internal_ReadKey(k);
  229. Result := True;
  230. End
  231. Else
  232. Result := False;
  233. End;
  234. Function TX11WindowDisplay.lock : Pointer;
  235. Begin
  236. lock := m_primary.lock;
  237. End;
  238. Procedure TX11WindowDisplay.unlock;
  239. Begin
  240. End;
  241. Procedure TX11WindowDisplay.palette(Const _palette : TPTCPalette);
  242. Var
  243. pal : Pint32;
  244. i : Integer;
  245. Begin
  246. pal := _palette.data;
  247. If Not m_format.indexed Then
  248. Exit;
  249. For i := 0 To 255 Do
  250. Begin
  251. m_colours[i].pixel := i;
  252. m_colours[i].red := ((pal[i] Shr 16) And $FF) Shl 8;
  253. m_colours[i].green := ((pal[i] Shr 8) And $FF) Shl 8;
  254. m_colours[i].blue := (pal[i] And $FF) Shl 8;
  255. Byte(m_colours[i].flags) := DoRed Or DoGreen Or DoBlue;
  256. End;
  257. XStoreColors(m_disp, m_cmap, m_colours, 256);
  258. End;
  259. Function TX11WindowDisplay.pitch : Integer;
  260. Begin
  261. pitch := m_primary.pitch;
  262. End;
  263. Function TX11WindowDisplay.createImage(disp : PDisplay; screen, _width, _height : Integer;
  264. _format : TPTCFormat) : TX11Image;
  265. {$IFDEF HAVE_X11_EXTENSIONS_XSHM}
  266. Var
  267. tmp : TX11Image;
  268. {$ENDIF}
  269. Begin
  270. {todo: shm}
  271. {$IFDEF HAVE_X11_EXTENSIONS_XSHM}
  272. If m_has_shm And XShmQueryExtension(disp) Then
  273. Begin
  274. Try
  275. tmp := TX11SHMImage.Create(disp, screen, _width, _height, _format);
  276. Except
  277. On e : TPTCError Do
  278. tmp := TX11NormalImage.Create(disp, screen, _width, _height, _format);
  279. End;
  280. createImage := tmp;
  281. End
  282. Else
  283. {$ENDIF}
  284. createImage := TX11NormalImage.Create(disp, screen, _width, _height, _format);
  285. End;
  286. Function TX11WindowDisplay.getX11Window : TWindow;
  287. Begin
  288. getX11Window := m_window;
  289. End;
  290. Function TX11WindowDisplay.getX11GC : TGC;
  291. Begin
  292. getX11GC := m_gc;
  293. End;
  294. Procedure TX11WindowDisplay.createColormap; { Register colour maps }
  295. Var
  296. i : Integer;
  297. r, g, b : Single;
  298. Begin
  299. If m_format.bits = 8 Then
  300. Begin
  301. m_colours := GetMem(256 * SizeOf(TXColor));
  302. If m_colours = Nil Then
  303. Raise TPTCError.Create('Cannot allocate colour map cells');
  304. m_cmap := XCreateColormap(m_disp, RootWindow(m_disp, m_screen),
  305. DefaultVisual(m_disp, m_screen), AllocAll);
  306. If m_cmap = 0 Then
  307. Raise TPTCError.Create('Cannot create colour map');
  308. XInstallColormap(m_disp, m_cmap);
  309. XSetWindowColormap(m_disp, m_window, m_cmap);
  310. End
  311. Else
  312. m_cmap := 0;
  313. { Set 332 palette, for now }
  314. If (m_format.bits = 8) And m_format.direct Then
  315. Begin
  316. {Taken from PTC 0.72, i hope it's fine}
  317. For i := 0 To 255 Do
  318. Begin
  319. r := ((i And $E0) Shr 5) * 255 / 7;
  320. g := ((i And $1C) Shr 2) * 255 / 7;
  321. b := (i And $03) * 255 / 3;
  322. m_colours[i].pixel := i;
  323. m_colours[i].red := Round(r) Shl 8;
  324. m_colours[i].green := Round(g) Shl 8;
  325. m_colours[i].blue := Round(b) Shl 8;
  326. Byte(m_colours[i].flags) := DoRed Or DoGreen Or DoBlue;
  327. End;
  328. XStoreColors(m_disp, m_cmap, m_colours, 256);
  329. End;
  330. End;