1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
11 #include <gdk/gdkkeysyms.h>
17 #include <LibreOfficeKit/LibreOfficeKitGtk.h>
18 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
20 #include "gtv-application-window.hxx"
21 #include "gtv-signal-handlers.hxx"
22 #include "gtv-helpers.hxx"
23 #include "gtv-lok-dialog.hxx"
25 #include <com/sun/star/awt/Key.hpp>
26 #include <vcl/event.hxx>
29 #include <boost/property_tree/json_parser.hpp>
31 struct GtvLokDialogPrivate
33 LOKDocView
* lokdocview
;
34 GtkWidget
* pDialogDrawingArea
;
35 GtkWidget
* pFloatingWin
;
38 guint32 m_nLastButtonPressTime
;
39 guint32 m_nLastButtonReleaseTime
;
40 guint32 m_nKeyModifier
;
41 guint32 m_nLastButtonPressed
;
45 // state for child floating windows
47 guint32 m_nChildWidth
;
48 guint32 m_nChildHeight
;
49 guint32 m_nChildLastButtonPressTime
;
50 guint32 m_nChildLastButtonReleaseTime
;
51 guint32 m_nChildKeyModifier
;
52 guint32 m_nChildLastButtonPressed
;
58 #if __has_warning("-Wdeprecated-volatile")
59 #pragma clang diagnostic push
60 #pragma clang diagnostic ignored "-Wdeprecated-volatile"
63 G_DEFINE_TYPE_WITH_PRIVATE(GtvLokDialog
, gtv_lok_dialog
, GTK_TYPE_DIALOG
);
65 #if __has_warning("-Wdeprecated-volatile")
66 #pragma clang diagnostic pop
73 PROP_LOKDOCVIEW_CONTEXT
,
80 static GParamSpec
* properties
[PROP_LAST
];
82 static GtvLokDialogPrivate
*
83 getPrivate(GtvLokDialog
* dialog
)
85 return static_cast<GtvLokDialogPrivate
*>(gtv_lok_dialog_get_instance_private(dialog
));
89 pixelToTwip(float fInput
)
91 return (fInput
/ 96 / 1.0 /* zoom */) * 1440.0f
;
96 twipToPixel(float fInput
)
98 return fInput
/ 1440.0f
* 96 * 1.0 /* zoom */;
103 gtv_lok_dialog_draw(GtkWidget
* pDialogDrawingArea
, cairo_t
* pCairo
, gpointer
)
105 GtvLokDialog
* pDialog
= GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea
));
106 GtvLokDialogPrivate
* priv
= getPrivate(pDialog
);
109 gdk_cairo_get_clip_rectangle(pCairo
, &aRect
);
110 g_info("Painting dialog region: %d, %d, %d, %d", aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
);
112 int nWidth
= priv
->m_nWidth
;
113 int nHeight
= priv
->m_nHeight
;
114 if (aRect
.width
!= 0 && aRect
.height
!= 0)
116 nWidth
= aRect
.width
;
117 nHeight
= aRect
.height
;
120 cairo_surface_t
* pSurface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, nWidth
, nHeight
);
121 unsigned char* pBuffer
= cairo_image_surface_get_data(pSurface
);
122 LibreOfficeKitDocument
* pDocument
= lok_doc_view_get_document(LOK_DOC_VIEW(priv
->lokdocview
));
123 pDocument
->pClass
->paintWindow(pDocument
, priv
->dialogid
, pBuffer
, aRect
.x
, aRect
.y
, nWidth
, nHeight
);
125 gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea
), priv
->m_nWidth
, priv
->m_nHeight
);
127 cairo_surface_flush(pSurface
);
128 cairo_surface_mark_dirty(pSurface
);
130 cairo_set_source_surface(pCairo
, pSurface
, aRect
.x
, aRect
.y
);
131 // paint the dialog image
134 // debug red-colored border around the painted region
135 cairo_set_source_rgb(pCairo
, 1.0, 0, 0);
136 cairo_rectangle(pCairo
, aRect
.x
, aRect
.y
, nWidth
, nHeight
);
137 cairo_stroke(pCairo
);
141 gtv_lok_dialog_signal_button(GtkWidget
* pDialogDrawingArea
, GdkEventButton
* pEvent
)
143 GtvLokDialog
* pDialog
= GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea
));
144 GtvLokDialogPrivate
* priv
= getPrivate(pDialog
);
146 GtvApplicationWindow
* window
= GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog
)));
147 LibreOfficeKitDocument
* pDocument
= lok_doc_view_get_document(LOK_DOC_VIEW(window
->lokdocview
));
149 std::string aEventType
= "unknown";
150 if (pEvent
->type
== GDK_BUTTON_PRESS
)
151 aEventType
= "BUTTON_PRESS";
152 else if (pEvent
->type
== GDK_BUTTON_RELEASE
)
153 aEventType
= "BUTTON_RELEASE";
155 g_info("lok_dialog_signal_button (type: %s): %d, %d",
157 static_cast<int>(pEvent
->x
), static_cast<int>(pEvent
->y
));
158 gtk_widget_grab_focus(pDialogDrawingArea
);
160 switch (pEvent
->type
)
162 case GDK_BUTTON_PRESS
:
165 if ((pEvent
->time
- priv
->m_nLastButtonPressTime
) < 250)
167 priv
->m_nLastButtonPressTime
= pEvent
->time
;
168 int nEventButton
= 0;
169 switch (pEvent
->button
)
172 nEventButton
= MOUSE_LEFT
;
175 nEventButton
= MOUSE_MIDDLE
;
178 nEventButton
= MOUSE_RIGHT
;
181 priv
->m_nLastButtonPressed
= nEventButton
;
182 pDocument
->pClass
->postWindowMouseEvent(pDocument
,
184 LOK_MOUSEEVENT_MOUSEBUTTONDOWN
,
189 priv
->m_nKeyModifier
);
193 case GDK_BUTTON_RELEASE
:
196 if ((pEvent
->time
- priv
->m_nLastButtonReleaseTime
) < 250)
198 priv
->m_nLastButtonReleaseTime
= pEvent
->time
;
199 int nEventButton
= 0;
200 switch (pEvent
->button
)
203 nEventButton
= MOUSE_LEFT
;
206 nEventButton
= MOUSE_MIDDLE
;
209 nEventButton
= MOUSE_RIGHT
;
212 priv
->m_nLastButtonPressed
= nEventButton
;
213 pDocument
->pClass
->postWindowMouseEvent(pDocument
,
215 LOK_MOUSEEVENT_MOUSEBUTTONUP
,
220 priv
->m_nKeyModifier
);
230 gtv_lok_dialog_signal_motion(GtkWidget
* pDialogDrawingArea
, GdkEventButton
* pEvent
)
232 GtvLokDialog
* pDialog
= GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea
));
233 GtvLokDialogPrivate
* priv
= getPrivate(pDialog
);
235 GtvApplicationWindow
* window
= GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog
)));
236 LibreOfficeKitDocument
* pDocument
= lok_doc_view_get_document(LOK_DOC_VIEW(window
->lokdocview
));
238 g_info("lok_dialog_signal_motion: %d, %d (in twips: %d, %d)",
239 static_cast<int>(pEvent
->x
), static_cast<int>(pEvent
->y
),
240 static_cast<int>(pixelToTwip(pEvent
->x
)),
241 static_cast<int>(pixelToTwip(pEvent
->y
)));
243 pDocument
->pClass
->postWindowMouseEvent(pDocument
,
245 LOK_MOUSEEVENT_MOUSEMOVE
,
249 priv
->m_nLastButtonPressed
,
250 priv
->m_nKeyModifier
);
256 gtv_lok_dialog_signal_key(GtkWidget
* pDialogDrawingArea
, GdkEventKey
* pEvent
)
258 GtvLokDialog
* pDialog
= GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea
));
259 GtvLokDialogPrivate
* priv
= getPrivate(pDialog
);
260 GtvApplicationWindow
* window
= GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog
)));
261 LibreOfficeKitDocument
* pDocument
= lok_doc_view_get_document(LOK_DOC_VIEW(window
->lokdocview
));
263 g_info("lok_dialog_signal_key");
266 priv
->m_nKeyModifier
&= KEY_MOD2
;
267 switch (pEvent
->keyval
)
269 case GDK_KEY_BackSpace
:
270 nKeyCode
= com::sun::star::awt::Key::BACKSPACE
;
273 nKeyCode
= com::sun::star::awt::Key::DELETE
;
276 case GDK_KEY_KP_Enter
:
277 nKeyCode
= com::sun::star::awt::Key::RETURN
;
280 nKeyCode
= com::sun::star::awt::Key::ESCAPE
;
283 nKeyCode
= com::sun::star::awt::Key::TAB
;
286 nKeyCode
= com::sun::star::awt::Key::DOWN
;
289 nKeyCode
= com::sun::star::awt::Key::UP
;
292 nKeyCode
= com::sun::star::awt::Key::LEFT
;
295 nKeyCode
= com::sun::star::awt::Key::RIGHT
;
297 case GDK_KEY_Page_Down
:
298 nKeyCode
= com::sun::star::awt::Key::PAGEDOWN
;
300 case GDK_KEY_Page_Up
:
301 nKeyCode
= com::sun::star::awt::Key::PAGEUP
;
304 nKeyCode
= com::sun::star::awt::Key::INSERT
;
306 case GDK_KEY_Shift_L
:
307 case GDK_KEY_Shift_R
:
308 if (pEvent
->type
== GDK_KEY_PRESS
)
309 priv
->m_nKeyModifier
|= KEY_SHIFT
;
311 case GDK_KEY_Control_L
:
312 case GDK_KEY_Control_R
:
313 if (pEvent
->type
== GDK_KEY_PRESS
)
314 priv
->m_nKeyModifier
|= KEY_MOD1
;
318 if (pEvent
->type
== GDK_KEY_PRESS
)
319 priv
->m_nKeyModifier
|= KEY_MOD2
;
321 priv
->m_nKeyModifier
&= ~KEY_MOD2
;
324 if (pEvent
->keyval
>= GDK_KEY_F1
&& pEvent
->keyval
<= GDK_KEY_F26
)
325 nKeyCode
= com::sun::star::awt::Key::F1
+ (pEvent
->keyval
- GDK_KEY_F1
);
327 nCharCode
= gdk_keyval_to_unicode(pEvent
->keyval
);
330 // rsc is not public API, but should be good enough for debugging purposes.
331 // If this is needed for real, then probably a new param of type
332 // css::awt::KeyModifier is needed in postKeyEvent().
333 if (pEvent
->state
& GDK_SHIFT_MASK
)
334 nKeyCode
|= KEY_SHIFT
;
336 if (pEvent
->state
& GDK_CONTROL_MASK
)
337 nKeyCode
|= KEY_MOD1
;
339 if (priv
->m_nKeyModifier
& KEY_MOD2
)
340 nKeyCode
|= KEY_MOD2
;
342 if (nKeyCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
)) {
343 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_A
&& pEvent
->keyval
<= GDK_KEY_Z
) {
348 nKeyCode
|= 512 + (pEvent
->keyval
- GDK_KEY_A
);
350 else if (pEvent
->keyval
>= GDK_KEY_0
&& pEvent
->keyval
<= GDK_KEY_9
) {
351 nKeyCode
|= 256 + (pEvent
->keyval
- GDK_KEY_0
);
355 std::stringstream ss
;
356 ss
<< "gtv_lok_dialog::postKey(" << pEvent
->type
<< ", " << nCharCode
<< ", " << nKeyCode
<< ")";
357 g_info("%s", ss
.str().c_str());
359 pDocument
->pClass
->postWindowKeyEvent(pDocument
,
361 pEvent
->type
== GDK_KEY_RELEASE
? LOK_KEYEVENT_KEYUP
: LOK_KEYEVENT_KEYINPUT
,
369 gtv_lok_dialog_init(GtvLokDialog
* dialog
)
371 GtvLokDialogPrivate
* priv
= getPrivate(dialog
);
373 GtkWidget
* pContentArea
= gtk_dialog_get_content_area(GTK_DIALOG(dialog
));
374 priv
->pDialogDrawingArea
= gtk_drawing_area_new();
375 priv
->pFloatingWin
= nullptr;
376 priv
->m_nChildId
= 0;
377 priv
->m_nChildWidth
= 0;
378 priv
->m_nChildHeight
= 0;
380 priv
->m_nLastButtonPressTime
= 0;
381 priv
->m_nLastButtonReleaseTime
= 0;
382 priv
->m_nKeyModifier
= 0;
383 priv
->m_nLastButtonPressed
= 0;
385 gtk_widget_add_events(priv
->pDialogDrawingArea
,
386 GDK_BUTTON_PRESS_MASK
387 |GDK_BUTTON_RELEASE_MASK
388 |GDK_BUTTON_MOTION_MASK
390 |GDK_KEY_RELEASE_MASK
);
391 // This is required to be able to capture key events on the drawing area
392 gtk_widget_set_can_focus(priv
->pDialogDrawingArea
, true);
394 g_signal_connect(G_OBJECT(priv
->pDialogDrawingArea
), "draw", G_CALLBACK(gtv_lok_dialog_draw
), nullptr);
395 g_signal_connect(G_OBJECT(priv
->pDialogDrawingArea
), "button-press-event", G_CALLBACK(gtv_lok_dialog_signal_button
), nullptr);
396 g_signal_connect(G_OBJECT(priv
->pDialogDrawingArea
), "button-release-event", G_CALLBACK(gtv_lok_dialog_signal_button
), nullptr);
397 g_signal_connect(G_OBJECT(priv
->pDialogDrawingArea
), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_signal_motion
), nullptr);
398 g_signal_connect(G_OBJECT(priv
->pDialogDrawingArea
), "key-press-event", G_CALLBACK(gtv_lok_dialog_signal_key
), nullptr);
399 g_signal_connect(G_OBJECT(priv
->pDialogDrawingArea
), "key-release-event", G_CALLBACK(gtv_lok_dialog_signal_key
), nullptr);
400 gtk_container_add(GTK_CONTAINER(pContentArea
), priv
->pDialogDrawingArea
);
404 gtv_lok_dialog_set_property(GObject
* object
, guint propId
, const GValue
* value
, GParamSpec
* pspec
)
406 GtvLokDialog
* self
= GTV_LOK_DIALOG(object
);
407 GtvLokDialogPrivate
* priv
= getPrivate(self
);
411 case PROP_LOKDOCVIEW_CONTEXT
:
412 priv
->lokdocview
= LOK_DOC_VIEW(g_value_get_object(value
));
415 priv
->dialogid
= g_value_get_uint(value
);
417 case PROP_DIALOG_WIDTH
:
418 priv
->m_nWidth
= g_value_get_uint(value
);
420 case PROP_DIALOG_HEIGHT
:
421 priv
->m_nHeight
= g_value_get_uint(value
);
424 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, propId
, pspec
);
427 //if (propId == PROP_DIALOG_WIDTH || propId == PROP_DIALOG_HEIGHT)
428 // gtk_widget_set_size_request(GTK_WIDGET(priv->pDialogDrawingArea), priv->m_nWidth, priv->m_nHeight);
432 gtv_lok_dialog_get_property(GObject
* object
, guint propId
, GValue
* value
, GParamSpec
* pspec
)
434 GtvLokDialog
* self
= GTV_LOK_DIALOG(object
);
435 GtvLokDialogPrivate
* priv
= getPrivate(self
);
439 case PROP_LOKDOCVIEW_CONTEXT
:
440 g_value_set_object(value
, priv
->lokdocview
);
443 g_value_set_uint(value
, priv
->dialogid
);
445 case PROP_DIALOG_WIDTH
:
446 g_value_set_uint(value
, priv
->m_nWidth
);
448 case PROP_DIALOG_HEIGHT
:
449 g_value_set_uint(value
, priv
->m_nHeight
);
452 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, propId
, pspec
);
457 gtv_lok_dialog_class_init(GtvLokDialogClass
* klass
)
459 G_OBJECT_CLASS(klass
)->get_property
= gtv_lok_dialog_get_property
;
460 G_OBJECT_CLASS(klass
)->set_property
= gtv_lok_dialog_set_property
;
462 properties
[PROP_LOKDOCVIEW_CONTEXT
] = g_param_spec_object("lokdocview",
463 "LOKDocView Context",
464 "The LOKDocView context object to be used for dialog rendering",
466 static_cast<GParamFlags
>(G_PARAM_READWRITE
|
467 G_PARAM_CONSTRUCT_ONLY
|
468 G_PARAM_STATIC_STRINGS
));
470 properties
[PROP_DIALOG_ID
] = g_param_spec_uint("dialogid",
472 "Unique dialog identifier",
474 static_cast<GParamFlags
>(G_PARAM_READWRITE
|
475 G_PARAM_CONSTRUCT_ONLY
|
476 G_PARAM_STATIC_STRINGS
));
478 properties
[PROP_DIALOG_WIDTH
] = g_param_spec_uint("width",
482 static_cast<GParamFlags
>(G_PARAM_READWRITE
|
483 G_PARAM_STATIC_STRINGS
));
485 properties
[PROP_DIALOG_HEIGHT
] = g_param_spec_uint("height",
489 static_cast<GParamFlags
>(G_PARAM_READWRITE
|
490 G_PARAM_STATIC_STRINGS
));
492 g_object_class_install_properties (G_OBJECT_CLASS(klass
), PROP_LAST
, properties
);
496 gtv_lok_dialog_floating_win_draw(GtkWidget
* pDrawingArea
, cairo_t
* pCairo
, gpointer userdata
)
498 GtvLokDialog
* pDialog
= GTV_LOK_DIALOG(userdata
);
499 GtvLokDialogPrivate
* priv
= getPrivate(pDialog
);
501 g_info("gtv_lok_dialog_floating_win_draw triggered");
502 cairo_surface_t
* pSurface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, priv
->m_nChildWidth
, priv
->m_nChildHeight
);
503 unsigned char* pBuffer
= cairo_image_surface_get_data(pSurface
);
504 LibreOfficeKitDocument
* pDocument
= lok_doc_view_get_document(LOK_DOC_VIEW(priv
->lokdocview
));
505 pDocument
->pClass
->paintWindow(pDocument
, priv
->m_nChildId
, pBuffer
, 0, 0, priv
->m_nChildWidth
, priv
->m_nChildHeight
);
507 gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea
), priv
->m_nChildWidth
, priv
->m_nChildHeight
);
508 //gtk_widget_set_size_request(GTK_WIDGET(pDialog), nWidth, nHeight);
509 //gtk_window_resize(GTK_WINDOW(pDialog), nWidth, nHeight);
511 cairo_surface_flush(pSurface
);
512 cairo_surface_mark_dirty(pSurface
);
514 cairo_set_source_surface(pCairo
, pSurface
, 0, 0);
519 gtv_lok_dialog_floating_win_signal_button(GtkWidget
* /*pDialogChildDrawingArea*/, GdkEventButton
* pEvent
, gpointer userdata
)
521 GtvLokDialog
* pDialog
= GTV_LOK_DIALOG(userdata
);
522 GtvLokDialogPrivate
* priv
= getPrivate(pDialog
);
524 GtvApplicationWindow
* window
= GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog
)));
525 LibreOfficeKitDocument
* pDocument
= lok_doc_view_get_document(LOK_DOC_VIEW(window
->lokdocview
));
527 std::string aEventType
= "unknown";
528 if (pEvent
->type
== GDK_BUTTON_PRESS
)
529 aEventType
= "BUTTON_PRESS";
530 else if (pEvent
->type
== GDK_BUTTON_RELEASE
)
531 aEventType
= "BUTTON_RELEASE";
533 g_info("lok_dialog_floating_win_signal_button (type: %s): %d, %d (in twips: %d, %d)",
535 static_cast<int>(pEvent
->x
), static_cast<int>(pEvent
->y
),
536 static_cast<int>(pixelToTwip(pEvent
->x
)),
537 static_cast<int>(pixelToTwip(pEvent
->y
)));
539 switch (pEvent
->type
)
541 case GDK_BUTTON_PRESS
:
544 if ((pEvent
->time
- priv
->m_nChildLastButtonPressTime
) < 250)
546 priv
->m_nChildLastButtonPressTime
= pEvent
->time
;
547 int nEventButton
= 0;
548 switch (pEvent
->button
)
551 nEventButton
= MOUSE_LEFT
;
554 nEventButton
= MOUSE_MIDDLE
;
557 nEventButton
= MOUSE_RIGHT
;
560 priv
->m_nChildLastButtonPressed
= nEventButton
;
561 pDocument
->pClass
->postWindowMouseEvent(pDocument
,
563 LOK_MOUSEEVENT_MOUSEBUTTONDOWN
,
568 priv
->m_nChildKeyModifier
);
572 case GDK_BUTTON_RELEASE
:
575 if ((pEvent
->time
- priv
->m_nChildLastButtonReleaseTime
) < 250)
577 priv
->m_nChildLastButtonReleaseTime
= pEvent
->time
;
578 int nEventButton
= 0;
579 switch (pEvent
->button
)
582 nEventButton
= MOUSE_LEFT
;
585 nEventButton
= MOUSE_MIDDLE
;
588 nEventButton
= MOUSE_RIGHT
;
591 priv
->m_nChildLastButtonPressed
= nEventButton
;
592 pDocument
->pClass
->postWindowMouseEvent(pDocument
,
594 LOK_MOUSEEVENT_MOUSEBUTTONUP
,
599 priv
->m_nChildKeyModifier
);
609 gtv_lok_dialog_floating_win_signal_motion(GtkWidget
* /*pDialogDrawingArea*/, GdkEventButton
* pEvent
, gpointer userdata
)
611 GtvLokDialog
* pDialog
= GTV_LOK_DIALOG(userdata
);
612 GtvLokDialogPrivate
* priv
= getPrivate(pDialog
);
614 GtvApplicationWindow
* window
= GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog
)));
615 LibreOfficeKitDocument
* pDocument
= lok_doc_view_get_document(LOK_DOC_VIEW(window
->lokdocview
));
617 g_info("lok_dialog_floating_win_signal_motion: %d, %d (in twips: %d, %d)",
618 static_cast<int>(pEvent
->x
), static_cast<int>(pEvent
->y
),
619 static_cast<int>(pixelToTwip(pEvent
->x
)),
620 static_cast<int>(pixelToTwip(pEvent
->y
)));
622 pDocument
->pClass
->postWindowMouseEvent(pDocument
,
624 LOK_MOUSEEVENT_MOUSEMOVE
,
628 priv
->m_nChildLastButtonPressed
,
629 priv
->m_nChildKeyModifier
);
634 // Public methods below
636 void gtv_lok_dialog_invalidate(GtvLokDialog
* dialog
, const GdkRectangle
& aRectangle
)
638 GtvLokDialogPrivate
* priv
= getPrivate(dialog
);
639 if (aRectangle
.width
!= 0 && aRectangle
.height
!= 0)
640 gtk_widget_queue_draw_area(priv
->pDialogDrawingArea
, aRectangle
.x
, aRectangle
.y
, aRectangle
.width
, aRectangle
.height
);
642 gtk_widget_queue_draw(priv
->pDialogDrawingArea
);
645 // checks if we are the parent of given childId
646 gboolean
gtv_lok_dialog_is_parent_of(GtvLokDialog
* dialog
, guint childId
)
648 GtvLokDialogPrivate
* priv
= getPrivate(dialog
);
650 return priv
->m_nChildId
== childId
;
653 void gtv_lok_dialog_child_create(GtvLokDialog
* dialog
, guint childId
, guint nX
, guint nY
, guint width
, guint height
)
655 GtvLokDialogPrivate
* priv
= getPrivate(dialog
);
657 g_debug("Dialog [ %d ] child window [ %d] being created, with dimensions [%dx%d]@(%d,%d)", priv
->dialogid
, childId
, width
, height
, nX
, nY
);
658 priv
->pFloatingWin
= gtk_window_new(GTK_WINDOW_POPUP
);
659 priv
->m_nChildId
= childId
;
660 priv
->m_nChildWidth
= width
;
661 priv
->m_nChildHeight
= height
;
662 GtkWidget
* pDrawingArea
= gtk_drawing_area_new();
663 gtk_container_add(GTK_CONTAINER(priv
->pFloatingWin
), pDrawingArea
);
665 gtk_window_set_transient_for(GTK_WINDOW(priv
->pFloatingWin
), GTK_WINDOW(dialog
));
666 gtk_window_set_destroy_with_parent(GTK_WINDOW(priv
->pFloatingWin
), true);
668 gtk_widget_add_events(pDrawingArea
,
669 GDK_BUTTON_PRESS_MASK
670 |GDK_POINTER_MOTION_MASK
671 |GDK_BUTTON_RELEASE_MASK
672 |GDK_BUTTON_MOTION_MASK
);
674 g_signal_connect(G_OBJECT(pDrawingArea
), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw
), dialog
);
675 g_signal_connect(G_OBJECT(pDrawingArea
), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button
), dialog
);
676 g_signal_connect(G_OBJECT(pDrawingArea
), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button
), dialog
);
677 g_signal_connect(G_OBJECT(pDrawingArea
), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion
), dialog
);
679 gtk_widget_set_size_request(priv
->pFloatingWin
, 1, 1);
680 gtk_window_set_type_hint(GTK_WINDOW(priv
->pFloatingWin
), GDK_WINDOW_TYPE_HINT_POPUP_MENU
);
681 gtk_window_set_screen(GTK_WINDOW(priv
->pFloatingWin
), gtk_window_get_screen(GTK_WINDOW(dialog
)));
683 gtk_widget_show_all(priv
->pFloatingWin
);
684 gtk_window_present(GTK_WINDOW(priv
->pFloatingWin
));
685 gtk_widget_grab_focus(pDrawingArea
);
687 // Get the root coords of our new floating window
688 GdkWindow
* pGdkWin
= gtk_widget_get_window(GTK_WIDGET(dialog
));
691 gdk_window_get_root_coords(pGdkWin
, nX
, nY
, &nrX
, &nrY
);
692 gtk_window_move(GTK_WINDOW(priv
->pFloatingWin
), nrX
, nrY
);
695 void gtv_lok_dialog_child_invalidate(GtvLokDialog
* dialog
)
697 GtvLokDialogPrivate
* priv
= getPrivate(dialog
);
698 g_debug("Dialog [ %d ] child invalidate request", priv
->dialogid
);
699 gtk_widget_queue_draw(priv
->pFloatingWin
);
702 void gtv_lok_dialog_child_close(GtvLokDialog
* dialog
)
704 g_info("Dialog's floating window close");
706 GtvLokDialogPrivate
* priv
= getPrivate(dialog
);
707 if (priv
->pFloatingWin
)
709 gtk_widget_destroy(priv
->pFloatingWin
);
710 priv
->pFloatingWin
= nullptr;
711 priv
->m_nChildId
= 0;
712 priv
->m_nChildWidth
= 0;
713 priv
->m_nChildHeight
= 0;
717 GtkWidget
* gtv_lok_dialog_new(LOKDocView
* pDocView
, guint dialogId
, guint width
, guint height
)
719 g_debug("Dialog [ %d ] of size: %d x %d created", dialogId
, width
, height
);
720 GtkWindow
* pWindow
= GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView
)));
721 return GTK_WIDGET(g_object_new(GTV_TYPE_LOK_DIALOG
,
722 "lokdocview", pDocView
,
723 "dialogid", dialogId
,
726 "title", "LOK Dialog",
728 "transient-for", pWindow
,
732 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */