summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--src/libplybootsplash/ply-boot-splash.c10
-rw-r--r--src/libplybootsplash/ply-console.c12
-rw-r--r--src/libplybootsplash/ply-console.h4
-rw-r--r--src/libplybootsplash/ply-renderer.c5
-rw-r--r--src/main.c3
-rw-r--r--src/plugins/renderers/Makefile.am2
-rw-r--r--src/plugins/renderers/drm/plugin.c7
-rw-r--r--src/plugins/renderers/frame-buffer/plugin.c7
-rw-r--r--src/plugins/renderers/x11/Makefile.am20
-rw-r--r--src/plugins/renderers/x11/plugin.c523
11 files changed, 576 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac
index 318c80e2..e257b9d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -216,6 +216,7 @@ AC_OUTPUT([Makefile
216 src/plugins/renderers/Makefile 216 src/plugins/renderers/Makefile
217 src/plugins/renderers/frame-buffer/Makefile 217 src/plugins/renderers/frame-buffer/Makefile
218 src/plugins/renderers/drm/Makefile 218 src/plugins/renderers/drm/Makefile
219 src/plugins/renderers/x11/Makefile
219 src/plugins/splash/Makefile 220 src/plugins/splash/Makefile
220 src/plugins/splash/throbgress/Makefile 221 src/plugins/splash/throbgress/Makefile
221 src/plugins/splash/fade-throbber/Makefile 222 src/plugins/splash/fade-throbber/Makefile
diff --git a/src/libplybootsplash/ply-boot-splash.c b/src/libplybootsplash/ply-boot-splash.c
index 72ee7f02..5ba1bc1d 100644
--- a/src/libplybootsplash/ply-boot-splash.c
+++ b/src/libplybootsplash/ply-boot-splash.c
@@ -169,8 +169,14 @@ on_keyboard_input (ply_boot_splash_t *splash,
169 case KEY_CTRL_T: 169 case KEY_CTRL_T:
170 ply_trace ("toggle text mode!"); 170 ply_trace ("toggle text mode!");
171 splash->should_force_text_mode = !splash->should_force_text_mode; 171 splash->should_force_text_mode = !splash->should_force_text_mode;
172 ply_console_force_text_mode (splash->console, 172
173 splash->should_force_text_mode); 173 if (splash->should_force_text_mode)
174 {
175 ply_console_set_mode (splash->console, PLY_CONSOLE_MODE_TEXT);
176 ply_console_ignore_mode_changes (splash->console, true);
177 }
178 else
179 ply_console_ignore_mode_changes (splash->console, false);
174 ply_trace ("text mode toggled!"); 180 ply_trace ("text mode toggled!");
175 return; 181 return;
176 182
diff --git a/src/libplybootsplash/ply-console.c b/src/libplybootsplash/ply-console.c
index 7fb92980..fb5a86db 100644
--- a/src/libplybootsplash/ply-console.c
+++ b/src/libplybootsplash/ply-console.c
@@ -68,7 +68,7 @@ struct _ply_console
68 68
69 uint32_t is_open : 1; 69 uint32_t is_open : 1;
70 uint32_t is_watching_for_vt_changes : 1; 70 uint32_t is_watching_for_vt_changes : 1;
71 uint32_t should_force_text_mode : 1; 71 uint32_t should_ignore_mode_changes : 1;
72}; 72};
73 73
74static bool ply_console_open_device (ply_console_t *console); 74static bool ply_console_open_device (ply_console_t *console);
@@ -106,8 +106,8 @@ ply_console_set_mode (ply_console_t *console,
106 assert (console != NULL); 106 assert (console != NULL);
107 assert (mode == PLY_CONSOLE_MODE_TEXT || mode == PLY_CONSOLE_MODE_GRAPHICS); 107 assert (mode == PLY_CONSOLE_MODE_TEXT || mode == PLY_CONSOLE_MODE_GRAPHICS);
108 108
109 if (console->should_force_text_mode) 109 if (console->should_ignore_mode_changes)
110 mode = PLY_CONSOLE_MODE_TEXT; 110 return;
111 111
112 switch (mode) 112 switch (mode)
113 { 113 {
@@ -124,10 +124,10 @@ ply_console_set_mode (ply_console_t *console,
124} 124}
125 125
126void 126void
127ply_console_force_text_mode (ply_console_t *console, 127ply_console_ignore_mode_changes (ply_console_t *console,
128 bool should_force) 128 bool should_ignore)
129{ 129{
130 console->should_force_text_mode = should_force; 130 console->should_ignore_mode_changes = should_ignore;
131} 131}
132 132
133static void 133static void
diff --git a/src/libplybootsplash/ply-console.h b/src/libplybootsplash/ply-console.h
index 36263bbc..4b45c86e 100644
--- a/src/libplybootsplash/ply-console.h
+++ b/src/libplybootsplash/ply-console.h
@@ -49,8 +49,8 @@ void ply_console_close (ply_console_t *console);
49void ply_console_set_mode (ply_console_t *console, 49void ply_console_set_mode (ply_console_t *console,
50 ply_console_mode_t mode); 50 ply_console_mode_t mode);
51 51
52void ply_console_force_text_mode (ply_console_t *console, 52void ply_console_ignore_mode_changes (ply_console_t *console,
53 bool should_force); 53 bool should_ignore);
54 54
55int ply_console_get_fd (ply_console_t *console); 55int ply_console_get_fd (ply_console_t *console);
56int ply_console_get_active_vt (ply_console_t *console); 56int ply_console_get_active_vt (ply_console_t *console);
diff --git a/src/libplybootsplash/ply-renderer.c b/src/libplybootsplash/ply-renderer.c
index 5410feb8..08a246ba 100644
--- a/src/libplybootsplash/ply-renderer.c
+++ b/src/libplybootsplash/ply-renderer.c
@@ -220,6 +220,7 @@ ply_renderer_open (ply_renderer_t *renderer)
220 */ 220 */
221 const char *known_plugins[] = 221 const char *known_plugins[] =
222 { 222 {
223 PLYMOUTH_PLUGIN_PATH "renderers/x11.so",
223 PLYMOUTH_PLUGIN_PATH "renderers/drm.so", 224 PLYMOUTH_PLUGIN_PATH "renderers/drm.so",
224 PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", 225 PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so",
225 NULL 226 NULL
@@ -299,10 +300,6 @@ ply_renderer_flush_head (ply_renderer_t *renderer,
299 assert (renderer->plugin_interface != NULL); 300 assert (renderer->plugin_interface != NULL);
300 assert (head != NULL); 301 assert (head != NULL);
301 302
302 if (ply_console_get_active_vt (renderer->console) !=
303 ply_terminal_get_vt_number (renderer->terminal))
304 return;
305
306 renderer->plugin_interface->flush_head (renderer->backend, head); 303 renderer->plugin_interface->flush_head (renderer->backend, head);
307} 304}
308 305
diff --git a/src/main.c b/src/main.c
index d79b816e..08ec1ae4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -989,9 +989,6 @@ add_default_displays_and_keyboard (state_t *state)
989 return; 989 return;
990 } 990 }
991 991
992 ply_console_set_active_vt (state->console,
993 ply_terminal_get_vt_number (terminal));
994
995 renderer = ply_renderer_new (NULL, terminal, state->console); 992 renderer = ply_renderer_new (NULL, terminal, state->console);
996 993
997 if (!ply_renderer_open (renderer)) 994 if (!ply_renderer_open (renderer))
diff --git a/src/plugins/renderers/Makefile.am b/src/plugins/renderers/Makefile.am
index 2fadbf40..5a449a79 100644
--- a/src/plugins/renderers/Makefile.am
+++ b/src/plugins/renderers/Makefile.am
@@ -1,2 +1,2 @@
1SUBDIRS = frame-buffer drm 1SUBDIRS = frame-buffer drm x11
2MAINTAINERCLEANFILES = Makefile.in 2MAINTAINERCLEANFILES = Makefile.in
diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c
index 2c5e1aa9..05e36fa2 100644
--- a/src/plugins/renderers/drm/plugin.c
+++ b/src/plugins/renderers/drm/plugin.c
@@ -783,6 +783,9 @@ map_to_device (ply_renderer_backend_t *backend)
783 node = next_node; 783 node = next_node;
784 } 784 }
785 785
786 ply_console_set_active_vt (backend->console,
787 ply_terminal_get_vt_number (backend->terminal));
788
786 return head_mapped; 789 return head_mapped;
787} 790}
788 791
@@ -922,6 +925,10 @@ flush_head (ply_renderer_backend_t *backend,
922 925
923 assert (backend != NULL); 926 assert (backend != NULL);
924 927
928 if (ply_console_get_active_vt (backend->console) !=
929 ply_terminal_get_vt_number (backend->terminal))
930 return;
931
925 ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); 932 ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS);
926 ply_terminal_set_unbuffered_input (backend->terminal); 933 ply_terminal_set_unbuffered_input (backend->terminal);
927 pixel_buffer = head->pixel_buffer; 934 pixel_buffer = head->pixel_buffer;
diff --git a/src/plugins/renderers/frame-buffer/plugin.c b/src/plugins/renderers/frame-buffer/plugin.c
index 6f45b8f4..0163daa0 100644
--- a/src/plugins/renderers/frame-buffer/plugin.c
+++ b/src/plugins/renderers/frame-buffer/plugin.c
@@ -491,6 +491,9 @@ map_to_device (ply_renderer_backend_t *backend)
491 491
492 initialize_head (backend, head); 492 initialize_head (backend, head);
493 493
494 ply_console_set_active_vt (backend->console,
495 ply_terminal_get_vt_number (backend->terminal));
496
494 return true; 497 return true;
495} 498}
496 499
@@ -522,6 +525,10 @@ flush_head (ply_renderer_backend_t *backend,
522 assert (backend != NULL); 525 assert (backend != NULL);
523 assert (&backend->head == head); 526 assert (&backend->head == head);
524 527
528 if (ply_console_get_active_vt (backend->console) !=
529 ply_terminal_get_vt_number (backend->terminal))
530 return;
531
525 ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); 532 ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS);
526 ply_terminal_set_unbuffered_input (backend->terminal); 533 ply_terminal_set_unbuffered_input (backend->terminal);
527 pixel_buffer = head->pixel_buffer; 534 pixel_buffer = head->pixel_buffer;
diff --git a/src/plugins/renderers/x11/Makefile.am b/src/plugins/renderers/x11/Makefile.am
new file mode 100644
index 00000000..2bf85d27
--- /dev/null
+++ b/src/plugins/renderers/x11/Makefile.am
@@ -0,0 +1,20 @@
1INCLUDES = -I$(top_srcdir) \
2 -I$(srcdir)/../../../libply \
3 -I$(srcdir)/../../../libplybootsplash \
4 -I$(srcdir)/../../.. \
5 -I$(srcdir)/../.. \
6 -I$(srcdir)/.. \
7 -I$(srcdir)
8
9plugindir = $(libdir)/plymouth/renderers
10plugin_LTLIBRARIES = x11.la
11
12x11_la_CFLAGS = $(GTK_CFLAGS) $(PLYMOUTH_CFLAGS)
13x11_la_LDFLAGS = -module -avoid-version -export-dynamic
14x11_la_LIBADD = $(PLYMOUTH_LIBS) \
15 $(GTK_LIBS) \
16 ../../../libply/libply.la \
17 ../../../libplybootsplash/libplybootsplash.la
18x11_la_SOURCES = $(srcdir)/plugin.c
19
20MAINTAINERCLEANFILES = Makefile.in
diff --git a/src/plugins/renderers/x11/plugin.c b/src/plugins/renderers/x11/plugin.c
new file mode 100644
index 00000000..a2b61c0b
--- /dev/null
+++ b/src/plugins/renderers/x11/plugin.c
@@ -0,0 +1,523 @@
1/* plugin.c - frame-backend renderer plugin
2 *
3 * Copyright (C) 2006-2009 Red Hat, Inc.
4 * 2009 Charlie Brej <cbrej@cs.man.ac.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 *
21 * Written by: Charlie Brej <cbrej@cs.man.ac.uk>
22 * Kristian Høgsberg <krh@redhat.com>
23 * Peter Jones <pjones@redhat.com>
24 * Ray Strode <rstrode@redhat.com>
25 */
26#include "config.h"
27
28#include <arpa/inet.h>
29#include <assert.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <signal.h>
33#include <string.h>
34#include <stdbool.h>
35#include <stdint.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <sys/ioctl.h>
39#include <sys/mman.h>
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <sys/ipc.h>
43#include <sys/shm.h>
44
45#include <values.h>
46#include <unistd.h>
47
48#include <linux/fb.h>
49#include <gtk/gtk.h>
50#include <gdk/gdkkeysyms.h>
51#include <gdk/gdkx.h>
52
53#include "ply-buffer.h"
54#include "ply-event-loop.h"
55#include "ply-list.h"
56#include "ply-logger.h"
57#include "ply-rectangle.h"
58#include "ply-region.h"
59#include "ply-terminal.h"
60
61#include "ply-renderer.h"
62#include "ply-renderer-plugin.h"
63
64struct _ply_renderer_head
65{
66 ply_renderer_backend_t *backend;
67 ply_pixel_buffer_t *pixel_buffer;
68 ply_rectangle_t area;
69 GtkWidget *window;
70 GdkPixmap *pixmap;
71 cairo_surface_t *image;
72};
73
74struct _ply_renderer_input_source
75{
76 ply_buffer_t *key_buffer;
77 ply_renderer_input_source_handler_t handler;
78 void *user_data;
79};
80
81struct _ply_renderer_backend
82{
83 ply_event_loop_t *loop;
84 ply_renderer_input_source_t input_source;
85 ply_list_t *heads;
86 ply_console_t *console;
87
88 ply_fd_watch_t *display_watch;
89};
90
91ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void);
92static void ply_renderer_head_redraw (ply_renderer_backend_t *backend,
93 ply_renderer_head_t *head);
94
95static gboolean on_motion_notify_event (GtkWidget *widget,
96 GdkEventMotion *event,
97 gpointer user_data);
98static gboolean on_key_event (GtkWidget *widget,
99 GdkEventKey *event,
100 gpointer user_data);
101
102static ply_renderer_backend_t *
103create_backend (const char *device_name,
104 ply_terminal_t *terminal,
105 ply_console_t *console)
106{
107 ply_renderer_backend_t *backend;
108
109 backend = calloc (1, sizeof (ply_renderer_backend_t));
110
111 backend->loop = ply_event_loop_get_default ();
112 backend->heads = ply_list_new ();
113 backend->input_source.key_buffer = ply_buffer_new ();
114 backend->console = console;
115
116 return backend;
117}
118
119static void
120destroy_backend (ply_renderer_backend_t *backend)
121{
122 ply_list_node_t *node;
123 node = ply_list_get_first_node (backend->heads);
124 while (node != NULL)
125 {
126 ply_list_node_t *next_node;
127 ply_renderer_head_t *head;
128
129 head = (ply_renderer_head_t *) ply_list_node_get_data (node);
130 next_node = ply_list_get_next_node (backend->heads, node);
131
132 free (head);
133 node = next_node;
134 }
135
136 ply_list_free (backend->heads);
137 ply_buffer_free (backend->input_source.key_buffer);
138 free (backend);
139}
140
141static void
142on_display_event (ply_renderer_backend_t *backend)
143{
144 while (gtk_events_pending ())
145 gtk_main_iteration ();
146}
147
148static bool
149open_device (ply_renderer_backend_t *backend)
150{
151 Display *display;
152 int display_fd;
153
154 if (!gtk_init_check (0, NULL))
155 return false;
156
157 display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
158 display_fd = ConnectionNumber (display);
159 backend->display_watch = ply_event_loop_watch_fd (backend->loop,
160 display_fd,
161 PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
162 (ply_event_handler_t) on_display_event,
163 NULL,
164 backend);
165
166 return true;
167}
168
169static void
170close_device (ply_renderer_backend_t *backend)
171{
172 ply_event_loop_stop_watching_fd (backend->loop, backend->display_watch);
173 backend->display_watch = NULL;
174 return;
175}
176
177static bool
178query_device (ply_renderer_backend_t *backend)
179{
180 ply_renderer_head_t *head;
181 assert (backend != NULL);
182
183 if (ply_list_get_first_node (backend->heads) == NULL)
184 {
185 head = calloc (1, sizeof (ply_renderer_head_t));
186
187 head->backend = backend;
188 head->area.x = 0;
189 head->area.y = 0;
190 head->area.width = 800; /* FIXME hardcoded */
191 head->area.height = 600;
192 head->pixmap = gdk_pixmap_new (NULL,
193 head->area.width,
194 head->area.height,
195 24);
196
197 ply_list_append_data (backend->heads, head);
198
199 head = calloc (1, sizeof (ply_renderer_head_t));
200
201 head->backend = backend;
202 head->area.x = 800;
203 head->area.y = 0;
204 head->area.width = 640; /* FIXME hardcoded */
205 head->area.height = 480;
206 head->pixmap = gdk_pixmap_new (NULL,
207 head->area.width,
208 head->area.height,
209 24);
210
211 ply_list_append_data (backend->heads, head);
212 }
213
214 return true;
215}
216
217static gboolean
218on_window_destroy (GtkWidget *widget,
219 GdkEvent *event,
220 gpointer user_data)
221{
222 return TRUE;
223}
224
225static bool
226map_to_device (ply_renderer_backend_t *backend)
227{
228 ply_list_node_t *node;
229 assert (backend != NULL);
230
231 /* Prevent other parts of plymouth from trying to use
232 * the console, since X draws to it.
233 */
234 ply_console_ignore_mode_changes (backend->console, true);
235
236 node = ply_list_get_first_node (backend->heads);
237 while (node != NULL)
238 {
239 ply_list_node_t *next_node;
240 ply_renderer_head_t *head;
241 uint32_t *shadow_buffer;
242
243 head = (ply_renderer_head_t *) ply_list_node_get_data (node);
244 next_node = ply_list_get_next_node (backend->heads, node);
245
246 head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height);
247 head->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
248 gtk_window_set_resizable (GTK_WINDOW (head->window), FALSE);
249 gtk_widget_set_size_request (head->window,
250 head->area.width,
251 head->area.height);
252 shadow_buffer = ply_pixel_buffer_get_argb32_data (head->pixel_buffer);
253 head->image = cairo_image_surface_create_for_data ((unsigned char *) shadow_buffer,
254 CAIRO_FORMAT_ARGB32,
255 head->area.width, head->area.height,
256 head->area.width * 4);
257 gtk_widget_set_app_paintable (head->window, TRUE);
258 gtk_widget_show_all (head->window);
259 gdk_window_set_back_pixmap (head->window->window, head->pixmap, FALSE);
260 gdk_window_set_decorations (head->window->window, GDK_DECOR_BORDER);
261 gtk_window_move (GTK_WINDOW (head->window), head->area.x, head->area.y);
262
263 gtk_widget_add_events (head->window, GDK_BUTTON1_MOTION_MASK);
264
265 g_signal_connect (head->window, "motion-notify-event",
266 G_CALLBACK (on_motion_notify_event),
267 head);
268 g_signal_connect (head->window, "key-press-event",
269 G_CALLBACK (on_key_event),
270 &backend->input_source);
271 g_signal_connect (head->window, "delete-event",
272 G_CALLBACK (on_window_destroy),
273 NULL);
274
275 ply_renderer_head_redraw (backend, head);
276 node = next_node;
277 }
278 return true;
279}
280
281static void
282unmap_from_device (ply_renderer_backend_t *backend)
283{
284 ply_list_node_t *node;
285 assert (backend != NULL);
286
287 node = ply_list_get_first_node (backend->heads);
288 while (node != NULL)
289 {
290 ply_list_node_t *next_node;
291 ply_renderer_head_t *head;
292
293 head = (ply_renderer_head_t *) ply_list_node_get_data (node);
294 next_node = ply_list_get_next_node (backend->heads, node);
295
296 gtk_widget_destroy (head->window);
297 head->window = NULL;
298 ply_pixel_buffer_free (head->pixel_buffer);
299 head->pixel_buffer = NULL;
300 cairo_surface_destroy (head->image);
301 head->image = NULL;
302
303 node = next_node;
304 }
305
306 ply_console_ignore_mode_changes (backend->console, false);
307}
308
309static void
310flush_area_to_device (ply_renderer_backend_t *backend,
311 ply_renderer_head_t *head,
312 ply_rectangle_t *area_to_flush,
313 cairo_t *cr)
314{
315 cairo_save (cr);
316 cairo_rectangle (cr,
317 area_to_flush->x,
318 area_to_flush->y,
319 area_to_flush->width,
320 area_to_flush->height);
321 cairo_clip (cr);
322
323 cairo_set_source_surface (cr, head->image, 0, 0);
324 cairo_paint (cr);
325 cairo_restore (cr);
326}
327
328static void
329flush_head (ply_renderer_backend_t *backend,
330 ply_renderer_head_t *head)
331{
332 ply_region_t *updated_region;
333 ply_list_t *areas_to_flush;
334 ply_list_node_t *node;
335 ply_pixel_buffer_t *pixel_buffer;
336 cairo_t *cr;
337
338 assert (backend != NULL);
339
340 pixel_buffer = head->pixel_buffer;
341 updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer);
342 areas_to_flush = ply_region_get_rectangle_list (updated_region);
343
344 cr = gdk_cairo_create (head->pixmap);
345
346 node = ply_list_get_first_node (areas_to_flush);
347 while (node != NULL)
348 {
349 ply_list_node_t *next_node;
350 ply_rectangle_t *area_to_flush;
351
352 area_to_flush = (ply_rectangle_t *) ply_list_node_get_data (node);
353
354 next_node = ply_list_get_next_node (areas_to_flush, node);
355
356 flush_area_to_device (backend, head, area_to_flush, cr);
357 gdk_window_clear_area (head->window->window,
358 area_to_flush->x,
359 area_to_flush->y,
360 area_to_flush->width,
361 area_to_flush->height);
362 node = next_node;
363 }
364 ply_region_clear (updated_region);
365
366 cairo_destroy (cr);
367
368 /* Force read-back to make sure plymouth isn't saturating the
369 * X server with requests
370 */
371 g_object_unref (gdk_drawable_get_image (GDK_DRAWABLE (head->pixmap),
372 0, 0, 1, 1));
373}
374
375static void
376ply_renderer_head_redraw (ply_renderer_backend_t *backend,
377 ply_renderer_head_t *head)
378{
379 ply_region_t *region;
380
381 region = ply_pixel_buffer_get_updated_areas (head->pixel_buffer);
382
383 ply_region_add_rectangle (region, &head->area);
384
385 flush_head (backend, head);
386}
387
388static ply_list_t *
389get_heads (ply_renderer_backend_t *backend)
390{
391 return backend->heads;
392}
393
394static ply_pixel_buffer_t *
395get_buffer_for_head (ply_renderer_backend_t *backend,
396 ply_renderer_head_t *head)
397{
398 if (head->backend != backend)
399 return NULL;
400
401 return head->pixel_buffer;
402}
403
404static bool
405has_input_source (ply_renderer_backend_t *backend,
406 ply_renderer_input_source_t *input_source)
407{
408 return input_source == &backend->input_source;
409}
410
411static ply_renderer_input_source_t *
412get_input_source (ply_renderer_backend_t *backend)
413{
414 return &backend->input_source;
415}
416
417static gboolean
418on_motion_notify_event (GtkWidget *widget,
419 GdkEventMotion *event,
420 gpointer user_data)
421{
422 ply_renderer_head_t *head = user_data;
423
424 gtk_window_begin_move_drag (GTK_WINDOW (head->window), 1,
425 event->x_root, event->y_root, event->time);
426 return FALSE;
427}
428
429static gboolean
430on_key_event (GtkWidget *widget,
431 GdkEventKey *event,
432 gpointer user_data)
433{
434 ply_renderer_input_source_t *input_source = user_data;
435
436 if (event->keyval == GDK_Return) /* Enter */
437 {
438 ply_buffer_append_bytes (input_source->key_buffer, "\r", 1);
439 }
440 else if (event->keyval == GDK_Escape) /* Esc */
441 {
442 ply_buffer_append_bytes (input_source->key_buffer, "\033", 1);
443 }
444 else if (event->keyval == GDK_BackSpace) /* Backspace */
445 {
446 ply_buffer_append_bytes (input_source->key_buffer, "\177", 1);
447 }
448 else
449 {
450 gchar bytes[7];
451 int byte_count;
452 guint32 unichar;
453 unichar = gdk_keyval_to_unicode (event->keyval);
454 byte_count = g_unichar_to_utf8 (unichar, bytes);
455 if (bytes[0] != 0)
456 ply_buffer_append_bytes (input_source->key_buffer, bytes, byte_count);
457 else
458 ply_trace ("unknown GDK key: 0x%X \"%s\"",
459 event->keyval,
460 gdk_keyval_name (event->keyval));
461 }
462
463 if (input_source->handler != NULL)
464 input_source->handler (input_source->user_data, input_source->key_buffer, input_source);
465 return FALSE;
466}
467
468static bool
469open_input_source (ply_renderer_backend_t *backend,
470 ply_renderer_input_source_t *input_source)
471{
472
473 assert (backend != NULL);
474 assert (has_input_source (backend, input_source));
475
476 return true;
477}
478
479static void
480set_handler_for_input_source (ply_renderer_backend_t *backend,
481 ply_renderer_input_source_t *input_source,
482 ply_renderer_input_source_handler_t handler,
483 void *user_data)
484{
485 assert (backend != NULL);
486 assert (has_input_source (backend, input_source));
487
488 input_source->handler = handler;
489 input_source->user_data = user_data;
490}
491
492static void
493close_input_source (ply_renderer_backend_t *backend,
494 ply_renderer_input_source_t *input_source)
495{
496 assert (backend != NULL);
497 assert (has_input_source (backend, input_source));
498}
499
500ply_renderer_plugin_interface_t *
501ply_renderer_backend_get_interface (void)
502{
503 static ply_renderer_plugin_interface_t plugin_interface =
504 {
505 .create_backend = create_backend,
506 .destroy_backend = destroy_backend,
507 .open_device = open_device,
508 .close_device = close_device,
509 .query_device = query_device,
510 .map_to_device = map_to_device,
511 .unmap_from_device = unmap_from_device,
512 .flush_head = flush_head,
513 .get_heads = get_heads,
514 .get_buffer_for_head = get_buffer_for_head,
515 .get_input_source = get_input_source,
516 .open_input_source = open_input_source,
517 .set_handler_for_input_source = set_handler_for_input_source,
518 .close_input_source = close_input_source
519 };
520 return &plugin_interface;
521}
522
523/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */