nss: upgrade to release 3.73
[LibreOffice.git] / libreofficekit / qa / gtktiledviewer / gtv-lok-dialog.cxx
blobbb70a15159d1742d33e8e8247b0ecb99cee72e9e
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>
22 #include <vcl/event.hxx>
24 namespace {
26 struct GtvLokDialogPrivate
28 LOKDocView* lokdocview;
29 GtkWidget* pDialogDrawingArea;
30 GtkWidget* pFloatingWin;
32 // state for dialog
33 guint32 m_nLastButtonPressTime;
34 guint32 m_nLastButtonReleaseTime;
35 guint32 m_nKeyModifier;
36 guint32 m_nLastButtonPressed;
37 guint32 m_nWidth;
38 guint32 m_nHeight;
40 // state for child floating windows
41 guint32 m_nChildId;
42 guint32 m_nChildWidth;
43 guint32 m_nChildHeight;
44 guint32 m_nChildLastButtonPressTime;
45 guint32 m_nChildLastButtonReleaseTime;
46 guint32 m_nChildKeyModifier;
47 guint32 m_nChildLastButtonPressed;
49 guint dialogid;
54 #if defined __clang__
55 #if __has_warning("-Wdeprecated-volatile")
56 #pragma clang diagnostic push
57 #pragma clang diagnostic ignored "-Wdeprecated-volatile"
58 #endif
59 #endif
60 G_DEFINE_TYPE_WITH_PRIVATE(GtvLokDialog, gtv_lok_dialog, GTK_TYPE_DIALOG);
61 #if defined __clang__
62 #if __has_warning("-Wdeprecated-volatile")
63 #pragma clang diagnostic pop
64 #endif
65 #endif
67 enum
69 PROP_0,
70 PROP_LOKDOCVIEW_CONTEXT,
71 PROP_DIALOG_ID,
72 PROP_DIALOG_WIDTH,
73 PROP_DIALOG_HEIGHT,
74 PROP_LAST
77 static GParamSpec* properties[PROP_LAST];
79 static GtvLokDialogPrivate*
80 getPrivate(GtvLokDialog* dialog)
82 return static_cast<GtvLokDialogPrivate*>(gtv_lok_dialog_get_instance_private(dialog));
85 static float
86 pixelToTwip(float fInput)
88 return (fInput / 96 / 1.0 /* zoom */) * 1440.0f;
91 #if 0
92 static float
93 twipToPixel(float fInput)
95 return fInput / 1440.0f * 96 * 1.0 /* zoom */;
97 #endif
99 static void
100 gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
102 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
103 GtvLokDialogPrivate* priv = getPrivate(pDialog);
105 GdkRectangle aRect;
106 gdk_cairo_get_clip_rectangle(pCairo, &aRect);
107 g_info("Painting dialog region: %d, %d, %d, %d", aRect.x, aRect.y, aRect.width, aRect.height);
109 int nWidth = priv->m_nWidth;
110 int nHeight = priv->m_nHeight;
111 if (aRect.width != 0 && aRect.height != 0)
113 nWidth = aRect.width;
114 nHeight = aRect.height;
117 cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
118 unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
119 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
120 pDocument->pClass->paintWindow(pDocument, priv->dialogid, pBuffer, aRect.x, aRect.y, nWidth, nHeight);
122 gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea), priv->m_nWidth, priv->m_nHeight);
124 cairo_surface_flush(pSurface);
125 cairo_surface_mark_dirty(pSurface);
127 cairo_set_source_surface(pCairo, pSurface, aRect.x, aRect.y);
128 // paint the dialog image
129 cairo_paint(pCairo);
131 // debug red-colored border around the painted region
132 cairo_set_source_rgb(pCairo, 1.0, 0, 0);
133 cairo_rectangle(pCairo, aRect.x, aRect.y, nWidth, nHeight);
134 cairo_stroke(pCairo);
137 static gboolean
138 gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEvent)
140 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
141 GtvLokDialogPrivate* priv = getPrivate(pDialog);
143 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
144 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
146 std::string aEventType = "unknown";
147 if (pEvent->type == GDK_BUTTON_PRESS)
148 aEventType = "BUTTON_PRESS";
149 else if (pEvent->type == GDK_BUTTON_RELEASE)
150 aEventType = "BUTTON_RELEASE";
152 g_info("lok_dialog_signal_button (type: %s): %d, %d",
153 aEventType.c_str(),
154 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y));
155 gtk_widget_grab_focus(pDialogDrawingArea);
157 switch (pEvent->type)
159 case GDK_BUTTON_PRESS:
161 int nCount = 1;
162 if ((pEvent->time - priv->m_nLastButtonPressTime) < 250)
163 nCount++;
164 priv->m_nLastButtonPressTime = pEvent->time;
165 int nEventButton = 0;
166 switch (pEvent->button)
168 case 1:
169 nEventButton = MOUSE_LEFT;
170 break;
171 case 2:
172 nEventButton = MOUSE_MIDDLE;
173 break;
174 case 3:
175 nEventButton = MOUSE_RIGHT;
176 break;
178 priv->m_nLastButtonPressed = nEventButton;
179 pDocument->pClass->postWindowMouseEvent(pDocument,
180 priv->dialogid,
181 LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
182 (pEvent->x),
183 (pEvent->y),
184 nCount,
185 nEventButton,
186 priv->m_nKeyModifier);
188 break;
190 case GDK_BUTTON_RELEASE:
192 int nCount = 1;
193 if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250)
194 nCount++;
195 priv->m_nLastButtonReleaseTime = pEvent->time;
196 int nEventButton = 0;
197 switch (pEvent->button)
199 case 1:
200 nEventButton = MOUSE_LEFT;
201 break;
202 case 2:
203 nEventButton = MOUSE_MIDDLE;
204 break;
205 case 3:
206 nEventButton = MOUSE_RIGHT;
207 break;
209 priv->m_nLastButtonPressed = nEventButton;
210 pDocument->pClass->postWindowMouseEvent(pDocument,
211 priv->dialogid,
212 LOK_MOUSEEVENT_MOUSEBUTTONUP,
213 (pEvent->x),
214 (pEvent->y),
215 nCount,
216 nEventButton,
217 priv->m_nKeyModifier);
218 break;
220 default:
221 break;
223 return FALSE;
226 static gboolean
227 gtv_lok_dialog_signal_motion(GtkWidget* pDialogDrawingArea, GdkEventButton* pEvent)
229 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
230 GtvLokDialogPrivate* priv = getPrivate(pDialog);
232 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
233 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
235 g_info("lok_dialog_signal_motion: %d, %d (in twips: %d, %d)",
236 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
237 static_cast<int>(pixelToTwip(pEvent->x)),
238 static_cast<int>(pixelToTwip(pEvent->y)));
240 pDocument->pClass->postWindowMouseEvent(pDocument,
241 priv->dialogid,
242 LOK_MOUSEEVENT_MOUSEMOVE,
243 (pEvent->x),
244 (pEvent->y),
246 priv->m_nLastButtonPressed,
247 priv->m_nKeyModifier);
249 return FALSE;
252 static gboolean
253 gtv_lok_dialog_signal_key(GtkWidget* pDialogDrawingArea, GdkEventKey* pEvent)
255 GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
256 GtvLokDialogPrivate* priv = getPrivate(pDialog);
257 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
258 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
260 g_info("lok_dialog_signal_key");
261 int nCharCode = 0;
262 int nKeyCode = 0;
263 priv->m_nKeyModifier &= KEY_MOD2;
264 switch (pEvent->keyval)
266 case GDK_KEY_BackSpace:
267 nKeyCode = com::sun::star::awt::Key::BACKSPACE;
268 break;
269 case GDK_KEY_Delete:
270 nKeyCode = com::sun::star::awt::Key::DELETE;
271 break;
272 case GDK_KEY_Return:
273 case GDK_KEY_KP_Enter:
274 nKeyCode = com::sun::star::awt::Key::RETURN;
275 break;
276 case GDK_KEY_Escape:
277 nKeyCode = com::sun::star::awt::Key::ESCAPE;
278 break;
279 case GDK_KEY_Tab:
280 nKeyCode = com::sun::star::awt::Key::TAB;
281 break;
282 case GDK_KEY_Down:
283 nKeyCode = com::sun::star::awt::Key::DOWN;
284 break;
285 case GDK_KEY_Up:
286 nKeyCode = com::sun::star::awt::Key::UP;
287 break;
288 case GDK_KEY_Left:
289 nKeyCode = com::sun::star::awt::Key::LEFT;
290 break;
291 case GDK_KEY_Right:
292 nKeyCode = com::sun::star::awt::Key::RIGHT;
293 break;
294 case GDK_KEY_Page_Down:
295 nKeyCode = com::sun::star::awt::Key::PAGEDOWN;
296 break;
297 case GDK_KEY_Page_Up:
298 nKeyCode = com::sun::star::awt::Key::PAGEUP;
299 break;
300 case GDK_KEY_Insert:
301 nKeyCode = com::sun::star::awt::Key::INSERT;
302 break;
303 case GDK_KEY_Shift_L:
304 case GDK_KEY_Shift_R:
305 if (pEvent->type == GDK_KEY_PRESS)
306 priv->m_nKeyModifier |= KEY_SHIFT;
307 break;
308 case GDK_KEY_Control_L:
309 case GDK_KEY_Control_R:
310 if (pEvent->type == GDK_KEY_PRESS)
311 priv->m_nKeyModifier |= KEY_MOD1;
312 break;
313 case GDK_KEY_Alt_L:
314 case GDK_KEY_Alt_R:
315 if (pEvent->type == GDK_KEY_PRESS)
316 priv->m_nKeyModifier |= KEY_MOD2;
317 else
318 priv->m_nKeyModifier &= ~KEY_MOD2;
319 break;
320 default:
321 if (pEvent->keyval >= GDK_KEY_F1 && pEvent->keyval <= GDK_KEY_F26)
322 nKeyCode = com::sun::star::awt::Key::F1 + (pEvent->keyval - GDK_KEY_F1);
323 else
324 nCharCode = gdk_keyval_to_unicode(pEvent->keyval);
327 // rsc is not public API, but should be good enough for debugging purposes.
328 // If this is needed for real, then probably a new param of type
329 // css::awt::KeyModifier is needed in postKeyEvent().
330 if (pEvent->state & GDK_SHIFT_MASK)
331 nKeyCode |= KEY_SHIFT;
333 if (pEvent->state & GDK_CONTROL_MASK)
334 nKeyCode |= KEY_MOD1;
336 if (priv->m_nKeyModifier & KEY_MOD2)
337 nKeyCode |= KEY_MOD2;
339 if (nKeyCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)) {
340 if (pEvent->keyval >= GDK_KEY_a && pEvent->keyval <= GDK_KEY_z)
342 nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_a);
344 else if (pEvent->keyval >= GDK_KEY_A && pEvent->keyval <= GDK_KEY_Z) {
345 nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_A);
347 else if (pEvent->keyval >= GDK_KEY_0 && pEvent->keyval <= GDK_KEY_9) {
348 nKeyCode |= 256 + (pEvent->keyval - GDK_KEY_0);
352 std::stringstream ss;
353 ss << "gtv_lok_dialog::postKey(" << pEvent->type << ", " << nCharCode << ", " << nKeyCode << ")";
354 g_info("%s", ss.str().c_str());
356 pDocument->pClass->postWindowKeyEvent(pDocument,
357 priv->dialogid,
358 pEvent->type == GDK_KEY_RELEASE ? LOK_KEYEVENT_KEYUP : LOK_KEYEVENT_KEYINPUT,
359 nCharCode,
360 nKeyCode);
362 return FALSE;
365 static void
366 gtv_lok_dialog_init(GtvLokDialog* dialog)
368 GtvLokDialogPrivate* priv = getPrivate(dialog);
370 GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
371 priv->pDialogDrawingArea = gtk_drawing_area_new();
372 priv->pFloatingWin = nullptr;
373 priv->m_nChildId = 0;
374 priv->m_nChildWidth = 0;
375 priv->m_nChildHeight = 0;
377 priv->m_nLastButtonPressTime = 0;
378 priv->m_nLastButtonReleaseTime = 0;
379 priv->m_nKeyModifier = 0;
380 priv->m_nLastButtonPressed = 0;
382 gtk_widget_add_events(priv->pDialogDrawingArea,
383 GDK_BUTTON_PRESS_MASK
384 |GDK_BUTTON_RELEASE_MASK
385 |GDK_BUTTON_MOTION_MASK
386 |GDK_KEY_PRESS_MASK
387 |GDK_KEY_RELEASE_MASK);
388 // This is required to be able to capture key events on the drawing area
389 gtk_widget_set_can_focus(priv->pDialogDrawingArea, true);
391 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
392 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_signal_button), nullptr);
393 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_signal_button), nullptr);
394 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_signal_motion), nullptr);
395 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "key-press-event", G_CALLBACK(gtv_lok_dialog_signal_key), nullptr);
396 g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "key-release-event", G_CALLBACK(gtv_lok_dialog_signal_key), nullptr);
397 gtk_container_add(GTK_CONTAINER(pContentArea), priv->pDialogDrawingArea);
400 static void
401 gtv_lok_dialog_set_property(GObject* object, guint propId, const GValue* value, GParamSpec* pspec)
403 GtvLokDialog* self = GTV_LOK_DIALOG(object);
404 GtvLokDialogPrivate* priv = getPrivate(self);
406 switch(propId)
408 case PROP_LOKDOCVIEW_CONTEXT:
409 priv->lokdocview = LOK_DOC_VIEW(g_value_get_object(value));
410 break;
411 case PROP_DIALOG_ID:
412 priv->dialogid = g_value_get_uint(value);
413 break;
414 case PROP_DIALOG_WIDTH:
415 priv->m_nWidth = g_value_get_uint(value);
416 break;
417 case PROP_DIALOG_HEIGHT:
418 priv->m_nHeight = g_value_get_uint(value);
419 break;
420 default:
421 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
424 //if (propId == PROP_DIALOG_WIDTH || propId == PROP_DIALOG_HEIGHT)
425 // gtk_widget_set_size_request(GTK_WIDGET(priv->pDialogDrawingArea), priv->m_nWidth, priv->m_nHeight);
428 static void
429 gtv_lok_dialog_get_property(GObject* object, guint propId, GValue* value, GParamSpec* pspec)
431 GtvLokDialog* self = GTV_LOK_DIALOG(object);
432 GtvLokDialogPrivate* priv = getPrivate(self);
434 switch(propId)
436 case PROP_LOKDOCVIEW_CONTEXT:
437 g_value_set_object(value, priv->lokdocview);
438 break;
439 case PROP_DIALOG_ID:
440 g_value_set_uint(value, priv->dialogid);
441 break;
442 case PROP_DIALOG_WIDTH:
443 g_value_set_uint(value, priv->m_nWidth);
444 break;
445 case PROP_DIALOG_HEIGHT:
446 g_value_set_uint(value, priv->m_nHeight);
447 break;
448 default:
449 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
453 static void
454 gtv_lok_dialog_class_init(GtvLokDialogClass* klass)
456 G_OBJECT_CLASS(klass)->get_property = gtv_lok_dialog_get_property;
457 G_OBJECT_CLASS(klass)->set_property = gtv_lok_dialog_set_property;
459 properties[PROP_LOKDOCVIEW_CONTEXT] = g_param_spec_object("lokdocview",
460 "LOKDocView Context",
461 "The LOKDocView context object to be used for dialog rendering",
462 LOK_TYPE_DOC_VIEW,
463 static_cast<GParamFlags>(G_PARAM_READWRITE |
464 G_PARAM_CONSTRUCT_ONLY |
465 G_PARAM_STATIC_STRINGS));
467 properties[PROP_DIALOG_ID] = g_param_spec_uint("dialogid",
468 "Dialog identifier",
469 "Unique dialog identifier",
470 0, G_MAXUINT, 0,
471 static_cast<GParamFlags>(G_PARAM_READWRITE |
472 G_PARAM_CONSTRUCT_ONLY |
473 G_PARAM_STATIC_STRINGS));
475 properties[PROP_DIALOG_WIDTH] = g_param_spec_uint("width",
476 "Dialog width",
477 "Dialog width",
478 0, 4096, 0,
479 static_cast<GParamFlags>(G_PARAM_READWRITE |
480 G_PARAM_STATIC_STRINGS));
482 properties[PROP_DIALOG_HEIGHT] = g_param_spec_uint("height",
483 "Dialog height",
484 "Dialog height",
485 0, 2048, 0,
486 static_cast<GParamFlags>(G_PARAM_READWRITE |
487 G_PARAM_STATIC_STRINGS));
489 g_object_class_install_properties (G_OBJECT_CLASS(klass), PROP_LAST, properties);
492 static void
493 gtv_lok_dialog_floating_win_draw(GtkWidget* pDrawingArea, cairo_t* pCairo, gpointer userdata)
495 GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
496 GtvLokDialogPrivate* priv = getPrivate(pDialog);
498 g_info("gtv_lok_dialog_floating_win_draw triggered");
499 cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, priv->m_nChildWidth, priv->m_nChildHeight);
500 unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
501 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
502 pDocument->pClass->paintWindow(pDocument, priv->m_nChildId, pBuffer, 0, 0, priv->m_nChildWidth, priv->m_nChildHeight);
504 gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), priv->m_nChildWidth, priv->m_nChildHeight);
505 //gtk_widget_set_size_request(GTK_WIDGET(pDialog), nWidth, nHeight);
506 //gtk_window_resize(GTK_WINDOW(pDialog), nWidth, nHeight);
508 cairo_surface_flush(pSurface);
509 cairo_surface_mark_dirty(pSurface);
511 cairo_set_source_surface(pCairo, pSurface, 0, 0);
512 cairo_paint(pCairo);
515 static gboolean
516 gtv_lok_dialog_floating_win_signal_button(GtkWidget* /*pDialogChildDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
518 GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
519 GtvLokDialogPrivate* priv = getPrivate(pDialog);
521 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
522 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
524 std::string aEventType = "unknown";
525 if (pEvent->type == GDK_BUTTON_PRESS)
526 aEventType = "BUTTON_PRESS";
527 else if (pEvent->type == GDK_BUTTON_RELEASE)
528 aEventType = "BUTTON_RELEASE";
530 g_info("lok_dialog_floating_win_signal_button (type: %s): %d, %d (in twips: %d, %d)",
531 aEventType.c_str(),
532 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
533 static_cast<int>(pixelToTwip(pEvent->x)),
534 static_cast<int>(pixelToTwip(pEvent->y)));
536 switch (pEvent->type)
538 case GDK_BUTTON_PRESS:
540 int nCount = 1;
541 if ((pEvent->time - priv->m_nChildLastButtonPressTime) < 250)
542 nCount++;
543 priv->m_nChildLastButtonPressTime = pEvent->time;
544 int nEventButton = 0;
545 switch (pEvent->button)
547 case 1:
548 nEventButton = MOUSE_LEFT;
549 break;
550 case 2:
551 nEventButton = MOUSE_MIDDLE;
552 break;
553 case 3:
554 nEventButton = MOUSE_RIGHT;
555 break;
557 priv->m_nChildLastButtonPressed = nEventButton;
558 pDocument->pClass->postWindowMouseEvent(pDocument,
559 priv->m_nChildId,
560 LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
561 (pEvent->x),
562 (pEvent->y),
563 nCount,
564 nEventButton,
565 priv->m_nChildKeyModifier);
567 break;
569 case GDK_BUTTON_RELEASE:
571 int nCount = 1;
572 if ((pEvent->time - priv->m_nChildLastButtonReleaseTime) < 250)
573 nCount++;
574 priv->m_nChildLastButtonReleaseTime = pEvent->time;
575 int nEventButton = 0;
576 switch (pEvent->button)
578 case 1:
579 nEventButton = MOUSE_LEFT;
580 break;
581 case 2:
582 nEventButton = MOUSE_MIDDLE;
583 break;
584 case 3:
585 nEventButton = MOUSE_RIGHT;
586 break;
588 priv->m_nChildLastButtonPressed = nEventButton;
589 pDocument->pClass->postWindowMouseEvent(pDocument,
590 priv->m_nChildId,
591 LOK_MOUSEEVENT_MOUSEBUTTONUP,
592 (pEvent->x),
593 (pEvent->y),
594 nCount,
595 nEventButton,
596 priv->m_nChildKeyModifier);
597 break;
599 default:
600 break;
602 return FALSE;
605 static gboolean
606 gtv_lok_dialog_floating_win_signal_motion(GtkWidget* /*pDialogDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
608 GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
609 GtvLokDialogPrivate* priv = getPrivate(pDialog);
611 GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
612 LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
614 g_info("lok_dialog_floating_win_signal_motion: %d, %d (in twips: %d, %d)",
615 static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
616 static_cast<int>(pixelToTwip(pEvent->x)),
617 static_cast<int>(pixelToTwip(pEvent->y)));
619 pDocument->pClass->postWindowMouseEvent(pDocument,
620 priv->m_nChildId,
621 LOK_MOUSEEVENT_MOUSEMOVE,
622 (pEvent->x),
623 (pEvent->y),
625 priv->m_nChildLastButtonPressed,
626 priv->m_nChildKeyModifier);
628 return FALSE;
631 // Public methods below
633 void gtv_lok_dialog_invalidate(GtvLokDialog* dialog, const GdkRectangle& aRectangle)
635 GtvLokDialogPrivate* priv = getPrivate(dialog);
636 if (aRectangle.width != 0 && aRectangle.height != 0)
637 gtk_widget_queue_draw_area(priv->pDialogDrawingArea, aRectangle.x, aRectangle.y, aRectangle.width, aRectangle.height);
638 else
639 gtk_widget_queue_draw(priv->pDialogDrawingArea);
642 // checks if we are the parent of given childId
643 gboolean gtv_lok_dialog_is_parent_of(GtvLokDialog* dialog, guint childId)
645 GtvLokDialogPrivate* priv = getPrivate(dialog);
647 return priv->m_nChildId == childId;
650 void gtv_lok_dialog_child_create(GtvLokDialog* dialog, guint childId, guint nX, guint nY, guint width, guint height)
652 GtvLokDialogPrivate* priv = getPrivate(dialog);
654 g_debug("Dialog [ %d ] child window [ %d] being created, with dimensions [%dx%d]@(%d,%d)", priv->dialogid, childId, width, height, nX, nY);
655 priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
656 priv->m_nChildId = childId;
657 priv->m_nChildWidth = width;
658 priv->m_nChildHeight = height;
659 GtkWidget* pDrawingArea = gtk_drawing_area_new();
660 gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
662 gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
663 gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
665 gtk_widget_add_events(pDrawingArea,
666 GDK_BUTTON_PRESS_MASK
667 |GDK_POINTER_MOTION_MASK
668 |GDK_BUTTON_RELEASE_MASK
669 |GDK_BUTTON_MOTION_MASK);
671 g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
672 g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
673 g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
674 g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);
676 gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
677 gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
678 gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));
680 gtk_widget_show_all(priv->pFloatingWin);
681 gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
682 gtk_widget_grab_focus(pDrawingArea);
684 // Get the root coords of our new floating window
685 GdkWindow* pGdkWin = gtk_widget_get_window(GTK_WIDGET(dialog));
686 int nrX = 0;
687 int nrY = 0;
688 gdk_window_get_root_coords(pGdkWin, nX, nY, &nrX, &nrY);
689 gtk_window_move(GTK_WINDOW(priv->pFloatingWin), nrX, nrY);
692 void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog)
694 GtvLokDialogPrivate* priv = getPrivate(dialog);
695 g_debug("Dialog [ %d ] child invalidate request", priv->dialogid);
696 gtk_widget_queue_draw(priv->pFloatingWin);
699 void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
701 g_info("Dialog's floating window close");
703 GtvLokDialogPrivate* priv = getPrivate(dialog);
704 if (priv->pFloatingWin)
706 gtk_widget_destroy(priv->pFloatingWin);
707 priv->pFloatingWin = nullptr;
708 priv->m_nChildId = 0;
709 priv->m_nChildWidth = 0;
710 priv->m_nChildHeight = 0;
714 GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, guint dialogId, guint width, guint height)
716 g_debug("Dialog [ %d ] of size: %d x %d created", dialogId, width, height);
717 GtkWindow* pWindow = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
718 return GTK_WIDGET(g_object_new(GTV_TYPE_LOK_DIALOG,
719 "lokdocview", pDocView,
720 "dialogid", dialogId,
721 "width", width,
722 "height", height,
723 "title", "LOK Dialog",
724 "modal", false,
725 "transient-for", pWindow,
726 nullptr));
729 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */