GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/platform/framebuffers_impl_xlib.h
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 0 319 0.0%
Functions: 0 25 0.0%
Branches: 0 146 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/graphics/framebuffers.h"
30 #include "gate/platform/posix/xlib.h"
31 #include "gate/inputs.h"
32
33 typedef struct xlibfb_impl
34 {
35 GATE_INTERFACE_VTBL(gate_framebuffer) const* vtbl;
36
37 gate_atomic_int_t ref_counter;
38
39 gate_uint32_t width;
40 gate_uint32_t height;
41
42 Display* display;
43 int screen;
44 Window root_window;
45 Atom protocols_atom;
46 Atom close_atom;
47
48 Window fb_window;
49 XImage* image;
50 gate_size_t image_size;
51 void* image_data;
52
53 } xlibfb_t;
54
55
56 static void xlibfb_destroy(xlibfb_t* fb)
57 {
58 if (fb->display)
59 {
60 xlib.XAutoRepeatOn(fb->display);
61 if (fb->image)
62 {
63 xlib.XDestroyImage(fb->image);
64 /* XDestroyImage also deletes the embedded image_data */
65 }
66 else if (fb->image_data)
67 {
68 gate_mem_dealloc(fb->image_data);
69 }
70
71 if (fb->fb_window)
72 {
73 xlib.XDestroyWindow(fb->display, fb->fb_window);
74 }
75 xlib.XCloseDisplay(fb->display);
76 }
77 gate_mem_dealloc(fb);
78 }
79
80
81 static char const* xlibfb_get_interface_name(void* obj)
82 {
83 return GATE_INTERFACE_NAME_FRAMEBUFFER;
84 }
85 static void xlibfb_release(void* obj)
86 {
87 xlibfb_t* impl = (xlibfb_t*)obj;
88 if (0 == gate_atomic_int_dec(&impl->ref_counter))
89 {
90 xlibfb_destroy(impl);
91 }
92 }
93 static int xlibfb_retain(void* obj)
94 {
95 xlibfb_t* impl = (xlibfb_t*)obj;
96 return gate_atomic_int_inc(&impl->ref_counter);
97 }
98
99 static gate_result_t xlibfb_get_info(void* obj, gate_framebuffer_info_t* ptr_info)
100 {
101 xlibfb_t* impl = (xlibfb_t*)obj;
102 gate_result_t ret = GATE_RESULT_INVALIDARG;
103 if (impl && ptr_info)
104 {
105 ptr_info->width = impl->width;
106 ptr_info->height = impl->height;
107 ptr_info->bits_per_pixel = 32;
108 ptr_info->format_id = 0;
109 ret = GATE_RESULT_OK;
110 }
111 return ret;
112 }
113 static gate_result_t xlibfb_get_property(void* obj, gate_string_t const* name, gate_property_t* prop)
114 {
115 return GATE_RESULT_NOTSUPPORTED;
116 }
117 static gate_result_t xlibfb_set_property(void* obj, gate_string_t const* name, gate_property_t const* prop)
118 {
119 return GATE_RESULT_NOTSUPPORTED;
120 }
121
122 static void xlibfb_draw_image(xlibfb_t* fb)
123 {
124 GC gc = xlib.XCreateGC(fb->display, fb->fb_window, 0, 0);
125 xlib.XSetGraphicsExposures(fb->display, gc, 0);
126 xlib.XPutImage(fb->display, fb->fb_window, gc, fb->image, 0, 0, 0, 0, fb->width, fb->height);
127 xlib.XFreeGC(fb->display, gc);
128 }
129
130 static gate_result_t xlibfb_update(void* obj)
131 {
132 xlibfb_t* impl = (xlibfb_t*)obj;
133 xlibfb_draw_image(impl);
134 return GATE_RESULT_OK;
135 }
136
137 static unsigned long XGetRgbPixel(Display* display, Colormap colmap, gate_uint8_t r, gate_uint8_t g, gate_uint8_t b)
138 {
139 XColor col;
140 col.pixel = 0;
141 col.red = ((gate_uint16_t)r << 8);
142 col.green = ((gate_uint16_t)g << 8);
143 col.blue = ((gate_uint16_t)b << 8);
144 col.flags = DoRed | DoGreen | DoBlue;
145
146 xlib.XAllocColor(display, colmap, &col);
147 return col.pixel;
148 }
149
150 static void XResolveRgbPixel(Display* display, Colormap colmap, unsigned long pixel, gate_color_t* ptr_color)
151 {
152 XColor col;
153 col.pixel = pixel;
154 col.flags = DoRed | DoGreen | DoBlue;
155
156 xlib.XQueryColor(display, colmap, &col);
157 ptr_color->r = (gate_uint8_t)(col.red >> 8);
158 ptr_color->g = (gate_uint8_t)(col.green >> 8);
159 ptr_color->b = (gate_uint8_t)(col.blue >> 8);
160 ptr_color->a = 255;
161 }
162
163 static gate_result_t xlibfb_get_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t* ptr_col)
164 {
165 xlibfb_t* impl = (xlibfb_t*)obj;
166 unsigned long pixel;
167 Colormap colmap;
168 if ((x >= impl->width) || (y >= impl->height))
169 {
170 return GATE_RESULT_INVALIDARG;
171 }
172 colmap = xlib.XDefaultColormap(impl->display, impl->screen);
173 pixel = xlib.XGetPixel(impl->image, x, y);
174 XResolveRgbPixel(impl->display, colmap, pixel, ptr_col);
175 return GATE_RESULT_OK;
176 }
177 static gate_result_t xlibfb_set_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t col)
178 {
179 xlibfb_t* impl = (xlibfb_t*)obj;
180 unsigned long pixel;
181 Colormap colmap;
182
183 if ((x >= impl->width) || (y >= impl->height))
184 {
185 return GATE_RESULT_INVALIDARG;
186 }
187
188 colmap = xlib.XDefaultColormap(impl->display, impl->screen);
189 pixel = XGetRgbPixel(impl->display, impl->screen, col.r, col.g, col.b);
190 xlib.XPutPixel(impl->image, x, y, pixel);
191 return GATE_RESULT_OK;
192 }
193
194 static gate_result_t xlibfb_get_image(void* obj, gate_uint32_t src_x, gate_uint32_t src_y, gate_uint32_t width, gate_uint32_t height, gate_rasterimage_t* ptr_image)
195 {
196 xlibfb_t* impl = (xlibfb_t*)obj;
197 gate_uint32_t x, y;
198 gate_color_t* ptr_color;
199
200 unsigned long pixel;
201 Colormap colmap;
202 if ((src_x >= impl->width) || (src_y >= impl->height) || (width == 0) || (height == 0))
203 {
204 return GATE_RESULT_INVALIDARG;
205 }
206
207 if (!gate_rasterimage_create(ptr_image, GATE_IMAGE_PIXELFORMAT_DEFAULT, width, height, NULL))
208 {
209 return GATE_RESULT_OUTOFMEMORY;
210 }
211
212 if (src_y + height > impl->height)
213 {
214 height = impl->height - src_y;
215 }
216 if (src_x + width > impl->width)
217 {
218 width = impl->width - src_x;
219 }
220
221 colmap = xlib.XDefaultColormap(impl->display, impl->screen);
222
223 for (y = 0; y != width; ++y)
224 {
225 ptr_color = (gate_color_t*)gate_rasterimage_get_line_ptr(ptr_image, y);
226 for (x = 0; x != width; ++x)
227 {
228 pixel = xlib.XGetPixel(impl->image, x + src_x, y + src_y);
229 XResolveRgbPixel(impl->display, colmap, pixel, ptr_color);
230 ++ptr_color;
231 }
232 }
233
234 return GATE_RESULT_OK;
235 }
236
237 static gate_result_t xlibfb_set_image32(xlibfb_t* fb, gate_rasterimage_t const* ptr_image,
238 gate_uint32_t dest_x, gate_uint32_t dest_y,
239 gate_uint32_t width, gate_uint32_t height)
240 {
241 gate_uint32_t x, y;
242 gate_uint32_t* ptr_data = (gate_uint32_t*)fb->image_data;
243 gate_uint32_t* ptr_dst;
244 gate_color_t const* ptr_src;
245 gate_uint32_t pixel;
246
247 for (y = 0; y != height; ++y)
248 {
249 ptr_dst = &ptr_data[fb->width * (dest_y + y) + dest_x];
250 ptr_src = (gate_color_t*)gate_rasterimage_get_line_ptr(ptr_image, y);
251
252 for (x = 0; x != width; ++x)
253 {
254 pixel = (((gate_uint32_t)ptr_src->r) << 16)
255 | (((gate_uint32_t)ptr_src->g) << 8)
256 | (((gate_uint32_t)ptr_src->b))
257 ;
258 *ptr_dst = pixel;
259 ++ptr_src;
260 ++ptr_dst;
261 }
262 }
263 return GATE_RESULT_OK;
264 }
265
266 static gate_result_t xlibfb_set_image_generic(xlibfb_t* fb, gate_rasterimage_t const* ptr_image,
267 gate_uint32_t dest_x, gate_uint32_t dest_y,
268 gate_uint32_t width, gate_uint32_t height)
269 {
270 gate_color_t col;
271 unsigned x, y;
272 unsigned long pixel;
273 Colormap colmap;
274
275 if ((fb->image->bits_per_pixel == 32) && ((fb->image->depth == 24) || (fb->image->depth == 32)))
276 {
277 // frame-buffer is 24/32 bit -> optimize color access
278 gate_uint32_t* ptr_data = (gate_uint32_t*)fb->image_data;
279 gate_uint32_t* ptr_dst;
280
281 for (y = 0; y != height; ++y)
282 {
283 ptr_dst = &ptr_data[fb->width * (dest_y + y) + dest_x];
284
285 for (x = 0; x != width; ++x)
286 {
287 gate_rasterimage_get_pixel(ptr_image, x, y, &col);
288 pixel = (((gate_uint32_t)col.r) << 16)
289 | (((gate_uint32_t)col.g) << 8)
290 | (((gate_uint32_t)col.b))
291 ;
292 *ptr_dst = pixel;
293 ++ptr_dst;
294 }
295 }
296
297 }
298 else
299 {
300 colmap = xlib.XDefaultColormap(fb->display, fb->screen);
301
302 for (y = 0; y != height; ++y)
303 {
304 for (x = 0; x != width; ++x)
305 {
306 gate_rasterimage_get_pixel(ptr_image, x, y, &col);
307 pixel = XGetRgbPixel(fb->display, colmap, col.r, col.g, col.b);
308 xlib.XPutPixel(fb->image, (int)(dest_x + x), (int)(dest_y + y), pixel);
309 }
310 }
311 }
312
313 return GATE_RESULT_OK;
314 }
315
316 static gate_result_t xlibfb_set_image(void* obj, gate_rasterimage_t const* ptr_image, gate_uint32_t dest_x, gate_uint32_t dest_y)
317 {
318 xlibfb_t* impl = (xlibfb_t*)obj;
319
320 gate_uint32_t width, height;
321
322 if ((dest_x >= impl->width) || (dest_y >= impl->height))
323 {
324 return GATE_RESULT_INVALIDARG;
325 }
326
327 width = gate_rasterimage_width(ptr_image);
328 height = gate_rasterimage_height(ptr_image);
329
330 if (dest_y + height > impl->height)
331 {
332 height = impl->height - dest_y;
333 }
334 if (dest_x + width > impl->width)
335 {
336 width = impl->width - dest_x;
337 }
338
339 if ((impl->image->bits_per_pixel == 32) && ((impl->image->depth == 24) || (impl->image->depth == 32))
340 && ((ptr_image->pixel_format == GATE_IMAGE_PIXELFORMAT_RGBA) || (ptr_image->pixel_format == GATE_IMAGE_PIXELFORMAT_RGB32)))
341 {
342 return xlibfb_set_image32(impl, ptr_image, dest_x, dest_y, width, height);
343 }
344
345 return xlibfb_set_image_generic(impl, ptr_image, dest_x, dest_y, width, height);
346 }
347
348 static gate_bool_t xlibfb_decode_event(XEvent* ptr_event, xlibfb_t* impl, gate_framebuffer_event_t* ptr_received_evt)
349 {
350 KeySym keysym;
351 gate_input_keycode_t key_code;
352 gate_uint32_t key_states;
353
354 switch (ptr_event->type)
355 {
356 case KeyPress:
357 {
358 keysym = xlib.XLookupKeysym(&ptr_event->xkey, 0);
359 key_states = 0;
360 if (ptr_event->xkey.state & ShiftMask)
361 {
362 key_states |= GATE_KBD_KEYSTATE_SHIFT;
363 }
364 if (ptr_event->xkey.state & LockMask)
365 {
366 key_states |= GATE_KBD_KEYSTATE_MENU;
367 }
368 if (ptr_event->xkey.state & ControlMask)
369 {
370 key_states |= GATE_KBD_KEYSTATE_CTRL;
371 }
372 key_code = 0;
373 gate_xlib_convert_keysym(keysym, &key_code);
374 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_KEY_DOWN;
375 ptr_received_evt->event_data.key.key_code = key_code;
376 ptr_received_evt->event_data.key.char_code = key_code;
377 return true;
378 }
379 case KeyRelease:
380 {
381 keysym = xlib.XLookupKeysym(&ptr_event->xkey, 0);
382 key_states = 0;
383 if (ptr_event->xkey.state & ShiftMask)
384 {
385 key_states |= GATE_KBD_KEYSTATE_SHIFT;
386 }
387 if (ptr_event->xkey.state & LockMask)
388 {
389 key_states |= GATE_KBD_KEYSTATE_MENU;
390 }
391 if (ptr_event->xkey.state & ControlMask)
392 {
393 key_states |= GATE_KBD_KEYSTATE_CTRL;
394 }
395 key_code = 0;
396 gate_xlib_convert_keysym(keysym, &key_code);
397 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_KEY_UP;
398 ptr_received_evt->event_data.key.key_code = key_code;
399 ptr_received_evt->event_data.key.char_code = key_code;
400 return true;
401 }
402 case ButtonPress:
403 {
404 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_POINTER_BUTTON_DOWN;
405 ptr_received_evt->event_data.pointer.x = ptr_event->xbutton.x;
406 ptr_received_evt->event_data.pointer.y = ptr_event->xbutton.y;
407 switch (ptr_event->xbutton.button)
408 {
409 case Button1: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_1; break;
410 case Button2: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_2; break;
411 case Button3: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_3; break;
412 }
413 return true;
414 }
415 case ButtonRelease:
416 {
417 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_POINTER_BUTTON_UP;
418 ptr_received_evt->event_data.pointer.x = ptr_event->xbutton.x;
419 ptr_received_evt->event_data.pointer.y = ptr_event->xbutton.y;
420 switch (ptr_event->xbutton.button)
421 {
422 case Button1: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_1; break;
423 case Button2: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_2; break;
424 case Button3: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_3; break;
425 }
426 return true;
427 }
428 case ClientMessage:
429 {
430 if (ptr_event->xclient.message_type == impl->protocols_atom)
431 {
432 if (ptr_event->xclient.data.l[0] == (long)impl->close_atom)
433 {
434 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_QUIT;
435 return true;
436 }
437 }
438 break;
439 }
440 }
441 return false;
442 }
443
444 static gate_result_t xlibfb_await_event(void* obj, gate_uint32_t timeout_ms, gate_framebuffer_event_t* ptr_received_evt)
445 {
446 xlibfb_t* impl = (xlibfb_t*)obj;
447 gate_result_t ret = GATE_RESULT_FAILED;
448
449 gate_timecounter_t start_time;
450 gate_timecounter_t current_time;
451 gate_int64_t time_diff;
452 const gate_int64_t timeout_us = (gate_int64_t)timeout_ms * (gate_int64_t)1000;
453
454 XEvent xevent;
455
456 long input_event_mask = FocusChangeMask | PropertyChangeMask
457 | KeyPressMask | KeyReleaseMask | KeymapStateMask
458 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | PointerMotionHintMask
459 | ExposureMask | VisibilityChangeMask
460 | StructureNotifyMask | SubstructureNotifyMask
461 ;
462
463 do
464 {
465 gate_timecounter_now(&start_time);
466
467 xlib.XSelectInput(impl->display, impl->fb_window, input_event_mask);
468
469 for (;;)
470 {
471 if (xlib.XPending(impl->display) > 0)
472 {
473 gate_mem_clear(&xevent, sizeof(xevent));
474 xlib.XNextEvent(impl->display, &xevent);
475
476 if (xlibfb_decode_event(&xevent, impl, ptr_received_evt))
477 {
478 ret = GATE_RESULT_OK;
479 break;
480 }
481 }
482 else
483 {
484 gate_timecounter_now(&current_time);
485 time_diff = gate_timecounter_diff(current_time, start_time);
486
487 if (time_diff >= timeout_us)
488 {
489 ret = GATE_RESULT_TIMEOUT;
490 break;
491 }
492 }
493 }
494 } while (0);
495
496 return ret;
497 }
498
499 static GATE_INTERFACE_VTBL(gate_framebuffer) gate_xlibfb_vtbl;
500 static void gate_init_xlibfb_vtbl(void)
501 {
502 if (!gate_xlibfb_vtbl.get_interface_name)
503 {
504 GATE_INTERFACE_VTBL(gate_framebuffer) const local_vtbl =
505 {
506 &xlibfb_get_interface_name,
507 &xlibfb_release,
508 &xlibfb_retain,
509
510 &xlibfb_get_info,
511 &xlibfb_get_property,
512 &xlibfb_set_property,
513
514 &xlibfb_update,
515
516 &xlibfb_get_pixel,
517 &xlibfb_set_pixel,
518
519 &xlibfb_get_image,
520 &xlibfb_set_image,
521
522 &xlibfb_await_event
523 };
524
525 gate_xlibfb_vtbl = local_vtbl;
526 }
527 }
528
529
530
531 gate_size_t gate_framebuffer_enum_displays(gate_framebuffer_info_t* ptr_infos, gate_size_t infos_capacity)
532 {
533 gate_size_t ret = infos_capacity;
534
535 if (ret > 2)
536 {
537 ret = 2;
538 }
539
540 if (ret >= 1)
541 {
542 ptr_infos[0].width = 640;
543 ptr_infos[0].height = 480;
544 ptr_infos[0].bits_per_pixel = 32;
545 ptr_infos[0].format_id = 0;
546 }
547
548 if (ret >= 2)
549 {
550 ptr_infos[1].width = 800;
551 ptr_infos[1].height = 600;
552 ptr_infos[1].bits_per_pixel = 32;
553 ptr_infos[1].format_id = 0;
554 }
555
556 return ret;
557 }
558
559 static gate_result_t xlibfb_create_image(xlibfb_t* fb)
560 {
561 Visual* visual = xlib.XDefaultVisual(fb->display, fb->screen);
562 unsigned int depth = (unsigned int)xlib.XDefaultDepth(fb->display, fb->screen);
563 unsigned int padding = xlib.XBitmapPad(fb->display);
564 unsigned int bytes_per_line = fb->width * 4;
565
566 if (bytes_per_line % padding != 0)
567 {
568 bytes_per_line += (padding - (bytes_per_line % padding));
569 }
570
571 fb->image_size = bytes_per_line * fb->height;
572 fb->image_data = gate_mem_alloc(fb->image_size);
573
574 if (!fb->image_data)
575 {
576 return GATE_RESULT_OUTOFMEMORY;
577 }
578
579 fb->image = xlib.XCreateImage(fb->display, visual, depth, ZPixmap, 0, fb->image_data, fb->width, fb->height, padding, 0);
580 if (!fb->image)
581 {
582 return GATE_RESULT_OUTOFRESOURCES;
583 }
584
585 return GATE_RESULT_OK;
586 }
587
588 static gate_result_t xlibfb_create_window(xlibfb_t* fb)
589 {
590 gate_result_t ret = GATE_RESULT_FAILED;
591
592 int depth;
593 Visual* visual;
594 Colormap colmap;
595 XSetWindowAttributes win_attribs;
596 int attr_mask;
597
598 do
599 {
600 ret = gate_xlib_load_functions();
601 GATE_BREAK_IF_FAILED(ret);
602
603 fb->display = xlib.XOpenDisplay(NULL);
604 if (fb->display == NULL)
605 {
606 fb->display = xlib.XOpenDisplay(":0");
607 }
608 if (fb->display == NULL)
609 {
610 ret = GATE_RESULT_OUTOFRESOURCES;
611 break;
612 }
613
614 fb->screen = xlib.XDefaultScreen(fb->display);
615 fb->root_window = xlib.XDefaultRootWindow(fb->display);
616 fb->protocols_atom = xlib.XInternAtom(fb->display, "WM_PROTOCOLS", False);
617 fb->close_atom = xlib.XInternAtom(fb->display, "WM_DELETE_WINDOW", False);
618
619 depth = xlib.XDefaultDepth(fb->display, fb->screen);
620 visual = xlib.XDefaultVisual(fb->display, fb->screen);
621 colmap = xlib.XDefaultColormap(fb->display, fb->screen);
622
623 gate_mem_clear(&win_attribs, sizeof(win_attribs));
624 win_attribs.colormap = colmap;
625 win_attribs.event_mask = StructureNotifyMask;
626 win_attribs.border_pixel = xlib.XBlackPixel(fb->display, fb->screen);
627 win_attribs.background_pixel = xlib.XWhitePixel(fb->display, fb->screen);
628
629 attr_mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
630
631 fb->fb_window = xlib.XCreateWindow(fb->display, fb->root_window, 0, 0, fb->width, fb->height,
632 0, depth, InputOutput, visual, attr_mask, &win_attribs);
633 if (!fb->fb_window)
634 {
635 ret = GATE_RESULT_FAILED;
636 break;
637 }
638
639 ret = xlibfb_create_image(fb);
640 GATE_BREAK_IF_FAILED(ret);
641
642 xlib.XSetWMProtocols(fb->display, fb->fb_window, &fb->close_atom, 1);
643
644 xlib.XMapWindow(fb->display, fb->fb_window);
645
646 xlib.XFlush(fb->display);
647
648 /* successfully initialized: */
649 xlib.XAutoRepeatOff(fb->display); /* repeated disable key-press events */
650 ret = GATE_RESULT_OK;
651
652 } while (0);
653
654 return ret;
655 }
656
657 gate_result_t gate_framebuffer_find_display(gate_uint32_t required_width, gate_uint32_t required_height, gate_framebuffer_info_t* ptr_found_display_info)
658 {
659 /* TODO */
660 ptr_found_display_info->bits_per_pixel = 32;
661 ptr_found_display_info->format_id = 0;
662 ptr_found_display_info->width = required_width;
663 ptr_found_display_info->height = required_height;
664 return GATE_RESULT_OK;
665 }
666
667 gate_result_t gate_framebuffer_open_display(gate_framebuffer_info_t const* ptr_infos, gate_framebuffer_t** ptr_framebuffer)
668 {
669 gate_result_t ret;
670 xlibfb_t* fb = NULL;
671
672 do
673 {
674 if (!ptr_infos)
675 {
676 ret = GATE_RESULT_INVALIDARG;
677 break;
678 }
679
680 fb = (xlibfb_t*)gate_mem_alloc(sizeof(xlibfb_t));
681 if (!fb)
682 {
683 ret = GATE_RESULT_OUTOFMEMORY;
684 break;
685 }
686
687 gate_mem_clear(fb, sizeof(xlibfb_t));
688 gate_init_xlibfb_vtbl();
689 fb->vtbl = &gate_xlibfb_vtbl;
690 gate_atomic_int_init(&fb->ref_counter, 1);
691 fb->width = ptr_infos->width;
692 fb->height = ptr_infos->height;
693
694 ret = xlibfb_create_window(fb);
695 GATE_BREAK_IF_FAILED(ret);
696
697 /* initialization successfully completed: */
698 ret = GATE_RESULT_OK;
699 if (ptr_framebuffer)
700 {
701 *ptr_framebuffer = (gate_framebuffer_t*)fb;
702 fb = NULL;
703 }
704 } while (0);
705
706 if (fb != NULL)
707 {
708 /* destroy partially initialized framebuffer */
709 xlibfb_destroy(fb);
710 }
711 return ret;
712 }
713