Bump version to 24.04.3.4
[LibreOffice.git] / libreofficekit / qa / gtktiledviewer / gtv-lok-dialog.cxx
blobf23148eaf2f948d9571456a34d38cab94bae59c2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <gtk/gtk.h>
11 #include <gdk/gdkkeysyms.h>
13 #include <iostream>
15 #include <LibreOfficeKit/LibreOfficeKitGtk.h>
16 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
18 #include "gtv-application-window.hxx"
19 #include "gtv-lok-dialog.hxx"
21 #include <com/sun/star/awt/Key.hpp>
23 #include <o3tl/unit_conversion.hxx>
24 #include <vcl/event.hxx>
26 namespace {
28 struct GtvLokDialogPrivate
30 LOKDocView* lokdocview;
31 GtkWidget* pDialogDrawingArea;
32 GtkWidget* pFloatingWin;
34 // state for dialog
35 guint32 m_nLastButtonPressTime;
36 guint32 m_nLastButtonReleaseTime;
37 guint32 m_nKeyModifier;
38 guint32 m_nLastButtonPressed;
39 guint32 m_nWidth;
40 guint32 m_nHeight;
42 // state for child floating windows
43 guint32 m_nChildId;
44 guint32 m_nChildWidth;
45 guint32 m_nChildHeight;
46 guint32 m_nChildLastButtonPressTime;
47 guint32 m_nChildLastButtonReleaseTime;
48 guint32 m_nChildKeyModifier;
49 guint32 m_nChildLastButtonPressed;
51 guint dialogid;
56 #if defined __clang__
57 #if __has_warning("-Wdeprecated-volatile")
58 #pragma clang diagnostic push
59 #pragma clang diagnostic ignored "-Wdeprecated-volatile"
60 #endif
61 #endif
62 G_DEFINE_TYPE_WITH_PRIVATE(GtvLokDialog, gtv_lok_dialog, GTK_TYPE_DIALOG);
63 #if defined __clang__
64 #if __has_warning("-Wdeprecated-volatile")
65 #pragma clang diagnostic pop
66 #endif
67 #endif
69 enum
71 PROP_0,
72 PROP_LOKDOCVIEW_CONTEXT,
73 PROP_DIALOG_ID,
74 PROP_DIALOG_WIDTH,
75 PROP_DIALOG_HEIGHT,
76 PROP_LAST
79 static GParamSpec* properties[PROP_LAST];
81 static GtvLokDialogPrivate*
82 getPrivate(GtvLokDialog* dialog)
84 return static_cast<GtvLokDialogPrivate*>(gtv_lok_dialog_get_instance_private(dialog));
87 static void
88 gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
90 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
91 GtvLokDialogPrivate* priv = getPrivate(pDialog);
93 GdkRectangle aRect;
94 gdk_cairo_get_clip_rectangle(pCairo, &aRect);
95 g_info("Painting dialog region: %d, %d, %d, %d", aRect.x, aRect.y, aRect.width, aRect.height);
97 int nWidth = priv->m_nWidth;
98 int nHeight = priv->m_nHeight;
99 if (aRect.width != 0 && aRect.height != 0)
101 nWidth = aRect.width;
102 nHeight = aRect.height;
105 cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
106 unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
107 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
108 pDocument->pClass->paintWindow(pDocument, priv->dialogid, pBuffer, aRect.x, aRect.y, nWidth, nHeight);
110 gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea), priv->m_nWidth, priv->m_nHeight);
112 cairo_surface_flush(pSurface);
113 cairo_surface_mark_dirty(pSurface);
115 cairo_set_source_surface(pCairo, pSurface, aRect.x, aRect.y);
116 // paint the dialog image
117 cairo_paint(pCairo);
119 // debug red-colored border around the painted region
120 cairo_set_source_rgb(pCairo, 1.0, 0, 0);
121 cairo_rectangle(pCairo, aRect.x, aRect.y, nWidth, nHeight);
122 cairo_stroke(pCairo);
125 static gboolean
126 gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEvent)
128 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
129 GtvLokDialogPrivate* priv = getPrivate(pDialog);
131 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
132 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
134 std::string aEventType = "unknown";
135 if (pEvent->type == GDK_BUTTON_PRESS)
136 aEventType = "BUTTON_PRESS";
137 else if (pEvent->type == GDK_BUTTON_RELEASE)
138 aEventType = "BUTTON_RELEASE";
140 g_info("lok_dialog_signal_button (type: %s): %d, %d",
141 aEventType.c_str(),
142 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y));
143 gtk_widget_grab_focus(pDialogDrawingArea);
145 switch (pEvent->type)
147 case GDK_BUTTON_PRESS:
149 int nCount = 1;
150 if ((pEvent->time - priv->m_nLastButtonPressTime) < 250)
151 nCount++;
152 priv->m_nLastButtonPressTime = pEvent->time;
153 int nEventButton = 0;
154 switch (pEvent->button)
156 case 1:
157 nEventButton = MOUSE_LEFT;
158 break;
159 case 2:
160 nEventButton = MOUSE_MIDDLE;
161 break;
162 case 3:
163 nEventButton = MOUSE_RIGHT;
164 break;
166 priv->m_nLastButtonPressed = nEventButton;
167 pDocument->pClass->postWindowMouseEvent(pDocument,
168 priv->dialogid,
169 LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
170 (pEvent->x),
171 (pEvent->y),
172 nCount,
173 nEventButton,
174 priv->m_nKeyModifier);
176 break;
178 case GDK_BUTTON_RELEASE:
180 int nCount = 1;
181 if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250)
182 nCount++;
183 priv->m_nLastButtonReleaseTime = pEvent->time;
184 int nEventButton = 0;
185 switch (pEvent->button)
187 case 1:
188 nEventButton = MOUSE_LEFT;
189 break;
190 case 2:
191 nEventButton = MOUSE_MIDDLE;
192 break;
193 case 3:
194 nEventButton = MOUSE_RIGHT;
195 break;
197 priv->m_nLastButtonPressed = nEventButton;
198 pDocument->pClass->postWindowMouseEvent(pDocument,
199 priv->dialogid,
200 LOK_MOUSEEVENT_MOUSEBUTTONUP,
201 (pEvent->x),
202 (pEvent->y),
203 nCount,
204 nEventButton,
205 priv->m_nKeyModifier);
206 break;
208 default:
209 break;
211 return FALSE;
214 static gboolean
215 gtv_lok_dialog_signal_motion(GtkWidget* pDialogDrawingArea, GdkEventButton* pEvent)
217 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
218 GtvLokDialogPrivate* priv = getPrivate(pDialog);
220 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
221 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
223 g_info("lok_dialog_signal_motion: %d, %d (in twips: %d, %d)",
224 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
225 static_cast<int>(o3tl::toTwips(pEvent->x, o3tl::Length::px)),
226 static_cast<int>(o3tl::toTwips(pEvent->y, o3tl::Length::px)));
228 pDocument->pClass->postWindowMouseEvent(pDocument,
229 priv->dialogid,
230 LOK_MOUSEEVENT_MOUSEMOVE,
231 (pEvent->x),
232 (pEvent->y),
234 priv->m_nLastButtonPressed,
235 priv->m_nKeyModifier);
237 return FALSE;
240 static gboolean
241 gtv_lok_dialog_signal_key(GtkWidget* pDialogDrawingArea, GdkEventKey* pEvent)
243 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
244 GtvLokDialogPrivate* priv = getPrivate(pDialog);
245 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
246 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
248 g_info("lok_dialog_signal_key");
249 int nCharCode = 0;
250 int nKeyCode = 0;
251 priv->m_nKeyModifier &= KEY_MOD2;
252 switch (pEvent->keyval)
254 case GDK_KEY_BackSpace:
255 nKeyCode = com::sun::star::awt::Key::BACKSPACE;
256 break;
257 case GDK_KEY_Delete:
258 nKeyCode = com::sun::star::awt::Key::DELETE;
259 break;
260 case GDK_KEY_Return:
261 case GDK_KEY_KP_Enter:
262 nKeyCode = com::sun::star::awt::Key::RETURN;
263 break;
264 case GDK_KEY_Escape:
265 nKeyCode = com::sun::star::awt::Key::ESCAPE;
266 break;
267 case GDK_KEY_Tab:
268 nKeyCode = com::sun::star::awt::Key::TAB;
269 break;
270 case GDK_KEY_Down:
271 nKeyCode = com::sun::star::awt::Key::DOWN;
272 break;
273 case GDK_KEY_Up:
274 nKeyCode = com::sun::star::awt::Key::UP;
275 break;
276 case GDK_KEY_Left:
277 nKeyCode = com::sun::star::awt::Key::LEFT;
278 break;
279 case GDK_KEY_Right:
280 nKeyCode = com::sun::star::awt::Key::RIGHT;
281 break;
282 case GDK_KEY_Page_Down:
283 nKeyCode = com::sun::star::awt::Key::PAGEDOWN;
284 break;
285 case GDK_KEY_Page_Up:
286 nKeyCode = com::sun::star::awt::Key::PAGEUP;
287 break;
288 case GDK_KEY_Insert:
289 nKeyCode = com::sun::star::awt::Key::INSERT;
290 break;
291 case GDK_KEY_Shift_L:
292 case GDK_KEY_Shift_R:
293 if (pEvent->type == GDK_KEY_PRESS)
294 priv->m_nKeyModifier |= KEY_SHIFT;
295 break;
296 case GDK_KEY_Control_L:
297 case GDK_KEY_Control_R:
298 if (pEvent->type == GDK_KEY_PRESS)
299 priv->m_nKeyModifier |= KEY_MOD1;
300 break;
301 case GDK_KEY_Alt_L:
302 case GDK_KEY_Alt_R:
303 if (pEvent->type == GDK_KEY_PRESS)
304 priv->m_nKeyModifier |= KEY_MOD2;
305 else
306 priv->m_nKeyModifier &= ~KEY_MOD2;
307 break;
308 default:
309 if (pEvent->keyval >= GDK_KEY_F1 && pEvent->keyval <= GDK_KEY_F26)
310 nKeyCode = com::sun::star::awt::Key::F1 + (pEvent->keyval - GDK_KEY_F1);
311 else
312 nCharCode = gdk_keyval_to_unicode(pEvent->keyval);
315 // rsc is not public API, but should be good enough for debugging purposes.
316 // If this is needed for real, then probably a new param of type
317 // css::awt::KeyModifier is needed in postKeyEvent().
318 if (pEvent->state & GDK_SHIFT_MASK)
319 nKeyCode |= KEY_SHIFT;
321 if (pEvent->state & GDK_CONTROL_MASK)
322 nKeyCode |= KEY_MOD1;
324 if (priv->m_nKeyModifier & KEY_MOD2)
325 nKeyCode |= KEY_MOD2;
327 if (nKeyCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)) {
328 if (pEvent->keyval >= GDK_KEY_a && pEvent->keyval <= GDK_KEY_z)
330 nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_a);
332 else if (pEvent->keyval >= GDK_KEY_A && pEvent->keyval <= GDK_KEY_Z) {
333 nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_A);
335 else if (pEvent->keyval >= GDK_KEY_0 && pEvent->keyval <= GDK_KEY_9) {
336 nKeyCode |= 256 + (pEvent->keyval - GDK_KEY_0);
340 std::stringstream ss;
341 ss << "gtv_lok_dialog::postKey(" << pEvent->type << ", " << nCharCode << ", " << nKeyCode << ")";
342 g_info("%s", ss.str().c_str());
344 pDocument->pClass->postWindowKeyEvent(pDocument,
345 priv->dialogid,
346 pEvent->type == GDK_KEY_RELEASE ? LOK_KEYEVENT_KEYUP : LOK_KEYEVENT_KEYINPUT,
347 nCharCode,
348 nKeyCode);
350 return FALSE;
353 static void
354 gtv_lok_dialog_init(GtvLokDialog* dialog)
356 GtvLokDialogPrivate* priv = getPrivate(dialog);
358 GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
359 priv->pDialogDrawingArea = gtk_drawing_area_new();
360 priv->pFloatingWin = nullptr;
361 priv->m_nChildId = 0;
362 priv->m_nChildWidth = 0;
363 priv->m_nChildHeight = 0;
365 priv->m_nLastButtonPressTime = 0;
366 priv->m_nLastButtonReleaseTime = 0;
367 priv->m_nKeyModifier = 0;
368 priv->m_nLastButtonPressed = 0;
370 gtk_widget_add_events(priv->pDialogDrawingArea,
371 GDK_BUTTON_PRESS_MASK
372 |GDK_BUTTON_RELEASE_MASK
373 |GDK_BUTTON_MOTION_MASK
374 |GDK_KEY_PRESS_MASK
375 |GDK_KEY_RELEASE_MASK);
376 // This is required to be able to capture key events on the drawing area
377 gtk_widget_set_can_focus(priv->pDialogDrawingArea, true);
379 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
380 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_signal_button), nullptr);
381 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_signal_button), nullptr);
382 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_signal_motion), nullptr);
383 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "key-press-event", G_CALLBACK(gtv_lok_dialog_signal_key), nullptr);
384 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "key-release-event", G_CALLBACK(gtv_lok_dialog_signal_key), nullptr);
385 gtk_container_add(GTK_CONTAINER(pContentArea), priv->pDialogDrawingArea);
388 static void
389 gtv_lok_dialog_set_property(GObject* object, guint propId, const GValue* value, GParamSpec* pspec)
391 GtvLokDialog* self = GTV_LOK_DIALOG(object);
392 GtvLokDialogPrivate* priv = getPrivate(self);
394 switch(propId)
396 case PROP_LOKDOCVIEW_CONTEXT:
397 priv->lokdocview = LOK_DOC_VIEW(g_value_get_object(value));
398 break;
399 case PROP_DIALOG_ID:
400 priv->dialogid = g_value_get_uint(value);
401 break;
402 case PROP_DIALOG_WIDTH:
403 priv->m_nWidth = g_value_get_uint(value);
404 break;
405 case PROP_DIALOG_HEIGHT:
406 priv->m_nHeight = g_value_get_uint(value);
407 break;
408 default:
409 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
412 //if (propId == PROP_DIALOG_WIDTH || propId == PROP_DIALOG_HEIGHT)
413 // gtk_widget_set_size_request(GTK_WIDGET(priv->pDialogDrawingArea), priv->m_nWidth, priv->m_nHeight);
416 static void
417 gtv_lok_dialog_get_property(GObject* object, guint propId, GValue* value, GParamSpec* pspec)
419 GtvLokDialog* self = GTV_LOK_DIALOG(object);
420 GtvLokDialogPrivate* priv = getPrivate(self);
422 switch(propId)
424 case PROP_LOKDOCVIEW_CONTEXT:
425 g_value_set_object(value, priv->lokdocview);
426 break;
427 case PROP_DIALOG_ID:
428 g_value_set_uint(value, priv->dialogid);
429 break;
430 case PROP_DIALOG_WIDTH:
431 g_value_set_uint(value, priv->m_nWidth);
432 break;
433 case PROP_DIALOG_HEIGHT:
434 g_value_set_uint(value, priv->m_nHeight);
435 break;
436 default:
437 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
441 static void
442 gtv_lok_dialog_class_init(GtvLokDialogClass* klass)
444 G_OBJECT_CLASS(klass)->get_property = gtv_lok_dialog_get_property;
445 G_OBJECT_CLASS(klass)->set_property = gtv_lok_dialog_set_property;
447 properties[PROP_LOKDOCVIEW_CONTEXT] = g_param_spec_object("lokdocview",
448 "LOKDocView Context",
449 "The LOKDocView context object to be used for dialog rendering",
450 LOK_TYPE_DOC_VIEW,
451 static_cast<GParamFlags>(G_PARAM_READWRITE |
452 G_PARAM_CONSTRUCT_ONLY |
453 G_PARAM_STATIC_STRINGS));
455 properties[PROP_DIALOG_ID] = g_param_spec_uint("dialogid",
456 "Dialog identifier",
457 "Unique dialog identifier",
458 0, G_MAXUINT, 0,
459 static_cast<GParamFlags>(G_PARAM_READWRITE |
460 G_PARAM_CONSTRUCT_ONLY |
461 G_PARAM_STATIC_STRINGS));
463 properties[PROP_DIALOG_WIDTH] = g_param_spec_uint("width",
464 "Dialog width",
465 "Dialog width",
466 0, 4096, 0,
467 static_cast<GParamFlags>(G_PARAM_READWRITE |
468 G_PARAM_STATIC_STRINGS));
470 properties[PROP_DIALOG_HEIGHT] = g_param_spec_uint("height",
471 "Dialog height",
472 "Dialog height",
473 0, 2048, 0,
474 static_cast<GParamFlags>(G_PARAM_READWRITE |
475 G_PARAM_STATIC_STRINGS));
477 g_object_class_install_properties (G_OBJECT_CLASS(klass), PROP_LAST, properties);
480 static void
481 gtv_lok_dialog_floating_win_draw(GtkWidget* pDrawingArea, cairo_t* pCairo, gpointer userdata)
483 GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
484 GtvLokDialogPrivate* priv = getPrivate(pDialog);
486 g_info("gtv_lok_dialog_floating_win_draw triggered");
487 cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, priv->m_nChildWidth, priv->m_nChildHeight);
488 unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
489 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
490 pDocument->pClass->paintWindow(pDocument, priv->m_nChildId, pBuffer, 0, 0, priv->m_nChildWidth, priv->m_nChildHeight);
492 gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), priv->m_nChildWidth, priv->m_nChildHeight);
493 //gtk_widget_set_size_request(GTK_WIDGET(pDialog), nWidth, nHeight);
494 //gtk_window_resize(GTK_WINDOW(pDialog), nWidth, nHeight);
496 cairo_surface_flush(pSurface);
497 cairo_surface_mark_dirty(pSurface);
499 cairo_set_source_surface(pCairo, pSurface, 0, 0);
500 cairo_paint(pCairo);
503 static gboolean
504 gtv_lok_dialog_floating_win_signal_button(GtkWidget* /*pDialogChildDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
506 GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
507 GtvLokDialogPrivate* priv = getPrivate(pDialog);
509 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
510 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
512 std::string aEventType = "unknown";
513 if (pEvent->type == GDK_BUTTON_PRESS)
514 aEventType = "BUTTON_PRESS";
515 else if (pEvent->type == GDK_BUTTON_RELEASE)
516 aEventType = "BUTTON_RELEASE";
518 g_info("lok_dialog_floating_win_signal_button (type: %s): %d, %d (in twips: %d, %d)",
519 aEventType.c_str(),
520 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
521 static_cast<int>(o3tl::toTwips(pEvent->x, o3tl::Length::px)),
522 static_cast<int>(o3tl::toTwips(pEvent->y, o3tl::Length::px)));
524 switch (pEvent->type)
526 case GDK_BUTTON_PRESS:
528 int nCount = 1;
529 if ((pEvent->time - priv->m_nChildLastButtonPressTime) < 250)
530 nCount++;
531 priv->m_nChildLastButtonPressTime = pEvent->time;
532 int nEventButton = 0;
533 switch (pEvent->button)
535 case 1:
536 nEventButton = MOUSE_LEFT;
537 break;
538 case 2:
539 nEventButton = MOUSE_MIDDLE;
540 break;
541 case 3:
542 nEventButton = MOUSE_RIGHT;
543 break;
545 priv->m_nChildLastButtonPressed = nEventButton;
546 pDocument->pClass->postWindowMouseEvent(pDocument,
547 priv->m_nChildId,
548 LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
549 (pEvent->x),
550 (pEvent->y),
551 nCount,
552 nEventButton,
553 priv->m_nChildKeyModifier);
555 break;
557 case GDK_BUTTON_RELEASE:
559 int nCount = 1;
560 if ((pEvent->time - priv->m_nChildLastButtonReleaseTime) < 250)
561 nCount++;
562 priv->m_nChildLastButtonReleaseTime = pEvent->time;
563 int nEventButton = 0;
564 switch (pEvent->button)
566 case 1:
567 nEventButton = MOUSE_LEFT;
568 break;
569 case 2:
570 nEventButton = MOUSE_MIDDLE;
571 break;
572 case 3:
573 nEventButton = MOUSE_RIGHT;
574 break;
576 priv->m_nChildLastButtonPressed = nEventButton;
577 pDocument->pClass->postWindowMouseEvent(pDocument,
578 priv->m_nChildId,
579 LOK_MOUSEEVENT_MOUSEBUTTONUP,
580 (pEvent->x),
581 (pEvent->y),
582 nCount,
583 nEventButton,
584 priv->m_nChildKeyModifier);
585 break;
587 default:
588 break;
590 return FALSE;
593 static gboolean
594 gtv_lok_dialog_floating_win_signal_motion(GtkWidget* /*pDialogDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
596 GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
597 GtvLokDialogPrivate* priv = getPrivate(pDialog);
599 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
600 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
602 g_info("lok_dialog_floating_win_signal_motion: %d, %d (in twips: %d, %d)",
603 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
604 static_cast<int>(o3tl::toTwips(pEvent->x, o3tl::Length::px)),
605 static_cast<int>(o3tl::toTwips(pEvent->y, o3tl::Length::px)));
607 pDocument->pClass->postWindowMouseEvent(pDocument,
608 priv->m_nChildId,
609 LOK_MOUSEEVENT_MOUSEMOVE,
610 (pEvent->x),
611 (pEvent->y),
613 priv->m_nChildLastButtonPressed,
614 priv->m_nChildKeyModifier);
616 return FALSE;
619 // Public methods below
621 void gtv_lok_dialog_invalidate(GtvLokDialog* dialog, const GdkRectangle& aRectangle)
623 GtvLokDialogPrivate* priv = getPrivate(dialog);
624 if (aRectangle.width != 0 && aRectangle.height != 0)
625 gtk_widget_queue_draw_area(priv->pDialogDrawingArea, aRectangle.x, aRectangle.y, aRectangle.width, aRectangle.height);
626 else
627 gtk_widget_queue_draw(priv->pDialogDrawingArea);
630 // checks if we are the parent of given childId
631 gboolean gtv_lok_dialog_is_parent_of(GtvLokDialog* dialog, guint childId)
633 GtvLokDialogPrivate* priv = getPrivate(dialog);
635 return priv->m_nChildId == childId;
638 void gtv_lok_dialog_child_create(GtvLokDialog* dialog, guint childId, guint nX, guint nY, guint width, guint height)
640 GtvLokDialogPrivate* priv = getPrivate(dialog);
642 g_debug("Dialog [ %d ] child window [ %d] being created, with dimensions [%dx%d]@(%d,%d)", priv->dialogid, childId, width, height, nX, nY);
643 priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
644 priv->m_nChildId = childId;
645 priv->m_nChildWidth = width;
646 priv->m_nChildHeight = height;
647 GtkWidget* pDrawingArea = gtk_drawing_area_new();
648 gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
650 gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
651 gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
653 gtk_widget_add_events(pDrawingArea,
654 GDK_BUTTON_PRESS_MASK
655 |GDK_POINTER_MOTION_MASK
656 |GDK_BUTTON_RELEASE_MASK
657 |GDK_BUTTON_MOTION_MASK);
659 g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
660 g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
661 g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
662 g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);
664 gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
665 gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
666 gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));
668 gtk_widget_show_all(priv->pFloatingWin);
669 gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
670 gtk_widget_grab_focus(pDrawingArea);
672 // Get the root coords of our new floating window
673 GdkWindow* pGdkWin = gtk_widget_get_window(GTK_WIDGET(dialog));
674 int nrX = 0;
675 int nrY = 0;
676 gdk_window_get_root_coords(pGdkWin, nX, nY, &nrX, &nrY);
677 gtk_window_move(GTK_WINDOW(priv->pFloatingWin), nrX, nrY);
680 void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog)
682 GtvLokDialogPrivate* priv = getPrivate(dialog);
683 g_debug("Dialog [ %d ] child invalidate request", priv->dialogid);
684 gtk_widget_queue_draw(priv->pFloatingWin);
687 void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
689 g_info("Dialog's floating window close");
691 GtvLokDialogPrivate* priv = getPrivate(dialog);
692 if (priv->pFloatingWin)
694 gtk_widget_destroy(priv->pFloatingWin);
695 priv->pFloatingWin = nullptr;
696 priv->m_nChildId = 0;
697 priv->m_nChildWidth = 0;
698 priv->m_nChildHeight = 0;
702 GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, guint dialogId, guint width, guint height)
704 g_debug("Dialog [ %d ] of size: %d x %d created", dialogId, width, height);
705 GtkWindow* pWindow = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
706 return GTK_WIDGET(g_object_new(GTV_TYPE_LOK_DIALOG,
707 "lokdocview", pDocView,
708 "dialogid", dialogId,
709 "width", width,
710 "height", height,
711 "title", "LOK Dialog",
712 "modal", false,
713 "transient-for", pWindow,
714 nullptr));
717 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */