~ubuntu-branches/debian/jessie/ardesia/jessie

« back to all changes in this revision

Viewing changes to src/text_window.c

  • Committer: Package Import Robot
  • Author(s): TANIGUCHI Takaki
  • Date: 2012-11-05 19:55:18 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20121105195518-ird6x2us0tui2q92
Tags: 1.1-1
* debian/watch: no longer use googlecode.d.n
* Imported Upstream version 1.1 (Closes: #620319, #692256)
* debian/control: add GTK+3 to B-D instead of GTK+2

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
/* The structure used internally to store the status. */
42
42
static TextData *text_data = (TextData *) NULL;
43
43
 
 
44
/* The structure used to configure text input. */
 
45
TextConfig *text_config = (TextConfig *) NULL;
44
46
 
45
47
/* Create the text window. */
46
48
static void
47
 
create_text_window (GtkWindow *parent)
 
49
create_text_window           (GtkWindow *parent)
48
50
{
49
51
  GError *error = (GError *) NULL;
50
52
 
57
59
      gtk_builder_add_from_file (text_data->text_window_gtk_builder, TEXT_UI_FILE, &error);
58
60
 
59
61
      if (error)
60
 
        {
61
 
          g_warning ("Failed to load builder file: %s", error->message);
62
 
          g_error_free (error);
63
 
          return;
64
 
        }
 
62
        {
 
63
          g_warning ("Failed to load builder file: %s", error->message);
 
64
          g_error_free (error);
 
65
          return;
 
66
        }
65
67
 
66
68
    }
67
69
 
70
72
      GObject *text_obj = gtk_builder_get_object (text_data->text_window_gtk_builder, "text_window");
71
73
      text_data->window = GTK_WIDGET (text_obj);
72
74
 
73
 
      gtk_window_set_transient_for (GTK_WINDOW (text_data->window), GTK_WINDOW (parent));
74
 
 
75
75
      gtk_window_set_opacity (GTK_WINDOW (text_data->window), 1);
76
 
      gtk_widget_set_usize (GTK_WIDGET (text_data->window), gdk_screen_width (), gdk_screen_height ());
 
76
      gtk_widget_set_size_request (GTK_WIDGET (text_data->window), gdk_screen_width (), gdk_screen_height ());
77
77
    }
78
78
 
79
79
}
80
80
 
81
81
 
82
82
/* Move the pen cursor. */
83
 
static void move_editor_cursor ()
 
83
static void move_editor_cursor    ()
84
84
{
85
85
  if (text_data->cr)
86
86
    {
90
90
 
91
91
 
92
92
/* Blink cursor. */
93
 
static gboolean blink_cursor (gpointer data)
 
93
static
 
94
gboolean blink_cursor        (gpointer data)
94
95
{
95
96
  if ((text_data->window) && (text_data->pos))
96
97
    {
101
102
      cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
102
103
 
103
104
      if (text_data->blink_show)
104
 
        {
105
 
          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
106
 
          cairo_set_line_width (cr, text_data->pen_width);
107
 
          cairo_set_source_color_from_string (cr, text_data->color);
108
 
 
109
 
          cairo_rectangle (cr, text_data->pos->x, text_data->pos->y - height, TEXT_CURSOR_WIDTH, height);
110
 
 
111
 
          text_data->blink_show = FALSE;
112
 
        }
 
105
        {
 
106
          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
107
          cairo_set_line_width (cr, text_data->pen_width);
 
108
          cairo_set_source_color_from_string (cr, text_data->color);
 
109
          cairo_rectangle (cr, text_data->pos->x, text_data->pos->y - height, TEXT_CURSOR_WIDTH, height);
 
110
          text_data->blink_show = FALSE;
 
111
        }
113
112
      else
114
 
        {
115
 
          cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
 
113
        {
 
114
          cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
116
115
          cairo_rectangle (cr, text_data->pos->x, text_data->pos->y - height, TEXT_CURSOR_WIDTH, height);
117
116
 
118
117
          cairo_rectangle (cr,
119
118
                           text_data->pos->x-1,
120
119
                           text_data->pos->y - height - 1,
121
 
                           TEXT_CURSOR_WIDTH  + 2,
122
 
                           height + 2);
123
 
 
124
 
          text_data->blink_show=TRUE;
125
 
        }
 
120
                           TEXT_CURSOR_WIDTH  + 2,
 
121
                           height + 2);
 
122
          text_data->blink_show=TRUE;
 
123
        }
126
124
 
127
125
      cairo_fill (cr);
128
126
      cairo_stroke (cr);
133
131
 
134
132
 
135
133
/* Delete the last character printed. */
136
 
static void delete_character ()
 
134
static void
 
135
delete_character        ()
137
136
{
138
137
  CharInfo *char_info = (CharInfo *) g_slist_nth_data (text_data->letterlist, 0);
139
138
 
142
141
      cairo_set_operator (text_data->cr, CAIRO_OPERATOR_CLEAR);
143
142
 
144
143
      cairo_rectangle (text_data->cr,
145
 
                       char_info->x + char_info->x_bearing -1,
146
 
                       char_info->y + char_info->y_bearing -1,
147
 
                       gdk_screen_width ()+2,
148
 
                       text_data->max_font_height + 2);
 
144
                       char_info->x + char_info->x_bearing -1,
 
145
                       char_info->y + char_info->y_bearing -1,
 
146
                       gdk_screen_width ()+2,
 
147
                       text_data->max_font_height + 2);
149
148
 
150
149
      cairo_fill (text_data->cr);
151
150
      cairo_stroke (text_data->cr);
160
159
 
161
160
/* Stop the timer to handle the blocking cursor. */
162
161
static void
163
 
stop_timer ()
 
162
stop_timer              ()
164
163
{
165
164
  if (text_data->timer>0)
166
165
    {
172
171
 
173
172
/* Set the text cursor. */
174
173
static gboolean
175
 
set_text_cursor (GtkWidget *window)
 
174
set_text_cursor              (GtkWidget  *window)
176
175
{
177
176
  gdouble decoration_height = 4;
178
177
  gint height = text_data->max_font_height + decoration_height * 2;
179
178
  gint width = TEXT_CURSOR_WIDTH * 3;  
180
 
  GdkPixmap *pixmap = gdk_pixmap_new (NULL, width, height, 1);
181
 
  cairo_t *text_pointer_pcr = gdk_cairo_create (pixmap);
182
 
  GdkPixmap *bitmap = gdk_pixmap_new (NULL, width, height, 1);
183
 
  cairo_t *text_pointer_cr = gdk_cairo_create (bitmap);
 
179
  cairo_surface_t *text_surface_t = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
 
180
  cairo_t *text_pointer_cr = cairo_create (text_surface_t);
184
181
  GdkColor *background_color_p = rgba_to_gdkcolor (BLACK);
185
182
  GdkColor *foreground_color_p = rgba_to_gdkcolor (text_data->color);
186
183
  GdkCursor *cursor = (GdkCursor *) NULL;
187
 
 
188
 
  clear_cairo_context (text_pointer_pcr);
189
 
  cairo_set_operator (text_pointer_pcr, CAIRO_OPERATOR_SOURCE);
190
 
  cairo_set_source_rgb (text_pointer_pcr, 1, 1, 1);
191
 
  cairo_paint (text_pointer_pcr);
192
 
  cairo_stroke (text_pointer_pcr);
193
 
  cairo_destroy (text_pointer_pcr);
 
184
  GdkPixbuf *pixbuf = (GdkPixbuf *) NULL;
194
185
 
195
186
  if (text_pointer_cr)
196
187
    {
197
188
      clear_cairo_context (text_pointer_cr);
198
 
      cairo_set_source_rgb (text_pointer_cr, 1, 1, 1);
 
189
      cairo_set_source_color_from_string (text_pointer_cr, text_data->color);
199
190
      cairo_set_operator (text_pointer_cr, CAIRO_OPERATOR_SOURCE);
200
191
      cairo_set_line_width (text_pointer_cr, 2);
201
192
 
215
206
 
216
207
      cairo_stroke (text_pointer_cr);
217
208
      cairo_destroy (text_pointer_cr);
218
 
    } 
219
 
  
220
 
  cursor = gdk_cursor_new_from_pixmap (pixmap,
221
 
                                                  bitmap,
222
 
                                                  foreground_color_p,
223
 
                                                  background_color_p,
224
 
                                                  TEXT_CURSOR_WIDTH,
225
 
                                                  height-decoration_height);
 
209
    }
 
210
 
 
211
  pixbuf = gdk_pixbuf_get_from_surface (text_surface_t,
 
212
                                        0,
 
213
                                        0,
 
214
                                        width,
 
215
                                        height);
 
216
 
 
217
  cursor = gdk_cursor_new_from_pixbuf ( gdk_display_get_default (), pixbuf, 0, 0);
226
218
 
227
219
  gdk_window_set_cursor (gtk_widget_get_window  (text_data->window), cursor);
228
220
  gdk_flush ();
229
 
  gdk_cursor_unref (cursor);
230
 
 
231
 
  g_object_unref (pixmap);
232
 
  g_object_unref (bitmap);
 
221
  g_object_unref (cursor);
 
222
  g_object_unref (pixbuf);
 
223
  cairo_surface_destroy (text_surface_t);
233
224
  g_free (foreground_color_p);
234
225
  g_free (background_color_p);
235
226
  
237
228
}
238
229
 
239
230
 
 
231
/* Add a save-point with the text. */
 
232
static void
 
233
save_text          ()
 
234
{
 
235
  if (text_data)
 
236
    {
 
237
      stop_timer (); 
 
238
      text_data->blink_show=FALSE;
 
239
      blink_cursor (NULL);
 
240
 
 
241
      if (text_data->letterlist)
 
242
        {
 
243
          annotate_push_context (text_data->cr);
 
244
          g_slist_foreach (text_data->letterlist,
 
245
                           (GFunc)g_free,
 
246
                           NULL);
 
247
 
 
248
          g_slist_free (text_data->letterlist);
 
249
          text_data->letterlist = NULL;
 
250
        }
 
251
 
 
252
    }
 
253
}
 
254
 
 
255
 
240
256
/* Initialization routine. */
241
257
static void
242
 
init_text_widget (GtkWidget *widget)
 
258
init_text_widget             (GtkWidget *widget)
243
259
{
 
260
  gtk_widget_input_shape_combine_region(text_data->window, NULL);
 
261
  drill_window_in_bar_area (text_data->window);
 
262
 
244
263
  if (!text_data->cr)
245
264
    {
246
 
      text_data->cr = gdk_cairo_create (widget->window);
 
265
      text_data->cr = gdk_cairo_create ( gtk_widget_get_window (widget) );
247
266
      cairo_set_operator (text_data->cr, CAIRO_OPERATOR_SOURCE);
248
267
      cairo_set_line_width (text_data->cr, text_data->pen_width);
249
268
      cairo_set_source_color_from_string (text_data->cr, text_data->color);
250
269
      cairo_set_font_size (text_data->cr, text_data->pen_width * 2);
 
270
      
 
271
      /* Select the font */
 
272
      cairo_select_font_face (text_data->cr, text_config->fontfamily,
 
273
                              CAIRO_FONT_SLANT_NORMAL,
 
274
                              CAIRO_FONT_WEIGHT_NORMAL);
 
275
 
251
276
      /* This is a trick; we must found the maximum height of the font. */
252
277
      cairo_text_extents (text_data->cr, "|" , &text_data->extents);
253
278
      text_data->max_font_height = text_data->extents.height;
254
279
      set_text_cursor (widget);
255
280
    }
256
281
 
257
 
  drill_window_in_bar_area (text_data->window);
258
 
 
259
282
#ifdef _WIN32
260
283
  grab_pointer (text_data->window, TEXT_MOUSE_EVENTS);
261
284
#endif
264
287
    {
265
288
      clear_cairo_context (text_data->cr);
266
289
    }
267
 
 
 
290
  
268
291
  if (!text_data->pos)
269
292
    {
270
293
      text_data->pos = g_malloc ( (gsize) sizeof (Pos));
275
298
}
276
299
 
277
300
 
278
 
/* Add a save-point with the text. */
279
 
static void
280
 
save_text ()
281
 
{
282
 
  if (text_data)
283
 
    {
284
 
      stop_timer (); 
285
 
      text_data->blink_show=FALSE;
286
 
      blink_cursor (NULL);
287
 
 
288
 
      if (text_data->letterlist)
289
 
        {
290
 
          annotate_push_context (text_data->cr);
291
 
          g_slist_foreach (text_data->letterlist, (GFunc)g_free, NULL);
292
 
          g_slist_free (text_data->letterlist);
293
 
          text_data->letterlist = NULL;
294
 
        }
295
 
 
296
 
    }
297
 
}
298
 
 
299
 
 
300
301
/* Destroy text window. */
301
302
static void
302
 
destroy_text_window ()
 
303
destroy_text_window     ()
303
304
{
304
305
  if (text_data->window)
305
306
    {
307
308
      ungrab_pointer (gdk_display_get_default ());
308
309
#endif
309
310
      if (text_data->window)
310
 
        {
311
 
          gtk_widget_destroy (text_data->window);
312
 
          text_data->window = NULL;
313
 
        }
 
311
        {
 
312
          gtk_widget_destroy (text_data->window);
 
313
          text_data->window = NULL;
 
314
        }
314
315
    }
315
316
}
316
317
 
317
318
 
318
319
/* keyboard event snooper. */
319
320
G_MODULE_EXPORT gboolean
320
 
key_snooper (GtkWidget *widget,
321
 
             GdkEventKey *event,
322
 
             gpointer user_data)
 
321
key_snooper                  (GtkWidget    *widget,
 
322
                              GdkEventKey  *event,
 
323
                              gpointer      user_data)
323
324
{
324
325
 
325
326
  if (event->type != GDK_KEY_PRESS) {
331
332
  blink_cursor (NULL);
332
333
 
333
334
  gboolean closed_to_bar = inside_bar_window (text_data->pos->x + text_data->extents.x_advance,
334
 
                                              text_data->pos->y-text_data->max_font_height/2);
 
335
                                              text_data->pos->y-text_data->max_font_height/2);
335
336
 
336
 
  if ( (event->keyval == GDK_BackSpace) ||
337
 
       (event->keyval == GDK_Delete))
 
337
  if ( (event->keyval == GDK_KEY_BackSpace) ||
 
338
       (event->keyval == GDK_KEY_Delete))
338
339
    {
339
340
      delete_character (); // undo the last character inserted
340
341
    }
341
342
  /* It is the end of the line or the letter is closed to the window bar. */
342
343
  else if ( (text_data->pos->x + text_data->extents.x_advance >= gdk_screen_width ()) ||
343
344
            (closed_to_bar) ||
344
 
            (event->keyval == GDK_Return) ||
345
 
            (event->keyval == GDK_ISO_Enter) ||
346
 
            (event->keyval == GDK_KP_Enter))
 
345
            (event->keyval == GDK_KEY_Return) ||
 
346
            (event->keyval == GDK_KEY_ISO_Enter) ||
 
347
            (event->keyval == GDK_KEY_KP_Enter))
347
348
    {
348
 
      text_data->pos->x = 0;
 
349
     /* select the x indentation */
 
350
      text_data->pos->x = text_config->leftmargin;
349
351
      text_data->pos->y +=  text_data->max_font_height;
350
352
    }
 
353
  /* Simple Tab-Implementation */
 
354
  else if (event->keyval == GDK_KEY_Tab)
 
355
    {
 
356
      text_data->pos->x += text_config->tabsize;
 
357
    }
351
358
  /* Is the character printable? */
352
359
  else if (isprint (event->keyval))
353
360
    {
382
389
}
383
390
 
384
391
 
 
392
/* On configure event. */
 
393
G_MODULE_EXPORT gboolean
 
394
on_text_window_configure     (GtkWidget       *widget,
 
395
                              GdkEventExpose  *event,
 
396
                              gpointer         user_data)
 
397
{
 
398
  return TRUE;
 
399
}
 
400
 
 
401
 
 
402
/* On screen changed. */
 
403
G_MODULE_EXPORT void
 
404
on_text_window_screen_changed     (GtkWidget  *widget,
 
405
                                   GdkScreen  *previous_screen,
 
406
                                   gpointer    user_data)
 
407
{
 
408
  GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET (widget));
 
409
  GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
 
410
  if (visual == NULL)
 
411
    {
 
412
      visual = gdk_screen_get_system_visual (screen);
 
413
    }
 
414
 
 
415
  gtk_widget_set_visual (widget, visual);
 
416
}
 
417
 
 
418
 
385
419
/* The windows has been exposed. */
386
420
G_MODULE_EXPORT gboolean
387
 
on_window_text_expose_event (GtkWidget *widget,
388
 
                             GdkEventExpose *event,
389
 
                             gpointer data)
 
421
on_text_window_expose_event  (GtkWidget  *widget,
 
422
                              cairo_t    *cr,
 
423
                              gpointer    data)
390
424
{
391
 
  gint is_fullscreen = gdk_window_get_state (widget->window) & GDK_WINDOW_STATE_FULLSCREEN;
 
425
  GdkWindow *gdk_win = gtk_widget_get_window (widget);
 
426
  gint is_fullscreen = gdk_window_get_state (gdk_win) & GDK_WINDOW_STATE_FULLSCREEN;
392
427
 
393
428
  if (!is_fullscreen)
394
429
    {
395
 
      return TRUE;
 
430
      return FALSE;
396
431
    }
397
432
 
398
433
  if (widget)
407
442
#ifdef _WIN32
408
443
/* Is the point (x,y) above the virtual keyboard? */
409
444
static gboolean
410
 
is_above_virtual_keyboard (gint x,
411
 
                           gint y)
 
445
is_above_virtual_keyboard    (gint  x,
 
446
                              gint  y)
412
447
{
413
448
  RECT rect;
414
449
  HWND hwnd = FindWindow (VIRTUALKEYBOARD_WINDOW_NAME, NULL);
415
450
  if (!hwnd)
416
451
    {
417
452
      return FALSE;
418
 
    }  
 
453
    }
419
454
  if (!GetWindowRect (hwnd, &rect))
420
 
    { 
 
455
    {
421
456
      return FALSE;
422
457
    }
423
458
  if ( (rect.left<x)&& (x<rect.right)&& (rect.top<y)&& (y<rect.bottom))
431
466
 
432
467
/* This is called when the button is leased. */
433
468
G_MODULE_EXPORT gboolean
434
 
on_window_text_button_release (GtkWidget *win,
435
 
                               GdkEventButton *ev,
436
 
                               gpointer user_data)
 
469
on_text_window_button_release     (GtkWidget       *win,
 
470
                                   GdkEventButton  *ev,
 
471
                                   gpointer         user_data)
437
472
{
438
473
  /* only button1 allowed */
439
474
  if (ev->button != 1)
462
497
      text_data->pos->y = ev->y_root;
463
498
      move_editor_cursor ();
464
499
 
465
 
      stop_virtual_keyboard ();
466
 
      start_virtual_keyboard ();
467
 
 
468
500
      /* This present the ardesia bar and the panels. */
469
501
      gtk_window_present (GTK_WINDOW (get_bar_window ()));
470
 
 
471
502
      gtk_window_present (GTK_WINDOW (text_data->window));
472
503
      gdk_window_raise (gtk_widget_get_window  (text_data->window));
473
504
 
 
505
      stop_virtual_keyboard ();
 
506
      start_virtual_keyboard ();
 
507
 
474
508
      text_data->timer = g_timeout_add (1000, blink_cursor, NULL);
475
509
    }
476
510
 
480
514
 
481
515
/* This shots when the text pointer is moving. */
482
516
G_MODULE_EXPORT gboolean
483
 
on_window_text_cursor_motion (GtkWidget *win,
484
 
                              GdkEventMotion *ev,
485
 
                              gpointer func_data)
 
517
on_text_window_cursor_motion      (GtkWidget       *win,
 
518
                                   GdkEventMotion  *ev,
 
519
                                   gpointer         func_data)
486
520
{
487
521
#ifdef _WIN32
488
522
  if (inside_bar_window (ev->x_root, ev->y_root))
495
529
 
496
530
 
497
531
/* Start the widget for the text insertion. */
498
 
void start_text_widget (GtkWindow *parent, gchar* color, gint tickness)
 
532
void start_text_widget      (GtkWindow  *parent,
 
533
                             gchar      *color,
 
534
                             gint        tickness)
499
535
{
500
536
  text_data = g_malloc ((gsize) sizeof (TextData));
501
537
 
515
551
 
516
552
  create_text_window (parent);
517
553
 
 
554
  /* This trys to set an alpha channel. */
 
555
  on_text_window_screen_changed(text_data->window, NULL, text_data);
 
556
  
518
557
  /* In the gtk 2.16.6 the gtkbuilder property double-buffered is not parsed
519
558
   * from the glade file and then I set this by hands. 
520
559
   */
521
560
  gtk_widget_set_double_buffered (text_data->window, FALSE); 
522
561
 
 
562
  //gtk_window_set_transient_for (GTK_WINDOW (text_data->window), GTK_WINDOW (parent));
523
563
  gtk_window_set_keep_above (GTK_WINDOW (text_data->window), TRUE);
524
 
  
 
564
  gtk_widget_grab_focus (text_data->window);
 
565
 
525
566
  /* Connect all the callback from gtkbuilder xml file. */
526
567
  gtk_builder_connect_signals (text_data->text_window_gtk_builder, (gpointer) text_data);
527
568
 
541
582
 
542
583
/* Stop the text insertion widget. */
543
584
void
544
 
stop_text_widget ()
 
585
stop_text_widget             ()
545
586
{
546
587
  if (text_data)
547
588
    {
548
589
      stop_virtual_keyboard ();
549
590
 
550
591
      if (text_data->snooper_handler_id)
551
 
        {
552
 
          gtk_key_snooper_remove (text_data->snooper_handler_id);
553
 
          text_data->snooper_handler_id = 0;
554
 
        }
 
592
        {
 
593
          gtk_key_snooper_remove (text_data->snooper_handler_id);
 
594
          text_data->snooper_handler_id = 0;
 
595
        }
555
596
 
556
597
      save_text ();
557
598
      destroy_text_window ();
558
599
 
559
600
      if (text_data->cr)
560
 
        {
561
 
          cairo_destroy (text_data->cr);
562
 
          text_data->cr = NULL;
563
 
        }
 
601
        {
 
602
          cairo_destroy (text_data->cr);
 
603
          text_data->cr = NULL;
 
604
        }
564
605
 
565
606
      if (text_data->pos)
566
 
        {
567
 
          g_free (text_data->pos);
568
 
          text_data->pos = NULL;
569
 
        }
 
607
        {
 
608
          g_free (text_data->pos);
 
609
          text_data->pos = NULL;
 
610
        }
570
611
 
571
612
      /* Free the gtk builder object. */
572
613
      if (text_data->text_window_gtk_builder)
573
 
        {
574
 
          g_object_unref (text_data->text_window_gtk_builder);
 
614
        {
 
615
          g_object_unref (text_data->text_window_gtk_builder);
575
616
          text_data->text_window_gtk_builder = NULL;
576
 
        }
 
617
        }
577
618
 
578
619
      g_free (text_data);
579
620
      text_data = NULL;