1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2
3 /* AbiSource Application Framework
4 * Copyright (C) 1998-2000 AbiSource, Inc.
5 * Copyright (C) 2002 William Lachance
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23 /*
24 * Port to Maemo Development Platform
25 * Author: INdT - Renato Araujo <renato.filho@indt.org.br>
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <gtk/gtk.h>
33 #include <gdk/gdkkeysyms.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <sys/stat.h>
38 #include <string.h>
39 #include <vector>
40
41 #include "ap_Features.h"
42 #include "ut_string.h"
43 #include "ut_types.h"
44 #include "ut_assert.h"
45 #include "ut_files.h"
46 #include "ut_misc.h"
47 #include "ut_sleep.h"
48 #include "xap_Gtk2Compat.h"
49 #include "xap_ViewListener.h"
50 #include "xap_UnixApp.h"
51 #include "xap_UnixFrameImpl.h"
52 #include "xap_Frame.h"
53 #include "ev_UnixKeyboard.h"
54 #include "ev_UnixMouse.h"
55 #include "ev_UnixMenuBar.h"
56 #include "ev_UnixMenuPopup.h"
57 #include "ev_UnixToolbar.h"
58 #include "ev_EditMethod.h"
59 #include "xav_View.h"
60 #include "fv_View.h"
61 #include "fv_FrameEdit.h"
62 #include "fl_DocLayout.h"
63 #include "xad_Document.h"
64 #include "gr_CairoGraphics.h"
65 #include "xap_UnixDialogHelper.h"
66 #include "xap_UnixClipboard.h"
67 #include "xap_Strings.h"
68 #include "xap_Prefs.h"
69 #include "ap_FrameData.h"
70 #include "ap_UnixFrame.h"
71 #include "ev_Mouse.h"
72
73 #include "ie_types.h"
74 #include "ie_imp.h"
75 #include "ie_impGraphic.h"
76 #include "fg_Graphic.h"
77
78 #ifdef HAVE_GCONF
79 #include "ev_GnomeToolbar.h"
80 #endif
81
82 #if defined(EMBEDDED_TARGET) && EMBEDDED_TARGET == EMBEDDED_TARGET_HILDON
83 #include "hildon/xap_UnixHildonApp.h"
84 #endif
85
86
87 enum {
88 TARGET_DOCUMENT, // 0, to sync with gtk_drag_dest_add_text_target's default info value
89 TARGET_IMAGE,
90 TARGET_URI_LIST,
91 TARGET_URL,
92 TARGET_UNKNOWN
93 };
94
95 static const GtkTargetEntry XAP_UnixFrameImpl__knownDragTypes[] = {
96 {(gchar *)"text/uri-list", 0, TARGET_URI_LIST},
97 {(gchar *)"_NETSCAPE_URL", 0, TARGET_URL},
98 {(gchar *)"image/gif", 0, TARGET_IMAGE},
99 {(gchar *)"image/jpeg", 0, TARGET_IMAGE},
100 {(gchar *)"image/png", 0, TARGET_IMAGE},
101 {(gchar *)"image/tiff", 0, TARGET_IMAGE},
102 {(gchar *)"image/vnd", 0, TARGET_IMAGE},
103 {(gchar *)"image/bmp", 0, TARGET_IMAGE},
104 {(gchar *)"image/x-xpixmap", 0, TARGET_IMAGE},
105
106 // RDF types
107 {(gchar *)"text/x-vcard", 0, TARGET_DOCUMENT}
108 };
109
110 struct DragInfo {
111 GtkTargetEntry * entries;
112 guint count;
113
DragInfoDragInfo114 DragInfo()
115 : entries(NULL), count(0)
116 {
117 }
118
~DragInfoDragInfo119 ~DragInfo()
120 {
121 for(guint i = 0; i < count; i++)
122 g_free(entries[i].target);
123
124 g_free(entries);
125 }
126
addEntryDragInfo127 void addEntry(const char * target, guint flags, guint info)
128 {
129 count++;
130 entries = (GtkTargetEntry *)g_realloc(entries, count * sizeof(GtkTargetEntry));
131 entries[count - 1].target = g_strdup(target);
132 entries[count - 1].flags = flags;
133 entries[count - 1].info = info;
134 }
135
136 private:
137 DragInfo& operator=(const DragInfo & rhs);
138 DragInfo(const DragInfo & rhs);
139 };
140
141 /*!
142 * Build targets table from supported mime types.
143 */
s_getDragInfo()144 static DragInfo * s_getDragInfo ()
145 {
146 static DragInfo dragInfo;
147 bool isInitialized = FALSE;
148
149 if (isInitialized) {
150 return &dragInfo;
151 }
152
153 std::vector<std::string>::const_iterator iter;
154 std::vector<std::string>::const_iterator end;
155
156 // static types
157 for (gsize idx = 0; idx < G_N_ELEMENTS(XAP_UnixFrameImpl__knownDragTypes); idx++) {
158 dragInfo.addEntry(XAP_UnixFrameImpl__knownDragTypes[idx].target,
159 XAP_UnixFrameImpl__knownDragTypes[idx].flags,
160 XAP_UnixFrameImpl__knownDragTypes[idx].info);
161 }
162
163 // document types
164 std::vector<std::string> &mimeTypes = IE_Imp::getSupportedMimeTypes();
165 iter = mimeTypes.begin();
166 end = mimeTypes.end();
167 while (iter != end) {
168 dragInfo.addEntry((*iter).c_str(), 0, TARGET_DOCUMENT);
169 iter++;
170 }
171
172 // image types
173 mimeTypes = IE_ImpGraphic::getSupportedMimeTypes();
174 iter = mimeTypes.begin();
175 end = mimeTypes.end();
176 while (iter != end) {
177 dragInfo.addEntry((*iter).c_str(), 0, TARGET_IMAGE);
178 iter++;
179 }
180
181 isInitialized = TRUE;
182
183 return &dragInfo;
184 }
185
s_mapMimeToUriType(const char * uri)186 static int s_mapMimeToUriType (const char * uri)
187 {
188 if (!uri || !strlen(uri))
189 return TARGET_UNKNOWN;
190
191 int target = TARGET_UNKNOWN;
192
193 gchar *mimeType;
194
195 mimeType = UT_go_get_mime_type (uri);
196
197 if (g_ascii_strcasecmp (mimeType, "application/octet-stream") == 0) {
198 FREEP (mimeType);
199 std::string suffix = UT_pathSuffix(uri);
200 if (!suffix.empty()) {
201 const gchar *mt = IE_Imp::getMimeTypeForSuffix(suffix.c_str());
202 if (!mt) {
203 mt = IE_ImpGraphic::getMimeTypeForSuffix(suffix.c_str());
204 }
205 if (mt) {
206 /* we to g_free that later */
207 mimeType = g_strdup(mt);
208 }
209 else {
210 return target;
211 }
212 }
213 else {
214 return target;
215 }
216 }
217
218 UT_DEBUGMSG(("DOM: mimeType %s dropped into AbiWord(%s)\n", mimeType, uri));
219
220 DragInfo * dragInfo = s_getDragInfo();
221 for (size_t i = 0; i < dragInfo->count; i++)
222 if (!g_ascii_strcasecmp (mimeType, dragInfo->entries[i].target)) {
223 target = dragInfo->entries[i].info;
224 break;
225 }
226
227 g_free (mimeType);
228 return target;
229 }
230
231 static void
s_loadImage(const UT_UTF8String & file,FV_View * pView,XAP_Frame * pF,gint x,gint y)232 s_loadImage (const UT_UTF8String & file, FV_View * pView, XAP_Frame * pF, gint x, gint y)
233 {
234 FG_Graphic * pFG = 0;
235 UT_Error error = IE_ImpGraphic::loadGraphic (file.utf8_str(), 0, &pFG);
236 if (error != UT_OK || !pFG)
237 {
238 UT_DEBUGMSG(("Dom: could not import graphic (%s)\n", file.utf8_str()));
239 return;
240 }
241 UT_sint32 xoff = static_cast<AP_UnixFrame*>(pF)->getDocumentAreaXoff();
242 UT_sint32 yoff = static_cast<AP_UnixFrame*>(pF)->getDocumentAreaYoff();
243 UT_sint32 mouseX = x - xoff;
244 UT_sint32 mouseY = y - yoff;
245 UT_DEBUGMSG(("x %d xoff %d y %d yoff %d ",y,xoff,y,yoff));
246 if(pView && pView->getGraphics())
247 mouseX = pView->getGraphics()->tlu(mouseX);
248 if(pView && pView->getGraphics())
249 mouseY = pView->getGraphics()->tlu(mouseY);
250 #ifdef DEBUG
251 double xInch = (double) mouseX/1440.;
252 double yInch = (double) mouseY/1440.;
253 #endif
254
255 UT_DEBUGMSG(("Insert Image at logical (x,y) %d %d \n",mouseX,mouseY));
256
257 UT_DEBUGMSG(("Insert Image at x %f in y %f in \n",xInch,yInch));
258 pView->cmdInsertPositionedGraphic(pFG,mouseX,mouseY);
259 DELETEP(pFG);
260 }
261
262 static void
s_loadImage(const UT_ByteBuf & bytes,FV_View * pView,XAP_Frame * pF,gint x,gint y)263 s_loadImage (const UT_ByteBuf & bytes, FV_View * pView, XAP_Frame * pF, gint x, gint y)
264 {
265 FG_Graphic * pFG = 0;
266 UT_Error error = IE_ImpGraphic::loadGraphic(bytes, 0, &pFG);
267 if (error != UT_OK || !pFG)
268 {
269 UT_DEBUGMSG(("JK: could not import graphic from data buffer\n"));
270 return;
271 }
272 UT_sint32 xoff = static_cast<AP_UnixFrame*>(pF)->getDocumentAreaXoff();
273 UT_sint32 yoff = static_cast<AP_UnixFrame*>(pF)->getDocumentAreaYoff();
274 UT_sint32 mouseX = x - xoff;
275 UT_sint32 mouseY = y - yoff;
276 UT_DEBUGMSG(("x %d newX %d y %d newY %d ",y,xoff,y,yoff));
277 if(pView && pView->getGraphics())
278 mouseX = pView->getGraphics()->tlu(mouseX);
279 if(pView && pView->getGraphics())
280 mouseY = pView->getGraphics()->tlu(mouseY);
281
282 pView->cmdInsertPositionedGraphic(pFG,mouseX,mouseY);
283 DELETEP(pFG);
284 }
285
286 static void
s_loadDocument(const UT_UTF8String & file,XAP_Frame * pFrame)287 s_loadDocument (const UT_UTF8String & file, XAP_Frame * pFrame)
288 {
289 XAP_Frame * pNewFrame = 0;
290 if (pFrame->isDirty() || pFrame->getFilename() ||
291 (pFrame->getViewNumber() > 0))
292 pNewFrame = XAP_App::getApp()->newFrame ();
293 else
294 pNewFrame = pFrame;
295
296
297 UT_Error error = pNewFrame->loadDocument(file.utf8_str(), 0 /* IEFT_Unknown */);
298 if (error)
299 {
300 // TODO: warn user that we couldn't open that file
301 // TODO: we crash if we just delete this without putting something
302 // TODO: in it, so let's go ahead and open an untitled document
303 // TODO: for now.
304 UT_DEBUGMSG(("DOM: couldn't load document %s\n", file.utf8_str()));
305 pNewFrame->loadDocument((const char *)NULL, 0 /* IEFT_Unknown */);
306 }
307 }
308
s_pasteFile(const UT_UTF8String & file,XAP_Frame * pFrame)309 static void s_pasteFile(const UT_UTF8String & file, XAP_Frame * pFrame)
310 {
311 if(!pFrame)
312 return;
313 XAP_App * pApp = XAP_App::getApp();
314 PD_Document * newDoc = new PD_Document();
315 UT_Error err = newDoc->readFromFile(file.utf8_str(), IEFT_Unknown);
316 if ( err != UT_OK )
317 {
318 UNREFP(newDoc);
319 return;
320 }
321 FV_View * pView = static_cast<FV_View *>(pFrame->getCurrentView());
322 // we'll share the same graphics context, which won't matter because
323 // we only use it to get font metrics and stuff and not actually draw
324 GR_Graphics *pGraphics = pView->getGraphics();
325 // create a new layout and view object for the doc
326 FL_DocLayout *pDocLayout = new FL_DocLayout(newDoc,pGraphics);
327 FV_View copyView(pApp,0,pDocLayout);
328
329 pDocLayout->setView (©View);
330 pDocLayout->fillLayouts();
331
332 copyView.cmdSelect(0, 0, FV_DOCPOS_BOD, FV_DOCPOS_EOD); // select all the contents of the new doc
333 copyView.cmdCopy(); // copy the contents of the new document
334 pView->cmdPaste ( true ); // paste the contents into the existing document honoring the formatting
335
336 DELETEP(pDocLayout);
337 UNREFP(newDoc);
338 return ;
339 }
340
341 static void
s_loadUri(XAP_Frame * pFrame,const char * uri,gint x,gint y)342 s_loadUri (XAP_Frame * pFrame, const char * uri,gint x, gint y)
343 {
344 FV_View * pView = static_cast<FV_View*>(pFrame->getCurrentView ());
345
346 int type = s_mapMimeToUriType (uri);
347 if (type == TARGET_UNKNOWN)
348 {
349 UT_DEBUGMSG(("DOM: unknown uri type: %s\n", uri));
350 return;
351 }
352
353 if (type == TARGET_IMAGE)
354 {
355 s_loadImage (uri, pView,pFrame,x,y);
356 return;
357 }
358 else
359 {
360 if(pFrame)
361 {
362 AP_FrameData *pFrameData = static_cast<AP_FrameData *>(pFrame->getFrameData());
363 if(pFrameData && pFrameData->m_bIsWidget)
364 {
365 s_pasteFile(uri,pFrame);
366 }
367 else if(pFrame->isDirty() || pFrame->getFilename())
368 {
369 s_pasteFile(uri,pFrame);
370 }
371 else
372 {
373 s_loadDocument (uri, pFrame);
374 }
375 }
376 }
377 }
378
379 static void
s_loadUriList(XAP_Frame * pFrame,const char * uriList,gint x,gint y)380 s_loadUriList (XAP_Frame * pFrame, const char * uriList,gint x, gint y)
381 {
382 gchar ** uris = g_uri_list_extract_uris(uriList);
383 gchar ** uriIter = uris;
384
385 while (uriIter && *uriIter) {
386 s_loadUri(pFrame,*uriIter,x,y);
387 uriIter++;
388 }
389 g_strfreev(uris);
390 }
391
392 static void
s_pasteText(XAP_Frame * pFrame,const char * target_name,const unsigned char * data,UT_uint32 data_length)393 s_pasteText (XAP_Frame * pFrame, const char * target_name,
394 const unsigned char * data, UT_uint32 data_length)
395 {
396 FV_View * pView = static_cast<FV_View*>(pFrame->getCurrentView ());
397 PD_Document * pDoc = pView->getDocument ();
398
399 IEFileType file_type = IEFT_Unknown;
400
401 file_type = IE_Imp::fileTypeForMimetype (target_name);
402 if (file_type == IEFT_Unknown)
403 file_type = IE_Imp::fileTypeForContents (reinterpret_cast<const char *>(data), data_length);
404
405 if (file_type != IEFT_Unknown)
406 {
407 IE_Imp * importer = NULL;
408
409 if (UT_OK == IE_Imp::constructImporter (pDoc, file_type, &importer) && importer)
410 {
411 PD_DocumentRange dr(pDoc, pView->getPoint(), pView->getPoint());
412 importer->pasteFromBuffer(&dr, data, data_length);
413
414 delete importer;
415 }
416 }
417 }
418
419 static void
s_drag_data_get_cb(GtkWidget *,GdkDragContext *,GtkSelectionData * selection,guint,guint,gpointer)420 s_drag_data_get_cb (GtkWidget * /*widget*/,
421 GdkDragContext * /*context*/,
422 GtkSelectionData *selection,
423 guint /*_info*/,
424 guint /*_time*/,
425 gpointer /*user_data*/)
426 {
427 void * data = NULL;
428 UT_uint32 dataLen = 0;
429 const char * formatFound = NULL;
430
431 GdkAtom target = gtk_selection_data_get_target(selection);
432 char *targetName = gdk_atom_name(target);
433 char *formatList[2];
434
435 formatList[0] = targetName;
436 formatList[1] = 0;
437
438 XAP_UnixApp * pApp = static_cast<XAP_UnixApp *>(XAP_App::getApp ());
439 XAP_Frame * pFrame = pApp->getLastFocussedFrame();
440 if(!pFrame)
441 return;
442 FV_View * pView = static_cast<FV_View *>(pFrame->getCurrentView());
443 if(!pView)
444 return;
445 UT_DEBUGMSG(("UnixFrameImpl: s_drag_data_get_cb(%s)\n", targetName));
446 if(strcmp(targetName,"text/uri-list") == 0)
447 {
448 char * szName = *pApp->getTmpFile();
449 if(!szName)
450 return;
451 UT_sint32 iLen = strlen(szName);
452 UT_DEBUGMSG(("Gave name %s to Nautilus \n",szName));
453 gtk_selection_data_set (selection,
454 target,
455 8,
456 (guchar *) szName,
457 iLen);
458
459 g_free(targetName);
460 return;
461 }
462 EV_EditMouseContext emc = pView->getLastMouseContext();
463 if(emc == EV_EMC_VISUALTEXTDRAG )
464 {
465 const UT_ByteBuf * pBuf = pView->getLocalBuf();
466 UT_DEBUGMSG(("pBuf %p \n",pBuf));
467 if(pBuf)
468 {
469 UT_DEBUGMSG((" data length %p \n", pBuf->getPointer(0)));
470 }
471 gtk_selection_data_set (selection,
472 target,
473 8,
474 (guchar *) pBuf->getPointer(0),
475 pBuf->getLength());
476 }
477 if(emc == EV_EMC_IMAGE)
478 {
479 return;
480 }
481 if(emc == EV_EMC_POSOBJECT)
482 {
483 UT_DEBUGMSG(("Dragging positioned object \n"));
484 FV_FrameEdit * fvFrame = pView->getFrameEdit();
485 const UT_ByteBuf * pBuf = NULL;
486 fvFrame->getPNGImage(&pBuf);
487 if(pBuf)
488 {
489 UT_DEBUGMSG(("Got data of length %d \n",pBuf->getLength()));
490 gtk_selection_data_set (selection,
491 target,
492 8,
493 (guchar *) pBuf->getPointer(0),
494 pBuf->getLength());
495
496 }
497 return;
498 }
499 if (pApp->getCurrentSelection((const char **)formatList, &data, &dataLen, &formatFound))
500 {
501 UT_DEBUGMSG(("DOM: s_drag_data_get_cb SUCCESS!\n"));
502 gtk_selection_data_set (selection,
503 target,
504 8,
505 (guchar *)data,
506 dataLen);
507 }
508
509 g_free (targetName);
510 }
511
512 static void
s_dndDropEvent(GtkWidget * widget,GdkDragContext *,gint x,gint y,GtkSelectionData * selection_data,guint info,guint,XAP_UnixFrameImpl * pFrameImpl)513 s_dndDropEvent(GtkWidget *widget,
514 GdkDragContext * /*context*/,
515 gint x,
516 gint y,
517 GtkSelectionData *selection_data,
518 guint info,
519 guint /*time*/,
520 XAP_UnixFrameImpl * pFrameImpl)
521 {
522 UT_DEBUGMSG(("DOM: dnd_drop_event being handled\n"));
523
524 UT_return_if_fail(widget != NULL);
525
526 XAP_Frame * pFrame = pFrameImpl->getFrame ();
527 FV_View * pView = static_cast<FV_View*>(pFrame->getCurrentView ());
528
529 char *targetName = gdk_atom_name(gtk_selection_data_get_target(selection_data));
530 UT_DEBUGMSG(("JK: target in selection = %s \n", targetName));
531
532 if (info == TARGET_URI_LIST)
533 {
534 const char * rawChar = reinterpret_cast<const char *>(gtk_selection_data_get_data(selection_data));
535 UT_DEBUGMSG(("DOM: text in selection = %s \n", rawChar));
536 s_loadUriList (pFrame,rawChar,x,y);
537 }
538 else if (info == TARGET_DOCUMENT)
539 {
540 if( !strcmp( targetName, "text/x-vcard" ))
541 {
542 UT_DEBUGMSG(("MIQ: Document target is a vcard/contact\n"));
543
544 // pView->cmdCharInsert( "fred" );
545 s_pasteText (pFrame, targetName, gtk_selection_data_get_data(selection_data),
546 gtk_selection_data_get_length(selection_data));
547 }
548 else
549 {
550 UT_DEBUGMSG(("JK: Document target as data buffer\n"));
551 s_pasteText (pFrame, targetName, gtk_selection_data_get_data(selection_data),
552 gtk_selection_data_get_length(selection_data));
553 }
554 }
555 else if (info == TARGET_IMAGE)
556 {
557 UT_ByteBuf bytes(gtk_selection_data_get_length(selection_data));
558
559 UT_DEBUGMSG(("JK: Image target\n"));
560 bytes.append (gtk_selection_data_get_data(selection_data),
561 gtk_selection_data_get_length(selection_data));
562 s_loadImage (bytes, pView,pFrame,x,y);
563 }
564 else if (info == TARGET_URL)
565 {
566 const char * uri = reinterpret_cast<const char *>(gtk_selection_data_get_data(selection_data));
567 UT_DEBUGMSG(("DOM: hyperlink: %s\n", uri));
568 //
569 // Look to see if this is actually an image.
570 //
571 std::string suffix = UT_pathSuffix(uri);
572 if (!suffix.empty())
573 {
574 UT_DEBUGMSG(("Suffix of uri is %s \n",suffix.c_str()));
575 if ((suffix.substr(1,3) == "jpg") ||
576 (suffix.substr(1,4) == "jpeg") ||
577 (suffix.substr(1,3) == "png") ||
578 (suffix.substr(1,3) == "svg") ||
579 (suffix.substr(1,3) == "gif"))
580 {
581
582 UT_UTF8String sUri = uri;
583 UT_uint32 i = 0;
584 if(sUri.length())
585 {
586 for(i=0;i<sUri.length()-1;i++)
587 {
588 if((sUri.substr(i,1) == "\n") ||
589 (sUri.substr(i,1) == " ") )
590 {
591 sUri = sUri.substr(0,i);
592 break;
593 }
594 }
595 }
596 UT_DEBUGMSG(("trimmed Uri is (%s) \n",sUri.utf8_str()));
597 s_loadImage(sUri,pView,pFrame,x,y);
598 g_free (targetName);
599 return;
600 }
601 }
602 pView->cmdInsertHyperlink(uri);
603 }
604
605 g_free (targetName);
606 }
607
608 static void
s_dndRealDropEvent(GtkWidget * widget,GdkDragContext * context,gint,gint,guint time,gpointer)609 s_dndRealDropEvent (GtkWidget *widget, GdkDragContext * context,
610 gint /*x*/, gint /*y*/, guint time, gpointer /*ppFrame*/)
611 {
612 UT_DEBUGMSG(("DOM: dnd drop event\n"));
613 GdkAtom selection = gdk_drag_get_selection(context);
614
615 UT_DEBUGMSG(("RealDrag and drop event: target in selection = %s \n", gdk_atom_name(selection)));
616 gtk_drag_get_data (widget,context,selection,time);
617 }
618
619 static void
s_dndDragEnd(GtkWidget *,GdkDragContext *,gpointer)620 s_dndDragEnd (GtkWidget *, GdkDragContext *, gpointer /*ppFrame*/)
621 {
622 UT_DEBUGMSG(("DOM: dnd end event\n"));
623
624 // XAP_UnixApp * pApp = static_cast<XAP_UnixApp *>(XAP_App::getApp ());
625 }
626
627 static void
s_dndDragBegin(GtkWidget *,GdkDragContext *,gpointer)628 s_dndDragBegin (GtkWidget *, GdkDragContext *, gpointer /*ppFrame*/)
629 {
630 UT_DEBUGMSG(("DOM: dnd begin event\n"));
631 }
632
dragText()633 void XAP_UnixFrameImpl::dragText()
634 {
635 #if 0
636 UT_DEBUGMSG(("DOM: XAP_UnixFrameImpl::dragText()\n"));
637
638 // todo: this requires an extra click in the target application. find a way to make that not suck
639
640 XAP_UnixClipboard *clipboard = static_cast<XAP_UnixApp *>(XAP_App::getApp())->getClipboard();
641
642 GtkTargetList *target_list = gtk_target_list_new (clipboard->getTargets(), clipboard->getNumTargets());
643
644 GdkDragContext *context = gtk_drag_begin (m_wTopLevelWindow,
645 target_list,
646 GDK_ACTION_COPY,
647 1,
648 NULL);
649
650 gtk_target_list_unref (target_list);
651 #endif
652 }
653
XAP_UnixFrameImpl(XAP_Frame * pFrame)654 XAP_UnixFrameImpl::XAP_UnixFrameImpl(XAP_Frame *pFrame) :
655 XAP_FrameImpl(pFrame),
656 m_imContext(NULL),
657 m_wTopLevelWindow(NULL),
658 m_pUnixMenu(NULL),
659 need_im_reset (false),
660 m_bDoZoomUpdate(false),
661 m_iNewX(0),
662 m_iNewY(0),
663 m_iNewWidth(0),
664 m_iNewHeight(0),
665 m_iZoomUpdateID(0),
666 m_iAbiRepaintID(0),
667 m_pUnixPopup(NULL),
668 m_dialogFactory(XAP_App::getApp(), pFrame),
669 m_iPreeditLen (0),
670 m_iPreeditStart (0)
671 {
672 }
673
~XAP_UnixFrameImpl()674 XAP_UnixFrameImpl::~XAP_UnixFrameImpl()
675 {
676 if(m_bDoZoomUpdate) {
677 g_source_remove(m_iZoomUpdateID);
678 }
679
680 // only delete the things we created...
681 if(m_iAbiRepaintID)
682 {
683 g_source_remove(m_iAbiRepaintID);
684 }
685
686 DELETEP(m_pUnixMenu);
687 DELETEP(m_pUnixPopup);
688
689 // unref the input method context
690 g_object_unref (G_OBJECT (m_imContext));
691 }
692
693
realize(GtkWidget *,GdkEvent *,gpointer)694 void XAP_UnixFrameImpl::_fe::realize(GtkWidget *, GdkEvent * /*e*/,gpointer /*data*/)
695 {
696 }
697
unrealize(GtkWidget *,GdkEvent *,gpointer)698 void XAP_UnixFrameImpl::_fe::unrealize(GtkWidget *, GdkEvent * /*e*/,gpointer /*data*/)
699 {
700 }
701
sizeAllocate(GtkWidget *,GdkEvent *,gpointer)702 void XAP_UnixFrameImpl::_fe::sizeAllocate(GtkWidget *, GdkEvent * /*e*/,gpointer /*data*/)
703 {
704 }
705
focusIn(GtkWidget *,GdkEvent *,gpointer)706 gint XAP_UnixFrameImpl::_fe::focusIn(GtkWidget *, GdkEvent * /*e*/,gpointer /*data*/)
707 {
708 return FALSE;
709 }
710
focusOut(GtkWidget *,GdkEvent *,gpointer)711 gint XAP_UnixFrameImpl::_fe::focusOut(GtkWidget * /* w*/, GdkEvent * /*e*/,gpointer /*data*/)
712 {
713 return FALSE;
714 }
715
focusIMIn()716 void XAP_UnixFrameImpl::focusIMIn ()
717 {
718 need_im_reset = true;
719 gtk_im_context_focus_in(getIMContext());
720 gtk_im_context_reset (getIMContext());
721 }
722
focusIMOut()723 void XAP_UnixFrameImpl::focusIMOut ()
724 {
725 need_im_reset = true;
726 gtk_im_context_focus_out(getIMContext());
727 }
728
resetIMContext()729 void XAP_UnixFrameImpl::resetIMContext()
730 {
731 if (need_im_reset)
732 {
733 need_im_reset = false;
734 gtk_im_context_reset (getIMContext());
735 }
736 }
737
focus_in_event(GtkWidget * w,GdkEvent *,gpointer)738 gboolean XAP_UnixFrameImpl::_fe::focus_in_event(GtkWidget *w,GdkEvent */*event*/,gpointer /*user_data*/)
739 {
740 XAP_UnixFrameImpl * pFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
741 UT_return_val_if_fail(pFrameImpl,FALSE);
742
743 XAP_Frame* pFrame = pFrameImpl->getFrame();
744 g_object_set_data(G_OBJECT(w), "toplevelWindowFocus",
745 GINT_TO_POINTER(TRUE));
746 if (pFrame->getCurrentView())
747 {
748 pFrame->getCurrentView()->focusChange(gtk_grab_get_current() == NULL || gtk_grab_get_current() == w ? AV_FOCUS_HERE : AV_FOCUS_NEARBY);
749 }
750 pFrameImpl->focusIMIn ();
751 //
752 // Note: GTK2's focus handler will send a superfluous expose event
753 // which could cause the screen to be completely redrawn and flicker.
754 // This function used to return TRUE to work around this, but that
755 // causes gail not to see the focus event, either, which is not what
756 // we want. So we depend on code elsewhere to disable the class
757 // focus handler.
758 //
759 return FALSE;
760 }
761
focus_out_event(GtkWidget * w,GdkEvent *,gpointer)762 gboolean XAP_UnixFrameImpl::_fe::focus_out_event(GtkWidget *w,GdkEvent */*event*/,gpointer /*user_data*/)
763 {
764 XAP_UnixFrameImpl * pFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
765 UT_return_val_if_fail(pFrameImpl,FALSE);
766
767 XAP_Frame* pFrame = pFrameImpl->getFrame();
768 g_object_set_data(G_OBJECT(w), "toplevelWindowFocus",
769 GINT_TO_POINTER(FALSE));
770 if (pFrame->getCurrentView())
771 pFrame->getCurrentView()->focusChange(AV_FOCUS_NONE);
772 pFrameImpl->focusIMOut();
773 //
774 // Note: GTK2's focus handler will send a superfluous expose event
775 // which could cause the screen to be completely redrawn and flicker.
776 // This function used to return TRUE to work around this, but that
777 // causes gail not to see the focus event, either, which is not what
778 // we want. So we depend on code elsewhere to disable the class
779 // focus handler.
780 //
781 return FALSE;
782 }
783
button_press_event(GtkWidget * w,GdkEventButton * e)784 gint XAP_UnixFrameImpl::_fe::button_press_event(GtkWidget * w, GdkEventButton * e)
785 {
786 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
787 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
788 pUnixFrameImpl->setTimeOfLastEvent(e->time);
789 AV_View * pView = pFrame->getCurrentView();
790 EV_UnixMouse * pUnixMouse = static_cast<EV_UnixMouse *>(pFrame->getMouse());
791
792 gtk_grab_add(w);
793
794 pUnixFrameImpl->resetIMContext ();
795
796 #if defined(EMBEDDED_TARGET) && EMBEDDED_TARGET == EMBEDDED_TARGET_HILDON
797 /* UGLY HACK -- for some reason in the OS2006 release of maemo the VKB
798 * does not pop up automatically as it used to and we have to bring it up
799 * ourselves; since this function is static we cannot make it virtual, and
800 * adding an additional handler for the button_press_event does not work
801 * for some reason (even after changing the return value from there to 0)
802 */
803 if (e->button == 1)
804 {
805 UT_DEBUGMSG(("Hildon button_press_event: pFrameImpl 0x%p\n",
806 pUnixFrameImpl));
807
808 hildon_gtk_im_context_show(pUnixFrameImpl->getIMContext());
809 }
810 #endif
811
812 if (pView)
813 pUnixMouse->mouseClick(pView,e);
814 return 1;
815 }
816
button_release_event(GtkWidget * w,GdkEventButton * e)817 gint XAP_UnixFrameImpl::_fe::button_release_event(GtkWidget * w, GdkEventButton * e)
818 {
819 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
820 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
821 pUnixFrameImpl->setTimeOfLastEvent(e->time);
822 AV_View * pView = pFrame->getCurrentView();
823
824 EV_UnixMouse * pUnixMouse = static_cast<EV_UnixMouse *>(pFrame->getMouse());
825
826 gtk_grab_remove(w);
827
828 if (pView)
829 pUnixMouse->mouseUp(pView,e);
830
831 return 1;
832 }
833
834 /*!
835 * Background zoom updater. It updates the view zoom level after all configure
836 * events have been processed. This is
837 */
do_ZoomUpdate(gpointer p)838 gint XAP_UnixFrameImpl::_fe::do_ZoomUpdate(gpointer /* XAP_UnixFrameImpl * */ p)
839 {
840 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(p);
841 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
842 FV_View * pView = static_cast<FV_View *>(pFrame->getCurrentView());
843 UT_sint32 prevWidth = 0;
844 UT_sint32 prevHeight = 0;
845 UT_sint32 iNewWidth = 0;
846 UT_sint32 iNewHeight = 0;
847 if(pView)
848 {
849 prevWidth = pView->getGraphics()->tdu(pView->getWindowWidth());
850 prevHeight = pView->getGraphics()->tdu(pView->getWindowHeight());
851 iNewWidth = pUnixFrameImpl->m_iNewWidth;
852 iNewHeight = pUnixFrameImpl->m_iNewHeight;
853 xxx_UT_DEBUGMSG(("OldWidth %d NewWidth %d \n",prevWidth,iNewWidth));
854 }
855 if(!pView || pFrame->isFrameLocked() ||
856 ((pUnixFrameImpl->m_bDoZoomUpdate) && (prevWidth == iNewWidth) && (prevHeight == iNewHeight)))
857 {
858 pUnixFrameImpl->m_iZoomUpdateID = 0;
859 pUnixFrameImpl->m_bDoZoomUpdate = false;
860 if(pView && !pFrame->isFrameLocked())
861 {
862 GR_Graphics * pGr = pView->getGraphics ();
863 UT_Rect rClip;
864 rClip.left = pGr->tlu(0);
865 UT_sint32 iHeight = abs(iNewHeight - prevHeight);
866 rClip.top = pGr->tlu(iNewHeight - iHeight);
867 rClip.width = pGr->tlu(iNewWidth)+1;
868 rClip.height = pGr->tlu(iHeight)+1;
869 xxx_UT_DEBUGMSG(("Drawing in zoom at x %d y %d height %d width %d \n",rClip.left,rClip.top,rClip.height,rClip.width));
870 pView->setWindowSize(iNewWidth, iNewHeight);
871 if(!pView->isConfigureChanged())
872 {
873 pView->draw(&rClip);
874 }
875 else
876 {
877 pView->draw();
878 pView->setConfigure(false);
879 }
880 }
881 if(pView)
882 {
883 pView->setWindowSize(iNewWidth, iNewHeight);
884 }
885 //
886 // Come back later when we have a view
887 //
888 if(!pView)
889 return TRUE;
890 return FALSE;
891 }
892 if(!pView || pFrame->isFrameLocked() ||
893 ((prevWidth == iNewWidth) && (pFrame->getZoomType() != XAP_Frame::z_WHOLEPAGE)))
894 {
895 xxx_UT_DEBUGMSG(("Abandoning zoom widths are equal \n"));
896 pUnixFrameImpl->m_iZoomUpdateID = 0;
897 pUnixFrameImpl->m_bDoZoomUpdate = false;
898 if(pView && !pFrame->isFrameLocked())
899 {
900 GR_Graphics * pGr = pView->getGraphics ();
901 UT_Rect rClip;
902 rClip.left = pGr->tlu(0);
903 UT_sint32 iHeight = abs(iNewHeight - prevHeight);
904 rClip.top = pGr->tlu(iNewHeight - iHeight);
905 rClip.width = pGr->tlu(iNewWidth)+1;
906 rClip.height = pGr->tlu(iHeight)+1;
907 xxx_UT_DEBUGMSG(("Drawing in zoom at x %d y %d height %d width %d \n",rClip.left,rClip.top,rClip.height,rClip.width));
908 pView->setWindowSize(iNewWidth, iNewHeight);
909 if(!pView->isConfigureChanged())
910 {
911 pView->draw(&rClip);
912 }
913 else
914 {
915 pView->draw();
916 pView->setConfigure(false);
917 }
918 }
919 if(pView)
920 pView->setWindowSize(iNewWidth, iNewHeight);
921 //
922 // Come back later when we have a view
923 //
924 if(!pView)
925 return TRUE;
926 return FALSE;
927 }
928
929 pUnixFrameImpl->m_bDoZoomUpdate = true;
930 UT_sint32 iLoop = 0;
931 do
932 {
933 // currently, we blow away the old view. This will change, rendering
934 // the loop superfluous.
935 pView = static_cast<FV_View *>(pFrame->getCurrentView());
936
937 if(!pView)
938 {
939 pUnixFrameImpl->m_iZoomUpdateID = 0;
940 pUnixFrameImpl->m_bDoZoomUpdate = false;
941 return FALSE;
942 }
943
944 // oops, we're not ready yet.
945 if (pView->isLayoutFilling())
946 return FALSE;
947
948 iNewWidth = pUnixFrameImpl->m_iNewWidth;
949 iNewHeight = pUnixFrameImpl->m_iNewHeight;
950 //
951 // In web mode we reflow the text to changed page set at the
952 // current zoom.
953 //
954 if((pView->getViewMode() == VIEW_WEB) && (abs(iNewWidth -prevWidth) > 2) && (prevWidth > 10) && (iNewWidth > 10))
955 {
956 pView->setWindowSize(iNewWidth, iNewHeight);
957 UT_sint32 iAdjustZoom = pView->calculateZoomPercentForPageWidth();
958 FL_DocLayout * pLayout = pView->getLayout();
959 PD_Document * pDoc = pLayout->getDocument();
960 UT_Dimension orig_ut = DIM_IN;
961 orig_ut = pLayout->m_docViewPageSize.getDims();
962 double orig_width = pDoc->m_docPageSize.Width(orig_ut);
963 double orig_height = pDoc->m_docPageSize.Height(orig_ut);
964 double rat = static_cast<double>(iAdjustZoom)/static_cast<double>(pView->getGraphics()->getZoomPercentage()) ;
965 double new_width = orig_width*rat;
966 UT_DEBUGMSG(("VIEW_WEB old width %f new width %f old height %f \n",orig_width,new_width,orig_height));
967 bool isPortrait = pLayout->m_docViewPageSize.isPortrait();
968 pLayout->m_docViewPageSize.Set(new_width,orig_height,orig_ut);
969 pLayout->m_docViewPageSize.Set(fp_PageSize::psCustom,orig_ut);
970 if(isPortrait)
971 {
972 pLayout->m_docViewPageSize.setPortrait();
973 }
974 else
975 {
976 pLayout->m_docViewPageSize.setLandscape();
977 }
978 pView->rebuildLayout();
979 pView->updateScreen(false);
980 //
981 // We're done. No more calls needed
982 //
983 return TRUE;
984 }
985 //
986 // If we are here in view_web we just return
987 //
988 pView->setWindowSize(iNewWidth, iNewHeight);
989 if(pView->getViewMode() == VIEW_WEB)
990 {
991 return TRUE;
992 }
993 pFrame->quickZoom(); // was update zoom
994 iLoop++;
995 }
996 while(((iNewWidth != pUnixFrameImpl->m_iNewWidth) || (iNewHeight != pUnixFrameImpl->m_iNewHeight))
997 && (iLoop < 10));
998
999 pUnixFrameImpl->m_iZoomUpdateID = 0;
1000 pUnixFrameImpl->m_bDoZoomUpdate = false;
1001 return FALSE;
1002 }
1003
configure_event(GtkWidget * w,GdkEventConfigure * e)1004 gint XAP_UnixFrameImpl::_fe::configure_event(GtkWidget* w, GdkEventConfigure *e)
1005 {
1006 // This is basically a resize event.
1007
1008 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1009 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
1010 AV_View * pView = pFrame->getCurrentView();
1011 if (pView)
1012 {
1013 if (pUnixFrameImpl->m_iNewWidth == e->width &&
1014 pUnixFrameImpl->m_iNewHeight == e->height &&
1015 pUnixFrameImpl->m_iNewY == e->y &&
1016 pUnixFrameImpl->m_iNewX == e->x)
1017 return 1;
1018 pUnixFrameImpl->m_iNewWidth = e->width;
1019 pUnixFrameImpl->m_iNewHeight = e->height;
1020 pUnixFrameImpl->m_iNewY = e->y;
1021 pUnixFrameImpl->m_iNewX = e->x;
1022 xxx_UT_DEBUGMSG(("Drawing in zoom at x %d y %d height %d width %d \n",e->x,e->y,e->height,e->width));
1023 XAP_App * pApp = XAP_App::getApp();
1024 UT_sint32 x,y;
1025 UT_uint32 width,height,flags;
1026 pApp->getGeometry(&x,&y,&width,&height,&flags);
1027 //
1028 // Who ever wants to change this code in the future. The height and widths you
1029 // get from the event struct are the height and widths of the drawable area of
1030 // the screen. We want the height and width of the entire widget which we get
1031 // from the m_wTopLevelWindow widget.
1032 // -- MES
1033 //
1034
1035 #if defined(EMBEDDED_TARGET) && EMBEDDED_TARGET == EMBEDDED_TARGET_HILDON
1036 #else
1037 GtkWindow * pWin = NULL;
1038 if(pFrame->getFrameMode() == XAP_NormalFrame) {
1039 pWin = GTK_WINDOW(pUnixFrameImpl->m_wTopLevelWindow);
1040 // worth remembering size?
1041 GdkWindowState state = gdk_window_get_state (gtk_widget_get_window(GTK_WIDGET(pWin)));
1042 if (!(state & GDK_WINDOW_STATE_ICONIFIED ||
1043 state & GDK_WINDOW_STATE_MAXIMIZED ||
1044 state & GDK_WINDOW_STATE_FULLSCREEN)) {
1045
1046 gint gwidth,gheight;
1047 gtk_window_get_size(pWin,&gwidth,&gheight);
1048 pApp->setGeometry(e->x,e->y,gwidth,gheight,flags);
1049 }
1050 }
1051 #endif
1052
1053 // Dynamic Zoom Implementation
1054
1055 if(!pUnixFrameImpl->m_bDoZoomUpdate && (pUnixFrameImpl->m_iZoomUpdateID == 0))
1056 {
1057 pUnixFrameImpl->m_iZoomUpdateID = g_idle_add(reinterpret_cast<GSourceFunc>(do_ZoomUpdate), static_cast<gpointer>(pUnixFrameImpl));
1058 }
1059
1060 }
1061 gtk_widget_grab_focus(w);
1062 return 1;
1063 }
1064
motion_notify_event(GtkWidget * w,GdkEventMotion * e)1065 gint XAP_UnixFrameImpl::_fe::motion_notify_event(GtkWidget* w, GdkEventMotion* e)
1066 {
1067 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1068 if(e->type == GDK_MOTION_NOTIFY)
1069 {
1070 //
1071 // swallow queued drag events and just get the last one.
1072 //
1073 GdkEvent * eNext = gdk_event_peek();
1074 if(eNext && eNext->type == GDK_MOTION_NOTIFY)
1075 {
1076 g_object_unref(G_OBJECT(e));
1077 e = reinterpret_cast<GdkEventMotion *>(eNext);
1078 while(eNext && eNext->type == GDK_MOTION_NOTIFY)
1079 {
1080 xxx_UT_DEBUGMSG(("Swallowing drag event \n"));
1081 gdk_event_free(eNext);
1082 eNext = gdk_event_get();
1083 gdk_event_free(reinterpret_cast<GdkEvent *>(e));
1084 e = reinterpret_cast<GdkEventMotion *>(eNext);
1085 eNext = gdk_event_peek();
1086 }
1087 if(eNext != NULL)
1088 {
1089 gdk_event_free(eNext);
1090 }
1091 }
1092 }
1093
1094 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
1095 pUnixFrameImpl->setTimeOfLastEvent(e->time);
1096 AV_View * pView = pFrame->getCurrentView();
1097 EV_UnixMouse * pUnixMouse = static_cast<EV_UnixMouse *>(pFrame->getMouse());
1098
1099 if (pView)
1100 pUnixMouse->mouseMotion(pView, e);
1101
1102 return 1;
1103 }
1104
scroll_notify_event(GtkWidget * w,GdkEventScroll * e)1105 gint XAP_UnixFrameImpl::_fe::scroll_notify_event(GtkWidget* w, GdkEventScroll* e)
1106 {
1107 xxx_UT_DEBUGMSG(("Scroll event \n"));
1108 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1109 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
1110 pUnixFrameImpl->setTimeOfLastEvent(e->time);
1111 AV_View * pView = pFrame->getCurrentView();
1112 EV_UnixMouse * pUnixMouse = static_cast<EV_UnixMouse *>(pFrame->getMouse());
1113
1114 if (pView)
1115 pUnixMouse->mouseScroll(pView, e);
1116
1117 return 1;
1118 }
1119
key_release_event(GtkWidget * w,GdkEventKey * e)1120 gint XAP_UnixFrameImpl::_fe::key_release_event(GtkWidget* w, GdkEventKey* e)
1121 {
1122 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1123
1124 // Let IM handle the event first.
1125 if (gtk_im_context_filter_keypress(pUnixFrameImpl->getIMContext(), e)) {
1126 UT_DEBUGMSG(("IMCONTEXT keyevent swallow: %u\n", e->keyval));
1127 pUnixFrameImpl->queueIMReset ();
1128 return 0;
1129 }
1130 return TRUE;
1131 }
1132
key_press_event(GtkWidget * w,GdkEventKey * e)1133 gint XAP_UnixFrameImpl::_fe::key_press_event(GtkWidget* w, GdkEventKey* e)
1134 {
1135 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1136
1137 // Let IM handle the event first.
1138 if (gtk_im_context_filter_keypress(pUnixFrameImpl->getIMContext(), e)) {
1139 pUnixFrameImpl->queueIMReset ();
1140
1141 if ((e->state & GDK_MOD1_MASK) ||
1142 (e->state & GDK_MOD3_MASK) ||
1143 (e->state & GDK_MOD4_MASK))
1144 return 0;
1145
1146 // ... else, stop this signal
1147 g_signal_stop_emission (G_OBJECT(w),
1148 g_signal_lookup ("key_press_event",
1149 G_OBJECT_TYPE (w)), 0);
1150 return 1;
1151 }
1152
1153 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
1154 pUnixFrameImpl->setTimeOfLastEvent(e->time);
1155 AV_View * pView = pFrame->getCurrentView();
1156 ev_UnixKeyboard * pUnixKeyboard = static_cast<ev_UnixKeyboard *>(pFrame->getKeyboard());
1157
1158 if (pView)
1159 pUnixKeyboard->keyPressEvent(pView, e);
1160
1161 // stop emission for keys that would take the focus away from the document widget
1162 switch (e->keyval) {
1163 case GDK_KEY_Tab:
1164 case GDK_KEY_ISO_Left_Tab:
1165 case GDK_KEY_Left:
1166 case GDK_KEY_Up:
1167 case GDK_KEY_Right:
1168 case GDK_KEY_Down:
1169 return TRUE;
1170 break;
1171 }
1172
1173 return FALSE;
1174 }
1175
delete_event(GtkWidget * w,GdkEvent *,gpointer)1176 gint XAP_UnixFrameImpl::_fe::delete_event(GtkWidget * w, GdkEvent * /*event*/, gpointer /*data*/)
1177 {
1178 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1179 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
1180 XAP_App * pApp = XAP_App::getApp();
1181 UT_return_val_if_fail(pApp,FALSE);
1182 if(pApp->isBonoboRunning())
1183 return FALSE;
1184
1185 UT_ASSERT(pApp->getMenuActionSet());
1186
1187 const EV_EditMethodContainer * pEMC = pApp->getEditMethodContainer();
1188 UT_return_val_if_fail(pEMC,FALSE);
1189
1190 // was "closeWindow", TRUE, FALSE
1191 const EV_EditMethod * pEM = pEMC->findEditMethodByName("closeWindowX");
1192 UT_ASSERT_HARMLESS(pEM);
1193
1194 if (pEM)
1195 {
1196 if (pEM->Fn(pFrame->getCurrentView(),NULL))
1197 {
1198 // returning FALSE means destroy the window, continue along the
1199 // chain of Gtk destroy events
1200
1201 return FALSE;
1202 }
1203 }
1204
1205 // returning TRUE means do NOT destroy the window; halt the message
1206 // chain so it doesn't see destroy
1207 return TRUE;
1208 }
1209
1210 #if GTK_CHECK_VERSION(3,0,0)
draw(GtkWidget * w,cairo_t * cr)1211 gboolean XAP_UnixFrameImpl::_fe::draw(GtkWidget * w, cairo_t * cr)
1212 #else
1213 gboolean XAP_UnixFrameImpl::_fe::expose(GtkWidget * w, GdkEventExpose* pExposeEvent)
1214 #endif
1215 {
1216 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1217 FV_View * pView = static_cast<FV_View *>(pUnixFrameImpl->getFrame()->getCurrentView());
1218 double x, y, width, height;
1219 #if GTK_CHECK_VERSION(3,0,0)
1220 cairo_clip_extents (cr, &x, &y, &width, &height);
1221 width -= x;
1222 height -= y;
1223 #else
1224 x = pExposeEvent->area.x;
1225 y = pExposeEvent->area.y;
1226 width = pExposeEvent->area.width;
1227 height = pExposeEvent->area.height;
1228 #endif
1229 /* Jean: commenting out next lines since the zoom update code does draw only
1230 * part of what needs to be updated. */
1231 // if((pUnixFrameImpl->m_bDoZoomUpdate) || (pUnixFrameImpl->m_iZoomUpdateID != 0))
1232 // {
1233 // return TRUE;
1234 // }
1235 if(pView)
1236 {
1237 GR_Graphics * pGr = pView->getGraphics ();
1238 UT_Rect rClip;
1239 if (pGr->getPaintCount () > 0)
1240 return TRUE;
1241 xxx_UT_DEBUGMSG(("Expose area: x %d y %d width %d height %d \n",pExposeEvent->area.x,pExposeEvent->area.y,pExposeEvent->area.width,pExposeEvent->area.height));
1242 rClip.left = pGr->tlu(x);
1243 rClip.top = pGr->tlu(y);
1244 #if GTK_CHECK_VERSION(3,0,0)
1245 rClip.width = pGr->tlu(width);
1246 rClip.height = pGr->tlu(height);
1247 static_cast<GR_CairoGraphics *>(pGr)->setCairo(cr);
1248 pView->draw(&rClip);
1249 static_cast<GR_CairoGraphics *>(pGr)->setCairo(NULL);
1250 #else
1251 rClip.width = pGr->tlu(width)+1;
1252 rClip.height = pGr->tlu(height)+1;
1253 pView->draw(&rClip);
1254 #endif
1255 }
1256 return TRUE;
1257 }
1258
1259 static bool bScrollWait = false;
1260
1261 class _ViewScroll
1262 {
1263 public:
_ViewScroll(AV_View * pView,UT_sint32 amount)1264 _ViewScroll(AV_View * pView, UT_sint32 amount):
1265 m_pView(pView),m_amount(amount)
1266 {
1267 }
1268 AV_View * m_pView;
1269 UT_sint32 m_amount;
1270 };
1271
_actualScroll(gpointer data)1272 static gboolean _actualScroll(gpointer data)
1273 {
1274 _ViewScroll * pVS = reinterpret_cast<_ViewScroll *>(data);
1275 AV_View * pView = pVS->m_pView;
1276 xxx_UT_DEBUGMSG(("vScrollSchanged callback\n"));
1277 if (pView)
1278 pView->sendVerticalScrollEvent(pVS->m_amount);
1279 bScrollWait = false;
1280 delete pVS;
1281 return FALSE;
1282 }
1283
vScrollChanged(GtkAdjustment * w,gpointer)1284 void XAP_UnixFrameImpl::_fe::vScrollChanged(GtkAdjustment * w, gpointer /*data*/)
1285 {
1286 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1287 if(bScrollWait)
1288 {
1289 xxx_UT_DEBUGMSG(("VScroll dropped!!! \n"));
1290 return;
1291 }
1292 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
1293 AV_View * pView = pFrame->getCurrentView();
1294 _ViewScroll * pVS = new _ViewScroll(pView,static_cast<UT_sint32>(gtk_adjustment_get_value(w)));
1295 bScrollWait = true;
1296 g_idle_add(_actualScroll, (gpointer) pVS);
1297 }
1298
hScrollChanged(GtkAdjustment * w,gpointer)1299 void XAP_UnixFrameImpl::_fe::hScrollChanged(GtkAdjustment * w, gpointer /*data*/)
1300 {
1301 XAP_UnixFrameImpl * pUnixFrameImpl = static_cast<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
1302 XAP_Frame* pFrame = pUnixFrameImpl->getFrame();
1303 AV_View * pView = pFrame->getCurrentView();
1304
1305 if (pView)
1306 pView->sendHorizontalScrollEvent(static_cast<UT_sint32>(gtk_adjustment_get_value(w)));
1307 }
1308
destroy(GtkWidget *,gpointer)1309 void XAP_UnixFrameImpl::_fe::destroy(GtkWidget * /*widget*/, gpointer /*data*/)
1310 {
1311 }
1312
1313 /*****************************************************************/
1314
_nullUpdate() const1315 void XAP_UnixFrameImpl::_nullUpdate() const
1316 {
1317 for (UT_uint32 i = 0; (i < 5) && gtk_events_pending(); i++)
1318 gtk_main_iteration ();
1319 }
1320
_initialize()1321 void XAP_UnixFrameImpl::_initialize()
1322 {
1323 UT_DEBUGMSG (("XAP_UnixFrameImpl::_initialize()\n"));
1324
1325 // get a handle to our keyboard binding mechanism
1326 // and to our mouse binding mechanism.
1327 EV_EditEventMapper * pEEM = XAP_App::getApp()->getEditEventMapper();
1328 UT_ASSERT(pEEM);
1329
1330 m_pKeyboard = new ev_UnixKeyboard(pEEM);
1331 UT_ASSERT(m_pKeyboard);
1332
1333 m_pMouse = new EV_UnixMouse(pEEM);
1334 UT_ASSERT(m_pMouse);
1335 }
1336
_setCursor(GR_Graphics::Cursor c)1337 void XAP_UnixFrameImpl::_setCursor(GR_Graphics::Cursor c)
1338 {
1339 // if (m_cursor == c)
1340 // return;
1341 // m_cursor = c;
1342 FV_View * pView = static_cast<FV_View *>(getFrame()->getCurrentView());
1343 if(pView)
1344 {
1345 GR_Graphics * pG = pView->getGraphics();
1346 if(pG && pG->queryProperties( GR_Graphics::DGP_PAPER))
1347 return;
1348 }
1349 if(getTopLevelWindow() == NULL || (m_iFrameMode != XAP_NormalFrame))
1350 return;
1351
1352 GdkCursorType cursor_number;
1353
1354 switch (c)
1355 {
1356 default:
1357 UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
1358 /*FALLTHRU*/
1359 case GR_Graphics::GR_CURSOR_DEFAULT:
1360 cursor_number = GDK_LEFT_PTR;
1361 break;
1362
1363 case GR_Graphics::GR_CURSOR_IBEAM:
1364 cursor_number = GDK_XTERM;
1365 break;
1366
1367 //I have changed the shape of the arrow so get a consistent
1368 //behaviour in the bidi build; I think the new arrow is better
1369 //for the purpose anyway
1370
1371 case GR_Graphics::GR_CURSOR_RIGHTARROW:
1372 cursor_number = GDK_SB_RIGHT_ARROW; //GDK_ARROW;
1373 break;
1374
1375 case GR_Graphics::GR_CURSOR_LEFTARROW:
1376 cursor_number = GDK_SB_LEFT_ARROW; //GDK_LEFT_PTR;
1377 break;
1378
1379 case GR_Graphics::GR_CURSOR_IMAGE:
1380 cursor_number = GDK_FLEUR;
1381 break;
1382
1383 case GR_Graphics::GR_CURSOR_IMAGESIZE_NW:
1384 cursor_number = GDK_TOP_LEFT_CORNER;
1385 break;
1386
1387 case GR_Graphics::GR_CURSOR_IMAGESIZE_N:
1388 cursor_number = GDK_TOP_SIDE;
1389 break;
1390
1391 case GR_Graphics::GR_CURSOR_IMAGESIZE_NE:
1392 cursor_number = GDK_TOP_RIGHT_CORNER;
1393 break;
1394
1395 case GR_Graphics::GR_CURSOR_IMAGESIZE_E:
1396 cursor_number = GDK_RIGHT_SIDE;
1397 break;
1398
1399 case GR_Graphics::GR_CURSOR_IMAGESIZE_SE:
1400 cursor_number = GDK_BOTTOM_RIGHT_CORNER;
1401 break;
1402
1403 case GR_Graphics::GR_CURSOR_IMAGESIZE_S:
1404 cursor_number = GDK_BOTTOM_SIDE;
1405 break;
1406
1407 case GR_Graphics::GR_CURSOR_IMAGESIZE_SW:
1408 cursor_number = GDK_BOTTOM_LEFT_CORNER;
1409 break;
1410
1411 case GR_Graphics::GR_CURSOR_IMAGESIZE_W:
1412 cursor_number = GDK_LEFT_SIDE;
1413 break;
1414
1415 case GR_Graphics::GR_CURSOR_LEFTRIGHT:
1416 cursor_number = GDK_SB_H_DOUBLE_ARROW;
1417 break;
1418
1419 case GR_Graphics::GR_CURSOR_UPDOWN:
1420 cursor_number = GDK_SB_V_DOUBLE_ARROW;
1421 break;
1422
1423 case GR_Graphics::GR_CURSOR_EXCHANGE:
1424 cursor_number = GDK_EXCHANGE;
1425 break;
1426
1427 case GR_Graphics::GR_CURSOR_GRAB:
1428 cursor_number = GDK_HAND1;
1429 break;
1430
1431 case GR_Graphics::GR_CURSOR_LINK:
1432 cursor_number = GDK_HAND2;
1433 break;
1434
1435 case GR_Graphics::GR_CURSOR_WAIT:
1436 cursor_number = GDK_WATCH;
1437 break;
1438
1439 case GR_Graphics::GR_CURSOR_HLINE_DRAG:
1440 cursor_number = GDK_SB_V_DOUBLE_ARROW;
1441 break;
1442
1443 case GR_Graphics::GR_CURSOR_VLINE_DRAG:
1444 cursor_number = GDK_SB_H_DOUBLE_ARROW;
1445 break;
1446
1447 case GR_Graphics::GR_CURSOR_CROSSHAIR:
1448 cursor_number = GDK_CROSSHAIR;
1449 break;
1450
1451 case GR_Graphics::GR_CURSOR_DOWNARROW:
1452 cursor_number = GDK_SB_DOWN_ARROW;
1453 break;
1454
1455 case GR_Graphics::GR_CURSOR_DRAGTEXT:
1456 cursor_number = GDK_TARGET;
1457 break;
1458
1459 case GR_Graphics::GR_CURSOR_COPYTEXT:
1460 cursor_number = GDK_DRAPED_BOX;
1461 break;
1462 }
1463 xxx_UT_DEBUGMSG(("Set cursor number in Frame %d to %d \n",c,cursor_number));
1464 GdkCursor * cursor = gdk_cursor_new(cursor_number);
1465 gdk_window_set_cursor(gtk_widget_get_window(getTopLevelWindow()), cursor);
1466 gdk_window_set_cursor(gtk_widget_get_window(getVBoxWidget()), cursor);
1467
1468 gdk_window_set_cursor(gtk_widget_get_window(m_wSunkenBox), cursor);
1469
1470 if (m_wStatusBar)
1471 gdk_window_set_cursor(gtk_widget_get_window(m_wStatusBar), cursor);
1472
1473 #if GTK_CHECK_VERSION(3,0,0)
1474 g_object_unref(cursor);
1475 #else
1476 gdk_cursor_unref(cursor);
1477 #endif
1478 }
1479
_setInputMode(const char * szName)1480 UT_sint32 XAP_UnixFrameImpl::_setInputMode(const char * szName)
1481 {
1482 UT_sint32 result = XAP_App::getApp()->setInputMode(szName);
1483 if (result == 1)
1484 {
1485 // if it actually changed we need to update keyboard and mouse
1486
1487 EV_EditEventMapper * pEEM = XAP_App::getApp()->getEditEventMapper();
1488 UT_ASSERT(pEEM);
1489
1490 m_pKeyboard->setEditEventMap(pEEM);
1491 m_pMouse->setEditEventMap(pEEM);
1492 }
1493
1494 return result;
1495 }
1496
getTopLevelWindow(void) const1497 GtkWidget * XAP_UnixFrameImpl::getTopLevelWindow(void) const
1498 {
1499 return m_wTopLevelWindow;
1500 }
1501
getVBoxWidget(void) const1502 GtkWidget * XAP_UnixFrameImpl::getVBoxWidget(void) const
1503 {
1504 return m_wVBox;
1505 }
1506
_getDialogFactory(void)1507 XAP_DialogFactory * XAP_UnixFrameImpl::_getDialogFactory(void)
1508 {
1509 return &m_dialogFactory;
1510 }
1511
_createInternalWindow(void)1512 GtkWidget * XAP_UnixFrameImpl::_createInternalWindow (void)
1513 {
1514 return gtk_window_new(GTK_WINDOW_TOPLEVEL);
1515 }
1516
1517 // TODO: split me up into smaller pieces/subfunctions
_createTopLevelWindow(void)1518 void XAP_UnixFrameImpl::_createTopLevelWindow(void)
1519 {
1520 // create a top-level window for us.
1521
1522 if(m_iFrameMode == XAP_NormalFrame)
1523 {
1524 m_wTopLevelWindow = _createInternalWindow ();
1525 gtk_window_set_title(GTK_WINDOW(m_wTopLevelWindow),
1526 XAP_App::getApp()->getApplicationTitleForTitleBar());
1527 gtk_window_set_resizable(GTK_WINDOW(m_wTopLevelWindow), TRUE);
1528 gtk_window_set_role(GTK_WINDOW(m_wTopLevelWindow), "topLevelWindow");
1529
1530 gtk_window_set_resizable(GTK_WINDOW(m_wTopLevelWindow), TRUE);
1531 gtk_window_set_role(GTK_WINDOW(m_wTopLevelWindow), "topLevelWindow");
1532
1533 g_object_set_data(G_OBJECT(m_wTopLevelWindow), "ic_attr", NULL);
1534 g_object_set_data(G_OBJECT(m_wTopLevelWindow), "ic", NULL);
1535
1536 }
1537 g_object_set_data(G_OBJECT(m_wTopLevelWindow), "toplevelWindow",
1538 m_wTopLevelWindow);
1539 g_object_set_data(G_OBJECT(m_wTopLevelWindow), "toplevelWindowFocus",
1540 GINT_TO_POINTER(FALSE));
1541 g_object_set_data(G_OBJECT(m_wTopLevelWindow), "user_data", this);
1542
1543 _setGeometry ();
1544
1545 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "realize",
1546 G_CALLBACK(_fe::realize), NULL);
1547 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "unrealize",
1548 G_CALLBACK(_fe::unrealize), NULL);
1549 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "size_allocate",
1550 G_CALLBACK(_fe::sizeAllocate), NULL);
1551
1552 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "focus_in_event",
1553 G_CALLBACK(_fe::focusIn), NULL);
1554 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "focus_out_event",
1555 G_CALLBACK(_fe::focusOut), NULL);
1556
1557 DragInfo * dragInfo = s_getDragInfo();
1558
1559 gtk_drag_dest_set (m_wTopLevelWindow,
1560 GTK_DEST_DEFAULT_ALL,
1561 dragInfo->entries,
1562 dragInfo->count,
1563 GDK_ACTION_COPY);
1564
1565 gtk_drag_dest_add_text_targets (m_wTopLevelWindow);
1566
1567 g_signal_connect (G_OBJECT (m_wTopLevelWindow),
1568 "drag_data_received",
1569 G_CALLBACK (s_dndDropEvent),
1570 static_cast<gpointer>(this));
1571 g_signal_connect (G_OBJECT (m_wTopLevelWindow),
1572 "drag_drop",
1573 G_CALLBACK (s_dndRealDropEvent),
1574 static_cast<gpointer>(this));
1575
1576 g_signal_connect (G_OBJECT (m_wTopLevelWindow),
1577 "drag_end",
1578 G_CALLBACK (s_dndDragEnd),
1579 static_cast<gpointer>(this));
1580
1581 g_signal_connect (G_OBJECT (m_wTopLevelWindow),
1582 "drag_begin",
1583 G_CALLBACK (s_dndDragBegin),
1584 static_cast<gpointer>(this));
1585 g_signal_connect (G_OBJECT (m_wTopLevelWindow), "drag_data_get",
1586 G_CALLBACK (s_drag_data_get_cb), this);
1587
1588 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "delete_event",
1589 G_CALLBACK(_fe::delete_event), NULL);
1590 // here we connect the "destroy" event to a signal handler.
1591 // This event occurs when we call gtk_widget_destroy() on the window,
1592 // or if we return 'FALSE' in the "delete_event" callback.
1593 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "destroy",
1594 G_CALLBACK(_fe::destroy), NULL);
1595
1596 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "focus_in_event",
1597 G_CALLBACK(_fe::focus_in_event), NULL);
1598 g_signal_connect(G_OBJECT(m_wTopLevelWindow), "focus_out_event",
1599 G_CALLBACK(_fe::focus_out_event), NULL);
1600
1601 // create a VBox inside it.
1602
1603 m_wVBox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
1604 g_object_set_data(G_OBJECT(m_wTopLevelWindow), "vbox", m_wVBox);
1605 g_object_set_data(G_OBJECT(m_wVBox),"user_data", this);
1606 gtk_container_add(GTK_CONTAINER(m_wTopLevelWindow), m_wVBox);
1607
1608 if (m_iFrameMode != XAP_NoMenusWindowLess) {
1609 // synthesize a menu from the info in our base class.
1610 m_pUnixMenu = new EV_UnixMenuBar(static_cast<XAP_UnixApp*>(XAP_App::getApp()), getFrame(), m_szMenuLayoutName,
1611 m_szMenuLabelSetName);
1612 UT_return_if_fail(m_pUnixMenu);
1613 UT_DebugOnly<bool> bResult;
1614 bResult = m_pUnixMenu->synthesizeMenuBar();
1615 UT_ASSERT(bResult);
1616 }
1617
1618 // create a toolbar instance for each toolbar listed in our base class.
1619 // TODO for some reason, the toolbar functions require the TLW to be
1620 // TODO realized (they reference m_wTopLevelWindow->window) before we call them.
1621
1622 if(m_iFrameMode == XAP_NormalFrame)
1623 gtk_widget_realize(m_wTopLevelWindow);
1624
1625 _createIMContext(gtk_widget_get_window(m_wTopLevelWindow));
1626
1627 /* If refactoring the toolbars code, please make sure that toolbars
1628 * are created AFTER the main menu bar has been synthesized, otherwise
1629 * the embedded build will stop working
1630 */
1631 if(m_iFrameMode == XAP_NormalFrame)
1632 _createToolbars();
1633
1634 // Let the app-specific frame code create the contents of
1635 // the child area of the window (between the toolbars and
1636 // the status bar).
1637 m_wSunkenBox = _createDocumentWindow();
1638 gtk_container_add(GTK_CONTAINER(m_wVBox), m_wSunkenBox);
1639 gtk_widget_show(m_wSunkenBox);
1640
1641 // Create statusLet the app-specific frame code create the status bar
1642 // if it wants to. we will put it below the document
1643 // window (a peer with toolbars and the overall sunkenbox)
1644 // so that it will appear outside of the scrollbars.
1645 m_wStatusBar = NULL;
1646
1647 #ifdef ENABLE_STATUSBAR
1648 if(m_iFrameMode == XAP_NormalFrame)
1649 m_wStatusBar = _createStatusBarWindow();
1650 #endif
1651
1652 if (m_wStatusBar)
1653 {
1654 gtk_widget_show(m_wStatusBar);
1655 gtk_box_pack_end(GTK_BOX(m_wVBox), m_wStatusBar, FALSE, FALSE, 0);
1656 }
1657
1658 gtk_widget_show(m_wVBox);
1659
1660 // set the icon
1661 if(m_iFrameMode == XAP_NormalFrame)
1662 _setWindowIcon();
1663 }
1664
_createIMContext(GdkWindow * w)1665 void XAP_UnixFrameImpl::_createIMContext(GdkWindow *w)
1666 {
1667 m_imContext = gtk_im_multicontext_new();
1668
1669 gtk_im_context_set_use_preedit (m_imContext, FALSE);
1670
1671 gtk_im_context_set_client_window(m_imContext, w);
1672
1673 g_signal_connect(G_OBJECT(m_imContext), "commit",
1674 G_CALLBACK(_imCommit_cb), this);
1675 g_signal_connect (m_imContext, "preedit_start",
1676 G_CALLBACK (_imPreeditStart_cb), this);
1677 g_signal_connect (m_imContext, "preedit_changed",
1678 G_CALLBACK (_imPreeditChanged_cb), this);
1679 g_signal_connect (m_imContext, "preedit_end",
1680 G_CALLBACK (_imPreeditEnd_cb), this);
1681 g_signal_connect (m_imContext, "retrieve_surrounding",
1682 G_CALLBACK (_imRetrieveSurrounding_cb), this);
1683 g_signal_connect (m_imContext, "delete_surrounding",
1684 G_CALLBACK (_imDeleteSurrounding_cb), this);
1685 }
1686
_imPreeditStart_cb(GtkIMContext *,gpointer data)1687 void XAP_UnixFrameImpl::_imPreeditStart_cb (GtkIMContext * /*context*/,
1688 gpointer data)
1689 {
1690 XAP_UnixFrameImpl * pImpl = static_cast<XAP_UnixFrameImpl*>(data);
1691 FV_View * pView =
1692 static_cast<FV_View*>(pImpl->getFrame()->getCurrentView ());
1693
1694 pImpl->m_iPreeditStart = pView->getInsPoint ();
1695 pImpl->m_iPreeditLen = 0;
1696
1697 UT_DEBUGMSG(("@@@@ Preedit Started, pos %d\n", pView->getInsPoint ()));
1698 }
1699
_imPreeditEnd_cb(GtkIMContext *,gpointer data)1700 void XAP_UnixFrameImpl::_imPreeditEnd_cb (GtkIMContext * /*context*/,
1701 gpointer data)
1702 {
1703 XAP_UnixFrameImpl * pImpl = static_cast<XAP_UnixFrameImpl*>(data);
1704 FV_View * pView =
1705 static_cast<FV_View*>(pImpl->getFrame()->getCurrentView ());
1706
1707 UT_DEBUGMSG(("@@@@ Preedit Ended\n"));
1708
1709 if (pImpl->m_iPreeditLen)
1710 {
1711 // Anything that might have been entered as part of pre-edit
1712 // needs to be nuked.
1713 UT_DEBUGMSG(("@@@@@ deleting preedit from %d, len %d\n",
1714 pImpl->m_iPreeditStart,
1715 pImpl->m_iPreeditLen));
1716 pView->moveInsPtTo (pImpl->m_iPreeditStart);
1717 pView->cmdCharDelete (true, pImpl->m_iPreeditLen);
1718
1719 pImpl->m_iPreeditLen = 0;
1720 }
1721
1722 pImpl->m_iPreeditStart = 0;
1723 }
1724
_imPreeditChanged_cb(GtkIMContext * context,gpointer data)1725 void XAP_UnixFrameImpl::_imPreeditChanged_cb (GtkIMContext *context,
1726 gpointer data)
1727 {
1728 gchar *text;
1729 gint len = 0;
1730 gint pos;
1731
1732 XAP_UnixFrameImpl * pImpl = static_cast<XAP_UnixFrameImpl*>(data);
1733 XAP_Frame* pFrame = pImpl->getFrame();
1734 FV_View * pView = static_cast<FV_View*>(pFrame->getCurrentView ());
1735 ev_UnixKeyboard * pUnixKeyboard =
1736 static_cast<ev_UnixKeyboard *>(pFrame->getKeyboard());
1737
1738 // delete previous pre-edit, if there is one
1739 if (pImpl->m_iPreeditLen)
1740 {
1741 UT_DEBUGMSG(("deleting preedit from %d, len %d\n",
1742 pImpl->m_iPreeditStart,
1743 pImpl->m_iPreeditLen));
1744 pView->moveInsPtTo (pImpl->m_iPreeditStart);
1745 pView->cmdCharDelete (true, pImpl->m_iPreeditLen);
1746
1747 pImpl->m_iPreeditLen = 0;
1748 pImpl->m_iPreeditStart = 0;
1749 }
1750
1751 // fetch the updated pre-edit string.
1752 gtk_im_context_get_preedit_string (context, &text, NULL, &pos);
1753
1754 if (!text || !(len = strlen (text)))
1755 return;
1756
1757 pImpl->m_iPreeditStart = pView->getInsPoint ();
1758 pImpl->m_iPreeditLen = g_utf8_strlen (text, -1);
1759
1760 pUnixKeyboard->charDataEvent(pView, static_cast<EV_EditBits>(0),
1761 text, strlen(text));
1762
1763 UT_DEBUGMSG(("@@@@ Preedit Changed, text %s, len %d (utf8 chars %d)\n",
1764 text, len, pImpl->m_iPreeditLen));
1765 }
1766
_imRetrieveSurrounding_cb(GtkIMContext * context,gpointer data)1767 gboolean XAP_UnixFrameImpl::_imRetrieveSurrounding_cb (GtkIMContext *context,
1768 gpointer data)
1769 {
1770 XAP_UnixFrameImpl * pImpl = static_cast<XAP_UnixFrameImpl*>(data);
1771 FV_View * pView =
1772 static_cast<FV_View*>(pImpl->getFrame()->getCurrentView ());
1773
1774 if (pView == nullptr) {
1775 UT_DEBUGMSG(("XAP_UnixFrameImpl::_imRetrieveSurrounding_cb(): No current view.\n"));
1776 return TRUE;
1777 }
1778
1779 PT_DocPosition begin_p, end_p, here;
1780
1781 begin_p = pView->mapDocPosSimple (FV_DOCPOS_BOB);
1782 end_p = pView->mapDocPosSimple (FV_DOCPOS_EOB);
1783 here = pView->getInsPoint ();
1784
1785 UT_UCSChar * text = NULL;
1786 if (end_p > begin_p)
1787 text = pView->getTextBetweenPos (begin_p, end_p);
1788
1789 if (!text)
1790 return TRUE;
1791
1792 UT_UTF8String utf (text);
1793 DELETEPV(text);
1794
1795 gtk_im_context_set_surrounding (context,
1796 utf.utf8_str(),
1797 utf.byteLength (),
1798 g_utf8_offset_to_pointer(utf.utf8_str(), here - begin_p) - utf.utf8_str());
1799
1800 return TRUE;
1801 }
1802
_imDeleteSurrounding_cb(GtkIMContext *,gint offset,gint n_chars,gpointer data)1803 gint XAP_UnixFrameImpl::_imDeleteSurrounding_cb (GtkIMContext * /*slave*/,
1804 gint offset, gint n_chars,
1805 gpointer data)
1806 {
1807 xxx_UT_DEBUGMSG(("Delete Surrounding\n"));
1808 XAP_UnixFrameImpl * pImpl = static_cast<XAP_UnixFrameImpl*>(data);
1809 FV_View * pView =
1810 static_cast<FV_View*>(pImpl->getFrame()->getCurrentView ());
1811
1812 PT_DocPosition insPt = pView->getInsPoint ();
1813 if ((gint) insPt + offset < 0)
1814 return TRUE;
1815
1816 pView->moveInsPtTo (insPt + offset);
1817 pView->cmdCharDelete (true, n_chars);
1818
1819 return TRUE;
1820 }
1821
1822 // Actual keyboard commit should be done here.
_imCommit_cb(GtkIMContext * imc,const gchar * text,gpointer data)1823 void XAP_UnixFrameImpl::_imCommit_cb(GtkIMContext *imc,
1824 const gchar *text, gpointer data)
1825 {
1826 XAP_UnixFrameImpl * impl = static_cast<XAP_UnixFrameImpl*>(data);
1827 impl->_imCommit (imc, text);
1828 }
1829
1830 // Actual keyboard commit should be done here.
_imCommit(GtkIMContext *,const gchar * text)1831 void XAP_UnixFrameImpl::_imCommit(GtkIMContext * /*imc*/, const gchar * text)
1832 {
1833 XAP_Frame* pFrame = getFrame();
1834 FV_View * pView = static_cast<FV_View*>(getFrame()->getCurrentView ());
1835 ev_UnixKeyboard * pUnixKeyboard =
1836 static_cast<ev_UnixKeyboard *>(pFrame->getKeyboard());
1837
1838 if (m_iPreeditLen)
1839 {
1840 /* delete previous pre-edit */
1841 UT_DEBUGMSG(("deleting preedit from %d, len %d\n",
1842 m_iPreeditStart,
1843 m_iPreeditLen));
1844 pView->moveInsPtTo (m_iPreeditStart);
1845 pView->cmdCharDelete (true, m_iPreeditLen);
1846
1847 m_iPreeditLen = 0;
1848 m_iPreeditStart = 0;
1849 }
1850
1851 pUnixKeyboard->charDataEvent(pView, static_cast<EV_EditBits>(0),
1852 text, strlen(text));
1853
1854 xxx_UT_DEBUGMSG(("<<<<<<<<_imCommit: text %s, len %d\n", text, strlen(text)));
1855 }
1856
getIMContext()1857 GtkIMContext * XAP_UnixFrameImpl::getIMContext()
1858 {
1859 return m_imContext;
1860 }
1861
_setGeometry()1862 void XAP_UnixFrameImpl::_setGeometry ()
1863 {
1864 UT_sint32 app_x = 0;
1865 UT_sint32 app_y = 0;
1866 UT_uint32 app_w = 0;
1867 UT_uint32 app_h = 0;
1868 UT_uint32 app_f = 0;
1869
1870 XAP_UnixApp * pApp = static_cast<XAP_UnixApp*>(XAP_App::getApp ());
1871 pApp->getGeometry (&app_x, &app_y, &app_w, &app_h, &app_f);
1872 // (ignore app_x, app_y & app_f since the WM will set them for us just fine)
1873
1874 // This is now done with --geometry parsing.
1875 if (app_w == 0 || app_w > USHRT_MAX) app_w = 760;
1876 if (app_h == 0 || app_h > USHRT_MAX) app_h = 520;
1877
1878 UT_DEBUGMSG(("xap_UnixFrameImpl: app-width=%lu, app-height=%lu\n",
1879 static_cast<unsigned long>(app_w),static_cast<unsigned long>(app_h)));
1880
1881 // set geometry hints as the user requested
1882 gint user_x = 0;
1883 gint user_y = 0;
1884 UT_uint32 uuser_w = static_cast<UT_uint32>(app_w);
1885 UT_uint32 uuser_h = static_cast<UT_uint32>(app_h);
1886 UT_uint32 user_f = 0;
1887
1888 pApp->getWinGeometry (&user_x, &user_y, &uuser_w, &uuser_h, &user_f);
1889 // to avoid bad signedess warnings
1890 gint user_w = static_cast<gint>(uuser_w);
1891 gint user_h = static_cast<gint>(uuser_h);
1892
1893 UT_DEBUGMSG(("xap_UnixFrameImpl: user-width=%u, user-height=%u\n",
1894 static_cast<unsigned>(user_w),static_cast<unsigned>(user_h)));
1895
1896 // Get fall-back defaults from preferences
1897 UT_sint32 pref_x = 0;
1898 UT_sint32 pref_y = 0;
1899 UT_uint32 pref_w = static_cast<UT_uint32>(app_w);
1900 UT_uint32 pref_h = static_cast<UT_uint32>(app_h);
1901 UT_uint32 pref_f = 0;
1902
1903 pApp->getPrefs()->getGeometry (&pref_x, &pref_y, &pref_w, &pref_h, &pref_f);
1904
1905 UT_DEBUGMSG(("xap_UnixFrameImpl: pref-width=%lu, pref-height=%lu\n",
1906 static_cast<unsigned long>(pref_w),static_cast<unsigned long>(pref_h)));
1907
1908 if (!(user_f & XAP_UnixApp::GEOMETRY_FLAG_SIZE))
1909 if (pref_f & PREF_FLAG_GEOMETRY_SIZE)
1910 {
1911 user_w = static_cast<guint>(pref_w);
1912 user_h = static_cast<guint>(pref_h);
1913 user_f |= XAP_UnixApp::GEOMETRY_FLAG_SIZE;
1914 }
1915 if (!(user_f & XAP_UnixApp::GEOMETRY_FLAG_POS))
1916 if (pref_f & PREF_FLAG_GEOMETRY_POS)
1917 {
1918 user_x = static_cast<gint>(pref_x);
1919 user_y = static_cast<gint>(pref_y);
1920 user_f |= XAP_UnixApp::GEOMETRY_FLAG_POS;
1921 }
1922
1923 UT_DEBUGMSG(("xap_UnixFrameImpl: user-x=%d, user-y=%d\n",
1924 static_cast<int>(user_x),static_cast<int>(user_y)));
1925
1926 if (!(user_f & XAP_UnixApp::GEOMETRY_FLAG_SIZE))
1927 {
1928 user_w = static_cast<guint>(app_w);
1929 user_h = static_cast<guint>(app_h);
1930 }
1931
1932 if (user_w > USHRT_MAX)
1933 user_w = app_w;
1934 if (user_h > USHRT_MAX)
1935 user_h = app_h;
1936
1937 if(getFrame()->getFrameMode() == XAP_NormalFrame)
1938 {
1939 GdkGeometry geom;
1940 geom.min_width = 100;
1941 geom.min_height = 100;
1942 gtk_window_set_geometry_hints (GTK_WINDOW(m_wTopLevelWindow), m_wTopLevelWindow, &geom,
1943 static_cast<GdkWindowHints>(GDK_HINT_MIN_SIZE));
1944
1945 GdkScreen *screen = gdk_screen_get_default ();
1946 user_w = (user_w < gdk_screen_get_width (screen) ? user_w : gdk_screen_get_width (screen));
1947 user_h = (user_h < gdk_screen_get_height (screen) ? user_h : gdk_screen_get_height (screen));
1948 gtk_window_set_default_size (GTK_WINDOW(m_wTopLevelWindow), user_w, user_h);
1949 }
1950
1951 // Because we're clever, we only honor this flag when we
1952 // are the first (well, only) top level frame available.
1953 // This is so the user's window manager can find better
1954 // places for new windows, instead of having our windows
1955 // pile upon each other.
1956
1957 if (pApp->getFrameCount () <= 1)
1958 if (user_f & XAP_UnixApp::GEOMETRY_FLAG_POS)
1959 {
1960 gtk_window_move (GTK_WINDOW(m_wTopLevelWindow), user_x, user_y);
1961 }
1962
1963 // Remember geometry settings for next time
1964 pApp->getPrefs()->setGeometry (user_x, user_y, user_w, user_h, user_f);
1965
1966 }
1967
1968 /*!
1969 * This code is used by the dynamic menu API to rebuild the menus after a
1970 * a change in the menu structure.
1971 */
_rebuildMenus(void)1972 void XAP_UnixFrameImpl::_rebuildMenus(void)
1973 {
1974 // no menu? then nothing to rebuild!
1975 if (!m_pUnixMenu) return;
1976
1977 // destroy old menu
1978 m_pUnixMenu->destroy();
1979 DELETEP(m_pUnixMenu);
1980
1981 // build new one.
1982 m_pUnixMenu = new EV_UnixMenuBar(static_cast<XAP_UnixApp*>(XAP_App::getApp()), getFrame(),
1983 m_szMenuLayoutName,
1984 m_szMenuLabelSetName);
1985 UT_return_if_fail(m_pUnixMenu);
1986 UT_DebugOnly<bool> bResult = m_pUnixMenu->rebuildMenuBar();
1987 UT_ASSERT_HARMLESS(bResult);
1988 }
1989
1990 /*!
1991 * This code is used by the dynamic toolbar API to rebuild a toolbar after a
1992 * a change in the toolbar structure.
1993 */
_rebuildToolbar(UT_uint32 ibar)1994 void XAP_UnixFrameImpl::_rebuildToolbar(UT_uint32 ibar)
1995 {
1996 XAP_Frame* pFrame = getFrame();
1997 // Destroy the old toolbar
1998 EV_Toolbar * pToolbar = static_cast<EV_Toolbar *>(m_vecToolbars.getNthItem(ibar));
1999 const char * szTBName = reinterpret_cast<const char *>(m_vecToolbarLayoutNames.getNthItem(ibar));
2000 EV_UnixToolbar * pUTB = static_cast<EV_UnixToolbar *>(pToolbar);
2001 UT_sint32 oldpos = pUTB->destroy();
2002
2003 // Delete the old class
2004 delete pToolbar;
2005 if(oldpos < 0) {
2006 return;
2007 }
2008
2009 // Build a new one.
2010 pToolbar = _newToolbar(pFrame, szTBName,
2011 static_cast<const char *>(m_szToolbarLabelSetName));
2012 static_cast<EV_UnixToolbar *>(pToolbar)->rebuildToolbar(oldpos);
2013 m_vecToolbars.setNthItem(ibar, pToolbar, NULL);
2014 // Refill the framedata pointers
2015
2016 pFrame->refillToolbarsInFrameData();
2017 pFrame->repopulateCombos();
2018 }
2019
_close()2020 bool XAP_UnixFrameImpl::_close()
2021 {
2022 gtk_widget_destroy(m_wTopLevelWindow);
2023 m_wTopLevelWindow = NULL;
2024 return true;
2025 }
2026
_raise()2027 bool XAP_UnixFrameImpl::_raise()
2028 {
2029 UT_ASSERT(m_wTopLevelWindow);
2030 if (GTK_IS_WINDOW (m_wTopLevelWindow))
2031 gtk_window_present(GTK_WINDOW (m_wTopLevelWindow));
2032 return true;
2033 }
2034
_show()2035 bool XAP_UnixFrameImpl::_show()
2036 {
2037 if(m_wTopLevelWindow) {
2038 gtk_widget_show(m_wTopLevelWindow);
2039 }
2040
2041 return true;
2042 }
2043
_updateTitle()2044 bool XAP_UnixFrameImpl::_updateTitle()
2045 {
2046 if (!XAP_FrameImpl::_updateTitle() || (m_wTopLevelWindow== NULL) || (m_iFrameMode != XAP_NormalFrame))
2047 {
2048 // no relevant change, so skip it
2049 return false;
2050 }
2051
2052 if(getFrame()->getFrameMode() == XAP_NormalFrame)
2053 {
2054 if (GTK_IS_WINDOW (m_wTopLevelWindow))
2055 {
2056 gtk_window_set_title(GTK_WINDOW(m_wTopLevelWindow), getFrame()->getTitle().utf8_str());
2057 }
2058 }
2059 return true;
2060 }
2061
_runModalContextMenu(AV_View *,const char * szMenuName,UT_sint32,UT_sint32)2062 bool XAP_UnixFrameImpl::_runModalContextMenu(AV_View * /* pView */, const char * szMenuName,
2063 UT_sint32 /*x*/, UT_sint32 /*y*/)
2064 {
2065 XAP_Frame* pFrame = getFrame();
2066 bool bResult = true;
2067
2068 UT_ASSERT_HARMLESS(!m_pUnixPopup);
2069
2070 // WL_REFACTOR: we DON'T want to do this
2071 m_pUnixPopup = new EV_UnixMenuPopup(static_cast<XAP_UnixApp*>(XAP_App::getApp()),
2072 pFrame, szMenuName, m_szMenuLabelSetName);
2073
2074 if (m_pUnixPopup && m_pUnixPopup->synthesizeMenuPopup())
2075 {
2076 // Add our InputMethod selection item to the popup menu, UNLESS WE'RE DOING A PRESENTATION Borrowed
2077 // from gtkentry.c
2078 if(!pFrame->isMenuScrollHidden())
2079 {
2080 GtkWidget * menuitem;
2081 GtkWidget * submenu;
2082 GtkWidget * menu = m_pUnixPopup->getMenuHandle();
2083 menuitem = gtk_separator_menu_item_new ();
2084 gtk_widget_show (menuitem);
2085 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2086
2087 const XAP_StringSet * pSS = XAP_App::getApp()->getStringSet();
2088
2089 menuitem = gtk_menu_item_new_with_label (pSS->getValue(XAP_STRING_ID_XIM_Methods));
2090
2091 gtk_widget_show (menuitem);
2092 submenu = gtk_menu_new ();
2093 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2094
2095 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2096
2097 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(m_imContext),
2098 GTK_MENU_SHELL(submenu));
2099 }
2100 // the popup will steal the mouse and so we won't get the
2101 // button_release_event and we won't know to release our
2102 // grab. so let's do it here. (when raised from a keyboard
2103 // context menu, we may not have a grab, but that should be ok.
2104 GtkWidget * w = gtk_grab_get_current();
2105 if (w)
2106 gtk_grab_remove(w);
2107
2108 //
2109 // OK lets not immediately drop the menu if the user releases the mouse button.
2110 // From the gtk FAQ.
2111 //
2112 GdkEvent * event = gtk_get_current_event();
2113 GdkEventButton *bevent = reinterpret_cast<GdkEventButton *>(event);
2114 if(!bevent)
2115 {
2116 DELETEP(m_pUnixPopup);
2117 return false;
2118 }
2119
2120 gtk_menu_popup(GTK_MENU(m_pUnixPopup->getMenuHandle()), NULL, NULL,
2121 NULL, NULL, bevent->button, bevent->time);
2122
2123 // We run this menu synchronously, since GTK doesn't.
2124 // Popup menus have a special "unmap" function to call
2125 // gtk_main_quit() when they're done.
2126 gdk_event_free(event);
2127 gtk_main();
2128 }
2129
2130 if (pFrame && pFrame->getCurrentView())
2131 pFrame->getCurrentView()->focusChange( AV_FOCUS_HERE);
2132
2133 DELETEP(m_pUnixPopup);
2134 return bResult;
2135 }
2136
setTimeOfLastEvent(guint32 eventTime)2137 void XAP_UnixFrameImpl::setTimeOfLastEvent(guint32 eventTime)
2138 {
2139 static_cast<XAP_UnixApp*>(XAP_App::getApp())->setTimeOfLastEvent(eventTime);
2140 }
2141
_queue_resize()2142 void XAP_UnixFrameImpl::_queue_resize()
2143 {
2144 gtk_widget_queue_resize(m_wTopLevelWindow);
2145 }
2146
_getMainMenu()2147 EV_Menu* XAP_UnixFrameImpl::_getMainMenu()
2148 {
2149 return m_pUnixMenu;
2150 }
2151
_setFullScreen(bool changeToFullScreen)2152 void XAP_UnixFrameImpl::_setFullScreen(bool changeToFullScreen)
2153 {
2154 if (!GTK_IS_WINDOW(m_wTopLevelWindow)) return;
2155
2156 if (changeToFullScreen)
2157 gtk_window_fullscreen (GTK_WINDOW(m_wTopLevelWindow));
2158 else
2159 gtk_window_unfullscreen (GTK_WINDOW(m_wTopLevelWindow));
2160 }
2161
_newToolbar(XAP_Frame * pFrame,const char * szLayout,const char * szLanguage)2162 EV_Toolbar * XAP_UnixFrameImpl::_newToolbar(XAP_Frame *pFrame,
2163 const char *szLayout,
2164 const char *szLanguage)
2165 {
2166 EV_UnixToolbar *pToolbar = NULL;
2167 #ifdef HAVE_GCONF
2168 pToolbar = new EV_GnomeToolbar(static_cast<XAP_UnixApp *>(XAP_App::getApp()), pFrame, szLayout, szLanguage);
2169 #else
2170 pToolbar = new EV_UnixToolbar(static_cast<XAP_UnixApp *>(XAP_App::getApp()), pFrame, szLayout, szLanguage);
2171 #endif
2172 return pToolbar;
2173 }
2174