Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/intel/tools/imgui/imgui_impl_gtk3.cpp
4547 views
1
// ImGui GLFW binding with OpenGL3 + shaders
2
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
3
4
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
5
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
6
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
7
// https://github.com/ocornut/imgui
8
9
#include <stdio.h>
10
11
#include "imgui/imgui.h"
12
#include "imgui_impl_gtk3.h"
13
14
#include <gtk/gtk.h>
15
16
#define ARRAY_SIZE(arg) (sizeof(arg) / sizeof((arg)[0]))
17
18
#define EVENT_MASK \
19
((GdkEventMask) \
20
(GDK_STRUCTURE_MASK | \
21
GDK_FOCUS_CHANGE_MASK | \
22
GDK_EXPOSURE_MASK | \
23
GDK_PROPERTY_CHANGE_MASK | \
24
GDK_ENTER_NOTIFY_MASK | \
25
GDK_LEAVE_NOTIFY_MASK | \
26
GDK_KEY_PRESS_MASK | \
27
GDK_KEY_RELEASE_MASK | \
28
GDK_BUTTON_PRESS_MASK | \
29
GDK_BUTTON_RELEASE_MASK | \
30
GDK_POINTER_MOTION_MASK | \
31
GDK_SMOOTH_SCROLL_MASK | \
32
GDK_SCROLL_MASK))
33
34
// Data
35
static GtkWidget* g_GtkGlArea = NULL;
36
static guint64 g_Time = 0;
37
static bool g_MousePressed[5] = { false, false, false, false, false };
38
static ImVec2 g_MousePosition = ImVec2(-1, -1);
39
static float g_MouseWheel = 0.0f;
40
static int g_NumRedraws = 0;
41
static guint g_RedrawTimeout = 0;
42
43
static const char* ImGui_ImplGtk3_GetClipboardText(void* user_data)
44
{
45
static char *last_clipboard = NULL;
46
47
g_clear_pointer(&last_clipboard, g_free);
48
last_clipboard = gtk_clipboard_wait_for_text(GTK_CLIPBOARD(user_data));
49
return last_clipboard;
50
}
51
52
static void ImGui_ImplGtk3_SetClipboardText(void* user_data, const char* text)
53
{
54
gtk_clipboard_set_text(GTK_CLIPBOARD(user_data), text, -1);
55
}
56
57
void ImGui_ImplGtk3_HandleEvent(GdkEvent *event)
58
{
59
ImGuiIO& io = ImGui::GetIO();
60
61
GdkEventType type = gdk_event_get_event_type(event);
62
switch (type)
63
{
64
case GDK_MOTION_NOTIFY:
65
{
66
gdouble x = 0.0f, y = 0.0f;
67
if (gdk_event_get_coords(event, &x, &y))
68
g_MousePosition = ImVec2(x, y);
69
break;
70
}
71
case GDK_BUTTON_PRESS:
72
case GDK_BUTTON_RELEASE:
73
{
74
guint button = 0;
75
if (gdk_event_get_button(event, &button) && button > 0 && button <= 5)
76
{
77
if (type == GDK_BUTTON_PRESS)
78
g_MousePressed[button - 1] = true;
79
}
80
break;
81
}
82
case GDK_SCROLL:
83
{
84
gdouble x, y;
85
if (gdk_event_get_scroll_deltas(event, &x, &y))
86
g_MouseWheel = -y;
87
break;
88
}
89
case GDK_KEY_PRESS:
90
case GDK_KEY_RELEASE:
91
{
92
GdkEventKey *e = (GdkEventKey *) event;
93
94
static const struct
95
{
96
enum ImGuiKey_ imgui;
97
guint gdk;
98
} gdk_key_to_imgui_key[] =
99
{
100
{ ImGuiKey_Tab, GDK_KEY_Tab },
101
{ ImGuiKey_Tab, GDK_KEY_ISO_Left_Tab },
102
{ ImGuiKey_LeftArrow, GDK_KEY_Left },
103
{ ImGuiKey_RightArrow, GDK_KEY_Right },
104
{ ImGuiKey_UpArrow, GDK_KEY_Up },
105
{ ImGuiKey_DownArrow, GDK_KEY_Down },
106
{ ImGuiKey_PageUp, GDK_KEY_Page_Up },
107
{ ImGuiKey_PageDown, GDK_KEY_Page_Down },
108
{ ImGuiKey_Home, GDK_KEY_Home },
109
{ ImGuiKey_End, GDK_KEY_End },
110
{ ImGuiKey_Delete, GDK_KEY_Delete },
111
{ ImGuiKey_Backspace, GDK_KEY_BackSpace },
112
{ ImGuiKey_Enter, GDK_KEY_Return },
113
{ ImGuiKey_Escape, GDK_KEY_Escape },
114
{ ImGuiKey_A, GDK_KEY_a },
115
{ ImGuiKey_C, GDK_KEY_c },
116
{ ImGuiKey_V, GDK_KEY_v },
117
{ ImGuiKey_X, GDK_KEY_x },
118
{ ImGuiKey_Y, GDK_KEY_y },
119
{ ImGuiKey_Z, GDK_KEY_z },
120
};
121
for (unsigned i = 0; i < ARRAY_SIZE(gdk_key_to_imgui_key); i++)
122
{
123
if (e->keyval == gdk_key_to_imgui_key[i].gdk)
124
io.KeysDown[gdk_key_to_imgui_key[i].imgui] = type == GDK_KEY_PRESS;
125
}
126
gunichar c = gdk_keyval_to_unicode(e->keyval);
127
if (g_unichar_isprint(c) && ImGuiKey_COUNT + c < ARRAY_SIZE(io.KeysDown))
128
io.KeysDown[ImGuiKey_COUNT + c] = type == GDK_KEY_PRESS;
129
130
if (type == GDK_KEY_PRESS && e->string)
131
io.AddInputCharactersUTF8(e->string);
132
133
struct {
134
bool *var;
135
GdkModifierType modifier;
136
guint keyvals[3];
137
} mods[] = {
138
{ &io.KeyCtrl, GDK_CONTROL_MASK,
139
{ GDK_KEY_Control_L, GDK_KEY_Control_R, 0 }, },
140
{ &io.KeyShift, GDK_SHIFT_MASK,
141
{ GDK_KEY_Shift_L, GDK_KEY_Shift_R, 0 }, },
142
{ &io.KeyAlt, GDK_MOD1_MASK,
143
{ GDK_KEY_Alt_L, GDK_KEY_Alt_R, 0 }, },
144
{ &io.KeySuper, GDK_SUPER_MASK,
145
{ GDK_KEY_Super_L, GDK_KEY_Super_R, 0 }, }
146
};
147
for (unsigned i = 0; i < ARRAY_SIZE(mods); i++)
148
{
149
*mods[i].var = (mods[i].modifier & e->state);
150
151
bool match = false;
152
for (int j = 0; mods[i].keyvals[j] != 0; j++)
153
if (e->keyval == mods[i].keyvals[j])
154
match = true;
155
156
if (match)
157
*mods[i].var = type == GDK_KEY_PRESS;
158
}
159
break;
160
}
161
default:
162
break;
163
}
164
165
// We trigger 2 subsequent redraws for each event because of the
166
// way some ImGui widgets work. For example a Popup menu will only
167
// appear a frame after a click happened.
168
g_NumRedraws = 2;
169
170
gtk_widget_queue_draw(g_GtkGlArea);
171
}
172
173
static gboolean handle_gdk_event(GtkWidget *widget, GdkEvent *event, void *data)
174
{
175
ImGui_ImplGtk3_HandleEvent(event);
176
return TRUE;
177
}
178
179
bool ImGui_ImplGtk3_Init(GtkWidget* gl_area, bool install_callbacks)
180
{
181
g_clear_pointer(&g_GtkGlArea, g_object_unref);
182
183
g_GtkGlArea = GTK_WIDGET(g_object_ref(gl_area));
184
gtk_widget_realize(g_GtkGlArea);
185
gtk_widget_set_can_focus(g_GtkGlArea, TRUE);
186
gtk_widget_grab_focus(g_GtkGlArea);
187
188
if (install_callbacks) {
189
gtk_widget_add_events(g_GtkGlArea, EVENT_MASK);
190
g_signal_connect(g_GtkGlArea, "event", G_CALLBACK(handle_gdk_event), NULL);
191
}
192
193
ImGuiIO& io = ImGui::GetIO();
194
for (int i = 0; i < ImGuiKey_COUNT; i++)
195
{
196
io.KeyMap[i] = i;
197
}
198
199
io.SetClipboardTextFn = ImGui_ImplGtk3_SetClipboardText;
200
io.GetClipboardTextFn = ImGui_ImplGtk3_GetClipboardText;
201
io.ClipboardUserData = gtk_widget_get_clipboard(g_GtkGlArea,
202
GDK_SELECTION_CLIPBOARD);
203
204
return true;
205
}
206
207
void ImGui_ImplGtk3_Shutdown()
208
{
209
g_clear_pointer(&g_GtkGlArea, g_object_unref);
210
if (g_RedrawTimeout)
211
g_source_remove(g_RedrawTimeout);
212
}
213
214
static gboolean timeout_callback(gpointer data)
215
{
216
gtk_widget_queue_draw(g_GtkGlArea);
217
g_RedrawTimeout = 0;
218
return FALSE;
219
}
220
221
static void kick_timeout_redraw(float timeout)
222
{
223
if (g_RedrawTimeout)
224
return;
225
g_RedrawTimeout = g_timeout_add(timeout * 1000, timeout_callback, NULL);
226
}
227
228
void ImGui_ImplGtk3_NewFrame()
229
{
230
bool next_redraw = false;
231
if (g_NumRedraws > 0)
232
{
233
gtk_widget_queue_draw(g_GtkGlArea);
234
g_NumRedraws--;
235
next_redraw = true;
236
}
237
238
ImGuiIO& io = ImGui::GetIO();
239
240
// Setup display size (every frame to accommodate for window resizing)
241
io.DisplaySize = ImVec2((float)gtk_widget_get_allocated_width(g_GtkGlArea),
242
(float)gtk_widget_get_allocated_height(g_GtkGlArea));
243
int scale_factor = gtk_widget_get_scale_factor(g_GtkGlArea);
244
io.DisplayFramebufferScale = ImVec2(scale_factor, scale_factor);
245
246
// Setup time step
247
guint64 current_time = g_get_monotonic_time();
248
io.DeltaTime = g_Time > 0 ? ((float)(current_time - g_Time) / 1000000) : (float)(1.0f/60.0f);
249
g_Time = current_time;
250
251
// Setup inputs
252
if (gtk_widget_has_focus(g_GtkGlArea))
253
{
254
io.MousePos = g_MousePosition; // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
255
}
256
else
257
{
258
io.MousePos = ImVec2(-1,-1);
259
}
260
261
GdkWindow *window = gtk_widget_get_window(g_GtkGlArea);
262
GdkDevice *pointer = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default()));
263
GdkModifierType modifiers;
264
gdk_device_get_state(pointer, window, NULL, &modifiers);
265
266
for (int i = 0; i < 3; i++)
267
{
268
io.MouseDown[i] = g_MousePressed[i] || (modifiers & (GDK_BUTTON1_MASK << i)) != 0;
269
g_MousePressed[i] = false;
270
}
271
272
io.MouseWheel = g_MouseWheel;
273
g_MouseWheel = 0.0f;
274
275
// Hide OS mouse cursor if ImGui is drawing it
276
GdkDisplay *display = gdk_window_get_display(window);
277
GdkCursor *cursor =
278
gdk_cursor_new_from_name(display, io.MouseDrawCursor ? "none" : "default");
279
gdk_window_set_cursor(window, cursor);
280
g_object_unref(cursor);
281
282
if (!next_redraw && io.WantTextInput)
283
kick_timeout_redraw(0.2);
284
}
285
286