• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Révision68ce6f59e103467a3cf6beaee19c388b2d2f3d22 (tree)
l'heure2022-08-28 20:28:50
Auteurphabrics <phabrics@phab...>
Commiterphabrics

Message de Log

Work to add SDL driver to display host framework.

Change Summary

Modification

--- a/host/display/display-keyboard.c
+++ b/host/display/display-keyboard.c
@@ -225,15 +225,37 @@ _tme_keyboard_keyval_name(tme_keyboard_keyval_t keyval)
225225 }
226226 #endif
227227
228-/* this is a callback for a key press or release event: */
228+/* this is a generic callback for a key press or release event: */
229229 int
230-_tme_keyboard_key_event(struct tme_keyboard_event *tme_event,
231- struct tme_display *display)
230+_tme_keyboard_key_press(int down, tme_keyboard_keyval_t key, void *disp)
231+{
232+ struct tme_keyboard_event tme_event;
233+ struct tme_display *display = (_tme_display_get) ? (_tme_display_get(disp)) : (disp);
234+
235+ /* make a tme event from this key event: */
236+ tme_event.tme_keyboard_event_type
237+ = (down
238+ ? TME_KEYBOARD_EVENT_PRESS
239+ : TME_KEYBOARD_EVENT_RELEASE);
240+ tme_event.tme_keyboard_event_modifiers
241+ = TME_KEYBOARD_MODIFIER_NONE;
242+ tme_event.tme_keyboard_event_keyval
243+ = key;
244+ tme_event.tme_keyboard_event_time = tme_thread_get_time();
245+
246+ return _tme_keyboard_key_event(&tme_event, display);
247+}
248+
249+int
250+_tme_keyboard_key_event(struct tme_keyboard_event *tme_event, struct tme_display *display)
232251 {
233252 int was_empty;
234253 int new_callouts;
235254 int rc;
236255
256+ /* lock the mutex: */
257+ tme_mutex_lock(&display->tme_display_mutex);
258+
237259 /* assume that we won't need any new callouts: */
238260 new_callouts = 0;
239261
@@ -264,6 +286,9 @@ _tme_keyboard_key_event(struct tme_keyboard_event *tme_event,
264286 /* run any callouts: */
265287 //_tme_display_callout(display, new_callouts);
266288
289+ /* unlock the mutex: */
290+ tme_mutex_unlock(&display->tme_display_mutex);
291+
267292 /* don't process this event any further: */
268293 return (TRUE);
269294 }
--- a/host/display/display-mouse.c
+++ b/host/display/display-mouse.c
@@ -52,15 +52,71 @@ _tme_mouse_debug(const struct tme_mouse_event *event)
5252 #define _tme_mouse_debug(e) do { } while (/* CONSTCOND */ 0)
5353 #endif
5454
55-/* this is a callback for a mouse event in the framebuffer event box: */
55+/* this is a generic callback for a mouse event: */
5656 int
57-_tme_mouse_mouse_event(struct tme_keyboard_event *tme_event,
58- struct tme_display *display)
57+_tme_mouse_button_press(int button, int x, int y, struct tme_display *display)
5958 {
59+ int state;
60+
61+ /* make the buttons mask: */
62+ state = display->tme_screen_mouse_buttons_last;
63+
64+ if(button>0)
65+ state |= TME_BIT(button-1);
66+ else if(button) {
67+ button = -button;
68+ state &= ~TME_BIT(button-1);
69+ }
70+
71+ return _tme_mouse_buttons_event(state, x, y, display);
72+}
73+
74+int _tme_mouse_buttons_event(int buttons, int x, int y, void *disp)
75+{
76+ struct tme_mouse_event tme_event;
6077 int was_empty;
61- int new_callouts;
62- int rc;
78+ int new_callouts, rc;
79+ struct tme_display *display = (_tme_display_get) ? (_tme_display_get(disp)) : (disp);
80+
81+ /* start the tme event: */
82+ tme_event.tme_mouse_event_delta_units
83+ = TME_MOUSE_UNITS_UNKNOWN;
84+
85+ /* lock the mutex: */
86+ tme_mutex_lock(&display->tme_display_mutex);
6387
88+ /* set the event time: */
89+ tme_event.tme_mouse_event_time = tme_thread_get_time();
90+
91+ /* if the button mask and pointer position haven't changed, return now.
92+ every time we warp the pointer we will get a motion event, and
93+ this should ignore those events: */
94+
95+ if (buttons == display->tme_screen_mouse_buttons_last
96+ && x == display->tme_screen_mouse_warp_x
97+ && y == display->tme_screen_mouse_warp_y) {
98+
99+ /* unlock the mutex: */
100+ tme_mutex_unlock(&display->tme_display_mutex);
101+
102+ /* stop propagating this event: */
103+ return (TRUE);
104+ }
105+
106+ tme_event.tme_mouse_event_buttons =
107+ display->tme_screen_mouse_buttons_last = buttons;
108+
109+ /* make the deltas: */
110+ tme_event.tme_mouse_event_delta_x =
111+ (((int) x)
112+ - ((int) display->tme_screen_mouse_warp_x));
113+ tme_event.tme_mouse_event_delta_y =
114+ (((int) y)
115+ - ((int) display->tme_screen_mouse_warp_y));
116+
117+ display->tme_screen_mouse_warp_x = x;
118+ display->tme_screen_mouse_warp_y = y;
119+
64120 /* assume that we won't need any new callouts: */
65121 new_callouts = 0;
66122
@@ -69,9 +125,9 @@ _tme_mouse_mouse_event(struct tme_keyboard_event *tme_event,
69125 = tme_mouse_buffer_is_empty(display->tme_display_mouse_buffer);
70126
71127 /* add this tme event to the mouse buffer: */
72- _tme_mouse_debug(tme_event);
128+ _tme_mouse_debug(&tme_event);
73129 rc = tme_mouse_buffer_copyin(display->tme_display_mouse_buffer,
74- tme_event);
130+ &tme_event);
75131 assert (rc == TME_OK);
76132
77133 /* if the mouse buffer was empty and now it isn't,
@@ -87,6 +143,9 @@ _tme_mouse_mouse_event(struct tme_keyboard_event *tme_event,
87143 /* run any callouts: */
88144 //_tme_display_callout(display, new_callouts);
89145
146+ /* unlock the mutex: */
147+ tme_mutex_unlock(&display->tme_display_mutex);
148+
90149 /* don't process this event any further: */
91150 return (TRUE);
92151 }
@@ -111,8 +170,8 @@ _tme_mouse_ctrl(struct tme_mouse_connection *conn_mouse,
111170 /* this is called to read the mouse: */
112171 static int
113172 _tme_mouse_read(struct tme_mouse_connection *conn_mouse,
114- struct tme_mouse_event *event,
115- unsigned int count)
173+ struct tme_mouse_event *event,
174+ unsigned int count)
116175 {
117176 struct tme_display *display;
118177 int rc;
--- a/host/display/display.c
+++ b/host/display/display.c
@@ -203,6 +203,8 @@ int
203203 tme_display_update(void *disp) {
204204 struct tme_display *display;
205205 struct tme_screen *screen;
206+ struct tme_fb_connection *conn_fb;
207+ int width, height;
206208 int rc;
207209
208210 display = (struct tme_display *)disp;
@@ -219,6 +221,9 @@ tme_display_update(void *disp) {
219221
220222 _tme_display_callout(display, 0);
221223
224+ width = screen->tme_screen_fb->tme_fb_connection_width;
225+ height = screen->tme_screen_fb->tme_fb_connection_height;
226+
222227 /* loop over all screens: */
223228 for (screen = display->tme_display_screens;
224229 screen != NULL;
@@ -227,7 +232,7 @@ tme_display_update(void *disp) {
227232 switch(screen->tme_screen_update) {
228233 case TME_SCREEN_UPDATE_REDRAW:
229234 if(display->tme_screen_redraw)
230- display->tme_screen_redraw(screen);
235+ display->tme_screen_redraw(screen, 0, 0, width, height);
231236 break;
232237 case TME_SCREEN_UPDATE_RESIZE:
233238 if(display->tme_screen_resize)
@@ -555,6 +560,9 @@ _tme_screen_add(struct tme_display *display,
555560 /* save our connection: */
556561 screen->tme_screen_fb = conn;
557562
563+ /* default screen scale: */
564+ screen->tme_screen_scale = 1;
565+
558566 /* the user hasn't specified a scaling yet: */
559567 screen->tme_screen_fb_scale
560568 = -TME_FB_XLAT_SCALE_NONE;
@@ -598,7 +606,7 @@ _tme_display_connection_make(struct tme_connection *conn,
598606 if (state == TME_CONNECTION_FULL) {
599607
600608 /* lock our mutex: */
601- //tme_mutex_lock(&display->tme_display_mutex);
609+ tme_mutex_lock(&display->tme_display_mutex);
602610
603611 /* if our initial screen is already connected, make a new screen: */
604612 screen = (display->tme_screen_add) ?
@@ -606,10 +614,10 @@ _tme_display_connection_make(struct tme_connection *conn,
606614 tme_screen_new(display, struct tme_screen, conn);
607615
608616 /* unlock our mutex: */
609- //tme_mutex_unlock(&display->tme_display_mutex);
617+ tme_mutex_unlock(&display->tme_display_mutex);
610618
611619 /* call our mode change function: */
612- // _tme_screen_mode_change((struct tme_fb_connection *) conn);
620+ _tme_screen_mode_change((struct tme_fb_connection *) conn);
613621 }
614622
615623 return (TME_OK);
@@ -669,9 +677,14 @@ _tme_display_connections_new(struct tme_element *element,
669677 int tme_display_init(struct tme_element *element,
670678 struct tme_display *display) {
671679
680+ if(!display) display = tme_new0(struct tme_display, 1);
681+
672682 /* start our data structure: */
673683 display->tme_display_element = element;
674684
685+ /* default display: */
686+ _tme_display_get = 0;
687+
675688 /* create the keyboard: */
676689 _tme_keyboard_new(display);
677690
--- a/host/display/display.h
+++ b/host/display/display.h
@@ -70,7 +70,7 @@ struct tme_screen {
7070 struct tme_display *tme_screen_display;
7171
7272 /* the framebuffer connection. unlike many other elements, this is
73- *our* side of the framebuffer connection, not the peer's side: */
73+ *our* side of the framebuffer connection, not the peer's side: */
7474 struct tme_fb_connection *tme_screen_fb;
7575
7676 /* the current scaling. if this is < 0, the user has not forced a
@@ -152,16 +152,38 @@ struct tme_display {
152152 int tme_screen_width;
153153 int tme_screen_height;
154154
155+ /* screen mouse data: */
156+ int tme_screen_mouse_buttons_last,
157+ tme_screen_mouse_warp_x,
158+ tme_screen_mouse_warp_y;
159+
160+ /* a convenience pointer for any platform-specific host data: */
161+ void *tme_screen_data;
162+
155163 /* implementation-specific callback functions: */
156164 int (*tme_display_bell) _TME_P((struct tme_display *));
157165 int (*tme_display_update) _TME_P((struct tme_display *));
158166 struct tme_screen *(*tme_screen_add) _TME_P((struct tme_display *, struct tme_connection *));
159167 int (*tme_screen_resize) _TME_P((struct tme_screen *));
160- int (*tme_screen_redraw) _TME_P((struct tme_screen *));
168+ int (*tme_screen_redraw) _TME_P((struct tme_screen *, int x, int y, int w, int h));
161169 int (*tme_screen_update) _TME_P((struct tme_screen *));
162170 };
163171
164172 /* prototypes: */
173+/* this recovers the scanline-pad value for an image buffer: */
174+inline unsigned int
175+_tme_scanline_pad(int bpl)
176+{
177+ if ((bpl % sizeof(tme_uint32_t)) == 0) {
178+ return (32);
179+ }
180+ if ((bpl % sizeof(tme_uint16_t)) == 0) {
181+ return (16);
182+ }
183+ return (8);
184+}
185+
186+struct tme_display *(*_tme_display_get) _TME_P((void *));
165187 struct tme_screen *_tme_screen_add _TME_P((struct tme_display *,
166188 size_t,
167189 struct tme_connection *));
@@ -172,10 +194,12 @@ void _tme_screen_xlat_set _TME_P((struct tme_screen *screen));
172194 void _tme_keyboard_new _TME_P((struct tme_display *));
173195 int _tme_keyboard_connections_new _TME_P((struct tme_display *,
174196 struct tme_connection **));
197+int _tme_keyboard_key_press _TME_P((int down, tme_keyboard_keyval_t key, void *disp));
175198 void _tme_mouse_new _TME_P((struct tme_display *));
176199 void _tme_mouse_mode_off _TME_P((struct tme_screen *, tme_uint32_t));
177200 int _tme_mouse_connections_new _TME_P((struct tme_display *,
178201 struct tme_connection **));
202+int _tme_mouse_buttons_event _TME_P((int buttons, int x, int y, void *disp));
179203
180204 #endif /* _HOST_DISPLAY_H */
181205
--- a/host/display/gtk/Makefile.am
+++ b/host/display/gtk/Makefile.am
@@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = 1.4 gnu
66 AM_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(top_srcdir)/lib -I$(srcdir)/.. -I. -D_TME_IMPL $(GTK_CFLAGS)
77
88 pkglib_LTLIBRARIES = tme_host_gtk.la
9-tme_host_gtk_la_SOURCES = gtk-mouse.c gtk-keyboard.c gtk-screen.c gtk-display.h
9+tme_host_gtk_la_SOURCES = gtk-mouse.c gtk-keyboard.c gtk-display.c gtk-display.h
1010 tme_host_gtk_la_LDFLAGS = -module -version-info 0:0:0
1111 tme_host_gtk_la_LIBADD = ../libtme-display.la $(GTK_LIBS)
1212
--- a/host/display/gtk/gtk-screen.c
+++ b/host/display/gtk/gtk-display.c
@@ -52,19 +52,6 @@ _tme_gtk_display_update(struct tme_display *display) {
5252 return TME_OK;
5353 }
5454
55-/* this recovers the scanline-pad value for an image buffer: */
56-static unsigned int
57-_tme_gtk_scanline_pad(int bpl)
58-{
59- if ((bpl % sizeof(tme_uint32_t)) == 0) {
60- return (32);
61- }
62- if ((bpl % sizeof(tme_uint16_t)) == 0) {
63- return (16);
64- }
65- return (8);
66-}
67-
6855 /* this sets the screen scaling to that indicated by the Scale menu: */
6956 static void
7057 _tme_gtk_screen_scale_default(GtkWidget *widget,
@@ -297,7 +284,7 @@ _tme_gtk_screen_configure(GtkWidget *widget,
297284 conn_fb->tme_fb_connection_width = cairo_image_surface_get_width(screen->tme_gtk_screen_surface);
298285 conn_fb->tme_fb_connection_height = cairo_image_surface_get_height(screen->tme_gtk_screen_surface);
299286 conn_fb->tme_fb_connection_skipx = 0;
300- conn_fb->tme_fb_connection_scanline_pad = _tme_gtk_scanline_pad(cairo_image_surface_get_stride(screen->tme_gtk_screen_surface));
287+ conn_fb->tme_fb_connection_scanline_pad = _tme_scanline_pad(cairo_image_surface_get_stride(screen->tme_gtk_screen_surface));
301288 conn_fb->tme_fb_connection_order = TME_ENDIAN_NATIVE;
302289 conn_fb->tme_fb_connection_buffer = cairo_image_surface_get_data(screen->tme_gtk_screen_surface);
303290 conn_fb->tme_fb_connection_buffsz = cairo_image_surface_get_stride(screen->tme_gtk_screen_surface) * conn_fb->tme_fb_connection_height;
@@ -317,7 +304,7 @@ _tme_gtk_screen_configure(GtkWidget *widget,
317304
318305 /* this is called before the screen's display is updated: */
319306 static void
320-_tme_gtk_screen_redraw(struct tme_gtk_screen *screen)
307+_tme_gtk_screen_redraw(struct tme_gtk_screen *screen, int x, int y, int w, int h)
321308 {
322309 cairo_surface_flush(screen->tme_gtk_screen_surface);
323310 cairo_surface_mark_dirty(screen->tme_gtk_screen_surface);
@@ -367,9 +354,6 @@ _tme_gtk_screen_new(struct tme_gdk_display *display,
367354 GtkWidget *menu_item;
368355 char title[sizeof(PACKAGE_STRING) + 16];
369356
370- /* lock our mutex: */
371- tme_mutex_lock(&display->display.tme_display_mutex);
372-
373357 screen = tme_screen_new(display, struct tme_gtk_screen, conn);
374358
375359 screen->screen.tme_screen_scale = gdk_monitor_get_scale_factor(display->tme_gdk_display_monitor);
@@ -455,14 +439,15 @@ _tme_gtk_screen_new(struct tme_gdk_display *display,
455439 snprintf(title, sizeof(title), "%s (%s)", PACKAGE_STRING, conn->tme_connection_other->tme_connection_element->tme_element_args[0]);
456440 gtk_window_set_title(GTK_WINDOW(screen->tme_gtk_screen_window), title);
457441
458- _tme_gtk_screen_resize(screen);
459-
460442 /* unlock our mutex: */
461443 tme_mutex_unlock(&display->display.tme_display_mutex);
462444
463445 /* show the top-level window: */
464446 gtk_widget_show_all(screen->tme_gtk_screen_window);
465447
448+ /* lock our mutex: */
449+ tme_mutex_lock(&display->display.tme_display_mutex);
450+
466451 return (screen);
467452 }
468453
--- a/host/display/gtk/gtk-display.h
+++ b/host/display/gtk/gtk-display.h
@@ -97,12 +97,6 @@ struct tme_gtk_screen {
9797 for the framebuffer event box: */
9898 GdkEventMask tme_gtk_screen_mouse_events_old;
9999
100- /* when mouse mode is on, this is the warp center: */
101- gint tme_gtk_screen_mouse_warp_x;
102- gint tme_gtk_screen_mouse_warp_y;
103-
104- /* when mouse mode is on, the last tme buttons state: */
105- unsigned int tme_gtk_screen_mouse_buttons_last;
106100 };
107101
108102 /* a menu item: */
--- a/host/display/gtk/gtk-mouse.c
+++ b/host/display/gtk/gtk-mouse.c
@@ -40,6 +40,7 @@ _TME_RCSID("$Id: gtk-mouse.c,v 1.3 2007/03/03 15:33:22 fredette Exp $");
4040 #include "gtk-display.h"
4141 #include <gdk/gdkkeysyms.h>
4242
43+#if 0
4344 /* this warps the pointer to the middle of the Gtkframe: */
4445 void
4546 _tme_gtk_mouse_warp_pointer(struct tme_gtk_screen *screen)
@@ -51,133 +52,56 @@ _tme_gtk_mouse_warp_pointer(struct tme_gtk_screen *screen)
5152
5253 gdk_device_warp(gdk_seat_get_pointer(display->tme_gdk_display_seat),
5354 gdk_screen_get_default(),
54- screen->tme_gtk_screen_mouse_warp_x,
55- screen->tme_gtk_screen_mouse_warp_y);
55+ screen->screen.tme_screen_mouse_warp_x,
56+ screen->screen.tme_screen_mouse_warp_y);
5657 }
57-
58+#endif
5859 /* this is a GTK callback for a mouse event in the framebuffer event box: */
5960 static int
6061 _tme_gtk_mouse_mouse_event(GtkWidget *widget,
6162 GdkEvent *gdk_event_raw,
62- struct tme_gtk_screen *screen)
63+ struct tme_gtk_screen *display)
6364 {
64- struct tme_display *display;
65- struct tme_mouse_event tme_event;
6665 gint x;
6766 gint y;
68- guint state, button;
69- unsigned int buttons;
70- int was_empty;
71- int new_callouts;
72- int rc;
73-
74- /* start the tme event: */
75- tme_event.tme_mouse_event_delta_units
76- = TME_MOUSE_UNITS_UNKNOWN;
77-
78- /* recover our data structure: */
79- display = screen->screen.tme_screen_display;
80-
81- /* lock the mutex: */
82- tme_mutex_lock(&display->tme_display_mutex);
67+ int button=0;
8368
8469 /* if this is motion: */
8570 if (gdk_event_raw->type == GDK_MOTION_NOTIFY) {
8671
87- /* this event must have happened in the gtkframe: */
88- assert (gdk_event_raw->motion.window
89- == gtk_widget_get_window(screen->tme_gtk_screen_gtkframe));
90-
91- /* set the event time: */
92- tme_event.tme_mouse_event_time
93- = gdk_event_raw->motion.time;
94-
95- /* the buttons haven't changed: */
96- tme_event.tme_mouse_event_buttons =
97- screen->tme_gtk_screen_mouse_buttons_last;
98-
9972 /* if the pointer position hasn't changed either, return now.
10073 every time we warp the pointer we will get a motion event, and
10174 this should ignore those events: */
10275 x = gdk_event_raw->motion.x_root;
10376 y = gdk_event_raw->motion.y_root;
104- if (x == screen->tme_gtk_screen_mouse_warp_x
105- && y == screen->tme_gtk_screen_mouse_warp_y) {
106-
107- /* unlock the mutex: */
108- tme_mutex_unlock(&display->tme_display_mutex);
109-
110- /* stop propagating this event: */
111- return (TRUE);
112- }
113-
114- }
115-
116- /* otherwise, if this is a double- or triple-click: */
117- else if (gdk_event_raw->type == GDK_2BUTTON_PRESS
118- || gdk_event_raw->type == GDK_3BUTTON_PRESS) {
119-
120- /* we ignore double- and triple-click events, since normal button
121- press and release events are always generated also: */
122-
123- /* unlock the mutex: */
124- tme_mutex_unlock(&display->tme_display_mutex);
12577
126- /* stop propagating this event: */
127- return (TRUE);
12878 }
12979
13080 /* otherwise, this must be a button press or a release: */
13181 else {
132- assert (gdk_event_raw->type == GDK_BUTTON_PRESS
133- || gdk_event_raw->type == GDK_BUTTON_RELEASE);
134-
135- /* this event must have happened in the gtkframe: */
136- assert (gdk_event_raw->button.window
137- == gtk_widget_get_window(screen->tme_gtk_screen_gtkframe));
138-
139- /* set the event time: */
140- tme_event.tme_mouse_event_time
141- = gdk_event_raw->button.time;
14282
14383 /* get the pointer position: */
14484 x = gdk_event_raw->button.x_root;
14585 y = gdk_event_raw->button.y_root;
14686
14787 /* make the buttons mask: */
148- buttons = 0;
14988 button = gdk_event_raw->button.button;
150- state = gdk_event_raw->button.state;
151-#define _TME_GTK_MOUSE_BUTTON(i, gdk, tme) \
152- if ((button == i) \
153- ? (gdk_event_raw->type == GDK_BUTTON_PRESS) \
154- : (state & gdk)) \
155- buttons |= tme
156- _TME_GTK_MOUSE_BUTTON(1, GDK_BUTTON1_MASK, TME_MOUSE_BUTTON_0);
157- _TME_GTK_MOUSE_BUTTON(2, GDK_BUTTON2_MASK, TME_MOUSE_BUTTON_1);
158- _TME_GTK_MOUSE_BUTTON(3, GDK_BUTTON3_MASK, TME_MOUSE_BUTTON_2);
159- _TME_GTK_MOUSE_BUTTON(4, GDK_BUTTON4_MASK, TME_MOUSE_BUTTON_3);
160- _TME_GTK_MOUSE_BUTTON(5, GDK_BUTTON5_MASK, TME_MOUSE_BUTTON_4);
161-#undef _TME_GTK_MOUSE_BUTTON
162- tme_event.tme_mouse_event_buttons = buttons;
163- screen->tme_gtk_screen_mouse_buttons_last = buttons;
89+ if(gdk_event_raw->type == GDK_BUTTON_RELEASE)
90+ button = -button;
16491 }
16592
166- /* make the deltas: */
167- tme_event.tme_mouse_event_delta_x =
168- (((int) x)
169- - ((int) screen->tme_gtk_screen_mouse_warp_x));
170- tme_event.tme_mouse_event_delta_y =
171- (((int) y)
172- - ((int) screen->tme_gtk_screen_mouse_warp_y));
93+ /* otherwise, if this is a double- or triple-click: */
94+ if (gdk_event_raw->type != GDK_2BUTTON_PRESS
95+ && gdk_event_raw->type != GDK_3BUTTON_PRESS) {
17396
174- screen->tme_gtk_screen_mouse_warp_x = x;
175- screen->tme_gtk_screen_mouse_warp_y = y;
176-
177- _tme_mouse_mouse_event(&tme_event, display);
97+ /* we ignore double- and triple-click events, since normal button
98+ press and release events are always generated also: */
99+ assert (gdk_event_raw->type == GDK_BUTTON_PRESS
100+ || gdk_event_raw->type == GDK_BUTTON_RELEASE);
101+
102+ _tme_mouse_button_press(button, x, y, display);
178103
179- /* unlock the mutex: */
180- tme_mutex_unlock(&display->tme_display_mutex);
104+ }
181105
182106 /* stop propagating this event: */
183107 return (TRUE);
@@ -267,8 +191,8 @@ _tme_gtk_mouse_ebox_event(GtkWidget *widget,
267191
268192 gdk_device_get_position(gdk_seat_get_pointer(display->tme_gdk_display_seat),
269193 NULL,
270- &screen->tme_gtk_screen_mouse_warp_x,
271- &screen->tme_gtk_screen_mouse_warp_y);
194+ &display->display.tme_screen_mouse_warp_x,
195+ &display->display.tme_screen_mouse_warp_y);
272196
273197 /* we are now in mouse mode: */
274198 screen->tme_gtk_screen_mouse_keyval
@@ -319,13 +243,9 @@ _tme_gtk_mouse_mode_off(struct tme_gtk_screen *screen,
319243 void
320244 _tme_gtk_mouse_attach(struct tme_gtk_screen *screen)
321245 {
322- struct tme_display *display;
323246 GtkWidget *hbox0;
324247 GtkWidget *ebox;
325248
326- /* get the display: */
327- display = screen->screen.tme_screen_display;
328-
329249 /* create the horizontal packing box for the mouse controls: */
330250 hbox0 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
331251
@@ -402,15 +322,15 @@ _tme_gtk_mouse_attach(struct tme_gtk_screen *screen)
402322 g_signal_connect(screen->tme_gtk_screen_gtkframe,
403323 "motion_notify_event",
404324 G_CALLBACK(_tme_gtk_mouse_mouse_event),
405- screen);
325+ screen->screen.tme_screen_display);
406326 g_signal_connect(screen->tme_gtk_screen_gtkframe,
407327 "button_press_event",
408328 G_CALLBACK(_tme_gtk_mouse_mouse_event),
409- screen);
329+ screen->screen.tme_screen_display);
410330 g_signal_connect(screen->tme_gtk_screen_gtkframe,
411331 "button_release_event",
412332 G_CALLBACK(_tme_gtk_mouse_mouse_event),
413- screen);
333+ screen->screen.tme_screen_display);
414334
415335 /* mouse mode is off: */
416336 screen->tme_gtk_screen_mouse_keyval = GDK_KEY_VoidSymbol;
--- a/host/display/rfb/rfb-display.c
+++ b/host/display/rfb/rfb-display.c
@@ -41,44 +41,18 @@
4141 #include <stdlib.h>
4242
4343 static const int bpp=4;
44-static struct tme_display *_display;
45-/* TODO: odd maxx doesn't work (vncviewer bug) */
46-
47-typedef struct tme_rfb_screen {
48- int tme_rfb_screen_mouse_buttons_last,
49- tme_rfb_screen_mouse_warp_x,
50- tme_rfb_screen_mouse_warp_y;
51-} tme_rfb_screen;
52-
53-typedef struct tme_rfb_display {
54- /* the generic display structure */
55- struct tme_display display;
56-
57- rfbScreenInfoPtr server;
58-} tme_rfb_display;
59-
60-static void _tme_rfb_clientgone(rfbClientPtr cl)
61-{
62- free(cl->clientData);
63- cl->clientData = NULL;
64-}
6544
66-static enum rfbNewClientAction _tme_rfb_newclient(rfbClientPtr cl)
67-{
68- cl->clientData = tme_new0(struct tme_rfb_screen, 1);
69- cl->clientGoneHook = _tme_rfb_clientgone;
70- return RFB_CLIENT_ACCEPT;
71-}
45+/* TODO: odd maxx doesn't work (vncviewer bug) */
7246
7347 static void
74-_tme_rfb_display_bell(struct tme_rfb_display *display) {
75- rfbSendBell(display->server);
48+_tme_rfb_display_bell(struct tme_display *display) {
49+ rfbSendBell(display->tme_screen_data);
7650 }
7751
7852 static int
7953 _tme_rfb_display_update(struct tme_display *display) {
8054 long usec;
81- rfbScreenInfoPtr server = ((tme_rfb_display *)display)->server;
55+ rfbScreenInfoPtr server = display->tme_screen_data;
8256
8357 if(!rfbIsActive(server)) return 1;
8458
@@ -89,15 +63,12 @@ _tme_rfb_display_update(struct tme_display *display) {
8963
9064 /* this is called before the screen's display is updated: */
9165 static void
92-_tme_rfb_screen_redraw(struct tme_screen *screen)
66+_tme_rfb_screen_redraw(struct tme_screen *screen, int x, int y, int w, int h)
9367 {
94- struct tme_fb_connection *conn_fb = screen->tme_screen_fb;
95- rfbScreenInfoPtr server = ((tme_rfb_display *)screen->tme_screen_display)->server;
68+ rfbScreenInfoPtr server = screen->tme_screen_display->tme_screen_data;
9669
97- if((char *)conn_fb->tme_fb_connection_buffer == server->frameBuffer)
98- rfbMarkRectAsModified(server, 0, 0,
99- conn_fb->tme_fb_connection_width,
100- conn_fb->tme_fb_connection_height);
70+ if((char *)screen->tme_screen_fb->tme_fb_connection_buffer == server->frameBuffer)
71+ rfbMarkRectAsModified(server, x, y, w, h);
10172 }
10273
10374 /* switch to new framebuffer contents */
@@ -107,9 +78,10 @@ static void _tme_rfb_screen_resize(struct tme_screen *screen)
10778 struct tme_fb_connection *conn_fb = screen->tme_screen_fb;
10879 int width = conn_fb->tme_fb_connection_width;
10980 int height = conn_fb->tme_fb_connection_height;
110- rfbScreenInfoPtr server = ((tme_rfb_display *)screen->tme_screen_display)->server;
81+ rfbScreenInfoPtr server = screen->tme_screen_display->tme_screen_data;
11182
11283 conn_fb->tme_fb_connection_buffsz = width * height * bpp;
84+ conn_fb->tme_fb_connection_scanline_pad = _tme_scanline_pad(width * bpp);
11385 newfb = (unsigned char*)tme_malloc(conn_fb->tme_fb_connection_buffsz);
11486 if(!conn_fb->tme_fb_connection_buffer ||
11587 (char *)conn_fb->tme_fb_connection_buffer == server->frameBuffer) {
@@ -122,25 +94,19 @@ static void _tme_rfb_screen_resize(struct tme_screen *screen)
12294
12395 /* this makes a new screen: */
12496 struct tme_screen *
125-_tme_rfb_screen_new(struct tme_rfb_display *display,
97+_tme_rfb_screen_new(struct tme_display *display,
12698 struct tme_connection *conn)
12799 {
128100 struct tme_screen *screen;
129101 struct tme_fb_connection *conn_fb;
130- rfbPixelFormat* format=&display->server->serverFormat;
131-
132- /* lock our mutex: */
133- tme_mutex_lock(&display->display.tme_display_mutex);
102+ rfbPixelFormat* format=&((rfbScreenInfoPtr)display->tme_screen_data)->serverFormat;
134103
135104 screen = tme_screen_new(display, struct tme_screen, conn);
136105
137- screen->tme_screen_scale = 1;
138-
139106 conn_fb = screen->tme_screen_fb;
140107
141108 /* update our framebuffer connection: */
142109 conn_fb->tme_fb_connection_skipx = 0;
143- conn_fb->tme_fb_connection_scanline_pad = 4 * bpp;
144110 conn_fb->tme_fb_connection_order = (format->bigEndian) ? (TME_ENDIAN_BIG) : (TME_ENDIAN_LITTLE);
145111 conn_fb->tme_fb_connection_bits_per_pixel = format->bitsPerPixel;
146112 conn_fb->tme_fb_connection_depth = format->depth;
@@ -149,144 +115,69 @@ _tme_rfb_screen_new(struct tme_rfb_display *display,
149115 conn_fb->tme_fb_connection_mask_b = format->blueMax << format->blueShift;
150116 conn_fb->tme_fb_connection_mask_r = format->redMax << format->redShift;
151117
152- _tme_screen_configure(screen);
153-
154- /* unlock our mutex: */
155- tme_mutex_unlock(&display->display.tme_display_mutex);
156-
157118 /* We've handled the configure event, no need for further processing. */
158119 return (screen);
159120 }
160121
161-/* this is a VNC callback for a key press or release event: */
162-static void
163-_tme_rfb_key_event(rfbBool down, rfbKeySym key, rfbClientPtr cl)
164-{
165- struct tme_keyboard_event tme_event;
166-
167- /* make a tme event from this rfb event: */
168- tme_event.tme_keyboard_event_type
169- = (down
170- ? TME_KEYBOARD_EVENT_PRESS
171- : TME_KEYBOARD_EVENT_RELEASE);
172- tme_event.tme_keyboard_event_modifiers
173- = TME_KEYBOARD_MODIFIER_NONE;
174- tme_event.tme_keyboard_event_keyval
175- = key;
176- tme_event.tme_keyboard_event_time = tme_thread_get_time();
177-
178- /* lock the mutex: */
179- tme_mutex_lock(&_display->tme_display_mutex);
180-
181- _tme_keyboard_key_event(&tme_event, _display);
182-
183- /* unlock the mutex: */
184- tme_mutex_unlock(&_display->tme_display_mutex);
122+static struct tme_display *display;
185123
124+static void _tme_rfb_clientgone(rfbClientPtr cl)
125+{
126+ cl->clientData = NULL;
186127 }
187128
188-/* this is a VNC callback for a mouse event: */
189-static int
190-_tme_rfb_mouse_event(int buttonMask, int x, int y, rfbClientPtr cl)
129+static enum rfbNewClientAction _tme_rfb_newclient(rfbClientPtr cl)
191130 {
192- struct tme_mouse_event tme_event;
193- struct tme_rfb_screen *screen = (tme_rfb_screen *)cl->clientData;
194-
195- /* start the tme event: */
196- tme_event.tme_mouse_event_delta_units
197- = TME_MOUSE_UNITS_UNKNOWN;
198-
199- /* lock the mutex: */
200- tme_mutex_lock(&_display->tme_display_mutex);
201-
202- /* set the event time: */
203- tme_event.tme_mouse_event_time = tme_thread_get_time();
204-
205- /* if the button mask and pointer position haven't changed, return now.
206- every time we warp the pointer we will get a motion event, and
207- this should ignore those events: */
208-
209- if (buttonMask == screen->tme_rfb_screen_mouse_buttons_last
210- && x == screen->tme_rfb_screen_mouse_warp_x
211- && y == screen->tme_rfb_screen_mouse_warp_y) {
212-
213- /* unlock the mutex: */
214- tme_mutex_unlock(&_display->tme_display_mutex);
215-
216- /* stop propagating this event: */
217- return (TRUE);
218- }
219-
220- /* make the buttons mask: */
221- tme_event.tme_mouse_event_buttons =
222- screen->tme_rfb_screen_mouse_buttons_last = buttonMask;
223-
224- /* make the deltas: */
225- tme_event.tme_mouse_event_delta_x =
226- (((int) x)
227- - ((int) screen->tme_rfb_screen_mouse_warp_x));
228- tme_event.tme_mouse_event_delta_y =
229- (((int) y)
230- - ((int) screen->tme_rfb_screen_mouse_warp_y));
231-
232- screen->tme_rfb_screen_mouse_warp_x = x;
233- screen->tme_rfb_screen_mouse_warp_y = y;
234-
235- _tme_mouse_mouse_event(&tme_event, _display);
236-
237- /* unlock the mutex: */
238- tme_mutex_unlock(&_display->tme_display_mutex);
239-
240- rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
241-
242- /* stop propagating this event: */
243- return (TRUE);
131+ cl->clientData = display;
132+ cl->clientGoneHook = _tme_rfb_clientgone;
133+ return RFB_CLIENT_ACCEPT;
244134 }
245135
136+static struct tme_display *tme_rfb_display(rfbClientPtr cl) { return cl->clientData; }
137+
246138 /* the new RFB display function: */
247139 TME_ELEMENT_SUB_NEW_DECL(tme_host_rfb,display) {
248140 rfbScreenInfoPtr server;
249- struct tme_rfb_display *display;
250141 int arg_i = 0;
251142
252143 while(args[++arg_i] != NULL);
253144
254145 /* start our data structure: */
255- display = tme_new0(struct tme_rfb_display, 1);
256- tme_display_init(element, display);
146+ tme_display_init(element, 0);
257147
148+ _tme_display_get = tme_rfb_display;
149+
258150 /* recover our data structure: */
259151 display = element->tme_element_private;
260152
261153 /* allocate initial screen structure of the given size: */
262154 // rfbProcessSizeArguments(&maxx, &maxy, &bpp, &arg_i, args);
263155 server=rfbGetScreen(&arg_i,args,
264- display->display.tme_screen_width,
265- display->display.tme_screen_height,
156+ display->tme_screen_width,
157+ display->tme_screen_height,
266158 8,3,bpp);
267159 if(!server)
268160 return 1;
269161 server->desktopName = "The Machine Emulator";
270- server->frameBuffer = (char*)tme_malloc(display->display.tme_screen_width *
271- display->display.tme_screen_height *
162+ server->frameBuffer = (char*)tme_malloc(display->tme_screen_width *
163+ display->tme_screen_height *
272164 bpp);
273165 server->alwaysShared = TRUE;
274- server->ptrAddEvent = _tme_rfb_mouse_event;
275- server->kbdAddEvent = _tme_rfb_key_event;
166+ server->ptrAddEvent = _tme_mouse_buttons_event;
167+ server->kbdAddEvent = _tme_keyboard_key_press;
276168 server->newClientHook = _tme_rfb_newclient;
277169 // server->httpDir = "../webclients";
278170 // server->httpEnableProxyConnect = TRUE;
279171 rfbInitServer(server);
280172
281- display->server = server;
173+ display->tme_screen_data = server;
282174
283175 /* set the display-specific functions: */
284- display->display.tme_display_bell = _tme_rfb_display_bell;
285- display->display.tme_display_update = _tme_rfb_display_update;
286- display->display.tme_screen_add = _tme_rfb_screen_new;
287- display->display.tme_screen_resize = _tme_rfb_screen_resize;
288- display->display.tme_screen_redraw = _tme_rfb_screen_redraw;
176+ display->tme_display_bell = _tme_rfb_display_bell;
177+ display->tme_display_update = _tme_rfb_display_update;
178+ display->tme_screen_add = _tme_rfb_screen_new;
179+ display->tme_screen_resize = _tme_rfb_screen_resize;
180+ display->tme_screen_redraw = _tme_rfb_screen_redraw;
289181
290- _display = display;
291182 return (TME_OK);
292183 }
--- /dev/null
+++ b/host/display/sdl/sdl-display.c
@@ -0,0 +1,385 @@
1+/* host/sdl/sdl-display.c - SDL2 support: */
2+
3+/*
4+ * Copyright (c) 2022 Ruben Agin
5+ * All rights reserved.
6+ *
7+ * Redistribution and use in source and binary forms, with or without
8+ * modification, are permitted provided that the following conditions
9+ * are met:
10+ * 1. Redistributions of source code must retain the above copyright
11+ * notice, this list of conditions and the following disclaimer.
12+ * 2. Redistributions in binary form must reproduce the above copyright
13+ * notice, this list of conditions and the following disclaimer in the
14+ * documentation and/or other materials provided with the distribution.
15+ * 3. All advertising materials mentioning features or use of this software
16+ * must display the following acknowledgement:
17+ * This product includes software developed by Matt Fredette.
18+ * 4. The name of the author may not be used to endorse or promote products
19+ * derived from this software without specific prior written permission.
20+ *
21+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31+ * POSSIBILITY OF SUCH DAMAGE.
32+ */
33+
34+#include <tme/common.h>
35+
36+/* includes: */
37+#include "display.h"
38+#include <SDL.h>
39+#include <signal.h>
40+
41+struct { char mask; int bits_stored; } utf8Mapping[]= {
42+ {0b00111111, 6},
43+ {0b01111111, 7},
44+ {0b00011111, 5},
45+ {0b00001111, 4},
46+ {0b00000111, 3},
47+ {0,0}
48+};
49+
50+/* TODO: odd maxx doesn't work (vncviewer bug) */
51+
52+static int enableResizable = 1, viewOnly, listenLoop;
53+struct tme_sdl_screen {
54+ /* the generic screen structure */
55+ struct tme_screen screen;
56+ int sdlFlags;
57+ SDL_Surface* sdl;
58+ SDL_Texture *sdlTexture;
59+ SDL_Renderer *sdlRenderer;
60+ SDL_Window *sdlWindow;
61+};
62+
63+/* client's pointer position */
64+int x,y;
65+static int rightAltKeyDown, leftAltKeyDown;
66+/* switch to new framebuffer contents */
67+static void _tme_sdl_screen_resize(struct tme_sdl_screen *screen)
68+{
69+ unsigned char *oldfb, *newfb;
70+ struct tme_fb_connection *conn_fb = screen->screen.tme_screen_fb;
71+ int width = conn_fb->tme_fb_connection_width;
72+ int height = conn_fb->tme_fb_connection_height;
73+ int depth = SDL_BITSPERPIXEL(SDL_PIXELFORMAT_RGBA32);
74+
75+ if (enableResizable)
76+ screen->sdlFlags |= SDL_WINDOW_RESIZABLE;
77+
78+ /* (re)create the surface used as the client's framebuffer */
79+ SDL_FreeSurface(screen->sdl);
80+ screen->sdl=SDL_CreateRGBSurface(0,
81+ width,
82+ height,
83+ depth,
84+ 0,0,0,0);
85+ if(!screen->sdl)
86+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
87+ (&display->tme_display_element->tme_element_log_handle,
88+ _("resize: error creating surface: %s\n", SDL_GetError())));
89+
90+ /* update our framebuffer connection: */
91+ conn_fb->tme_fb_connection_width = screen->sdl->pitch / (depth / 8);
92+ conn_fb->tme_fb_connection_buffer = screen->sdl->pixels;
93+ conn_fb->tme_fb_connection_buffsz = screen->sdl->pitch * height;
94+ conn_fb->tme_fb_connection_skipx = 0;
95+ conn_fb->tme_fb_connection_scanline_pad = _tme_scanline_pad(screen->sdl->pitch);
96+ conn_fb->tme_fb_connection_order = TME_ENDIAN_LITTLE;
97+ conn_fb->tme_fb_connection_bits_per_pixel = depth;
98+ conn_fb->tme_fb_connection_depth = 24;
99+ conn_fb->tme_fb_connection_class = TME_FB_XLAT_CLASS_COLOR;
100+ conn_fb->tme_fb_connection_mask_g = screen->sdl->format->Gmask >> screen->sdl->format->Gshift;
101+ conn_fb->tme_fb_connection_mask_b = screen->sdl->format->Bmask >> screen->sdl->format->Bshift;
102+ conn_fb->tme_fb_connection_mask_r = screen->sdl->format->Rmask >> screen->sdl->format->Rshift;
103+ /* create or resize the window */
104+ if(!screen->sdlWindow) {
105+ screen->sdlWindow = SDL_CreateWindow(display->desktopName,
106+ SDL_WINDOWPOS_UNDEFINED,
107+ SDL_WINDOWPOS_UNDEFINED,
108+ width,
109+ height,
110+ screen->sdlFlags);
111+ if(!screen->sdlWindow)
112+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
113+ (&display->tme_display_element->tme_element_log_handle,
114+ _("resize: error creating window: %s\n", SDL_GetError())));
115+ } else {
116+ SDL_SetWindowSize(screen->sdlWindow, width, height);
117+ }
118+ /* create the renderer if it does not already exist */
119+ if(!screen->sdlRenderer) {
120+ screen->sdlRenderer = SDL_CreateRenderer(screen->sdlWindow, -1, 0);
121+ if(!screen->sdlRenderer)
122+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
123+ (&display->tme_display_element->tme_element_log_handle,
124+ _("resize: error creating renderer: %s\n", SDL_GetError())));
125+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); /* make the scaled rendering look smoother. */
126+ }
127+ SDL_RenderSetLogicalSize(screen->sdlRenderer, width, height); /* this is a departure from the SDL1.2-based version, but more in the sense of a VNC viewer in keeeping aspect ratio */
128+ /* (re)create the texture that sits in between the surface->pixels and the renderer */
129+ if(screen->sdlTexture)
130+ SDL_DestroyTexture(screen->sdlTexture);
131+ screen->sdlTexture = SDL_CreateTexture(screen->sdlRenderer,
132+ SDL_PIXELFORMAT_ARGB8888,
133+ SDL_TEXTUREACCESS_STREAMING,
134+ width, height);
135+ if(!screen->sdlTexture)
136+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
137+ (&display->tme_display_element->tme_element_log_handle,
138+ _("resize: error creating texture: %s\n", SDL_GetError())));
139+ return TRUE;
140+}
141+#if 0
142+static tme_keyboard_keyval_t SDL_key2rfbKeySym(SDL_KeyboardEvent* e) {
143+ tme_keyboard_keyval_t k = 0;
144+ SDL_Keycode sym = e->keysym.sym;
145+ switch (sym) {
146+ case SDLK_BACKSPACE: k = XK_BackSpace; break;
147+ case SDLK_TAB: k = XK_Tab; break;
148+ case SDLK_CLEAR: k = XK_Clear; break;
149+ case SDLK_RETURN: k = XK_Return; break;
150+ case SDLK_PAUSE: k = XK_Pause; break;
151+ case SDLK_ESCAPE: k = XK_Escape; break;
152+ case SDLK_DELETE: k = XK_Delete; break;
153+ case SDLK_KP_0: k = XK_KP_0; break;
154+ case SDLK_KP_1: k = XK_KP_1; break;
155+ case SDLK_KP_2: k = XK_KP_2; break;
156+ case SDLK_KP_3: k = XK_KP_3; break;
157+ case SDLK_KP_4: k = XK_KP_4; break;
158+ case SDLK_KP_5: k = XK_KP_5; break;
159+ case SDLK_KP_6: k = XK_KP_6; break;
160+ case SDLK_KP_7: k = XK_KP_7; break;
161+ case SDLK_KP_8: k = XK_KP_8; break;
162+ case SDLK_KP_9: k = XK_KP_9; break;
163+ case SDLK_KP_PERIOD: k = XK_KP_Decimal; break;
164+ case SDLK_KP_DIVIDE: k = XK_KP_Divide; break;
165+ case SDLK_KP_MULTIPLY: k = XK_KP_Multiply; break;
166+ case SDLK_KP_MINUS: k = XK_KP_Subtract; break;
167+ case SDLK_KP_PLUS: k = XK_KP_Add; break;
168+ case SDLK_KP_ENTER: k = XK_KP_Enter; break;
169+ case SDLK_KP_EQUALS: k = XK_KP_Equal; break;
170+ case SDLK_UP: k = XK_Up; break;
171+ case SDLK_DOWN: k = XK_Down; break;
172+ case SDLK_RIGHT: k = XK_Right; break;
173+ case SDLK_LEFT: k = XK_Left; break;
174+ case SDLK_INSERT: k = XK_Insert; break;
175+ case SDLK_HOME: k = XK_Home; break;
176+ case SDLK_END: k = XK_End; break;
177+ case SDLK_PAGEUP: k = XK_Page_Up; break;
178+ case SDLK_PAGEDOWN: k = XK_Page_Down; break;
179+ case SDLK_F1: k = XK_F1; break;
180+ case SDLK_F2: k = XK_F2; break;
181+ case SDLK_F3: k = XK_F3; break;
182+ case SDLK_F4: k = XK_F4; break;
183+ case SDLK_F5: k = XK_F5; break;
184+ case SDLK_F6: k = XK_F6; break;
185+ case SDLK_F7: k = XK_F7; break;
186+ case SDLK_F8: k = XK_F8; break;
187+ case SDLK_F9: k = XK_F9; break;
188+ case SDLK_F10: k = XK_F10; break;
189+ case SDLK_F11: k = XK_F11; break;
190+ case SDLK_F12: k = XK_F12; break;
191+ case SDLK_F13: k = XK_F13; break;
192+ case SDLK_F14: k = XK_F14; break;
193+ case SDLK_F15: k = XK_F15; break;
194+ case SDLK_NUMLOCKCLEAR: k = XK_Num_Lock; break;
195+ case SDLK_CAPSLOCK: k = XK_Caps_Lock; break;
196+ case SDLK_SCROLLLOCK: k = XK_Scroll_Lock; break;
197+ case SDLK_RSHIFT: k = XK_Shift_R; break;
198+ case SDLK_LSHIFT: k = XK_Shift_L; break;
199+ case SDLK_RCTRL: k = XK_Control_R; break;
200+ case SDLK_LCTRL: k = XK_Control_L; break;
201+ case SDLK_RALT: k = XK_Alt_R; break;
202+ case SDLK_LALT: k = XK_Alt_L; break;
203+ case SDLK_LGUI: k = XK_Super_L; break;
204+ case SDLK_RGUI: k = XK_Super_R; break;
205+#if 0
206+ case SDLK_COMPOSE: k = XK_Compose; break;
207+#endif
208+ case SDLK_MODE: k = XK_Mode_switch; break;
209+ case SDLK_HELP: k = XK_Help; break;
210+ case SDLK_PRINTSCREEN: k = XK_Print; break;
211+ case SDLK_SYSREQ: k = XK_Sys_Req; break;
212+ default: break;
213+ }
214+ /* SDL_TEXTINPUT does not generate characters if ctrl is down, so handle those here */
215+ if (k == 0 && sym > 0x0 && sym < 0x100 && e->keysym.mod & KMOD_CTRL)
216+ k = sym;
217+ return k;
218+}
219+#endif
220+/* UTF-8 decoding is from https://rosettacode.org/wiki/UTF-8_encode_and_decode which is under GFDL 1.2 */
221+static tme_keyboard_keyval_t utf8char2rfbKeySym(const char chr[4]) {
222+ int bytes = strlen(chr);
223+ int shift = utf8Mapping[0].bits_stored * (bytes - 1);
224+ tme_keyboard_keyval_t codep = (*chr++ & utf8Mapping[bytes].mask) << shift;
225+ int i;
226+ for(i = 1; i < bytes; ++i, ++chr) {
227+ shift -= utf8Mapping[0].bits_stored;
228+ codep |= ((char)*chr & utf8Mapping[0].mask) << shift;
229+ }
230+ return codep;
231+}
232+static void
233+_tme_sdl_screen_redraw(struct tme_sdl_screen *screen, int x, int y, int w, int h)
234+{
235+ SDL_Surface *sdl = screen->sdl;
236+ /* update texture from surface->pixels */
237+ SDL_Rect r = {x,y,w,h};
238+ if(SDL_UpdateTexture(screen->sdlTexture, &r, sdl->pixels + y*sdl->pitch + x*4, sdl->pitch) < 0)
239+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
240+ (&display->tme_display_element->tme_element_log_handle,
241+ _("update: failed to update texture: %s\n", SDL_GetError())));
242+ /* copy texture to renderer and show */
243+ if(SDL_RenderClear(screen->sdlRenderer) < 0)
244+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
245+ (&display->tme_display_element->tme_element_log_handle,
246+ _("update: failed to clear renderer: %s\n", SDL_GetError())));
247+ if(SDL_RenderCopy(screen->sdlRenderer, screen->sdlTexture, NULL, NULL) < 0)
248+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
249+ (&display->tme_display_element->tme_element_log_handle,
250+ _("update: failed to copy texture to renderer: %s\n", SDL_GetError())));
251+ SDL_RenderPresent(screen->sdlRenderer);
252+}
253+static int
254+_tme_sdl_display_update(struct tme_display *display) {
255+ SDL_Event e;
256+
257+ if(SDL_PollEvent(&e)) {
258+
259+ switch(e->type) {
260+ case SDL_WINDOWEVENT:
261+ switch (e->window.event) {
262+ case SDL_WINDOWEVENT_EXPOSED:
263+ SendFramebufferUpdateRequest(cl, 0, 0,
264+ cl->width, cl->height, FALSE);
265+ break;
266+ case SDL_WINDOWEVENT_FOCUS_LOST:
267+ if (rightAltKeyDown) {
268+ _tme_keyboard_key_press(FALSE, SDLK_RALT, display);
269+ rightAltKeyDown = FALSE;
270+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
271+ (&display->tme_display_element->tme_element_log_handle,
272+ _("released right Alt key\n")));
273+ }
274+ if (leftAltKeyDown) {
275+ _tme_keyboard_key_press(FALSE, SDLK_LALT, display);
276+ leftAltKeyDown = FALSE;
277+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
278+ (&display->tme_display_element->tme_element_log_handle,
279+ _("released left Alt key\n")));
280+ }
281+ break;
282+ }
283+ break;
284+ case SDL_MOUSEWHEEL:
285+ {
286+ int steps;
287+ if (viewOnly)
288+ break;
289+ if(e->wheel.y > 0)
290+ for(steps = 0; steps < e->wheel.y; ++steps) {
291+ _tme_mouse_button_press(4, x, y, display);
292+ _tme_mouse_button_press(-4, x, y, display);
293+ }
294+ if(e->wheel.y < 0)
295+ for(steps = 0; steps > e->wheel.y; --steps) {
296+ _tme_mouse_button_press(5, x, y, display);
297+ _tme_mouse_button_press(-5, x, y, display);
298+ }
299+ if(e->wheel.x > 0)
300+ for(steps = 0; steps < e->wheel.x; ++steps) {
301+ _tme_mouse_button_press(7, x, y, display);
302+ _tme_mouse_button_press(-7, x, y, display);
303+ }
304+ if(e->wheel.x < 0)
305+ for(steps = 0; steps > e->wheel.x; --steps) {
306+ _tme_mouse_button_press(6, x, y, display);
307+ _tme_mouse_button_press(-6, x, y, display);
308+ }
309+ break;
310+ }
311+ case SDL_MOUSEBUTTONUP:
312+ case SDL_MOUSEBUTTONDOWN:
313+ case SDL_MOUSEMOTION:
314+ {
315+ int button, i;
316+ if (viewOnly)
317+ break;
318+ if (e->type == SDL_MOUSEMOTION) {
319+ x = e->motion.x;
320+ y = e->motion.y;
321+ button = 0; // e->motion.state;
322+ }
323+ else {
324+ x = e->button.x;
325+ y = e->button.y;
326+ button = e->button.button;
327+ if (e->type == SDL_MOUSEBUTTONUP)
328+ button = -button;
329+ }
330+ _tme_mouse_button_press(button, x, y, display);
331+ break;
332+ }
333+ case SDL_KEYUP:
334+ case SDL_KEYDOWN:
335+ if (viewOnly)
336+ break;
337+ _tme_keyboard_key_press(e->type == SDL_KEYDOWN ? TRUE : FALSE,
338+ e->keysym.sym, display);
339+ if (e->key.keysym.sym == SDLK_RALT)
340+ rightAltKeyDown = e->type == SDL_KEYDOWN;
341+ if (e->key.keysym.sym == SDLK_LALT)
342+ leftAltKeyDown = e->type == SDL_KEYDOWN;
343+ break;
344+ case SDL_TEXTINPUT:
345+ if (viewOnly)
346+ break;
347+ tme_keyboard_keyval_t sym = utf8char2rfbKeySym(e->text.text);
348+ _tme_keyboard_key_press(TRUE, sym, display);
349+ _tme_keyboard_key_press(FALSE, sym, display);
350+ break;
351+ default:
352+ tme_log(&display->tme_display_element->tme_element_log_handle, 0, TME_OK,
353+ (&display->tme_display_element->tme_element_log_handle,
354+ _("ignore SDL event: 0x%x\n", e->type)));
355+ }
356+ return TRUE;
357+ }
358+}
359+
360+/* the new SDL display function: */
361+TME_ELEMENT_SUB_NEW_DECL(tme_host_sdl,display) {
362+ struct tme_display *display;
363+ int arg_i = 0;
364+
365+ while(args[++arg_i] != NULL);
366+
367+ /* start our data structure: */
368+ display = tme_new0(struct tme_display, 1);
369+ tme_display_init(element, display);
370+
371+ /* recover our data structure: */
372+ display = element->tme_element_private;
373+
374+ SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
375+ atexit(SDL_Quit);
376+ signal(SIGINT, exit);
377+
378+ /* set the display-specific functions: */
379+ // display->tme_display_bell = _tme_sdl_display_bell;
380+ display->tme_display_update = _tme_sdl_display_update;
381+ display->tme_screen_resize = _tme_sdl_screen_resize;
382+ display->tme_screen_redraw = _tme_sdl_screen_redraw;
383+
384+ return (TME_OK);
385+}